aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--todo.org62
1 files changed, 62 insertions, 0 deletions
diff --git a/todo.org b/todo.org
index 2f7c27a..d14acec 100644
--- a/todo.org
+++ b/todo.org
@@ -718,6 +718,68 @@ sudo stat -c '%a %U' /etc/NetworkManager/system-connections/<PROFILE>.nmconnecti
#+end_src
Expected: the verdict/fix is chmod-keyfile and the keyfile reads =600 root= afterward.
+*** Net doctor sharpened auth verdict (net Phase 2) — needs a real WPA3 / hidden network
+What we're verifying: the auth-cause classifier names the specific auth cluster (SAE / hidden / enterprise / generic) instead of a bare "password rejected", and the SAE / hidden one-line profile fixes actually run and take. These need a real network the machine can (fail to) associate with, so they can't be faked; run against an AP you control or a VM bridged to one. The classify logic is already unit-tested — this is the live half.
+**** SAE cause named + auth-sae fix
+What we're verifying: a WPA3-only network whose saved profile is still WPA2-PSK reports the SAE cause, and =--fix= sets key-mgmt sae so the association can complete.
+- Set an AP (or its VM equivalent) to WPA3-Personal only (pure SAE, not WPA2/WPA3 transition).
+- Save a profile for it as WPA2-PSK (=nmcli connection add type wifi ... wifi-sec.key-mgmt wpa-psk=), then try to connect so the association fails on auth.
+#+begin_src sh :results output
+net doctor --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["outcome"], d.get("message"), "|", d.get("next_action"))'
+#+end_src
+- Expected (diagnose): outcome fixable, action auth-sae, the message names WPA3 (not just "password rejected").
+#+begin_src sh :results output
+net doctor --fix --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print("fixed=",d["fixed"],"attempts=",[a["id"] for a in d["attempts"]])'
+nmcli -g 802-11-wireless-security.key-mgmt connection show <PROFILE>
+nmcli -g 802-11-wireless-security.pmf connection show <PROFILE>
+#+end_src
+Expected: attempts start with auth-sae (then reset), the profile now reads key-mgmt =sae=, and pmf is accepted (the =pmf optional= keyword took — this is the one value only a live nmcli can confirm). Note whether the link comes back after the chained reset.
+**** hidden SSID cause named + auth-hidden fix
+What we're verifying: a hidden (non-broadcast) network whose profile lacks the hidden flag reports the hidden cause, and =--fix= sets 802-11-wireless.hidden yes so NM probes for it.
+- Set the AP SSID to non-broadcast (hidden). Save a profile for it without =802-11-wireless.hidden yes=, then try to connect.
+#+begin_src sh :results output
+net doctor --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["outcome"], d.get("message"))'
+net doctor --fix --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print([a["id"] for a in d["attempts"]])'
+nmcli -g 802-11-wireless.hidden connection show <PROFILE>
+#+end_src
+Expected: diagnose names the hidden cause (outcome fixable, action auth-hidden); the fix attempts auth-hidden; the profile now reads hidden =yes=.
+**** enterprise / generic stay terminal + named
+What we're verifying: an enterprise (802.1X) auth failure stays needs-user-action and names the missing cert rather than offering a bogus fix; a plain wrong-password stays the generic "rejected" message.
+#+begin_src sh :results output
+# On an enterprise network with a broken/absent CA cert, or a WPA2 network with a wrong saved password:
+net doctor --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["outcome"], "|", d.get("next_action"))'
+#+end_src
+Expected: enterprise → outcome needs-user-action, next_action names the CA certificate / identity (no auth-sae/auth-hidden action); wrong password → needs-user-action with the "re-enter the password" message.
+
+*** Bt doctor persistent-power fix (bt Phase 2) — proves out only across a real reboot
+What we're verifying: a deliberately boot-disabled adapter reports =powered-off-persistent= (not the transient =power-on=), =bt doctor --fix= clears the cause and powers it on, and the adapter comes up on its own after a reboot. The reboot-survival is the whole point, so this can't be faked; run on a machine (or VM) you can reboot. Back up =/etc/bluetooth/main.conf= first.
+**** AutoEnable=false → persistent verdict → fix → survives reboot
+What we're verifying: the full loop — break persistence, confirm the verdict, fix, reboot, confirm it stuck.
+#+begin_src sh :results output
+sudo cp /etc/bluetooth/main.conf /etc/bluetooth/main.conf.bak
+# Force the deliberate disable and power the adapter off:
+printf '[Policy]\nAutoEnable=false\n' | sudo tee -a /etc/bluetooth/main.conf
+bluetoothctl power off
+bt doctor --json | python3 -c 'import sys,json; d=json.load(sys.stdin); p=[s for s in d["steps"] if s["id"]=="powered"][0]; print(p["code"], "|", p["evidence"])'
+#+end_src
+- Expected (diagnose): the powered step reads code =powered-off-persistent= and the evidence names AutoEnable=false (not the plain "adapter is powered off").
+#+begin_src sh :results output
+bt doctor --fix --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print("attempts=",[a["id"] for a in d["attempts"]])'
+grep -i autoenable /etc/bluetooth/main.conf
+bluetoothctl show | grep -i powered
+#+end_src
+- Expected (fix): attempts include persist-power; main.conf now reads =AutoEnable=true=; the adapter is powered on now.
+- Reboot the machine.
+#+begin_src sh :results output
+bluetoothctl show | grep -i powered # after the reboot, before touching anything
+#+end_src
+Expected: the adapter is powered on straight out of the reboot (AutoEnable=true held). Restore the backup if desired: =sudo mv /etc/bluetooth/main.conf.bak /etc/bluetooth/main.conf=.
+**** service-disabled and TLP causes (optional variants)
+What we're verifying: the other two persistent causes are named and fixed the same way.
+- Service variant: =sudo systemctl disable bluetooth= (leave it running this boot), power the adapter off, then =bt doctor --json= should read =powered-off-persistent=; =--fix= should re-enable it (check =systemctl is-enabled bluetooth=).
+- TLP variant (only if TLP is installed): add =bluetooth= to =DEVICES_TO_DISABLE_ON_STARTUP= in =/etc/tlp.conf=, power off, diagnose (persistent), =--fix=, confirm bluetooth is dropped from the list.
+Expected: each variant names the persistent verdict and the fix clears exactly that cause, leaving the others untouched.
+
*** Maintenance console — in-person checklist
Re-homed here by the 2026-07-09 audit: this was a second top-level "Manual testing and validation" parent. One parent, per verification.md. Priority and the :test: tag now live on the parent.
Promoted from the build parent when it closed 2026-07-08 — Craig's checklist, runs once in person. Collects everything not agent-verifiable; populate per verification.md as phases land. Known so far: panel look-and-feel vs the E5 prototype (Craig's eyeball); arm-press wording reads right at the moment of use; results-wall readability during a real doctor run; a real UPDATE through the armed guard (and the TTY path once); REBOOT offer after an update; velox in-person glyph check (battery %, charging glyph, low-charge red); SET 80% charge limit sticks across a charge cycle; KILL on a real memory hog.