v0.63.0: B3+B2 fresh-install fixes — TokenStore reload-on-miss + guesthook snippets dir

B3: Lookup re-reads the append-only store once on a miss (cross-process
coherence with the one-shot provisioner; size short-circuit bounds the cost;
behind the TokenAuthority seam). B2: fenced mkdir -p /var/lib/vz/snippets
before the snippet install + the one narrow sudoers grant. Both red-proofed;
drill findings DRILL-day0-cleanroom-2026-07-03 B3/B2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-03 15:48:24 +02:00
parent 84f3f7ddb1
commit f31a76f788
8 changed files with 254 additions and 8 deletions
+29
View File
@@ -1,3 +1,32 @@
## v0.63.0 — B3 + B2: fresh-install fixes — token reload-on-miss + guesthook snippets dir (2026-07-03)
The two agent-side gaps the Day-0 clean-room drill surfaced
(`felhom.eu/documentation/audits/DRILL-day0-cleanroom-2026-07-03.md` findings B3/B2). Both are
fresh-install path fixes; no behavior change on a warm box.
- **B3 — `TokenStore.Lookup` reload-on-miss** (localapi/tokenstore.go): provisioning is a SEPARATE
one-shot process (`--selftest=provision`) that Mints the new guest's token into the shared
append-only JSONL, while the long-lived daemon serves Lookup from an index built once at open —
so the daemon 401'd every token minted after it started (the drill's
`POST /controller/swap: HTTP 401`, until a manual `systemctl restart felhom-agent`). Lookup now
re-reads the file ONCE on a miss (`reloadLocked()`, factored from `load()`; full re-read is
idempotent under `apply`'s last-write-wins) and re-checks. An append-only size short-circuit
bounds the cost: an unknown token on an unchanged file is one `stat`, no re-read — never a reload
loop. Fix is entirely behind the `TokenAuthority` seam (no server change). Fail-closed on an
unreadable store; missing file loads as empty. Tests (tokenstore_test.go): cross-process-mint
coherence (red-proofed: pre-fix shape returns (0,false)), exactly-once reload bound +
size short-circuit, cross-process re-mint rotation coherence, deleted-file no-crash
(linux-only; windows can't unlink an open handle).
- **B2 — `guesthook.InstallSnippet` ensures the snippets dir** (guesthook/install.go): a fresh PVE
has no `/var/lib/vz/snippets` and `install` (without `-D`) won't create parents — the pre-start
self-heal hook silently failed to install on every freshly-bootstrapped box (warn-only in the
back-half). A fenced `mkdir -p /var/lib/vz/snippets` now precedes the install; **sudoers gains
exactly that one grant** (FELHOM_GUESTHOOK — configs/felhom-agent.sudoers must ship WITH this
binary, as always). Test: mkdir-precedes-install argv assertion (red-proofed: pre-fix has no
mkdir op).
- Guide follow-through (felhom.eu, separate commit): D.1b's "restart the agent first" step drops
once B3 is live-verified.
## v0.62.0 — A1: pool-membership ownership check for the stale-lock reaper (2026-07-03)
Implements audit finding A1 (`AUDIT-blast-radius-hostroot-localapi-2026-07-02` §A) per the spike