controller v0.67.0: intermediary-mount — HDD_PATH repoint + drive-absent gate + H1 routes

Drives are visible in-guest only at the STABLE /mnt/felhom-drives/<name>; the
registered path + HDD_PATH + FileBrowser source repoint there while agent calls
map back to raw /mnt/<name> (agentWhere). Enroll binds-under-parent before
register. Drive-absent GATE (planDriveGates + 30s driveGateLoop) stops/blocks
apps when a drive vanishes and auto-restarts on return; start-gate refuses start
when the drive is absent. H1 endpoints (disconnect/reconnect/restart-apps) routed
onto host-side ops. Non-hollow tests + companions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 16:45:13 +02:00
parent 2687843a83
commit 55c896624f
9 changed files with 467 additions and 17 deletions
+29
View File
@@ -535,6 +535,35 @@ func (s *Settings) RemoveStoragePath(path string) error {
return s.save()
}
// RepointStoragePath changes a registered path's Path string in place (intermediary-mount migration:
// /mnt/<name> → /mnt/felhom-drives/<name>), preserving all other fields (label, default, schedulable,
// disconnect/decommission state). No-op (nil) if oldPath isn't registered or already equals newPath.
// Errors if newPath collides with a different existing entry.
func (s *Settings) RepointStoragePath(oldPath, newPath string) error {
s.mu.Lock()
defer s.mu.Unlock()
if oldPath == newPath {
return nil
}
idx := -1
for i := range s.StoragePaths {
if s.StoragePaths[i].Path == newPath {
return fmt.Errorf("repoint target %q already registered", newPath)
}
if s.StoragePaths[i].Path == oldPath {
idx = i
}
}
if idx < 0 {
return nil // nothing to repoint
}
s.StoragePaths[idx].Path = newPath
if s.log != nil {
s.log.Printf("[INFO] [settings] Repointed storage path: %s → %s", oldPath, newPath)
}
return s.save()
}
// SetDefaultStoragePath changes which path is the default.
func (s *Settings) SetDefaultStoragePath(path string) error {
s.mu.Lock()