Files
felhom.eu/documentation/audits/i18n-slice2-2026-09-18/C/parity-exception-diff.txt
T
admin 95c10954ae
gates / gates (push) Successful in 23s
docs: localisation slice 2 CLOSED (controller v0.254.0) — R-577, R-578, and a probe rule
10-localisation.md §10.3: the saved notes follow the box language at write time, with the
one-night consequence stated rather than hidden; the globe, and the table of WHO reads which
page and where its globe posts — getting that wrong makes the button do nothing, which it did
on /recovery until the live probe found it. Decision 6 superseded a second time; decision 8
(a claim carries the visitor's language) recorded. Decision 5 of §11's anonymous-surface line:
changing what a VISITOR reads is within what an anonymous request may do; changing anything the
household owns is not, and POST /lang can do only the first.

R-578 — the deadlock, and why it is a row rather than a fixed bug: UpdateOffboxStatus holds the
settings write lock while running its callback, boxLang() wants the read lock, sync.RWMutex is
not reentrant. On a real box an off-site run would have hung FOREVER holding that lock. The
symptom was a test suite going from 8 minutes to a 25-minute timeout. Fixed and guarded, but the
guard covers one package and three helper names; the class needs a gate.

R-577 — a guest share visitor still has no way to pick a language, and the household's setting
is the wrong default for a stranger. Deliberately left, pinned by a test, and the operator's to
decide because it is a promise the share feature makes.

.claude/rules/live-probes.md, unconditional: never send a deploy request for an app that is not
installed, not even expecting a refusal — the endpoint accepts first and validates later. Two
sessions made that mistake in two days, the second WITH a prompt line forbidding it. A prompt is
read once; a rule file is loaded every session.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-18 14:31:49 +02:00

47 lines
4.3 KiB
Plaintext

PARITY EXCEPTIONS — controller v0.254.0 (R-557 slice 2 release C)
Every Hungarian fixture rendered NOW, against the fixture as it stood at eb6aa58 (v0.253.0) —
itself captured from the UNCONVERTED templates and never regenerated to make a conversion pass.
A real diff (LCS), not a line-index compare: the globe ADDS lines, and a line-index compare calls
every line below an insertion changed, which measures nothing (redproofs.txt, catch D).
The per-session CSRF token is blanked on both sides — it is random per session and can never be
a fixture value; what is still pinned is that the field is THERE and WHICH form it sits in.
[89 fixtures] e.g. app_export.html, app_import_bundles.html, app_import_empty.html
- <span class="version">0.247.0</span><form method="POST" action="/settings/language" class="lang-switch"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="hu" class="lang-sw
+ <span class="version">0.247.0</span><details class="lang-globe">
+ <summary class="lang-globe-btn" aria-label="Nyelv" title="Nyelv"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx=
+ <ul class="lang-globe-menu">
+ <li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="CSRF"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="hu" lang="hu" class="lang-globe
+ <li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="CSRF"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="en" lang="en" class="lang-globe
+ </ul>
+</details>
[7 fixtures] e.g. recovery_locked_can.html, recovery_locked_cannot.html, recovery_locked_confirm.html
+ <div class="shell-lang"><details class="lang-globe">
+ <summary class="lang-globe-btn" aria-label="Nyelv" title="Nyelv"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx=
+ <ul class="lang-globe-menu">
+ <li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="CSRF"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="hu" lang="hu" class="lang-globe
+ <li><form method="POST" action="/settings/language"><input type="hidden" name="_csrf" value="CSRF"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="en" lang="en" class="lang-globe
+ </ul>
+</details></div>
[5 fixtures] e.g. claim_reset_code.html, claim_reset_nocode.html, claim_setup_code.html
+ <div class="shell-lang"><details class="lang-globe">
+ <summary class="lang-globe-btn" aria-label="Nyelv" title="Nyelv"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx=
+ <ul class="lang-globe-menu">
+ <li><form method="POST" action="/lang"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="hu" lang="hu" class="lang-globe-item current" aria-current="true">Magyar</button></form></l
+ <li><form method="POST" action="/lang"><input type="hidden" name="back" value="/i18n-fixture"><button type="submit" name="lang" value="en" lang="en" class="lang-globe-item">English</button></form></li>
+ </ul>
+</details></div>
[5 fixtures] IDENTICAL — not one byte moved: catchall_app.html, catchall_unknown.html, launcher_share_password.html, launcher_shared_apps.html, launcher_shared_empty.html
DISTINCT CHANGE SHAPES: 3.
The release declares TWO blocks — the dashboard footer, and the globe on the pages outside the
dashboard chrome. The second has two forms, because WHO reads the page decides where its globe
posts: /recovery is an AUTHENTICATED route so its reader is the household and writes their
setting; /login and /claim are met with no session and write the visitor's own cookie. The five
untouched fixtures are exactly the pages that must not change: both guest share pages and the
catch-all (R-577).