5e3dfcb714
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
47 lines
3.2 KiB
Markdown
47 lines
3.2 KiB
Markdown
# 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](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](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/lxc` under 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/felhom` under the token → **403 "Permission check failed (/pool/felhom,
|
|
Pool.Audit)"**. `GET /pools` → 200 `[]` (silently filtered, not an error).
|
|
- **T3:** throwaway `felhom-probe@pve!probe` with ONLY `Pool.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/felhom` works but would be a 4th `proxmox.Privileged` fence
|
|
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/resources` withholds the `pool` field without
|
|
`Pool.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.
|