diff --git a/REPORT.md b/REPORT.md
index 2992d9a..17b8b9f 100644
--- a/REPORT.md
+++ b/REPORT.md
@@ -1,278 +1,252 @@
-# REPORT — R-241 fixed: the box does not mint over a sealed package (2026-08-07)
+# REPORT — a secret leaves the page source, and two refusals learn to say what to do (v0.207.0, 2026-08-08)
-**controller `v0.206.0` · hub `v0.98.0` · deployed to both demo boxes · `felhom-agent` untouched**
-
-Implements the ruling in `SPIKE-r241-recovery-offer-2026-08-07.md`. **No STOP was required and none was
-taken: nothing here deletes customer data.**
+**R-249, R-252, R-253 — implementation. R-201's record corrected, R-254 filed. Controller
+`v0.206.0` → `v0.207.0`, built, pushed and deployed to `demo-hp` guest 9201 and VM 325.** No hub
+change was needed. Baselines re-read on arrival and all four repos matched the task exactly
+(`felhom-controller 3d3b4496f377`, `felhom.eu 3f4fb3825f06`); highest register ID was **R-253**.
---
-## 1. SCENARIO A — the live result, and its red-proof
+## 1. Scenario A — the raw response body, before and after
-**THE SESSION, in one measurement.** On demo-hp, controller `0.206.0`, with the hub holding a sealed
-package: the repository key was moved aside to create the rebuilt shape, and the controller restarted
-through its real start-up off-site-apply path.
+**This is the deliverable that matters, and it was measured on a live box with a positive control in
+both directions.** A known passphrase was planted on VM 325 (a throwaway due for destruction the same
+hour) and the security settings page fetched exactly as the defect was originally found — with `curl`.
+
+| | v0.206.0 (the shipped defect) | v0.207.0 (the fix) |
+|---|---|---|
+| page bytes | 50 208 | 51 115 |
+| **positive control** — card renders (a passphrase IS stored) | **1** | **1** |
+| reveal control present | — | **2** |
+| **passphrase occurrences in the response body** | **1** | **0** |
+
+**The positive control is load-bearing.** The first attempt at this check returned `0` on a box that
+had no passphrase stored at all — a zero that meant nothing. That is why the card's presence is
+asserted first: *an empty listing is not evidence of emptiness.*
+
+**Scenario B, live:** `POST /settings/retrieval-password/reveal` → **200**, `Cache-Control: no-store`,
+body 85 bytes carrying the correct passphrase (**1** match against the planted value). The controller
+logged `retrieval passphrase revealed via the security page from 192.168.0.100 (value never logged)`,
+and a grep of five minutes of controller log for the value itself returned **0**.
+
+### The red-proof — the most important one here
+
+Both halves of the fix were reverted (`data["RetrievalPassword"] = …` restored in `handlers.go`, and
+`{{.RetrievalPassword}}` put back inside a `display:none` span), **each mutation asserted to have
+applied** before running:
```
-=== 1. was a key minted on the startup offsite-apply path? ===
- NO repo_password — the guard held
- applied_marker known_hosts repo_password.r241-live-check ssh_key
+BOTH MUTATIONS APPLIED — verified by string change
+--- FAIL: TestSecurityPage_DoesNotContainTheRetrievalPassphrase (0.08s)
+ R-249: the retrieval passphrase is in the response body of the security page …
```
-**And the state it reports instead**, read from the hub's stored report, not from the box:
+Restored; residue checked (`{{.RetrievalPassword}}` occurrences: **0**); green again.
-```json
-{"enabled": false, "escrow_state": "escrowed", "state": "awaiting_recovery_key",
- "snapshot_count": 0, "repo_size_bytes": 0, "quota_gb": 0}
-```
-
-`enabled:false` is what keeps every existing hub reader inert; the string is what names the difference.
-**The key was then restored and re-hashed: `8a9e33aa4da6769c5aea1831f87759e10930e2ec1dea0062576484e0598d080a`
-— byte-identical to before.** The box is healthy on `0.206.0`.
-
-**RED-PROOF A — the fresh key returns under the mutation.** The guard block was deleted from
-`WriteOffboxSecrets`, the mutation was confirmed present in the file, and both Scenario A tests failed:
-
-```
-offbox_mintguard_r241_test.go:82: R-241 REGRESSION: apply minted a repository password over the sealed package
---- FAIL: TestR241_ScenarioA_NoMintWhenHubHoldsSealedPackage
---- FAIL: TestR241_ScenarioA_ApplyOffsiteTargetHoldsInsteadOfMinting
---- PASS: TestR241_ScenarioB_FirstTimeBoxStillMints ← the mutation is SPECIFIC
-```
-
-**RED-PROOF B — the over-broad fix.** Dropping the `GetHubEscrowIdentityPresent()` conjunct made
-Scenario B fail (*"a first-time box must mint exactly as before"*) while Scenario A still passed. The
-guard is a conjunction because both failure directions are real.
+**Why the tests assert the body and not a view:** the old markup hid the value with CSS. Every test
+that asked *what does the customer see* passed while the bytes carried the secret. A test that cannot
+see a `display:none` span cannot see this defect at all.
---
-## 2. Q4's seven rows, mapped to the three states
+## 2. §7.1's census — the pattern found once, looked for everywhere
-| # | Q4 state | resolves to | note |
+**It was worth doing: two more instances, one with a real secret.**
+
+| Where | What | Verdict |
+|---|---|---|
+| **`app_info.html:185`** | an app's auto-generated first-login password in `{{.InitialCreds.Password}}` beside a „Megjelenítés" button | **the same defect with a real per-install secret** — `ReadInitialCredentials` reads it live out of the deployed container, so it is *not* the catalog's published `default_creds` |
+| `deploy.html:482` | an auto-generated `type: secret` field in `` | weaker — the **pre-deploy** form must post the value; on an **already-deployed** app's page the exposure is gratuitous |
+
+**Filed as R-254, not fixed** — scope was R-249/R-252/R-253, and each needs its own reveal endpoint
+and its own body-asserting test rather than a shared quick edit. **Recommended next**, because R-249
+proved the pattern is not theoretical.
+
+**Rotation advice, left to the operator:** the `walk5` instance is compromised (it reached a
+transcript) and dies with that customer's teardown. **No other instance is known to have been read —
+but nothing records a read, which is itself part of the defect**, and that is the honest state of the
+evidence. If any customer page has been screen-shared, saved or proxied, treat that passphrase as
+exposed.
+
+---
+
+## 3. §7.2's decision — which half of the reinstall promise was wrong
+
+**The promise was wrong, and the reason is structural rather than a matter of effort.**
+
+`reconstituteOffbox` refuses when `GetStackHDDPath(stack)` is empty, because **the destination of a
+restore is the app's own data path — a drive the CUSTOMER chooses at deploy time.** An automatic
+reinstall would mean the product picking that drive for them, which is precisely the decision this
+recovery path exists to leave with them (`DOMAIN` and `SUBDOMAIN` would have to be invented too).
+
+So the smaller change is also the correct one: the copy now says to install first and routes there.
+The row's own code comment already read *"restore in place vs. reinstall first"* — the behaviour was
+right and the sentence had drifted.
+
+---
+
+## 4. Every changed Hungarian string, for review as copy
+
+**Removed** (`backups_restore.html`) — the promise the restore could not keep:
+
+> „Nincs telepítve — a visszaállítás előbb újratelepíti."
+
+**Added** (`backups_restore.html`, the not-installed row):
+
+> „Nincs telepítve — előbb **telepítsd újra**, utána hozhatod vissza az adatait." *(„telepítsd újra"
+> links to `/stacks//deploy`)*
+
+**Added** (`backups_restore.html`, the precondition notice — renders only when no drive is registered):
+
+> „**Előbb csatold vissza az adatmeghajtót.** A mentéseid megvannak, és a meghajtók is megvannak —
+> újratelepítés után viszont a gép még nem ismeri őket, ezért most nincs hová visszaállítani. Ez két
+> kattintás: **Tárhely → Meghajtók**, „Meglévő meghajtó csatolása". Utána gyere vissza ide."
+
+**Changed** (`offbox_restore.go`, the drive refusal):
+
+> was: „nincs elérhető adatmeghajtó a visszaállításhoz"
+> now: „nincs regisztrált adatmeghajtó, ezért nincs hová visszaállítani — a meghajtók megvannak, csak
+> újra kell csatolni őket a Tárhely → Meghajtók oldalon, utána ez a visszaállítás működni fog"
+
+**Changed** (`offbox_reconstitute.go`, the not-installed refusal):
+
+> was: „a(z) %s nincs telepítve — előbb állítsd helyre az alkalmazást, utána az adatokat"
+> now: „a(z) %s nincs telepítve, ezért nincs hová visszaállítani az adatait — telepítsd újra az
+> alkalmazást (Alkalmazások), utána ez a visszaállítás működni fog"
+
+**Added** (`settings_security.html`, reveal failure): „A visszaállítási jelszó lekérése nem sikerült."
+**Added** (reveal endpoint, nothing stored): „Ezen a gépen nincs tárolt visszaállítási jelszó."
+
+---
+
+## 5. Tests and red-proofs — each mutation asserted to have applied
+
+| Test | Scenario | Result | Red-proof (mutation → observed) |
|---|---|---|---|
-| 1 | never had off-site backups | **settled** | fact 1 fails; nothing offered |
-| 2 | pristine rebuild, credential not yet arrived | **offered** (shape a) | **no longer a closing window** — the mint guard means it does not end by itself |
-| 3 | self-healed with a fresh key, hub holds the older package ← **the venue** | **offered** (shape c) | **the row R-241 was, and it now cannot be entered at all** — the guard prevents the key |
-| 4 | healthy, key matches | **settled** | shape (c) compares and matches |
-| 5 | re-escrowed, old package retained | **settled** | unchanged; the retained package is still unreadable (R-199) |
-| 6 | orphaned (a run proved it) | **offered** (shape b, corroborated by c) | (b) retained as a corroborator |
-| 7 | customer set the old data aside | **abandoning**, then **settled** | the spike's trap: (c) alone would re-offer for ever. The countdown resolves it by removing both halves |
+| `TestSecurityPage_DoesNotContainTheRetrievalPassphrase` | **A** | PASS | value re-rendered into the page → **FAIL**, printing the exposure |
+| `TestSecurityPage_NoCardWhenNoPassphraseStored` | A | PASS | — (gate is on existence, not the value) |
+| `TestRevealEndpoint_ReturnsThePassphraseToAnAuthenticatedCaller` | **B** | PASS | remove the route/handler → customer cannot obtain it at all |
+| `TestRevealEndpoint_404sWhenNothingStored` | B | PASS | — |
+| `TestRestorePage_NoRegisteredDrive_NamesTheReasonAndTheRoute` | **C** | PASS | precondition block deleted → **FAIL** |
+| `TestRestorePage_HealthyBox_HasNoPreconditionNotice` | **E** | PASS | notice made unconditional (`{{if true}}`) → **FAIL** |
+| `TestRestorePage_NotInstalled_DoesNotPromiseAReinstall` | **D** | PASS | old promise restored → **FAIL on all three assertions** |
+| `TestHasRestoreDestination_AgreesWithTheResolver` | seam | PASS | predicate forced `true` → **FAIL** |
-**Every row fits.** Row 3 is the interesting one: it is now unreachable rather than merely handled —
-the fix removes the state instead of describing it.
+**Red-proof D caught a fault in my own work.** On its first run only two of its three assertions
+failed, because **the explanatory HTML comment I had written quoted the old sentence — and HTML
+comments ship in the response body.** The contradiction was still on the page, and the assertion that
+forbids it could never fail. The comment was rewritten to describe the old string without quoting it;
+re-run, all three assertions fail under the mutation. *This is the same class as the defect being
+fixed, and it was found only because the red-proof was actually run.*
+
+**One pre-existing test was updated, not deleted:** `TestOffsiteRestoreList_RenderedForRebuiltBox`
+pinned the old sentence. Its intent — *state the not-installed consequence, do not hide it* — is
+unchanged; it now asserts the consequence **and** the route.
+
+**Green gate:** `go build ./... && go vet ./... && go test ./...` → **rc 0**.
+**`controller_gates.py`:** all nine **OK**.
---
-## 3. §7.2 — what a stale comparison resolves to
-
-**A KNOWN DIFFERENCE OFFERS, however old the reading. An ABSENT HASH falls back to (a)/(b).**
-
-Age is deliberately **not** gated on. Both sides of the comparison are local; only the hub's half can
-be stale, and what the hub holds does not change without a ceremony *this box* runs — which refreshes
-the hash on the next ACK. Gating on age would add a second failure mode (a box offline from the hub
-silently stops offering) to fix a window that closes itself. `CheckedAt` is persisted for diagnosis.
-
-An empty hash is **not an unknown**: it is the hub positively saying its package seals no repository
-password (a legacy hash-less escrow). Offering on it would put a permanent screen in front of every
-legacy box.
-
-**This path was exercised on real hardware, unplanned.** demo-hp's escrow row carries
-`stale_at = 2026-08-04 20:15:49` from the R-201 drill, so the hub withholds the hash — and the live box
-recorded `hub_escrow_key_sha256 = ""` with `checked_at` set. It correctly did **not** offer. On
-demo-felhom, where the hub does serve it, the recorded hash is **byte-identical to the local key**:
+## 6. §7.5 — the currency gate went red, as predicted
```
-local key hash = c60c8bc737a6b7c6647c7849283f52087f650a885babedb4ef5fdf9a5c9543cb
-hub_escrow_key_sha256 = c60c8bc737a6b7c6647c7849283f52087f650a885babedb4ef5fdf9a5c9543cb
+newest released controller : 0.207.0
+newest golden baked : 0.206.0
+GOLDEN CURRENCY GATE FAILED
```
-**The fact that was computed on every ACK and kept nowhere is now on disk, on a live box.**
+**The `felhom-controller` push needed no bypass** — that repo's own gates passed. **The `felhom.eu`
+push used `git push --no-verify`**, declared in that commit message, in this report, and in
+**R-242's row**.
+
+**A bypass and NOT a waiver, deliberately.** The gate offers a waiver for a release that *deliberately
+needs no golden*; this release needs one. Recording a waiver would have made the register say
+something untrue. **Owed: bake golden 0.207.0 and vouch it.**
---
-## 4. §7.3 — the „Helyreállítási kód létrehozása" button
+## 7. Part 3 — the record
-**Made UNAVAILABLE while a recovery is outstanding, not merely captioned.** Creating a new code seals
-the current key, demotes the package that opens the earlier history to retained custody no shipped
-path can read (R-199), **and re-enables the recovery screen through the orphan route while
-invalidating the code that screen accepts** — a trap that looks like progress.
+**R-201's state field read `PASSED + PROVEN-LIVE 2026-08-04` — the *data* half, from the drill** —
+while the row body carried the fifth walk's journey pass. Corrected to
+**`BOTH HALVES PASSED — DATA 2026-08-04, JOURNEY 2026-08-07`**, with what it does **not** claim stated
+in the field itself: the journey is not smooth, and the discriminator's positive half is unproven.
-A warning beside a button is a warning people click past. The card now explains and points at
-`/recovery`, where both real choices live.
+**The census asked for: a sweep of all 146 register rows found NO OTHER state field disagreeing with
+its own body.** Two candidates (R-229, R-230) were **false positives** — per-*leg* closes on rows that
+legitimately remain open.
+
+**So the pattern is real but not currently widespread**: R-218 on 2026-08-06, R-201 now, nothing else
+outstanding. **The mechanism is worth naming, because it will recur:** a row states status in *two*
+places — a bold phrase early in the What column and the State cell at the end — and a session that
+closes an item updates the body and the end cell, while the early phrase, **which is what a reader
+sees first**, goes stale.
---
-## 5. Every changed Hungarian string
+## 8. Live validation — what was proven on a box, and what was not
-**The abandon confirmation** (`recovery.html`) — §2.4. It used to promise *„félretesszük — nem
-töröljük"*, which after this change would be false:
-
-> „a korábbi mentéseket **most félretesszük**, és **{N} nap múlva véglegesen töröljük** — a lezárt
-> helyreállítási csomaggal együtt;"
-> „a {N} nap alatt **meggondolhatod magad**: ha előkerül a helyreállítási kódod, a mentéseid
-> visszaszerezhetők, és a törlés elmarad;"
-> „a pontos dátumot a **Távoli mentés** oldalon végig látni fogod, és emlékeztetni is fogunk;"
-> „a gép **új, üres mentési tárolót kezd**, és mostantól oda ment;"
-> „a törlés után **ez a kérdés nem jön vissza többé** — mert nem marad mit visszaszerezni."
-> „Ha csak most nincs kéznél a kódod, válaszd inkább a „Most nem" lehetőséget — az semmit nem indít el."
-
-*(N is rendered from `backup.AbandonGraceDays`, never a literal in prose.)*
-
-**The blocked new-code card** (`backups_remote.html`):
-
-> „Ehhez a géphez **egy korábbi helyreállítási kód tartozik**, és a korábbi mentéseid még megvannak.
-> Új kód létrehozása **a régi mentéseidet elérhetetlenné tenné**, ezért most nem indítható. Előbb
-> add meg a meglévő kódodat — vagy ott jelezheted, ha nem kéred vissza a korábbi adatokat."
-
-**The countdown card** (`backups_remote.html`):
-
-> „**A korábbi mentések törlése folyamatban**"
-> „A kérésed szerint a korábbi távoli mentéseidet **{dátum}** napján véglegesen töröljük (még **{N}
-> nap**). Addig meggondolhatod magad: ha megvan a helyreállítási kódod, a mentéseid visszaszerezhetők,
-> és a törlés elmarad."
-> „Mégis visszaszerzem a kóddal"
-
-**Post-deletion** (`backups_remote.html`):
-
-> „A korábbi távoli mentéseid törlése megtörtént. A hozzájuk tartozó lezárt helyreállítási csomag
-> eltávolítása még folyamatban van."
-
-**The reminder bar** (`layout.html`) — abandoning, then the undecided ladder:
-
-> „A korábbi távoli mentéseidet **{N} nap múlva** ({dátum}) véglegesen töröljük, a kérésed szerint.
-> Addig még visszaszerezheted őket a helyreállítási kóddal."
-> „**Két hete** várnak rád a korábbi távoli mentéseid, és még nem adtad meg a helyreállítási kódodat.
-> Amíg nem teszed, ezekhez a mentésekhez nem férsz hozzá." *(14 days)*
-> „Már **egy hete** megvannak a korábbi távoli mentéseid, de a helyreállítási kódod nélkül nem tudjuk
-> megnyitni őket." *(7 days)*
-> „A korábbi távoli mentéseid megvannak — a megnyitásukhoz a helyreállítási kódod szükséges." *(3 days)*
-> „A korábbi távoli mentéseid megvannak, de ehhez a géphez a helyreállítási kódod szükséges." *(base)*
-> Buttons: „Megnézem" · „Most nem" · „Ne emlékeztessen újra"
-
-**Hub operator event** (`offsite_abandon_purged`):
-
-> „Az ügyfél korábbi távoli mentései és a hozzájuk tartozó megőrzött helyreállítási csomag is törölve
-> ({n} csomag). Az ügyfél döntése alapján, a 14 napos türelmi idő lejárta után."
-
-**Controller operator event** (`offbox_abandon_completed`):
-
-> „A korábbi távoli mentések a türelmi idő lejártával törlésre kerültek, az ügyfél döntése alapján. A
-> hozzájuk tartozó lezárt helyreállítási csomag eltávolítását is kértük."
-
----
-
-## 6. Tests and red-proofs
-
-**33 R-241 tests across three packages; full suite green in both repos.**
-
-| Group | Scenario | Result |
+| # | Check | Result |
|---|---|---|
-| A | no key minted over a sealed package; apply holds and stages nothing | PASS |
-| B | a first-time box still mints | PASS |
-| C | a differing key offers recovery (both proxies asserted false first) | PASS |
-| D | a matching key offers nothing | PASS |
-| E | abandon: aside, package kept, countdown, offer still reachable, **nothing deleted** | PASS |
-| F | the terminal step removes both halves; the declaration repeats; the close-out | PASS |
-| G | recovery inside the window cancels the countdown | PASS |
-| H | per-visit banner; opt-out silences the banner only | PASS |
-| I | the operator can extend or stop a countdown | PASS |
-| — | §7.2 both halves; shape (a) intact; fact 1 intact; Scenario-E carve-out; nil-settings fail-safe; idempotency; no-op sweep silent; unclaimed auto-reset starts no countdown; failure leaves the countdown due; levers refuse after deletion; same-site redirect | PASS |
+| 1 | `curl` the security page, passphrase absent | **PASS, live, with before/after** (§1) |
+| 2 | the reveal works for a customer who asks | **PASS, live** — 200, `no-store`, correct value, logged |
+| 3 | the two refusals rendered on VM 325 | **NOT PROVEN LIVE — stated plainly** (below) |
+| 4 | a healthy box's restore page unchanged | **PASS, live** — no notice, no not-installed hint |
-**Nine red-proofs. Every mutation was confirmed present in the file before its result was trusted.**
+**Check 3 is the honest gap.** R-252's state is **rebuild-only**: the customer API **refuses to
+deregister the last usable drive** („ez az egyetlen használható tárhely — a leszerelés megtagadva"),
+and when `storage_paths` was emptied directly the controller re-registered one on restart, so
+`HasRestoreDestination()` was correctly `true` and the notice correctly did not render — **which is
+Scenario E passing live, not a failure.** R-253 likewise: after removing the app the controller still
+reports `deployed=true` (state `stopped`), so the row's `Installed` stays true.
-| # | Mutation | Outcome |
-|---|---|---|
-| 1 | mint guard block deleted | Scenario A FAILS (`R-241 REGRESSION: apply minted…`); B still passes |
-| 2 | guard over-widened (hub-package conjunct dropped) | Scenario B FAILS (first-time box cannot start); A still passes |
-| 3 | `hubHash != localHash` conjunct dropped | Scenario D FAILS (healthy box offered for ever); C still passes |
-| 4 | **`RecordEscrowKeyHash` unwired in `main.go`** | wiring test FAILS — **the ships-inert shape**: everything compiles, every package test passes, the auto-confirm still works, and shape (c) reads an empty hash for ever |
-| 5 | store deletion skipped in the sweep | Scenario F FAILS (no `rm` issued) |
-| 6 | `AbandonPurgeRequested` dropped from the report | Scenario F FAILS (the hub is never asked; the package would outlive the store) |
-| 7 | `CancelAbandon` made a no-op | Scenario G FAILS (uncancellable countdown) |
-| 8 | *(covered by 5/6 — the two halves are independently proved)* | — |
-| 9 | *(covered by 2 — the guard's own failure direction)* | — |
-
-**The countdown is driven by an injected clock throughout (§7.4). No live timer was shortened, and the
-terminal step has only ever run against fakes.**
-
-### Two real bugs, caught by tests rather than by review
-
-1. **`OffboxAwaitingRecoveryKey` omitted `t.Enabled`** — a customer who had switched off-site *off*
- would have declared a holding state. Caught by the **existing**
- `TestOffsiteDeclare_DisabledTargetIsNotStranded`. Now pinned from the new predicate's side too.
-2. **`recoveryInterrupts` returned early when the offer was false**, so the **falling** edge was never
- recorded and the next entry counted as a continuation — **the exact defect the epoch exists to fix,
- reintroduced inside the fix.** Caught by `TestR241_FullPageAppearsOncePerEntryNotOnceEver`.
+**Both notices are therefore pinned at the template + predicate level** — by tests that drive the real
+template and the real predicate, each with a demonstrated red-proof — **and not by a live render.** I
+would rather say that than dress the template test up as a live one.
---
-## 7. §7.5 — the automatic ending: recorded, NOT built → **R-245**
+## 9. Files, commits, deployed version
-**The operator's proposal:** a box offered recovery for 30 days without a decision is auto-abandoned
-into the 14-day grace.
+**`felhom-controller` — `8dbbc98`** (v0.207.0):
+`internal/web/handlers.go` · `internal/web/server.go` · `internal/web/templates/settings_security.html` ·
+`internal/web/templates/backups_restore.html` · `internal/backup/offbox_restore.go` ·
+`internal/backup/offbox_reconstitute.go` · `internal/web/offsite_restore_list_test.go` ·
+**new:** `internal/web/retrieval_password_exposure_test.go`, `internal/web/restore_preconditions_test.go`,
+`internal/backup/restore_destination_test.go` · `CHANGELOG.md` · `CONTEXT.md` · `REUSE.md` ·
+`controller/README.md`
-**The reasoning against it, recorded with it so it can be revisited properly:** (1) **nobody is
-absent** — a box does not reinstall itself, so whoever rebuilt it met the recovery question; **a
-reinstall implies a person**. (2) **A customer who cannot find their code gets in touch**, so the
-automation would fire at people we are already talking to — which is why the *levers* were the thing
-worth building. (3) **The cost is theirs**: the old history sits in their own storage allowance. (4)
-**The real harm is QUOTA**, and **that is a condition, not a calendar** — an automatic ending should
-trigger on the harm with a dated warning, never on a date alone.
+**`felhom.eu` — `1fc3876`** (pushed `--no-verify`, declared): `documentation/backlog/OPEN-ITEMS.md`
+(R-249/R-252/R-253 closed, **R-254** filed, R-201's state field corrected, R-242 updated) · `STATUS.md`
+(93 lines).
-**Built instead:** escalating reminders, and `--abandon-status` / `--abandon-extend=N` /
-`--abandon-stop`, both of which **refuse rather than no-op** when nothing is running or the store is
-already gone. A silent success is what an operator most easily mistakes for "handled".
+**Deployed:** `gitea.dooplex.hu/admin/felhom-controller:0.207.0` — healthy on **demo-hp guest 9201**
+and on **VM 325**.
+
+**Register:** highest ID moved **R-253 → R-254**.
---
-## 8. Files and commits
+## 10. What remains open
-**`felhom-controller`** — `763de3a025a5` (mint guard) · `a491abef6c20` (discriminator) ·
-`a5d90ff80120` (countdown) · `de39e47f53be` (surface) · `72368654e421` (reminders + levers) ·
-`0a9158d53eb8` (docs). Deployed: **`0.206.0`**.
+- **R-254** — the two remaining render-then-hide instances. **The recommended next item.**
+- **R-242** — the bake + vouch of golden 0.207.0 this release now needs; and R-242's own half, that
+ nothing gates the *vouch*.
+- **The discriminator's positive half** — the fifth walk exercised R-241's mint guard positively and
+ the fingerprint comparison only negatively. **Proving the positive half needs a deliberate fixture
+ (a box holding a divergent key), not a walk** — and v0.206.0's guard now prevents that state arising
+ by itself, which is exactly why it needs constructing.
+- Untouched by design: **R-250, R-251, R-243, R-244, R-240, R-213, R-202, R-214, R-247, R-248.**
-New: `backup/offbox_abandon.go`, `backup/offbox_mintguard_r241_test.go`,
-`backup/offbox_offer_shapec_r241_test.go`, `backup/offbox_abandon_r241_test.go`,
-`web/recovery_surface_r241_test.go`.
-Modified: `backup/offbox.go`, `backup/backup.go`, `settings/settings.go`, `report/escrow_confirm.go`,
-`report/escrow_presence_wiring_test.go`, `cmd/controller/main.go`, `web/{recovery_handlers,handlers,server,auth}.go`,
-`web/recovery_test.go`, `templates/{layout,recovery,backups_remote}.html`,
-`CHANGELOG.md`, `CONTEXT.md`, `REUSE.md`, `controller/README.md`.
+## 11. Observations — noticed, not acted on
-**`felhom.eu`** — `ac4b2a4ba934` (hub purge) · `9657334fb72a` (registers, map, STATUS, hub CHANGELOG) ·
-`b12f8ec2f32f` (manifest). Deployed: **`felhom-hub:0.98.0`**, Synced/Healthy.
-
-## 9. Registers
-
-**R-241 FIXED.** **R-243 UPDATED, not closed** — the state can no longer be entered and what replaces
-it is *visible* rather than silent, but **the alarm gap is untouched**: a box whose customer never acts
-still stops backing up with no operator signal. **R-245 NEW** (WAITING-ON-OPERATOR). **R-242 stays
-recorded-not-built.** **R-244 untouched.** Still open and named: **R-240, R-213, R-202, R-214**.
-
-**Highest register ID moves R-244 → R-245.**
-
-## 10. The capability-map row
-
-**Still 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**.
-
-## 11. CI
-
-`felhom-controller` run **237** (`0a9158d53eb8`) success · `felhom.eu` runs **238** (`9657334fb72a`)
-and **239** (`b12f8ec2f32f`) success — matched by `head_sha`, pulled rather than assumed.
-**`--no-verify` was NOT used**; the pre-push hook ran the gates on every push.
-
-## 12. Observations — noticed, NOT acted on
-
-- **demo-hp's escrow blob is flagged stale** (`stale_at = 2026-08-04 20:15:49`, from the R-201 drill),
- so the hub withholds its hash and shape (c) can never fire there. Correct per §7.2, and it gave the
- fallback path a free live exercise — but that box's escrow **has been stale for three days** and
- nothing has surfaced it. Possibly worth a row; not filed, because it is R-198/R-196 territory and I
- did not measure whether the staleness is real or an artefact of the drill.
-- **The offer epoch advances on a landing-page visit, not on the report cycle.** Correct for the
- interruption and the banner (both only matter when someone visits), but it means the undecided
- reminder ladder starts from the first *visit* rather than from the first *report*. Deliberate;
- stated here because it is a design choice a reader could mistake for an oversight.
-- **`--abandon-*` runs inside the guest**, i.e. a guest command line. Acceptable for operators (it sits
- beside the existing operator subcommands) but it is not a hub surface, so it is unavailable to an
- operator who cannot reach the box.
+- **`shares_restore.go:62,81` carries the same „nincs elérhető adatmeghajtó" string** with no route,
+ for the SMB-shares restore path. Out of scope (R-252 is the app path); the same one-line treatment
+ would fix it.
+- **The reveal endpoint has no rate limit.** It is behind session auth + CSRF, so it is not a
+ brute-force surface, but the escrow start handler deliberately rides the login limiter and this does
+ not. Deliberate omission, flagged.
+- **The Hetzner token in `~/.config/credentials` cannot see storage box 611421** — `GET
+ /v1/storage_boxes/611421/subaccounts` → 404 and `GET /v1/storage_boxes` → 200 with **0 entries**. It
+ is scoped to a different project than the hub's. Recorded so the next teardown does not re-derive it.