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
+26
View File
@@ -249,6 +249,24 @@ What byo does differently (everything else matches C.4's eight steps):
- Step 4b/8 (break-glass) is skipped; the verify step asserts pool membership + the scoped ACL
grants landed (both modes do this from v1.10.0).
### C.5b Operator key pin — self-update authority (v1.11.0)
The agent's self-update only acts on **operator-signed** update ops; the verifying public keys are
pinned in the agent config (`authz.signers`). A fresh install with **no key pinned runs self-update
DORMANT** (the safe default — the verify step prints a WARN, not an error). To arm it at install
time, either:
- fill the `OPERATOR_KEY_*` constants near the top of the script (one commit, after the offline
key-generation ceremony), or
- pass `--operator-pubkey-file <path>` — one key per line, `operational <authorized_keys line>` or
`recovery <authorized_keys line>`; the authorized_keys **comment field is the key_id and is
required**. The file overrides the constants.
Rules: PUBLIC keys only (private keys never touch the box or this script); a reinstall with no
keys resolved **keeps** an already-pinned config's signers (`--preserve-from`) — pinned boxes are
never silently un-pinned; providing keys over a preserved config replaces them (pin rotation,
logged). byo installs show the operational key_id in the disclosure block.
### C.6 Post-hoc mode note for pre-v1.10.0 installs
Boxes installed by ≤ v1.9.1 have no recorded mode; their state file simply predates it. `--resume`
@@ -349,6 +367,14 @@ state dir/config/service user), the shared-parent unit + wrapper + `/mnt/felhom-
guarded-mkfs wrapper, the guest-hook snippet, the lan-resolver dnsmasq snippets, the pveum
roles/ACL/token/user, the pool (if empty), the install state file.
v1.11.0 additions: the teardown also removes the **self-update artifacts** (guarded wrapper, A/B
slots, rollback unit, limits drop-in), **unmounts enrolled drives** under `/mnt/felhom-drives/`
(plain umount only — a busy drive gets a warning and guidance, never a forced unmount; the data is
never touched and the drives are physically removable afterwards), and both modes end with an
explicit **KEPT-vs-WIPED statement** — read it before pulling drives or closing the customer out
(it lists what lives on: drive data, PBS backups, the hub record, the escrow blob, the vaulted
recovery credential).
**Expected remnants** (documented, not residue):
- The **hub host record** (+ its report/guest history) — the hub currently has **no host-delete**;