GL-4: uninstaller gap-closure + operator-key day-0 fold (host-install v1.11.0)

Uninstall: NEW 4b4 removes the self-update artifacts (guarded wrapper,
.prev/.new.* A/B slots, rollback unit, limits drop-in — derived from
configs/felhom-selfupdate-guarded); enrolled drives under /mnt/felhom-drives
unmounted plain-umount-only (busy = warn+guidance, never -l/-f; root bind
guarded); both modes end with a KEPT-vs-WIPED statement (drives/PBS/hub
record/escrow/vaulted recovery credential live on); guest-only mode prints
the vmid's bind-store drives.

Key-pin: OPERATOR_KEY_* constants (empty until the operator ceremony) +
--operator-pubkey-file (argv-validated; comment=key_id required; file
overrides constants) -> authz.signers per the agent SignerKey schema;
no-keys-resolved KEEPS preserved signers; verify reports armed/dormant WARN.

Harness: +13 static cases + GL4-D parity + GL4-INV + PVE-tier GL4 H-U
(full-uninstall dry transcript vs live 9201). 28/28 on felhom-pve;
red-proofs RP-1..3 run->fail->revert. GO-LIVE-PACKAGE.md ABSENT AGAIN ->
status in CONTEXT.md. Live teardown/armed-pin = GL-6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-08 08:14:07 +02:00
parent a63cc7151b
commit f7cc6a720e
7 changed files with 484 additions and 52 deletions
+39
View File
@@ -1,5 +1,44 @@
# Felhom scripts — Changelog
## felhom-host-install v1.11.0 — uninstaller gap-closure + operator-key day-0 fold (TASK GL-4, go-live G6 + G1-follow-up) (2026-07-08)
- **Uninstall gap-closure (G6):**
- NEW 4b4 block removes the self-update artifacts the install lays down but v1.10.0 never
removed: `/usr/local/sbin/felhom-selfupdate-guarded`, the A/B slot files next to the live
binary (`felhom-agent.prev` + orphaned `.new.*` temps), `felhom-agent-rollback.service`, and
the `felhom-agent.service.d/felhom-agent-limits.conf` drop-in (+dir). Paths derived from the
authoritative `felhom-agent/configs/felhom-selfupdate-guarded`; `pending.json` was already
covered by the state-dir removal. Tolerate-absent, 4b2 shape.
- Enrolled/network drives mounted under `/mnt/felhom-drives/<name>` are now unmounted (deepest
first) before the root self-bind — **plain `umount` ONLY, never `-l`/`-f`**: a busy mount gets
a warning + "eject via the dashboard or stop the apps and retry" and the root bind is then left
alone (previously a child mount made the root umount die mid-teardown). The data is NEVER
touched — no wipe/format path exists anywhere near `/mnt/felhom-drives`.
- Both modes now END with an explicit **KEPT-vs-WIPED statement**: WIPED mirrors what the mode
actually ran; KEPT names the drives + their data (physically removable; busy ones listed as
retry), PBS backups + customer namespace (conditional on a pbs storage), the hub host/customer
record, the escrow blob, and — when step 4b had vaulted one — the root@pam recovery credential.
- Guest-only mode prints the drives the agent's bind store records for that vmid (best-effort
from `/var/lib/felhom-agent/guest-binds.json`, generic note otherwise) + "eject BEFORE
uninstall" guidance; no umounts there (remaining guests may use the drives).
- **Operator-key day-0 fold (the GL-1/G1 key-pin follow-up):** `OPERATOR_KEY_{OPERATIONAL,RECOVERY}_{ID,LINE}`
constants (EMPTY until the operator's offline pin ceremony) + `--operator-pubkey-file PATH`
(lines `operational|recovery <authorized_keys line>`; the comment field IS the key_id, required;
malformed/empty file dies at argv time naming the line; file OVERRIDES the constants with a
notice). Resolved keys are written to `authz.signers` in the agent config (exact
`config.go` SignerKey schema; `nonce_store_path` left to the agent default). **Preserve rule:**
script/file keys are authoritative ONLY when non-empty — a reinstall with no keys KEEPS a
preserved config's signers (never silently clobber a manually-pinned box; replacing preserved
signers logs a pin-rotation notice). byo disclosure names the operational key_id (or "NONE —
dormant"); verify reports `authz signers: N` (armed) or a dormant WARN (dormant = safe default).
- Harness: +13 static cases (GL4-C1..C5 incl. 5 live key-file refusals + grep shapes, GL4-D
disclosure↔uninstall parity, GL4-INV no-forced-unmount/no-format invariant) + PVE-tier **GL4 H-U**
(full uninstall DRY transcript against the live guest, state-override protected). 28/28 PASS on
felhom-pve; red-proofs RP-1 (4b4 dropped → parity FAILs), RP-2 (preserve guard dropped → C4
FAILs), RP-3 (role-die dropped → C3a FAILs) all run→fail→revert on scratch copies.
- NOT live-validated (GL-6): the real (non-dry) uninstall with mounted/busy drives, the statement
on a real teardown, and an armed key-pin install end-to-end.
## felhom-host-install v1.10.0 — --mode appliance|byo install profile (TASK GL-2, go-live G2/G4/G5) (2026-07-07)
- **`--mode appliance|byo` is now REQUIRED** for a fresh install / `--resume` (no default — the