# REPORT — Impl-2a: raw-device discovery + registry-sourced drive tracking (agent v0.55.0) **Date:** 2026-07-01 · **Repo:** `felhom-agent` (backend only) · **Class:** Risky/supervised (re-sources the drive health/detach path — a regression re-creates the 3b-fix false-detach class). No mkfs here. Impl-2a of the drive-enrollment series (SPIKE-drive-enrollment §SQ1/SQ4/SQ5). Makes raw (non-PVE-storage) drives discoverable for enrollment AND health-tracked without being a PVE storage. The controller wizard (Impl-2b) + the shared-box operator gate (Impl-3) are separate. ## 1. Baseline → target felhom-agent `5209830` (v0.54.0) → **v0.55.0**. ## 2. Files changed + commit - `internal/storage/candidates.go` (new) — `ListCandidateDisks` (enumerate `/sys/block` whole-disks → Impl-1 `deviceUnclaimed` → probe: size/model/FS/data-bearing/durable-id; mountable ext4/xfs split). - `internal/storage/registry_known.go` (new) — `RegistryKnownTargets` (watchdog `Known()` from intent registry + Felhom `.mount` units) + `ReconcileExistingDrives` (idempotent migration). - `internal/localapi/disks.go` — `GET /disks/candidates` handler + `DiskOps.ListCandidateDisks`; `handleDisks` additive+deduped registry-drive union. `internal/localapi/server.go` — route + `DriveTargets` option. - `cmd/felhom-agent/main.go` — swap watchdog `KnownTargets` source → `RegistryKnownTargets`; run the migration at start; thread `driveKnown` into the local-API. - Tests: `internal/storage/registry_known_test.go`, `internal/localapi/disks_candidates_test.go`, `disks_test.go` (fake). `CHANGELOG.md`, `README.md`, version. - Commit **`91f6a26`** on `main` (parent `066e3bf`). Watchdog/HostLiveness/Remounter unchanged. ## 3. Green gate `go build ./...`, `go vet ./...`, `go test ./...` — clean (local + build server 180). ## 4. Tests + red-proof - `TestRegistryKnownTargets`: enrolled drive tracked; `new`-intent excluded; ejected still tracked; non-Felhom unit ignored; KnownTarget fields correct (DurableID `uuid:`, MountBacked, MountPath). - **`TestRegistryVsObserve_RedProof`:** with NO PVE storage, the OLD `Observer.Known()` returns empty (drive invisible — the 3b-fix class) while `RegistryKnownTargets.Known()` tracks it. Proves the decoupling adds the coverage. - `TestReconcileExistingDrives_Idempotent`: a mounted Felhom-unit drive → enrolled; re-run no-op; an UNMOUNTED unit is NOT auto-migrated. - `TestDiskCandidates_Split`: initialize = all unclaimed; attach = mountable-FS subset. (Candidate fail-safe carries through Impl-1's `classifyClaim`, unit-tested there.) ## 5. Deploy + live validation (felhom-pve, agent v0.55.0) Published Gitea `felhom-agent/0.55.0` (sha `b8122511460413489ae0f5323ad34ebeaa00cfd091e91cba06f00398128bb577`); deployed (backup `.bak-0.54.0`, restart). All four scenarios proven: | Scenario | Result | |----------|--------| | **C — no false detach** | ✅ post-deploy: 5 storages (Observe intact), both drives mounted, both intents `enrolled`, no detach/error in the journal, 9201 running. Migration a no-op (drives already enrolled). | | **B — registry-sourced tracking (definitive)** | ✅ controlled `systemctl stop mnt-felhom\x2dflash.mount` (app-less drive) → watchdog **detected** `felhom-flash attached→disconnected` (`durable_id=uuid:81a26531…` = the registry key) → **self-healed** (`re-mounting enrolled drive` → gate benign → `ensured mount` → remounted in 5s). Proves the Known set is registry+units-sourced, NOT silently empty. | | **A — discovery** | ✅ `GET /disks/candidates` (real local-API endpoint) returns **only `/dev/sdd`** (size 63.8G, model, fstype ext4, mountable, `durable_id uuid:950d8ad0…`) under both `initialize` and `attach`; **sda/sdb/sdc excluded**. | | **D — fail-safe** | ✅ carried through the reused Impl-1 filter (`classifyClaim` exclude-on-error; unit-tested). | ## 6. NOT yet done - **Impl-2b:** the controller wizard rewiring (consume `GET /disks/candidates`) + the enroll orchestration UI + a live end-to-end raw enrollment (format via the Impl-1 guarded path → mount → bind → intent). **Impl-3:** the shared-box operator gate for self-serve format. - The controller settings storage-section screenshot for Scenario C (agent-side evidence above is definitive; the UI still shows the drives via Observe dir-storages + the registry union). ## 7. Observations - The existing drives are still PVE dir-storages (not removed — later cleanup, per the spike). They now ALSO track via the registry; `/disks` dedups by mount path (no doubles). Retiring the dir-storages is optional and out of scope here. - `/dev/sdd` (the Impl-1 throwaway, now ext4) is a live discovery candidate; unmounted, not enrolled.