# DIAGNOSIS — post-F9 storage-registration gap (read-only; no system changes made) **Date:** 2026-06-14. **Scope:** why the HDD (`felhom-usb`) is attached + written-to by RomM yet badged "Nem regisztrált" and absent from the deploy dropdown. **Method:** live SSH (read-only) + controller source. **No state changed** — no registration, deploy, restart, or edits. Diagnosis only; fix to be specced next. ## TL;DR F9 attached the HDD at the **agent/guest layer** (the `pct set -mpN` bind). The controller's **storage registry** (`settings.json → storage_paths`) is a **separate layer** that F9 never touched. The controller registers a drive only through its own enroll flows (`runStorageInit` / `runStorageAttach` / `handleStorageRegister`), each of which calls `registerStoragePath`. In the F9 session the drive was attached by calling the **agent's `/disks/guest-attach` directly** (and RomM got `HDD_PATH=/mnt/felhom-usb` via a manual `deploy` value) — both bypass the controller's registry. Auto-discovery can't backfill it (it's a one-time seed that only scans deployed-app `HDD_PATH`s, never the agent's attached-drive list). Result: attached + in use, but unregistered → not selectable for a new app. **F9 is NOT closed.** ## Q1 — Real storage topology (what each path maps to) | Name (UI) | Host path | Device | Size / free | What it is | |---|---|---|---|---| | `Tárhely (felhom-data)` ★ (registered) | `/mnt/sys_drive/felhom-data` | `/dev/mapper/pve-vm--9201--disk--0` | 32 G / **~29 G** | the **internal OS-disk volume** (rootfs disk-0). The "28.7 GB szabad" in the dropdown = this. | | `felhom-usb` (NOT registered) | `/mnt/felhom-usb` | `/dev/sdb1` | **916 G / 870 G** | the **HDD**, guest-attached (mp1), 2.1 MB used | Evidence: `pct config 9201` → `mp1: /mnt/felhom-usb/felhom-data,mp=/mnt/felhom-usb`; guest `df` → `/mnt/sys_drive` on `…disk--0` (32 G, 29 G avail) vs `/mnt/felhom-usb` on `/dev/sdb1` (916 G, 870 G avail). The registry (`settings.json`) lists only `{"path":"/mnt/sys_drive/felhom-data","label":"Tárhely (felhom-data)","is_default":true,"added_at":"2026-06-13T22:22:50Z"}`. **Confirmed: the "28.7 GB" option is the internal volume, not the HDD.** ## Q2 — Where RomM's data is + how it got an HDD path - RomM's `app.yaml` (`/opt/docker/stacks/romm/app.yaml`): `env.HDD_PATH: /mnt/felhom-usb`, `deployed: true`, `locked_fields: [HDD_PATH]`. Its data dirs live under `/mnt/felhom-usb/felhom-data/appdata/romm/…` (the HDD). - **How it got set:** the `HDD_PATH` deploy field was filled with `/mnt/felhom-usb` when RomM was (re)deployed onto the HDD during the F9 P3/restore test. The deploy path validates `os.Stat(HDD_PATH)` exists (`stacks/deploy.go` path-field check) — it does, because F9 had bound `/mnt/felhom-usb` into the guest — but **the deploy does NOT register the path** in `storage_paths`. So RomM references the HDD path *directly*, entirely independent of the registry. That's how "RomM uses the HDD" coexists with "HDD unregistered." ## Q3 — Why `felhom-usb` is "Nem regisztrált" The registry (`settings.json storage_paths`) contains **only** `/mnt/sys_drive/felhom-data`; `/mnt/felhom-usb` is absent. Nothing registered it, at any layer: - **F9's attach is agent-layer only.** `ReassertGuestBinds` / `handleDiskGuestAttach` → `guestbind.go AttachBind` do `pct set -mpN` (the bind). They never call the controller's `registerStoragePath`. In the F9 session the drive was attached by calling the agent `/disks/guest-attach` **directly**, bypassing the controller enroll flow. - **Deploy doesn't register.** Setting `HDD_PATH` on RomM only validates existence (above), no registry write. - **Auto-discovery can't backfill it** — two reasons in `settings.AutoDiscoverStoragePaths` (`internal/settings/settings.go:584`): 1. **One-time seed:** `if len(s.StoragePaths) > 0 { return // already configured }` (≈:592). The registry already holds `sys_drive` (seeded 2026-06-13), so discovery is now **permanently inert** on every restart. 2. **Wrong source even if it ran:** it's fed by `discoverHDDPaths(StacksDir)` (`cmd/controller/main.go:1337`, called once at startup, `main.go:126`), which scans **deployed apps' `HDD_PATH`** — never the agent's `/disks` attached-drive list. A drive attached out-of-band (or whose app was deployed after startup) is invisible. So: **registration is decoupled from attach; auto-discovery is a one-shot startup seed of app `HDD_PATH`s; the agent-layer F9 bind and the manual deploy both bypass registration** → the HDD stays unregistered. ## Q4 — Why the deploy dropdown excludes the HDD The deploy dropdown is populated from `s.settings.GetSchedulableStoragePaths()` (`internal/web/handlers.go:323`), i.e. **registered paths only**. `/mnt/felhom-usb` is not in the registry → not schedulable → absent. So a new app (Calibre) can only be pointed at `sys_drive` (the 31 G internal volume). The "Nem regisztrált" badge is the storage page (`storageWizardPageHandler`) merging the agent `/disks` (attached, `guest_attached=true`) against `GetStoragePaths()` (registry) and flagging the difference (`storage_handlers.go` `Registered` field; `settings.html` `window.__registeredPaths`). ## Q5 — Intended registration-vs-attach behavior (per the code) The controller's design intends **register + attach as one operator-driven enroll operation**, NOT an automatic side-effect of an agent bind: - `runStorageInit` (format a blank/new drive) and `runStorageAttach` (mount an existing-fs drive — the "Csatolás" button) both do: assign (host mount) → **`registerStoragePath`** → `attachIntoGuest`→`agent.GuestAttach` (`internal/web/storage_handlers.go:83-158`). The comment is explicit: *"the StoragePath **registration is the durable intent**, so a transient attach failure is logged (not fatal) — P3 self-heal completes it."* - For an **already-mounted, unregistered** drive (exactly `felhom-usb`'s state), there is a dedicated action: `POST /api/storage/register` → `handleStorageRegister` (`storage_handlers.go:442`, the "Regisztrálás" button), commented: *"the natural primary action for a mounted-but-unregistered data drive (e.g. **felhom-usb**): the customer's intent is to USE the existing data, not wipe it… registering a host-only mount otherwise leaves it guest-invisible (the exact gap that produced the 'nem elérhető' banner)."* It registers + attaches into the guest. So per the code, registration is meant to come **through these controller flows**. There is **no reconciliation that auto-registers a drive the agent attached out-of-band** — which is precisely the F9 case (the agent's re-assert / a direct guest-attach binds the drive without ever invoking the controller's register step). ## Q6 — The "felhom-data" naming collision Deliberate convention, but genuinely confusing. `felhom-data` is BOTH: 1. the **path tail of the internal volume's registered path** (`/mnt/sys_drive/felhom-data`), surfaced as the label `Tárhely (felhom-data)`, and 2. the **per-drive Felhom namespace subdirectory** created on EVERY user-data drive by the agent's `AttachBind` (`guestbind.go:29 felhomDataNS = "felhom-data"`, "matches `appbackup.FelhomDataDir`") — hence `/mnt/felhom-usb/felhom-data/…`. So `felhom-data` denotes both a specific volume and the generic namespace. Risk: the label `Tárhely (felhom-data)` reads as generic but is specifically the OS-disk volume; meanwhile the HDD also has a `felhom-data` dir. A clearer label (e.g. "Belső SSD" for the internal volume vs the drive's own name for the HDD) would remove the ambiguity. ## Recommended fix direction (to spec next — NOT implemented here) 1. ~~**Auto-register on attach (primary).**~~ **REJECTED (2026-06-14)** — contradicts the new→enrolled manual-enrollment model; manual enroll is by design. A drive becomes usable through the explicit enroll/"Regisztrálás" flow (recommendation #2), not by auto-registering whatever the agent attached out-of-band. (The "make discovery additive, not return-if-any-path-exists" sub-point WAS adopted — shipped in controller v0.64.0, A1 — but only as additive pickup of paths referenced by *deployed apps*, NOT as auto-register-on-attach.) ~~Make a drive the agent has attached into the guest become a registered storage path automatically, so F9's attach is usable end-to-end. Options: (a) the controller's startup/periodic storage reconcile consults the **agent `/disks`** and registers any `guest_attached=true` user-data drive missing from the registry (extend beyond the app-`HDD_PATH` scan); and/or (b) the enroll/re-assert path that binds a drive also performs `registerStoragePath`. Also **remove the one-time-seed gate** (or make discovery additive, not "return if any path exists") so it can pick up drives added after the first run.~~ 2. **Keep `handleStorageRegister` as the explicit fallback** ("Regisztrálás" button) for the mounted-but-unregistered case, and make the "Nem regisztrált" badge clearly actionable. For the **immediate** demo state, this button (`POST /api/storage/register {where:/mnt/felhom-usb}`) would register felhom-usb + make it selectable — no fix needed to recover now. 3. **Clarify the `felhom-data` label** (Q6) to disambiguate the internal volume from the per-drive namespace. Recommended: **both** auto-register-on-attach AND the clearer manual path — auto so the normal flow "just works", manual for out-of-band/edge cases. ## Verdict on F9 — NOT closed F9 made the HDD present + writable **inside the guest** (agent layer), but did not make it **usable for new apps through the UI** (controller registry layer). The deploy dropdown is gated on the registry; the registry is unaware of the agent-attached drive. **F9 should remain open (or spawn an F9b)** until: attach ⇒ auto-registered ⇒ a NEW app (e.g. Calibre) can be deployed to the HDD through the normal deploy UI with its data landing on `/dev/sdb1` persistently. Today that round-trip fails at the dropdown.