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
+11 -4
View File
@@ -81,6 +81,9 @@ type Options struct {
Disks DiskOps
DiskGate StorageGate
Guests2 GuestLister
// GuestAttach binds an enrolled user-data drive's felhom-data namespace into the guest (slice 10
// P2, Model A). OPTIONAL — when nil, POST /disks/guest-attach reports "not configured".
GuestAttach GuestAttacher
// HostReader is the root-free host topology reader used to classify a device/mount's protection
// ROLE (it backs SystemDisks for the eject role-gate + the /disks role hints). OPTIONAL — when nil
// it defaults to the production *storage.ProcHostReader. Injectable so the role-gate is testable.
@@ -132,10 +135,11 @@ type Server struct {
logger *slog.Logger
now func() time.Time
disks DiskOps // slice 8C (optional)
diskGate StorageGate // slice 8C (optional)
guestList GuestLister // slice 8C (optional)
host storage.HostReader // role classification source (optional; defaults to ProcHostReader)
disks DiskOps // slice 8C (optional)
diskGate StorageGate // slice 8C (optional)
guestList GuestLister // slice 8C (optional)
guestAttach GuestAttacher // slice 10 P2 (optional)
host storage.HostReader // role classification source (optional; defaults to ProcHostReader)
hostMetrics HostMetricsProvider // slice 9 (optional)
hostID string // slice 10B: for the data-bearing-format pending-op hint
@@ -175,6 +179,7 @@ func NewServer(o Options) (*Server, error) {
disks: o.Disks,
diskGate: o.DiskGate,
guestList: o.Guests2,
guestAttach: o.GuestAttach,
host: o.HostReader,
hostMetrics: o.HostMetrics,
hostID: o.HostID,
@@ -200,6 +205,8 @@ func (s *Server) Handler() http.Handler {
mux.HandleFunc("POST /disks/assign", s.withGuest(s.handleDiskAssign))
mux.HandleFunc("POST /disks/eject", s.withGuest(s.handleDiskEject))
mux.HandleFunc("POST /disks/format", s.withGuest(s.handleDiskFormat))
// Guest data-drive passthrough (slice 10 P2): bind an enrolled drive's felhom-data namespace in.
mux.HandleFunc("POST /disks/guest-attach", s.withGuest(s.handleDiskGuestAttach))
return mux
}