# REPORT — v0.73.0: F2 mount-role fallback (enrolled user-data drives ejectable/decommissionable) **Date:** 2026-07-06 · **Class:** risky/supervised (loosens a role gate; bounded by containment red-proofs). **Baseline:** `main` @ `26664d6` (v0.72.0) → `7545af8`. Part A of the pilot-blockers bundle (B = controller v0.102.0, C = catalog healthcheck sweep). Provenance: campaign F2 + RERUN addendum. ## The bug `roleForMountPath` (`internal/localapi/disks.go`) resolved a mount's protection role ONLY from the PVE storage view (`Observe`). A bind-mounted RAW enrolled user-data drive is not a PVE storage → no MountPath match → fail-safe `RoleSystem` → the eject (disks.go:353) and decommission (disks.go:404) role gates 403'd **every user-data drive in the standard topology** (campaign journal: `where=/mnt/teszt_enroll role=system`). ## The fix (only `roleForMountPath`) After the MountPath loop misses on a SUCCESSFUL Observe, resolve the mount's device from the host mount table (mirroring `durableIDForMount`'s Impl-2b) and classify **device-keyed**: - non-`/dev` source (NAS) → system; - device on the same whole disk as a KNOWN target → THAT target's role (containment, new `storage.SameWholeDisk`, whole-disk granularity so a protected disk can't be ejected here); - else `RoleForRawDevice` (system-disk membership). **Fail-safe preserved:** an Observe error returns system BEFORE the fallback (a blind containment pass could label a backup drive user-data — permissive); a mount-read failure or absent/NAS mount → system. Handlers, `deviceRole`, `DecommissionExecutor`, `classify.go`, `ReassertGuestBinds` untouched; the `deviceRole`/`roleForMountPath` unification is deferred. ## Tests + red-proofs (`f2_role_fallback_test.go`) A1 bind-mounted user-data ejectable + decommission effects; B1 containment (mount on a protected target's disk → 403); B2 system-disk mount → 403; C1/C2 fail-safe (absent, NAS → 403); C3 Observe-error skips the fallback (403 + Mounts() called once). **Three red-proofs demonstrated:** pre-fix body → A1 FAIL (exact `role: system` 403); containment-skip mutation → B1 FAIL (protected disk becomes ejectable); Observe-error fallback → C3 FAIL (permissive). Existing `TestEject_RoleGated`/`TestDecommission_*` green UNMODIFIED. Full gate `go build/vet/test ./...` = PASS. ## Deploy + live acceptance (on `/mnt/teszt_enroll` ONLY) Built `-X main.version=0.73.0` on 180, deployed to felhom-pve (`.bak-0.72.0` kept). `--version` = 0.73.0, `systemctl is-active` = active, capabilities 56/56 degraded=0. Full F2 lifecycle through the real controller endpoints: **eject → HTTP 200** (was 403), **decommission-anyway → HTTP 200** (`decommissioned:true`, was 403), post-decommission bind detached, **agent restart → drive stayed detached (no rebind)**, re-commission (reconnect) → 200, **end state == pre-state** (bound on /dev/sdb, attached, durable `uuid:f2236136-ced7…`). ## Not changed / observations Only `roleForMountPath` + the new `storage.SameWholeDisk` helper. The pre-existing `VM.Audit` permission ERROR in the agent log is unrelated (known A1 privilege gap). The `deviceRole`/`roleForMountPath` unification refactor is deferred.