From 3e2bdda7213dfa6e9a0e93bab1141440c448edec Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 14 Oct 2026 15:40:23 +0200 Subject: [PATCH] R-1009 closed (estimator live, read back); R-1007: the operator's ruling recorded, and Immich v3.2.4 rebuilds single photos Read-back: live sizing-data.json?v=4 byte-equal to the commit; the presets keep their verdicts, Immich alone on 8 GB still tight; only the set without Immich changed. Spike B2 on 9202: POST /api/assets/jobs regenerate-thumbnail rebuilt exactly the 10 broken assets (1.55 s, 5.3 s CPU), 0 of the other 20 photos' 40 files rewritten (control: all rewrote 40 of 40); an empty file maps to its asset by the first 36 characters of its name. Immich removed through the product, no leftovers. Register 134 -> 133 (opened 0, closed 1). STATUS D9/D10 ruled. Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb --- REPORT-estimator-immich-2026-10-14.md | 42 +++++++++++++++++++ STATUS.md | 8 ++-- .../B2/single-asset-repair.txt | 29 +++++++++++++ .../B2/teardown.txt | 8 ++++ .../power-cut-fixes-2026-10-14/README.md | 28 +++++++++++++ .../sizing-check-2026-10-14/live-readback.txt | 7 ++++ documentation/backlog/CLOSED-ITEMS.md | 6 +++ documentation/backlog/OPEN-ITEMS.md | 5 +-- 8 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 REPORT-estimator-immich-2026-10-14.md create mode 100644 documentation/audits/power-cut-fixes-2026-10-14/B2/single-asset-repair.txt create mode 100644 documentation/audits/power-cut-fixes-2026-10-14/B2/teardown.txt create mode 100644 documentation/audits/sizing-check-2026-10-14/live-readback.txt diff --git a/REPORT-estimator-immich-2026-10-14.md b/REPORT-estimator-immich-2026-10-14.md new file mode 100644 index 00000000..11f8d98d --- /dev/null +++ b/REPORT-estimator-immich-2026-10-14.md @@ -0,0 +1,42 @@ +# REPORT — 2026-10-14: the estimator's raised figures published (R-1009 = A); Immich can rebuild single photos (R-1007) + +Times UTC. Baseline felhom.eu `65493fc4`. Read first: `audits/sizing-2026-10-13/SIZING.md` §5 and +`audits/sizing-check-2026-10-14/CHECK.md` (the estimator); `audits/power-cut-fixes-2026-10-14/README.md` F (Immich). +No release; no controller, agent, hub or catalog change. No key, token or password in any file. + +## 1. The page — live + +- The tool change applied as its own commit (`3f7f26a7`, the waiting patch unchanged). Data rebuilt (`54112954`): + 23 figures up, none down; `build_sizing_web.py --check` OK; `test_build_sizing_web.py` 14/14 after its expected values + moved with the rule (the one verdict, the household peak 6,021, the bar). +- **The one stricter answer:** the household set without Immich on 8 GB — fits well → fits, but tight (2,731 × 1.5 = + 4,096.5 > 4,096 MB). `SIZING.md` §5 table, bullets, memory table and the dated line updated; the five largest peaks too. +- Lede, meta description and method note (HU + EN) name both machines (N100 and HP t740, 13–14 October 2026). Data `?v=4`. +- **Read-back** (live files; verdicts by the test's copy of the page rule — no browser on DooPlex): the live + `sizing-data.json?v=4` is byte-equal to the commit. „Family starter set" (no / tight / well …) and „Just files and + passwords" (well everywhere) keep their verdicts; Immich alone on 8 GB is still „tight"; only the set without Immich + changed (`audits/sizing-check-2026-10-14/live-readback.txt`). +- https://felhom.eu/gepigeny and https://felhom.eu/en/sizing. R-1009 closed. + +## 2. Immich — yes, it rebuilds single photos + +- Ruling recorded in R-1007: after an unclean boot, rebuild only the broken photos, run the missing-files check, tell + the operator about lost originals; no „thumbnails: all". +- The running v3.2.4 answers `POST /api/assets/jobs {assetIds, name: "regenerate-thumbnail"}` (read from its own 400 + reply and its server code). +- 10 broken assets (5 empty thumbnails, 5 empty previews), found from the disk alone; repaired in **1.55 s, 5.3 s CPU**. + The other 20 photos: **0 of 40 files rewritten**; the positive control („all") rewrote 40 of 40. +- An empty file maps to its asset: the first 36 characters of `thumbs////_thumbnail.webp`. +- **Next step (R-1007):** build a per-app after-unclean-boot hook that finds the zero-byte files under `thumbs/`, calls + that endpoint for those ids only, runs `integrity-missing-files`, and tells the operator about lost originals. +- Counts note: the task named „5+5", „10 assets" and „the other 25"; with 30 photos those do not all hold. I damaged 10 + different assets, which left 20 as the control. +- Teardown: Immich removed through the product on 9202; no folder, container, volume or image left; 9202's standing apps + untouched. Nothing on 9201, Tester 1 or the N100. Host and hub: nothing made. + +## 3. Record + +- Commits: felhom.eu `3f7f26a7`, `54112954`, and this one. +- Register: **134 before → 133 after; opened 0; closed 1** (R-1009). R-1007 updated (ruling + answer + next action). +- STATUS.md: 45 lines; D9 and D10 left the decide table (both ruled). +- Fixed without a row: none. System poster: no listed fact changed. diff --git a/STATUS.md b/STATUS.md index 613eb9bd..786dd59d 100644 --- a/STATUS.md +++ b/STATUS.md @@ -9,7 +9,7 @@ - A power cut in the middle of a backup no longer blocks later backups: the box removes the half-written backup at start-up (proven with a real cut on demo-hp, on all three boxes now). - A household can switch the machine off; the hub holds alarms for 14 days and clears the state by itself (N100). - A real power cut on demo-hp: it started by itself after all 8 cuts of the night (with the BIOS set), every app back in ~4 min; stale and recovered mails true and paired. -- The machine estimator is public (/gepigeny, /en/sizing); sizing measured for 61 apps on the N100. +- The machine estimator is public (/gepigeny, /en/sizing), with figures from two machines (N100 and HP t740; raised only, 2026-10-14). - 62 apps in the catalog, the Usenet and torrent clients included. OS updates, the kernel lane too, run at night. - The hub is closed again after the 2026-10-12 security review; one box cannot read another's data. @@ -18,10 +18,10 @@ - DooPlex: a failed disk with its alarms silenced (R-934); CI jobs still get lost (R-887); something sets the shared checkout to „bare" (R-935); a Longhorn volume at 91 %. - Tester 2 has never made an off-site check (R-862). The scratch box cannot read the drill catalog (R-992). -- After a power cut: Immich keeps photos with empty previews or no original until its own repair job runs (R-1007, your decision). +- After a power cut: Immich keeps photos with empty previews or no original; your ruling „fix only the broken photos" is shown to work (Immich rebuilds single photos) — the build is a later task (R-1007). ## What we work on -- The power-cut findings still open (R-1004, R-1005, R-1007, R-1010, R-1012, R-1013) and the estimator figures (R-1009, your choice). +- The power-cut findings still open (R-1004, R-1005, R-1007, R-1010, R-1012, R-1013) and the Immich repair build (R-1007). ## Waiting on you — decide @@ -35,8 +35,6 @@ | D6 | R-992 | The scratch box cannot read the private drill catalog: give it a read-only login, or make that copy readable? | **A read-only login** | Readable copy: the drill catalog becomes public | every new-app test needs hand-staging | new-app tests | | D7 | R-990, R-989 | Rule yes / no / later on the forum ideas (`audits/forum-research-2026-10-12/FELHOM.md` §5) and the selfh.st ideas (`audits/selfhst-survey-2026-10-12/FELHOM.md` §6) | — | — | nothing changes; the research ages | — | | D8 | R-206 | Install DooPlex's Docker settings from git (restarts Docker), and prune the build cache weekly: yes or no? | **Yes, in a quiet window** | — | a rebuild of DooPlex still has the settings in git | — | -| D9 | R-1007 | After an unclean boot, should Immich run its own repair: the „missing files" check (report a lost photo) and „thumbnails: all" (fix empty previews) in the night window? | **Yes** | CPU in proportion to the library (a big one: hours, at night) | broken previews stay; a lost original stays unnoticed | — | -| D10 | R-1009 | The „raise only" estimator update changes ONE verdict: 5 apps without Immich on 8 GB, fits well → tight (0.5 MB over). Publish anyway (A), round down first (B), or keep today's figures (C)? | **A** — the page stays truthful, one line reads stricter | B: one rule sentence, may still flip; C: nothing | the page keeps today's figures; Immich, Jellyfin, Home Assistant, Paperless read low | — | ## Waiting on you — do - **N100 BIOS:** read „After Power Loss" (the HP's „Previous State" made it start after 8 of 8 cuts). **HP BIOS:** „Bypass F1 Prompt on Configuration Changes" → Enable. diff --git a/documentation/audits/power-cut-fixes-2026-10-14/B2/single-asset-repair.txt b/documentation/audits/power-cut-fixes-2026-10-14/B2/single-asset-repair.txt new file mode 100644 index 00000000..65873482 --- /dev/null +++ b/documentation/audits/power-cut-fixes-2026-10-14/B2/single-asset-repair.txt @@ -0,0 +1,29 @@ +assets: 30 +== path layout (one asset): +thumbs/8b6e9d61-4727-4f6f-acc8-9cbd34b9e17c/b6/43/b6439ff3-bf84-4a36-abea-83be61c39ceb_thumbnail.webp +thumbs/8b6e9d61-4727-4f6f-acc8-9cbd34b9e17c/b6/43/b6439ff3-bf84-4a36-abea-83be61c39ceb_preview.jpeg + thumbs files: 61; kinds: 1 .immich 30 preview.jpeg 30 thumbnail.webp +== 13:35:43 damage: assets 1-5 thumbnail -> 0 B, assets 6-10 preview -> 0 B +== 13:35:45 found from the DISK only (zero-byte files -> asset id = the first 36 characters of the name): + 250f3daa-97cd-4995-8e36-4106a000ee97_thumbnail.webp + 3bf485a3-ce9c-4a97-a403-d79d28f01d73_preview.jpeg + 7cc1da19-4414-4ccf-9625-1193ddcdb050_preview.jpeg + 85552913-9900-487f-84eb-fe5839cc7df9_thumbnail.webp + a57b10e1-a7b1-474f-8782-462b747228c1_thumbnail.webp + ad2c19a0-26b3-4a26-8291-00a375f98515_preview.jpeg + b6439ff3-bf84-4a36-abea-83be61c39ceb_thumbnail.webp + ca86f976-4624-42c0-b800-34e8372f485f_preview.jpeg + f807f803-2042-46cc-ae47-e8a27277f022_preview.jpeg + fc6ca10a-e9ee-45dc-ac4a-73de7db40bac_thumbnail.webp + broken assets: 10 + API before: 0/208760 5630/0 5856/0 0/194665 0/194607 6246/0 0/203683 5720/0 6022/0 0/198427 +== 13:35:48 POST /api/assets/jobs regenerate-thumbnail for the 10 broken assets -> 204 + zero-byte files left: 0; all files non-empty after 1.55 s; queue idle after 16.85 s; CPU (all immich containers) 5340 ms to non-empty, 5828 ms to idle + API after: 6698/208760 5630/197443 5856/193665 5858/194665 5882/194607 6246/201464 6398/203683 5720/199228 6022/204622 5964/198427 + files of the 10 broken assets: 20, rewritten 20, empty after 0 + files of the other 21 assets: 41, rewritten 0 <- must be 0 + new files: []; gone: [] +== 13:36:05 positive control: thumbnails ALL (force=true) must rewrite the other assets' files + PUT -> 200 + files of the other assets rewritten by ALL: 40 of 41 + ALL: queue idle after 18.21 s; CPU 16488 ms (30 assets) diff --git a/documentation/audits/power-cut-fixes-2026-10-14/B2/teardown.txt b/documentation/audits/power-cut-fixes-2026-10-14/B2/teardown.txt new file mode 100644 index 00000000..5b998041 --- /dev/null +++ b/documentation/audits/power-cut-fixes-2026-10-14/B2/teardown.txt @@ -0,0 +1,8 @@ +15:37:20 immich: stop 200, remove 200, deployed=False, leftovers='' +True +left: 0 dirs +containers: felhom-controller paperless-webserver paperless-postgres paperless-redis filebrowser traefik +immich volumes: 0 +immich images: 0 + +["15:37:20 immich: stop 200, remove 200, deployed=False, leftovers=''"] diff --git a/documentation/audits/power-cut-fixes-2026-10-14/README.md b/documentation/audits/power-cut-fixes-2026-10-14/README.md index 701fd55f..a5e5fd04 100644 --- a/documentation/audits/power-cut-fixes-2026-10-14/README.md +++ b/documentation/audits/power-cut-fixes-2026-10-14/README.md @@ -116,6 +116,34 @@ hook and CPU in proportion to the library; a missing original then needs a resto done: broken previews stay until someone forces a regeneration by hand; a lost original stays unnoticed. +## B2 — can Immich rebuild single photos? (R-1007, after the operator ruling „fix only the broken photos", spike only) + +Immich v3.2.4 on scratch guest 9202, deployed and removed through the product; 30 bench photos (`B2/`). + +**What the running server answers** (asked, not remembered): `POST /api/assets/jobs` with a bad body → 400 listing the +names `refresh-faces`, `refresh-metadata`, `regenerate-thumbnail`, `transcode-video`; body `{"assetIds": […], +"name": "regenerate-thumbnail"}`, permission `AssetUpdate` (an admin or the owner's key). In the server code +(`dist/services/asset.service.js` `run()`): one `AssetGenerateThumbnails` job per id given — nothing else is queued. + +**Path layout:** `/thumbs////_thumbnail.webp` and `…_preview.jpeg` (+ one +`.immich` marker file). **Mapping an empty file to its asset:** the first 36 characters of the file name ARE the asset +id. A box finds the broken photos from the disk alone: `find /thumbs -type f -size 0`, cut the names to 36 +characters, unique. + +| Step | Result | +|---|---| +| damage | assets 1–5: thumbnail → 0 B; assets 6–10: preview → 0 B; the API served the 0-byte files | +| found from the disk | 10 zero-byte files → 10 asset ids (the mapping above) | +| `POST /api/assets/jobs regenerate-thumbnail` for those 10 | **204**; no zero-byte file left after **1.55 s**; queue idle after 16.9 s (5 s polling); **CPU 5.3 s** (all Immich containers, cgroup `usage_usec`) | +| the 10 assets | all 20 files rewritten (the undamaged sibling too), none empty; the API serves real thumbnails and previews | +| the other 20 assets | **0 of 40 files rewritten** (mtimes before/after) | +| positive control: thumbnails „all" (`force=true`) | rewrote **40 of 40** of those same files (the 41st counted file is the `.immich` marker); CPU 16.5 s for 30 photos | +| teardown | Immich removed through the product; no folder, container, volume or image left; 9202's standing apps untouched | + +**Answer:** yes — v3.2.4 rebuilds single photos. Cost ≈ 0.5 s CPU per photo here (a family library with 80 broken photos, +like the night's R2: well under a minute) against „all" in proportion to the whole library. A lost original is still +found only by `integrity-missing-files` and restored only from a backup. + ## E — the live proof on demo-hp (agent 0.156.1 + bundle, delivered by signed jobs) Vouched by the operator 2026-10-14 (read back from `/configuration`): agent 0.156.1 `83c7da27…`, golden 0.310.0 `2110d5e4…`, diff --git a/documentation/audits/sizing-check-2026-10-14/live-readback.txt b/documentation/audits/sizing-check-2026-10-14/live-readback.txt new file mode 100644 index 00000000..b51754b4 --- /dev/null +++ b/documentation/audits/sizing-check-2026-10-14/live-readback.txt @@ -0,0 +1,7 @@ +Live read-back 2026-10-14, https://felhom.eu/gepigeny and https://felhom.eu/en/sizing; data sizing-data.json?v=4 (sha256 equal to the commit). +Presets read from the live page; verdicts by the page rule (scripts/test_build_sizing_web.py estimate(), mirrors sizing.js). +Columns [8, 12, 16, 24, 32, 48, 64] GB +Family starter set: peak 5515 -> 6021 MB | before ['no', 'tight', 'well', 'well', 'well', 'well', 'well'] | now ['no', 'tight', 'well', 'well', 'well', 'well', 'well'] | SAME +Just files and passwords: peak 1094 -> 1094 MB | before ['well', 'well', 'well', 'well', 'well', 'well', 'well'] | now ['well', 'well', 'well', 'well', 'well', 'well', 'well'] | SAME +Immich alone: peak 3531 -> 3760 MB | before ['tight', 'well', 'well', 'well', 'well', 'well', 'well'] | now ['tight', 'well', 'well', 'well', 'well', 'well', 'well'] | SAME +Family set without Immich: peak 2454 -> 2731 MB | before ['well', 'well', 'well', 'well', 'well', 'well', 'well'] | now ['tight', 'well', 'well', 'well', 'well', 'well', 'well'] | CHANGED diff --git a/documentation/backlog/CLOSED-ITEMS.md b/documentation/backlog/CLOSED-ITEMS.md index 94f0b561..ca1d6567 100644 --- a/documentation/backlog/CLOSED-ITEMS.md +++ b/documentation/backlog/CLOSED-ITEMS.md @@ -26,6 +26,12 @@ --- +## 2026-10-14 — the estimator takes the second machine's figures, raise only + +| Row | What | Closed | Evidence | +|---|---|---|---| +| **R-1009** | **Operator: decide whether the machine estimator's figures move with the 2026-10-14 check on a second machine** (P3) | CLOSED 2026-10-14 — operator ruling A: raise only. 23 figures up, none down (Immich peak 3,061 → 3,290; Jellyfin, Home Assistant, Paperless-ngx, Grimmory, 18 small). One verdict stricter: the household set without Immich on 8 GB, fits well → fits, but tight (2,731 × 1.5 = 4,096.5 > 4,096 MB). Live on https://felhom.eu/gepigeny and https://felhom.eu/en/sizing (data `?v=4`, byte-equal to the commit); read back: „Family starter set" and „Just files and passwords" keep their verdicts, Immich alone on 8 GB still tight. **Reasoning kept:** the second machine can only raise a figure, never lower one (operator ruling) | felhom.eu `3f7f26a7` (tool), `54112954` (data + pages); `audits/sizing-check-2026-10-14/live-readback.txt` | + ## 2026-10-14 — a box clears up after a power cut mid-backup | Row | What | Closed | Evidence | diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index 437633d0..f575dbae 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -112,11 +112,10 @@ match what the reader sees is how an instrument stops being believed (R-421). It **nothing was proven on the day this line was drawn** and a stopping line that moves a status is a stopping line that lies. -## Install & onboarding — 9 rows (P3 7, P4 2) +## Install & onboarding — 8 rows (P3 6, P4 2) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| -| **R-1009** | Install & onboarding | P3 | **Operator: decide whether the machine estimator's figures move with the 2026-10-14 check on a second machine** (`audits/sizing-check-2026-10-14/CHECK.md`, „Proposal"). The three answers on an 8 GB box held (files + passwords fit well; Immich alone tight — 14 OOM kills in its ML container; the family set does not fit — real harm); the family set's real simultaneous peak was 97 % of the page's sum. Proposed (A): Immich peak 3,061 → 3,300, Jellyfin 373 → 450, Home Assistant 328 → 435, Nextcloud 525 → 300, Vaultwarden 99 → 45, Grimmory typical 346 → 450; no verdict changes (site rule: family 5,515 → 5,659). (B) a sentence for Immich on 8 GB. | **WAITING-ON-OPERATOR** — 2026-10-14: the „raise only" ruling was built (`raise-only-source.patch`, `hp-figures.json`: 23 figures up, none down) and **STOPPED before the push**: one `SIZING.md` §5 verdict changes — „Household set without Immich" on 8 GB, fits well → tight (peak 2,731 MB × 1.5 = 4,096.5 vs 4,096 MB: 0.5 MB over; any one of the Jellyfin, Home Assistant, Paperless raises removed keeps it). Presets unchanged. `CHECK.md` last section | operator: A, B or C | Operator: (A) publish the raise and accept that one verdict; (B) round the HP figures down to 10 MB first (to be checked); (C) keep today's figures | operator | | **R-980** | Install & onboarding | P3 | **A person cannot check that the installer is ours: the ISO's first boot runs the install script from a movable tag with no hash or signature, and the ISO checksum sits on the same website as the download.** Fix: a signed manifest (or signature) checked by the ISO before it runs the script, and the public key printed in the guide. Security review 2026-10-12 (`audits/security-review-2026-10-12/`); detail held off-git for the operator (`/mnt/5_hdd/felhom.eu/evidence/security-review-2026-10-12-PRIVATE/`). | OPEN — design-proposal | — | Design note, then build | CC | | **R-250** | Install & onboarding | P3 | **A customer create can fail fail-closed because the host-key scan ladder is shorter than the DNS/AAAA settle time.** Found 2026-08-07 creating the fifth walk's venue. `POST /configs/new` with off-site enabled provisions the Storage Box sub-account and then scans its SSH host key to pin it — **fail-closed by design** (`offsite.go:111-121`, *"don't serve a descriptor the controller can't verify"*), with `defaultScanBackoff` = 2+4+8+16+30 ≈ **60 s**, sized by its own comment to *"the observed DNS propagation lag"*. **Measured, both halves:** the first create exhausted the ladder — five `no such host`, then `dial tcp [2a01:4f8:bacc:2:200::d30]:23: connect: network is unreachable` (the name had just begun resolving, **AAAA-first, into a pod with no IPv6 route**) — and the hub logged `[ERROR] offsite provision for walk5`. An **identical second POST succeeded** ~70 s later on its own final rung (`shared already provisioned … (subaccount 285351)`). **Total settle ≈ 100 s against a 60 s budget.** The endpoint was never the problem: verified afterwards from both the node and the hub pod, by name, `SSH-2.0-OpenSSH_9.6p1`. **Two distinct things are wrong and should not be merged:** (1) the budget is sized against DNS *existence*, but what actually bit is the **AAAA-before-A** window, a different and longer phenomenon — lengthen the ladder and/or prefer the A record for the scan dial; (2) **the operator is told nothing actionable** — the create fails with a generic error, the remedy is "press it again", and nothing says so. The retry is genuinely safe (idempotent on the label; confirmed afterwards — `one_time_secrets` 1, one sub-account, no double-provision) **but that safety is invisible to the person deciding whether pressing again will double-charge them.** **Severity LOW-MEDIUM:** self-clearing, no data at risk — but it is the first thing a new customer's provisioning does and it fails looking like an outage. | **VERIFY** — **2026-10-12: hub 0.147.0 live** (S29, decision 224): the host-key scan dials IPv4 first, waits ~2 min (was ~1), and when it still runs out says the store was created and it is safe to press Save again (`TestScannerDialsIPv4First`, `TestScanOutOfRetriesSaysSafeToPressAgain`, red-proved). Known limit: the hub Ingress reads for 60 s, so a very slow first try can show a gateway timeout while provisioning finishes in the background (pressing again is safe). **READY** — operator ruling 2026-10-12 (S29, `09` §3 decision 224): yes — the scan prefers IPv4, waits longer, and the error says „safe to press again". **READY** — owner Viktor | — | The next real off-site setup (a new customer): read the hub log for the scan; success or the new message → close | CC | | **R-516** | Install & onboarding | P3 | **[P3-LOW] English a customer meets on a fresh box and its apps' first screens — enumerated by the big night.** MEASURED 2026-09-14 (BIGNIGHT, VM 333, ISO 1.27.1, controller 0.242.0). Felhom-owned: (1) the dashboard menu item **„Debug"**; (2) the dashboard CPU tile **„Load: 0.29 / 0.39 / 0.37"**; (3) the launcher tile **„Filebrowser"** opens a login in English with no Felhom text (R-513); (4) the storage page mixes formal „Adjon hozzá / Csatlakoztasson" with the product's „te". App first screens a household meets before any Felhom text helps: (5) **Uptime Kuma 2.4 opens on „Which database would you like to use?"** (SQLite / Embedded MariaDB, „Next") — the app card's „Első lépések" does not mention it; (6) PrivateBin, Gokapi, AdventureLog and FileBrowser UIs are English (the apps' own). Already rows: the Proxmox installer screens (R-495, answered by the guide), `wiki.DOMAIN` (R-498). **Fix shape:** rename „Debug"/„Load" (controller); add the Uptime Kuma database step to its card, or pre-seed `db-config.json` for SQLite in the template (catalog). **Added by F4 (20:04:54Z):** (7) the storage page prints the disconnect time as a raw ISO UTC string „Leválasztva: 2026-09-14T19:58:02Z"; (8) the „Meghajtó leválasztva" banner appears twice on every page; (9) „4 telepített alkalmazás nem fut — nézze meg a rendszermonitort" uses the formal form. **Added by F7 (20:50–21:00Z, system disk at 95 %):** (10) a banner on every page in English, „**SSD disk usage high: 90%**"; (11) the dashboard tile reads „Rendszer (/) 61.8 GB / 68.7 GB (**90%**)" while `df` reports **95 %** (reserved blocks ignored), and „(/)" labels the data volume `/mnt/sys_drive`; the deploy page says nothing about free disk. **Added by the i18n spike (2026-09-17, controller v0.247.0):** (12) **six formal („ön") forms in the converted dashboard copy** — „Olvassa be telefonnal" (launcher QR hint), „Biztosan kikapcsolja a megosztást?" (launcher), „Ha újratelepíti … importálnia kell" (the layout's remove-app modal), „Kérjük, vegye fel a kapcsolatot" (backups empty state). They were NOT fixed — a localisation release may not change Hungarian bytes — and are now COUNTED by `controller/scripts/i18n_missing_gate.py` (`HU_FORMAL_CEILING` = 6, a ratchet: a new one convicts, fixing one lowers it). The inventory (`audits/I18N-INVENTORY-2026-09-17.md`) is the list this row closes against in localisation slice 6 (R-561). **Extended 2026-09-17 by slice 1 (controller v0.248.0–v0.250.0):** the converted copy now counts **16** formal forms (`HU_FORMAL_CEILING` 6 → 10 → 12 → 16, each raise stated, Hungarian unchanged by rule) — and the count is an UNDER-count: the gate's stem list sees 4 on the release C pages (storage, drive wizards, debug), while a wider list („írja be”, „adja meg”, „adjon hozzá”, „válassza ki”, „biztosan eltávolítja”, „engedélyezze”, „hozzon létre”, „kattintson”) finds at least **22** keys there alone (login „Adja meg a jelszavát”, the NAS guide, the storage confirms). Widen the stems when this row is worked; the ceiling rises with them. **NARROWED 2026-09-20 by localisation slice 6's walk, item by item** (`audits/i18n-slice6-2026-09-20/R-516-item-by-item.md`): item 2 FIXED (slice 1), items 3 and 6 APP-OWNED (and for an English household item 6 is an advantage), item 11 is a wrong NUMBER rather than a language and needs its own row, item 1 is correct English for an English reader and still open for a Hungarian one. **Items 4, 7, 8, 9 and 10 are NOT DECIDABLE FROM AN ENGLISH WALK** - they are about Hungarian copy quality, a disconnected drive and a full disk, none of which this walk had. **What this row is now waiting for is a HUNGARIAN walk on a box with a second drive**, not another English one; saying it closed would be the kind of closure that makes a register stop meaning anything. **-- 2026-10-08:** the recovery screen's own answers are Go literals in Hungarian only — 14 `renderRecovery` messages in `controller/internal/web/recovery_handlers.go` (seen: the safe default „A művelet nem fejeződött be…" rendered on an English page in a red-proof run). Today's new R-304 sentence is a bundle key in both languages; the 14 old ones are not. | **NARROWED 2026-09-20 - rank P3-LOW; owner: CC; needs a Hungarian walk** **2026-10-05 (burn-down night): items 1 and 4 FIXED on controller `main`** (`d7efa7b`): the menu says „Hibakeresés” (English „Debug”); the storage pages use the te-form (formal-form ceiling 17 → 14; 116 parity fixtures changed by exactly those bytes). Item 2 was already fixed. **Left:** items 5–6 (apps' own screens) and the rest. **2026-10-06: items 1 and 4 DELIVERED** (controller v0.298.0). **2026-10-06 (burn-down night, later): items 7–10 and 12 FIXED on controller `main`** (`e4774e6`, `2e5ef7e`): the disconnect time in local time; one banner per unplugged drive; „nézd meg”; the disk/memory/CPU/temperature banners in the household's language (`health.*` keys; the wire text to the hub unchanged and pinned); the last eleven counted formal forms are te-form (ceiling 14 → 0; 119 parity fixtures changed by exactly those bytes). **Left:** items 5–6 (apps' own screens); about 20 formal forms the gate does not count yet („írja be”, „adja meg”, „hozzon létre”, …) on the debug, storage, network-storage and security pages. Item 11 moved to its own row **R-889**. **2026-10-06 02:40: the bundle has NO formal form left** (controller `4c3c203`, unreleased): 49 sentences in the te-form; the gate's stem list widened (it counted 61 on the previous bundle, 0 now) with decoys and one listed third-person exception. **Left (narrowed):** Felhom-owned formal forms in Go and template literals the gate cannot read yet — the network-storage attach errors, escrow and share handlers, the single-copy notice, a settings refusal, the SMART mail, a fill-watch „Kérjük”, and the setup wizard pages; each moves into the bundle in the te-form. Items 5–6 are the apps' own screens (not ours). **2026-10-06: items 7–10, 12 and the bundle's 49 formal forms DELIVERED** in controller v0.299.0. **2026-10-06 night: the Go-literal leftover moved** (controller main `3d6ba28`, unreleased): 22 Go-literal messages — escrow handler (6), share password page (2), export upload (1), network-storage uid/remove/attach failures (13) — are bundle keys (`api.escrow.*`, `api.share.*`, `api.export.*`, `api.netstorage.*`) in the te-form with English (14 were formal); a detached attach failure renders in the reader's language; the NAS refusal says „Válassz". `TestR516_GoLiteralFormalFormsAreGone` (source scan + positive control), `TestR516_NetAddFailureFollowsTheReader`; red-proofs `audits/night-burndown-2026-10-06/ctrl/R-516-red*.txt`. **Left:** the setup wizard and recovery-info.txt (R-554); the SMART and fill-watch texts (the hub event's message — wire text, needs the household-copy producer shape); items 5–6 (apps' own screens). | — | — | CC | @@ -137,7 +136,7 @@ stopping line that lies. | **R-707** | Apps & catalog | P4 | **[P2] 37 apps still start with a login a stranger can take (`09` §3 decision 45).** Audit of all 53 apps: `app-catalog-felhom.eu/FIRST-ADMIN.md` (class, fix route, status, measured or read). Open: **3 hard-coded defaults** — calibre-web (`admin / admin123`, measured working on demo-hp and 9202; its own `cps.py -s` route needs a generated password WITH a special character — our generator is letters+digits, a controller change), mealie (`changeme@example.com / MyPassword`), wger (`admin / adminadmin`); **34 open first-run screens** (the first visitor creates the admin: actualbudget, adventurelog, audiobookshelf, calcom, docmost, emby, ghost, gitea, gramps-web, home-assistant, homebox, immich, jellyfin, komga, n8n, navidrome, opengist, outline, papra, plant-it, radarr, rallly, recipe-importer, romm, seerr, sonarr, sparkyfitness, tandoor, termix, uptime-kuma, vikunja, wanderer, wishlist, zipline). **Stale notes:** romm's `default_creds` `admin / admin` answers 401 on demo-hp (like a wrong password) — the page now warns with a login that does not exist; zipline's looks stale too. **Measured on demo-hp 2026-09-28 (read-only):** bookstack's default still logs in on the INSTALLED app (the fix is for new installs; the page now warns). Each fix: route (a) env or (b) the app's own CLI/API via `after_install:`, proven on 9202 with the default failing and the generated password working; route (c) a page sentence. Several sessions (operator, 2026-09-28). **2026-09-29 (controller v0.280.0, catalog `d0e7e2e`):** every class-3 app fixed — mealie, wger, calibre-web by `after_install` (calibre-web with the new `password:24:special`), proven on 9202 fresh installs (`audits/login-gate-2026-09-29/D/`); the setup gate (decision 46, spike PASSED) built and live on immich, n8n, audiobookshelf (probes measured) and uptime-kuma (button) (`…/C/`); romm's and zipline's stale notes removed. **Left: 30 class-4 apps** — gate each (probe measured on 9202 where one exists — 11 upstream candidates listed in `…/B/B-VERDICT.md` §3; the button otherwise). **2026-09-29 afternoon (controller v0.281.0, catalog `6faf432`):** 28 more class-4 apps gated — 32 of 34 — each proven on 9202 (`audits/gate-rollout-2026-09-29/`B): stranger → gate page / 401, household reached the first-setup screen, the gate opened (9 by a measured probe, the rest by the press), the app answered after. seerr, outline, rallly: gated, their opening needs a media server / e-mail (not proven). **Left:** wanderer (R-714); plant-it is not installable. | **NARROWED** (2026-10-03 triage: the row's verdict was finished, but it names open work no other row carries — seerr, outline and rallly are gated, but the gate OPENING is not proven (needs a media server / e-mail)) — **CLOSED — 2026-09-29 (the rest → R-714)** | — | — | CC | | **R-905** | Apps & catalog | P4 | **wger's collected style files (283 MB) go into every wger backup, though the app rebuilds them at every start.** Since R-762's fix (`DJANGO_DEBUG=False` + `collectstatic`, catalog `cf1ed43`) the static files sit in a named volume that the backup legs copy like data (measured 283 MB, `audits/design-build-2026-10-06/`); `collectstatic` regenerates them, so they are rebuildable bytes in every Tier-1 unit, Tier-2 copy and off-site snapshot. wger is `lifecycle: hidden` and no box runs it (hub read 2026-10-08). Options to weigh: a non-backed-up volume class for regenerable data, or an anonymous volume. Found by the R-762 helpers 2026-10-08. | **OPEN — needs a design before wger is shown** | — | Design the „regenerable volume" exclusion (catalog + controller backup legs) | CC | | **R-995** | Apps & catalog | P4 | **Removing an app through the product can leave unnamed Docker volumes and an empty import folder behind.** MEASURED 2026-10-13 on demo-felhom after 61 removals (`documentation/audits/sizing-2026-10-13/METHOD.md` „Teardown”, `evidence/leftover-volumes-after-bench.txt`): 8 unnamed volumes (4–72 KB; immich 1, romm 2, privatebin 3, onlyoffice 2 — volumes the images declare themselves) and `userdata/import/{paperless,calibre,grimmory}` (empty, created by the deploy). The removal answered 200 and its own leftover check was clean, because it looks only at labelled volumes. No data risk; disk and tidiness only. Removed by name on the bench. | **READY** — filed 2026-10-13 | — | Make the removal account for the containers' unnamed volumes (and an empty import folder it created), with a test that deploys an image that declares a VOLUME | CC | -| **R-1007** | Apps & catalog | P3 | **After a power cut Immich shows photos as done that are broken, and nothing repairs them: of 101 photos uploaded in the last ~30 s before the cut, 81 kept their original but got an EMPTY thumbnail and preview (162 zero-byte files), and 1 — answered „201 Created" 0.3 s before the cut — has no original at all.** Immich's job queues are empty after the start, so it never redoes them (`audits/night-power-2026-10-13/` R2, `immich-check.txt`). Same ext4 effect on a plain 40-byte file. Other apps may do the same with files written just before a cut. | **WAITING-ON-OPERATOR** — 2026-10-14 spike (`audits/power-cut-fixes-2026-10-14/README.md` F, Immich v3.2.4): „thumbnails: missing" does not fix a zero-byte thumbnail (nor after deleting it — Immich decides from its database); „thumbnails: all" (force) fixes them; `integrity-missing-files` (`/api/admin/integrity/report?type=missing_file`) finds a lost original; nothing restores one but a backup | operator: the proposal | Operator: yes/no — after an unclean boot, run Immich's integrity-missing-files and show its report, and run „thumbnails: all" in the night window (CPU in proportion to the library); then CC builds it as a catalog-level hook | operator | +| **R-1007** | Apps & catalog | P3 | **After a power cut Immich shows photos as done that are broken, and nothing repairs them: of 101 photos uploaded in the last ~30 s before the cut, 81 kept their original but got an EMPTY thumbnail and preview (162 zero-byte files), and 1 — answered „201 Created" 0.3 s before the cut — has no original at all.** Immich's job queues are empty after the start, so it never redoes them (`audits/night-power-2026-10-13/` R2, `immich-check.txt`). Same ext4 effect on a plain 40-byte file. Other apps may do the same with files written just before a cut. | **OPEN** — 2026-10-14 spike (`audits/power-cut-fixes-2026-10-14/README.md` F, Immich v3.2.4): „thumbnails: missing" does not fix a zero-byte thumbnail (nor after deleting it — Immich decides from its database); „thumbnails: all" (force) fixes them; `integrity-missing-files` (`/api/admin/integrity/report?type=missing_file`) finds a lost original; nothing restores one but a backup. **Operator ruling 2026-10-14: fix only the broken photos** — after an unclean boot, find the photos with an empty thumbnail or preview, rebuild only those, run the missing-files integrity check, and tell the operator about lost originals. No „thumbnails: all". 2026-10-14 B2 spike (`audits/power-cut-fixes-2026-10-14/README.md` B2): **yes** — `POST /api/assets/jobs {assetIds, name: regenerate-thumbnail}` rebuilt exactly the 10 broken assets (1.55 s, 5.3 s CPU) and rewrote none of the other 20; an empty file maps to its asset by the first 36 characters of its name. | — | CC: build — a per-app after-unclean-boot hook that finds the zero-byte files under `thumbs/`, calls `POST /api/assets/jobs` `regenerate-thumbnail` for those asset ids only, runs `integrity-missing-files`, and tells the operator about lost originals (a task file: catalog + controller) | CC | ## App updates — 4 rows (P3 4)