v0.78.0: storage register uses the STABLE intermediary path, not the raw path

handleStorageRegister (the "Regisztrálás" action for an already-mounted,
unregistered drive) registered the raw /mnt/<name> path verbatim, unlike
runStorageInit/runStorageAttach which map to the stable /mnt/felhom-drives/<name>
path the agent actually binds the drive at. The controller then watched an empty
placeholder dir on the guest rootfs → "Rendszermeghajtón" + stuck "activation
pending" banner after a re-provision.

Fix: register stablePathForName(path.Base(req.Where)); attachIntoGuest still uses
the raw path (the agent operates on raw). Test + red-proof added.

Diagnosis: felhom.eu/documentation/audits/DIAGNOSE-drive-bind-after-reprovision-2026-06-23.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PsnU2ASocYrvzqE82YDYW
This commit is contained in:
2026-06-23 17:28:07 +02:00
parent 66d84627b8
commit 68e7e07838
4 changed files with 124 additions and 35 deletions
+49 -30
View File
@@ -1,36 +1,55 @@
# REPORT — controller v0.77.0: per-app `open_path` for the "Megnyitás" link
# REPORT — controller v0.78.0: storage register uses the STABLE path (not the raw path)
## Baseline
- felhom-controller `main` @ `66d8462`, **v0.77.0 → v0.78.0**. Trunk-based, `main`.
- Fixes the diagnosis `felhom.eu/documentation/audits/DIAGNOSE-drive-bind-after-reprovision-2026-06-23.md`
(§4/§5). Agent untouched (it already binds drives at the stable path).
## Problem
The dashboard / deploy / app-info **"Megnyitás"** (open app) button was hardcoded to the bare subdomain
root `https://{subdomain}.{domain}` for every app. Apps whose useful UI isn't at `/` opened to the wrong
place — e.g. Gokapi's `/` redirects away (its admin is `/admin`), Ghost's `/` is the public blog (admin
is `/ghost/`).
`handleStorageRegister` (the "Regisztrálás" action for an already-mounted, unregistered drive) registered
the **raw** `/mnt/<name>` path verbatim, while `runStorageInit`/`runStorageAttach` register the **stable**
intermediary path `/mnt/felhom-drives/<name>`. In the intermediary model the drive is live in the guest
only at the stable path, so the controller watched an empty placeholder dir on the guest rootfs →
"Rendszermeghajtón" badge (~31 GB), `0 connected / N disconnected`, and a stuck "activation pending"
banner. The real drives were fine the whole time.
## Change (commit `904e787`)
- `internal/stacks/metadata.go`: new optional `Metadata.OpenPath` (`open_path` in `.felhom.yml`),
appended to the open-app URL. Empty = bare root (unchanged behaviour for all other apps).
- Wired into all three link sites via `.Meta.OpenPath`**no handler changes** (all three templates
already carry `.Meta`):
- `dashboard.html:173` (range over stacks → `.Meta.OpenPath`)
- `deploy.html:18` (`.Meta` from the deploy handler)
- `app_info.html:13` (`.Meta` from the app-info handler)
## Fix (`controller/internal/web/storage_handlers.go`, `handleStorageRegister`)
- `stable := stablePathForName(path.Base(req.Where))``registerStoragePath(stable, …)` (was
`registerStoragePath(req.Where, …)`), mirroring `runStorageInit`/`runStorageAttach`.
- `attachIntoGuest(req.Where)` unchanged — the agent still operates on the **raw** path.
- Success `[INFO]` log + the `writeDiskJSON` payload now report the stable registered path (+ raw).
- No change to `runStorageInit`/`runStorageAttach`/`registerStoragePath` or any other behavior.
## Catalog (app-catalog-felhom.eu, commits `6a71c5a`)
Audited all 53 templates (subagent + cross-check). No Traefik `PathPrefix` anywhere; the only apps whose
bare `/` is not a usable landing:
- `gokapi``open_path: "/admin"` (file-share index redirects away)
- `ghost``open_path: "/ghost/"` (bare `/` is the public blog; admin/setup at `/ghost/`)
All other 51 serve or redirect usefully at `/` (e.g. plex `/``/web/`, radarr/sonarr/gitea/vaultwarden
`/``/login`). `onlyoffice` is API-only (status page at `/`) — left at root.
## Tests + red-proof
- `go build ./... && go vet ./... && go test ./...`**all green** before and after.
- New `TestHandleStorageRegister_RegistersStablePath` (`storage_handlers_test.go`): drives the HTTP
handler with `where=/mnt/felhom-flash`, asserts the registry holds `/mnt/felhom-drives/felhom-flash`
and the JSON reports stable `where` + raw. PASS.
- **Red-proof:** reverted the handler to `registerStoragePath(req.Where, …)` → the test FAILED
(`got "/mnt/felhom-flash"`) → re-applied the fix → green. ✅
- Existing `TestRunStorageInit_Success` / `TestRunStorageAttach_Success` (which assert stable registration
+ raw guest-attach) kept green, unmodified.
- `internal/web` test count: +1 (the new register test). Full suite green.
## Validation (live, guest 9201, v0.77.0 healthy)
- Rendered `Megnyitás` href on the gokapi **Beállítások** page: `https://share.demo-felhom.eu/admin`
- Dashboard hrefs: `share.demo-felhom.eu/admin` for gokapi; **all other apps unchanged** at bare root
(arcade, audiobooks, books, budget, komga, media, paperless, paste, photos, radarr, recipes, status,
tasks) — no regression ✓
- (Earlier, same session: gokapi's index `RedirectUrl` was also repointed `/``/admin` so direct-URL
visitors to the bare root reach the login too.)
## Deploy (v0.78.0 → guest 9201)
- _(filled at deploy)_ built+pushed `gitea.dooplex.hu/admin/felhom-controller:0.78.0` on 192.168.0.180;
deployed to 9201 (pull → `/etc/felhom-controller-image` → restart `felhom-controller-bootstrap.service`);
`docker ps``:0.78.0 Up (healthy)`.
## Notes
- `open_path` must start with `/`. It's purely cosmetic (the open link); routing is unchanged.
- Build/deploy: build-server `git pull` first (build.sh doesn't pull), `:0.77.0` via bootstrap.
## 9201 registry remediation (non-destructive)
- _(filled at remediation)_ deregistered the two raw entries `/mnt/felhom-flash` + `/mnt/felhom-usb`
(deregister-only — NOT eject, the live drive stays mounted), removed the empty rootfs placeholder dirs,
re-registered via the fixed `POST /api/storage/register` → both now at `/mnt/felhom-drives/<name>`.
## Verification (§6-C)
- _(filled at verify)_ registry holds the stable paths; controller selftest storage paths CONNECTED;
storage UI shows real size/device, **no "Rendszermeghajtón"** badge, **no activation banner**.
## Observations (recorded, NOT acted on)
1. `pendingActivationDrives` (`storage_handlers.go`) keys `attached` by the agent's raw `MountPath` and
compares to the registered `sp.Path`. With stable registration the activation banner clears, but the
function no longer detects a genuinely not-yet-propagated drive. The intermediary model activates LIVE
(no reboot), so the "~30 mp újraindítás" banner copy is likely obsolete; activation detection should
key off `GuestPath`/`BoundUnderParent` like `planDriveGates`, or the banner be retired. Follow-up.
2. The free-form settings storage-add (`handlers.go`) registers a user-typed path verbatim; a raw
`/mnt/<name>` typed there would hit the same shape. Advanced manual flow, out of scope.