R-225/R-227/R-228 Parts 2-4: unknown is not zero, the gateway speaks Hungarian, the set-aside is visible
R-225 — an unread store said '0 pillanatkép / 0 / 50 GB' above a card stating it held backups under another key. An SFTP listing found snapshot f3d9cd67 and 12 535 KB really there; snapshot_count and repo_size_bytes were simply ABSENT and the zero value spoke for them. StatsKnown is now NAMED, for the same reason OffsiteInventory.Empty is: zero is what an unread store and an empty one both look like, and on the wire 'absent' and '0' are the same bytes. The fill bar renders only when the fill is known — a 0%-wide bar is a picture of emptiness, and a picture is a claim. A measured zero still says zero. R-227 — WHICH LAYER ANSWERS: traefik, and this repo generates its config. But traefik v3 serves no static files, so a branded proxy page needs a new always-up container for every 502 on the box — out of proportion, and scoped in the report rather than built. Shipped instead: the unlock posts via fetch and answers a gateway failure in Hungarian without leaving the page. Progressive enhancement — with no JS the plain POST is unchanged and still shows the proxy's error, which the report says plainly rather than implying otherwise. R-228 — the set-aside history was recorded in orphaned_renamed_to and read by nobody: a census found zero references in any template or handler, while 12 535 KB sat at that path. It is surfaced as two facts and stops. It does NOT promise the history can be reopened, because it cannot be by anyone today (R-199's inventory is unbuilt) — and the set-aside CONFIRMATION copy was corrected for the same reason: 'a helyreállítási kód nélkül többé nem lesznek megnyithatók' implied that WITH the code they could be. The field's own comment called it 'recovery-code-recoverable', which was the same over-promise in the code. Tests: scenarios F, G, H as render tests per branch of each gate. Red-proofs, each demonstrated failing then restored: remove the StatsKnown guards (F, 'R-225 RETURNED: an unread store reports a snapshot COUNT of zero'), delete the set-aside block (H). The F assertion on the fill bar is scoped to the bar's own container — a bare width:0% search matched unrelated elements and would have passed for the wrong reason. 28 packages ok, vet clean, all controller gates OK (the emoji gate caught a warning sign in a template comment).
This commit is contained in:
@@ -242,3 +242,38 @@ func TestClassifyRecoveryFailure_MapsFromTheValueNotTheText(t *testing.T) {
|
||||
t.Fatal("classification followed the TEXT — it must follow the status")
|
||||
}
|
||||
}
|
||||
|
||||
// ── SCENARIO G (R-227) — A RESTART MID-UNLOCK IS ANSWERED IN HUNGARIAN ──────────────────────────
|
||||
//
|
||||
// Measured 2026-08-05 (CAMPAIGN-11 F8): the controller was restarted 0.7 s into an unlock and the
|
||||
// customer got traefik's raw English `Bad Gateway`. The state was clean; the page was not.
|
||||
//
|
||||
// The layer that answers is traefik, whose config this repo generates — but traefik v3 serves no
|
||||
// static files, so a branded proxy page would need a new always-up container for every 502 on the
|
||||
// box. What ships is the second sanctioned option: the unlock posts via fetch and answers a gateway
|
||||
// failure in the page. This asserts the handling is PRESENT and says the right thing; with no JS the
|
||||
// plain POST is unchanged and still shows the proxy's error, which the report states plainly.
|
||||
func TestRecoveryClass_G_GatewayErrorIsAnsweredInHungarian(t *testing.T) {
|
||||
f := newRecoveryFixture(t)
|
||||
body := getRecoveryPage(t, f.s).Body.String()
|
||||
|
||||
// RED-PROOF: delete the fetch handler from recovery.html → this FAILS, and a restart mid-unlock
|
||||
// shows `Bad Gateway` again.
|
||||
if !strings.Contains(body, "unlock-gateway-error") {
|
||||
t.Fatal("R-227 RETURNED: the page carries no handling for a gateway failure")
|
||||
}
|
||||
if !strings.Contains(body, "A gép éppen újraindul") {
|
||||
t.Fatal("the gateway message must say, in Hungarian, that the machine is restarting")
|
||||
}
|
||||
if !strings.Contains(body, "resp.status >= 500") {
|
||||
t.Fatal("a 5xx from the proxy must be caught, not rendered")
|
||||
}
|
||||
// It must claim NOTHING about the code — whether it was used is unknown at that point.
|
||||
if namesTyping(body) && !strings.Contains(body, "Helyreállítási kód (tíz szó)") {
|
||||
t.Fatal("the gateway path must not blame the code")
|
||||
}
|
||||
// Progressive enhancement: the plain form must survive for a JS-less browser.
|
||||
if !strings.Contains(body, `method="POST" action="/recovery/unlock"`) {
|
||||
t.Fatal("the plain POST form must remain for browsers without JS")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user