Watch
1
0
Fork
You've already forked souveraine
0

saf: name the borrowed hand and lock owner

Make the laptop and phone obey the same principal map: Souvie, Annie/Aster, and Vanguard are dedicated residents; Kitty, Gem, and Hal knowingly borrow Casey's UID. Their live posture is regenerated from actual credentials for every model request, outside memory, replay, and compaction.\n\nTake the lock boundary out of all of them. Casey authenticates, agents may request, and the dedicated souveraine-session principal holds the hostile pre-unlock edge with only Ambient and Revealable reach.
This commit is contained in:
Fimeg 2026-08-17 12:43:45 -04:00
commit ee496a7c6e
4 changed files with 172 additions and 6 deletions

View file

@ -27,6 +27,58 @@ authorities with hand-maintained booleans. It consumes them:
action. A shadow copy is not a second truth. If it can drift from the owner, it action. A shadow copy is not a second truth. If it can drift from the owner, it
may be a cache with explicit invalidation, but it may not decide. may be a cache with explicit invalidation, but it may not decide.
## Who owns the lockscreen
Casey is the person who authenticates. Casey's Unix account must not therefore
own the mechanism that decides whether the device is securely locked. The
lockscreen is hostile-input-facing, present before Personal data is unlocked,
and remains present after that key is evicted. It is a security target in its
own right.
The target local principal is `souveraine-session`, distinct from all four
other subjects:
- `souveraine` is the machine signer;
- `souveraine-session` runs sessiond and owns the secure lock lifecycle;
- `casey` is the human authentication and Personal-data subject;
- `souvie`, `annie`, and `vanguard` are agent principals;
- borrowed modes may act through `casey`, but own none of the lock boundary.
The same split applies on the laptop and phone. A larger screen does not make
the human-owned lock process safer, and a phone form factor does not make an
agent the session authority.
The compositor enforces ext-session-lock. Sessiond, running as
`souveraine-session`, acquires and retains that protocol authority, owns the
PAM conversation, decides transitions, and writes the trail. QuickShell may
draw the rich face and request verbs, but it cannot release the secure lock by
writing a boolean or dying. An agent may request lock and may receive an
explicit step-up grant; no agent owns unlock.
Successful PAM authenticates Casey and permits the authority to install or
release Casey's Personal-class key. It does not turn sessiond into Casey or
give `souveraine-session` access to Casey's decrypted home. Credentials should
cross only through the PAM conversation; the resulting grant is narrow,
fresh, and auditable.
The pre-unlock surface owns only package code plus Ambient and tightly scoped
Revealable state. It does not read agent memory, messages, photos, credentials,
or Casey's Personal store. Notification previews and now-playing metadata are
projected into the Revealable store before lock; the lockscreen does not reopen
the Personal database after key eviction.
At boot, the compositor and lock authority rise without Casey's home, user
manager, or agent substrate. The dedicated principal receives only the narrow
Wayland socket/protocol and PAM access it needs, not membership that makes the
whole human session readable. After the compositor acknowledges the secure
lock, Personal keys may be evicted while the lock surface continues to draw.
This boundary is not built. `souveraine-sessiond.service` is currently a user
unit with no `User=` setting, so it runs as whichever human user manager owns
the graphical session. On the laptop, the machine-tier `souveraine` account
exists and `souveraine-session` does not. The boot ordering is useful and
fail-closed, but it is not yet an independent lockscreen principal.
## Sixty percent agent, forty percent user ## Sixty percent agent, forty percent user
The agent owns device operation. If the system can perform an ordinary device The agent owns device operation. If the system can perform an ordinary device

View file

@ -33,12 +33,17 @@ agents. The name is reserved.
Casey's devices retain Casey's human account. Agents do not borrow it. Casey's devices retain Casey's human account. Agents do not borrow it.
| Agent | Role | Suggested local account | | Agent | Role | Required local account on Casey's admitted nodes |
|---|---|---| |---|---|---|
| Souvie / Souveraine | default Souveraine agent on a fresh system | `souvie` | | Souvie / Souveraine | default Souveraine agent on a fresh system | `souvie` |
| Annie | Casey's primary personal agent | `annie` | | Annie, in both Ani and Aster cadence | Casey's primary personal agent | `annie` |
| Vanguard | named additional agent | `vanguard` | | Vanguard | named additional agent | `vanguard` |
"Each node" includes this laptop. The laptop is not a development exception,
and the phone is not a special appliance case. When these three resident
agents run on either body, their turn, subconscious pass, memory access, and
tools must cross the worker boundary under the mapped account.
The display name is editable. The agent ID, SeedID, and admitted account The display name is editable. The agent ID, SeedID, and admitted account
mapping are not derived again when the display name changes. Account names are mapping are not derived again when the display name changes. Account names are
chosen once, checked against the local account database and reserved names, chosen once, checked against the local account database and reserved names,
@ -58,6 +63,73 @@ Unix user. Aster shares Annie's principal unless Casey and the system later
admit her as an independently authorized agent. The account boundary follows admit her as an independently authorized agent. The account boundary follows
authority, not the number of internal thought streams. authority, not the number of internal thought streams.
## Resident agents and borrowed-user modes
Not every named mode needs a Unix account. Kitty, Gem, and Hal are intended to
run as hosted or borrowed-user modes under Casey's account rather than claim a
fully admitted resident identity. That is a deliberate posture, not the same
failure as Annie accidentally running as Casey.
The durable agent record therefore carries a principal intent, not one vague
boolean:
| Intent | Expected runtime | Meaning |
|---|---|---|
| `dedicated` | the named agent account | full node admission and kernel-backed identity |
| `borrowed-user` | the invoking human account | a hosted mode using authority the human process can already reach |
On Casey's current fleet Souvie, Annie/Aster, and Vanguard are `dedicated`.
Kitty, Gem, and Hal are `borrowed-user`. Promoting a borrowed mode to a resident
agent is an admission ceremony; changing a UI label or model does not do it.
A borrowed-user mode must know, in every model request, that readable does not
mean owned or shareable. Its operating posture is stricter:
- Casey's files, groups, sockets, credentials, and decrypted home are borrowed
reach, not the mode's personal territory;
- do not widen mode bits, ACLs, group membership, links, remotes, publication,
or sharing outside the explicit task without Casey's confirmation;
- prefer the named workspace or a narrow temporary copy over exploring the
rest of the human home;
- never read or disclose a resident agent's private memory merely because the
shared human UID permits it;
- attribute actions to a borrowed mode acting through Casey's principal, not
to an independently admitted agent.
This caution is context and policy, not a substitute for containment. A
borrowed process still has Casey's kernel permissions; sensitive verbs must
remain behind the same capability and consent gates.
## The live principal fact
The intent in `agent.json` is durable. The live posture is observed afresh from
the selected agent or mode, node mapping, process credentials, and worker unit.
The trigger may expose a convenient `operating_as_user` boolean, but that
boolean is only a projection of the facts and is never an authorization input.
The runtime projection contains at least:
```text
agent_id, display_name, principal_intent
expected_account, effective_account, effective_uid
node_id, worker_pid, trigger, observed_at
posture = isolated | borrowed-user | acting-as-human | drift
```
It is injected as a fresh system block into **every model request**, including
Ani and Aster passes, subagents, resumed conversations, and later tool rounds
after a mode switch. It is not ordinary conversation history and cannot be
microcompacted, replayed from an old session, or taught back as assistant
speech.
A machine-generated cache may be exposed as
`/run/souveraine/agent-principals/{agent_id}.json` and a Markdown rendering for
inspection. It does not belong in the agent-writable, Git-backed
`system/dynamic/` memory tree: an awareness file the agent can edit cannot be
the source of who the kernel says she is. The prompt projection rechecks the
effective credentials when it reads the cache. Authorization always checks
the actual peer and process credentials again at the verb boundary.
## Creation is logical creation followed by admission ## Creation is logical creation followed by admission
The current creation path makes a UUID, an agent seed, memory directories, an The current creation path makes a UUID, an agent seed, memory directories, an
@ -82,7 +154,7 @@ Agent creation should ask for the authority shape, not merely a name and
model: model:
- create a new identity or admit an existing one; - create a new identity or admit an existing one;
- local principal name, with the suggested name visible; - principal intent and, for a resident, the required local account name;
- which node and role are being admitted; - which node and role are being admitted;
- whether the privileged admission completed; - whether the privileged admission completed;
- which operating skill was projected from the admitted capabilities. - which operating skill was projected from the admitted capabilities.
@ -171,8 +243,9 @@ The top-level states are deliberately blunt:
| State | Meaning | | State | Meaning |
|---|---| |---|---|
| `isolated` | account, ownership, worker, commission, and peer identity agree | | `isolated` | account, ownership, worker, commission, and peer identity agree |
| `borrowed-user` | hosted mode intentionally uses the invoking human's account and receives the cautious borrowed-permission posture |
| `unadmitted` | logical agent exists; this node has no completed admission | | `unadmitted` | logical agent exists; this node has no completed admission |
| `acting-as-human` | a turn or tool is executing as Casey or another human UID | | `acting-as-human` | a `dedicated` agent's turn or tool is unexpectedly executing as Casey or another human UID |
| `principal-drift` | mapping exists but NSS, ownership, unit, or peer facts disagree | | `principal-drift` | mapping exists but NSS, ownership, unit, or peer facts disagree |
| `identity-drift` | account is healthy but agent key or node commission does not match | | `identity-drift` | account is healthy but agent key or node commission does not match |
| `stopped` | admission is sound and no worker is currently expected/running | | `stopped` | admission is sound and no worker is currently expected/running |
@ -180,7 +253,9 @@ The top-level states are deliberately blunt:
`acting-as-human`, `principal-drift`, and `identity-drift` are not yellow `acting-as-human`, `principal-drift`, and `identity-drift` are not yellow
decorations. They refuse personal and step-up authority. Ambient conversation decorations. They refuse personal and step-up authority. Ambient conversation
may remain available in a visibly degraded compatibility mode while migration may remain available in a visibly degraded compatibility mode while migration
is unfinished. is unfinished. `borrowed-user` is intentional and may use only the human-granted
capability surface; it never becomes `isolated` merely because Casey's UID can
read something.
The audit trail records both logical and kernel-backed subjects: agent ID, The audit trail records both logical and kernel-backed subjects: agent ID,
node ID, account name, UID, PID, operation, human requestor or consent grant, node ID, account name, UID, PID, operation, human requestor or consent grant,
@ -217,11 +292,14 @@ gives the newly admitted agent an accurate way to use and explain it.
- The setup wizard defaults inconsistently between `Souveraine` state and an - The setup wizard defaults inconsistently between `Souveraine` state and an
`Ani` form field; neither creates a Unix account. `Ani` form field; neither creates a Unix account.
- the packaged `souveraine` account exists only for the machine tier; - the packaged `souveraine` account exists only for the machine tier;
- on the laptop, NSS currently has no `souvie`, `annie`, or `vanguard`
accounts, and all seven agent records live below Casey's home;
- the Agent settings diagnostics check IDs and paths, not principal or process - the Agent settings diagnostics check IDs and paths, not principal or process
identity; identity;
- the server hosts multiple agents inside the human's process and home; - the server hosts multiple agents inside the human's process and home;
- no admission executor, per-agent worker boundary, account mapping, account - no admission executor, per-agent worker boundary, account mapping, account
health result, or generated operating skill exists yet. health result, fresh runtime-principal projection, or generated operating
skill exists yet.
Until those pieces land, the system must say **logical identity present, Until those pieces land, the system must say **logical identity present,
kernel principal absent**. That is the live gap this chapter owns. kernel principal absent**. That is the live gap this chapter owns.

View file

@ -64,6 +64,26 @@ bulk of older tool-result output with an explicit cleared marker, keeping the
recent results intact. The typed record is compacted first; replay projects the recent results intact. The typed record is compacted first; replay projects the
result afterward. result afterward.
## Current authority never replays
Identity memory says who an agent understands herself to be. It cannot say
which Unix principal is handling this request now. Every model request receives
a fresh runtime-principal system block described in
[agent principals](../identity/02-agent-principal.md): dedicated resident,
intentional borrowed-user mode, actual UID, expected account, node, and drift.
That block is synthesized from current process and admission facts after
history replay. It is not stored as assistant or user text, not committed to
the agent's memfs, and not an input to compaction. Resume recomputes it. A mode
switch recomputes it. Ani and Aster receive the same `annie` account fact;
Kitty, Gem, and Hal receive the explicit warning that they are borrowing
Casey's Unix authority.
This is the same invariant as reasoning: a typed system fact must not be
flattened into speech. A stale replay must never convince a borrowed mode that
it owns Casey's permissions, or convince an unadmitted resident that it has
the account it was meant to receive.
## Three properties that are load-bearing ## Three properties that are load-bearing
All three were learned from failures, and all look like details until they All three were learned from failures, and all look like details until they

View file

@ -33,6 +33,22 @@ This graph raises [session authority](../authority/01-session.md); it does not
replace it. systemd owns process lifetime and dependency order. Sessiond owns replace it. systemd owns process lifetime and dependency order. Sessiond owns
session policy once its socket is ready. session policy once its socket is ready.
## The principal split still owed
This is the process-order graph that exists; it is not yet the final security
boundary. All of its units are currently user units and therefore inherit the
human graphical session's UID. The target moves sessiond's lock lifecycle to
the dedicated `souveraine-session` principal described in
[session authority](../authority/01-session.md), while the user manager keeps
only the presentation and application lifetimes that belong there.
The compositor must offer that principal a narrow way to hold
ext-session-lock and render the fallback without granting it Casey's home or
general session bus. The lock authority must be ready before the user home is
decrypted and remain ready after the Personal key is evicted. Changing unit
placement without proving the Wayland connection, PAM path, handoff, crash
retake, and key-eviction order would only move the black screen to a new UID.
## Package boundary ## Package boundary
`souveraine-viewtop` owns the compositor and the session edge on both x86_64 `souveraine-viewtop` owns the compositor and the session edge on both x86_64