docs: offsite continuity Part B REPORT/CONTEXT; DIAGNOSE incident→fix pointer; capability map (offsite reinstall-continuity + escrow retention); ROADMAP R-25 (TOCTOU hardening) + R-26 (guided old-history recovery)
This commit is contained in:
@@ -2,43 +2,39 @@
|
||||
|
||||
> **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](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md).
|
||||
|
||||
## N100 polish — F5 guest auto-sizing (host-install v1.17.0) + docs — 2026-07-17
|
||||
## Offsite continuity Part B — superseded-escrow retention (hub v0.60.0) — 2026-07-17
|
||||
|
||||
Closes `documentation/tests/VALIDATION-n100-baremetal-2026-07-16.md` **F5 (MEDIUM)**. Companion to the
|
||||
controller v0.141.0 F6/F7 fixes (see the felhom-controller REPORT). `bash -n` + the mode harness pass.
|
||||
**Baseline:** hub v0.59.0 → **v0.60.0** (LIVE on prod, ArgoCD Synced/Healthy). Closes the data-loss
|
||||
half of the reinstall-orphaned-repo incident
|
||||
(`documentation/audits/DIAGNOSE-offbox-repo-orphaned-2026-07-17.md`): the destructive
|
||||
`SaveHostEscrow` `ON CONFLICT` overwrite meant a new escrow blob DESTROYED the old passphrase's only
|
||||
copy (18 snapshots unrecoverable). Viktor's ruling — data protection first — is now enforced. Pairs
|
||||
with controller v0.142.0 (Part A). Green: `go build ./... && go vet ./... && go test ./...`.
|
||||
|
||||
### F5 — appliance guest auto-sizing (`scripts/felhom-host-install.sh` v1.17.0)
|
||||
The golden default (2 GB RAM) reached the guest on a 16 GB host because appliance mode passed no
|
||||
`--memory`/`--cores`. Now, in **appliance** mode with no explicit cap, the guest is auto-sized from
|
||||
the host: `autosize_guest_caps` runs right after mode validation (before the plan summary + provision)
|
||||
and fills `MEM_MIB`/`CPU_CORES`:
|
||||
- RAM = `clamp(host-4096, min 4096, max host-2048)` then a hard ceiling `host-1024` (never
|
||||
over-commit). Sizing: 8 GB→4096, 16 GB→12288, 32 GB→28672 MiB; a 4 GB host→3072 (min capped at the
|
||||
ceiling — the edge rule).
|
||||
- cores = `host-1, min 2`.
|
||||
- An explicit `--memory`/`--cores` ALWAYS wins untouched; byo mode still requires explicit caps (never
|
||||
auto-sized). The values flow into the existing `cap_args` → the agent's `-memory`/`-cores`.
|
||||
- Host reads (`MemTotal`/`nproc`) are overridable via `FELHOM_FAKE_MEMTOTAL_MIB`/`FELHOM_FAKE_NPROC`.
|
||||
- **Red-proof:** `hostinstall-mode-harness.sh` new F5 section (8/16/32 GB + small-host edge +
|
||||
explicit-flag precedence) — the auto-size log line is emitted before any PVE contact, so it asserts
|
||||
portably; pre-fix (auto-size disabled) FAILs, post-fix PASSes.
|
||||
### Schema decision: history table (not a flag)
|
||||
`host_escrow_superseded` — an append-only, one-row-per-superseded-blob table. A flag couldn't hold N
|
||||
retained blobs, and Viktor's ruling is to keep ALL (no pruning); a history table is the only shape
|
||||
that does. `SaveHostEscrow` now, in one tx: reads the current row; if it seals a DIFFERENT
|
||||
`restic_pw_sha256`, COPIES it into the history table BEFORE the current row is overwritten; then upserts
|
||||
the new row. Same-sha re-upload (idempotent re-ceremony) → refresh only, no supersede row. Returns
|
||||
`superseded bool`.
|
||||
|
||||
**Same commit (R-16 doc-drift leftover, R-20 closure note):** the operator-signing-keys "EMPTY by
|
||||
default" comment was stale (the keys are PINNED to the real `felhom-op-1`/`felhom-rec-1` ceremony
|
||||
keypairs) — corrected, comment-only, no behavior.
|
||||
### What ships (retention only — the guided-recovery flow is R-26, NOT built)
|
||||
- `SaveHostEscrow` rewrite + `CountSupersededEscrow` / `ListSupersededEscrow` (the latter seeds R-26).
|
||||
The hub still never decrypts; the ACK + restore-serving read the CURRENT row (`GetHostEscrow`) —
|
||||
**unchanged**. `DeleteHost(deleteEscrow=true)` also drops the retained rows.
|
||||
- Upload handler: `escrow_superseded` hub-internal audit event (tied to the owning customer) + a log
|
||||
line with the retained count. Operator host-detail DR/Backup panel shows "N superseded escrow
|
||||
blob(s) retained". Registered the controller-pushed `offbox_repo_orphaned` / `offbox_repo_reset` in
|
||||
`allowedEventTypes` + `customerMessages`.
|
||||
- **Red-proof** `TestSaveHostEscrow_RetainsSuperseded` (pre-fix destructive overwrite → old blob gone →
|
||||
FAIL; fixed → retained + retrievable via `ListSupersededEscrow`; same-sha idempotent = no supersede).
|
||||
|
||||
### NOT live this task
|
||||
F5 is validated by harness only — live at the next from-scratch rehearsal (Viktor's planned
|
||||
delete/re-create run); stated in the ROADMAP and the VALIDATION disposition.
|
||||
### Deploy
|
||||
Built `felhom-hub:0.60.0`, bumped `manifests/hub.yaml`, ArgoCD Synced/Healthy, rollout complete
|
||||
(`:0.60.0`). The `CREATE TABLE IF NOT EXISTS host_escrow_superseded` migration runs at startup
|
||||
(idempotent). ACK semantics unaffected (current-row reads only).
|
||||
|
||||
### Docs updated
|
||||
VALIDATION-n100 F5/F6/F7 dispositions → FIXED-in-vX (erratum style); capability map drive-wizard row →
|
||||
F6 fresh-USB wizard enroll+format **PROVEN-LIVE**; ROADMAP R-16 (doc-drift bit closed), R-22 & R-13
|
||||
already PROVEN-LIVE, new **R-24** (guest resources as hub desired-state / live resize — the F5
|
||||
follow-on); operator-sidebar item #1 (BIOS "State After G3 → Power On") added to `scripts/iso/README.md`.
|
||||
|
||||
### Operator sidebar (Viktor — CC does NOT do these; recorded verbatim)
|
||||
1. **BIOS "State After G3" → "Power On"/"Last State"** before final sign-off — added to
|
||||
`scripts/iso/README.md` hardware-prep notes.
|
||||
2. **campaign6 autofs orphan** — clears at the next host reboot.
|
||||
3. **tied-CreatedAt flash duplicates** (audiobookshelf/komga/romm) — standing action item.
|
||||
### NOT done (registered as R-26)
|
||||
The guided "recover old history with the old recovery code" flow — Part B ships retention + visibility
|
||||
only; R-26 registers the recovery flow that consumes the retained blobs.
|
||||
|
||||
Reference in New Issue
Block a user