diff --git a/STATUS.md b/STATUS.md index 33bac5a4..b5a3d9f6 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,30 +1,44 @@ # STATUS — what works, what's broken, what's next -**Updated 2026-09-17 (late) — five hidden traps removed before the next language step.** +**Updated 2026-09-18 — the sentences the program writes now follow the language.** -> **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. +> **Ready for a volunteer: yes, unchanged.** A Hungarian household sees exactly what it saw +> yesterday. I did not read the pages to decide that — I compared them, letter by letter. -**Decisions I took.** None. +**Decisions I took.** None. One choice you were asked for stayed on its own stated default: notes +saved to disk at night (last error, last warning) will be written in the box's language at the time +they are written. A household that switches language sees last night's note in the old language until +the next run. That is option 1 in the plan, and the plan says it is what happens if nobody decides. -**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 I exercised, on the demo HP box.** The pages were already English. The SENTENCES the program +writes into them were not — "Saved.", "The remote target is not set.", the country names, the yellow +banners at the top. I moved 226 of them, and they now follow the language. Two I want to name: -**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. +- **The little green "done" line after you press a button.** It travels inside the web address, so + it is written by one page and read by the next. It used to be written in whoever's language came + first. It now travels as a short code and the page you land on writes the sentence. A link you + already have open from before still shows its old sentence, word for word — I checked that live. +- **The country list.** All 237 names, and the list re-sorts itself, so the English list really is in + English alphabetical order and not Hungarian order with English words in it. -**Rows.** Two closed, three opened. The register went from **263** to **264** open rows. +**How I know Hungarian did not change.** A new check freezes every Hungarian sentence in the program +as it stood before I started — 7 467 of them — and refuses any sentence that is not exactly that, +down to a comma. It caught a real mistake in itself on the first run and I fixed the check. Then on +the box: ten Hungarian pages before and after. Six identical. The other four differ only in things +that move on their own — a clock ticking over, an app that was unhealthy for a minute, and the +"update available" line, which is true on the old version and not on the new one. + +**What I deliberately did NOT translate.** Anything the central service reads and turns into an +e-mail to the household. I checked, and found the plan was wrong about this: the service does not +always write its own e-mail — for several kinds of message it sends the box's own sentence straight +on. Translating those here would have changed an e-mail nobody asked to change. They are now frozen +by a test, and they get their turn in the next step. + +**What is not done yet.** About 900 sentences remain. 176 of them are error messages, which is the +next release; the rest are notes saved to disk, which is the one after. Four smaller gaps I found +while working are written down with a number each. + +**Rows.** One closed, three opened. The register went from **264** to **266** 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. diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/README.md b/documentation/audits/i18n-slice2-2026-09-18/A/live/README.md new file mode 100644 index 00000000..df1a6315 --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/README.md @@ -0,0 +1,80 @@ +# Live validation — controller v0.252.0 on demo-hp guest 9201 (2026-09-18) + +**Method: endpoint-level, stated as such.** `claude-in-chrome` is not available on DooPlex, so each +probe invokes the exact endpoint the page's own script or form invokes; only rendering is skipped. +Strict click-through remains a manual pass by the operator. + +Reached at the container IP inside the guest (`172.17.0.2:8080`) with the mandatory +`Host: felhom.enkisfelhom.hu`. Session obtained by a real `POST /login`; `felhom_session` is read off +the `Set-Cookie` header because curl's jar drops it. The API POST carries `X-CSRF-Token` from the +page's meta tag — the second of the two CSRF mechanisms. + +Scripts as run: `probe2.sh` (authenticated probe), `dump.sh` (page bodies for the parity compare). +The password was passed as a file and deleted from the host and the guest afterwards; it is not in +any script, any log or any file here. + +## 1. The flash line — the thing this release changes + +| probe | 0.251.0 (before) | 0.252.0 (after) | +|---|---|---| +| `/launcher?flash=flash.share.enabled&lang=hu` | `flash.share.enabled` (a raw key — the old build has no key logic) | **„A megosztás bekapcsolva."** | +| `/launcher?flash=flash.share.enabled&lang=en` | `flash.share.enabled` | **"Sharing is on."** | +| `/launcher?flash=Sikeres+ment%C3%A9s` (a link an OLD controller minted) | „Sikeres mentés" | **„Sikeres mentés"** — unchanged, in BOTH languages | +| `/login?flash=%3Cscript%3E…` | `<script>alert(1)</script>` | **identical** — escaped at render, as always | + +The third row is the compatibility guarantee, live: a bookmark, an open tab or a back-forward cache +replaying a 0.251.0 URL still reads correctly. + +## 2. Country names follow the language, and the list re-sorts + +`GET /api/geo/countries` — the call the geo picker makes. + +| | 0.251.0 | 0.252.0 `lang=hu` | 0.252.0 `lang=en` | +|---|---|---|---| +| DE | Németország | Németország | **Germany** | +| US | Egyesült Államok | Egyesült Államok | **United States** | +| AO | Angola | Angola | Angola (identical in both, and it still resolves) | +| first three in order | Afganisztán, Albánia, Algéria | same | **Afghanistan, Albania, Algeria** | + +## 3. The 409 probe — a refusal a customer really meets, without installing anything + +`POST /api/stacks/bentopdf/deploy` on an app that is ALREADY installed (R-553's report established +this shape so no install is needed on the demo box): + +``` +{"ok":false,"error":"stack \"bentopdf\" is already deployed; use update instead"} [409] +``` + +The status code is right in both languages — `errors.Is(err, stacks.ErrAlreadyDeployed)`, R-553's +signal, untouched. **The sentence is internal English and stays English: that is R-569, not this +slice.** Recorded here so nobody reads it as a gap this release left. + +`POST /api/stacks/felhom-controller/stop` → `403 cannot stop protected stack felhom-controller`, also +internal English, same row. + +## 4. Hungarian parity — measured on the page bodies, not on a hash + +Ten Hungarian pages fetched on 0.252.0, then the guest rolled BACK to 0.251.0, the same ten fetched +again, then rolled forward. (The first pass saved only hashes; a hash cannot show WHAT moved, so the +before-state was reproduced independently rather than asserted — the documented expectation.) + +After normalising the version string, the CSRF token and live numbers (ages, sizes, percentages): + +**6 of 10 byte-identical.** `backups`, `backups/remote`, `login`, `sharing`, `stacks`, `storage`. + +The other four differ **only in live state**, each identified: + +| page | the difference | why it is not copy | +|---|---|---| +| `backups/apps` | „Utolsó: most" vs „Utolsó: perce" ×10 | a relative age crossed the one-minute boundary between the two fetches | +| `monitoring` | „most" vs „ perce" | the same clock | +| `launcher` | a „Nem egészséges" badge present in one fetch | an app was unhealthy at one moment and healthy at the other, across a restart | +| `settings` | „Frissítés elérhető" + the install button vs „— naprakész" | on 0.251.0 an update (0.252.0) genuinely IS available; on 0.252.0 it is not. The update checker working. | + +Full diff: `hu-parity-diff.txt`. + +## 5. State left behind + +The box runs **0.252.0** and its saved language is **`hu`** — it was never changed; every English +probe used the `?lang=en` per-request override, which is not persisted. No app was installed, no app +removed, no drive touched, no floor raised, no golden baked. **Provisioned nothing.** diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/auth-probe-0.251.0.txt b/documentation/audits/i18n-slice2-2026-09-18/A/live/auth-probe-0.251.0.txt new file mode 100644 index 00000000..a304227f --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/auth-probe-0.251.0.txt @@ -0,0 +1,46 @@ +LOGIN OK +##### lang=hu +--- /api/geo/countries : DE, US, AO (name) + Angola + Egyesült Államok + Németország +--- /api/geo/countries : first 3 in sort order + Afganisztán + Albánia + Algéria +--- deploy an ALREADY INSTALLED app (409, no install happens) +{"ok":false,"error":"CSRF token missing or invalid"} [403] +--- /launcher md5 + flash key render +ee517ff0ddf893d9079d8b17621738a0 - +alert-message">flash.share.enabled +alert-message">Sikeres mentés +--- /backups md5, /monitoring md5, /settings md5 + /backups 86d2055f91fe5dfc95a5a100a7145bd3 - + /monitoring 627318e618a2ead5ab1eafd984836479 - + /settings 24fbc882bbab95ce6b764bc23b4bde66 - +--- /backups/remote md5 +f569bc3e345572dd59a68ce3ae030923 - +##### lang=en +--- /api/geo/countries : DE, US, AO (name) + Angola + Egyesült Államok + Németország +--- /api/geo/countries : first 3 in sort order + Afganisztán + Albánia + Algéria +--- deploy an ALREADY INSTALLED app (409, no install happens) +{"ok":false,"error":"CSRF token missing or invalid"} [403] +--- /launcher md5 + flash key render +af9b7ace27894a7b29cf2be38fcf2087 - +alert-message">flash.share.enabled +alert-message">Sikeres mentés +--- /backups md5, /monitoring md5, /settings md5 + /backups ab275d3b0b8731f750da9acfc8f1ecab - + /monitoring fb23d136558d0e9dc14816be8124ce4b - + /settings 24ecdf2ca3ca1bc97c83553115c38ff3 - +--- /backups/remote md5 +0b3048f2417b49da95875bdd96e8d18c - +##### hub report language + health warnings +{"ok":false,"error":"endpoint not found"} + diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/auth-probe-0.252.0.txt b/documentation/audits/i18n-slice2-2026-09-18/A/live/auth-probe-0.252.0.txt new file mode 100644 index 00000000..0974fdf3 --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/auth-probe-0.252.0.txt @@ -0,0 +1,54 @@ +LOGIN OK +##### lang=hu +--- /api/geo/countries : DE, US, AO (name) + Angola + Egyesült Államok + Németország +--- /api/geo/countries : first 3 in sort order + Afganisztán + Albánia + Algéria +--- deploy an ALREADY INSTALLED app (409, no install happens) +{"ok":false,"error":"stack \"bentopdf\" is already deployed; use update instead"} + [409] +--- start an app that needs a missing drive / memory refusal shape +{"ok":false,"error":"cannot stop protected stack felhom-controller"} + [403] +--- /launcher md5 + flash key render +e9a1524044e4a07b34d2c87a9ba8d77c - +alert-message">A megosztás bekapcsolva. +alert-message">Sikeres mentés +--- /backups md5, /monitoring md5, /settings md5 + /backups 910ef0bb4f8c0f2da4d8a8469fcf3f94 - + /monitoring 28d85ba6adf6c625ce76cf8d3d725e91 - + /settings b0afa6082c2a8839b9181b93600e8fe8 - +--- /backups/remote md5 +5171b8336f1a0e230814d58712634520 - +##### lang=en +--- /api/geo/countries : DE, US, AO (name) + Angola + Germany + United States +--- /api/geo/countries : first 3 in sort order + Afghanistan + Albania + Algeria +--- deploy an ALREADY INSTALLED app (409, no install happens) +{"ok":false,"error":"stack \"bentopdf\" is already deployed; use update instead"} + [409] +--- start an app that needs a missing drive / memory refusal shape +{"ok":false,"error":"cannot stop protected stack felhom-controller"} + [403] +--- /launcher md5 + flash key render +f039b2a57bf7d242aeaee6cf9133caed - +alert-message">Sharing is on. +alert-message">Sikeres mentés +--- /backups md5, /monitoring md5, /settings md5 + /backups caca54241f52e756e4ee66e875d2cb4c - + /monitoring b02be318a6ce3952516c5c765622d9f4 - + /settings b1a8f6e6762c6faa6309072f242c96a7 - +--- /backups/remote md5 +7d8e889540871d99d6b01500c8c53c67 - +##### hub report language + health warnings +{"ok":false,"error":"endpoint not found"} + diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/dump.sh b/documentation/audits/i18n-slice2-2026-09-18/A/live/dump.sh new file mode 100644 index 00000000..d42ce168 --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/dump.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Dump the Hungarian dashboard pages so 0.251.0 and 0.252.0 can be compared byte by byte. +IP=172.17.0.2:8080 +H="Host: felhom.enkisfelhom.hu" +PW=$(cat /tmp/.felhompw); J=/tmp/pj.txt; rm -f $J +curl -s -c $J -H "$H" "http://$IP/login" -o /tmp/lg.html +CSRF=$(grep -o 'name="_csrf" value="[^"]*"' /tmp/lg.html | head -1 | sed 's/.*value="//;s/"//') +SESS=$(curl -s -b $J -H "$H" -D - -o /dev/null -X POST "http://$IP/login" \ + --data-urlencode "password=$PW" --data-urlencode "_csrf=$CSRF" \ + | grep -i '^set-cookie: felhom_session' | head -1 | sed 's/[Ss]et-[Cc]ookie: //;s/;.*//') +[ -z "$SESS" ] && { echo "LOGIN FAILED"; exit 1; } +OUT=/tmp/hu_pages; rm -rf $OUT; mkdir -p $OUT +for P in launcher backups backups/remote backups/apps backups/restore monitoring settings storage sharing stacks; do + F=$(echo $P | tr '/' '_') + curl -s -H "$H" -H "Cookie: $SESS" --max-time 10 "http://$IP/$P?lang=hu" -o $OUT/$F.html +done +curl -s -H "$H" --max-time 10 "http://$IP/login?lang=hu" -o $OUT/login.html +cd $OUT && wc -c *.html diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/hu-parity-diff.txt b/documentation/audits/i18n-slice2-2026-09-18/A/live/hu-parity-diff.txt new file mode 100644 index 00000000..ee0e17c9 --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/hu-parity-diff.txt @@ -0,0 +1,41 @@ +IDENTICAL backups.html 46016 bytes +DIFFERS backups_apps.html 20 changed lines + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO + - Utolsó: most + + Utolsó: # AGO +IDENTICAL backups_remote.html 53647 bytes +DIFFERS launcher.html 2 changed lines + - Nem egészséges + + +IDENTICAL login.html 1578 bytes +DIFFERS monitoring.html 2 changed lines + - most + + # AGO +DIFFERS settings.html 4 changed lines + - ● Frissítés elérhető + + — naprakész + - + - +IDENTICAL sharing.html 44783 bytes +IDENTICAL stacks.html 145363 bytes +IDENTICAL storage.html 66019 bytes + +6 of 10 Hungarian pages byte-identical once the version string, the CSRF token and live +numbers (ages, sizes, percentages) are normalised. Remaining changed lines: 28 diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/probe-0.251.0.txt b/documentation/audits/i18n-slice2-2026-09-18/A/live/probe-0.251.0.txt new file mode 100644 index 00000000..d5d3a26c --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/probe-0.251.0.txt @@ -0,0 +1,25 @@ +##### lang=hu +--- /login (plain) +b9eeb1a2586e884f8f021a78dfa4ced6 - +--- /login legacy flash text (an old link) +alert alert-info">Sikeres mentés +--- /login flash KEY +alert alert-info">flash.login.password_changed +--- /login flash key + script (escaping) +alert alert-info"><script>alert(1)</script> +--- /api/geo/countries : DE, US, AO +--- /api/stacks//deploy 409 probe +{"ok":false,"error":"authentication required"} [401] +##### lang=en +--- /login (plain) +53a568ee582e6ed3e277b779cacfbb98 - +--- /login legacy flash text (an old link) +alert alert-info">Sikeres mentés +--- /login flash KEY +alert alert-info">flash.login.password_changed +--- /login flash key + script (escaping) +alert alert-info"><script>alert(1)</script> +--- /api/geo/countries : DE, US, AO +--- /api/stacks//deploy 409 probe +{"ok":false,"error":"authentication required"} [401] +##### version diff --git a/documentation/audits/i18n-slice2-2026-09-18/A/live/probe2.sh b/documentation/audits/i18n-slice2-2026-09-18/A/live/probe2.sh new file mode 100644 index 00000000..75abf5c5 --- /dev/null +++ b/documentation/audits/i18n-slice2-2026-09-18/A/live/probe2.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Authenticated endpoint-level i18n probe, run INSIDE guest 9201. +IP=172.17.0.2:8080 +H="Host: felhom.enkisfelhom.hu" +PW=$(cat /tmp/.felhompw) +J=/tmp/pj.txt; rm -f $J +# 1. pre-auth page: CSRF field + cookie +curl -s -c $J -H "$H" "http://$IP/login" -o /tmp/lg.html +CSRF=$(grep -o 'name="_csrf" value="[^"]*"' /tmp/lg.html | head -1 | sed 's/.*value="//;s/"//') +# 2. sign in, keep the Set-Cookie header ourselves (curl's jar drops felhom_session) +SESS=$(curl -s -b $J -H "$H" -D - -o /dev/null -X POST "http://$IP/login" \ + --data-urlencode "password=$PW" --data-urlencode "_csrf=$CSRF" \ + | grep -i '^set-cookie: felhom_session' | head -1 | sed 's/[Ss]et-[Cc]ookie: //;s/;.*//') +if [ -z "$SESS" ]; then echo "LOGIN FAILED (no session cookie)"; exit 1; fi +a(){ curl -s -H "$H" -H "Cookie: $SESS" --max-time 10 "http://$IP$1"; } +echo "LOGIN OK" +for L in hu en; do + echo "##### lang=$L" + echo "--- /api/geo/countries : DE, US, AO (name)" + a "/api/geo/countries?lang=$L" | tr '}' '\n' | grep -E '"(DE|US|AO)"' | sed 's/.*"name":"/ /;s/"$//' | head -3 + echo "--- /api/geo/countries : first 3 in sort order" + a "/api/geo/countries?lang=$L" | tr '}' '\n' | sed -n '1,3p' | sed 's/.*"name":"/ /;s/"$//' + echo "--- deploy an ALREADY INSTALLED app (409, no install happens)" + a "/launcher?lang=$L" > /tmp/lp.html + MC=$(grep -o 'name="csrf-token" content="[^"]*"' /tmp/lp.html | head -1 | sed 's/.*content="//;s/"//') + curl -s -H "$H" -H "Cookie: $SESS" -H "X-CSRF-Token: $MC" --max-time 10 -X POST "http://$IP/api/stacks/bentopdf/deploy?lang=$L" \ + -H 'Content-Type: application/json' -d '{"values":{}}' -w " [%{http_code}]" | head -c 400; echo + echo "--- start an app that needs a missing drive / memory refusal shape" + curl -s -H "$H" -H "Cookie: $SESS" -H "X-CSRF-Token: $MC" --max-time 10 -X POST "http://$IP/api/stacks/felhom-controller/stop?lang=$L" -w " [%{http_code}]" | head -c 250; echo + echo "--- /launcher md5 + flash key render" + a "/launcher?lang=$L" | md5sum + a "/launcher?flash=flash.share.enabled&lang=$L" | grep -o 'alert-message">[^<]*' | head -1 + a "/launcher?flash=Sikeres+ment%C3%A9s&lang=$L" | grep -o 'alert-message">[^<]*' | head -1 + echo "--- /backups md5, /monitoring md5, /settings md5" + for P in /backups /monitoring /settings; do echo -n " $P "; a "$P?lang=$L" | md5sum; done + echo "--- /backups/remote md5" + a "/backups/remote?lang=$L" | md5sum +done +echo "##### hub report language + health warnings" +a "/api/status" | head -c 200; echo