Convert the 11 TODO items to phases 20-24 (masthead/nav polish, page cleanups, /disks hiding unconfigured hosts, LLM rate window, dev mTLS rollout). TODO.md cleared; items now live in .agents/phases/todo/. LLM-Generated: true
3.5 KiB
3.5 KiB
Task 04 — The fleet is mTLS: the end state, verified
Phase: 24_dev_mtls_rollout · Source: TODO.md:3 — "…so we never need non-mtls servers."
Story: n/a
Objective
The end state is proven read-only, the way phase 15's task-05 final pass proved its composition: the dashboard dials all three agents with its client certificate, the issued-vs-deployed revisions agree, nothing non-mTLS is left in the config, and the things the bundle install must not have broken (driveripper's 16 SMART reads, deskwork's GPU row) still work. No live revocation is performed — the revocation wiring is phase 15's e2e proof (data/logs/verify-15-tls-e2e.py), and a live revoke of a working fleet is a change, not a check.
Work
./scripts/dev-server.sh status— the nine-source tableok(host:driveripper,host:deskwork,host:gateway,disks:driveripper,disks:deskwork,disks:gateway,nut,llm:gufo,llm:vllm);disks:gatewayisokwith the page hiding gateway (phase 22's gate) — the job healthy, the page scoped.- Signed-in
GET /api/certs: all three rowsstatus: "active",deployed_bundle_rev == bundle_rev(the "install the new bundle" sentence is gone for every host),agentblock from thesystempayload:agent.tls: true+agent.bundle_revpresent on all three (the task-03 passthrough — a token-mode snapshot grows nothing, so the fields' presence is the mTLS proof, rule 2's shape). - Signed-in
GET /api/system/snapshot+GET /api/disks/snapshot: theagentblocks on all three hosts; gateway's row absent from/disks(phase 22); driveripper's 16 drives with live SMART numbers (the--forceunit rewrite is the gap-10 shape — asmart: nullrow here fails the task); deskwork'snvme0n1row and its GPU card on/system(the 1.1.0 agent file's reads intact). - The config:
grepof.env.dev— nohttp://inHOST_TARGETS, no@userinfo in any target URL;data/env-backup/holds the pre-flip copy (the rollback path exists on disk). - The negative control, without touching the fleet:
data/logs/verify-15-tls-e2e.py's transcript (phase 15) is the standing proof that a revoked serial is refused on/healthtoo; this task re-runs none of it live — it names the transcript as the control and checks only thattests/test_collectors.py's revocation-before-dial pin andtests/test_api.py'sbuild_hubwiring pin are green (they run in the suite). - Screenshots (invariant 10) in
data/logs/:/certs(the three active rows with matching revs),/disks(the two visible hosts, driveripper's 16 live rows),/system(deskwork's GPU card) — the "the dashboard says all three are mTLS" proof is a screenshot, not a curl.
Testing & Quality
- Coverage: n/a (verification task)
- The read-only rule: no
POSTto the fleet, noupsdcommand, no revocation, no unit change — the task reads the fleet and screenshots it
Completion Criteria
- nine sources
ok;deployed_bundle_rev == bundle_revandagent.tls: truefor all three hosts (pinned by the API checks, shown by the screenshots) .env.devhas nohttp://agent URL and no userinfo; the pre-flip backup exists- driveripper's 16 SMART reads and deskwork's GPU card are live in the served payloads
- screenshots of
/certs,/disks,/systemindata/logs/ - the revocation pins (
tests/test_collectors.py,tests/test_api.py) green in the suite - the full suite +
bash .agents/validate.shgreen; AGENTS.md's fleet record and gap 11 updated by the phase's Documentation & Consistency pass to the mTLS end state