Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.1 KiB
REPORT — restore guests INTO the felhom pool (pool-scoped-ACL enabler, agent v0.53.0)
Date: 2026-07-01 · Repo: felhom-agent · Class: Risky/supervised (agent code normal; the
live token re-scope was the supervised step — executed + validated on felhom-pve).
Colleague-safety batch #4 phase b (agent half). Makes every restore allocate the guest INTO the felhom
pool so the agent token can be scoped to /pool/felhom + /storage/<targets> (blast-radius containment
on a shared host). Grounded by felhom.eu/documentation/audits/SPIKE-pool-scoped-acl-2026-07-01.md (PASS).
1. Baseline → target
felhom-agent 0573ec9 (v0.52.0) → v0.53.0. No engine/ACL logic beyond the restore param.
2. Files changed + commit
internal/proxmox/mutate.go—RestoreLXCOptions.Pool+RestoreLXCsendspool=when non-empty.internal/reconcile/bringup.go—const DefaultPool = "felhom";BringUpSpec.Pool; bring-up restore passesPool: spec.Pool.internal/reconcile/restoretest.go— scratch restore passesPool: DefaultPool(residual #2).cmd/felhom-agent/main.go— bothBringUpSpecliterals (bring-up/DR + provision) setDefaultPool.- Tests:
internal/proxmox/restore_test.go(TestRestoreLXC_PoolParam),internal/reconcile/bringup_test.go(TestRestoreSitesUsePool).CHANGELOG.md,README.md. - Commit
7639ab5onmain(parent33e3443).
3. Green gate
go build ./..., go vet ./..., go test ./... — clean (local + build server 180).
4. Tests + red-proofs (§10)
TestRestoreLXC_PoolParamPASS:Pool:"felhom"→pool=felhomin the POST body;Pool:""→ key absent. Red-proof: unconditionalv.Set("pool",…)→ the empty case sentpool=→ omit assertion FAILED as designed; reverted.TestRestoreSitesUsePoolPASS: the provision bring-up threadsspec.Pooland the restore-test hardcodesDefaultPool→ both capturedRestoreLXCOptions.Pool == "felhom". Red-proof: removedPoolfrom both sites → the provision assertion FAILED; reverted.
5. Published + hub manifest
- Gitea generic package
admin/generic/felhom-agent/0.53.0/felhom-agent, sha2569d1ef8298dcc5090936afa1b88f1612c0b5f03a62548ebbe0989d34d6622aa61(publish did delete-then-PUT + round-trip GET verify). - Hub artifact manifest — REQUIRED operator follow-up (mandatory for fresh installs): the served
manifest still advertises agent 0.52.0. A FRESH install now runs script v1.6.0 (scoped ACL +
Pool.Allocate), which is only correct with agent ≥ v0.53.0 (restore--pool); with 0.52.0 the guest restores OUTSIDE the pool and the scoped token then 403s on it. An operator must set the artifact manifest to agent 0.53.0 / sha9d1ef8298dcc5090936afa1b88f1612c0b5f03a62548ebbe0989d34d6622aa61in the hub UI (now a dropdown, auto-sha — hub v0.29.0) before any fresh v1.6.0 install. The demo swap did NOT depend on this (binary deployed directly).
6. Supervised swap on felhom-pve — executed + validated (all gates PASS)
Sequence: systemctl stop felhom-agent → felhom-host-install.sh --rescope-acl --vmid 9201 (added the
3 scoped roles+grants incl. /storage/felhom-pbs; removed the old broad FelhomAgent / grant + role)
→ deploy felhom-agent 0.53.0 (backup .bak-0.52.0) → systemctl start. Validation, all under the
scoped token:
| Gate | Result |
|---|---|
| A selftest=read | ✅ OK — now sees only the pool guest (9201) + the 3 scoped storages (was 5+all guests) |
| B provision-into-pool | ✅ --selftest=bring-up -mode provision -vmid 9300 → boot+running, 9300 landed in pool (restore-into-pool + SetConfig + start all scoped) |
| C PBS under scope (residual #1) | ✅ vzdump 9300 → felhom-pbs (200, task OK) + restore-from-PBS → 9301 pool=felhom (200, OK, landed in pool); cleanup 200 |
| D restore-test into pool (residual #2) | ✅ scratch 990000 restored into pool, boot+running, torn down, pass=true |
| E blast-radius | ✅ non-pool guests 9001/9100 → 403 (VM.Audit/VM.PowerMgmt); ungranted felhom-usb → 403 |
| F 9201 health | ✅ running; controller container Up (healthy) — agent↔guest channel intact; --selftest=hub OK; journal clean; pool = [9201] |
Cleanup: scratch 9300/9301/990000 destroyed, PBS + local scratch snapshots freed, .bak-0.52.0 rollback
binary retained. The live felhom pool holds only 9201.
7. NOT yet live-validated — awaiting supervised run
- The colleague's-box migration (single-node, so no cluster nuance) — a later supervised repeat of the §6 stop→rescope→deploy→start + gates, once the hub manifest serves 0.53.0.
8. Observations
- Storage blast-radius is a bonus: the scoped token also 403s on ungranted storages (felhom-usb) — read containment beyond guests.
- The agent's
ListLXC/ListStoragenow return filtered lists (pool guests / scoped storages) — the host-report naturally scopes to Felhom's own footprint. Correct + intended. - felhom-pbs is the offsite backup target; the
Storegrant on/storage/felhom-pbsis mandatory (was the SPIKE's main unvalidated residual — now proven live).