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/`.
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
**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/`.
|
||||
@@ -0,0 +1 @@
|
||||
ok
|
||||
@@ -0,0 +1,66 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 23%]
|
||||
.........................................................s.............. [ 27%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 46%]
|
||||
........................................................................ [ 50%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 64%]
|
||||
........................................................................ [ 69%]
|
||||
sssssssssss............................................................. [ 73%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
...........................................................sss.......... [ 97%]
|
||||
............................................. [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 32
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 440 0 100%
|
||||
src/dashboards/app.py 186 0 100%
|
||||
src/dashboards/auth.py 265 0 100%
|
||||
src/dashboards/certs.py 292 0 100%
|
||||
src/dashboards/collectors.py 205 5 98% 284-285, 289-290, 307
|
||||
src/dashboards/config.py 120 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 112 5 96% 126, 163, 177, 180, 183
|
||||
src/dashboards/rates.py 73 0 100%
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 134 0 100%
|
||||
src/dashboards/sources/host.py 209 0 100%
|
||||
src/dashboards/sources/llm.py 178 1 99% 285
|
||||
src/dashboards/sources/nut.py 413 20 95% 153, 172, 186, 198, 204, 217, 225, 241, 319-320, 322, 579, 591, 626, 657, 661, 718-719, 724, 736
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 313 2 99% 553-554
|
||||
------------------------------------------------------------------
|
||||
TOTAL 3495 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1542 passed, 15 skipped, 1 warning in 165.53s (0:02:45)
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
advisory: dependencies are out of date (AGENTS.md rule 8 — update on purpose):
|
||||
fastapi 0.153.0 0.158.1 wheel
|
||||
@@ -0,0 +1,15 @@
|
||||
**Implemented**
|
||||
- `scripts/dev-certs-export.py` (new, stdlib `urllib`): `--url/--password(+$DASH_ADMIN_PASSWORD)/--names/--out-dir`; signs in via public `POST /api/auth/login`, reads the token out of `Set-Cookie`, `GET /api/certs/<name>/bundle` per name; writes `0600` via `os.open` (birth mode + re-chmod) into gitignored `data/certs/`. Arms: issued→file, `issued:false`/`configured:false`→one-line note + no file, other statuses→`!` line; exit 0 all-resolved / 1 a refused host (others still attempted) / 2 no sign-in. Reads the route only — never `ensure_certs`, so it cannot mint.
|
||||
- `scripts/dev-server.sh`: `export_bundles` after the readiness probe (names split from `HOST_TARGETS`, failure = `|| echo` warning, never fails `start`); `bundles` block (names/sizes/modes) printed by `status` and as its own subcommand.
|
||||
- 19 new tests in `tests/test_deploy_scripts.py`: real `create_app` served by uvicorn on `127.0.0.1:0`, byte-identity vs the route, `0600` (+ re-chmod of a loosened file), unissued/unconfigured notes, wrong-password & no-server exit 2 writing nothing, idempotence, "never mints" (serials/revs/root unchanged), no PEM/token/password printed, name-escape refusal, and the dev-server composition pins (order, warning-only, `status` block, `CERTDIR` under `data/`).
|
||||
|
||||
**Verification** — `bash .agents/validate.sh`: `uv run pytest --cov --cov-fail-under=94` → **1513 passed, 15 skipped**, coverage **98.94%** (floor 94%); `ruff check src tests agent` clean (also clean on `scripts/`); `pyright` 0 errors; `node --check` ran. `uv run pytest -m live --live` → **11 passed**. Real boot: `./scripts/dev-server.sh restart` exported `data/certs/deskwork.bundle` (1430 B, `mode 0600`, byte-identical to the route; verified over HTTP) and printed the unissued note for `driveripper`/`gateway`; `status` still reads nine sources `ok`.
|
||||
|
||||
**Docs** — README (Quickstart `bundles` subcommand + export paragraph, new *Managing the certificates* dev paragraph, rollout step 1 note, Testing paragraph) and AGENTS.md (invariant 6 export rules, `certs.py` bullet, Commands block + count 1494→1513, new testing-policy bullet, gap 11 dev-side half closed).
|
||||
|
||||
**Decisions / deviations**
|
||||
- Kept the logic in the standalone script as the task specifies; `scripts/` is outside `[tool.coverage.run] source` (like the other dev scripts), so the gate number is unchanged — the new code is instead exercised end-to-end as a subprocess on every arm plus in-process helper tests.
|
||||
- Cookie name is imported from `dashboards.auth` (with an `ImportError` fallback) so it cannot drift; `--password` also falls back to the env var.
|
||||
- No live-infra changes: only the local dev-server restart and a read-only export over loopback. No fleet change, no bundle installed, no `HOST_TARGETS` edited — tasks 02-04 are untouched. Pre-existing `uv pip list --outdated` advisory (fastapi 0.153.0→0.156.8) left alone: dependencies were not touched here.
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/24_dev_mtls_rollout/02_installer_fetch_bundle.md`
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 23%]
|
||||
.........................................................s.............. [ 28%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 42%]
|
||||
........................................................................ [ 47%]
|
||||
........................................................................ [ 51%]
|
||||
........................................................................ [ 56%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 65%]
|
||||
...........................................sssssssssss.................. [ 70%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 94%]
|
||||
..............................sss....................................... [ 98%]
|
||||
................ [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 32
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 440 0 100%
|
||||
src/dashboards/app.py 186 0 100%
|
||||
src/dashboards/auth.py 265 0 100%
|
||||
src/dashboards/certs.py 292 0 100%
|
||||
src/dashboards/collectors.py 205 5 98% 284-285, 289-290, 307
|
||||
src/dashboards/config.py 120 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 112 5 96% 126, 163, 177, 180, 183
|
||||
src/dashboards/rates.py 73 0 100%
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 134 0 100%
|
||||
src/dashboards/sources/host.py 209 0 100%
|
||||
src/dashboards/sources/llm.py 178 1 99% 285
|
||||
src/dashboards/sources/nut.py 413 20 95% 153, 172, 186, 198, 204, 217, 225, 241, 319-320, 322, 579, 591, 626, 657, 661, 718-719, 724, 736
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 313 2 99% 553-554
|
||||
------------------------------------------------------------------
|
||||
TOTAL 3495 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1513 passed, 15 skipped, 1 warning in 156.26s (0:02:36)
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
advisory: dependencies are out of date (AGENTS.md rule 8 — update on purpose):
|
||||
fastapi 0.153.0 0.156.8 wheel
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
All green. Final state:
|
||||
|
||||
**Implemented**
|
||||
- `deploy/install-agent.sh`: `--fetch-bundle <url> --cert-name <name> --session <token>` — `python3` `urllib` GETs `/api/certs/<name>/bundle`, writes it to a `mktemp` file that becomes `$BUNDLE_SRC`, so the existing shape check → `0640 root:agent` install → unit `--cert-bundle`+`RuntimeDirectory` → `--status` probe all run on fetched bytes unchanged.
|
||||
- Order: flag checks → fetch → `validate_bundle` → `need_root`; refusals (unissued `issued:false`, `401`/`403`/`5xx`/`404`, no dashboard, non-bundle 200 body) print one line and write nothing; `trap cleanup_fetch EXIT` sweeps the temp key on every path.
|
||||
- Refusals added before `need_root`: partial flag set (exit 1), `--fetch-bundle` + local `--cert-bundle` (two sources), fetch with `--status`/`--uninstall`.
|
||||
- Token hygiene: travels to python via env (not argv), only the URL is logged, `unset` before any write, never in the token file/unit/bundle/log nor in the sudoers hint's re-quoted command; `validate_bundle` gained a flag-name label so a fetched refusal says `--fetch-bundle` and the file path still says `--cert-bundle`.
|
||||
- `--help` documents the three flags + copy-pasteable recipe.
|
||||
|
||||
**Tests/lint/coverage** — `uv run pytest` → **1535 passed, 15 skipped**; `bash .agents/validate.sh` → **exit 0** (coverage 98.94%, floor 94%; ruff clean; pyright 0 errors; `node --check` ok; hygiene clean). 12 new pins in `tests/test_deploy_scripts.py` run the real `create_app` on a socket (byte-identical `0640` install + TLS unit lines, unissued/`configured:false`/401 refusals with no stub call logged, non-bundle 200 bodies, dead server, token grep of every file + both streams + sudoers hint, all-or-nothing/two-source/mode refusals, fetch-before-shape-before-root ordering). Four deliberate script mutations were used to confirm the pins bite.
|
||||
|
||||
**Docs** — README: rollout step 1 is now the `--fetch-bundle` registration run (manual signed-in `curl` demoted to the fallback), plus the flag list and the dev-export paragraph; AGENTS.md: invariant 6 (session token as fetch credential), installer deployment paragraph, gap 11 (task 02 landed), testing-policy pin, pytest count.
|
||||
|
||||
**Decisions / deviations**
|
||||
- Pins drive the real `served_dashboard` socket (not a look-alike `http.server`); a canned `http.server` covers only the shapes the app cannot answer (200-with-HTML, empty 200).
|
||||
- Added two refusals beyond the task list (fetch with `--status`/`--uninstall`; per-flag value check follows existing style) — silent ignoring of a credential flag was the alternative.
|
||||
- Live infra: **no live changes made**. Verified read-only against the running dev dashboard: fetched `deskwork` (then correctly stopped at the unprivileged root boundary, token absent from output, temp dir empty) and got the one-line unissued refusal for `gateway`. The per-host rollout is task 03.
|
||||
|
||||
Next pending task: `.agents/phases/todo/24_dev_mtls_rollout/03_fleet_rollout.md` (agent 1.1.0 + bundle on deskwork/driveripper/gateway, `HOST_TARGETS` flipped per host — live, operator-gated root on two hosts).
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 23%]
|
||||
.........................................................s.............. [ 27%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 46%]
|
||||
........................................................................ [ 51%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 65%]
|
||||
.................................................................sssssss [ 69%]
|
||||
ssss.................................................................... [ 74%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 92%]
|
||||
....................................................sss................. [ 97%]
|
||||
...................................... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 32
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 440 0 100%
|
||||
src/dashboards/app.py 186 0 100%
|
||||
src/dashboards/auth.py 265 0 100%
|
||||
src/dashboards/certs.py 292 0 100%
|
||||
src/dashboards/collectors.py 205 5 98% 284-285, 289-290, 307
|
||||
src/dashboards/config.py 120 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 112 5 96% 126, 163, 177, 180, 183
|
||||
src/dashboards/rates.py 73 0 100%
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 134 0 100%
|
||||
src/dashboards/sources/host.py 209 0 100%
|
||||
src/dashboards/sources/llm.py 178 1 99% 285
|
||||
src/dashboards/sources/nut.py 413 20 95% 153, 172, 186, 198, 204, 217, 225, 241, 319-320, 322, 579, 591, 626, 657, 661, 718-719, 724, 736
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 313 2 99% 553-554
|
||||
------------------------------------------------------------------
|
||||
TOTAL 3495 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1535 passed, 15 skipped, 1 warning in 162.74s (0:02:42)
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
advisory: dependencies are out of date (AGENTS.md rule 8 — update on purpose):
|
||||
fastapi 0.153.0 0.156.8 wheel
|
||||
@@ -0,0 +1,18 @@
|
||||
Final state verified. Summary of this task's work:
|
||||
|
||||
**Fleet rollout (live, all three hosts now mTLS-only)**
|
||||
| host | how | proof |
|
||||
|---|---|---|
|
||||
| `gateway` | staged installer + 1.1.0, dry-run diff → `--force`, restart, CA-only `--status` probe, then URL flip | `answering over TLS (bundle rev 2)` |
|
||||
| `deskwork` | same; its `zz-devices.conf` drop-in (`DeviceAllow=/dev/nvme0n1`, SYS_ADMIN caps) survived the rewrite | same, SMART still reads |
|
||||
| `driveripper` | gap-10 line `--as-root --caps CAP_SYS_RAWIO,CAP_SYS_ADMIN --force`; diff moved comments + TLS lines only | same, **16/16 drives with temps before and after** |
|
||||
|
||||
`.env.dev` `HOST_TARGETS` is now `driveripper/deskwork/gateway=https://…:9120` with no `http://`, no userinfo (pre-flip file backed up in `data/env-backup/`); `/certs` reads `bundle_rev == deployed_bundle_rev == 2` on all three; `dev-server.sh status` = nine sources `ok`. Every installer ran twice, once without `--force` to read the guard's diff. A canary revoke on `gateway` proved the bite (`agent certificate revoked (serial …)` on `host:gateway` + `disks:gateway`, page-side too), then restored.
|
||||
|
||||
**Defects found and fixed**
|
||||
- `data/logs/NOTES-24-rollout.md` § *the defect that stopped the first flip*: the stored root predated the SKI fix → strict dials failed `Missing Subject Key Identifier`. Repaired with `POST /api/certs/root/rotate` (not the `DELETE FROM meta` reset), pinned by `tests/test_certs.py::test_a_stored_root_without_an_identifier_still_boots_and_root_rotate_repairs_it` and a new `certs.ensure_certs` docstring paragraph.
|
||||
- The live suite could not dial the fleet (3 failures, `CERTIFICATE_VERIFY_FAILED: self-signed certificate in chain`): `tests/test_live_fleet.py` gained an `agent_tls` fixture (read-only `sqlite3` authority whose `set_meta`/`delete_meta` raise, `certs.write_material` + `collectors.agent_tls_map`), and the four host tests now go through `fetch_snapshot`/`fetch_host_snapshot`/`fetch_disk_snapshot` with `tls=` → **11 passed, 0 failed**.
|
||||
|
||||
**Docs**: `README.md` (rollout order, reverse-tunnel route, `--status --bind` caveat, pre-SKI CA rule, rollback rule, live-suite note) and `AGENTS.md` (fleet record now mTLS + corrected sudo/staging facts, gap 10 trap closed, gap 11 resolved into rotation hygiene, gap 12, testing policy, `--status` address rule).
|
||||
|
||||
**Gates**: `bash .agents/validate.sh` → **EXIT=0** (1536 passed / 15 skipped, ruff clean, pyright clean, `node --check` clean); `pytest -m live --live` → EXIT=0; evidence in gitignored `data/logs/` (`NOTES-24-rollout.md`, `24-*-install.log`, `24-fleet-{before,after,end-state}.txt`, `24-certs-end-state.txt`, `24-units-after-rollout.txt`, `24-mtls-{system,certs}.png`). Only the advisory `fastapi 0.153.0 → 0.157.0` was left alone (no dependency was touched here). Nothing staged, committed, or moved in `.agents/`.
|
||||
@@ -0,0 +1 @@
|
||||
ok
|
||||
@@ -0,0 +1,66 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 23%]
|
||||
.........................................................s.............. [ 27%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 37%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 46%]
|
||||
........................................................................ [ 51%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 64%]
|
||||
..................................................................ssssss [ 69%]
|
||||
sssss................................................................... [ 74%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 92%]
|
||||
.....................................................sss................ [ 97%]
|
||||
....................................... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 32
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 440 0 100%
|
||||
src/dashboards/app.py 186 0 100%
|
||||
src/dashboards/auth.py 265 0 100%
|
||||
src/dashboards/certs.py 292 0 100%
|
||||
src/dashboards/collectors.py 205 5 98% 284-285, 289-290, 307
|
||||
src/dashboards/config.py 120 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 112 5 96% 126, 163, 177, 180, 183
|
||||
src/dashboards/rates.py 73 0 100%
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 134 0 100%
|
||||
src/dashboards/sources/host.py 209 0 100%
|
||||
src/dashboards/sources/llm.py 178 1 99% 285
|
||||
src/dashboards/sources/nut.py 413 20 95% 153, 172, 186, 198, 204, 217, 225, 241, 319-320, 322, 579, 591, 626, 657, 661, 718-719, 724, 736
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 313 2 99% 553-554
|
||||
------------------------------------------------------------------
|
||||
TOTAL 3495 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1536 passed, 15 skipped, 1 warning in 167.02s (0:02:47)
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
advisory: dependencies are out of date (AGENTS.md rule 8 — update on purpose):
|
||||
fastapi 0.153.0 0.157.0 wheel
|
||||
@@ -0,0 +1,19 @@
|
||||
Everything is green. Final state of the work:
|
||||
|
||||
**Implemented (task 04 — read-only verification of the mTLS end state)**
|
||||
- `data/logs/verify-24-mtls.py` + `24-task04-endstate.txt`: 57 signed-in GET assertions — nine sources `ok`; `/api/certs` all three `active` with `deployed_bundle_rev == bundle_rev == 2`; `agent.tls: true` + `agent.bundle_rev` + `agent.version 1.1.0` on every host; driveripper 16/16 drives with temp+hours (same single `nvme5n1` alarm chip, no `smart: null`), deskwork `nvme0n1`; gateway absent from `/api/disks/snapshot` while `disks:gateway` still `ok`; `/api/summary` fleet block identical, **no transport/certificate alert**; `/api/config` + `.env.dev` all `https://`, no userinfo; pre-flip backup present; bundles in gitignored `data/certs/` at `0600`.
|
||||
- `data/logs/24-task04-verify.cjs` → `24-task04-{certs,disks,system}.png` (+ `.log`/`.out`): the same claims as rendered — `#2 → #2` with no `stale` chip on all three rows, deskwork's GPU card with four live values, four masthead dots all green.
|
||||
- Negative control per the task: named phase 15's `verify-15-tls-e2e.py`/`.out` as the standing proof and ran the two suite pins (`tests/test_collectors.py`, `tests/test_api.py`) → 3 passed, logged in `24-task04-revocation-pins.log`. **Nothing revoked, posted or restarted on the fleet.**
|
||||
- Doc-consistency pass (this phase's final pass): README dev quick-start and `HOST_TARGETS` config row now lead with bundle registration; `AGENTS.md` transport bullet, `Commands` block, gap 11 (verification record + pins named) and gap 12 (phase closed) updated, plus a pre-existing duplicated sentence in gap 11 de-duplicated; `.env.example`/`.env.dev.example` now document `https://`-no-userinfo as the shape a new host gets, token mode as the compatibility path.
|
||||
- Added 6 regression pins to `tests/test_deploy_scripts.py` so the docs can't slide back: setup docs must name `--fetch-bundle`/`--cert-name`/`--session`, and every template `HOST_TARGETS` example URL must be `https://` with no userinfo.
|
||||
|
||||
**Gates (exact)**
|
||||
- `uv run pytest` → **1542 passed, 15 skipped**, exit 0; `uv run pytest -m live --live` → **11 passed**, exit 0.
|
||||
- `bash .agents/validate.sh` → **EXIT=0**: coverage **98.94%** (floor 94; `certs.py`/`api.py`/`app.py`/`auth.py` 100%), ruff `All checks passed!`, pyright `0 errors, 0 warnings, 0 informations`, `node --check` clean, repo-hygiene clean.
|
||||
- `./scripts/dev-server.sh status` → `status: ok`, nine sources ok, three bundles exported.
|
||||
|
||||
**Docs**: `README.md`, `AGENTS.md`, `.env.example`, `.env.dev.example` (see above); transcript `data/logs/NOTES-24-verification.md`.
|
||||
|
||||
**Decisions**: no live revoke/restart (read-only by rule); left the advisory `fastapi 0.153.0 → 0.157.0` alone — no dependency was touched.
|
||||
|
||||
**Next pending task**: none in `todo/24_dev_mtls_rollout` (this completes the phase); `25_masthead_control_placement` is next.
|
||||
@@ -0,0 +1 @@
|
||||
ok
|
||||
@@ -0,0 +1,66 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 23%]
|
||||
.........................................................s.............. [ 27%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 46%]
|
||||
........................................................................ [ 50%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 60%]
|
||||
........................................................................ [ 64%]
|
||||
........................................................................ [ 69%]
|
||||
sssssssssss............................................................. [ 73%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 92%]
|
||||
...........................................................sss.......... [ 97%]
|
||||
............................................. [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 32
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 440 0 100%
|
||||
src/dashboards/app.py 186 0 100%
|
||||
src/dashboards/auth.py 265 0 100%
|
||||
src/dashboards/certs.py 292 0 100%
|
||||
src/dashboards/collectors.py 205 5 98% 284-285, 289-290, 307
|
||||
src/dashboards/config.py 120 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 112 5 96% 126, 163, 177, 180, 183
|
||||
src/dashboards/rates.py 73 0 100%
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 134 0 100%
|
||||
src/dashboards/sources/host.py 209 0 100%
|
||||
src/dashboards/sources/llm.py 178 1 99% 285
|
||||
src/dashboards/sources/nut.py 413 20 95% 153, 172, 186, 198, 204, 217, 225, 241, 319-320, 322, 579, 591, 626, 657, 661, 718-719, 724, 736
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 313 2 99% 553-554
|
||||
------------------------------------------------------------------
|
||||
TOTAL 3495 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1542 passed, 15 skipped, 1 warning in 165.02s (0:02:45)
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
advisory: dependencies are out of date (AGENTS.md rule 8 — update on purpose):
|
||||
fastapi 0.153.0 0.158.0 wheel
|
||||
Reference in New Issue
Block a user