hub v0.150.0: app_repaired_after_crash — allow-listed + operator-only, counts line in the operator mail (R-1007); decision 236 recorded
gates / gates (push) Successful in 6m40s

The operator's half of the repair after an unclean boot (controller 0.311.0): counts only, never a
file name; warning mails, info is recorded. Registered in allowedEventTypes and operatorOnlyEvents in
the same commit, plus the per-app cooldown list; tests pin the pair, a household that enabled the type
gets nothing, and the counts line (red-proofed). Decision 236 (operator, 2026-10-14): the box asks
Immich through Immich's own job queue. R-1007 updated; the scripts' run on 9202 added as evidence.

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
This commit is contained in:
2026-10-14 16:58:35 +02:00
parent 5d39171e90
commit 822d039344
10 changed files with 155 additions and 3 deletions
@@ -915,6 +915,17 @@ its length, and both fixes cost something the household would notice — operato
127. **The agent's three by-design abilities (`03` §3.1) stay for now**; revisited before the first paying customer.
*Operator ruling 2026-10-05.* (R-861)
### 2026-10-14 — R-1007: how the box asks Immich to repair after a power cut (recorded before the build)
236. **The box repairs Immich's broken photos through Immich's OWN job queue (option 1, spike A4)** — the controller adds
the same job Immich's API adds (`AssetGenerateThumbnails {id}` on `thumbnailGeneration`, Immich's own `bullmq`
inside `immich-server`) for the asset ids of the zero-byte thumbnail/preview files only, queues Immich's own
missing-files check, and READS its report from the database (a SELECT, never a write). Not chosen: a household-made
API key (it covers only the admin's photos — a family member's were refused, measured), a database write, the
household pressing „thumbnails: all". The job/queue names are internal to Immich: the catalog pins the Immich
versions they were proven on; any other version is skipped and reported, never guessed. Evidence:
`audits/immich-repair-2026-10-14/` Part A. *Operator ruling 2026-10-14, in chat.*
### 2026-10-12 (evening) — the notification page's two questions answered (recorded before the work; the disk + shrink brief)
*Operator answers in chat 2026-10-12 ~16:30, „as picked" (`08` §8.1).*
@@ -0,0 +1,14 @@
syntax rc=1
uploaded admin 20 member 10
damage: 4 empty files, 1 original deleted
== repair.js with 4 ids
FELHOM_REPAIR_OK queued=4 waited_ms=2005
rc=0 in 2.38 s; empty now: 0
controls rewritten: 0 of 53
== lost.js
LOST {"name":"gen-007.jpg","taken":"2026-01-03 01:00"}
FELHOM_LOST_OK lost=1 waited_ms=2040
rc=0 in 2.4 s
== a second run of lost.js (a stale or repeated report?)
FELHOM_LOST_OK lost=1 waited_ms=2040
+1 -1
View File
@@ -136,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. | **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 |
| **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". **Decision 236 (operator 2026-10-14, after spike A `audits/immich-repair-2026-10-14/`): the box asks Immich through Immich's own job queue (no key; every user's photos; the lost-file report read from the database); the catalog pins the proven Immich versions.** 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 per decision 236 — catalog block `after_unclean_boot` (Immich), controller runner after an unclean boot, household note for lost photos, operator-only event; live proof on demo-hp 9201 (`audits/immich-repair-2026-10-14/`) | CC |
## App updates — 4 rows (P3 4)