phase: 17_installer_device_filter
**Phase 17 — final verification pass: complete, all green.** Verified (criteria): - `grep -n "DevicePolicy\|DeviceAllow" deploy/install-agent.sh` → no match; `PrivateDevices=false` retained (line 472) ✓ - `install-agent.sh --help` names `--as-root`/`--caps` with the kernel-gate sentence; `--force` documented ✓ - Fresh fake-root install = pre-phase unit minus the filter lines: `test_a_default_install_unit_is_the_pre_phase_unit_minus_the_filter_lines` + `test_the_template_unit_has_no_device_filter_lines` pass ✓ - Re-run that differs → exit 1 with diff on stdout, `--force` applies, identical re-run silent: `test_a_re_run_that_differs_refuses_without_force_and_applies_with_it` (+ 3 sibling guard pins) pass ✓ - driveripper reproduction — verified **read-only**, no live change: `systemctl cat` shows `User=root`, `CapabilityBoundingSet=CAP_SYS_RAWIO CAP_SYS_ADMIN`, no filter, same `ExecStart`; `active`, `CapEff 0000000000220000`; `/api/disks/snapshot` → 16/16 drives with temperatures ✓ - `uv run pytest` → **1451 passed, 15 skipped**; `bash .agents/validate.sh` → **exit 0** (coverage **98.94%** ≥ 94, `ruff` clean, `pyright` 0 errors, `node --check` + hygiene clean); `uv run pytest -m live --live` → **11 passed**; dev server 9/9 sources `ok` (one initial live failure was a transient gufo timeout, clean on re-run) Docs (inconsistencies found + fixed, incl. pre-existing): - `AGENTS.md` fleet record said driveripper's unit runs `User=dashboards-agent` while the same bullet (and the live host) says `User=root` — rewritten to separate the installed user from the running one. - `AGENTS.md` gap 10 header still claimed "the installer template is what is left" → now records phase 17 as the fix. - `README.md` "with no capabilities" → "with an empty `CapabilityBoundingSet` (unless `--caps`…)", since this phase added the capability flag. - `README.md` battery-test "gated four times" now notes the two session gates in front, matching AGENTS invariant 1. - `.env.example` was missing three README-documented settings (`DASH_ENV_FILE`, `DASH_RELOAD`, `NUT_SIMULATE`) and `AGENT_CERT_BUNDLE` in the agent-variables note — added, annotated; all template values re-checked against `config.py` defaults. Deviations: no live `--force` run on driveripper (needs the Oct-18 sudo-staged installer re-staged — it lacks the flags — and would push agent 1.1.0 mid phase-15 rollout); command + expected diff + post-checks recorded in AGENTS/gap 10. `uv pip list --outdated` still advisory (fastapi 0.153→0.156), untouched as in tasks 02/04 — this phase moved no dependency. Next pending phase: `.agents/phases/todo/18_nav_hamburger/`.
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
**Phase 17 — final verification pass: complete, all green.**
|
||||
|
||||
Verified (criteria):
|
||||
- `grep -n "DevicePolicy\|DeviceAllow" deploy/install-agent.sh` → no match; `PrivateDevices=false` retained (line 472) ✓
|
||||
- `install-agent.sh --help` names `--as-root`/`--caps` with the kernel-gate sentence; `--force` documented ✓
|
||||
- Fresh fake-root install = pre-phase unit minus the filter lines: `test_a_default_install_unit_is_the_pre_phase_unit_minus_the_filter_lines` + `test_the_template_unit_has_no_device_filter_lines` pass ✓
|
||||
- Re-run that differs → exit 1 with diff on stdout, `--force` applies, identical re-run silent: `test_a_re_run_that_differs_refuses_without_force_and_applies_with_it` (+ 3 sibling guard pins) pass ✓
|
||||
- driveripper reproduction — verified **read-only**, no live change: `systemctl cat` shows `User=root`, `CapabilityBoundingSet=CAP_SYS_RAWIO CAP_SYS_ADMIN`, no filter, same `ExecStart`; `active`, `CapEff 0000000000220000`; `/api/disks/snapshot` → 16/16 drives with temperatures ✓
|
||||
- `uv run pytest` → **1451 passed, 15 skipped**; `bash .agents/validate.sh` → **exit 0** (coverage **98.94%** ≥ 94, `ruff` clean, `pyright` 0 errors, `node --check` + hygiene clean); `uv run pytest -m live --live` → **11 passed**; dev server 9/9 sources `ok` (one initial live failure was a transient gufo timeout, clean on re-run)
|
||||
|
||||
Docs (inconsistencies found + fixed, incl. pre-existing):
|
||||
- `AGENTS.md` fleet record said driveripper's unit runs `User=dashboards-agent` while the same bullet (and the live host) says `User=root` — rewritten to separate the installed user from the running one.
|
||||
- `AGENTS.md` gap 10 header still claimed "the installer template is what is left" → now records phase 17 as the fix.
|
||||
- `README.md` "with no capabilities" → "with an empty `CapabilityBoundingSet` (unless `--caps`…)", since this phase added the capability flag.
|
||||
- `README.md` battery-test "gated four times" now notes the two session gates in front, matching AGENTS invariant 1.
|
||||
- `.env.example` was missing three README-documented settings (`DASH_ENV_FILE`, `DASH_RELOAD`, `NUT_SIMULATE`) and `AGENT_CERT_BUNDLE` in the agent-variables note — added, annotated; all template values re-checked against `config.py` defaults.
|
||||
|
||||
Deviations: no live `--force` run on driveripper (needs the Oct-18 sudo-staged installer re-staged — it lacks the flags — and would push agent 1.1.0 mid phase-15 rollout); command + expected diff + post-checks recorded in AGENTS/gap 10. `uv pip list --outdated` still advisory (fastapi 0.153→0.156), untouched as in tasks 02/04 — this phase moved no dependency.
|
||||
|
||||
Next pending phase: `.agents/phases/todo/18_nav_hamburger/`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 24%]
|
||||
...........................s............................................ [ 29%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 63%]
|
||||
................................................................ssssssss [ 68%]
|
||||
sss..................................................................... [ 73%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 93%]
|
||||
........................................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 436 0 100%
|
||||
src/dashboards/app.py 185 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 3490 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1451 passed, 15 skipped, 1 warning in 153.26s (0:02:33)
|
||||
== 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.0 wheel
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
**Implemented (phase 17 task 01 — `deploy/install-agent.sh`)**
|
||||
- Deleted `DevicePolicy=strict` + all nine `DeviceAllow=…` lines from the `do_install` unit heredoc; `PrivateDevices=false` stays explicit.
|
||||
- Rewrote the rationale comment block (and the top-of-file/help paragraph) to the new truth: no device filter on purpose — systemd matches a device-filter glob by *name* against `/proc/devices`, kernel 7.2 lists NVMe as `blkext` (major 259), so `/dev/nvme*` matched nothing and a strict policy denied the whole namespace (driveripper, root included); device access is DAC via the `disk` group + SELinux. Kept the `status=208/STDIN` warning as the reason `PrivateDevices=false` is written out.
|
||||
- `tests/test_deploy_scripts.py`: the sandbox-install test now pins the *absence* of the filter plus `PrivateDevices=false`; added `test_the_written_unit_is_only_comments_and_directives` — a defect found while verifying this task: the unit heredoc is unquoted (so phase 15's `$TLS_UNIT_LINES` expands), which **executes backticked prose** (`disk`, `blkext`, `/dev/nvme*` became `command not found` + a smartctl banner pasted into the unit). Mutation-checked: the pin catches it.
|
||||
- Docs: README install paragraph and four AGENTS.md places (fleet divergence bullet, driveripper sudoers bullet, Deployment paragraph, gap 10) now say the template applies no device filter; the obsolete "missing `/dev/ng*n*`/`/dev/bsg/*` in the allow-list" warning is retired; gap 10 records `--as-root`/`--caps` + the re-run guard as the phase's remaining tasks.
|
||||
|
||||
**Tests / lint / coverage**
|
||||
- `uv run pytest` → **1428 passed, 15 skipped** (was 1427; +1 new test), exit 0.
|
||||
- `bash .agents/validate.sh` → exit 0: `pytest --cov --cov-fail-under=94` **98.94%** total, `ruff check src tests agent` clean, `pyright` 0 errors, `node --check` clean, repo hygiene clean. `uv pip list --outdated` empty (no deps moved).
|
||||
- Task criteria: `grep -n "DevicePolicy\|DeviceAllow" deploy/install-agent.sh` → no match; `bash -n` clean; manual fake-root sandbox install (`--bind 127.0.0.1 --port 9199`) diffed against a HEAD-version sandbox install: directive lines differ **only** by the ten removed filter lines (comments rewritten per the task).
|
||||
|
||||
**README/AGENTS.md**: updated as above (docs stayed in sync mid-phase).
|
||||
|
||||
**Decisions/deviations**: the phase's grep criterion forbids the literal directive names in the script, so the comment explains them in prose ("device-filter glob", "strict device policy") instead of naming `DevicePolicy`/`DeviceAllow`. Added the heredoc-expansion pin (not in the task text) because it is a real pre-existing hazard this task's own comment nearly shipped. **No live-infrastructure changes** — the driveripper reproduction (`--as-root --caps … --force`, `systemctl diff`, 16/16 drives) is task 04's operator-gated step and needs the task 02 flags first.
|
||||
|
||||
**Next pending task**: `.agents/phases/todo/17_installer_device_filter/02_root_and_caps_flags.md`
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 24%]
|
||||
...........................s............................................ [ 29%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 64%]
|
||||
.........................................sssssssssss.................... [ 69%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 94%]
|
||||
.................sss.................................................... [ 99%]
|
||||
... [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 436 0 100%
|
||||
src/dashboards/app.py 185 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 3490 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1428 passed, 15 skipped, 1 warning in 127.90s (0:02:07)
|
||||
== 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 ==
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
**Task 02 — `--as-root` / `--caps` (phase 17) — done**
|
||||
|
||||
- `deploy/install-agent.sh`: added `--as-root` (`User=root`) and `--caps LIST` (`CapabilityBoundingSet=<space-separated>`), both off by default → default unit byte-identical to before; comma→space normalisation drops empty entries and runs with globbing off (`--caps '*'` stays literal).
|
||||
- Validation: `--caps` without `--as-root` → stderr refusal + exit 1 **before** `need_root` and any write (same reasoning as the bundle validator); `--caps` with no argument / empty / punctuation-only → exit 1 with its own sentence; `--as-root` alone proceeds with the exact CapEff-0 note on stdout.
|
||||
- Unit heredoc gained the one `--caps` comment above `CapabilityBoundingSet=`; `--status` and the token-file `0640 root:dashboards-agent` logic deliberately untouched; `--help` (the header comment) now names both flags with the kernel-gate sentence and the copy-pasteable recipe line.
|
||||
- Tests (`tests/test_deploy_scripts.py`, 8 new / 12 new cases): exact `User=`/`CapabilityBoundingSet=` lines for default, `--as-root --caps …`, `--as-root` alone; parametrized refusals asserting nothing was written and no privileged stub ran; missing-argument refusal; normalisation + no-glob; `--help` recipe; `status()` blind to `AS_ROOT`/`CAPS`.
|
||||
- `bash .agents/validate.sh` → **1439 passed, 15 skipped**, coverage **98.94%** (floor 94), `ruff check src tests agent` clean, `pyright` 0 errors, `node --check` clean, `bash -n deploy/install-agent.sh` clean; `uv run pytest -m live --live` → **11 passed** (unchanged).
|
||||
- Docs: README (install flag block + a new kernel-gate paragraph) and AGENTS.md (fleet record, sudoers/grant bullet, deployment flag list, gap 10 tail) now state the flags exist, the `driveripper` recipe `--as-root --caps CAP_SYS_RAWIO,CAP_SYS_ADMIN`, and that the unconditional unit rewrite is task 03's remaining guard.
|
||||
- **No live changes made**: the driveripper re-run (`systemctl diff`, `CapEff`, 16/16 drives) is task 04's operator-verified criterion, and gap 10 warns the sudo-granted Oct-18 *staged* snapshot would clobber the working unit — it must be re-staged from the repo first (now noted in AGENTS.md).
|
||||
- Advisory only (not touched, deps not in scope): `uv pip list --outdated` reports `fastapi 0.153.0 → 0.154.0`.
|
||||
- Next pending task: `.agents/phases/todo/17_installer_device_filter/03_no_silent_clobber.md`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 24%]
|
||||
...........................s............................................ [ 29%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 64%]
|
||||
....................................................sssssssssss......... [ 69%]
|
||||
........................................................................ [ 74%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 94%]
|
||||
............................sss......................................... [ 99%]
|
||||
.............. [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 436 0 100%
|
||||
src/dashboards/app.py 185 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 3490 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1439 passed, 15 skipped, 1 warning in 135.34s (0:02:15)
|
||||
== 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.154.0 wheel
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
All green. Report:
|
||||
|
||||
**Implemented**
|
||||
- `deploy/install-agent.sh`: new `--force` flag (`FORCE=0` default) + `--help` text (`--force overwrite an existing unit even if the generated unit differs (prints the diff first)`, aligned to the `--as-root`/`--caps` column).
|
||||
- `do_install` now renders the unit heredoc to `mktemp "${TMPDIR:-/tmp}/dashboards-agent-unit.XXXXXX"`; if `$UNIT` exists and `! cmp -s`, it prints `refusing to overwrite $UNIT (generated unit differs); run with --force to apply:` + `diff -u` and `exit 1` **before** the unit write, `daemon-reload` and `enable --now`; with `--force` it prints the same diff then overwrites; identical unit → silent proceed. `--status`/`--uninstall` untouched.
|
||||
- 8 new pins in `tests/test_deploy_scripts.py`: refuse (exit 1, diff on stdout, unit byte-identical to the hand-edit, token value+`0640` unchanged, **zero new `systemctl` calls**), force (diff then write + re-enable), silent idempotent re-run, fresh install unaffected (plain vs `--force` render identical), the `driveripper` kernel-gate line refuses once → applies with `--force` → silent afterwards, uninstall never asks, source-ordering pin (render < cmp < write < reload < enable, no `cat > "$UNIT" <<` remains), and a `--help` alignment pin.
|
||||
- Docs: README install block + a re-run-guard paragraph, and TLS-rollout step 2 now runs `--cert-bundle … --force` with the reason (installing a bundle *is* a unit change); AGENTS.md fleet bullet, the Commands flag list + guard paragraph, gap 10's task-03 status, and gap 11's staged-snapshot warnings (the Oct-18 copy predates the guard, so it still clobbers silently).
|
||||
|
||||
**Tests / lint / coverage**
|
||||
- `uv run pytest` → **1447 passed, 15 skipped**; `bash .agents/validate.sh` → green (coverage **98.94%**, floor 94%), `ruff check src tests agent` clean, `pyright` 0 errors, `node --check` ok.
|
||||
- `uv run pytest -m live --live` → 11 passed (read-only; dev server still 9/9 `ok`). **No live infra change** — the `driveripper` `--force` reproduction is task 04's operator-verified step.
|
||||
|
||||
**Decisions / deviations**
|
||||
- Guard sits immediately before the unit write (the task's own parenthetical), so the earlier idempotent writes still run; the refusal path never re-writes the unit nor touches the service, and the reused token's value/mode are pinned unchanged (mtime isn't — noted in the test and script comment).
|
||||
- Refusal sentence *and* diff both go to stdout (the diff is the answer's payload; task-04 pins "diff on stdout"). Temp file gets a readable prefix so the diff's `+++` names the generated unit.
|
||||
- Wrote the formal pins now rather than leaving the guard untested until task 04; task 04's remaining doc/live items are untouched except where my change made prose stale.
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/17_installer_device_filter/04_tests_docs_gate.md`
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 24%]
|
||||
...........................s............................................ [ 29%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 64%]
|
||||
............................................................sssssssssss. [ 68%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 93%]
|
||||
....................................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 436 0 100%
|
||||
src/dashboards/app.py 185 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 3490 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1447 passed, 15 skipped, 1 warning in 146.51s (0:02:26)
|
||||
== 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.154.0 wheel
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
**Implemented**
|
||||
- `tests/test_deploy_scripts.py`: added the four task-named pins — `test_the_template_unit_has_no_device_filter_lines` (heredoc region + the whole-file `DevicePolicy`/`DeviceAllow` absence, `PrivateDevices=false` kept, rationale must name `/proc/devices`/`blkext`/status 208), `test_a_default_install_unit_is_the_pre_phase_unit_minus_the_filter_lines` (whole pre-phase unit recorded verbatim as `PRE_PHASE_DEFAULT_UNIT` + `DEVICE_FILTER_LINES`, unified-diff failure output), `test_as_root_and_caps_write_the_kernel_gate_unit_lines` (recipe changes **exactly** two directives vs a default install; `--caps` alone refused before any privileged call; `--as-root` alone proceeds with the CapEff note), `test_a_re_run_that_differs_refuses_without_force_and_applies_with_it` (refuse→force→silent on one host).
|
||||
- Mutation-checked both new filter pins (re-adding `DevicePolicy=strict`+`DeviceAllow=/dev/nvme*`, dropping `RestrictRealtime`, flipping `ProtectHome`) fail; script restored and `bash -n` clean.
|
||||
- Docs: README's TLS rollout now restarts the service after `--force` and says why (installer uses `systemctl enable --now`, which only *starts*; `--status` picks http/https by reading the unit file); AGENTS.md gap 10 + the Deployment paragraph record task 04's read-only reproduction, the Oct-18 staged snapshot refusing the recipe with `unknown argument: --as-root`/exit 2, and the test count 1427→1451.
|
||||
|
||||
**Tests / lint** (`uv run`, exact): `bash .agents/validate.sh` → **exit 0** — `pytest --cov --cov-fail-under=94` **1451 passed, 15 skipped, coverage 98.94%**; `ruff check src tests agent` clean; `pyright` 0 errors; `node --check` + repo hygiene clean. `uv run pytest tests/test_deploy_scripts.py` → 63 passed, 0 failed. `uv run pytest -m live --live` → **11 passed, 0 skipped**; dev server all 9 sources `ok`.
|
||||
|
||||
**README/AGENTS changes:** as above (plus `data/logs/NOTES-17-installer-repro.md`, local/gitignored evidence).
|
||||
|
||||
**Decisions / deviations**
|
||||
- "Byte-identical minus the ten filter lines" is compared on **directives** (comments are the one thing task 01 rewrote deliberately); the new prose is pinned separately for its mechanism sentences. Documented in the test.
|
||||
- **No live change made.** `driveripper`'s installed unit was diffed (read-only, `systemctl cat`) against the sandbox render of `--bind 10.1.0.126 --port 9120 --as-root --caps CAP_SYS_RAWIO,CAP_SYS_ADMIN`: **every directive identical**, only comments differ; host `active`, `CapEff 0000000000220000`, 16/16 drives with temps. Running the real `--force` needs re-staging the sudo-granted Oct-18 snapshot (which lacks the flags, so it can't run them) and would push agent 1.1.0 to a prod host mid phase-15 rollout — left to the operator with the exact command, expected diff and post-checks in the note.
|
||||
- `uv pip list --outdated` advisory (fastapi 0.153→0.155) left untouched, same handling as task 02; deps are not in this task's scope.
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/18_nav_hamburger/01_hamburger_markup.md` (phase 17 has no other todo task).
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 14%]
|
||||
........................................................................ [ 19%]
|
||||
........................................................................ [ 24%]
|
||||
...........................s............................................ [ 29%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 63%]
|
||||
................................................................ssssssss [ 68%]
|
||||
sss..................................................................... [ 73%]
|
||||
........................................................................ [ 78%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 93%]
|
||||
........................................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 436 0 100%
|
||||
src/dashboards/app.py 185 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 3490 37 99%
|
||||
Required test coverage of 94% reached. Total coverage: 98.94%
|
||||
1451 passed, 15 skipped, 1 warning in 154.14s (0:02:34)
|
||||
== 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.155.0 wheel
|
||||
Reference in New Issue
Block a user