From 2bd6fbfac9a29276acbdc7bde50cb256dbdab016 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Thu, 17 Sep 2026 21:11:31 +0200 Subject: [PATCH] =?UTF-8?q?R-553=20+=20R-563=20CLOSED=20(controller=20v0.2?= =?UTF-8?q?51.0):=20evidence,=2010=20=C2=A79=20rewritten,=20R-569..R-571,?= =?UTF-8?q?=20slice-2=20dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - audits/r553-2026-09-17/: live before/after on demo-hp (CSRF redacted), the 409 refusal, the hub health block, red-proofs for all five sites, the site-5 fixture diff, gates. - 10-localisation.md §9: the five decisions with what each reads now; the rule (a text signature may remain only where the text is not ours); the one legacy exception and its end date. - Register: R-553 and R-563 closed to CLOSED-ITEMS; R-569 (four API handlers match English words), R-570 (the legacy stale-note fallback + the slice-2 fence), R-571 (classifier and alert placement documented nowhere). R-557 carries the R-570 dependency. 263 -> 264 open. - STATUS, including the live probe that installed an app and was removed the same minute. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- STATUS.md | 33 + documentation/architecture/10-localisation.md | 34 +- .../audits/r553-2026-09-17/README.md | 31 + .../audits/r553-2026-09-17/green-gate.txt | 205 +++ .../live/hub-report-health.txt | 11 + .../r553-2026-09-17/live/page-comparison.txt | 19 + .../r553-after-0.251.0/backups_remote.html | 894 +++++++++++ .../live/r553-after-0.251.0/dashboard.html | 1108 ++++++++++++++ .../r553-after-0.251.0/deploy-refusal.json | 1 + .../live/r553-after-0.251.0/launcher.html | 706 +++++++++ .../live/r553-after-0.251.0/monitoring.html | 1323 +++++++++++++++++ .../r553-after-0.251.0/offbox-settings.json | 7 + .../r553-before-0.250.0/backups_remote.html | 891 +++++++++++ .../live/r553-before-0.250.0/dashboard.html | 1108 ++++++++++++++ .../r553-before-0.250.0/deploy-refusal.json | 1 + .../live/r553-before-0.250.0/launcher.html | 706 +++++++++ .../live/r553-before-0.250.0/monitoring.html | 1323 +++++++++++++++++ .../r553-before-0.250.0/offbox-settings.json | 7 + .../audits/r553-2026-09-17/redproofs.txt | 112 ++ .../r553-2026-09-17/site5-fixture-diff.txt | 23 + documentation/backlog/CLOSED-ITEMS.md | 7 + documentation/backlog/OPEN-ITEMS.md | 7 +- 22 files changed, 8549 insertions(+), 8 deletions(-) create mode 100644 documentation/audits/r553-2026-09-17/README.md create mode 100644 documentation/audits/r553-2026-09-17/green-gate.txt create mode 100644 documentation/audits/r553-2026-09-17/live/hub-report-health.txt create mode 100644 documentation/audits/r553-2026-09-17/live/page-comparison.txt create mode 100644 documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/backups_remote.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/dashboard.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/deploy-refusal.json create mode 100644 documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/launcher.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/monitoring.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/offbox-settings.json create mode 100644 documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/backups_remote.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/dashboard.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/deploy-refusal.json create mode 100644 documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/launcher.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/monitoring.html create mode 100644 documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/offbox-settings.json create mode 100644 documentation/audits/r553-2026-09-17/redproofs.txt create mode 100644 documentation/audits/r553-2026-09-17/site5-fixture-diff.txt diff --git a/STATUS.md b/STATUS.md index af64f104..33bac5a4 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,5 +1,38 @@ # STATUS — what works, what's broken, what's next +**Updated 2026-09-17 (late) — five hidden traps removed before the next language step.** + +> **Ready for a volunteer: yes, unchanged.** Nothing a household reads changed. The machine now knows +> WHY something happened, instead of guessing from the Hungarian words on the screen. + +**Decisions I took.** None. + +**What I exercised, on the demo HP box.** Five places in the product used to make a decision by reading +their own Hungarian words: which error code an install refusal gets, whether a cloud backup failed +because the space ran out, where a disk warning is shown, whether an old note about "nothing selected" +is still true, and whether a backup is running right now. Each one now reads a small hidden marker set +where the message is written. The words are exactly the same, letter for letter. I checked the pages +before and after the update: only live numbers differ, plus one new hidden marker on the backup page. + +**What broke, and whether it is fixed.** +- **My mistake, fixed in two minutes:** my first live test of the install refusal picked an app that + did not need any field, so it INSTALLED that app on the demo box. I stopped it and removed it with + the empty folder it had just made, and rewrote the test to a safe one. Nothing else was touched. +- The word "Fut" (running) on the cloud-backup page can finally be translated. Until today the page + read that word to know a backup was running, so the English page never noticed one. +- Found, not fixed, filed: four more places do the same with English words; the classifier and the + warning rules are written down nowhere; and one old note on a not-yet-updated box still needs the + old word test until every box has made one cloud backup on the new version. + +**Rows.** Two closed, three opened. The register went from **263** to **264** open rows. + +**Needs you.** Nothing. The new version runs on the demo HP box only; the fleet floor is unchanged at +0.250.0. If you do nothing: the other boxes keep the version they have, and nothing breaks. + +--- + +## Previous note + **Updated 2026-09-17 (night) — English, step 3 of 3 done: every dashboard page speaks English, and the language switch is there for everyone.** > **Ready for a volunteer: yes, unchanged.** A Hungarian household will see one new thing: a small diff --git a/documentation/architecture/10-localisation.md b/documentation/architecture/10-localisation.md index b660b9ee..27876d96 100644 --- a/documentation/architecture/10-localisation.md +++ b/documentation/architecture/10-localisation.md @@ -238,11 +238,35 @@ gates need an English rule. Read on privatebin, nextcloud and immich (inventory ## 9. Compared, not shown — latent bugs a translation would trigger -**[FACT]** Four places decide behaviour by matching Hungarian wording (inventory §3): an HTTP status -(`api/router.go:478`), an off-site quota classification (`backup/offbox.go:186`), an alert's placement -(`web/alerts.go:208`), and a **persisted** warning compared by marker (`web/handlers.go:927`). Each -breaks the day the words change in either language. **R-553 fixes them first, before slice 2 touches a -single Go string.** +**[FACT] There were FIVE, and they are fixed (controller v0.251.0, R-553 + R-563, 2026-09-17).** Four +in Go and one in a page script. Each producer now attaches a machine-readable signal and each decision +reads that signal; every Hungarian sentence is byte-identical (pinned per producer), and the hub report +is unchanged. + +| decision | read before | reads now | +|---|---|---| +| deploy HTTP status — `api.deployStatusFor` | „kötelező", „memória", "does not exist", "already deployed" | `stacks.ErrRequiredField`, `ErrPathMissing`, `ErrNotEnoughMemory` (400); `ErrAlreadyDeployed` (409) | +| off-site failure class — `ClassifyOffsiteFailure` | „tárhelykeretet" | `backup.ErrOffsiteQuota` | +| alert placement — `web/alerts.go` | „meghajtó" / „adattároló" in the warning | `monitor.WarnKindStorageNotSeparate`, carried in `HealthReport.WarningKinds` (internal; NOT on the wire) | +| the stale off-site note — `offboxWarningDisplay` | „nincs mentésre jelölt alkalmazás" in the PERSISTED text | `settings.OffboxTarget.LastWarningKind` = `backup.OffboxWarnNoAppsSelected` | +| the remote-backup poll — `backups_remote.html` | the displayed word „Fut" | `data-status="running"` on the status element (R-563) | + +**[DESIGN] The rule this establishes:** a text signature may remain ONLY where the text is not ours. +The classifier's restic and ssh signatures stay, because that output is neither written nor translated +here; every sentence this product writes is display, and a decision reads a signal beside it. +`internal/util.KindErrorf` exists for exactly that: the same message bytes `fmt.Errorf` produced, plus +a sentinel for `errors.Is` — never `fmt.Errorf("%w: …")`, which would prepend the sentinel's own text +to the customer's sentence. + +**[FACT] One exception, with an end date:** a box upgraded to 0.251.0 carries the OLD persisted note +with no kind until its next off-site run, so `offboxWarningDisplay` keeps the substring test for +`kind == ""` only. **Slice 2 (R-557) must not translate that producer until R-570 closes.** + +**[FACT] Measured after the fix** (`audits/r553-2026-09-17/`): the inventory's comparison detector finds +**no template compare** (was one) and no Go compare of ours — the two remaining hits are the known +false positive (an `[INFO]` log line) and the deliberate legacy fallback above; planted decoys prove the +detector still convicts. **What it does NOT cover:** four API handlers pick their status by matching +ENGLISH internal words — the same shape, one language over, filed as R-569 rather than folded in here. --- diff --git a/documentation/audits/r553-2026-09-17/README.md b/documentation/audits/r553-2026-09-17/README.md new file mode 100644 index 00000000..944ee75a --- /dev/null +++ b/documentation/audits/r553-2026-09-17/README.md @@ -0,0 +1,31 @@ +# R-553 + R-563 — nothing decides by reading a Hungarian word (controller v0.251.0), 2026-09-17 + +Method: **endpoint-level** inside demo-hp guest 9201 (no browser on DooPlex) — `https://127.0.0.1:443` +with `Host: felhom.enkisfelhom.hu` and a session. CSRF tokens in the saved files are ``. + +| what | result | +|---|---| +| pages before (0.250.0) → after (0.251.0), Hungarian | `live/page-comparison.txt`: `/launcher` and `/monitoring` identical; `/backups/remote` identical apart from the new `data-status` attribute and the one poll line (+23 bytes); `/dashboard` differs only in live numbers (CPU, load) | +| the deploy refusal, live | `POST /api/stacks/adventurelog/deploy` on an ALREADY DEPLOYED app → **409 before and after, byte-identical message**; the app kept running (`Up 10 hours (healthy)`) | +| the 400 refusals | **not provoked live** — a live probe starts an install (one did; it was stopped and removed the same minute, see REPORT.md). Covered by `TestR553_DeployProducersCarryKindAndKeepTheirWords` through the real `DeployStack`, and by the status table | +| site 2 (quota) and site 4 (stale note) | **not provoked live**: demo-hp's off-site tier reports `last_status: ok` with no warning, and provoking either would mean filling a quota or clearing the selection on a live box. Red-proofed unit tests carry them | +| site 3 (disk warning placement) | **not visible live**: the box has no storage warning (`alert-banner` blocks 0 on all three pages, before and after). The placement is unit-tested with a translated warning | +| site 5 (R-563) | after: `id="offbox-status-value" data-status="ok"`, poll reads `v.dataset.status === 'running'`; before: no attribute, poll read `textContent.indexOf('Fut')` | +| the hub wire | `live/hub-report-health.txt`: the health block on 0.251.0 carries exactly `issues, status, warnings` — no kind reached the hub. `warnings` is `[]` on this box before and after (it has no warnings), so the BYTES with warnings present are pinned by `TestR553_HubReportWarningsAreUnchangedOnTheWire` instead | +| settings | `offbox` block identical before and after; `last_warning_kind` absent (no warning to carry one) | + +Unit evidence: `redproofs.txt` (every site's pre-fix predicate restored and watched failing, then +restored), `site5-fixture-diff.txt` (12 re-captured fixtures differ ONLY by the attribute and the poll +line; the other 94 byte-identical), `green-gate.txt`. + +Detector re-run (`scripts/i18n_inventory.py`): template compares **1 → 0**; one Go compare left +(`offbox_handlers.go:132`, the known false positive — an `[INFO]` log line) and one indirect compare +left (`handlers.go` `offboxStaleWarningMarker`, the deliberate legacy fallback, row R-570). Decoys +planted in a template and in Go were both convicted, then removed. + +Teardown: machine — demo-hp guest 9201 on `hu`, controller 0.251.0, fleet floor unchanged (0.250.0), +no golden; the password file and scripts shredded/removed; evidence pulled here. Host — transfer files +removed. Hub — nothing written; the DB copy read for the report lines shredded on DooPlex. +**One thing was changed and put back:** a first live probe of the deploy refusal used an app with no +empty required field and therefore INSTALLED vaultwarden; it was stopped and removed (data volume it +had just created removed with it) within two minutes, and the probe was rewritten to the 409 form. diff --git a/documentation/audits/r553-2026-09-17/green-gate.txt b/documentation/audits/r553-2026-09-17/green-gate.txt new file mode 100644 index 00000000..305e3745 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/green-gate.txt @@ -0,0 +1,205 @@ +controller_gates — 16 gate(s) [--fast] + +============================================================================== +== gate: template-id (template_id_gate.py) +============================================================================== +integrity gate OK — every JS element-ID reference resolves within its own template + +============================================================================== +== gate: emoji (emoji_gate.py) +============================================================================== +emoji gate OK — no emoji in web/setup templates + +============================================================================== +== gate: native-confirm (native_confirm_gate.py) +============================================================================== +native-confirm gate OK — no native confirm()/prompt()/alert() in templates + +============================================================================== +== gate: offbox-rename (offbox_rename_gate.py) +============================================================================== +offbox rename gate OK — Tier-3 is 'Tavoli mentes' everywhere customer-facing + +============================================================================== +== gate: app-row-dedup (app_row_dedup_gate.py) +============================================================================== +app_row_dedup_gate: OK (row markup single-sourced in app_row.html; 36 templates scanned) + +============================================================================== +== gate: mojibake (mojibake_gate.py) +============================================================================== +mojibake_gate: OK (777 files clean — no double-encoding signatures) + +============================================================================== +== gate: docker-v (docker_run_volume_path_gate.py) +============================================================================== +docker -v gate OK — every volume mount is named-volume or proven host-visible + +============================================================================== +== gate: secret-markup (secret_in_markup_gate.py) +============================================================================== +secret-in-markup gate OK — 36 templates, no secret-named expression rendered + (NAME-BASED: blind to a secret arriving under a neutral PAGE-DATA key — see the docstring) + +============================================================================== +== gate: retrieval-promise (retrieval_promise_gate.py) +============================================================================== +retrieval-promise gate OK — 37 surface(s) incl. 1 Go handler file(s), 11 registered claim(s) + 16 English, none unregistered + (BLIND SPOT: it registers WHERE the claim is made, not whether each conditional is wired + to a true predicate — that is what the R-302 render tests are for.) + +============================================================================== +== gate: debug-routes (debug_route_gate.py) +============================================================================== +debug route gate OK - 19 referenced address(es), all dispatched, none orphaned + +============================================================================== +== gate: reuse-refs (reuse_refs_check.py /mnt/5_hdd/felhom.eu/git/felhom-controller) +============================================================================== +note [felhom-controller] line 15: backup/appbackup_bridge.go (resolved by suffix → controller/internal/backup/appbackup_bridge.go) +note [felhom-controller] line 19: appbackup/userdata.go (resolved by suffix → controller/internal/appbackup/userdata.go) +note [felhom-controller] line 19: stacks/skeleton_derive.go (resolved by suffix → controller/internal/stacks/skeleton_derive.go) +note [felhom-controller] line 47: internal/report/builder.go (resolved by suffix → controller/internal/report/builder.go) +note [felhom-controller] line 76: stacks/deploy.go (resolved by suffix → controller/internal/stacks/deploy.go) +note [felhom-controller] line 129: cmd/controller/main.go (resolved by suffix → controller/cmd/controller/main.go) +note [felhom-controller] line 152: appbackup/appdata.go (resolved by suffix → controller/internal/appbackup/appdata.go) +note [felhom-controller] line 174: scripts/secret_in_markup_gate.py (resolved by suffix → controller/scripts/secret_in_markup_gate.py) +note [felhom-controller] line 216: hub/internal/api/handler.go (cross-repo → felhom.eu/hub/internal/api/handler.go) +note [felhom-controller] line 216: hub/internal/notify/dispatcher.go (cross-repo → felhom.eu/hub/internal/notify/dispatcher.go) +note [felhom-controller] line 229: monitor/deadline.go (cross-repo (suffix) → felhom.eu/hub/internal/monitor/deadline.go) +note [felhom-controller] line 267: wgsync/reconciler.go (cross-repo (suffix) → felhom.eu/hub/internal/wgsync/reconciler.go) +note [felhom-controller] line 301: api/router.go (resolved by suffix → controller/internal/api/router.go) +note [felhom-controller] line 323: web/netprobe.go (resolved by suffix → controller/internal/web/netprobe.go) +note [felhom-controller] line 323: web/server.go (resolved by suffix → controller/internal/web/server.go) +note [felhom-controller] line 347: felhom.eu/scripts/golden_currency_gate.py (cross-repo → felhom.eu/scripts/golden_currency_gate.py) +OK [felhom-controller]: 174 cited paths — exact 158, suffix 11, ambiguous 0, cross-repo 5, FAILED 0 (siblings searched: app-catalog-felhom.eu, felhom-agent, felhom.eu) + +============================================================================== +== gate: instructions (instructions_gate.py /mnt/5_hdd/felhom.eu/git/felhom-controller) +============================================================================== +instructions_gate: /mnt/5_hdd/felhom.eu/git/felhom-controller + CLAUDE.md effective lines : 92 (ceiling 200) + version literals : 0 + TEMPORARY blocks : 0 + rule files : 5 (4 path-scoped) + workspace file : SYMLINK -> felhom.eu/documentation/runbooks/workspace-CLAUDE.md (resolves to the versioned copy) + memory index : 181 lines (ceiling 200), 25554 bytes (ceiling 25600) + memory index content : 39 version literal(s), 5 host address(es), 0 expired statement(s) [WARN only] + memory topic files : 148 indexed, 0 orphaned, 40 archived + register citations : 13 cited, 533 register items known + +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:19: version literal '0.112.0' — the fleet is not uniform, so it is stale within a day. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - **[A floor above the golden needs a DECLARED MinAgent](floor-held-above-golden.md)** — h +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:21: version literal '0.236.0' — the fleet is not uniform, so it is stale within a day. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - **["Delete my data too" was INERT until ctrl 0.236.0 (R-442)](r442-remove-reads-per-app- +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:24: version literal '0.14.0' — the fleet is not uniform, so it is stale within a day. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - **[restic 0.14.0 `--verify` is size+mtime, NOT content](restic-0140-verify-and-lock-sema +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:35: version literal '1.25.0' — the fleet is not uniform, so it is stale within a day. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [ISO train v1.25.0](iso-train-v1.25.0-2026-07-23.md) — R-71 build-gate (golden≥floor), r +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:59: version literal '1.2.0' — the fleet is not uniform, so it is stale within a day. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [Offsite pool-box aggregate](offsite-pool-box-aggregate-2026-07-17.md) — R-5 hub 0.64/0. +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:63: version literal '0.90.0' — the fleet is not uniform, so it is stale within a day. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [Guest RAM resize + fast-tick](guest-ram-resize-fasttick-2026-07-17.md) — R-24 controlle +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md: ... and 33 more version literal(s) — full list from the tally counts above. +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:39: host address '192.168.0.192' — operations/nodes.md is the single home for these. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [hub.felhom.eu resolves to the LAN here](hub-resolves-to-lan-on-dooplex-network.md) — 19 +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:54: host address '192.168.0.0' — operations/nodes.md is the single home for these. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [Tailscale N100 location-independent](tailscale-n100-location-independent-2026-07-19.md) +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:58: host address '167.233.158.164' — operations/nodes.md is the single home for these. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [Offsite PBS box RAM ceiling](offsite-pbs-box-ram-ceiling-2026-07-27.md) — **root SSH = +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:58: host address '10.77.0.1' — operations/nodes.md is the single home for these. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - [Offsite PBS box RAM ceiling](offsite-pbs-box-ram-ceiling-2026-07-27.md) — **root SSH = +WARNING: /mnt/5_hdd/felhom.eu/git/.claude-memory/MEMORY.md:162: host address '192.168.0.180' — operations/nodes.md is the single home for these. Not a failure: Claude writes this file between sessions, so this warning is aimed at the model that will next edit it, not at whoever is pushing. + - **CC runs ON DooPlex** (192.168.0.180) — repos `/mnt/5_hdd/felhom.eu/git/felhom-*`, buil + +instructions_gate: OK (12 warning(s)) + +============================================================================== +== gate: observations (observations_gate.py /mnt/5_hdd/felhom.eu/git/felhom-controller) +============================================================================== + report : /mnt/5_hdd/felhom.eu/git/felhom-controller/REPORT.md + section : ## Observations + observation items : 9 + OK 1. FILED R-563 + OK 2. FILED R-564 + OK 3. FILED R-565 + OK 4. FILED R-566 + OK 5. FILED R-567 + OK 6. FILED R-568 + OK 7. FILED R-516 + OK 8. NOT-A-FINDING + OK 9. NOT-A-FINDING +observations gate OK — every observation is either filed or explicitly declared + +============================================================================== +== gate: minagent-header (minagent_header_gate.py) +============================================================================== +minagent header gate OK — v0.250.0 declares MinAgent 0.131.0 + +============================================================================== +== gate: i18n (i18n_missing_gate.py) +============================================================================== +i18n: 1875 markers in 36 templates; hu 1588 keys, en 1591 keys +i18n: English missing 0 (ceiling 0); Hungarian formal forms 16 (ceiling 16, R-516) + formal: launcher.olvassa_be_telefonnal_a_gyors (olvassa be) + formal: launcher.biztosan_kikapcsolja_a_megosztast_a (biztosan kikapcsolja) + formal: layout.ha_ujratelepiti_az_alkalmazast_az (ujratelepiti az) + formal: layout.ha_ujratelepiti_az_alkalmazast_az (importalnia) + formal: backups_shared.empty_body (kerjuk) + formal: backups_shared.empty_body (vegye fel) + formal: app_import.fab_csomag_feltoltese_huzza_ide (valassza ki) + formal: app_import.a_feltoltes_megszakadt_ellenorizze_a (ellenorizze) + formal: deploy.a_kontener_leallt_ellenorizze_a (ellenorizze) + formal: settings_system.ezek_az_ertekek_a_helyi (kerjuk) + formal: backups_remote.a_megerosites_nem_erkezett_meg (ellenorizze) + formal: backups_escrow.a_megadott_szavak_nem_egyeznek (ellenorizze) + formal: storage.nincs_regisztralt_adattarolo_adjon_hozza (adjon hozza) + formal: storage_init.valassza_ki_a_formazando_felhasznaloi (valassza ki) + formal: storage_attach.valassza_ki_a_mar_fajlrendszerrel (valassza ki) + formal: debug.kattintson_a_gombra_a_telemetria (kattintson) +i18n gate OK + +============================================================================== +== gate: golden-notice (golden_notice.py /mnt/5_hdd/felhom.eu/git/felhom-controller) +============================================================================== +============================================================================== +NOTICE — v0.250.0 OWES A GOLDEN. (this NEVER blocks; see the docstring) +============================================================================== + newest released controller : 0.250.0 (this repo's CHANGELOG.md) + newest golden baked : 0.246.0 (felhom.eu documentation/tests/) + + A machine installed right now would receive 0.246.0, not 0.250.0. + + This is a REMINDER AT THE ONE MOMENT IT IS USEFUL — you are in the repo where the + release happens. It does not block, and must not: at the moment a release is + committed the golden cannot exist yet. + + WHAT CLEARS IT: bake a golden (felhom.eu documentation/runbooks/RUNBOOK-manual-build.md + section 4.1), then vouch it — a THREE-field change: golden_version + agent_version + + min_agent. The bake record lands in felhom.eu documentation/tests/golden--/. + + If this release deliberately needs no golden, record a waiver row in + felhom.eu documentation/backlog/OPEN-ITEMS.md — never a habit of bypassing. +============================================================================== + +============================================================================== +== summary +============================================================================== + template-id OK (exit 0) + emoji OK (exit 0) + native-confirm OK (exit 0) + offbox-rename OK (exit 0) + app-row-dedup OK (exit 0) + mojibake OK (exit 0) + docker-v OK (exit 0) + secret-markup OK (exit 0) + retrieval-promise OK (exit 0) + debug-routes OK (exit 0) + reuse-refs OK (exit 0) + instructions OK (exit 0) + observations OK (exit 0) + minagent-header OK (exit 0) + i18n OK (exit 0) + golden-notice ADVISORY (exit 0, advisory) + +all controller gates OK diff --git a/documentation/audits/r553-2026-09-17/live/hub-report-health.txt b/documentation/audits/r553-2026-09-17/live/hub-report-health.txt new file mode 100644 index 00000000..1791add5 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/hub-report-health.txt @@ -0,0 +1,11 @@ +demo-hp reports around the 0.250.0 -> 0.251.0 deploy; health.warnings quoted verbatim: + 2026-09-17 18:06:53 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 18:15:05 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 18:30:05 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 18:45:05 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 19:00:05 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 19:05:35 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 19:06:29 controller 0.250.0 health.status='ok' health.warnings=[] + 2026-09-17 19:07:19 controller 0.251.0 health.status='ok' health.warnings=[] + +keys of the health block on the newest report: ['issues', 'status', 'warnings'] diff --git a/documentation/audits/r553-2026-09-17/live/page-comparison.txt b/documentation/audits/r553-2026-09-17/live/page-comparison.txt new file mode 100644 index 00000000..7f71e782 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/page-comparison.txt @@ -0,0 +1,19 @@ +Live, endpoint-level in guest 9201 (no browser on DooPlex). CSRF token, version and relative +times normalised; the new data-status attribute and the one poll line canonicalised — those two +are the ONLY rendered bytes this release changes, and the comparison shows nothing else moved. + +backups_remote.html: 54488 -> 54511 bytes; data-status attributes 0 -> 1; everything else identical: YES +dashboard.html: 60837 -> 60837 bytes; data-status attributes 0 -> 0; everything else identical: 10 differing lines + - 2% + + 6% + -
+ - + -
Load: 0.76 / 0.64 / 0.57
+ +
+launcher.html: 44642 -> 44642 bytes; data-status attributes 0 -> 0; everything else identical: YES +monitoring.html: 67755 -> 67755 bytes; data-status attributes 0 -> 0; everything else identical: YES + +deploy-refusal.json: before == after: True + {"ok":false,"error":"stack \"adventurelog\" is already deployed; use update instead"} +offbox-settings.json: before == after: True + { "last_status": "ok", "last_run": "2026-09-17T02:18:14Z", "last_warning": null, "last_warning_kind": null, "last_error": null } diff --git a/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/backups_remote.html b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/backups_remote.html new file mode 100644 index 00000000..43ae2087 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/backups_remote.html @@ -0,0 +1,894 @@ + + + + + + + + Biztonsági mentés — Távoli mentés — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + +

Távoli mentés (3. mentés) — titkosított, offsite

+

Az alkalmazás-mentések titkosított másolata egy távoli tárolóra — saját NAS vagy Felhom offsite tárhely — restic + SFTP kapcsolaton. A tároló csak titkosított adatot lát. Ez a 3-2-1 szabály „1 off-site" lába — független a helyi másodpéldánytól és a teljes rendszermentéstől.

+
+ +
+
+
✓ Rendben
+
Utolsó távoli mentés
16 órája
+
+
+
178.3 MB
+
Tároló méret · 89 pillanatkép
+
+
+
u629488-sub3@u629488-sub3.your-storagebox.de
+
/home/felhom-repo
+
+
+ + + +
+
Tárhelykeret: 178.3 MB / 50 GB (0%)
+
+
+
+
+ + + + + + + + + + + +
+

A helyreállítási kód letétbe helyezve.

+ Új helyreállítási kód készítése +
+ + + +
+
+ +
+
+ + +

Mely alkalmazások mentődnek a távoli tárolóra?

+ + +
+ + +
+ +
+ AdventureLog + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ BentoPDF + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ BookStack + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Calibre-Web Automated + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Docmost + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Kimai + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ OpenGist + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Paperless-ngx + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ PrivateBin + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ RomM + +
+
+ +
+ + + +
+ + +
+
+ + +
+ + + + +
+ Távoli mentési cél beállítása +
+
+
+
+
+
+
+ + A kulcsot 0600-as fájlba írjuk; sosem naplózzuk és nem tároljuk a beállításokban.
+
+ + A host-kulcs rögzítése (no blind TOFU). Lekérdezhető: ssh-keyscan -p <port> <host>
+ +
+
+
+ + + + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/dashboard.html b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/dashboard.html new file mode 100644 index 00000000..c6658a34 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/dashboard.html @@ -0,0 +1,1108 @@ + + + + + + + + Vezérlőpult — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + +
+
+
+
+ Memória + 3.8 GB / 25 GB (15%) +
+
+
+
+
+
+
+ CPU + 6% +
+
+
+
+
Load: 0.56 / 0.63 / 0.57
+
+ +
+
+ Hőmérséklet + 54°C +
+
+ +
+
+ + + +
+
+ Rendszer (/) + 16.9 GB / 68.7 GB (25%) +
+
+
+
+ +
+ + + + +
+
+ NVME 1TB + 15.1 GB / 938 GB (2%) +
+
+
+
+ +
+ + +
+ + +
+ + +
+

Lemezek állapota

+ +
    + +
  • + KXG50PNV1T02 NVMe TOSHIBA 1024GB + Rendben + 53 °C +
  • + +
  • + SanDisk X600 M.2 2280 SATA 128GB + Rendben + 50 °C +
  • + +
+ +
+ + +
+

Biztonsági mentés

+ +
+ Utolsó mentés: + + + 2026-09-17 08:50 + + +
+ + +
+ Adatbázisok: + 16 mentve +
+ + +
+ + +

Telepített alkalmazások

+ +
+ + + + +
+ +
+ AdventureLog + Utazási napló és kalandtervező +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ BentoPDF + Adatvédelmi fókuszú PDF eszköztár +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ BookStack + Egyszerű, könyv-szerű wiki és dokumentáció platform +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Calibre-Web Automated + Automatizált e-könyv könyvtár - konvertálás, metaadat kezelés és webes olvasó +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Cloudflare Tunnel + Biztonságos internetkapcsolat — a szerver portnyitás nélkül érhető el kívülről. +
+
+ + + Fut + + + + + + + + + + Védett + + + + + + + +
+
+ + + + + +
+ +
+ Docmost + Modern wiki és dokumentáció platform (Notion-szerű) +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ FileBrowser + Fájlkezelő — a tárhely fájljainak böngészése a böngészőből. +
+
+ + + Fut + + + + + + + + + + Védett + + + + Megnyitás + + + + + + +
+
+ + + + + +
+ +
+ Kimai + Időkövetés és projektmenedzsment +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ OpenGist + Kód snippetek megosztása (GitHub Gist alternatíva) +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Paperless-ngx + Dokumentumok digitalizálása és rendszerezése +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ PrivateBin + Titkosított jegyzet és szöveg megosztás +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ RomM + Retró játékgyűjtemény kezelő +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Traefik + Forgalomirányító (reverse proxy) — a kéréseket a megfelelő alkalmazáshoz irányítja. +
+
+ + + Fut + + + + + + + + + + Védett + + + + + + + +
+
+ + +
+ + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/deploy-refusal.json b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/deploy-refusal.json new file mode 100644 index 00000000..e8ba281b --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/deploy-refusal.json @@ -0,0 +1 @@ +{"ok":false,"error":"stack \"adventurelog\" is already deployed; use update instead"} diff --git a/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/launcher.html b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/launcher.html new file mode 100644 index 00000000..fd71d17f --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/launcher.html @@ -0,0 +1,706 @@ + + + + + + + + Indítópult — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/monitoring.html b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/monitoring.html new file mode 100644 index 00000000..da38b9dc --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/monitoring.html @@ -0,0 +1,1323 @@ + + + + + + + + Rendszermonitor — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + +
+
+

Szerver állapota (gazdagép)

+ +
+ + +
+ + +
+

Rendszer áttekintés

+
+
+ Gépnév + – +
+
+ Operációs rendszer + – +
+
+ Kernel + – +
+
+ Processzor + – +
+
+ Üzemidő + – +
+
+ Indítás + – +
+
+
+ + +
+

Tárhely

+
+ +
+
+ Rendszer (/) + 16.9 GB / 68.7 GB (25%) +
+
+
+
+
+ + +
+
+ NVME 1TB + 15.1 GB / 938 GB (2%) +
+
+
+
+
Külső adattároló — a telepített alkalmazások nagy méretű fájljai (média, dokumentumok) ide kerülnek; az adatbázisok a belső SSD-n vannak.
+
+ + + +
+ +
+ + +
+

Hub kapcsolat

+ + +
+ Kapcsolódva — a központi rendszer aktívan figyeli a szervert. +
+ +
+
+ Hub URL + https://hub.felhom.eu +
+
+ Ügyfél azonosító + demo-hp +
+ +
+ Utolsó sikeres jelentés + most +
+ + +
+ +
+ + +
+
+

Rendszer metrikák

+
+ + + + + +
+
+
+
+
CPU használat (%)
+
+
+
+
Memória használat (GB)
+
+
+
+
Hőmérséklet (°C)
+
+
+
+
Terhelés (Load Average)
+
+
+
+ +
+ + + + + +
+

Alkalmazás erőforrások

+
+
+
CPU használat (%)
+
+
+
+
Memória használat (MB)
+
+
+
+ +
+ + + + + + + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/offbox-settings.json b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/offbox-settings.json new file mode 100644 index 00000000..618705a5 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-after-0.251.0/offbox-settings.json @@ -0,0 +1,7 @@ +{ + "last_status": "ok", + "last_run": "2026-09-17T02:18:14Z", + "last_warning": null, + "last_warning_kind": null, + "last_error": null +} diff --git a/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/backups_remote.html b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/backups_remote.html new file mode 100644 index 00000000..cd1d6452 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/backups_remote.html @@ -0,0 +1,891 @@ + + + + + + + + Biztonsági mentés — Távoli mentés — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + +

Távoli mentés (3. mentés) — titkosított, offsite

+

Az alkalmazás-mentések titkosított másolata egy távoli tárolóra — saját NAS vagy Felhom offsite tárhely — restic + SFTP kapcsolaton. A tároló csak titkosított adatot lát. Ez a 3-2-1 szabály „1 off-site" lába — független a helyi másodpéldánytól és a teljes rendszermentéstől.

+
+ +
+
+
✓ Rendben
+
Utolsó távoli mentés
16 órája
+
+
+
178.3 MB
+
Tároló méret · 89 pillanatkép
+
+
+
u629488-sub3@u629488-sub3.your-storagebox.de
+
/home/felhom-repo
+
+
+ + + +
+
Tárhelykeret: 178.3 MB / 50 GB (0%)
+
+
+
+
+ + + + + + + + + + + +
+

A helyreállítási kód letétbe helyezve.

+ Új helyreállítási kód készítése +
+ + + +
+
+ +
+
+ + +

Mely alkalmazások mentődnek a távoli tárolóra?

+ + +
+ + +
+ +
+ AdventureLog + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ BentoPDF + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ BookStack + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Calibre-Web Automated + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Docmost + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Kimai + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ OpenGist + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ Paperless-ngx + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ PrivateBin + +
+
+ +
+ + + +
+ + +
+
+ + + +
+ +
+ RomM + +
+
+ +
+ + + +
+ + +
+
+ + +
+ + + + +
+ Távoli mentési cél beállítása +
+
+
+
+
+
+
+ + A kulcsot 0600-as fájlba írjuk; sosem naplózzuk és nem tároljuk a beállításokban.
+
+ + A host-kulcs rögzítése (no blind TOFU). Lekérdezhető: ssh-keyscan -p <port> <host>
+ +
+
+
+ + + + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/dashboard.html b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/dashboard.html new file mode 100644 index 00000000..f1a5986c --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/dashboard.html @@ -0,0 +1,1108 @@ + + + + + + + + Vezérlőpult — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + +
+
+
+
+ Memória + 3.8 GB / 25 GB (15%) +
+
+
+
+
+
+
+ CPU + 2% +
+
+
+
+
Load: 0.76 / 0.64 / 0.57
+
+ +
+
+ Hőmérséklet + 54°C +
+
+ +
+
+ + + +
+
+ Rendszer (/) + 16.9 GB / 68.7 GB (25%) +
+
+
+
+ +
+ + + + +
+
+ NVME 1TB + 15.1 GB / 938 GB (2%) +
+
+
+
+ +
+ + +
+ + +
+ + +
+

Lemezek állapota

+ +
    + +
  • + KXG50PNV1T02 NVMe TOSHIBA 1024GB + Rendben + 54 °C +
  • + +
  • + SanDisk X600 M.2 2280 SATA 128GB + Rendben + 50 °C +
  • + +
+ +
+ + +
+

Biztonsági mentés

+ +
+ Utolsó mentés: + + + 2026-09-17 08:50 + + +
+ + +
+ Adatbázisok: + 16 mentve +
+ + +
+ + +

Telepített alkalmazások

+ +
+ + + + +
+ +
+ AdventureLog + Utazási napló és kalandtervező +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ BentoPDF + Adatvédelmi fókuszú PDF eszköztár +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ BookStack + Egyszerű, könyv-szerű wiki és dokumentáció platform +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Calibre-Web Automated + Automatizált e-könyv könyvtár - konvertálás, metaadat kezelés és webes olvasó +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Cloudflare Tunnel + Biztonságos internetkapcsolat — a szerver portnyitás nélkül érhető el kívülről. +
+
+ + + Fut + + + + + + + + + + Védett + + + + + + + +
+
+ + + + + +
+ +
+ Docmost + Modern wiki és dokumentáció platform (Notion-szerű) +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ FileBrowser + Fájlkezelő — a tárhely fájljainak böngészése a böngészőből. +
+
+ + + Fut + + + + + + + + + + Védett + + + + Megnyitás + + + + + + +
+
+ + + + + +
+ +
+ Kimai + Időkövetés és projektmenedzsment +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ OpenGist + Kód snippetek megosztása (GitHub Gist alternatíva) +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Paperless-ngx + Dokumentumok digitalizálása és rendszerezése +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ PrivateBin + Titkosított jegyzet és szöveg megosztás +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ RomM + Retró játékgyűjtemény kezelő +
+
+ + + Fut + + + + + + + + + + + + Megnyitás + + + + Napló + + + +
+
+ + + + + +
+ +
+ Traefik + Forgalomirányító (reverse proxy) — a kéréseket a megfelelő alkalmazáshoz irányítja. +
+
+ + + Fut + + + + + + + + + + Védett + + + + + + + +
+
+ + +
+ + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/deploy-refusal.json b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/deploy-refusal.json new file mode 100644 index 00000000..e8ba281b --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/deploy-refusal.json @@ -0,0 +1 @@ +{"ok":false,"error":"stack \"adventurelog\" is already deployed; use update instead"} diff --git a/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/launcher.html b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/launcher.html new file mode 100644 index 00000000..1b3a1718 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/launcher.html @@ -0,0 +1,706 @@ + + + + + + + + Indítópult — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/monitoring.html b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/monitoring.html new file mode 100644 index 00000000..922d02dc --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/monitoring.html @@ -0,0 +1,1323 @@ + + + + + + + + Rendszermonitor — Felhom.eu + + + + + + + + +
+ + +
+ + +
+ + + + + + + + + + + +
+
+

Szerver állapota (gazdagép)

+ +
+ + +
+ + +
+

Rendszer áttekintés

+
+
+ Gépnév + – +
+
+ Operációs rendszer + – +
+
+ Kernel + – +
+
+ Processzor + – +
+
+ Üzemidő + – +
+
+ Indítás + – +
+
+
+ + +
+

Tárhely

+
+ +
+
+ Rendszer (/) + 16.9 GB / 68.7 GB (25%) +
+
+
+
+
+ + +
+
+ NVME 1TB + 15.1 GB / 938 GB (2%) +
+
+
+
+
Külső adattároló — a telepített alkalmazások nagy méretű fájljai (média, dokumentumok) ide kerülnek; az adatbázisok a belső SSD-n vannak.
+
+ + + +
+ +
+ + +
+

Hub kapcsolat

+ + +
+ Kapcsolódva — a központi rendszer aktívan figyeli a szervert. +
+ +
+
+ Hub URL + https://hub.felhom.eu +
+
+ Ügyfél azonosító + demo-hp +
+ +
+ Utolsó sikeres jelentés + most +
+ + +
+ +
+ + +
+
+

Rendszer metrikák

+
+ + + + + +
+
+
+
+
CPU használat (%)
+
+
+
+
Memória használat (GB)
+
+
+
+
Hőmérséklet (°C)
+
+
+
+
Terhelés (Load Average)
+
+
+
+ +
+ + + + + +
+

Alkalmazás erőforrások

+
+
+
CPU használat (%)
+
+
+
+
Memória használat (MB)
+
+
+
+ +
+ + + + + + + + +
+ + + + diff --git a/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/offbox-settings.json b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/offbox-settings.json new file mode 100644 index 00000000..618705a5 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/live/r553-before-0.250.0/offbox-settings.json @@ -0,0 +1,7 @@ +{ + "last_status": "ok", + "last_run": "2026-09-17T02:18:14Z", + "last_warning": null, + "last_warning_kind": null, + "last_error": null +} diff --git a/documentation/audits/r553-2026-09-17/redproofs.txt b/documentation/audits/r553-2026-09-17/redproofs.txt new file mode 100644 index 00000000..fc870094 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/redproofs.txt @@ -0,0 +1,112 @@ +# R-553 / R-563 red-proofs — each mutation restores the PRE-FIX shape (what HEAD e236dca does) and is watched failing + +## Site 1 — TestR553_Deploy_DecisionSurvivesWordingChange + TestR553_DeployHandlerUsesTheKind +mutation: deployStatusFor reads the error text again (the HEAD chain) +--- FAIL: TestR553_Deploy_DecisionSurvivesWordingChange (0.00s) + r553_deploy_status_test.go:49: required field, TRANSLATED: deployStatusFor("the \"Password\" (PASSWORD) field is required") = 500, want 400 + r553_deploy_status_test.go:49: password field, TRANSLATED: deployStatusFor("fill in the \"Password\" field — use the Generate button") = 500, want 400 + r553_deploy_status_test.go:49: path missing, TRANSLATED: deployStatusFor("a mappa \"/mnt/nope\" nem létezik (\"Adatok\" mező)") = 500, want 400 + r553_deploy_status_test.go:49: not enough memory, TRANSLATED: deployStatusFor("Not enough memory to install this app. Needed: 512 MB, available: 100 MB") = 500, want 400 + r553_deploy_status_test.go:49: already deployed, TRANSLATED: deployStatusFor("a(z) \"privatebin\" alkalmazás már telepítve van") = 500, want 409 + r553_deploy_status_test.go:49: a message that merely CONTAINS the old words is not a refusal kind: deployStatusFor("docker: kötelező memória does not exist") = 400, want 500 +FAIL + +## Site 1 producers — TestR553_DeployProducersCarryKindAndKeepTheirWords +mutation: the required-field producer goes back to plain fmt.Errorf (no kind) +--- FAIL: TestR553_DeployProducersCarryKindAndKeepTheirWords (0.75s) + --- FAIL: TestR553_DeployProducersCarryKindAndKeepTheirWords/required_field_left_empty (0.26s) + r553_deploy_error_kinds_test.go:91: refusal carries no kind: a(z) "Adatmappa" (DATA_DIR) mező kitöltése kötelező (want errors.Is … required field empty) +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.754s + +## Site 2 — TestR553_OffsiteQuota_DecisionSurvivesWordingChange + HeadLine +mutation: the classifier reads „tárhelykeretet" again instead of the sentinel (the HEAD arm) +--- FAIL: TestR553_OffsiteQuota_DecisionSurvivesWordingChange (0.00s) + r553_offsite_quota_test.go:40: quota refusal, TRANSLATED: ClassifyOffsiteFailure = "unknown", want "quota" + r553_offsite_quota_test.go:40: quota refusal wrapped by a caller: ClassifyOffsiteFailure = "unknown", want "quota" +--- FAIL: TestR553_OffsiteQuota_HeadLineSurvivesWordingChange (0.00s) + r553_offsite_quota_test.go:52: a translated quota failure is reported with the wrong cause line: "A távoli mentés ismeretlen okból nem sikerült (12s): The remote backup is over its storage quota (51/50 GB)." +FAIL + +## restored +ok gitea.dooplex.hu/admin/felhom-controller/internal/api 0.007s +ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.752s +ok gitea.dooplex.hu/admin/felhom-controller/internal/backup (cached) + +## Site 3 — TestR553_DiskWarningPlacementSurvivesWordingChange +mutation: alerts.go reads the warning's words again (the HEAD condition) +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web [build failed] +FAIL + +## Site 3 wire — TestR553_HubReportWarningsAreUnchangedOnTheWire +mutation: the kinds are added to the hub report's health block +--- FAIL: TestR553_HubReportWarningsAreUnchangedOnTheWire (0.00s) + r553_alert_placement_test.go:84: the hub's health block changed shape: "status,issues,warnings,warning_kinds", want "status,issues,warnings" + r553_alert_placement_test.go:100: the hub report's health bytes CHANGED: + r553_alert_placement_test.go:103: a warning KIND reached the wire — the hub contract gained a field nobody agreed to +FAIL +## restored +ok gitea.dooplex.hu/admin/felhom-controller/internal/web 0.007s + +## Site 3 (retry, the first attempt did not compile: the loop index became unused) +mutation: alerts.go reads the warning's words again (the HEAD condition) +--- FAIL: TestR553_DiskWarningPlacementSurvivesWordingChange (0.00s) + r553_alert_placement_test.go:55: TRANSLATED: Inline = false, want true (message "The data storage (/mnt/hdd) is not on a separate drive — the data is written to the system drive") + r553_alert_placement_test.go:62: TRANSLATED: PageOnly = [], want 2 page(s) + r553_alert_placement_test.go:55: a warning that merely CONTAINS the old words is not moved: Inline = true, want false (message "A meghajtó ellenőrzése nem futott le") + r553_alert_placement_test.go:62: a warning that merely CONTAINS the old words is not moved: PageOnly = [dashboard monitoring], want 0 page(s) +FAIL +## restored +ok gitea.dooplex.hu/admin/felhom-controller/internal/web 0.010s + +## Site 4 — TestR553_StaleNoteDecisionSurvivesWordingChange +mutation: offboxWarningDisplay decides by the Hungarian marker again (the HEAD predicate) +--- FAIL: TestR553_StaleNoteDecisionSurvivesWordingChange (0.00s) + r553_stale_note_test.go:41: TRANSLATED, apps now selected: +--- FAIL: TestR553_StaleNoteOnTheRenderedPage (0.06s) +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.064s +FAIL + +## Site 4 producer — TestR553_WarningKindIsPersistedAndCopied is about persistence; the producer arm is proven by removing the kind at the run +mutation: the zero-selection run no longer records its kind +testing: warning: no tests to run +ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.004s [no tests to run] +## restored +ok gitea.dooplex.hu/admin/felhom-controller/internal/web 0.071s +## Site 4 producer — TestR553_OffboxRunRecordsTheKind (retry: the test now exists) +mutation: the zero-selection run no longer records its kind +--- FAIL: TestR553_OffboxRunRecordsTheKind (0.00s) + r553_offsite_quota_test.go:89: the zero-selection run records its sentence but not its KIND — the Távoli mentés page is left reading Hungarian words, which localisation slice 2 will change (R-553) +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.006s +## restored +ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.005s + +## Site 5 (R-563) — TestR563_PollStartsFromAttribute +mutation: the poll reads the displayed word again (the HEAD line), attribute left in place +--- FAIL: TestR563_PollStartsFromAttribute (0.12s) + r563_poll_attribute_test.go:36: [hu] the poll does not read the attribute + r563_poll_attribute_test.go:39: [hu] the poll reads the displayed Hungarian word again (R-563) + r563_poll_attribute_test.go:36: [en] the poll does not read the attribute + r563_poll_attribute_test.go:39: [en] the poll reads the displayed Hungarian word again (R-563) + +mutation 2: the running word goes back inline (untranslatable) — the English page shows Hungarian +--- FAIL: TestR563_PollStartsFromAttribute (0.12s) + r563_poll_attribute_test.go:46: [en] status label = "Fut…", want "Running…" +FAIL +FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.133s +## restored +ok gitea.dooplex.hu/admin/felhom-controller/internal/web 0.416s + +## Detector re-run (felhom.eu/scripts/i18n_inventory.py) on the fixed tree +template compares: 0 (was 1 - backups_remote 'Fut'); controller_go compares: 1; indirect: 1 + - controller_go offbox_handlers.go:132 is the known FALSE POSITIVE (an [INFO] log line, named in the prompt) + - indirect handlers.go:944 offboxStaleWarningMarker is the DELIBERATE legacy fallback (kind == "" only), row R-570 + +## Decoy: plant one compare of each shape, prove the detector still convicts +with the decoys planted: template compares 1 | controller_go compares 2 + template hit: sharing.html {'line': 5, 'text': 'Megosztott mappák'} + go hit: alerts.go 164 Meghajtó leválasztva + go hit: offbox_handlers.go 132 A távoli mentési cél elmentve. +decoys removed diff --git a/documentation/audits/r553-2026-09-17/site5-fixture-diff.txt b/documentation/audits/r553-2026-09-17/site5-fixture-diff.txt new file mode 100644 index 00000000..9a1686e2 --- /dev/null +++ b/documentation/audits/r553-2026-09-17/site5-fixture-diff.txt @@ -0,0 +1,23 @@ +Site 5 (R-563) - what changed in the Hungarian fixtures, and nothing else. +Normalisation applied to BOTH sides: remove the new data-status attribute, canonicalise the one +poll line, drop blank lines (the template's JS comments render as blanks). If the two sides are +then identical byte-for-byte, the attribute and that one line are the whole change. + +backups_remote_empty: data-status in the new file 0 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_error: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_escrowed: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_full: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_incomplete: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_notconf: data-status in the new file 0 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_notconf_hub: data-status in the new file 0 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_pending_agent: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_pending_old: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_running: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_stale: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True +backups_remote_stale_old: data-status in the new file 1 (old 0), poll line reads the attribute: True, everything else identical: True + +12 of 12 re-captured states differ ONLY by the data-status attribute and the poll line. +The other 94 fixtures are byte-identical: 94 of 94. + +The displayed Hungarian is unchanged: the running label moved into bundle key backups_remote.fut, +whose Hungarian value is the same text that was inline - the rendered bytes above prove it. diff --git a/documentation/backlog/CLOSED-ITEMS.md b/documentation/backlog/CLOSED-ITEMS.md index bdf5510a..46b34971 100644 --- a/documentation/backlog/CLOSED-ITEMS.md +++ b/documentation/backlog/CLOSED-ITEMS.md @@ -26,6 +26,13 @@ --- +## 2026-09-17 — nothing decides by reading a Hungarian word (controller v0.251.0) + +| Row | What | Closed | Full text | +|---|---|---|---| +| **R-553** | **Five places decided behaviour by matching their own Hungarian wording (P3).** Closed in controller **v0.251.0** (`c00fed6` + `f806baf`): each producer attaches a signal and each decision reads it — deploy sentinels (`stacks.ErrRequiredField` / `ErrPathMissing` / `ErrNotEnoughMemory` / `ErrAlreadyDeployed` → `api.deployStatusFor`, 400/409), `backup.ErrOffsiteQuota` in `ClassifyOffsiteFailure`, `monitor.HealthReport.WarningKinds` for alert placement, `settings.OffboxTarget.LastWarningKind` for the stale off-site note. `util.KindErrorf` produces the same message bytes `fmt.Errorf` did while carrying the sentinel, so **not one Hungarian byte moved** (pinned per producer). The hub wire is unchanged: `report.HealthReport` still carries exactly `status, issues, warnings` — proven live and by test. Each site red-proofed by restoring its pre-fix predicate. **Reasoning kept:** a text signature is replaced by a signal only where WE produce the text — restic's and ssh's English output stays matched by text, because we neither write nor translate it. `audits/r553-2026-09-17/` | **CLOSED 2026-09-17 — PROVEN-LIVE (the 409 refusal and the page bytes; the 400 / quota / stale-note paths are red-proofed tests, not provoked on a live box)** | full text: `git show b408b28:documentation/backlog/OPEN-ITEMS.md` | +| **R-563** | **The remote-backup page started its progress poll by reading its own Hungarian word „Fut" (P3).** Closed in controller **v0.251.0** (`f806baf`): the status element carries `data-status="{{.Offbox.LastStatus}}"` and the poll reads `v.dataset.status === 'running'`. The word became `{{T "backups_remote.fut"}}` (en „Running…"), so **the English page can finally see a running backup** — slice 1 had to leave that one word Hungarian for this reason. 12 parity fixtures re-captured; each differs from its predecessor by exactly the attribute and that poll line, the other 94 byte-identical. Red-proofed twice (poll back on the word; word back inline). `audits/r553-2026-09-17/site5-fixture-diff.txt` | **CLOSED 2026-09-17 — PROVEN-LIVE (the rendered attribute and poll line on demo-hp)** | full text: `git show b408b28:documentation/backlog/OPEN-ITEMS.md` | + ## 2026-09-17 — localisation slice 1: the whole dashboard in English (controller v0.248.0–v0.250.0) | Row | What | Closed | Full text | diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index e520e0ef..9b4ef5d5 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -731,21 +731,22 @@ class (an image `VOLUME` at an unmounted path) is still live — `immich-server` | **R-548** | **[P3-LOW] The whole-guest backup’s LOCAL tier cannot fit on a small-system-disk box, and will retry on that tier for ever.** MEASURED 2026-09-17 (chaos night) on `tester-1-022354`: a whole-guest backup wrote a **~29 GB source** (`mp0` = `local-lvm:vm-9201-disk-1`, 70 G provisioned, 40.58 % used, `backup=1`) into `pve-root`, which on a 32 GB system disk is **14 GB total with ~4.9 GB free**. Two samples thirty seconds apart showed the archive growing ~497 MB while free space fell ~475 MB — **~16 MB/s, i.e. under four minutes to a full `/`** on the nested PVE. **The product’s behaviour is correct and legible throughout:** it failed the tier and said which one — `whole_guest_backup_failed` (error, operator-only): „Whole-guest backup FAILED on the local tier — retrying with backoff (next attempt in 15m0s)” — its status surface agreed (`target_id:"local"`, `success:false`, `size_bytes:0`), and the **off-site tier then ran from the same snapshot and succeeded in ~8½ minutes, encrypted to ep0, consuming no local disk at all**. So the data still left the house. What is filed is the loop: on a box shaped like this the local tier can **never** succeed, and it keeps retrying on a backoff for ever, burning I/O and risking `/` each time. **Honest caveat:** the 32 GB system disk is this drill’s fixture choice, so the row is conditional on disk size — but nothing in the product checks whether the local target could ever hold the source before trying. **Fix shape:** compare the source size against the target’s free space before starting the local tier and skip it with a clear reason, rather than discovering it at ~16 MB/s. Evidence: `audits/evidence-chaos-night-2026-09-17/round-6.txt`. | **READY — rank P3-LOW; owner: CC** | | **R-551** | **[P3-LOW] No Tier-0 box can put the escrow ceremony in the state R-546 fixes — paused AND connected to its agent — so the readiness branches are proven only by tests.** FOUND 2026-09-17 while live-validating controller v0.246.0 (R-546). The branches (reminder bar held back while the agent's preflight is not `ok`; the waiting card on `/backup/escrow`; `POST /api/escrow/start` refused 409 before staging) need a box whose off-site tier is configured, whose escrow is NOT done, and whose controller reaches the agent. Measured on demo-hp: **9201** reaches the agent but is escrowed (the bar is off by design there; making it paused would be hand-set state on the standing demo box, and a real ceremony would supersede its live escrow — the hub keeps ONE `host_escrow` row per host, `host_id PRIMARY KEY`); **9202** is paused-capable but has **no local-API token at all** (its `bootstrap.json` holds only `schema`, `customer.id`, `disposition`), so its readiness is always UNKNOWN and the bar always shows. The fresh-bind window where this state occurs naturally (~17 min, chaos night Phase 0) needs a fresh install. **What IS proven:** five tests driving the real pages and handler through `ServeHTTP` with a fake agent, each red-proofed; and chaos night measured live that the agent's preflight is red for ~17 minutes after a bind and turns green by itself (`evidence-chaos-night-2026-09-17/phase0-escrow-*`). **Fix shape:** give the scratch guest a local-API token through the agent's own provisioning path, or walk R-546 on the next fresh install. | **READY - rank P3-LOW; owner: CC** | | **R-552** | **[P3-LOW] An interrupted-restore notice for an app that is then REMOVED stays on the restore page for ever.** FOUND 2026-09-17 by CC reviewing its own controller v0.246.0 (R-550) during live validation. The per-app notice (`Manager.opInterrupted`, persisted in `restore-status.json`) is cleared in exactly one place — `BeginRestoreOp` for that app (`internal/backup/opstatus.go`) — and `removeStack` (`internal/api/router.go`) never touches the restore record. So a household that answers „A visszaállítás megszakadt … indítsd el újra" by REMOVING the app instead of restoring it keeps a „Megszakadt visszaállítás" card about an app that no longer exists. Measured shape, not hypothetical: on 9201 the notice cleared only when homebox was restored again (08:54:50Z, card count 0) — the teardown deliberately took that path before removing it. **Fix shape:** `removeStack` clears the app's notice (a `ClearInterruptedRestore(stack)` beside the existing update-hold clear, R-491's precedent), with a wiring test. Not fixed in v0.246.0: found after the release was built; one release per repo per session. | **READY - rank P3-LOW; owner: CC** | -| **R-553** | **[P3-LOW] Four places decide BEHAVIOUR by matching Hungarian wording — each breaks the day the words change, in either language.** FOUND 2026-09-17 by the i18n inventory (`audits/I18N-INVENTORY-2026-09-17.md` §3), read at source: (1) `controller/internal/api/router.go:478` picks **400 vs 500** for a deploy error by `strings.Contains(err, "kötelező"/"memória")`; (2) `internal/backup/offbox.go:186` classifies the off-site **quota** failure by „tárhelykeretet" in a lower-cased error; (3) `internal/web/alerts.go:208` moves a disk warning inline-vs-top-banner by „meghajtón"/„adattároló"/„meghajtó"; (4) `internal/web/handlers.go:927` compares a **persisted** off-site warning against `offboxStaleWarningMarker` („nincs mentésre jelölt alkalmazás") — a warning written in one language is compared in another. (A fifth hit, `offbox_handlers.go:132`, is a detector false positive.) Templates: zero (detector decoy-tested). **Fix shape:** a typed error / sentinel / reason code at each producer, the display text derived from it, one red-proofed test per site asserting the consequence (status code, quota class, placement, substitution) with the wording changed. **Blocks localisation slice 2 (R-557)** — it goes first. | **READY - rank P3-LOW; owner: CC** | | **R-554** | **[P3-LOW] Delete the first-boot setup wizard — obsolete by design, still reachable.** OPERATOR DECISION 2026-09-17 (localisation starter, decision 4: „out of scope, obsolete"). `02-controller-module-map.md` L56 calls `internal/setup/` obsolete; `cmd/controller/main.go` L322 still enters it when `setup.NeedsSetup(cfg)` — `customer.id` empty after bootstrap ingestion, or a `.needs-setup` marker (`internal/setup/setup.go` L17-25). Ingestion leaves `customer.id` empty on a missing/invalid `bootstrap.json`, a failed hub pull, or a failed merge/write/reload (`internal/bootstrap/bootstrap.go` L109-163) — so a box whose first boot cannot reach the hub shows a household an 8-page wizard (95 Hungarian strings, its own template set and CSRF). **Fix shape:** decide what such a box shows instead (a single „cannot reach Felhom yet, retrying" page — needs no decision beyond copy), then delete `internal/setup/` and `runSetupMode`; red-proof that a failed ingestion renders the waiting page, not a 404. **Check first** whether any drill/golden path still relies on `.needs-setup`. | **READY - rank P3-LOW; owner: CC** | | **R-555** | **[P3-LOW] The wire-contract gate counts a field as received when its name appears in a Go COMMENT on the receiving side.** FOUND 2026-09-17 by CC adding the report's `language` field (controller v0.247.0): `scripts/wire_contract_gate.py` passed WITHOUT an allowlist entry, because `receiver_tokens()` tokenises whole files and the word „language" occurs hub-side only in a comment (`hub/internal/web/configs.go:558`, „this page's existing language"). The shape is the gate's own named failure class (name-for-fact, R-421): any English tag name that also appears in hub prose passes unread. The field was allowlisted by hand with this row named. **Fix shape:** strip `//` and `/* */` comments (and template `{{/* */}}`) before tokenising; add the decoy „a tag whose name appears only in a receiver comment must convict"; expect a handful of currently-passing tags to surface — each is a finding, not noise. | **READY - rank P3-LOW; owner: CC** | -| **R-557** | **[P3-LOW] Localisation slice 2 — Go-side customer strings follow the language.** PLAN 2026-09-17 (10 §10). Inventory §2.2: 947 shown + 184 error literals in 84 files; 237 format strings, 111 concatenations, 42 numeric `%d` (English plurals). Flash messages travel inside the redirect URL (`?flash=`) and must become keys; `cloudflare/countries.go` (113 country names); alert texts; handler errors printed with `err.Error()`. **After R-553** (the four compare-not-show sites). Cost 16–20 CC-hours. | **READY - rank P3-LOW; owner: CC** | +| **R-557** | **[P3-LOW] Localisation slice 2 — Go-side customer strings follow the language.** PLAN 2026-09-17 (10 §10). Inventory §2.2: 947 shown + 184 error literals in 84 files; 237 format strings, 111 concatenations, 42 numeric `%d` (English plurals). Flash messages travel inside the redirect URL (`?flash=`) and must become keys; `cloudflare/countries.go` (113 country names); alert texts; handler errors printed with `err.Error()`. **After R-553** (the four compare-not-show sites). Cost 16–20 CC-hours. **DEPENDENCY added 2026-09-17 (R-553 shipped, v0.251.0):** the behaviour-by-wording sites are fixed, so this slice is unblocked — EXCEPT one producer: `"Sikeres — nincs mentésre jelölt alkalmazás"` (controller/internal/backup/offbox.go) must stay Hungarian until **R-570** closes, because the page's legacy fallback still reads it on boxes that have not run off-site since 0.251.0. Everything else this slice touches is now decided by a kind, not by its words. | **READY - rank P3-LOW; owner: CC** | | **R-558** | **[P3-LOW] Localisation slice 3 — the hub's customer e-mails follow the household's language; the operator sets it at customer creation.** PLAN 2026-09-17 (10 §3, §10), operator decision 2. The box already reports `"language"` (controller v0.247.0); nothing hub-side reads it. Build: a per-customer language on the hub (default hu) set at creation and rendered into `controller.yaml` beside `customer.*` (`hub/internal/configgen/configgen.go`), used by the box only while `settings.json` has no choice; the dispatcher picks the language the box REPORTS; English for the 39 `customerMessages`, the 4 severity labels, the body wrapper, the claim/re-enroll/reset/claimed/self-bind mails and the public bind page (inventory §2.3). Delete the `language` allowlist entry in `wire_contract_gate.py` when the field is read. Cost 6–8 CC-hours, one hub + one controller release. | **READY - rank P3-LOW; owner: CC** | | **R-559** | **[P3-LOW] Localisation slice 4 — the console banner and the download page in English.** IN SCOPE — operator ruling 2026-09-17 evening („yes", 10 §11 1b). PLAN 2026-09-17 (10 §10, open decision 1b): the starter listed them; the operator's scope ruling names „the controller, emails, guide, app catalog" and not them. Inventory §2.4: 34 banner lines (`scripts/iso/felhom-bootstrap.sh`, printf to the console; `/etc/issue` byte-coupled to `iso/pkg/debian/postinst`, console font avoids ő/ű) and 32 strings on `website/letoltes.html`. Cost 4–6 CC-hours plus an ISO release train. | **READY - rank P3-LOW; owner: CC** | | **R-560** | **[P3-LOW] Localisation slice 5 — catalog cards, settings and first steps in English.** PLAN 2026-09-17 (10 §7, §10). Inventory §2.5: 835 strings, ~4 984 words across all 53 `.felhom.yml` (use_cases 262, first_steps 233, deploy_fields descriptions 79 / labels 68, prerequisites 60, description 56, tagline 53). Proposed format: an `i18n: {en: {...}}` block inside each `.felhom.yml` (controller's `yaml.Unmarshal` ignores unknown keys, so older controllers are unaffected), field-by-field fallback. Needs a controller change to read it and catalog copy gates with an English rule. Cost 12–16 CC-hours. | **READY - rank P3-LOW; owner: CC (catalog + controller)** | | **R-561** | **[P3-LOW] Localisation slice 6 — the volunteer guide in English, then a stranger's first hour in English; closes R-516.** PLAN 2026-09-17 (10 §10). `runbooks/VOLUNTEER-first-hour.md`: 44 paragraphs, ~1 579 words. Then the 2026-09-14 walk repeated by an English speaker on a fresh box, R-516 closed against `audits/I18N-INVENTORY-2026-09-17.md`. Depends on R-556..R-560. Cost 6–8 CC-hours plus the attended walk. | **READY - rank P3-LOW; owner: CC** | | **R-562** | **[P3-LOW] Dates and sizes are not formatted for any locale — and the Hungarian pages disagree with themselves.** FOUND 2026-09-17 by the i18n inventory §2.8: the two template date layouts differ (`2006. 01. 02. 15:04` Hungarian vs `2006-01-02 15:04` ISO); 10 layout literals in `internal/web` Go and 25 elsewhere pick formats ad hoc; sizes print a decimal POINT (`%.1f GB`, 4 helpers) where Hungarian uses a comma; `timeAgo`/`nextRunLabel`/`pruneLabel` produce Hungarian words outside the three converted pages. Not changed by v0.247.0 (Hungarian bytes are frozen by the parity rule). **Fix shape:** one date and one size formatter per language in `internal/i18n`, the Hungarian output deliberately changed in ONE reviewed release with the parity fixtures re-captured for that release only and the change named in its CHANGELOG. Needs an operator word on the Hungarian format (comma, date style). | **READY - rank P3-LOW; owner: CC** | -| **R-563** | **[P3-LOW] `backups_remote.html` decides its progress poll by reading its OWN Hungarian status text — `v.textContent.indexOf('Fut')` — so an English page would never see a running off-site backup on load.** FOUND 2026-09-17 by the slice-1 comparison sweep (R-556, `audits/i18n-slice1-2026-09-17/A/A1-comparison-sweep.txt`): accented Hungarian in template/JS comparisons measured zero, but the ASCII-only word „Fut" is compared at `backups_remote.html` L288 against the stat value rendered at L48 („Fut…"). Same class as R-553 (behaviour decided by wording), one layer up in the browser. **Not converted in slice 1**: „Fut…" at L48 stays Hungarian on the English page so the poll keeps working. **Fix shape:** render a language-neutral marker (`data-status="running"`) beside the text and test that instead; then convert the word; a render test asserting the attribute. | **READY - rank P3-LOW; owner: CC** | | **R-564** | **[P3-LOW] The retrieval-promise gate's Hungarian stems cannot see a SPLIT verb — „csak akkor állíthatók vissza", „hozod vissza" — so those Hungarian sentences were never scanned; the English translation exposed them.** FOUND 2026-09-17 by slice 1 release B (R-556): after the gate learnt English (`EN_PATTERNS`), seven English retrieval phrases on `backups_remote`, `backups_escrow`, `backups_restore` and `backups_restore_wizard` had NO Hungarian registration, because their Hungarian carries the verb particle after the verb („A távoli mentések csak akkor állíthatók vissza …", „a távoli mentések CSAK ezzel a kóddal állíthatók vissza", „csak a hiányzó fájlokat hozod vissza"). The stems (`visszaállíthat`, `visszaszerezhet`, `visszahozhat`, `visszanyit`) match only the joined form. The seven were registered in English with reasons (none is a false promise: two are preconditions, five describe the action on the same page). **Fix shape:** add split-form patterns to the Hungarian scan (`állíthatók? vissza`, `(hoz|szerez|nyit)\w* vissza`), register the Hungarian occurrences found, decoy with a planted split-verb promise. | **READY - rank P3-LOW; owner: CC** | | **R-565** | **[P3-LOW] The English page test sees only ACCENTED Hungarian: an ASCII-only Hungarian word left in a template passes it on the English page.** FOUND 2026-09-17 by slice 1 release C (R-556, controller v0.250.0): after the extractor and the tests were green, a by-eye review of the English renders found six Hungarian fragments still in JavaScript strings — „, majd a(z)” and „FIGYELEM:” in the storage decommission dialog, „jelenlegi:” on the drive-init list, the uptime units „mp” and „p” and the count word „ db” on the debug page. All six were converted by hand; **no test failed on any of them**, because `TestI18nEnglishPages` looks for Hungarian letters and the extractor's ASCII word list (`i18n_extract.py` `ASCII_HU`) is used by neither test nor gate. Release B's review had found more of the same kind (Konfig, Megtartva, helyi, pl., Befejezve, automatikus, jelenleg:, kedd/szerda/szombat, szint). **Fix shape:** run the ASCII word list over the English renders in `TestI18nEnglishPages` (after the data mask), with a negative control on an English sentence and a decoy planting „mp” in an English value; extend the list with the words releases B and C found. | **READY - rank P3-LOW; owner: CC** | | **R-566** | **[P3-LOW] Three page titles are built in Go around an app name and stay Hungarian in the English browser tab: „ — Naplók”, „ — Telepítés” / „— Beállítások”, „2. mentés beállítása — ”.** FOUND 2026-09-17 by slice 1 release C while giving every static title a key (`TestHandlerTitleKeysMatchHungarianTitle` pins those): `handlers.go` logs (L413) and deploy (L435–439), `tier2_config_handler.go` L33 concatenate the app name into the Hungarian title, so `TitleKey` (one static message) cannot carry them. The page BODIES are English. Belongs to slice 2 (R-557, Go-side strings): a title key with a parameter (`page.title.logs` = „{{.App}} — Naplók”, expanded Go-side) and the pin test extended to the three sites. | **READY - rank P3-LOW; owner: CC** | | **R-567** | **[P3-LOW] The two drive wizard pages (/storage/init, /storage/attach) do not highlight the Tárhely menu group — the sidebar reads as if the household left the storage section.** FOUND 2026-09-17 by slice 1 release C: the release C parity cases first used page name `storage` for the wizards; re-captured with the handler's real page name (`storage_handlers.go` `storageWizardPageHandler` passes the TEMPLATE name, `storage_init`/`storage_attach`, as `Page`) the fixtures lost `nav-group is-open` and the `active` link. Present since the wizards shipped; not caused by localisation. **Fix shape:** pass `Page` `storage` (or teach the layout's storage group both names), with a render assertion that /storage/init carries the open storage group. | **READY - rank P3-LOW; owner: CC** | | **R-568** | **[P3-LOW] The dashboard's drive-health rows swap order between visits — the same two disks, listed in a different order a minute apart.** MEASURED 2026-09-17 on demo-hp 9201 during slice 1 release C's live proof: `/dashboard` fetched on 0.249.0 listed „KXG50PNV1T02 NVMe TOSHIBA 1024GB” then „SanDisk X600 M.2 2280 SATA 128GB”; fetched on 0.250.0 a minute later, the reverse (`audits/i18n-slice1-2026-09-17/C/live/hu-before-vs-after.txt`). `diskHealthRows` (`disk_health.go` L135–141) keeps the agent's response order and does not sort; the agent's order is therefore not stable. Cosmetic, but a household that reads „the second disk” finds a different one. **Fix shape:** sort the rows controller-side by a durable key (device path or serial), with a test that feeds two orders and expects one. | **READY - rank P3-LOW; owner: CC** | +| **R-569** | **[P3-LOW] Four more API handlers pick their status code by matching ENGLISH words in an error — the same shape as R-553, one language over.** FOUND 2026-09-17 while fixing R-553: `controller/internal/api/router.go` matches `"protected"`, `"not found"`, `"not deployed"`, `"still running"`, `"not orphaned"` in `err.Error()` at the stop/start, remove and orphan-cleanup handlers (three separate blocks). These strings are internal English, so localisation does not move them — the risk is a reworded internal error, not a translation, which is why this is P3 and was NOT folded into R-553's release. **Fix shape:** the same `util.KindErrorf` sentinels in `internal/stacks` (`ErrProtectedStack`, `ErrStackNotFound`, `ErrStillRunning`, …), a `statusFor` helper per handler family, and one table test per family passing a reworded message. | **READY - rank P3-LOW; owner: CC** | +| **R-570** | **[P3-LOW] The off-site stale-note display still has a Hungarian-text fallback, for boxes that have not run off-site since v0.251.0.** OPENED 2026-09-17 by R-553's fix: `offboxWarningDisplay` (controller/internal/web/handlers.go) decides on `LastWarningKind`, but a box upgraded to 0.251.0 carries the PERSISTED old sentence with no kind until its next off-site run rewrites it, so the substring test survives under `kind == ""`. **Close when every fleet box has completed one off-site run on ≥ 0.251.0** (the hub's reports carry the controller version; the off-site anchor is `offbox.last_success`), then delete the fallback, its constant and its legacy test rows. **Hard dependency: localisation slice 2 (R-557) must NOT translate the producer `"Sikeres — nincs mentésre jelölt alkalmazás"` (controller/internal/backup/offbox.go) until this row closes** — translating it while the fallback is load-bearing strands exactly those boxes. | **WATCHING - rank P3-LOW; owner: operator (the fleet condition), CC (the deletion)** | +| **R-571** | **[P3-LOW] The off-site failure classifier and the dashboard's alert-placement rules are described in no architecture document.** FOUND 2026-09-17 while fixing R-553: `07-backup-architecture.md` and `02-controller-module-map.md` grep clean for `ClassifyOffsiteFailure`, `Inline` and `PageOnly`, so the six failure classes (quota / orphaned / no-repo / no-units / transport / unknown), the head lines they pick and the rule that one warning renders inline under the storage bars while every other renders in the top banner exist only in code. `10-localisation.md` §9 now names the SIGNALS each decision reads; the behaviour itself still has no home. **Fix shape:** a short section in `07-backup-architecture.md` for the classifier (its classes, what each means for the customer, and that restic/ssh text signatures are external) and one in `02-controller-module-map.md` for alert placement. | **READY - rank P3-LOW; owner: CC** | | **R-537** | **[P1-HIGH] The app-backup page labels the tier-1 backup „DB + Konfig + Adatok" and prints the app's data-drive size next to it — but the tier-1 unit contains NO drive-side app data at all.** MEASURED 2026-09-16 on the drill box (fresh install, controller 0.243.0, one drive, tier 2 and tier 3 both „Nincs beállítva"): five photos (3 000 000 B) were uploaded into Nextcloud through its own WebDAV interface, then the customer-visible „Mentés most" was pressed (`POST /api/backup/run` → 200, the unit grew 25 337 B → 978 MB). The resulting unit's `manifest.json` lists `db-dumps` + three **docker volume** dumps and nothing else; listing the 781 MB `nextcloud_nextcloud_html.tar` (29 346 entries, positive control `version.php` = 3 hits) gives **`Fotok` = 0 and `nyaralas` = 0**, and `./data/` is the empty bind-mount point. A `find` over the whole `backups/` tree for `*appdata*` / `*Fotok*` returns nothing. The page nevertheless renders „1. mentés … DB + Konfig + Adatok" and „Nextcloud Adatlemez 65.1 MB" — a size measured on exactly the data it does not copy (`internal/web/handlers.go:1176-1178`, `BackupContents`). **This is a truth defect, not a design defect:** `07-backup-architecture.md` §6.2 places nextcloud's file leg at **Tier 2 and Tier 3 only**, and its „[FACT] What the whole-guest tiers do NOT carry" says `mp8 /mnt/felhom-drives` is out of vzdump scope (confirmed live: „excluding bind mount point mp8 … (not a volume)"). So on a one-drive box with no off-site tier — the state every fresh install starts in — the household's files are in **no backup**, while the page says „Adatok". Same family as R-517/R-518. **Fix shape:** render tier-1 contents from the capture set actually written (`ComputeCaptureSet`), so a unit with no file leg reads „DB + Konfig" and the drive size is not shown beside it; and say on the page that the app's files need tier 2 or tier 3. Evidence: `audits/evidence-drill-0243-2026-09-16/phase2-f10.txt`. **CLOSED 2026-09-16 — controller v0.244.0, proven live.** The contents label is computed PER TIER from what that tier captures: Tier 1 says „Adatok" only when the app's data really is in the volumes the unit captured, and a class-A app carries one sentence saying where its files ARE protected. Proven on demo-hp through the page the customer opens: Paperless-ngx reads „1. mentés … DB + Konfig" with „Az alkalmazás fájljait a távoli másolat (és a második meghajtó) védi …", while its „2. mentés" row still reads „DB + Konfig + Adatok". Red-proof: restoring the old app-shaped label fails `TestAppBackupRows_Tier1LabelDoesNotClaimFilesItCannotHold`. **RE-PROVEN 2026-09-16 on a FRESH box** (installed from the built ISO 1.28.0, controller 0.244.0, off-site on by default): the Nextcloud row read „1. mentés … DB + Konfig" with the new sentence, „2. mentés … Nincs 2. (off-drive) másolat", „3. mentés Sikeres restic → …your-storagebox.de"; „DB + Konfig + Adatok" appeared ZERO times while the local unit held no file leg. | **CLOSED 2026-09-16 — controller v0.244.0 (proven live on demo-hp)** | | **R-538** | **[P1-HIGH] A tier-1 app restore reports plain success and leaves Nextcloud listing files whose bytes were never in the backup — and it destroys the app's own trash, the customer's last copy.** MEASURED 2026-09-16 on the drill box, F10 („a child deletes the photo folder"): the five photos were deleted through Nextcloud (DELETE 204, PROPFIND 404), then restored through the page exactly as a customer would (`POST /backup/restore` `stack_name=nextcloud` `snapshot_id=helyi` → 302, finished in **35 s**, „A(z) nextcloud: 3 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult."). Afterwards the folder is back and **lists all five photos**, and **none of them opens**: `GET nyaralas-1..5` = 404 / 503×4 with `Sabre\DAV\Exception\NotFound`, while the positive controls at the same moment pass (`status.php` 200, WebDAV PUT 201, GET 200). Cause: the replayed MariaDB dump (11:01:45Z) knows the photos, the bytes live on `mp8` and were never captured (R-537). **Worse:** the bytes were still on the drive in Nextcloud's own trash (`appdata/nextcloud/admin/files_trashbin/files/Fotok.d1789556707/nyaralas-1..5.jpg`, all five present) and the restored database no longer references them — the trash listing comes back **empty**, so „restore from trash", the one route that would have worked, is gone. The customer is left with five unopenable photos, a success message, and no warning. **Fix shape:** before replaying a database whose app has an uncaptured file leg, refuse or warn („ennek az alkalmazásnak a fájljai nincsenek ebben a mentésben — a visszaállítás után a fájlok hiányozni fognak"); and never present a DB-only restore of a class-A app as a complete one. Evidence: `audits/evidence-drill-0243-2026-09-16/phase2-f10.txt`. **CLOSED 2026-09-16 — controller v0.244.0, proven live.** A unit restore refuses before anything is touched when the unit cannot return the app's drive-side files, and names the route that can. Fired live on demo-hp: `POST /backup/restore` for paperless-ngx → 302 with „Ez a mentés nem tartalmazza az alkalmazás fájljait, ezért nem állítjuk vissza az adatbázist föléjük — a fájlok így a helyükön maradnak. A fájlok a távoli másolatból állíthatók vissza …", and the app read `running` before AND after, so nothing was stopped and no trash was made unreachable. The database-and-settings-only path exists as a separately worded second step. Red-proof: disabling the guard fails `TestUnitRestore_RefusesWhenTheUnitCannotHoldTheFiles`. **RE-PROVEN 2026-09-16 on a FRESH box, and this time the refusal had somewhere to point:** after five photos were deleted, `POST /backup/restore` was refused with „…a fájlok így a helyükön maradnak. A fájlok a távoli másolatból állíthatók vissza: … „Teljes visszaállítás (fájlok + adatbázis)"", the app read `running` before AND after, and the wastebasket was untouched. The off-site route then returned all five photos — 200 with the exact uploaded sizes and sha256 IDENTICAL to the originals, 5/5, with a negative control. Evidence: `audits/evidence-backup-promise-2026-09-16/phaseE-photos.txt`. | **CLOSED 2026-09-16 — controller v0.244.0 (proven live on demo-hp)** | | **R-525** | **[P3-LOW] FileBrowser has its own login; putting it behind the dashboard session (traefik forwardAuth or Quantum proxy auth) is a new mechanism nobody has measured.** Filed 2026-09-15 by the P1-fixes task (B.5). R-513 closed the default-password hole with a generated password; a household still has two logins. **What it needs:** a spike on a scratch guest — forwardAuth to the controller session, and what FileBrowser Quantum does with a trusted header. | **READY — rank P3-LOW; owner: CC (spike)** |