Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
4.7 KiB
R-79 — health issue and warning text on the household's pages and mail: a one-page design (2026-10-08)
Status: design only. Read in source today (controller main a0370b4ed8ef, hub main b2dce901b2). Architecture
document: architecture/10-localisation.md (§9 „compared, not shown", §10.1 „on the wire = not translated",
§10.6b residue table).
The row is half stale — what moved since it was filed
The row (filed 2026-07-26) says „every producer is English" and asks for a spike to pick the seam. The seam was picked
and built by R-516 item 10 (controller, after 0.252.0): the wire text stays frozen (internal/monitor/wire_golden_test.go)
and each entry carries a parallel MsgRef (bundle key + args) that the dashboard banner renders in the household's
language (internal/monitor/healthcheck.go:28-35, 73-86; internal/web/alerts.go:238-279, MessageKey/MessageArgs
rendered by GetAlerts(lang)). That is the render-boundary seam, and it is the right one: the hub report keeps its bytes.
Done (key attached, pinned by internal/monitor/r516_resource_msgs_test.go): all 7 resource entries —
system/data disk high + critical, memory, CPU, temperature (healthcheck.go:357-441).
Still verbatim on the household's banner (zero MsgRef):
| producer | healthcheck.go |
wire text | what a household sees |
|---|---|---|---|
| Docker unreachable | 138 | Docker: %v (English) |
English in both languages |
| protected container down | 157 | Protected container not running: %s (English) |
English in both languages |
| storage almost full (issue) | 170 via checkStoragePaths 336 |
issueFmtStorageAlmostFull (Hungarian, frozen) |
Hungarian for an English household |
| storage unavailable / not separate / usage high (warnings) | 173 via 322, 328, 338 | warnFmtStorage* (Hungarian, frozen) |
Hungarian for an English household |
(The disconnected-drive warning is already replaced by its own banner, alerts.go:254-261.)
The mail half, not covered by R-516: health_critical is customer-on by default
(controller internal/settings/settings.go:635). The controller sends HealthDetails{issues, warnings} as the event's
details (internal/notify/notifier.go:139-144, 383-396). The hub's customer mail localises the headline
(mail.event.health_critical) but then appends the raw details JSON as „- Megjegyzés: {…}"
(hub internal/notify/templates.go:187-189, called from dispatcher.go:331, 880). So the household's mail carries
{"previous_status":"ok","current_status":"fail","issues":["Protected container not running: cloudflared"]}.
Options
| What | Costs | Risk | |
|---|---|---|---|
| A | Dashboard only: give the 6 remaining producers a MsgRef (checkStoragePaths returns a parallel []MsgRef); 6 hu+en keys whose Hungarian equals today's text. |
~2 h, controller only. | None on the wire (the wire golden stays green by construction). |
| B | A + mail: the hub stops appending the raw details JSON to the CUSTOMER mail of health_degraded / health_critical / health_recovered (operator mail unchanged); the household's mail says what the headline says and points to the dashboard, where A shows the list in its language. |
A + ~1 h hub (one set + one test). Needs a hub release. | The household loses a list it could not read anyway; the operator keeps it. |
| C | A + translated list in the mail: details carry issue_keys [{key,args}] and the hub renders them from its own bundle. |
Two-repo, ~1 session; the hub must hold copies of controller keys (two producers, one sentence — the R-516 trap). | Drift between the two bundles. |
Pick: A now, B after the operator's word. A is a small, decision-free fix in the shape R-516 item 10 already set. B is the cheapest honest mail; C buys a translated list at the price of a second copy of every sentence.
First slice (A), with its red test: extend r516_resource_msgs_test.go with a case per remaining producer
(checkStoragePaths with a fake unavailable / not-separate / >90 % path; the Docker and protected-container issues via
their seams) asserting (1) the wire text is unchanged byte for byte and (2) the entry carries its key. Red-proof: drop one
MsgRef → the case fails and the internal/web banner test shows the wire text. The i18n Go-parity gate
(scripts/i18n_go_parity.py) checks the Hungarian values equal the frozen literals.
One question for the operator
May the household's „system health" e-mail stop showing the raw technical note, and send the household to the dashboard for the list instead? If you do nothing: A ships alone; the dashboard is right in both languages, and the mail keeps its note — a line of English inside curly brackets — as it does today.