Files
felhom.eu/REPORT.md
T
admin d202b43b95 docs(map): capability-map evidence audit — verify every status claim against source
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.
2026-07-16 09:19:51 +02:00

14 KiB
Raw Blame History

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 L11811219 (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 L21462156, and a re-install with no keys preserves an existing box's signers); verified at the step-8 check L23322337 ("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 L193197 comment still says the constants are "EMPTY by default" though L198201 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-15 is 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.