R-294/R-295: orphan card stops promising restorability; one name per secret
gates / gates (push) Successful in 14s

The orphan card told a customer their set-aside off-site history may be
restorable later with their recovery code. The discriminator lives on the hub
and no wire field carries it, so the box rendering that card cannot evaluate the
promise. Copy replaced per the spec: state what happens, decline what we cannot
know and say why, name a route.

The claim page called the same three-word dashboard code two different names
depending on branch, one of which collides with the ten-word escrow code.
Retired 'Visszaallito kod'; the name is now constant and the sentence changes.
Naming only - a test pins that a reset code is still accepted.

secret_in_markup_gate no longer convicts Go template comments, which are
stripped before render; still convicts a real rendered secret.
This commit is contained in:
2026-08-10 13:53:21 +02:00
parent b762a37097
commit 86a78c6767
7 changed files with 276 additions and 7 deletions
@@ -98,7 +98,16 @@
<p class="form-hint" style="margin:0 0 .5rem">A távoli tárhelyen lévő mentések egy korábbi, már nem elérhető kulccsal készültek (jellemzően újratelepítés után). Emiatt új mentés jelenleg nem írható a tárolóba. A meglévő mentések nem sérültek — a hozzájuk tartozó helyreállítási kóddal később visszaállíthatók lehetnek.</p>
<button type="button" class="btn btn-sm btn-outline" id="orphan-reveal" onclick="var c=document.getElementById('orphan-confirm');c.style.display='block';this.style.display='none'">Új távoli mentés indítása…</button>
<div id="orphan-confirm" style="display:none;margin-top:.6rem">
<p class="form-hint" style="margin:0 0 .5rem">A régi előzmény <strong>félretéve marad</strong> (nem törlődik), és a hozzá tartozó helyreállítási kóddal később visszaállítható lehet. Egy üres, új tároló jön létre a mostani kulccsal, és a következő mentés ide készül.</p>
{{/* R-294 / R-202: this paragraph promised the set-aside copies "may be restorable later
with the recovery code". The discriminator is host_escrow_superseded.identity_blob,
which lives on the HUB; the box caches only HubEscrowIdentityPresent (about the
CURRENT escrow) and no report or ACK field carries superseded-blob retention. So the
renderer cannot evaluate the condition it was stating — and a conditional promise the
system cannot evaluate is the same defect as an unconditional false one. It now
states what it knows, declines what it does not, and names a route.
Copy is verbatim from documentation/design/SPEC-orphan-card-copy-2026-08-10.md §4. */}}
<p class="form-hint" style="margin:0 0 .5rem">A régi előzmény <strong>félretéve marad a tárhelyen — nem töröljük</strong>. Új, üres tárolót hozunk létre, és a következő mentés oda készül.</p>
<p class="form-hint" style="margin:0 0 .5rem"><strong>A félretett mentések megnyithatóságát itt nem tudjuk megígérni.</strong> Ez attól függ, megvan-e még a hozzájuk tartozó kulcs, és ezt ez a gép nem tudja megállapítani. Ha szeretnéd, hogy utánanézzünk, <strong>írj nekünk</strong> — a félretett másolat addig is a helyén marad.</p>
<form method="POST" action="/backup/offbox/reset" style="display:inline">{{.CSRFField}}
<input type="hidden" name="confirm" value="1">
<button type="submit" class="btn btn-sm btn-primary">Megerősítés — új távoli mentés indítása</button>
+12 -3
View File
@@ -16,14 +16,23 @@
{{if .Flash}}<div class="alert alert-info">{{.Flash}}</div>{{end}}
{{if .Error}}<div class="alert alert-error">{{.Error}}</div>{{end}}
{{/* R-295 — ONE NAME PER SECRET. This page used to call the SAME three-word code „Beállító
kód" on the first-time branch and „Visszaállító kód" on the reset branch, while the
TEN-word code that opens the sealed backups is called „Helyreállítási kód" elsewhere in
this UI. Two of those three names are near-homographs, and the collision cost a real code.
The ruling: the code that gives a person control of the DASHBOARD is „Beállító kód"
everywhere — the name this page already showed where it is typed — and where one secret
serves two situations the NAME stays constant and the SENTENCE changes. „Visszaállító
kód" is retired. This is naming only: no acceptance logic moved, and a test pins that a
reset code is still accepted here. */}}
{{if .HasCode}}
<p style="font-size:0.85rem;color:var(--text-muted,#8a94a6);margin:0 0 1rem">
{{if .IsReset}}Add meg az e-mailben kapott visszaállító kódot, majd válassz új jelszót.{{else}}Add meg az e-mailben kapott beállító kódot, majd válassz saját jelszót a vezérlőpult védelméhez.{{end}}
{{if .IsReset}}Add meg az e-mailben kapott beállító kódot, majd válassz új jelszót.{{else}}Add meg az e-mailben kapott beállító kódot, majd válassz saját jelszót a vezérlőpult védelméhez.{{end}}
</p>
<form method="POST" action="/claim">
<input type="hidden" name="_csrf" value="{{.ClaimCSRF}}">
<div class="form-group">
<label for="code">{{if .IsReset}}Visszaállító kód{{else}}Beállító kód{{end}}</label>
<label for="code">Beállító kód</label>
<input type="text" id="code" name="code" required autofocus autocomplete="off"
placeholder="szó-szó-szó" class="form-control">
</div>
@@ -45,7 +54,7 @@
<form method="POST" action="/claim/request-new-code" style="margin-top:1rem">
<input type="hidden" name="_csrf" value="{{.ClaimCSRF}}">
<button type="submit" class="btn btn-outline btn-full">{{if .IsReset}}Visszaállító kód kérése{{else}}Nem kaptad meg a kódot? Új kód kérése{{end}}</button>
<button type="submit" class="btn btn-outline btn-full">{{if .IsReset}}Új beállító kód kérése{{else}}Nem kaptad meg a kódot? Új kód kérése{{end}}</button>
</form>
<p class="login-footer">Felhom — Otthoni szerver kezelés<br>