Opened every citation in 00-capability-map.md and judged each of the 55 rows against the specific scenario (not topic adjacency). 23 confirmed (incl. 5 MISSING proven-absent by code sweep), 26 citation-corrected, 6 demoted; no upgrades. Status: 32 PROVEN-LIVE / 15 IMPLEMENTED / 3 PARTIAL / 5 MISSING (was 38 PROVEN-LIVE). Demotions PROVEN-LIVE->IMPLEMENTED: B6 (post-deploy config — T-PAGE-ALL is render-only), E7 (FileBrowser access — no browse/download proof), F1 (health email — cited P3-DELIVERY is the enlarge-block trigger), F4 (metrics — cited legs are H1/H2 harness artifacts), F6 (operator alerting — no corpus doc), G6 (offsite fill/staleness/freeze — no live-fired leg, freeze inconclusive). Key corrections: D6 cited CAMPAIGN-3 F10/F11/F12 which are the CRITICAL failures — fixes shipped agent v0.85 and were re-validated live in CAMPAIGN-4 /6A; C6 cited offbox-restic doc for a PBS-restore claim -> CAMPAIGN-2 T-P9; C1/C5/B5 cited defect-discovery docs instead of the fix-validation legs. Closed ROADMAP R-20: operator-key pinning is fully automatic in day-0 (felhom-host-install.sh step_agent_config, L2044/2146-2156/2332-2337). Header draft caveat swapped for the verified stamp. Full per-row verdict table in REPORT.md.
14 KiB
felhom.eu — task reports
Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.
Capability-map audit — verify every status claim against evidence — 2026-07-16
Task: docs-only audit of documentation/architecture/00-capability-map.md. Open every citation,
confirm/correct/demote each of the 55 rows against the actual evidence doc (scenario-specific PASS,
not topic adjacency), prove the MISSING rows absent by code sweep, close ROADMAP R-20, and swap the
draft caveat in the map header. Zero code changes; read-only against three sibling repos.
1. Confirmed baselines (re-confirmed at task start)
| Repo | main @ commit |
Role |
|---|---|---|
| felhom.eu | 4b18cc5 (local == origin) |
audit target — WRITE |
| felhom-controller | e99c675 (v0.137.0) |
read-only reference |
| felhom-agent | c040c18 (v0.88.0) |
read-only reference |
| app-catalog-felhom.eu | 21e8df1 |
read-only reference |
The map's evidence corpus is read at felhom.eu tip 4b18cc5; the header caveat now records that.
2. Counts
55 rows audited = 23 confirmed (18 confirmed + 5 confirmed-absent) + 26 corrected + 6 demoted. No row was upgraded (candidate upgrades are Observations). Status distribution after the audit: 32 PROVEN-LIVE / 15 IMPLEMENTED / 3 PARTIAL / 5 MISSING (was 38 PROVEN-LIVE → 6 demoted).
3. Per-row verdict table
Each verdict names the doc opened and the leg/section carrying (or failing to carry) the scenario.
| Row | Scenario | Verdict | Evidence opened → leg / reason |
|---|---|---|---|
| A1 | Appliance day-0 zero-click auto-confirm | CONFIRMED | DRILL-day0-take2 §2/§3 (auto-confirm 6m39s, zero clicks; floor self-update 0.120→0.122; claim gate closed) + DRILL-day0-vm §5.6 |
| A2 | BYO install (PARTIAL) | CONFIRMED | DRILL-GL6 Phase 2 byo happy-path PASS; coexistence guards (GL6-F3/F6) only fixed v1.12.0, never live-revalidated — PARTIAL right |
| A3 | Customer claim | CORRECTED | DRILL-day0-vm §10/F-4 carries it; dropped mis-cited CAMPAIGN-4 F-C (that is the escrow-claim 502, not the password claim) |
| A4 | Escrow ceremony | CORRECTED | agent v0.88 REPORT (claim 200→410, R absent). Qualifier fixed demo→drill VM; browser-wizard leg flagged not-yet-validated |
| A5 | DR tier by default (IMPLEMENTED) | CORRECTED | cited SPIKE-pbs-tier-provisioning = slice-0, shipped nothing → DRILL-day0-take2 §2 (WG both modes, PBS-DR descriptor auto-provisioned live). Upgrade candidate |
| A6 | Uninstall (PARTIAL) | CORRECTED | DRILL-GL6 Phase 1/5 (KEPT-vs-WIPED printed, data intact ×3); secret-purge fixed v1.12.0, mnt-*.mount residue open — PARTIAL right |
| B1 | Deploy app from catalog | CORRECTED | CAMPAIGN-2 T-DEPLOY-SET + RERUN-p1p3 PASS; dropped T-RES-MEMGUARD (guard never fired — ample RAM / auth-walled) |
| B2 | App lifecycle | CORRECTED | T-LIFECYCLE PASS + remove live in CAMPAIGN-3; T-REMOVE-REDEPLOY never cleanly passed (stale dryrun) — noted open edge |
| B3 | Protected infra un-stoppable | CORRECTED | cited CAMPAIGN-2 T-SEC-PROTECTED was a stale-dryrun FAIL → CAMPAIGN-nomercy + RERUN-p1p3 T-SEC-PROTECTED PASS |
| B4 | Catalog sync + validation choke | CONFIRMED | CAMPAIGN-2 T-SYNC-IDEMPOTENT PASS; choke-point is unit-red-proofed (v0.132) — status held |
| B5 | App crash → customer notified (IMPLEMENTED) | CORRECTED | citation CAMPAIGN-3 fix-3 arc (surfaced the gap) → controller v0.120.0 (impl+red-proof); "delivery proven" softened (6B deferred/6C inconclusive) |
| B6 | Post-deploy config + restart | DEMOTED PROVEN-LIVE→IMPLEMENTED | T-PAGE-ALL is a GET-only page-render smoke test; config-save+restart exercised in no campaign (CAMPAIGN-3 skipped it) |
| B7 | Backup classification (13 apps) | CONFIRMED | SPIKE-backup-classification SQ2 (13 bind apps) + 6D/6E live legs |
| C1 | Nightly DB dumps, atomic writes | CORRECTED | cited CAMPAIGN-3 F7 is the finding of non-atomic writes + T-RST-DB auth-hollow → CAMPAIGN-6B P4 + 6E B1/B2 (SIGKILL→last-good byte-unchanged) + 6D P-FAB |
| C2 | Tier-2 copy | CONFIRMED | CAMPAIGN-6E P-TIER2 deep-4 4/4 PASS + 6C |
| C3 | Offsite restic | CORRECTED | enlargement gate live (6D P3-DELIVERY); noted raw-data-quota/retention are SPIKE-restic-snapshot-shape dry-run only |
| C4 | Offsite restore | CONFIRMED | CAMPAIGN-6D P-IMMICH/P-PLACE (functional from offsite alone, byte-identical) |
| C5 | Manual .fab |
CORRECTED | 6D P-FAB (1.7GB circle) + 6B P2 (chunking at real CF edge via curl --resolve); rendered-browser upload leg still deferred; C6B-F1 was the 6B finding |
| C6 | Guest-loss PBS DR | CORRECTED | cited VALIDATION-newbox-restore = offbox restic (wrong tier) → CAMPAIGN-2 T-P9-DESTROY-RESTORE (whole-guest pct restore→healthy) + T-PBS-VERIFY (13 snapshots) |
| C7 | PBS-DR self-heal (IMPLEMENTED) | CORRECTED | cited spike = findings-only → hub v0.56.0 reconciler + §10 red-proofs. Facts fixed: scoped to one host (not fleet-wide); already fired live on drill qm300 |
| C8 | Crash mid-backup/migration self-heal | CORRECTED | cited CAMPAIGN-2 T-RBT-* legs empty/auth-hollow → 6D P5-REST + 6E B1-B3; mid-migration crash still weakest sub-claim |
| C9 | Soft-quota block + notify | CONFIRMED | 6D P3-DELIVERY (block + op+customer email live); usage-bar UI only weakly corroborated |
| C10 | Customer performs a restore (MISSING) | CONFIRMED-ABSENT | sweep: only self-reference at map L34 "never executed by a non-Viktor human"; all restores operator-driven |
| D1 | Drive wizard incl. legacy LVM-root | CORRECTED | DISPOSITION-ia (legacy EFI+LVM, root not offered) + storage-lifecycle-acceptance (enroll live) + agent fence self-test; cited CAMPAIGN-2 legs were auth-hollow; UI-wizard leg supervised |
| D2 | Data migration (all/per-app) | CORRECTED | 6C 4P-5 (per-app) + storage-lifecycle-acceptance (2× migrate-all via UI, byte-identical); cited CAMPAIGN-2 legs auth-hollow; crash-safe design-level only |
| D3 | NAS client verify-before-commit | CONFIRMED | SPIKE-nas-verify Q2/Q4 + SPIKE-nas-dsm (real DSM 7.2 end-to-end) + CAMPAIGN-3 |
| D4 | USB enroll/unplug/recommission | CORRECTED | storage-lifecycle-acceptance E4 (yank→auto-rebind) + E10 (re-enroll) + 4/6A (3-USB reshuffle); cited RUNBOOK could not complete enroll |
| D5 | Decommission / eject | CORRECTED | storage-lifecycle-acceptance E9 (decommission-anyway, reboot-safe) + E12; cited CAMPAIGN-2 legs auth-hollow, SPIKE was report-only |
| D6 | Boot ordering survives reboot | CORRECTED | cited CAMPAIGN-3 F10/F11/F12 are the CRITICAL/HIGH failures → fixes shipped agent v0.85 + re-validated live CAMPAIGN-4 (0 ordering cycles) + 6A 1D |
| E1 | Remote CF Tunnel | CONFIRMED | CAMPAIGN-2 T-FLT-CF PASS (not in the H1-hollow set; recovered 20s) |
| E2 | LAN access when net down (IMPLEMENTED) | CONFIRMED | empty citation consistent with IMPLEMENTED; never drilled as customer experience → R-19 |
| E3 | Phone photo backup | CONFIRMED | 6D Accept #1 + SQ3 (immich functional from offsite, byte-identical) |
| E4 | Documents/OCR | CORRECTED | tightened vague "6C/6E legs" → 6C 4P-1 (paperless consume+OCR PASS) |
| E5 | SMB server (MISSING) | CONFIRMED-ABSENT | sweep smbd|samba|wsdd|net usershare|smb.conf: 10 hits, all client/offsite/docs — no server. Hetzner SambaEnabled = a box we write to, not a share we expose |
| E6 | DLNA to TV (MISSING) | CONFIRMED-ABSENT | sweep minidlna|dlna|ssdp|upnp: 3 hits, all ROADMAP/map docs; zero implementation |
| E7 | File access via browser | DEMOTED PROVEN-LIVE→IMPLEMENTED | T-PAGE-ALL renders only controller dashboard pages, not FileBrowser; no browse/download proof anywhere |
| E8 | Forgot-password reset code | CORRECTED | tightened "F-15 arc" → DRILL-day0-take2 F-15 (live re-run, hash applied 1s, code accepted first try) |
| E9 | Multi-user accounts (MISSING) | CONFIRMED-ABSENT | sweep of controller auth.go: single effectivePasswordHash(), no user table / role / permission model |
| E10 | WireGuard OOB (IMPLEMENTED) | CONFIRMED | SPIKE-oob-wg-operator-peer GO + SPIKE-felhom-sshd; unproven on true 100.64/10 — IMPLEMENTED right |
| E11 | Break-glass recovery (IMPLEMENTED) | CONFIRMED | runbooks/break-glass.md; live incident reproduced in SPIKE-felhom-sshd; no end-to-end recovery drill — IMPLEMENTED right |
| F1 | Health-degradation email | DEMOTED PROVEN-LIVE→IMPLEMENTED | cited 6D P3-DELIVERY is the enlarge-block trigger, not health-degradation; NotifyHealthChange never fired an email live in any doc |
| F2 | Event catalog | CORRECTED | vague "per-arc" → 3 live-delivered families: enlarge-block (6D), claim code (DRILL-day0-vm F-4), reset code (take2 F-15); app_start_failed/dead-app unit-only |
| F3 | Empty-email wipe guard (IMPLEMENTED) | CONFIRMED | controller v0.137.0, red-proofed 07-15 |
| F4 | System/container metrics | DEMOTED PROVEN-LIVE→IMPLEMENTED | cited T-RES-CPU/T-SOAK-LOOP are H1/H2 harness artifacts (auth-302); SQLite/Chart.js/30-day downsampling validated nowhere |
| F5 | Debug rings + log-bundle pulls | CORRECTED | rings live-exercised CAMPAIGN-3 fix-6; noted log-bundle-pull TTL/custody half is changelog-only |
| F6 | Operator alerting (Healthchecks) | DEMOTED PROVEN-LIVE→IMPLEMENTED | no corpus doc; healthchecks-config app not deployed; per enum "no citation → not PROVEN-LIVE". Re-upgrade candidate if operator cites a live alert |
| G1 | Customer/host management UI | CORRECTED | cited "daily operator use" no-doc + AUDIT-hub-gui predates features (v0.25) → hub v0.53 (Peti-cluster live) + CAMPAIGN-4 + take2 F-16; 8-tab render = render-test-validated (UI password-gated) |
| G2 | Publish train (PARTIAL) | CONFIRMED | runbooks/publish-train-rules.md (floor-LAST, MinAgent gate); never proven on a real remote customer — PARTIAL right |
| G3 | Agent self-update | CORRECTED | cited SPIKE-agent-selfupdate is dummy-only, no operator-signed leg → DRILL-GL6 Phase 3 (armed-key round-trip with the REAL key) |
| G4 | Controller self-update | CORRECTED | cited "07-10 arc" CHANGELOG → DRILL-day0-take2 §2 (credential-empty box self-updated 0.120→0.122 live) |
| G5 | Offsite provisioning | CONFIRMED | VALIDATION-offsite-provisioning-e2e PASS (real box 611714, end-to-end) + SPIKE-hetzner-api + re-issue in CAMPAIGN-offsite-overnight |
| G6 | Per-customer offsite fill/staleness/freeze | DEMOTED PROVEN-LIVE→IMPLEMENTED | OffsiteChecker in code but no live-fired leg; CAMPAIGN-offsite-overnight = no fill/staleness emails, freeze write-block inconclusive |
| G7 | Box-level Storage Box aggregate (MISSING) | CONFIRMED-ABSENT | hub sweep storagebox|aggregate|oversubscription|sum.*quota: only per-customer OffsiteChecker + app-telemetry; no box-level roll-up |
| G8 | Secrets hygiene (IMPLEMENTED) | CONFIRMED | hub v0.53.0 closing bundle (bearer → k8s Secret) |
| G9 | Operator login password from UI (IMPLEMENTED) | CONFIRMED | hub v0.54.0 (handleChangePassword, effectivePasswordHash()) |
4. R-20 verdict — CLOSED
Read from current scripts/felhom-host-install.sh source (not the changelog). Operator-key pinning
is fully automatic in the day-0 flow, no manual step: keys resolve at L1181–1219 (script
constants OPERATOR_KEY_OPERATIONAL_*/_RECOVERY_*, already populated, optional
--operator-pubkey-file override); pinned by step_agent_config() — "STEP 6/8 agent config +
service" (L2044; embedded python builds authz.signers L2146–2156, and a re-install with no keys
preserves an existing box's signers); verified at the step-8 check L2332–2337 ("authz signers: N
(operator-signed self-update armed)"). No interactive prompt or post-install hand-edit gates it →
ROADMAP R-20 set to closed. One loose end (doc-drift, not a reopen): the L193–197 comment still
says the constants are "EMPTY by default" though L198–201 are populated — folded into R-16 hygiene.
5. Commits pushed to main
- (recorded on push) —
docs(map): capability-map evidence audit(00-capability-map.md header + 26 corrected / 6 demoted rows; ROADMAP R-20 closed; this REPORT).
6. Observations (out of scope — NOT acted on)
- Candidate upgrades (audit cannot upgrade): A5 DR-tier-by-default is shown working live and
hands-free in
DRILL-day0-take2§2 — arguably PROVEN-LIVE(drill), left IMPLEMENTED per the no-upgrade rule. C7 self-heal has code + red-proofs + a hands-free live convergence on qm300 — stronger than a bare IMPLEMENTED, but scoped-to-one-host with no real-customer firing. - F6 demotion is a judgment call: operator Healthchecks→Resend alerting may genuinely run in production; it simply has no corpus doc, and the strict enum forbids PROVEN-LIVE without a citation. Re-upgrade the moment a live alert is cited.
- Recurring "cite-the-finding" inversion: several rows cited the doc where a defect was discovered as if it were the proof — D6 (F10/F11/F12 failures), C1 (F7 non-atomic finding), C6 (VALIDATION-newbox = wrong tier), C5/B5 (6B/CAMPAIGN-3 findings). The fixes live in later legs. Worth a standing authoring rule: cite the fix-validation leg, never the finding ID.
storage-lifecycle-acceptance-2026-06-15is an uncited, high-value corpus doc — it live-proves D2/D4/D5 (and local-drive boot survival). Now cited; consider it first for storage rows.- CAMPAIGN-2 is fragile as a citation source for restore/reboot/storage rows: harness bug H1
(auth-session expiry → CSRF-403) hollowed every
T-RST-*,T-STG-*,T-RBT-*; several cited evidence dirs are literally empty or a 302. Re-anchor such rows on 6D P5-REST / 6E Phase B / storage-lifecycle-acceptance, which actually exercised these live. - MEMORY.md drift: the note that
CAMPAIGN-6D"DEFERRED P3-BROWSER/P3-DELIVERY" is stale — the committed 6D marks both PASS.