From bd22749e501540cfe2526408613832fef29f8de7 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 21 Sep 2026 12:59:35 +0200 Subject: [PATCH] REPORT for the R-469 rule lift Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- REPORT.md | 218 ++++++++++++++---------------------------------------- 1 file changed, 56 insertions(+), 162 deletions(-) diff --git a/REPORT.md b/REPORT.md index ce54011..311b50a 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,176 +1,70 @@ -# REPORT — the app catalog speaks English (R-560 slice 5, Parts B and C) +# REPORT — the engine-major rule, half lifted (R-469 + R-450) -2026-09-20 · catalog `main` at the batch-3 commit · needs controller **v0.257.0**, which is now the -fleet floor. **All 53 apps translated; 1 031 of 1 032 strings.** +**Base `18a6d2d8243e` → `5ff36d098cbc`.** No template moved. Architecture read first and named: +`felhom.eu/documentation/architecture/09-update-architecture.md` §3 decision 5 (the 2026-09-13 ruling +and its three precautions) and §6.1 (slice 4 as shipped). ---- +## Why now -## For the operator, in one paragraph +The rule of 2026-09-13 named its own expiry — *until the Update button takes a verified backup as its +precondition* — **precisely so it would be removed deliberately rather than forgotten.** That +condition was met the same day: update arc Slice 4 shipped (controller v0.237.0/v0.238.0; any backup +tier since v0.239.0). R-469 exists to make the removal a reviewed diff. This is it, and it removes +exactly half. -Every app now describes itself in English. You read three of them and said go; the other fifty follow -that same voice. The English app list on the demo box shows **no Hungarian app text at all**. The -Hungarian pages are unchanged down to the byte. One single line is still Hungarian on purpose — it is -wrong in Hungarian, and fixing Hungarian words is not something a translation release may do. +## What changed ---- +- **LIFTED — MariaDB.** The four `mariadb:` sidecars (`bookstack-db`, `kimai-db`, `nextcloud-db`, + `romm-db`) may cross a major. They now have both halves: a verified backup in front of the Update, + and `MARIADB_AUTO_UPGRADE=1` (R-459) whose conversion the harness WATCHED run on the E3/E3b edges + with the seeded data read back after. +- **NOT LIFTED — PostgreSQL and MySQL.** Postgres performs no `pg_upgrade` and REFUSES to start on an + older major's datadir, across eleven templates (R-463). **A backup is a route BACK, not a + conversion** — the app would simply not come up. MySQL has nothing measured at all. The refusal + text now says this, instead of citing the shipped R-448. +- **NEW — one edge, one migration (R-450's second half, recorded 2026-09-02, enforced now).** A + MariaDB major must be the ONLY image move in its template in that commit. bookstack's `0b73e5e` + moved the application 25.02.2 → 26.05.2 **and** MariaDB 11.6 → 12.3 together: two migrations behind + one edge, and an unreadable failure when it breaks. The refusal names what it was bundled with. + **Within a major is unaffected** and may still ride with anything. +- **The gate PRINTS what it allowed**, by name and with the reason, rather than passing in silence. A + lifted rule that goes quiet is a lifted rule nobody can audit. -## What shipped, in order +## Red-proofs — two, each SEEN to fail -| commit | what | strings | -|---|---|---| -| the freeze, alone | `scripts/copy_freeze/hu.json` — every Hungarian copy string, captured before any translation existed | 1 032 frozen | -| the gate | `scripts/check-copy-i18n.py`, fifth row of `catalog_gates.py`, + 18 decoy cases | — | -| the pilot | privatebin, paperless-ngx, romm | 89 | -| batch 1 | 17 apps | 319 | -| batch 2 | 17 apps | 317 | -| batch 3 | 16 apps | 306 | +| the mutation | what failed | +|---|---| +| drop the own-edge check (`others = []`) | *FACT: kimai-db 11.6 → 12.3 BUNDLED with the kimai app bump: rc=0 expected 1* — the bookstack shape passes | +| empty `LIFTED` | *GENUINE: kimai-db 11.6 → 12.3 ALONE (the R-469 lift): rc=1 expected 0* — the lift is undone | -`EN_MISSING_CEILING`: 1032 → 943 → 624 → 307 → **1**. +Both reverted; **40 decoy cases green**. The old *"a lone MariaDB major is REFUSED"* case is now the +*"…is ALLOWED"* case — that inversion is the lift itself. A third case pins the bundled PostgreSQL +shape. -**No image, no pin, no `catalog_since`, no compose line changed in any of them.** A translation is not -a version bump of an app. +`catalog_gates.py --fast`: image-pins, engine-major, catalog-since, copy-i18n — **all OK**. The +pre-push hook ran and passed; no `--no-verify`. -## The blocks are generated, not hand-written — and that is a decision +## Measured while here, and it belongs in this repo's record -Fifty nested YAML blocks whose keys must match the Hungarian side exactly is fifty chances to mistype -an `env_var`. **A mistyped key is INERT on the box rather than an error** — the app simply keeps -showing Hungarian for that field and nobody learns. So each app's English is a flat -`{path: english}` map and a generator builds the block from the same paths the freeze uses, which are -derived from the Hungarian file itself. A key that does not exist on the Hungarian side cannot be -written at all, and review happens on the map, where one line is one string. +A read-only sweep of all 66 unique pins against the public registries, from DooPlex, never from a box +(`felhom.eu/documentation/audits/UPDATE-ARC-STATE-2026-09-21.md` §3): -## The one string deliberately left in Hungarian +- **46 of 58 exact pins are behind upstream today**; 39 within a major, 7 across one. The seven were + all pinned 2026-07-18: nextcloud 34→35, paperless-ngx 2.20→3.2, claper 2.5→3.0, gokapi 1.9→2.2, + homepage 1.13→2.4, sparkyfitness 0.17→1.7 (two images). +- **6 of the 7 measurable floating pins have been repushed upstream since the catalog set them** — + `postgres:16-alpine`, `postgres:15-alpine`, `redis:7-alpine`, `mariadb:11.4`, `mariadb:12.3`, + `postgis:16-3.5-alpine`. Only `mariadb:11.6` has not. This is R-446 measured rather than theorised, + and it is the case for recording digests at push time (put to the operator as `09` §3b Q6). +- **`msdeluise/plant-it:0.10.0` is gone upstream.** The repo's own gate says INCONCLUSIVE (it refuses + to read a `denied` stderr as "dead", correctly); two independent signals say it really is gone — + Docker Hub's catalog API answers `object not found` for the whole repository, and the upstream + GitHub repo 404s. The app is already `lifecycle: abandoned`, so this is the expected end state, not + an incident. A deployed plant-it survives; it can never be redeployed. -papra's `deploy_fields[AUTH_SECRET].description` reads „Az alkalmazás aldomainje" — the sentence that -belongs on `SUBDOMAIN`, sitting on a session-signing key. That is a **Hungarian defect** (R-593). A -localisation release may not change Hungarian bytes, and translating a wrong sentence faithfully would -ship the error in a second language, so it falls back. +## Rows -**The ceiling's floor is therefore 1, not 0, and that is written into the ceiling's own comment** — so -a later session cannot "reach zero" by quietly editing Hungarian. - -## Per-app table - -| app | copy strings | English | push | live-checked | -|---|---|---|---|---| -| actualbudget | 15 | 15 | batch 3 | gate only | -| adventurelog | 17 | 17 | batch 1 | yes | -| audiobookshelf | 21 | 21 | batch 2 | gate only | -| bentopdf | 14 | 14 | batch 1 | yes | -| bookstack | 19 | 19 | batch 1 | yes | -| calcom | 21 | 21 | batch 1 | gate only | -| calibre-web | 24 | 24 | batch 1 | yes | -| claper | 17 | 17 | batch 3 | gate only | -| code-server | 20 | 20 | batch 2 | gate only | -| crafty-controller | 24 | 24 | batch 2 | gate only | -| docmost | 19 | 19 | batch 3 | gate only | -| emby | 22 | 22 | batch 3 | gate only | -| ghost | 16 | 16 | batch 1 | gate only | -| gitea | 16 | 16 | batch 3 | yes | -| glance | 15 | 15 | batch 2 | gate only | -| gokapi | 19 | 19 | batch 2 | gate only | -| grafana | 19 | 19 | batch 1 | gate only | -| gramps-web | 16 | 16 | batch 2 | gate only | -| home-assistant | 18 | 18 | batch 1 | gate only | -| homebox | 16 | 16 | batch 1 | gate only | -| homepage | 15 | 15 | batch 1 | gate only | -| immich | 24 | 24 | batch 3 | yes | -| jellyfin | 22 | 22 | batch 2 | gate only | -| kimai | 20 | 20 | batch 3 | gate only | -| komga | 21 | 21 | batch 3 | gate only | -| mealie | 17 | 17 | batch 2 | gate only | -| n8n | 17 | 17 | batch 1 | gate only | -| navidrome | 21 | 21 | batch 2 | gate only | -| nextcloud | 28 | 28 | batch 1 | gate only | -| onlyoffice | 24 | 24 | batch 3 | gate only | -| opengist | 15 | 15 | batch 3 | yes | -| outline | 21 | 21 | batch 1 | gate only | -| paperless-ngx | 33 | 33 | pilot | yes | -| papra | 14 | 13 **(1 left — R-593)** | batch 1 | gate only | -| plant-it | 16 | 16 | batch 3 | gate only | -| plex | 25 | 25 | batch 2 | gate only | -| privatebin | 14 | 14 | pilot | yes | -| radarr | 22 | 22 | batch 1 | gate only | -| rallly | 17 | 17 | batch 3 | gate only | -| recipe-importer | 19 | 19 | batch 3 | yes | -| romm | 42 | 42 | pilot | yes | -| seerr | 18 | 18 | batch 3 | gate only | -| sonarr | 22 | 22 | batch 2 | gate only | -| sparkyfitness | 20 | 20 | batch 1 | gate only | -| tandoor | 18 | 18 | batch 2 | gate only | -| termix | 11 | 11 | batch 2 | gate only | -| uptime-kuma | 16 | 16 | batch 2 | gate only | -| vaultwarden | 23 | 23 | batch 3 | yes | -| vikunja | 17 | 17 | batch 2 | gate only | -| wanderer | 19 | 19 | batch 1 | gate only | -| wger | 18 | 18 | batch 2 | gate only | -| wishlist | 15 | 15 | batch 2 | gate only | -| zipline | 20 | 20 | batch 3 | gate only | -| **total** | **1032** | **1031** | | **12 apps checked live** | - - -## Unverified UI labels — for the slice-6 walk (R-561) - -These English lines name a button or a menu inside the app's **own** interface. No gate and no -endpoint can tell whether the app shows that word in English; somebody has to open it. - -| app | the line | what to check | -|---|---|---| -| privatebin | "Type your text and select **Send**" | PrivateBin's send button | -| paperless-ngx | "Create **tags and correspondents**" | Paperless's English words for these two | -| romm | "in the **Settings** menu" / "Start a **Scan** from the menu on the left" | RomM's menu and button labels | -| grafana | "(**Connections > Data Sources**)" | Grafana's menu path in English | -| crafty-controller | "**server.properties -> server-port**" | a file key, not a UI label — but the port range is a claim worth re-checking | -| vaultwarden | 'the "**Users**" tab, "**Invite User**"', '"**Create account**"' | Vaultwarden's English admin labels | -| immich | "**Administration -> External Libraries**" | Immich's English menu path | -| recipe-importer | "**Profile -> API Tokens**" (Mealie), "**Settings -> API Browser -> Auth Token**" (Tandoor) | two other apps' English menu paths | -| komga | "**Tachiyomi**" | an app name, verbatim — no check needed, listed for completeness | -| calibre-web | "the **import/calibre** folder in the File manager (FileBrowser)" | Felhom's own File manager - right by construction unless the controller bundle changes | - -Several apps' English also names **Felhom's own** interface (Settings, File manager, Automatically -generated values). Those come from the controller's English bundle and are right by construction. - -## Judgement calls, recorded rather than hidden - -- **Jellyfin** told the reader to pick Hungarian in the setup wizard. For an English household that is - wrong advice, so the English reads "choose your language". The Hungarian is untouched. -- **Mealie's** „multilingual - Hungarian is available too" became "A multilingual interface - English - and Hungarian among them": the same fact, seen from the reader's side. -- **recipe-importer** imports from six Hungarian recipe sites. Its English says exactly that and names - the sites; it is not a general importer and the English must not pretend it is. -- **Vaultwarden's** two select options keep the recommendation on the same option: "No - by invitation - only (recommended)". - -## The gate convicted two of my own sentences, and was half right - -Vaultwarden's invite step and sign-up setting both ended "…can open an account". The English -retrieval-promise pattern reads `can … open` as the claim that **sealed backups** can be opened, so it -convicted. Opening an ACCOUNT is not that claim — a false positive — but the wording was also the -weaker wording, so both now read "can sign up", which is what a household would say. - -**The structural gap is that the gate can convict a promise but cannot REGISTER a true one**, which is -exactly what the shared vocabulary's design calls for. Filed as R-594. Rewording was honest today; the -first genuinely true "can be restored" in catalog copy will need the mechanism. - -## Live proof - -Endpoint level, from inside the guest, with the customer `Host` header and a real session — the same -handlers and templates a browser drives, with only the drawing skipped. - -- **The English Apps list on demo-hp shows ZERO Hungarian app descriptions across all 53 apps.** The - only Hungarian left on that page is the „Naprakész" badge (R-589, ten occurrences) and the language - picker naming itself, which is correct. -- **The Hungarian Apps list is identical** to the capture taken before the pilot, once the per-session - CSRF token and Docker's own „Up N hours" string are normalised. -- **Twelve apps were opened individually** in both languages across the pushes (the table's last - column). -- **The second demo box took the new controller by itself** when the floor was raised, and then - rendered the English tagline — so the mechanism works on a box nobody touched by hand. - -Evidence: `felhom.eu/documentation/audits/i18n-slice5-2026-09-20/`. - -## Teardown - -Nothing installed, nothing removed, no app deployed. Template files changed on both demo boxes, which -is what a catalog sync does. Every staged password file and capture script was shredded from both -Proxmox hosts and both guests; `ls` confirms. Both boxes left on Hungarian. +**R-469 PARTLY CLOSED** (MariaDB lifted; the PostgreSQL half stands until R-463). +**R-450 half SHIPPED** (the own-edge clause; the automatic-within-a-major half is Slice 6 and awaits +`09` §3b Q1–Q4). **R-605 filed** — a catalog gate that refused to run and one that ran and could not +decide print the same word.