agent v0.25.0: slice 10 P2 — bind enrolled user-data drives into the guest

POST /disks/guest-attach binds an enrolled drive's felhom-data namespace into
the guest (Model A: felhom-data is the bind source mounted at /mnt/<name>, so
only Felhom's namespace crosses in). GuestBinder does mkdir+chown(100000)+pct set
(RW bind) via the fenced runner. Idempotent, free-slot selection, path-validated.
Spike-proven on 9201. Pairs with controller P2C + golden /mnt:rslave (P2B).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 15:38:55 +02:00
parent d1bd44d2d5
commit c1d04c28c1
6 changed files with 311 additions and 8 deletions
+24
View File
@@ -3,6 +3,30 @@
All notable changes to **felhom-agent** are recorded here. Update on every code
change that gets pushed.
## v0.25.0 — slice 10 P2: bind enrolled user-data drives into the guest (passthrough) (2026-06-12)
External user-data drives are mounted on the HOST but were never passed INTO the guest (diagnosed
Branch A), so apps silently wrote to the rootfs and the controller couldn't see them. This adds the
guest passthrough. Spike-proven on 9201 first (see REPORT / the usb-passthrough-spike findings):
`pct set` **bind form** (host path, never `storage:size`), `chown` to the guest base (idmap not clean
for mixed-ownership data), `shared:49` propagation host↔guest automatic.
- **`POST /disks/guest-attach` (`internal/localapi`)** — self-scoped (vmid from token). Binds an
enrolled drive's **felhom-data namespace** into the guest at `/mnt/<name>` (**Model A**: the
felhom-data dir is the bind source mounted AT `/mnt/<name>`, so only Felhom's namespace crosses into
the guest — the customer's other data on the drive never does). Idempotent (returns the existing slot
if already bound); picks the lowest free `mpN`; validates `where` is `/mnt/<name>` (no traversal).
- **`GuestBinder` (`internal/localapi/guestbind.go`)** — the host-root steps over the fenced
`proxmox.Runner` (same pattern as the provision back-half's bind): `mkdir -p <drive>/felhom-data`
`chown 100000:100000` the namespace ROOT (not -R; per-app subdirs are chowned at deploy) → `pct set
<vmid> -mpN <drive>/felhom-data,mp=/mnt/<name>` (RW bind). The namespace is created fresh + uniformly
owned, which sidesteps the drive's pre-existing mixed-ownership data entirely.
- **Tests** — `TestGuestAttach_*`: free-slot selection (mp0 when mp9 taken), idempotency (no re-bind +
`already:true`), bad-path rejection (traversal/non-/mnt/multi-component), not-configured 503.
Pairs with felhom-controller P2C (enroll triggers attach) + the golden's `/mnt:rslave` controller bind
(P2B). Self-heal reconcile (P3) and dual-role (P4) follow.
## v0.24.0 — role-gate the eject path (system/backup mounts are unmount-protected at the agent) (2026-06-12)
Closes the eject gap in the storage-authorization redesign: `POST /disks/eject` now **refuses to