Files
felhom-agent/.claude/rules/localapi.md
T
admin aa74294a7d
gates / gates (push) Successful in 8s
docs: felhom-agent CLAUDE.md becomes a core plus path-scoped rules (R-229 leg b)
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.
2026-08-06 11:28:27 +02:00

2.1 KiB

paths
paths
internal/localapi/**
internal/authz/**
internal/guesthook/**

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.md also matches internal/localapi/** and internal/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