docs: live evidence for controller v0.252.0 + STATUS (R-557 slice 2 release A)
gates / gates (push) Successful in 23s

Endpoint-level on demo-hp guest 9201, method stated. The flash key renders the sentence in
each language where 0.251.0 showed the raw key; a link an OLD controller minted still shows
its prose, in both languages; country names follow the language and the list re-sorts.

Hungarian parity measured on the page BODIES, not on a hash: ten pages on 0.252.0, the guest
rolled back to 0.251.0, the same ten again, then rolled forward. Six byte-identical; the other
four differ only in live state (a clock crossing a minute, an app unhealthy for a moment, and
the update-available line, which is true on the old version and false on the new). The first
pass had saved only hashes — a hash cannot show WHAT moved — so the before-state was
reproduced rather than asserted.

Box left on 0.252.0 with its saved language `hu`; every English probe used the ?lang= override,
which is not persisted. Provisioned nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-18 10:24:52 +02:00
parent ea4f6ab340
commit 92ee0f9881
8 changed files with 338 additions and 20 deletions
+34 -20
View File
@@ -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.
@@ -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…` | `&lt;script&gt;alert(1)&lt;/script&gt;` | **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ó: <n> perce" ×10 | a relative age crossed the one-minute boundary between the two fetches |
| `monitoring` | „most" vs „<n> 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.**
@@ -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"}
@@ -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"}
@@ -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
@@ -0,0 +1,41 @@
IDENTICAL backups.html 46016 bytes
DIFFERS backups_apps.html 20 changed lines
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
- <span class="layer-last">Utolsó: most
+ <span class="layer-last">Utolsó: # AGO
IDENTICAL backups_remote.html 53647 bytes
DIFFERS launcher.html 2 changed lines
- <span class="tag tag-warn"><span class="dot"></span>Nem egészséges</span>
+
IDENTICAL login.html 1578 bytes
DIFFERS monitoring.html 2 changed lines
- <span class="sysinfo-value">most</span>
+ <span class="sysinfo-value"># AGO</span>
DIFFERS settings.html 4 changed lines
- <span class="state-text-run" style="margin-left:0.5em;">● Frissítés elérhető</span>
+ <span style="margin-left:0.5em; color:var(--text-3);">— naprakész</span>
-
- <button class="btn btn-primary btn-sm" id="btn-trigger-update" onclick="triggerUpdate()" style="margin-left:0.5em;">Frissítés telepítése</button>
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
@@ -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">&lt;script&gt;alert(1)&lt;/script&gt;
--- /api/geo/countries : DE, US, AO
--- /api/stacks/<installed>/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">&lt;script&gt;alert(1)&lt;/script&gt;
--- /api/geo/countries : DE, US, AO
--- /api/stacks/<installed>/deploy 409 probe
{"ok":false,"error":"authentication required"} [401]
##### version
@@ -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