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:
@@ -172,7 +172,7 @@ func (s safetyDumpSet) First() string {
|
||||
// failed restore on a machine that may be unwell, and the honest claim available here is presence.
|
||||
// A zero-length file is reported as MISSING — a 0-byte dump restores nothing, and calling it present
|
||||
// is the same false reassurance one step smaller.
|
||||
func undoCopyPhrase(set safetyDumpSet) string {
|
||||
func (m *Manager) undoCopyPhrase(set safetyDumpSet) string {
|
||||
var present, absent []string
|
||||
for _, f := range set.Files {
|
||||
if f.Path == "" {
|
||||
@@ -186,16 +186,15 @@ func undoCopyPhrase(set safetyDumpSet) string {
|
||||
}
|
||||
switch {
|
||||
case len(present) > 0 && len(absent) == 0:
|
||||
return "a korábbi állapot mentése megvan: " + strings.Join(present, ", ")
|
||||
return m.note("note.undo.present", strings.Join(present, ", "))
|
||||
case len(present) > 0:
|
||||
// Partial: name both halves. An app with two databases whose undo is half there is a
|
||||
// different situation from either whole one, and support must not have to guess which.
|
||||
return "a korábbi állapot mentése RÉSZBEN van meg — megvan: " + strings.Join(present, ", ") +
|
||||
"; HIÁNYZIK: " + strings.Join(absent, ", ")
|
||||
return m.note("note.undo.partial", strings.Join(present, ", "), strings.Join(absent, ", "))
|
||||
case len(absent) > 0:
|
||||
return "a korábbi állapot mentését NEM találjuk a helyén (" + strings.Join(absent, ", ") + ")"
|
||||
return m.note("note.undo.absent", strings.Join(absent, ", "))
|
||||
default:
|
||||
return "a korábbi állapotról nem készült menthető másolat"
|
||||
return m.note("note.undo.none")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +340,7 @@ func (m *Manager) RestoreHoldFor(stack string) (bool, string) {
|
||||
// Slice 4: one storage, two reasons. An update hold names the copy it can be restored from; a
|
||||
// restore hold names nothing, because the restore it refers to already consumed the copy.
|
||||
if h.Reason == settings.HoldReasonUpdateFailed {
|
||||
copyDate := "legutóbbi"
|
||||
copyDate := m.note("note.reconstitute.copy_latest")
|
||||
if h.CopyDate != "" {
|
||||
copyDate = fmtHoldTime(h.CopyDate)
|
||||
}
|
||||
@@ -358,8 +357,7 @@ func (m *Manager) RestoreHoldFor(stack string) (bool, string) {
|
||||
if t, err := time.Parse(time.RFC3339, h.At); err == nil {
|
||||
when = t.Format("2006-01-02 15:04")
|
||||
}
|
||||
return true, fmt.Sprintf("a(z) %s adatainak visszaállítása %s-kor megszakadt, és a korábbi állapotot sem sikerült visszatölteni. "+
|
||||
"Az alkalmazás biztonsági okból leállítva marad, hogy az adatai ne sérüljenek tovább. Vedd fel velünk a kapcsolatot", stack, when)
|
||||
return true, m.note("note.reconstitute.held", stack, when)
|
||||
}
|
||||
|
||||
// holdAppAfterFailedRollback records the R-379/R-380 hold and makes sure nothing restarts the app
|
||||
@@ -810,7 +808,7 @@ func (m *Manager) ReconstituteFromOffsite(ctx context.Context, stack string, ack
|
||||
// R-383: the undo copy is DESCRIBED FROM DISK, never from the path alone. See
|
||||
// undoCopyPhrase — this sentence used to assert the file existed in exactly the
|
||||
// branch where a missing file is one of the two causes.
|
||||
return res, util.MsgError("err.backup.db_restore_and_rollback_failed", stack, undoCopyPhrase(safetySet))
|
||||
return res, util.MsgError("err.backup.db_restore_and_rollback_failed", stack, m.undoCopyPhrase(safetySet))
|
||||
}
|
||||
res.RolledBack = true
|
||||
if sErr := restartStack(); sErr != nil {
|
||||
|
||||
Reference in New Issue
Block a user