R-241 FIXED: registers, capability map, STATUS, hub CHANGELOG v0.98.0
gates / gates (push) Successful in 14s

R-241 closed against controller v0.206.0 + hub v0.98.0, following the spike's
ruling rather than the obvious reading. The row records what the fix does AND
the two real bugs the tests caught rather than review - a missing t.Enabled
(caught by an EXISTING test) and a missing falling-edge sync that
reintroduced the very defect the epoch exists to fix.

R-243 UPDATED, not closed: the STATE it describes can no longer be entered
(the mint guard), and what replaces it is VISIBLE rather than silent - the box
declares awaiting_recovery_key and the customer is offered the screen. But the
ALARM GAP is untouched, for the same three reasons, so a box whose customer
never acts still stops backing up with no operator signal. The remaining work
is an operator-side signal for a box held past some age, deliberately not
bundled into R-241's fix.

R-245 NEW - WAITING-ON-OPERATOR, recorded and NOT built: should an undecided
customer be auto-abandoned after 30 days? The operator's proposal is recorded
WITH the reasoning against it, so the decision can be revisited properly: a
reinstall implies a person, so nobody is absent; a customer who cannot find
their code gets in touch, which is why the operator LEVERS were the thing
worth building; the cost is the customer's own storage allowance; and the real
harm is QUOTA, which is a condition, not a calendar. If it is ever built,
build it to trigger on the harm with a dated warning, never on a date alone.

The capability map's recovery-journey row STAYS FAIL. These are fixes, not a
walk - nothing here walked a customer end to end, and the row goes green only
when one completes with no operator intervention AND a byte-identical
sentinel. R-214, R-202 and R-240 are still open.

STATUS compressed rather than extended, per its own one-screen rule, and the
"rebuilding throws away the off-site history" line corrected: the cause is
fixed, so leaving it as a live defect would be false.

hub CHANGELOG v0.98.0 for the superseded-package purge.

Highest register ID moves R-244 -> R-245.
This commit is contained in:
2026-08-07 12:13:09 +02:00
parent ac4b2a4ba9
commit 9657334fb7
4 changed files with 69 additions and 39 deletions
+33 -36
View File
@@ -15,43 +15,40 @@ who sets their own password. They install apps from a catalogue of fifty-three,
home network, and open apps from a launcher or a shared link. Backups run on their own to three
places — the machine's drive, a second drive, and an encrypted off-site copy.
**The backup promise is proved again. The recovery JOURNEY still is not — and last night it got
worse before it gets better.** On 67 August we built a brand-new machine from the published disc,
gave it three marked files, left it alone through a full night's scheduled work, destroyed it, and
rebuilt it. **The files came back byte for byte identical**, all three, including one with Hungarian
accents in its name. **But the household had no way to ask for them.** The screen that takes their
recovery code had switched itself off, and the backup page offered to make them a *new* code — which
would have locked the old backups away for good. There was no box to type their code into at all.
**The backup promise is proved again. The recovery JOURNEY still is not — but the fault that broke it
last night is now fixed.** On 67 August we built a brand-new machine from the published disc, gave it
three marked files, soaked it through a full night, destroyed it and rebuilt it. **The files came back
byte for byte identical**, all three, including one with Hungarian accents in its name. **But the
household had no way to ask for them:** the screen that takes their recovery code had switched itself
off, and the backup page offered to make them a *new* code instead.
**The cause is a success.** A repair that runs on its own — and which this same night proved working
beautifully, with nobody touching anything — hands the machine a fresh key. Holding that key makes the
machine think it no longer needs rescuing. It is the same mistake the system already fixed once, one
level higher up. *(R-241)*
**7 August — we asked which of two things was wrong, and the answer reversed the repair.** The obvious
reading was that the screen's rule was too narrow. It was not. **The screen was telling the truth**
there really was nothing openable with the key the machine held, **because the machine had made that
key itself**, on top of the sealed package we were already keeping for it. And it knew: it wrote *"the
sealed package does not cover the current key"* into its own log **thirty-five minutes before the
household looked**, then threw the answer away. Mending the screen would have hidden a machine quietly
making its own backups unopenable. *(R-241)*
**7 August — we asked which of two things was actually wrong, and the answer changes the repair.** The
obvious reading was that the screen's rule was too narrow. It was not. **The screen was telling the
truth**: there really was nothing openable with the key the machine was holding — because the machine
had *made that key itself*, on top of the sealed package we were already keeping for it. Three things
now measured rather than argued: the part that makes the key asks only *"is there a file here?"*,
while the two neighbouring pieces of code both check first whether we are holding a package; the
machine had that knowledge **half an hour before** it made the key, and it was the very reason the
repair ran at all; and **the machine worked out the problem itself**, wrote *"the sealed package does
not cover the current key"* into its own log thirty-five minutes before the household looked, and then
threw the answer away. **So mending the screen would have hidden a machine quietly making its own
backups unopenable.** No code was written — this was a question, and it is now answered. *(R-241)*
**Fixed the same day.** The machine **stops making its own key** while we hold a package for it — the
repair that prevents the situation rather than tidying up after it. **The comparison it was already
making now decides whether to offer help**, instead of two indirect guesses that have each been wrong
in opposite directions. And **giving up the old backups became a finishable thing**: a **14-day
countdown** you can see and change your mind about, at the end of which the old backups *and* their
sealed package go together — so the question stops coming back because there is nothing left to ask
about, not because something is suppressing it. On the way past, the *"create a new recovery code"*
button is now **unavailable** while a recovery is outstanding, and the confirmation says plainly that
the old backups are deleted **on a date** rather than merely set aside.
**Two things we did not go looking for.** A machine in this state also **stops making off-site backups
altogether, and nothing raises an alarm** — three separate safety nets each correctly decide it is not
their business *(R-243)*. And the obvious repair has a trap: a household that has already said *"I do
not want the old data"* would be asked again, forever, unless we record that they decided.
**Two of our own mistakes were caught by tests rather than by reading the code**, which is the point of
having them: one would have warned a household that had switched off-site backups off, and one would
have brought back the very fault we were fixing.
**And separately: today's machines now DO get last week's fixes — approved 7 August.** The newer
in-house service is packaged and approved, so a machine installed from now on gets both fixes a new
customer was still missing last night. Existing machines are untouched, and the approval can be undone
by re-selecting the previous one. *(R-239 — closed)* **The gap that let it happen is not closed**: a
release that changes what a customer sees is still not *delivered* until it is packaged, and nothing
checks that. *(R-242 — recorded, not built)*
**Still open, on purpose:** a machine held waiting for its code raises no alarm to *us* *(R-243)*;
nothing enforces that a release reaches a new machine *(R-242)*; and we deliberately did **not** build
automatic abandonment after 30 days *(R-245 — the reasoning is written down)*.
**Today's machines now get last week's fixes — approved 7 August.** *(R-239 — closed.)*
## What's broken
@@ -71,10 +68,10 @@ checks that. *(R-242 — recorded, not built)*
drives, so no app can be put back on its data; it cannot create a new recovery code at all; and the
screen at the machine itself never stops showing a stale pairing code. Each is understood, measured
and written down — none is fixed yet. *(R-220, R-221, R-214)*
- **Rebuilding a machine still throws away its off-site backup HISTORY.** The machine invents the key
that encrypts its own off-site backups, and a rebuilt machine invents a new one. **The good news:
the old key really is kept now — we proved it on a real machine today, for the first time**, and a
changed key raises an alarm the same day. *(R-193, R-198)*
- **~~Rebuilding a machine throws away its off-site backup history~~ — the CAUSE is fixed (7 August).**
A rebuilt machine used to invent a new encryption key over the top of the sealed package we hold for
it. It no longer does: while we hold a package, it waits for the household's recovery code instead.
The old key is kept and a changed key still raises an alarm the same day. *(R-193, R-198, R-241)*
- **The kept older backups cannot be opened — by anyone.** We keep the previous sealed package and
there is no way to open it. The screens now say exactly that and stop. **One place still promises
otherwise**: the older-backups card says they "may be restorable later with the matching code",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+31
View File
@@ -1,3 +1,34 @@
## v0.98.0 — drop the retained recovery package when the box says its set-aside history is gone (2026-08-07, R-241)
The hub half of the controller's abandonment countdown, and the **only** reason the hub was touched
for R-241 at all.
A customer who abandons their old off-site history gets a 14-day grace on the box. At the end of it
the controller deletes the set-aside restic store and then **declares**
`offsite.abandon_purge_requested` in its report until the retained sealed package that protected that
store is gone too. **Removing only one half leaves a state that asks a question nobody can answer:** a
package that opens nothing, or ciphertext nobody can ever decrypt.
`store.PurgeSupersededEscrowForCustomer` is the one place R-198's retention is ever undone, and its
doc comment says why that is legitimate here. **It never touches `host_escrow`** — the current package
covers the key the box is using now and is what makes its live backups recoverable. Only
`host_escrow_superseded` rows go.
**It acts on a DECLARATION, never an inference**, on the same principle as `offsite.state`: the hub
cannot see that a remote store was deleted, and the box can.
**Placed immediately before the ACK is built, deliberately.** `GetEscrowStatusForCustomer` is read
after it runs, so the *same* response that carries the request's effect is what closes the box's
two-phase commit — no second round-trip, and no window in which the box believes it is still owed. The
declaration repeats on every report until that ACK stops reporting a superseded package, so a lost
request retries by itself rather than leaving the pair half-removed.
A purge failure is logged at ERROR and never swallowed; an idempotent re-declaration (already purged,
the box has not yet seen the confirming ACK) logs at DEBUG and is not an error. Audit event
`offsite_abandon_purged` is hub-internal, like the `pbsdr_*` and `offsite_selfheal_*` events.
Needs controller **v0.206.0** to declare it. No agent change.
## v0.97.1 — the held-floor REASON must match the hold's CAUSE (2026-08-05, CAMPAIGN-11 follow-on)
> **Entry added retroactively 2026-08-05 (CAMPAIGN-11 Phase 2).** The change shipped and **is** the