175 -> 99 effective lines. New .claude/rules/{proxmox,localapi,backup,storage}.md alongside the
existing health-checks.md. The release section points at the felhom-build-deploy skill rather than
restating a table that drifts from the script; the layout section's per-package annotations moved
into the rule file for their area instead of being deleted.
Kept in the core because it is the only part re-injected after /compact: the root-CLI fence and its
three exceptions, the destructive-op gate, prove-ownership (audit A1), the gate entry point, the F9
live-validation fence, and the checklist.
health-checks.md overlaps localapi.md and storage.md on three globs -- deliberate, both load,
stated in each file. Go build/vet/test green and unchanged.
2.1 KiB
paths
| paths | |||
|---|---|---|---|
|
Local API, authz and guest hooks — the per-guest blast radius
internal/localapi/ is the narrow per-guest local API: token store, disks/format, guest binds,
controller swap, stale-lock recovery, pinned self-signed leaf. internal/authz/ is the operator
signed-op verifier (SSHSIG) plus the durable nonce store. internal/guesthook/ installs the
pre-start self-heal hookscript.
Overlap note:
health-checks.mdalso matchesinternal/localapi/**andinternal/guesthook/**. That is deliberate — both rules apply there and both load. Neither supersedes the other.
Scoping is the whole security property
This API is reachable from inside a customer guest. Every route must be scoped to the guest that called it — a route that can name another guest's id has escaped its blast radius. Fail safe to protected: an unrecognised or unresolvable caller gets less access, never more.
Replay protection must survive a restart
authz.MemoryNonceStore on a real host is a defect — replay protection dies on restart. Use
authz.FileNonceStore. The memory store exists for tests.
The token is a hash on disk, plaintext only at mint
The store keeps hashes. The plaintext token exists in exactly one place, bootstrap.json on the
PVE host — so a "read the token" step means reading that file, and a lost token is re-minted, never
recovered.
Binds can brick guest boot
| Do not | Because | Use |
|---|---|---|
GuestBinder.AttachBind/DetachBind (per-drive pct set -mpN) |
legacy model; a missing bind source can brick guest boot (C1) | AttachDrive/DetachDrive (intermediary model) |
isHostMountpoint to reconcile bind state |
a boolean cannot converge stacked double-binds (the /mnt doubling bug) |
countHostMounts normalization inside AttachDrive |