This commit is contained in:
@@ -1,3 +1,72 @@
|
|||||||
|
## v0.96.0 — the hub answers a rebuilt box's request (2026-08-05, R-204 item 4 / R-193 / R-192)
|
||||||
|
|
||||||
|
The hub half of the last manual intervention the 2026-08-04 drill needed. The box declares
|
||||||
|
(controller v0.199.0); this answers.
|
||||||
|
|
||||||
|
### `internal/offsiteheal` — the sibling of `pbsdrheal`
|
||||||
|
|
||||||
|
Same shape, same restraint: **declared states only**, a debounce, **restage → escalate**, a distinct
|
||||||
|
audit event per remediation, and a healthy box is a pure no-op. It never blind-timer-reissues and
|
||||||
|
never re-runs a provisioning step.
|
||||||
|
|
||||||
|
**The debounce is TWO distinct reports, derived rather than chosen.** The controller reports every
|
||||||
|
~15 minutes, so two distinct declarations mean the state survived a full report cycle — a restart, a
|
||||||
|
slow first report or a transient config read all resolve well inside one. One report would act on a
|
||||||
|
blip; three would leave a stranded customer waiting ~45 minutes for the one thing they cannot obtain
|
||||||
|
any other way. The reconciler's own tick (5 min) is deliberately faster than the report cadence so it
|
||||||
|
adds no latency of its own; the debounce counts **fresh evidence, not ticks**.
|
||||||
|
|
||||||
|
**§8.4 — is there a deliberately-unhealed state, as `pbsdrheal` has in `verify_failed`?** Yes, and it
|
||||||
|
is excluded **by construction** rather than by a case in the switch — worth stating plainly, because
|
||||||
|
"there is nothing like that here" is usually wrong. The analogue is the **regressed** shape: a box
|
||||||
|
that had a working tier and lost its target while still holding its repository password. Re-arming a
|
||||||
|
credential would not help it. It cannot reach this reconciler at all, because the controller's
|
||||||
|
declaration predicate requires the repository password to be **absent**.
|
||||||
|
|
||||||
|
### Restage before mint — and the fact it rests on
|
||||||
|
|
||||||
|
`store.RestageOneTimeSecret` clears the consumed flag without touching the value, mirroring
|
||||||
|
`RestageHostPBSSecret`. **That the value survives a consume was established from this schema and from
|
||||||
|
`ConsumeOneTimeSecret` — which stamps `consumed_at` and nothing else — not inherited from the PBS
|
||||||
|
analogy.** The two secrets are different objects with different lifecycles, and assuming a shared
|
||||||
|
shape is how two earlier sessions confused the credentials. `TestRestageOneTimeSecret_ReArmsTheSameValue`
|
||||||
|
asserts the **same** value comes back, so a future "hardening" that cleared the column would fail
|
||||||
|
loudly instead of silently turning every rebuild into an external mint.
|
||||||
|
|
||||||
|
### `reportHasOffsite` tightened — the ninth comment-vs-code entry, caught before it shipped
|
||||||
|
|
||||||
|
Its comment asserted *"the report builder attaches `offsite` only when the box actually has an offbox
|
||||||
|
target configured, so presence == applied-on-the-box"*. Controller v0.199.0 breaks that premise
|
||||||
|
deliberately. Left as bare presence, this would have read a **request for help** as proof the tier was
|
||||||
|
**applied** — making `DeliveryStateFor` return `DeliveryApplied` for exactly the stranded boxes, and
|
||||||
|
suppressing their stuck event. It now requires `enabled:true`, which is **provably a no-op for every
|
||||||
|
report shape that existed before** (an attached object has always carried `enabled:true`), and the
|
||||||
|
equivalence is measured in `TestReportHasOffsite_EnabledOnly` rather than argued.
|
||||||
|
|
||||||
|
### R-192's guard half — CLOSED BY REPLACEMENT, not repaired
|
||||||
|
|
||||||
|
The delivery checker decided the shape by counting how many of the **oldest 500** reports after a
|
||||||
|
consume carried an offbox target. On demo-hp all 500 predated the rebuild, so it confidently reported
|
||||||
|
the *regressed* shape and declined to heal — for 108 reports, while the box sat stranded. A
|
||||||
|
declaration needs no window, no count and no inference, so it **outranks both inferred shapes**
|
||||||
|
(`shapeDeclared`), the stuck e-mail says what was declared instead of prescribing Re-issue, and
|
||||||
|
`maybeHeal` **stands down with a record** because `offsiteheal` owns the remediation. Two mechanisms
|
||||||
|
healing one customer would double-issue — and this one can only mint, so it would also skip the cheap
|
||||||
|
path.
|
||||||
|
|
||||||
|
### What is deliberately NOT automated
|
||||||
|
|
||||||
|
**No escrow ceremony is ever run or requested.** A credential is replaceable; the recovery code is
|
||||||
|
not, because only the customer holds it. **Credential automatic, key customer-present.**
|
||||||
|
|
||||||
|
**On security, weighed rather than skipped:** a re-issued credential is transport only. Anyone able to
|
||||||
|
forge the declaration already controls the box, and the box already holds its own installed access
|
||||||
|
key. The data stays sealed under the recovery code throughout.
|
||||||
|
|
||||||
|
### Rider — the pre-push hook refuses a clone outside the workspace
|
||||||
|
|
||||||
|
One assertion, identical in all four repos. See the controller's v0.199.0 entry.
|
||||||
|
|
||||||
## v0.95.0 — a re-issue no longer marks a healthy escrow stale (2026-08-05, R-196 / R-204 item 2)
|
## v0.95.0 — a re-issue no longer marks a healthy escrow stale (2026-08-05, R-196 / R-204 item 2)
|
||||||
|
|
||||||
`ReissueCredentials` called `MarkEscrowStale` on every re-issue that found an escrow row. The mark was
|
`ReissueCredentials` called `MarkEscrowStale` on every re-issue that found an escrow row. The mark was
|
||||||
|
|||||||
Reference in New Issue
Block a user