REPORT.md overwritten with the Phase-1 gate run (catalog template fix + agreement test + live RomM migration on guest 9201, gate PASSED). CONTEXT.md dated entry. README HDD_PATH/felhom-data convention note corrected for Model-A single-nesting. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.6 KiB
REPORT — felhom-controller v0.52.0 (Phase 1 GATE: deploy-side double-nest fix)
Completes the Model-A double-nest reconciliation deferred in v0.48.0 and half-fixed in v0.51.0.
v0.51.0 fixed the backup-helper side (NamespaceRoot provenance); this slice fixes the
deploy/compose side and locks the two together. Validated live on guest 9201 (demo-felhom).
This is the GATE for the larger per-app-recovery-unit / Tier-2 slice — Phases 2–4 build on a proven single-nested, agreeing path layout. Per plan: Phase 1 shipped + validated first.
Root cause (corrected from the spec's assumption)
The extra felhom-data segment was not built in controller deploy.go — DeployStack passes
HDD_PATH through verbatim, and the deploy storage dropdown only ever offers registered in-guest drives
(GetSchedulableStoragePaths), never the system-data path. The segment was hardcoded in the app-catalog
compose templates as ${HDD_PATH}/felhom-data/appdata/<app>. On a Model-A in-guest drive the guest
mount /mnt/<drive> already IS the host's <drive>/felhom-data namespace, so that segment double-nested
to <drive>/felhom-data/felhom-data/appdata/<app> on disk — diverging from where the (v0.51.0) backup
helpers look: AppDataDir(NamespaceRoot(HDD_PATH,true)) = /mnt/<drive>/appdata/<app>, single-nested.
Changes
- Catalog (
app-catalog-felhom.eu, the behavioral fix): exhaustivegrepconfirmed exactly four HDD templates carried the segment —romm,nextcloud,immich,paperless-ngx. All changed${HDD_PATH}/felhom-data/appdata/<app>→${HDD_PATH}/appdata/<app>(volume mounts + header comments). - Controller (test-only, no runtime change):
internal/stacks/hddpath_agreement_test.goresolves a compose's${HDD_PATH}bind mounts via the real deploy-sideParseComposeHDDMountsand asserts they are byte-identical to the backup-sideAppDataDir(NamespaceRoot(HDD_PATH,true))— no doubledfelhom-data, deploy↔backup locked so they can't drift again.go test ./internal/stacks/...and./internal/appbackup/...pass;go build ./...clean. - No controller image rebuild. The controller passes
HDD_PATHthrough unchanged and already resolved the single-nested path since v0.51.0, so no runtime change was needed. The controller in guest 9201 stays:0.51.0(functionally current); v0.52.0 marks the catalog gate + test and rolls into the next image build (Phase 2). The controller is golden-image/bootstrap-managed — not rebaked for a no-op.
Live validation (guest 9201, demo-felhom, root@felhom-pve)
- Only one live HDD app: RomM (the others aren't drive-deployed).
HDD_PATH=/mnt/felhom-usb; data was at the doubled/mnt/felhom-usb/felhom-data/appdata/romm. - Catalog fix delivered by the real mechanism: the controller's periodic git-sync logged
"Sablonok frissítve — frissítve: immich, nextcloud, paperless-ngx, romm" and updated all four
on-disk stack files to
${HDD_PATH}/appdata/<app>(single-nest) — confirmed in/opt/docker/stacks/*/docker-compose.yml. - RomM migrated (stop → move → verify → redeploy, ordered, reversible
mv, never delete-then-move): captured RomM's runtime env from the running containers into a guest-only temp file (secrets never left the guest),docker compose down(named DB/redis volumes preserved), moved/mnt/felhom-usb/felhom-data/appdata/romm→/mnt/felhom-usb/appdata/romm, verified file count unchanged, then recreated with the fixed compose + captured env. - Result: RomM binds the single-nest paths
(
/mnt/felhom-usb/appdata/romm/{library,resources}), all three containers healthy, DB connected (the captured creds worked), in-guestHTTP/1.1 200 OK, "Application startup complete". Old namespace/mnt/felhom-usb/felhom-data/appdata/confirmed empty; backups already single-nested at/mnt/felhom-usb/backups/primary. Controller untouched & healthy throughout.
Gate outcome — PASSED
A drive-app lands single-nested AND the backup helpers resolve the identical path — proven live (not
REPORT-only): the deploy-resolver and the backup helper agree by test and by the live RomM binds, the
catalog fix propagated via real git-sync, and no doubled felhom-data remains. Cleared to start Phase 2.
Not done (intentionally deferred to Phases 2–4)
Per-app recovery unit (backup/<app>), Tier 2 off-drive copy (auto-enabled, durable-id target, rootfs
headroom guard), secret preserve-vs-regenerate classing, FileBrowser scoping, deploy-UI DB-on-SSD note,
monitoring storage sort/descriptions. The README's backup-paths section still describes the stale
restic/secondary layout — to be rewritten when Tier 2 is built.