REPORT: the pilot's English quoted in full for the operator's read (R-560)
gates / gates (push) Failing after 2s

The three apps' English text, the per-app table, the unverified UI labels for the
slice-6 walk, the gate's five checks and the three defects its own decoys found in
it, and the live proof on both demo boxes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-20 14:44:02 +02:00
parent e81d41e527
commit d9aa02a93f
+196 -25
View File
@@ -1,32 +1,203 @@
# REPORT — vaultwarden closed by default, paperless-ngx sized for a batch (2026-09-15) # REPORT — localisation slice 5, Part B: the copy freeze, the gate, and the English pilot (R-560)
Task: *before the volunteer — the big night's P1 fixes*, Part E. No image or version change. 2026-09-20 · catalog `main` `e81d41e` · needs controller **v0.257.0** to render · Part C not started.
## What changed ---
- **vaultwarden (R-512):** `SIGNUPS_ALLOWED` defaults to `false`; the select explains both choices; „Első lépések" is
invite-first (admin panel with the generated token → invite → create account); the compose header no longer tells
anyone to change a setting after install.
- **paperless-ngx (R-514, R-515):** `PAPERLESS_TASK_WORKERS=1`, `THREADS_PER_WORKER=1`, webserver `memory: 1280M`
(`mem_limit` hint 1664M); `default_creds: admin / admin` removed; first steps point at the generated password.
## Measured first ## For the operator — the one thing you have to do
- **E.1 spike** (throwaway container on scratch 9202, SMTP off as on a box without app-email): stranger register **400**,
admin invite **200**, invited register **200**, second stranger **400**. So invite-first needs no controller change.
- **E.2** (1 worker × 1 thread, no cap): 20 three-page PDFs → **20/20**, `memory.peak` 783 294 464 B → cap = peak × 1.5
rounded up to 256M = **1280M**. Caveat: the PDFs carried text, so OCR on scanned images may need more.
## Proven live after the change (scratch 9202, deployed from the catalog through the controller API) **Read the English below (it is short) and say "go", or say what to change.** Fifty more apps follow
- Vaultwarden: container `SIGNUPS_ALLOWED=false`; stranger `send-verification-email` via traefik → **400 „Registration whatever you say. Ten minutes now against a day of rework later. Everything else in this report is
not allowed or user already exists"**; the app page shows the invite steps (fragment 1, negative control 0). for the record.
*One invalid attempt first: a hand-built register body got 422 (did not parse) — marked invalid in the evidence.*
- Paperless: 20 PDFs posted at once → tasks **20 SUCCESS**, documents **20**, limit 1 342 177 280 B, `memory.peak` ---
**772 370 432 B**, OOMKilled false, 0 kernel OOM lines.
- Forcing an OOM (cap 128M) showed Docker reports nothing in an LXC guest (R-528, a controller/agent row). **Mistake, ## The three pilot apps, in full, for your read
stated:** restoring the cap on the throwaway with a broad `sed` also changed its redis cap; moot, the stack was removed.
### PrivateBin
> **What it is:** Encrypted note and text sharing
> **Tagline:** Encrypted text sharing - the server never sees the content
**What it is for**
- Share sensitive text safely
- End-to-end encryption - the server cannot reach the content
- You choose how long it lasts (5 minutes to 1 year, or never)
- Optional: delete it automatically after it is read
- Password protection for extra safety
**First steps**
1. Open paste.DOMAIN in your browser
2. Type your text and select Send
3. Share the link you get - the encryption key is part of the URL
**Install settings:** Domain — "The server domain name" · Subdomain — "The subdomain this app
answers on"
### Paperless-ngx
> **What it is:** Digitise your documents and keep them in order
> **Tagline:** A digital filing cabinet - scanning, OCR and automatic sorting
**What it is for**
- Turn paper documents into files and keep them in order
- Automatic OCR text recognition on scanned documents
- Smart automatic sorting and tagging
- Full text search across every document
- Documents that arrive by e-mail are processed automatically
**First steps**
1. Open paperless.DOMAIN in your browser
2. Sign in: user "admin". The password is on the Settings page, under Automatically generated values
3. Upload a document in the app, OR drop it into the import/paperless folder in the File manager
(FileBrowser) - it is read in and processed with OCR from there. The File manager sign-in is on
the File manager app page
4. You can upload many documents at once: they are processed one by one, and a larger batch takes a
few minutes
5. Create tags and correspondents so new documents sort themselves
**Before you start**
- An external hard drive is recommended to keep the documents on
- At least 1 GB of free RAM (for the OCR work)
**Install settings:** Database password · Encryption key · Admin user name · Admin password ("For
the first sign-in. You can change it in the app afterwards.") · Data storage path ("The path to the
external hard drive where the documents are kept") · OCR language (Hungarian / English / Hungarian +
English / German + English — "The language the text recognition reads") · Folder label: "Documents
to read in"
### RomM
> **What it is:** Retro game collection manager
> **Tagline:** Retro game collection manager, browser and player
**What it is for**
- Sort and browse a retro game collection in your browser
- Game details download themselves - cover art, descriptions, ratings
- Filter and search the whole collection by platform
- Upload and download ROM files in your browser
- Several people in the household can have their own account
**First steps**
1. Open arcade.DOMAIN in your browser
2. Sign in with the default admin / admin account
3. Change the password straight away, in the Settings menu
4. Upload the ROM files into the roms/ folder in the File manager (FileBrowser), sorted into
platform folders (for example roms/gba/, roms/snes/)
5. Start a Scan from the menu on the left to read the ROMs in
6. Optional: set up metadata providers so cover art and descriptions download themselves (see below)
**Before you start**
- An external hard drive is needed to keep the ROM files and cover art on
- At least 1 GB of free RAM is recommended (MariaDB + Redis + RomM)
- ROM files sorted into platform folders (for example roms/gba/, roms/snes/)
**Optional settings — "Metadata providers":** "So that cover art, descriptions and ratings download
themselves. IGDB is the one worth setting up first. All of them are free after you sign up." · six
key fields with their own sign-up instructions · Folder label: "ROM collection"
---
## Per-app table
| app | copy strings | English | list-length exceptions | push | live-checked |
|---|---|---|---|---|---|
| privatebin | 14 | 14 | none | pilot | **yes** — app page, Apps list |
| paperless-ngx | 33 | 33 | none | pilot | **yes** — app page, deploy page, Apps list |
| romm | 42 | 42 | none | pilot | **yes** — app page, deploy page, Apps list |
| the other 50 | 943 | 0 | — | — | — |
| **total** | **1 032** | **89** | **none** | | |
No app needed a list-length exception: every English list has exactly as many entries as its
Hungarian twin, which is what the gate requires unless the file carries a stated reason.
## Unverified UI labels — for the slice-6 walk (R-561)
These English lines name a button or a menu in the app's OWN interface. No gate and no endpoint can
tell whether the app actually shows that word in English; somebody has to open it.
| app | the line | what has to be checked |
|---|---|---|
| privatebin | "Type your text and select **Send**" | PrivateBin's send button's English label |
| paperless-ngx | "under **Automatically generated values**" | this is Felhom's own Settings page — taken from the controller's English bundle, so it is right by construction unless that bundle changes |
| paperless-ngx | "Create **tags and correspondents**" | Paperless's English words for these two |
| romm | "Change the password straight away, in the **Settings** menu" | RomM's English menu label |
| romm | "Start a **Scan** from the menu on the left" | RomM's English button label |
## What changed in this repo
**Three commits, in this order, and the order is the point.**
1. `0c19b45` — **the freeze alone.** `scripts/copy_freeze/hu.json`: every customer-facing Hungarian
string in the catalog, 1 032 of them across 53 apps, captured from the commit before any
translation existed. Its own commit so that a baseline cannot be said to have arrived with the
checker that reads it.
2. `84e0584` — **the gate.** `scripts/check-copy-i18n.py`, fifth row of `catalog_gates.py`, static
and in the pre-push hook: the Hungarian freeze, the English block's structure, its language, its
credential tokens, and a coverage ratchet. 18 new decoy cases.
3. `e81d41e` — **the pilot.** Three apps, 89 strings, `EN_MISSING_CEILING` 1032 → 943.
**No image, no pin, no `catalog_since`, no compose line changed.** A translation is not a version
bump of an app.
## What the gate checks, and what it cannot
| # | check | convicts on |
|---|---|---|
| 1 | FREEZE | any Hungarian copy string that differs from the freeze, is new, or has gone. Runs on all 53 apps whatever scope is named — a scoped push that quietly edits a neighbour is what a freeze is for. A new app must be admitted with `--add-app NAME --reason "…"` |
| 2 | STRUCTURE | a key the English block may not carry; an `env_var`, option `value`, `match_group`, `target` or `path` with no Hungarian twin (it would be INERT on the box and the translator would never learn); a list whose length differs from the Hungarian |
| 3 | LANGUAGE | an accented Hungarian letter; **ASCII-only Hungarian**; "please"/"kindly"; an English retrieval promise the Hungarian does not make; a dropped app name or „Felhom" |
| 4 | CREDENTIALS | a login token inside `default_creds` or an initial-credentials note that did not survive translation, matched on WORD boundaries |
| 5 | RATCHET | a coverage count above **or** below `EN_MISSING_CEILING`, counted over the whole catalog whatever scope is named |
**It cannot judge whether the English says what the Hungarian says**, and it cannot judge whether an
app's first steps match that app's real screens. The first is your read above; the second is the
table before it.
## Numbers that were wrong in the plan, corrected by measurement
| | the plan said | measured on `94bc5febaca2` |
|---|---|---|
| copy strings | 835 | **1 032** (it omitted 13 `placeholder` values, and every ASCII-only label) |
| with a Hungarian letter | 832 | **832** ✔ |
| ASCII-only Hungarian | three — „Igen", „Nem", „Nincs" | **~120**, and those three do not occur in this catalog at all |
The last row decides an instrument rather than a footnote. „Aldomain" appears 53 times and „A szerver
domain neve" 53 times; both are Hungarian with no accent in them. **A gate that scans for accents
passes every one of them inside an English block.** So check 3 folds the text and matches word-bounded
stems, and prints a positive and two negative controls on every run.
## Three defects in the gate, each found by a decoy rather than by reading it (R-592)
1. **Coverage was counted only for the apps named on the command line.** `check-copy-i18n.py
privatebin` reported 47 more untranslated strings than the same tree unscoped — a ratchet anybody
could loosen by naming one app.
2. **The credential check matched its token as a bare substring**, so „admin / adminadmin" translated
to "administrator / hunter2" passed: "admin" is inside "administrator".
3. **The ASCII-Hungarian stems matched as bare substrings too**, so „ird be" convicted "the third
best" and „angol" convicted "Angola".
All three now have their own case. 33 decoy cases in total, every one seen to convict or to pass as
intended.
## Live proof
Endpoint-level, from inside the guest, with the customer `Host` header and a real session — the same
handlers and templates the browser drives, only the drawing skipped. Said plainly because "the page
shows X" has to name how it was seen.
- **demo-hp (controller 0.257.0):** the three English app pages, the Apps list and two deploy pages
show the English catalog text. The seven **Hungarian** pages are byte-identical before and after the
push apart from the per-session CSRF token.
- **demo-felhom (controller 0.255.0, deliberately old):** with the pilot synced onto the box —
confirmed positively, the sync named the three apps and the block is present in both the cache and
the stack copy — its pages hash identically before and after and its log carries no parse warning,
in a 93-line window that includes the sync's own lines.
Evidence: `felhom.eu/documentation/audits/i18n-slice5-2026-09-20/`.
## Teardown ## Teardown
Machine: scratch 9202's throwaway `paperless-ngx` and `vaultwarden` stopped and removed (volumes removed; the paperless
data folder on the scratch drive kept, the product default). Host: nothing. Hub: nothing (9202 reports to no hub).
## Gates Nothing installed, nothing removed, no app deployed. Three template files changed on each demo box,
`catalog_gates.py --fast` OK on every push. Evidence: `felhom.eu/documentation/audits/evidence-p1fixes-2026-09-15/E1-*`, `E2-*`, `teardown-9202.txt`. which is what a catalog sync does. The staged password file and the capture scripts were shredded from
both Proxmox hosts and both guests. Both boxes left on Hungarian.