Files
felhom-agent/REPORT.md
T

3.1 KiB

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.