6.2 KiB
REPORT — R-204 item 4 (controller v0.199.0), 2026-08-05
A rebuilt box declares that it needs a credential. The box half of the last manual intervention
the 2026-08-04 drill needed. Hub half: felhom.eu v0.96.0, reported in that repo's
REPORT-r204-item4.md.
1. Baselines
felhom-controller at 68f195676b91 / v0.198.0 — exact match, tree clean, HEAD == origin/main.
§4's landmarks held: backup.OffboxReportStatus returned nil when no target existed (the ambiguity),
and the ACK's escrow object was discarded on an unconfigured box because
EscrowAutoConfirmer.Reconcile returns early when the box is neither pending nor escrowed.
Register drift worth flagging: the task states R-204 is the highest ID in use. It is R-211; grepped before minting, and the hub session mints R-212.
2. What changed
The ACK field stopped being discarded. RecordPresence is called FIRST in Reconcile, before
every gate. It lives in the auto-confirmer because that is already the one place the ACK escrow object
arrives and is already wired — a second consumer would be a second wiring point, and this project's
built-but-never-wired count is six. Last-write-wins, not set-only, so a customer RESET turns the
declaration back off; a nil ACK escrow records nothing (absence of a statement is not a statement of
absence); a record failure is logged and does not block the auto-confirm.
The declaration needs BOTH halves (needsOffsiteCredential): a fresh data area (no repository
password) AND a hub-held recovery package. Freshness alone is a box that never had off-site backups —
declaring on it would make every un-configured box in the fleet ask for a credential. A merely
DISABLED target is the customer's own choice and never declares.
Inert to every existing reader, established from the hub's code: enabled:false + zero sizes, so
isStale short-circuits on !Enabled and fillBand returns OK on a zero quota/size; an unknown
state string is ignored by encoding/json. A configured box's JSON is byte-identical to
v0.198.0's. The one reader that would have misread it is the hub's reportHasOffsite, tightened in
hub v0.96.0.
3. Files modified
| File | Change |
|---|---|
controller/internal/settings/settings.go |
new HubEscrowIdentityPresent field + accessors (saves only on a change) |
controller/internal/report/escrow_confirm.go |
new RecordPresence seam, called before every gate |
controller/internal/backup/offbox.go |
new OffsiteStateNeedsCredential, needsOffsiteCredential; State on the report object |
controller/cmd/controller/main.go |
wires RecordPresence |
controller/internal/backup/offbox_declare_test.go |
new — Scenarios A and B + the two exclusions + the byte-compat assertion |
controller/internal/report/escrow_presence{,_wiring}_test.go |
new — the recorder and its AST wiring test |
.githooks/pre-push |
the workspace-root assertion (rider) |
Commits on main: 1214bae (the declaration) · a91f055 (rider) · 992803c (CHANGELOG).
Deployed: felhom-controller:0.199.0 on demo-felhom 9201 and demo-hp 9201, both healthy.
4. Tests and red-proofs
Green gate: go build ./... && go vet ./... && go test ./... — rc=0.
python3 controller/scripts/controller_gates.py --fast — all eight gates OK.
| Scenario | Test | Result | Red-proof — what was mutated | Outcome |
|---|---|---|---|---|
| A | TestOffsiteDeclare_RebuiltBoxDeclaresNeedsCredential |
PASS | dropped the escrow condition from needsOffsiteCredential |
Scenario B FAILED — "a box that never had off-site backups DECLARED a need… every un-configured box in the fleet would now ask for a credential". This is the plausible wrong fix, and B is the guard that catches it. |
| B | TestOffsiteDeclare_NeverHadOffsiteSaysNothing |
PASS | (as above) | FAILED |
| — | TestOffsiteDeclare_BoxThatStillHoldsItsRepoPasswordDoesNotDeclare |
PASS | — | — |
| — | TestOffsiteDeclare_DisabledTargetIsNotStranded |
PASS | — | — |
| — | TestOffsiteDeclare_ConfiguredBoxJSONIsUnchanged |
PASS | — | — |
| — | TestEscrowConfirm_RecordsPresenceEvenWhenOffboxUnconfigured (+ nil-ACK, record-failure) |
PASS | — | — |
| seam | TestMainWiresRecordPresence |
PASS | commented out RecordPresence: in main.go |
FAILED — "EscrowAutoConfirmer is constructed WITHOUT RecordPresence — R-204 item 4 ships inert" |
5. Live validation
- The recorder works on a HEALTHY box — the case that used to return early. Both demo boxes now
carry
hub_escrow_identity_present = trueinsettings.json. - The declaration, produced live without wiping a box. demo-felhom 9201 was arranged
reversibly into the stranded shape (settings +
offbox/backed up first). The hub received report id=16743:{"enabled":false,"escrow_state":"","state":"needs_credential", "snapshot_count":0,"repo_size_bytes":0,"quota_gb":0}. Restored the same minute — report id=16744 is healthy. The single declaration was absorbed by the hub's debounce; no self-heal event fired. - A push from outside the workspace is refused, naming the expected root, before the gates run; with the assertion removed the same push succeeds. Both directions demonstrated.
- Part 4 (the deletion) HALTED at its STOP — the measured paths do not match the register. See
felhom.eu/REPORT-r204-item4.md§8 and R-212.
Teardown: demo-felhom restored and verified (enabled=True, escrow_state=escrowed,
repo_password present=True); the pre-change backup remains at /root/r204-backup on that guest.
Scratch clones removed. Nothing provisioned.
6. CI and hooks
--no-verify was NOT used. Every push ran the pre-push gate, including the new workspace-root
assertion. CI runs were confirmed green by head_sha for each push.
7. Observations — noticed, NOT acted on
- The workspace-root assertion is per-clone like the rest of the hook, so it binds only an armed clone; CI remains the half that is neither per-clone nor skippable (R-168).
felhom-agent'sreuse-refsgate incidentally also fails outside the workspace (the shared checker lives in thefelhom.eusibling). Repo-specific and not a substitute for the assertion.