CHANGELOG: controller v0.199.0 (R-204 item 4, box half)
gates / gates (push) Successful in 10s

This commit is contained in:
2026-08-05 10:49:20 +02:00
parent a91f055960
commit 992803c10b
+58
View File
@@ -1,3 +1,61 @@
## v0.199.0 — a rebuilt box asks for its credential back (2026-08-05, R-204 item 4 / R-193)
The last of the four manual interventions the 2026-08-04 drill needed. A rebuilt box has no off-site
credential of its own — its predecessor spent the one-time provider password — and everything after
that point is already self-service. **This is the box's half: it now DECLARES what it needs.**
### Why a declaration and not an inference (the operator ruling, and the whole design)
From the hub, an **absent** off-site object has FOUR meanings — never configured, mid-restart, a
transient config read failure, and rebuilt-and-stranded — and the hub cannot tell them apart. **The
box can**, from two local facts it holds with certainty. So it says so, in its ordinary report, and
the hub acts on a stated request instead of on a silence.
### The two halves, and why neither is sufficient
`backup.needsOffsiteCredential` requires **both**:
- **a fresh data area** — no repository password on disk. Alone this is simply a box that never had
off-site backups, and declaring on it would make *every un-configured box in the fleet* ask for a
credential. That is the plausible wrong fix, and `TestOffsiteDeclare_NeverHadOffsiteSaysNothing` is
the guard that catches it.
- **a hub-held recovery package** — the report ACK's `escrow.identity_blob_present`. Alone this is a
healthy box that has run its ceremony.
A target that exists but is merely **disabled** is the customer's own choice and never declares.
### The ACK field stopped being discarded
`EscrowAutoConfirmer.Reconcile` now records `identity_blob_present` **first, before every gate**. Those
gates return immediately when the box is neither pending nor escrowed — which is exactly a rebuilt
box — so the one fact that distinguishes it from a box that never had off-site backups was thrown
away on every cycle. It is recorded through the confirmer because that is already the ONE place the
ACK's escrow object arrives and is already wired; a second consumer would be a second wiring point,
and this project's count of features built but never wired is six. `TestMainWiresRecordPresence`
asserts the wiring from main.go's AST.
The recorder is **last-write-wins, not set-only**: a customer RESET that removes the hub's escrow row
must be able to turn the declaration back off. A nil ACK escrow object records nothing — absence of a
statement is not a statement of absence.
### Inert to every existing reader
The declaration carries `enabled:false` and zero sizes. Established from the hub's code rather than
assumed: `OffsiteChecker.isStale` returns early on `!Enabled`, and `fillBand` returns OK on a zero
quota/size — so it raises no staleness and no fill alarm, on a new hub **or an old one**, and an
unknown `state` string is ignored by `encoding/json`. **A configured box's report JSON is
byte-identical to v0.198.0's** — there is no `state` key at all.
The one reader that would have misread it is the hub's `reportHasOffsite`, whose comment asserted
*"presence == applied-on-the-box"*; felhom.eu v0.96.0 tightens it to require `enabled:true`.
### Rider — the pre-push hook refuses a clone outside the workspace
`.githooks/pre-push` gains one assertion, identical in all four repos. The workspace root was already
written down and was drifted from anyway; a rule that has failed once as a reminder is not fixed by
writing it down again. A push is the right trigger — throwaway `/tmp` clones for probes never push.
The only bypass is the documented `--no-verify`.
## v0.198.0 — the four steps a customer would have hit alone: two of them closed (2026-08-05, R-204 items 1 & 3) ## v0.198.0 — the four steps a customer would have hit alone: two of them closed (2026-08-05, R-204 items 1 & 3)
The 2026-08-04 recovery drill (R-201) passed — and it only passed because a person was there. Four The 2026-08-04 recovery drill (R-201) passed — and it only passed because a person was there. Four