From d1056573557e3b5d2babe47686eda5057b4dbefa Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 15 Jun 2026 21:53:10 +0200 Subject: [PATCH] docs: M3 live re-verification addendum (closes E14/E15 residual) + two controller UI fixes Co-Authored-By: Claude Opus 4.8 (1M context) --- ...storage-lifecycle-acceptance-2026-06-15.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/documentation/audits/storage-lifecycle-acceptance-2026-06-15.md b/documentation/audits/storage-lifecycle-acceptance-2026-06-15.md index 718a3f0..f361f67 100644 --- a/documentation/audits/storage-lifecycle-acceptance-2026-06-15.md +++ b/documentation/audits/storage-lifecycle-acceptance-2026-06-15.md @@ -157,3 +157,61 @@ dashboard + monitoring HTTP 200; no exited containers. ## Commit hashes agent `1e20584` (v0.36.7) · controller `7a85732` (v0.68.1) · catalog `939864f`. Agent versions this run: v0.36.0→v0.36.7. Controller: v0.68.0→v0.68.1. + +--- + +## Addendum (2026-06-15, later session) — M3 live re-verification + two UI fixes (controller v0.68.2/.3) + +Closes the **E14/E15 residual** above ("full live migrate-all not re-run; M3 unit-tested + convention +verified live"). The M3 setgid re-assertion on a **pre-existing stale dir** is now **live-proven** on +guest 9201, alongside two small UI cleanups shipped the same session. + +### M3 — migrate merge-walk re-asserts setgid on a stale dir (LIVE, non-hollow) +Two full **migrate-all** runs were executed **via the dashboard UI** (the real `/api/storage/migrate` +endpoint, all 8 flash-resident apps): flash→usb, then usb→flash (restoring apps to the default drive). +Before each, the migrate **target** was pre-seeded host-side with deliberately-stale `0755`, +**non-setgid** userdata dirs (mimicking the B3 calibre case), `stat` recorded. + +**Result — clean proof (usb→flash run):** a pre-seeded `userdata/documents` at `755 gid1000` — +a dir **no app mounts** — came out **`2775 gid1000`** after migrate (`EnsureUserdataDir` re-assert in +`walkMerge`, migrate.go:854-859), as did the seeded `userdata` root and `userdata/import`. Every userdata +dir in the tree was `2775` afterwards. Static seeded files (`b3-document.txt`, `b3-movie.txt`, +`b3-photo.txt`, `demo.jpg`) had **identical sha256** before/after (integrity intact). All 8 apps +redeployed **healthy** on the target (komga "unhealthy" throughout = its pre-existing +`/api/v1/actuator/health` 401, serving fine — unrelated). + +**Important secondary finding — the residual `import/calibre` 755 is NOT a migrate bug.** In *both* runs +`userdata/import/calibre` ended at `755` despite the merge-walk. Root cause isolated live: the +**calibre-web (CWA) container** bind-mounts `${USERDATA_PATH}/import/calibre` as its `/cwa-book-ingest` +drop-zone and **chmods it to 755 (strips setgid) on every startup** — proven by setting the dir to +`2775` and restarting calibre-web (reverted to `755` with no migration involved). This is why the +*source* flash calibre was already `755` pre-migration too. The merge-walk re-asserts `2775` correctly +during the copy phase; calibre-web clobbers it again during the flip/redeploy phase. So **migrate.go was +NOT changed** — the M3 path is correct. (If the convention matters for that single-app ingest dir, the +fix belongs in the catalog/app layer, e.g. an `umask`/entrypoint wrapper for CWA, not in migrate.) + +### UI fix 1 — stack-card state-badge clipping (controller v0.68.2, CSS) +`.stack-detail-header` is flex/space-between; the title-row lacked `min-width:0` and the +`white-space:nowrap` `.stack-state-badge` lacked `flex-shrink:0`, so on an **unhealthy** app the long +"⚠ URL nem elérhető…" route-unpublished warning inflated the title-row and the flexbox compressed the +badge — clipping "Nem egészséges" to "Ner…". Fix: `.stack-title-row{flex:1;min-width:0}` + +`.stack-state-badge{flex-shrink:0}`. Browser-verified on /stacks (komga BEFORE clipped "Ner…" → AFTER +full "Nem egészséges" with the warning wrapping in the title column; Mealie/healthy + not-deployed cards +unchanged). The defensive `flex-shrink:0` on `.badge-missing-storage`/`.badge-orphaned` was **not** +added — no card is currently both unhealthy AND missing-storage/orphaned, and the title-row absorbing all +shrink already shields sibling badges; one-liner available if that combo ever surfaces. + +### UI fix 2 — Beállítások endless-refresh loop (controller v0.68.3) +Found while validating M3: after **any** migration finished, the settings page reloaded itself every +~1.5 s forever. `MigrationStatus` keeps returning the last `done` job indefinitely; the page's resume-view +called `migWatch()` for *any* job, and `migWatch`'s `done` branch does `setTimeout(location.reload,1500)` +→ load → see persisted done → watch → reload → loop. Fix (settings.html): resume-view watches **only an +in-progress job** (`phase!=='done' && phase!=='aborted'`); the one-time post-completion reload still +fires from the active watcher. Browser-verified: with a persisted `done` job present, the page stayed put +for 25 s (`navType:navigate`, marker survived, panel idle) on v0.68.3. + +### Resting state +Apps healthy on **felhom-flash** (default drive); felhom-usb cleaned/empty; controller **v0.68.3**. + +### Commit hashes (this addendum) +controller `a821a9d` (v0.68.3; CSS fix v0.68.2 = `37ed757`). Deployed live on guest 9201 / felhom-pve.