docs: disk-health phase 1 — capability map, roadmap arc, register rows R-328..R-333
gates / gates (push) Successful in 14s

- capability-map: the disk-failure scenario no longer says a failing disk has
  never been seen. Healthy path + delivery + the severity wire stay PROVEN-LIVE;
  the new Hiba-from-counters path is IMPLEMENTED and explicitly NOT proven-live
  (R-332), because it has only ever run against the fixture's values.
- ROADMAP R-73: phase 1 shipped; the genuinely hub-side half splits into R-330
  (phase 2, a declared wire change under G-1) and R-331 (phase 3, growth-rate
  detection and retiring the static 64). Its premise 'no demo hardware exposes
  real SMART' is retired — a real failing drive is now committed as a fixture.
- register: R-328 (the severity drop, CLOSED and proven live side by side),
  R-329 (app_start_failed has the same defect, needs a decision first),
  R-330/R-331 (phases 2 and 3), R-332 (the Fail path has never fired on real
  hardware, WATCHING), R-333 (NVMe temperature bands measured 2 degrees from
  tripping on a healthy drive; and the agent's smartctl has no -n standby).
This commit is contained in:
2026-08-14 08:33:13 +02:00
parent 848de8153d
commit 767960bb11
3 changed files with 9 additions and 2 deletions
+1 -1
View File
@@ -162,7 +162,7 @@ by looking a fourth time.**
| R-14 | Headscale/WireGuard spike: Minecraft/gaming port connectivity (CGNAT-proof, sovereign DERP fallback) | M | idea | |
| R-15 | Multi-user dashboard accounts (household members, roles) | L | idea | Single password is a stated alpha limitation (R-11). **Launcher coupling — REVISED (controller v0.165.0):** the "share the launcher outside the household" need is now met WITHOUT member accounts — the **Indítópult megosztása** capability-URL guest link (`/s/<token>`, information-only, no account) shipped in v0.165.0. What remains for this arc is member-specific: **per-member tile visibility** (each member sees only their apps) and the launcher-as-member-landing-page — both live inside this SSO/members arc; the guest-link ruling explicitly SUPERSEDES the earlier "members are how you share the launcher" framing |
| R-72 | Curate `brand_color` for the top catalog apps | XS | idea | Parked follow-up to the v0.163.0 launcher. `.felhom.yml` `brand_color` (`#rgb`/`#rrggbb`) overrides the deterministic slug-hash tile color; no catalog app sets it yet. Pick brand-accurate colors for the most-installed apps so their launcher tiles match their real brand. Catalog-only change (`app-catalog-felhom.eu`), `brand_color` is already `omitempty` and consumed by the controller |
| R-73 | **SMART history / trending (hub-side)** | M | idea (parked) | Parked follow-up to the v0.169.0 disk-health card + degradation alert (agent v0.94.0 serializes SMART into `/disks`; controller renders „Lemezek állapota" + fires `disk_health_degraded` on a degradation). Today the verdict is point-in-time and the baseline is in-memory (a controller restart re-baselines silently). Hub-side would let the operator SEE a disk's SMART counters trend over time (reallocated/pending sectors climbing, NVMe wear %), catch slow degradation the 6h transition check can miss between reboots, and persist the baseline across restarts. Needs a hub ingest surface for periodic SMART snapshots + a small time-series store + an operator trend view. **No demo hardware exposes real SMART** (virtualized), so this only earns evidence on a real box |
| R-73 | **SMART history / trending (hub-side) — SUPERSEDED by the phased disk-health arc; see R-330 (Phase 2) and R-331 (Phase 3)** | M | **partly SHIPPED** | **Phase 1 SHIPPED (controller v0.215.0, 2026-08-14):** the two halves of this item that did not need the hub are done — the baseline is **persisted** across restarts (`disk-health-state.json`, so a controller that restarts while a disk is failing no longer forgets), the point-in-time verdict became a **ladder** that can reach Hiba from raw counters, the poll went 6h → **hourly**, and the alert now carries a severity the hub actually routes. The premise *"no demo hardware exposes real SMART"* is **no longer true**: a genuinely failing drive was captured on DooPlex on 2026-08-14 and its raw `smartctl`/`smartd` output is committed as a fixture (`audits/DIAG-smart-passed-trap-2026-08-14.md`). What REMAINS of R-73 is the genuinely hub-side half — an ingest surface for periodic SMART snapshots, a time-series store and an operator trend view — which is now tracked as **R-330 (Phase 2: collect attrs 187/199/188 + persist samples; a declared WIRE change, so the hub models them in the same session under G-1)** and **R-331 (Phase 3: growth-rate detection on that history, and revisit the static 64-sector threshold, which is a judgement from ONE drive)** |
| R-74 | **Island control plane on a CLUSTER (Peti's 2 nodes)** — bring R-50's island bridge to a multi-node PVE cluster. | M | idea (Phase C of R-50, parked) | R-50 shipped the island for the ONE-host fleet (demo-hp, demo-felhom). A cluster needs **bridge parity on every node**: either per-node identical `/etc/network/interfaces` `vmbr9` stanzas (simplest, drift-prone) or — preferred at ≥2 nodes — a Proxmox **SDN zone/vnet** defined cluster-wide (one definition, auto-applied per node). The guest island IP is per-guest + node-independent; the **agent-follows-guest** rule holds (each node's agent binds its own `vmbr9` `169.254.253.1`). Migration order per the spike: drill-proven → demo (done) → **Peti (this row)**. Its own supervised runbook, coordinated with Peti (a live customer). Completes the capability-map "site/network change" row for clustered installs. Source: `audits/SPIKE-island-bridge-2026-07-25.md` (cluster-parity finding) + `RUNBOOK-island-migration.md` (single-host procedure to generalise) |
| R-75 | **Catalog-derived userdata skeleton + import surfaces** | M | **SHIPPED (controller v0.172.0 + catalog, 2026-07-26)** | `${IMPORT_PATH}` = `<system namespace root>/userdata/import` — ONE canonical drop-zone per box on the system drive, with **no per-drive fallback** (unresolvable leaves the var unset so compose fails loudly). *Operator ruling overriding the spike's Fork-1 per-drive recommendation:* each drop-zone app has exactly one ingest bind, so a per-drive `import/` would put a dead lookalike on every other drive — unbacked too, since `import/*` is `class: excluded`. Third `BindRoot` (`RootImport`) threaded through the classifier AND every resolver (`resolveAbs` would otherwise have named a directory on the WRONG DRIVE); catalog-derived skeleton, **sorted** (the naive map-order derivation measured 20 distinct outputs from 20 identical runs — a fleet-wide FileBrowser restart loop via `fbNeedsRecreate`); one authoritative compose parser; FileBrowser „Beolvasás" source; app-page „Hova tegyem a fájlokat?" with `PathEscape` deep links and **class-driven** copy; `data_paths:` annotation (malformed path ⇒ whole-block reject, unknown role ⇒ fails OPEN); system-owned `beolvasas` SMB share refused server-side at handler AND store. **Live-proven on demo-hp:** consume bind resolves to the system drive, a file dropped through FileBrowser's mount was ingested and deleted in ~30 s, the share auto-appeared on enable and survived a direct delete POST, and the before/after directory diff on BOTH boxes shows **zero removals** (demo-hp gained `media/podcasts`, the one genuinely derived entry). Two defects found and fixed during the live legs: `EnsureImportRoot` left the parent `userdata` at 755, and the carry-list initially re-created the per-drive drop-zone forever. Capability-map row *File access via browser* **deliberately NOT upgraded** — nothing drove the FileBrowser HTTP UI. Docs: `controller/import-and-data-paths.md`, spike `audits/SPIKE-catalog-data-paths-2026-07-26.md` |
| R-77 | **Endpoint-drift detection, samba protected-set gate, channel log honesty** | S | **SHIPPED (controller v0.173.0 + hub v0.74.0, 2026-07-26)** | Fixes the two defects in `audits/DIAG-agent-channel-2026-07-26.md`. `bootstrap.DetectEndpointDrift` names a `controller.yaml` vs `bootstrap.json` `local_api.endpoint` divergence with its own event type `local_api_endpoint_drift` and its own banner — and **writes nothing** (see R-78). `EffectiveProtected` now gates samba on `Enabled && UserSet`, mirroring both of `reconcileSambaAt`'s early returns, plus the doc-comment correction. Channel log distinguishes born-down (`unseeded->down`) from a real transition, logging-only. **Part 0 repaired both production boxes** (endpoint → `169.254.253.1:8443`; fingerprint+token agreed). Tests 951→959; red-proofs A/E/F. |