v0.207.0 — R-249: the retrieval passphrase leaves the page body; R-252/R-253: two refusals learn to say what to do
gates / gates (push) Successful in 18s
gates / gates (push) Successful in 18s
R-249. settings_security.html rendered the passphrase into a display:none span behind a Megjelenit button. That toggle stops a browser DRAWING the value and nothing else — the plaintext was in the response body of every render, so a curl of the page returned it. Found by exactly that: it landed in a session transcript while driving the documented rebuild path. The codebase already stated this rule for the recovery code and this page did not follow it (escrow_handlers.go: 'reveal (claim XHR only — R is NEVER templated server-side into HTML)'). The page now carries only HasRetrievalPassword; the value comes from POST /settings/retrieval-password/reveal — CSRF-covered because POST, no-store, and LOGGED as an act, which reading it off the markup never was. The tests assert the RAW RESPONSE BODY. Every test that asked what the customer sees passed while the bytes carried the secret; that is why this survived. Census: the render-then-hide pattern appears twice more — app_info.html (a real per-install app password in a hidden span) and deploy.html. Filed as R-254, NOT fixed here. R-252. A rebuilt box keeps its drives but loses their REGISTRATION. The restore page now states that before the customer presses anything, says the backups and drives are both still there, and links to Tarhely > Meghajtok. Page and resolver ask ONE question — HasRestoreDestination() reads the same GetSchedulableStoragePaths() the scratch resolver reads. R-253. The list promised 'a visszaallitas elobb ujratelepiti' three lines above a refusal that fired BECAUSE the app was not installed. The promise was the wrong half: reconstitution writes to the app's own GetStackHDDPath, which exists only once the CUSTOMER has chosen a drive at deploy time. Auto-reinstalling would mean the product making that choice for them. Copy now says to install first and routes to /stacks/<app>/deploy. Both notices are conditional — a healthy box renders as before, pinned by a test that fails if either becomes unconditional.
This commit is contained in:
+32
-1
@@ -7,7 +7,38 @@
|
||||
>
|
||||
> Ask Claude Code: "Please update CONTEXT.md with what we did today"
|
||||
|
||||
Last updated: 2026-08-07 (v0.206.0 — R-241: the box does not mint a key over a sealed package)
|
||||
Last updated: 2026-08-08 (v0.207.0 — R-249/R-252/R-253: a secret leaves the page source, two refusals learn to say what to do)
|
||||
|
||||
> **2026-08-08 — v0.207.0 (R-249, R-252, R-253). Three things the fifth walk exposed BY PASSING.**
|
||||
> The walk closed R-201 (both halves) on 2026-08-07; none of the below touches the recovery path it
|
||||
> proved.
|
||||
>
|
||||
> **R-249 — a secret was living in the page source.** `settings_security.html` rendered the retrieval
|
||||
> passphrase into a `display:none` span behind a „Megjelenít" button. That toggle stops a browser
|
||||
> DRAWING it and nothing else: the plaintext was in the response body of every render. Found by doing
|
||||
> exactly that — it landed in a session transcript while driving the documented rebuild path.
|
||||
> **THE RULE, which the codebase already stated for R and this page did not follow:** a secret is
|
||||
> revealed by an XHR, never templated server-side into HTML (`escrow_handlers.go`). The page now
|
||||
> carries only `HasRetrievalPassword`; the value comes from `POST /settings/retrieval-password/reveal`
|
||||
> — CSRF-covered, `no-store`, and **logged as an act**, which reading it off the markup never was.
|
||||
> **The test asserts the RAW RESPONSE BODY** — every test that asked what the customer *sees* passed
|
||||
> while the bytes carried the secret, and that is why it survived.
|
||||
> **The census found two more instances** (`app_info.html`, a real per-install app password in a
|
||||
> `hidden` span; `deploy.html`, a generated secret in a `value=`) — **filed as R-254, not fixed.**
|
||||
>
|
||||
> **R-252 / R-253 — the two obstacles, and the rule they share.** A rebuilt box keeps its drives but
|
||||
> loses their REGISTRATION, so every restore refused with a sentence naming no next step; and the
|
||||
> restore list promised „a visszaállítás előbb újratelepíti" three lines above a refusal that fired
|
||||
> *because* the app was not installed. **The promise was the wrong half:** reconstitution writes to
|
||||
> the app's own `GetStackHDDPath`, which exists only once the CUSTOMER has chosen a drive at deploy
|
||||
> time — an automatic reinstall would mean the product making that choice for them, which is the one
|
||||
> decision this recovery path exists to leave with them. Both now name a reason and route to the step
|
||||
> that clears it, and both notices are conditional (a healthy box is byte-identical, pinned by a test
|
||||
> that fails if either becomes unconditional).
|
||||
>
|
||||
> **The page and the resolver ask ONE question:** `HasRestoreDestination()` reads the same
|
||||
> `GetSchedulableStoragePaths()` the scratch resolver reads. A second copy of that predicate is
|
||||
> exactly how a page ends up promising what the handler refuses — which is R-253 itself.
|
||||
|
||||
> **2026-08-07 — v0.206.0 (R-241). THE RULING, and it reversed the fix: this was a MINTING defect,
|
||||
> not a screen-predicate defect.** The recovery screen was telling the truth — there genuinely was
|
||||
|
||||
Reference in New Issue
Block a user