From 992803c10bd37e0514630ebcdfe59f01c6e76d59 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 5 Aug 2026 10:49:20 +0200 Subject: [PATCH] CHANGELOG: controller v0.199.0 (R-204 item 4, box half) --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c8fc79..10a94eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) The 2026-08-04 recovery drill (R-201) passed — and it only passed because a person was there. Four