Files
felhom.eu/documentation/architecture/00-capability-map.md
T
2026-07-16 08:10:33 +02:00

116 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 00 — Felhom Capability Map
> **What this is:** the single cross-component truth table of what the Felhom platform can do
> **today**, at what confidence level, with verifiable evidence. Rows are *scenarios* (user- or
> operator-visible outcomes), not modules — a scenario spans agent + controller + hub + catalog,
> and this is the only doc that shows that view.
>
> **What this is NOT:** a roadmap. Planned work lives in `documentation/backlog/ROADMAP.md` and is
> referenced from gap rows by ID (`→ R-n`). A row here never claims future behavior.
>
> **Status enum (strict):**
> | Status | Meaning |
> |--------|---------|
> | **PROVEN-LIVE** | Exercised end-to-end on real infrastructure; MUST cite a campaign/drill/validation doc in `documentation/audits/` or `documentation/tests/`. No citation → not PROVEN-LIVE. |
> | **IMPLEMENTED** | Shipped + unit/red-proof tested, but the real flow has not been exercised live (or not on the surface that matters — noted per row). |
> | **PARTIAL** | Some legs live, some missing/unvalidated — the note says which. |
> | **MISSING** | Does not exist. Present-tense fact; if planned, the row points at a roadmap ID. |
>
> **Update rule (end-of-session checklist item):** if a task changed any capability's status,
> update the row in the same session — with the new evidence citation. A PROVEN-LIVE claim is
> subject to the cardinal rule like any other claim.
>
> *Drafted 2026-07-16 by project-Claude from live CHANGELOGs (controller v0.137.0, agent v0.88.0,
> hub v0.56.0) + audit index. Verify statuses once against source before first commit.*
---
## A. Provisioning & day-0
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Appliance day-0 install: golden image → first boot → auto-confirm (zero clicks) → claimable box | installer, agent, hub, golden | **PROVEN-LIVE** (nested VM) | `DRILL-day0-vm-2026-07-12`, `DRILL-day0-take2-2026-07-12` | First firing on real customer hardware pending → R-1 |
| BYO install: `--mode byo`, mandatory caps, host-mutation disclosure, coexistence guards | installer v1.15+, agent | **PARTIAL** | `DRILL-GL6-2026-07-08` (demo box); GL-8 coexistence fixes | Peti clean-slate reinstall on proxmox2 is the first real BYO run of the current path → R-1 |
| Customer claim: one-time emailed code → customer sets own password (bcrypt, operator never sees it) | controller v0.122, hub v0.50 | **PROVEN-LIVE** (drill VM) | `DRILL-day0-vm-2026-07-12` (F-4 arc), `CAMPAIGN-4-2026-07-13` (F-C) | Never executed by a non-Viktor human → R-3 |
| Escrow ceremony: customer-facing wizard, one-shot R claim, operator zero-knowledge | controller v0.127, agent v0.88 | **PROVEN-LIVE** (demo, endpoint-exact) | agent v0.88.0 REPORT (ceremony ~4s, one-shot claim + 410); `SPIKE-controller-escrow-2026-07-13` | First supervised ceremony with a real customer pending → R-1 |
| DR tier by default: PBS + WireGuard base infra on every install, hub-controlled activation | installer v1.15, agent v0.86, hub v0.51 | **IMPLEMENTED** | `SPIKE-pbs-tier-provisioning-2026-07-10` | Live only on demo/drill fleet |
| Uninstall: KEPT-vs-WIPED statement, secret purge, enrolled-drive handling | installer | **PARTIAL** | GL-4 (uninstaller gaps closed) | Cluster-aware `felhom_guests` guard + saferemove cost warning missing → R-9 |
## B. Apps & catalog
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Deploy an app from the catalog (env config, memory guard, health-aware progress) | controller, catalog (~52 apps, images pinned) | **PROVEN-LIVE** | `CAMPAIGN-2` T-DEPLOY-SET (7 apps), T-RES-MEMGUARD | |
| App lifecycle: start/stop/restart/update/logs/remove/redeploy | controller | **PROVEN-LIVE** | `CAMPAIGN-2` T-LIFECYCLE, T-REMOVE-REDEPLOY | |
| Protected infra stacks can't be stopped/removed from UI | controller | **PROVEN-LIVE** | `CAMPAIGN-2` T-SEC-PROTECTED | |
| Catalog sync (git, 15 min) + orphan lifecycle + validation choke point (bad `backup:` block degrades to legacy, loudly) | controller v0.132, catalog | **PROVEN-LIVE** | `CAMPAIGN-2` T-SYNC-IDEMPOTENT; v0.132 LoadMetadata red-proofs | |
| App crashes → customer notified (one event per transition, no flapping spam) | controller v0.120, hub v0.48 | **IMPLEMENTED** | CAMPAIGN-3 fix-3 arc | Delivery proven; long-run anti-spam behavior only unit-proven |
| Post-deploy optional config (API keys etc.) with restart | controller, catalog `.felhom.yml` | **PROVEN-LIVE** | long-standing; page sweep in `CAMPAIGN-2` T-PAGE-ALL | |
| Backup classification: 13 bind-bearing apps carry mandatory/optional/excluded classes | catalog, controller v0.132133 | **PROVEN-LIVE** | `SPIKE-backup-classification-2026-07-14`, `CAMPAIGN-6D/6E` | Remaining ~39 apps are legacy-class by design (unit-only offsite) |
## C. Protection & recovery (the product promise)
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Nightly DB dumps (postgres/mariadb autodiscovery), atomic writes | controller v0.118 | **PROVEN-LIVE** | `CAMPAIGN-2` T-BAK-FULL, T-RST-DB; CAMPAIGN-3 F7 fix | T-6E-1 dir-fsync asymmetry (LOW) → R-10 |
| Tier-2 secondary-drive copy: class-driven legs, v2 relpath layout, NAS-target exclusion, safe-remove boundary | controller v0.135 | **PROVEN-LIVE** | `CAMPAIGN-6E-2026-07-15` (P-TIER2 deep-4 PASS), `CAMPAIGN-6C` | |
| Offsite (restic → Hetzner Storage Box): mandatory class only, raw-data quota, enlargement gate, retention regrouping | controller v0.134, agent, hub | **PROVEN-LIVE** | `CAMPAIGN-6D-2026-07-15`, `SPIKE-restic-snapshot-shape-2026-07-14`, `VALIDATION-offbox-storagebox-2026-07-09` | |
| Offsite restore: local-preferred scratch, unit-only default, full two-step, missing-only place-to-live | controller v0.134/134.1/135 | **PROVEN-LIVE** | `CAMPAIGN-6D` accept legs (immich end-to-end from offsite alone) | |
| Manual `.fab` export/import: class-scoped capture, browser up/download, tunnel-proof chunking | controller v0.125/128/130/136 | **PROVEN-LIVE** | `CAMPAIGN-6D` Accept #1 (≥1 GiB full circle); `CAMPAIGN-6B` (C6B-F1 hollow-export fix) | |
| Guest-loss DR: PBS restore with full-fidelity layout from archive, restore-test verification | agent v0.75/0.76, PBS | **PROVEN-LIVE** | `VALIDATION-newbox-restore-2026-07-10`, `DRILL-GL6-2026-07-08` | |
| PBS-DR secret self-heal on reused-peer re-provision | hub v0.56 | **IMPLEMENTED** | `SPIKE-pbsdr-selfheal-2026-07-15` (root cause proven) | Reconciler fleet-wide since 07-15; first real-world firing pending |
| Crash/power-loss mid-backup/mid-migration → self-heal on next run | controller, agent | **PROVEN-LIVE** | `CAMPAIGN-2` T-FLT-KILL9, T-RBT-MIDBACKUP, T-RBT-MIDMIGRATION | |
| Soft-quota: usage bar, pre-push enlargement block, customer notification | controller v0.109/134, hub v0.41/55 | **PROVEN-LIVE** | 6D/6E; hub OffsiteChecker | |
| **A customer (not the operator) performs a restore via UI alone** | all | **MISSING** (as evidence) | — | Alpha will produce this; script it into R-3 |
## D. Storage & devices
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Drive wizard: scan/format/mount/enroll, incl. legacy-boot LVM-root hosts | controller, agent v0.87 | **PROVEN-LIVE** | `CAMPAIGN-2` T-STG-ENROLL/SEC-FORMAT; `DISPOSITION-ia-finding2-systemdisks-2026-07-13` | |
| Data migration between drives (all / per-app), crash-safe | controller | **PROVEN-LIVE** | `CAMPAIGN-2` T-STG-MIGRATE-*, `CAMPAIGN-6C` (scope=app round-trip) | |
| NAS (NFS/SMB-client) verify-before-commit, uid-1000 probe, categorized Hungarian errors, DSM-validated | controller v0.113117, agent v0.81/84/85 | **PROVEN-LIVE** | `SPIKE-nas-verify-2026-07-11`, `SPIKE-nas-dsm-2026-07-11`, `CAMPAIGN-3-2026-07-11` (boot/reassert fixes) | |
| USB drive enrollment + unplug detection + recommission | controller, agent | **PROVEN-LIVE** | `RUNBOOK-usb-enrollment-3bfix-2026-07-01`, `CAMPAIGN-2` T-STG-UNPLUG/RECOMMISSION | |
| Decommission (migrate-first and anyway-paths), eject | agent, controller | **PROVEN-LIVE** | `CAMPAIGN-2` T-STG-DECOM-*; `SPIKE-decommission-migration-2026-06-14` | |
| Boot ordering: automount + networking survive reboot; appliance self-heal watchdog | agent v0.85 | **PROVEN-LIVE** | `CAMPAIGN-3-2026-07-11` (F10/F11/F12) | |
## E. Access, networking & household use
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Remote access via Cloudflare Tunnel + Traefik (per-app subdomains) | cloudflared, traefik | **PROVEN-LIVE** | `CAMPAIGN-2` T-FLT-CF | Per-customer zone-scoped CF tokens (blast-radius ruling) |
| LAN access when internet is down (lan_resolver) | agent | **IMPLEMENTED** | — | Never drilled as a customer experience ("net down — can I reach my photos?") → R-19 |
| Phone photo backup | immich (classified) | **PROVEN-LIVE** | 6D end-to-end restore proof | |
| Documents/OCR | paperless-ngx (classified) | **PROVEN-LIVE** | first deployed app; 6C/6E legs | Consume-folder ingestion awkward without SMB → R-7 |
| Files from Windows Explorer / Mac Finder (SMB **server**) | — | **MISSING** | — | → R-6 (spike), R-7 (feature) |
| Media to TV via DLNA | — | **MISSING** | — | Jellyfin app exists; DLNA/SSDP unvalidated → R-6, R-8 |
| File access via browser | FileBrowser (infra app, auto-mount sync) | **PROVEN-LIVE** | long-standing; `CAMPAIGN-2` T-PAGE-ALL | |
| Forgot dashboard password → instant reset code | controller v0.123, hub | **PROVEN-LIVE** | F-15 arc, drill validation | |
| Multiple household users / per-person accounts | — | **MISSING** | — | Single dashboard password; acceptable for alpha → R-15 |
| WireGuard base infra always-on; OOB operator access (felhom-sshd, /32 peer) | agent v0.72, hub v0.35 | **IMPLEMENTED** | `SPIKE-oob-wg-operator-peer-2026-07-05`, `SPIKE-felhom-sshd-2026-07-05` | Mutual-repair desired-state arc not built → R-13 |
| Break-glass management-plane recovery | agent v0.71, hub v0.34 | **IMPLEMENTED** | `runbooks/break-glass.md` | |
## F. Notifications & monitoring
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Health-degradation email (edge-triggered, cooldowns, Hungarian) via hub → Resend | controller, hub | **PROVEN-LIVE** | 6D P3-DELIVERY | Deliverability to HU freemail providers untested → R-4 |
| Event catalog: app_start_failed, dead-app, offbox_enlarge_blocked, claim/reset codes, critical severity | controller, hub v0.31/48/50/55 | **PROVEN-LIVE** | per-arc validations | |
| Prefs safety: empty-email wipe guard | controller v0.137 | **IMPLEMENTED** | red-proofed 07-15 | Born from a live incident; guard itself unit-proven |
| System + container metrics (SQLite, Chart.js, 30-day downsampling) | controller | **PROVEN-LIVE** | `CAMPAIGN-2` T-RES-CPU/T-SOAK-LOOP | |
| Always-on debug rings + on-demand log-bundle pulls with TTL/custody | controller v0.116, agent v0.83, hub v0.46 | **PROVEN-LIVE** | observability arc 07-11 | |
| Operator alerting (Healthchecks → monitoring@felhom.eu) | k3s, Resend | **PROVEN-LIVE** | in production since 02-04 | |
## G. Fleet & operator (hub)
| Scenario | Components | Status | Evidence | Gap / roadmap |
|---|---|---|---|---|
| Customer/host management: 8-tab detail, scoped auto-refresh, safe stale-host deletion, capability chips | hub v0.470.53 | **PROVEN-LIVE** | in daily operator use | |
| Publish train: MinAgent floors, gated auto-Reissue, version channels, floor-field-LAST rules | hub v0.45/0.53, agent | **PARTIAL** | `runbooks/publish-train-rules.md`; demo-fleet updates proven | **Never proven on a real remote customer** — parked trains `RUNBOOK-publish-0.79/0.81/0.85-*` await Peti → R-1 |
| Agent self-update: A/B slots, crash-loop auto-rollback, operator-signed | agent v0.70+ | **PROVEN-LIVE** (demo) | `SPIKE-agent-selfupdate-2026-07-05` | Remote-customer proof pending → R-1 |
| Controller self-update: anonymous registry, no credentials in guest | controller v0.112 | **PROVEN-LIVE** (demo) | 07-10 arc | |
| Offsite provisioning: Hetzner API, sub-account per customer, host-key pinning, credential re-issue | hub v0.370.39 | **PROVEN-LIVE** | `VALIDATION-offsite-provisioning-e2e-2026-07-09`, `SPIKE-hetzner-api-provisioning-2026-07-09` | |
| Per-customer offsite fill + staleness + freeze lever | hub v0.41 | **PROVEN-LIVE** | OffsiteChecker in production | |
| **Box-level Storage Box aggregate (total fill, Σ quotas, oversubscription alert)** | — | **MISSING** | — | → R-5 |
| Secrets hygiene: bearer in k8s Secret, no secrets in git, single-quote credential store | hub v0.53, conventions | **IMPLEMENTED** | 07-13 closing bundle | |
| Operator login password changeable from UI | hub v0.54 | **IMPLEMENTED** | 07-13 | |