Files
felhom-controller/REPORT.md
T
2026-06-15 21:53:09 +02:00

97 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — two UI cleanups + M3 live re-verification (2026-06-15)
**Deployed:** controller **v0.68.3** on guest 9201 / felhom-pve (bootstrap-managed; healthy).
**Commits:** `37ed757` (v0.68.2 CSS) · `a821a9d` (v0.68.3 refresh fix). Trunk-based, pushed to `main`.
---
## Part 1 — stack-card state-badge clipping fix (v0.68.2, CSS-only)
**Symptom:** on the /stacks page, an **unhealthy** app's state badge clipped — "Nem egészséges" rendered
as "Ner…". Healthy / not-deployed cards were fine.
**Root cause (confirmed):** `.stack-detail-header` is `flex` / `space-between` holding `.stack-title-row`
(logo + title + subdomain link + the `route-unpublished` warning) and `.stack-state-badge`. Only on an
unhealthy app does the long "⚠ URL nem elérhető útvonal nincs publikálva" warning render, inflating the
title-row. The title-row had no `min-width:0` (so it wouldn't shrink below its content) and the
`white-space:nowrap` badge had no `flex-shrink:0` (so the flexbox compressed the *badge* instead → clip).
**Fix** (`internal/web/templates/style.css`):
```css
.stack-title-row { flex: 1; min-width: 0; } /* shrinks + wraps its own content */
.stack-state-badge { flex-shrink: 0; } /* never compressed */
```
**Browser-verified on /stacks (demo, guest 9201):**
- BEFORE (v0.68.1): komga badge clipped to "Ner…" at the card's right edge (screenshot captured live).
- AFTER (v0.68.2): komga badge reads the full **"Nem egészséges"**; the "⚠ URL nem elérhető…" warning
**wraps within the title column** (screenshot captured live).
- Regression: Mealie ("Fut", healthy) and all "Nincs telepítve" cards visually unchanged.
**Defensive note (not applied):** the spec offered adding `flex-shrink:0` to
`.badge-missing-storage`/`.badge-orphaned` *if* a card showing BOTH unhealthy AND a missing-storage/
orphaned badge still clipped. No such card exists live right now, and the primary fix's mechanism
(title-row `min-width:0` absorbing all shrink) already shields sibling badges, so it was left out — a
one-liner if that combo ever appears.
---
## Part 2 — M3 live re-verification (no code change — the migrate path is correct)
**Goal:** prove the migrate merge-walk re-asserts the `2775`-setgid/gid-1000 convention on a
**pre-existing STALE dir** (the B3 calibre case), which the acceptance audit had only covered by unit
test + static convention.
**Method:** two full **migrate-all** runs driven through the dashboard UI (the real
`/api/storage/migrate` endpoint, all 8 flash apps: audiobookshelf, calibre-web, immich, jellyfin, komga,
paperless-ngx, radarr, romm): **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; `stat` recorded.
**Result — PASS (clean, non-hollow):**
- Pre-seeded `userdata/documents` at `755 gid1000` — a dir **no app mounts** — became
**`2775 gid1000`** after migrate (the `EnsureUserdataDir` re-assert in `walkMerge`, migrate.go:854-859).
Same for the seeded `userdata` root and `userdata/import`. Whole target userdata tree = `2775`.
- Integrity: static seeded files (`b3-document.txt`, `b3-movie.txt`, `b3-photo.txt`, `demo.jpg`) had
**identical sha256** before/after.
- All 8 apps redeployed **healthy** on the target (komga "unhealthy" = its pre-existing
`/api/v1/actuator/health` 401 — serving, unrelated to migration).
**Secondary finding — the `import/calibre` 755 is an APP clobber, not a migrate bug.** In both runs
`userdata/import/calibre` ended at `755`. Isolated live: **calibre-web (CWA)** bind-mounts
`${USERDATA_PATH}/import/calibre` as `/cwa-book-ingest` and **chmods it to 755 (strips setgid) on every
startup** — proven by setting it to `2775` and restarting calibre-web alone (reverted to `755`, no
migration). The merge-walk *does* re-assert `2775` during copy; calibre-web re-clobbers it during the
flip/redeploy phase (this is also why the source flash calibre was already `755` pre-migration).
**migrate.go was therefore NOT modified** — the M3 path works. If the convention must hold for that
single-app ingest dir, the fix belongs in the catalog/app layer (an `umask`/entrypoint wrapper for CWA),
not in migrate.
---
## Part 3 — Beállítások endless-refresh loop fix (v0.68.3) — found during Part 2
**Symptom (user-reported):** after any migration finished, the settings page reloaded itself every
~1.5 s, forever.
**Root cause:** `MigrationStatus` keeps returning the last `done` job indefinitely (never cleared). The
settings page's resume-view IIFE called `migWatch()` for *any* returned job, and `migWatch`'s `done`
branch does `setTimeout(()=>location.reload(),1500)`. So every load saw the persisted `done` job → watched
it → reloaded → saw it again → endless loop.
**Fix** (`internal/web/templates/settings.html`): the resume-view now starts the watcher **only for an
in-progress job** (`phase!=='done' && phase!=='aborted'`). The one-time post-completion reload still fires
from the *active* watcher started by `storageMigrateAll`, so a real migration refreshes drive state once
when it finishes — but a stale terminal job no longer triggers the loop.
**Browser-verified on v0.68.3:** with a persisted `done` job present in the journal, the settings page
stayed put for 25 s (`navType:navigate`, planted marker survived, migration panel idle) — no reload.
---
## Resting state
- Apps healthy on **felhom-flash** (the default drive); **felhom-usb** cleaned/empty.
- Controller **v0.68.3** deployed live on guest 9201.
- Build/deploy: built+pushed on 192.168.0.180, deployed via the bootstrap mechanism
(`docker pull``/etc/felhom-controller-image` → restart `felhom-controller-bootstrap.service`).