Files
dashboards/.agents/phases/complete/24_dev_mtls_rollout/04_verification.md
T
ducoterra 89d9fb9f89 phase: 24_dev_mtls_rollout
**Phase 24 final verification — all green**

- **Verified (read-only re-run, 62/62 PASS)** via `data/logs/verify-24-mtls.py`: nine sources `ok`; `/api/certs` all three `active` with `deployed_bundle_rev == bundle_rev == 2`; `agent.tls: true` + `agent.version 1.1.0` on every host; driveripper 16/16 drives live; gateway absent from `/disks` but `disks:gateway ok`; all served target URLs `https://`, no userinfo; pre-flip backup present; no transport/cert alert.
- **Criterion 1 (export):** `data/certs/{driveripper,deskwork,gateway}.bundle` re-checked byte-identical (sha256) to `GET /api/certs/<name>/bundle`, mode `0600`, under gitignored `data/`; live arms re-probed (issued→file, unknown/`issued:false`→one-line note + no file, wrong password→exit 2, nothing written).
- **Criterion 2 (`--fetch-bundle`):** 54 sandbox pins in `tests/test_deploy_scripts.py` pass — byte-identical `0640` install + TLS unit lines, refusals (unissued / 401 / non-bundle body / dead dashboard) before `need_root` with no write, token absent from token file, unit, stdout and sudoers hint.
- **Criterion 3–4:** `./scripts/dev-server.sh status` nine `ok` + bundles block; screenshots `data/logs/24-task04-{certs,disks,system}.png` exist.
- **Criterion 7:** no behavior change — `agent/` untouched, `src/` diff is a `certs.ensure_certs` docstring only; token-mode, revocation-before-dial and bundle-route tests green.
- **Tests/lint:** `bash .agents/validate.sh` → **EXIT=0**; `uv run pytest --cov --cov-fail-under=94` → **1542 passed, 15 skipped, coverage 98.94%**; `ruff check src tests agent` → All checks passed; `pyright` → 0 errors; `node --check` clean; `uv run pytest -m live --live` → **11 passed**.
- **Docs:** README.md (all 1144 lines) + AGENTS.md reviewed against the live project — every config.py env var is in README and both templates, route set / severity thresholds / test counts / coverage figure match, all repo paths, cited test names and `Dash.*`/`DashCharts.*` helpers resolve, phase-24 doc pins green. **Verified consistent — no changes needed.**
- **Notable:** left `fastapi 0.153.0 → 0.158.0` (validate reports it as advisory; no dependency was touched, rule 8 conditions the check on deps moving). Killed two abandoned `/tmp/fbtest` loopback stub processes left by task 02's manual probe; dev server unaffected.
- **Next pending phase:** `.agents/phases/todo/25_masthead_control_placement/`.
2026-10-21 13:47:45 -04:00

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

  1. ./scripts/dev-server.sh status — the nine-source table ok (host:driveripper, host:deskwork, host:gateway, disks:driveripper, disks:deskwork, disks:gateway, nut, llm:gufo, llm:vllm); disks:gateway is ok with the page hiding gateway (phase 22's gate) — the job healthy, the page scoped.
  2. Signed-in GET /api/certs: all three rows status: "active", deployed_bundle_rev == bundle_rev (the "install the new bundle" sentence is gone for every host), agent block from the system payload: agent.tls: true + agent.bundle_rev present 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).
  3. Signed-in GET /api/system/snapshot + GET /api/disks/snapshot: the agent blocks on all three hosts; gateway's row absent from /disks (phase 22); driveripper's 16 drives with live SMART numbers (the --force unit rewrite is the gap-10 shape — a smart: null row here fails the task); deskwork's nvme0n1 row and its GPU card on /system (the 1.1.0 agent file's reads intact).
  4. The config: grep of .env.dev — no http:// in HOST_TARGETS, no @ userinfo in any target URL; data/env-backup/ holds the pre-flip copy (the rollback path exists on disk).
  5. 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 /health too; this task re-runs none of it live — it names the transcript as the control and checks only that tests/test_collectors.py's revocation-before-dial pin and tests/test_api.py's build_hub wiring pin are green (they run in the suite).
  6. 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 POST to the fleet, no upsd command, no revocation, no unit change — the task reads the fleet and screenshots it

Completion Criteria

  • nine sources ok; deployed_bundle_rev == bundle_rev and agent.tls: true for all three hosts (pinned by the API checks, shown by the screenshots)
  • .env.dev has no http:// 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, /system in data/logs/
  • the revocation pins (tests/test_collectors.py, tests/test_api.py) green in the suite
  • the full suite + bash .agents/validate.sh green; AGENTS.md's fleet record and gap 11 updated by the phase's Documentation & Consistency pass to the mTLS end state