Join the older storage and authority audits to the SAF principal contract. Passwd entries are not isolation while one human-owned process still executes every agent, and the existing souveraine account is machined's—not Souvie's.\n\nKeep the readiness task honest: its current health fields inventory paths, but do not yet prove admission or the UID handling a live turn.
5.6 KiB
Component audit status — toward the RedFlag security bar
Live tracker. Each component page carries an Audit gaps section with the detail; this page is the rollup: which RedFlag primitive each gap maps to, and where it sits in priority. When a gap closes, move it here to "Closed" and update the component page.
The bar is read from RedFlag's source, not the doctrine summary. The five
primitives that matter, with anchors into ~/Projects/RedFlag:
| Primitive | What it is in RedFlag | Anchor |
|---|---|---|
| Capability token | Ed25519-signed, forward-only (Version), operation-scoped, expiring authorization |
agent/internal/capability/token.go |
| Closure hash | sha256 over sorted/dedup name@version#sha256 — binds token to exactly what it authorizes |
Token.ClosureHash() |
| Canonical message | Deterministic field-delimited string that is signed/verified | Token.CanonicalMessage() |
| KeyID fingerprint | hex(sha256(pubkey)[:16]) — binds a signature to a pinned key |
KeyIDFor() |
| Independent verifier | The privileged executor verifies the token itself; never trusts the relay's claim | helper/src/main.rs, token-executor mode |
| Binary integrity | SHA-256 compare (verify-binary), exit-on-mismatch |
helper/src/main.rs:2226-2283 |
| Kernel stop (defense-in-depth) | eBPF on execve, denies outside a valid token context; not the gate |
docs/tasks/KERN-001 |
| Least-privilege executor | network-less, single-op, exact-match sudoers | helper/src/main.rs |
Two things to internalize from RedFlag's own status, because they set expectations for Souveraine:
- Binary mutual attestation is deliberately unwired in RedFlag too
(SEC-022: "kill-on-mismatch and phone-home are deliberately not wired").
The standing guarantee in both systems is DAC —
root/owner-owned binaries the running user cannot overwrite. The watchdog raises the cost on top of that; it is not the gate. - The token is the universal primitive, not just for installs. RedFlag's ARCH-001 direction is "every fleet operation is a capability" — nothing runs on standing authority. Souveraine's equivalent: every authority verb (sign, unlock, handoff, release-secret, step-up) should be a capability, not a "the caller is local so it's fine."
Priority order
P0 — the unlock/handoff verb has no attestation
Component: sessiond. Gap: shell_ready / lock honored on any
same-uid caller; no token. Primitive missing: capability token +
independent verifier. Why P0: unlock-adjacent verbs are the highest-value
authority in the system; a same-uid process that reaches the socket can
induce a handoff or retake. Closes when: the shell presents a
machined-signed token (operation-scoped, short expiry, closure carrying the
shell binary hash) that sessiond verifies against the pinned machine pubkey
before honoring shell_ready. Depends on machined issuing tokens (P1).
P1 — machined signs but does not issue tokens
Component: machined. Gap: signs raw domain:payload bytes; no
operation, expiry, closure, or KeyID. Primitive missing: capability
token (full), closure hash, canonical message, KeyID. Why P1: it is the
root authority; every other attestation depends on it minting real tokens.
Closes when: machined issues forward-only, expiring, operation-scoped
tokens over a canonical message that includes the authorized target (verb +
binary hash), advertises a KeyID fingerprint, and the signing/verification
logic is byte-identical across mint and verifier (RedFlag invariant:
agent/internal/capability/token.go ↔ helper/src/main.rs).
P2 — secrets releases on D-Bus policy, not caller identity
Component: secrets. Gap: any session-bus process can GetSecrets;
no per-caller capability, no item-scoping, no SO_PEERCRED. Primitive
missing: capability token with closure = item path; independent verifier.
Why P2: the data is highest-sensitivity but the trust boundary (the
unlocked user session) is currently accepted by design; closes when personal-
tier credentials require a step-up token (§10) honored by secrets, not just
session-unlocked.
P3 — caller identity is uid 1000 for everything
Cross-cutting. Gap: SO_PEERCRED is logged (machined) or unread
(sessiond); every substrate caller is the same UID, so the audit trail
cannot distinguish Annie from a curl script. Primitive it blocks:
AgentID-equivalent — the token's "who is asking" field. Closes when:
per-agent UNIX accounts and per-agent worker processes land, making
SO_PEERCRED kernel-backed caller identity that the token binds to. Passwd
entries alone do not close it while one uid-1000 server executes every turn.
Creation, node admission, the acting-as-human health refusal, and the
operating-skill projection are owned by
../../../souveraine/saf/identity/02-agent-principal.md. This is the enabler
for P0/P1/P2, tracked separately because it is account provisioning and
process isolation, not crypto.
P4 — binary integrity watchdog (shared with RedFlag)
All components. Gap: no self/peer SHA-256 verification. Primitive
missing: verify-binary equivalent, wired. Status: deliberately
deferred, same as RedFlag SEC-022. DAC (root/owner-owned, non-overwritable)
is the standing guarantee. When the capability token lands (P1), the token's
closure should carry each component's expected hash so a swapped binary
cannot replay a valid old token — that is the point at which the watchdog
becomes load-bearing rather than ornamental.
Closed
(none yet — component family documented 2026-07-16, all gaps open.)