Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.4 KiB
REPORT — slice 8C (controller half): de-privileging + disk management via the agent (v0.37.0) (2026-06-10)
Overwrite-latest report. Cumulative history: CHANGELOG.md. Implements the in-guest controller half of
TASK — Slice 8C(closes slice 8). Pairs withfelhom-agentv0.12.0.
Outcome
The disk-execution subsystem moved to the host agent. The in-guest controller is now Docker-only with no disk/Proxmox privileges and drives disk management through the agent's local API. ~12.3k LOC retired. The controller-side re-platform milestone — slice 8 CLOSED.
What landed
- Disk management via the agent (
internal/web/agent_disk_handlers.go,ServeDiskAPI): thin proxiesGET /api/disks/POST /api/disks/{assign,eject,format}over the slice-8Aagentapiclient (leaf-pinned, own token). Execution is the agent's; the UX stays here. A data-bearing format refusal (agentapi.ErrFormatRefused) surfaces as HTTP 409 "operator authorization required" — the agent inspects the device; the controller's claim is irrelevant. internal/agentapi:Disks/AssignDisk/EjectDisk/FormatDisk+ErrFormatRefused.
Retired (→ agent / obsolete)
internal/storage/(whole package: scan/format/attach/migrate/safety, DriveMigrator).internal/backup/: restic, crossdrive, restore_drives, disk_layout, local_infra, restore_scan, drive-restore, restic paths.backup.Managersurgically split to app-data only (DB dumps + Docker-volume tars + per-app restore kept; restic/cross-drive/snapshot-history/integrity dropped;RestoreAppnow restores from on-disk volume-tar dumps — snapshot restore is the agent's domain).report/infra_backup*+infra_pull(kept the setup fresh-install config download),setup/scanner+ the wizard's drive-recovery flows,monitor/watchdog+pinger(watchdog → agent; Healthchecks pinging → the Hub owns monitoring),web/storage_handlers+handler_restore. Wiring dropped from main/router/web (CrossDriveRunner, DriveMigrator, watchdog, infra push, restic scheduler jobs; kept the db-dump job).
De-privileged
scripts/docker-setup.sh controller compose: dropped privileged: true, /mnt rshared, /sys,
/dev, /etc/fstab, /run/udev. The golden's bootstrap docker run was already minimal (8A).
Tests / build
go build ./... + go test ./... green (app-data backup / stacks / quiesce / bootstrap / agentapi /
disk-client tests pass). The data-bearing-format refusal is proven in agentapi tests.
Live validation (demo-felhom)
A provisioned controller v0.37.0 from the refreshed golden: Privileged=false, container mounts
ONLY bootstrap + data + docker.sock (no /dev//etc/fstab//sys//mnt), healthy + configured
(not setup). It drove the agent disk API: GET /disks (data-bearing flags) and a data-bearing
format → refused (the agent inspected the device, the gate returned pending_signature, nothing
formatted). The de-privileged controller runs app management normally (8A bootstrap / 8B quiesce
unaffected).
Deferred / note
The operator-signed completion of a data-bearing wipe → slice 10. RestoreApp restore semantics
changed (volume-tar dumps, not restic) — restic/snapshot restore is the agent's domain now. Unused
config.Backup restic/retention fields left in place (harmless; out of scope). No secrets committed.