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
4.6 KiB
Phase 22 — /disks hides hosts without smartctl
Source: TODO.md L13 — "VMs that don't have smartctl enabled disks should not show up. Gateway shouldn't even be a host on the disks page."
Story: n/a
Context: src/dashboards/api.py (disks_router() at line 791 — /api/disks/snapshot answering one entry per configured host; the /api/summary disks block at lines 640–704 — disks_hosts built from job.state.payload or _disks_stub(...) at line 640, fleet_disk_summary(disks_hosts) at line 693; _disks_stub() at line 771 — smartctl_available: None for a never-answered host), src/dashboards/sources/disks.py (smartctl_available() at line 142 — the three-way flag: True a disk answered, False the agent said the binary is not installed, None an agent predating the pass or --no-smart), src/dashboards/web/static/page-disks.js (the per-host cards + the fleet_disk_summary header, hidden below two hosts), tests/test_api.py (the /api/disks/* pins — "one entry per configured host", the smartctl_available three-way, "with and without targets configured", the fleet_disk_summary key paths)
Objective
A host whose agent answered smartctl_available: false (the binary is not installed — gateway's VM, no smartmontools behind vda) is not a host on the /disks page at all: it is absent from /api/disks/snapshot, from the fleet block and from /api/summary's disks rows, and the fleet header counts only the hosts that are shown. The three-way flag itself is unchanged in sources/disks.py (the agent still reports it, the /disks page's null-case why-line still exists for None hosts, and an unreachable host keeps its dimmed stub row — a dead agent is a different fact from a missing binary, invariant 3). The filter is one API-level decision, so the source, the store and the health records see nothing new.
Dependencies
21_page_cleanups(todo) — both phases touch the/diskspage markup (task 21.01 removes the page's#pausebutton); landing 21 first keeps this phase's diff confined to the host list.
Tasks
01_hide_smartctl_false_hosts.md— the one API-level visibility gate (explicitFalseonly) over/api/disks/snapshot,/api/summary's disks block and the fleet summary; the pins rewritten02_verification.md— browser + API verification against the live fleet: gateway absent, deskwork/driveripper intact, fleet header consistent, screenshots
Testing & Quality
- Unit/integration:
tests/test_api.py— the rewritten/api/disks/snapshotpin (one entry per configured host whose agent can read its drives — asmartctl_available: falsepayload is absent, aNonepayload is present, anunreachablestub is present), the/api/summarydisks-block pin (fleet counts over the visible hosts, per-host rows for the visible hosts only), the unchangedsmartctl_availablethree-way pin insources/disks.py's own tests (tests/test_disks.pyor wherever the flag is pinned — grepsmartctl_availableintests/first) - Coverage: >90% on new/modified code
- The phase is "Complete" only when the entire project test suite passes 100% (every test in the project, not just this phase's)
Documentation & Consistency
- The final pass reviews
README.mdandAGENTS.mdin full against the project as it stands after this phase — fixing every inconsistency found, including pre-existing ones not caused by this phase. AGENTS.md'ssources/disks.pybullet (the three-way flag'sFalsearm — "so the page can say install smartmontools") and the/disksUI paragraph (the.banner.infowhy-line forfalse) are rewritten: thefalsearm's page-side consequence is now absence, and the three-way flag keeps its agent-side meaning; the "gateway answerssmartctl_available: false" fleet fact gains the "and is therefore not a host on the disks page" clause.
Completion Criteria
/api/disks/snapshotand/api/summary's disks block carry no entry for a host whose agent answeredsmartctl_available: false; aNonehost and anunreachablestub both remain (pinned both ways intests/test_api.py)- the
/diskspage on the live fleet shows deskwork + driveripper only, the fleet header counts 2 hosts, and the per-host cards are unchanged (screenshot indata/logs/) uv run pytestgreen, coverage not down,ruff+pyrightcleanbash .agents/validate.shgreen- no behavior change in completed work: the agent's SMART pass, the
disks:<host>job's health record, the storeddisk.*series, theNone-case why-line and the unreachable stub are all untouched