spike(pin-mismatch): follow-up — aside-var-lib holds matching token store; R1 = one-copy fix for pin+token

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EPZ4GJ8L5Jqf8UiPwbn1kt
This commit is contained in:
2026-06-29 14:44:10 +02:00
parent 2de9659592
commit 8254b8823e
@@ -179,7 +179,37 @@ the old token store), or the symptom merely changes from `TLS pin mismatch` to `
**Token store (applies to R1/R2):** also re-seed guest 9201's bearer token into
`/var/lib/felhom-agent/local-tokens.log` (re-provision token mint, or restore the old token store
from the same `aside-var-lib` set-aside if present), else expect a `401` after the pin is fixed.
from the same `aside-var-lib` set-aside), else expect a `401` after the pin is fixed.
### Follow-up CONFIRMED (2026-06-29) — `aside-var-lib` holds the matching token store → R1 is one copy
The set-aside **does** contain the pre-migration token store, and it matches guest 9201's
*current* controller token, so **R1 fixes the pin and the token blocker in a single restore**:
```
/root/agent-backup-bundle-test/aside-var-lib/local-tokens.log
656 bytes, 8 records, mtime 2026-06-26 19:56 (pre-migration)
effective (last-write-wins) vmids: 9200, 9201
vs live /var/lib/felhom-agent/local-tokens.log : 0 bytes, mtime 2026-06-28 08:56 (reset at migration)
```
Verified on-host (token plaintext/hashes never left the host; only the verdict was emitted): the
agent stores `{"v":<vmid>,"h":hex(sha256(token))}` JSONL (`internal/localapi/tokenstore.go`,
last-write-wins per vmid). The SHA-256 of the controller's **current** `controller.yaml`
`local_api.token` (the line under `local_api:`, **not** the unrelated `git:`/`hub:` tokens in the
same file) is **present in the old store under vmid 9201**. So:
- old leaf fp `60b5974d…` **==** `PIN_FP` (and `SEED_FP`) ✓
- old store's effective 9201 token hash **==** controller's current `local_api.token` hash ✓
**Therefore the cleanest remedy is R1 extended to three files:** restore
`local-api.crt`, `local-api.key`, **and** `local-tokens.log` from `…/aside-var-lib/`
`/var/lib/felhom-agent/`, `chown felhom-agent:felhom-agent` (crt `0644`, key/tokens `0600`),
restart the agent. The agent then *loads* (not regenerates) the old leaf and re-indexes the old
token store; the controller's existing pin **and** token both validate, **with zero in-guest
change**. (Caveat: this reinstates the pre-migration leaf `60b5974d…` rather than adopting the
new `ced34036…` — fine for restoring service; if the operator wants the new leaf to be canonical,
that's R2/R3 instead, both of which still need the token re-seed handled separately.)
**Forward-looking:** the root→non-root migration runbook should **carry the existing
`local-api.{crt,key}` and `local-tokens.log` into the new data dir** (or treat their loss as a
@@ -196,8 +226,10 @@ incident.
migration mtime is strong evidence; not *proven* live because the TLS pin fails before any token is
evaluated, and probing it would require an authenticated call (out of scope for read-only). Operator
should expect it and plan the token re-seed alongside whichever pin remedy is chosen.
- **Not assessed:** whether `…/aside-var-lib/` also holds the matching pre-migration
`local-tokens.log` (would make R1 + token restore a single copy). Cheap to check before choosing.
- **Resolved (was "not assessed"):** `…/aside-var-lib/` **does** hold the matching pre-migration
`local-tokens.log`, and its effective 9201 token hash equals the controller's current
`local_api.token` hash — so R1 restored as three files (crt+key+tokens) fixes pin **and** token in
one copy, zero in-guest change. See §7 follow-up.
*No secrets recorded: the per-guest bearer token is referenced as "stored out-of-band"; the leaf
fingerprint is not a secret.*