Live-probed on felhom-pve under the PRODUCTION scoped token vs root: enumeration IS pool-filtered (T1: token sees [9201] of 4 guests); pool read 403s naming Pool.Audit (T2); Pool.Audit@/pool/felhom alone suffices (T3, throwaway identity, torn down); /cluster/resources withholds the pool field without Pool.Audit (T7); local ownership records all partial (T5). Recommendation for the A1 impl spec (now unblocked): Pool.Audit added to FelhomAgentGuest + GET /pools/felhom cross-check in staleLockController, fail-safe skip on read failure. Appendix: committed-secrets rotation micro-runbook (operator follow-up). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
3.2 KiB
felhom.eu — task reports
Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.
SPIKE — A1 pool-membership read for the stale-lock reaper (2026-07-03)
Class: SPIKE (docs-only; no production code, no felhom-agent commit, no live ACL/agent change).
Deliverable: documentation/audits/SPIKE-a1-pool-membership-read-2026-07-03.md.
Empirically answered the three open A1 mechanism questions on live felhom-pve, probing under the
production scoped token felhom-agent@pve!agent (secret read on-host, length-only recorded)
vs root as oracle:
- T1 (crux):
GET /nodes/demo-felhom/lxcunder the scoped token returns [9201] only; root sees [9001, 9100, 9201, 9999]. LXC enumeration IS pool-filtered — the reaper's scan is already ownership-scoped as deployed, so A1 is latent, re-armed only by a broad-token redeploy. - T2:
GET /pools/felhomunder the token → 403 "Permission check failed (/pool/felhom, Pool.Audit)".GET /pools→ 200[](silently filtered, not an error). - T3: throwaway
felhom-probe@pve!probewith ONLYPool.Audit@/pool/felhom→ 200 with members — minimal priv delta proven. Bonus (T3b): a token with no VM.Audit gets 200 + empty list from the LXC index (mis-scope is silent, not an error). Full teardown verified (0 residue). - T4: root
pvesh get /pools/felhomworks but would be a 4thproxmox.Privilegedfence exception — rejected. - T5: local ownership records (guest-binds.json, reconcile journal, guests/ dir, installer state.json) are all partial — journal's newest vmid (9310) no longer exists; adopted or drive-less guests are absent — rejected as reaper gate.
- T6: live foreign-guest reap deliberately NOT run (needs broad-token redeploy); deferred to
the named unit test. T7 (extra):
/cluster/resourceswithholds thepoolfield withoutPool.Audit— no zero-ACL-change API path exists.
Recommendation (for the now-unblocked A1 impl spec): add Pool.Audit to PVE_PRIVS_GUEST
(scripts/felhom-host-install.sh L183, granted at /pool/felhom) + intersect ListLXC with
GET /pools/felhom members inside staleLockController.Guests(); a pool-read failure propagates
to the existing "guest list unavailable — skipping recovery" fail-safe. Ship agent + --rescope-acl
together; optionally surface pool-read in the capability probe. Named tests:
TestStaleLock_ForeignGuestNotReaped, TestStaleLock_PoolGuestStillReaped,
TestStaleLock_PoolReadFails_SkipsAll.
Appendix folded in: committed-secrets rotation micro-runbook for the 3 live stringData blocks
in manifests/felhom.secret.yaml (healthchecks-config / umami-config / gitea-creds) — rotate
upstream first, out-of-band kubectl create secret, then de-git; operator follow-up, no execution.
Cleanup: probe user/token/role removed and verified absent; no throwaway guest needed (three real non-pool guests existed); production roles/token/agent untouched; secrets never persisted.