v0.254.0 — the saved notes follow the language, and the switch becomes a globe (R-557 slice 2 release C; SLICE 2 CLOSED)
gates / gates (push) Successful in 23s
gates / gates (push) Successful in 23s
The notes a background run SAVES — last night's backup line, the last error, the proof result, the restore outcome — are written in the BOX's language at the moment they are written. A household that switches sees the previous run's note in the old language until the next run rewrites it: the operator's §16 option 1, stated rather than hidden. EndRestoreOp no longer receives a Hungarian literal from anywhere. The language switch is a globe. Two text links wrapped in the sidebar footer and asked the reader to recognise "Magyar"/"English" as links; a globe is the one symbol every web user already reads as "language", so nobody has to read Hungarian to escape Hungarian. It is <details>/<summary> — a menu with no script, drawn inline because the icon sprite lives only in layout.html and the visitor pages have their own shell. Those visitor pages get the same globe, and a visitor's choice stays theirs: a display-only felhom_lang cookie that langFor reads ONLY when there is no session. A signed-in household can never inherit a language a previous visitor picked in the same browser. POST /lang is CSRF-exempt for a narrow reason written at the exemption — its only achievable effect is the language of the page the victim's own browser shows them — and safeBackPath refuses //evil.example as well as https://, because "starts with /" alone is not the test. §16 taken: a successful claim carries the cookie into the household's setting. TWO PARITY EXCEPTIONS, MEASURED: 106 fixtures compared with a real diff — exactly two change shapes (the dashboard footer, the globe in the shells) and 5 byte-identical, which are the three pages that must not change. I INTRODUCED A DEADLOCK AND THE SUITE CAUGHT IT BY HANGING. 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 the settings lock. Fixed by resolving the language before the callback, and guarded by a test that names the file and line in a second instead of hanging for 25 minutes. MinAgent: 0.131.0 (unchanged). No hub release needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/i18n"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -246,6 +247,11 @@ func claimPageAllowedPath(path string) bool {
|
||||
switch path {
|
||||
case "/claim", "/claim/request-new-code", "/api/health":
|
||||
return true
|
||||
case langCookiePath:
|
||||
// The claim page carries the language globe, so its switch has to work on an unclaimed box —
|
||||
// which is precisely the box whose first visitor may not read Hungarian (v0.254.0, R-557).
|
||||
// It sets a display-only cookie and can do nothing else; see langCookieHandler.
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(path, "/static/")
|
||||
}
|
||||
@@ -390,6 +396,23 @@ func (s *Server) handleClaimSubmit(w http.ResponseWriter, r *http.Request) {
|
||||
// flips in seconds — the operator sees the customer claim land immediately.
|
||||
s.reportTriggerNow()
|
||||
s.claimClearFailures(ip)
|
||||
|
||||
// §16 (operator default, v0.254.0): the claim CARRIES the visitor's language. Someone who switched
|
||||
// the claim page to English and then claimed the box chose English deliberately; the first
|
||||
// dashboard they see should be in it, and the hub's e-mails will follow once slice 3 lands.
|
||||
//
|
||||
// Only here, and only on SUCCESS: this is the one moment an anonymous visitor becomes the
|
||||
// household, so it is the one moment their display cookie may become the household's setting.
|
||||
// Every other anonymous request leaves settings.json alone (langFor, CsrfProtect).
|
||||
if c, err := r.Cookie(langCookieName); err == nil && i18n.IsSupported(c.Value) {
|
||||
if err := s.settings.SetLanguage(c.Value); err != nil {
|
||||
// Not fatal: the box is claimed either way, and the household can switch on the dashboard.
|
||||
s.logger.Printf("[WARN] [web] claim: could not carry the visitor's language %q: %v", c.Value, err)
|
||||
} else {
|
||||
s.logger.Printf("[INFO] [web] claim: household language set to %q from the claim page", c.Value)
|
||||
}
|
||||
}
|
||||
|
||||
s.invalidateAllSessions() // reset: kill old sessions; first-claim: none exist
|
||||
|
||||
action := "claimed"
|
||||
|
||||
Reference in New Issue
Block a user