Files
felhom-controller/controller/internal/web/templates/claim.html
T
admin 48f3336956
gates / gates (push) Successful in 23s
v0.254.0 — the saved notes follow the language, and the switch becomes a globe (R-557 slice 2 release C; SLICE 2 CLOSED)
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
2026-09-18 14:19:31 +02:00

66 lines
4.0 KiB
HTML

{{define "claim"}}
<!DOCTYPE html>
<html lang="{{T "layout.html_lang"}}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{if .IsReset}}{{T "claim.jelszo_visszaallitasa"}}{{else}}{{T "claim.a_szerver_beallitasa"}}{{end}} — Felhom</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body class="login-body">
<div class="shell-lang">{{template "lang_globe" .}}</div>
<div class="login-card">
<img src="/static/felhom-logo.svg" alt="Felhom.eu" class="login-logo">
<h1 class="login-title">{{if .IsReset}}{{T "claim.jelszo"}} <span class="title-accent">{{T "claim.visszaallitasa"}}</span>{{else}}{{T "claim.a_szerver"}} <span class="title-accent">{{T "claim.beallitasa"}}</span>{{end}}</h1>
<p class="login-subtitle">{{.CustomerName}}</p>
{{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}}{{T "claim.add_meg_az_e_mailben"}}{{else}}{{T "claim.add_meg_az_e_mailben_2"}}{{end}}
</p>
<form method="POST" action="/claim">
<input type="hidden" name="_csrf" value="{{.ClaimCSRF}}">
<div class="form-group">
<label for="code">{{T "claim.beallito_kod"}}</label>
<input type="text" id="code" name="code" required autofocus autocomplete="off"
placeholder="{{T "claim.szo_szo_szo"}}" class="form-control">
</div>
<div class="form-group">
<label for="new_password">{{T "claim.uj_jelszo_min_karakter"}}</label>
<input type="password" id="new_password" name="new_password" required minlength="{{.MinPassword}}"
placeholder="{{T "claim.legalabb_karakter"}}" class="form-control">
</div>
<div class="form-group">
<label for="confirm_password">{{T "claim.uj_jelszo_megerositese"}}</label>
<input type="password" id="confirm_password" name="confirm_password" required minlength="{{.MinPassword}}"
placeholder="{{T "claim.jelszo_megegyszer"}}" class="form-control">
</div>
<button type="submit" class="btn btn-primary btn-full">{{if .IsReset}}{{T "claim.jelszo_beallitasa"}}{{else}}{{T "claim.beallitas_es_belepes"}}{{end}}</button>
</form>
{{else}}
<div class="alert alert-info">{{T "claim.jelenleg_nincs_aktiv_kod_ehhez"}}</div>
{{end}}
<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}}{{T "claim.uj_beallito_kod_kerese"}}{{else}}{{T "claim.nem_kaptad_meg_a_kodot"}}{{end}}</button>
</form>
<p class="login-footer">{{T "claim.felhom_otthoni_szerver_kezeles_felhom"}}</p>
</div>
</body>
</html>
{{end}}