Design 58 and 36: role names for the machines and no operator logins, as a public repository needs (fixes what #394 wrote)
mesh/merge-gate head cc0503ef663a merged into trunk 85f0aecf5ad6 — pass: the change touches no module of the mesh's graph
mesh/repo-check head cc0503ef663a merged into trunk 85f0aecf5ad6 — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

This commit is contained in:
2026-10-17 10:13:02 +00:00
parent 56d8d546c7
commit cc0503ef66
2 changed files with 28 additions and 28 deletions
@@ -312,15 +312,15 @@ operator's word — and, for the operator's own home, only at the terminal or on
Everywhere above, "the operator's home" and "the operator account" mean **the account the agent runs as**:
the machine account of the identity the module runs for (ADR 0412). claude-code declares that it can run for
an agent identity, in its assignment or when a session is started: started for `nox` it runs with the agent's
home; started for `jochen`, the operator, it is the default run, with the operator's configuration. On a
home; started for the operator, it is the default run, with the operator's configuration. On a
machine where no agent is marked as the agent account, its assignment is the default run, as every module's is.
**The fact.** The machine accounts come from the identity seat (ADR 0411); the operator no longer states the
agent account at the controller's terminal. A machine's agent account is the machine account of the agent the
identity seat marks as the agent account there, on the operator's Approve: `nox` on novox. There this module's
identity seat marks as the agent account there, on the operator's Approve: `nox` on the control node. There this module's
assignment is run for that agent, and the controller refuses one that is not. The controller resolves the
machine facts `agent-account`, `agent-home` and `agent-root` from it, and gives the tool runner the account and
its home. Where no agent is marked (ace, g14 and shanks), the facts name the operator account and `agent-root`
its home. Where no agent is marked (every other machine today), the facts name the operator account and `agent-root`
is empty, so nothing changes there, though a login `nox` exists for the modules run for it.
**What the module declares.**
@@ -115,11 +115,11 @@ machine calls as the operator's person identity or as an agent, never through th
### 5.1 An identity on the machines (ADR 0411, ADR 0414)
A person or agent identity also holds a **login name**, the **machines** it is present on and, for a person, the
login name kept on a machine where it differs. The seat starts with two: `jochen`, the operator, and `nox`, the one
login name kept on a machine where it differs. The seat starts with two: the operator's person identity and `nox`, the one
agent; every piece of agent work is a thread of `nox` (§2), and a second agent identity is made only when a rule needs
another role. The agent is `nox` everywhere: its login, its forge account (the forge account `nox-agent` renamed,
keys and team kept), Keycloak, mail and the bus. The operator is `jochen` where the operator has no account yet;
the logins `jochens`, `jochen` and `ace` and the forge account `jschoubben` are kept as they are. On a machine where agents ran as the
keys and team kept), Keycloak, mail and the bus. A login or service account the mesh makes for the operator from now on carries the operator's identity name;
the operator's existing logins and forge account are kept as they are. On a machine where agents ran as the
operator's login, that login stays the operator's and `nox` gets a login of its own; nox's bus account is `agent.nox`. `nox` is also the
operator's terminal command (`mesh-cli`), and prose says which is meant.
@@ -132,22 +132,22 @@ person or an agent: claude-code's `agent-account` resource goes, and the catalog
declares one. The node record's operator account and agent account are read from the identities, no longer stated
at the controller's terminal or in the mesh-config snapshot; the machine facts `account`, `agent-account` and their
homes keep their names. A machine names an agent account only where the identity seat marks an agent as its agent
account: novox, marked `nox`, where the guard and the licence stay as they are. ace, g14 and shanks are marked with
none, so the guard stays off there and the operator's sessions keep the mesh's tools, while the login `nox` serves the
account: the control node, marked `nox`, where the guard and the licence stay as they are. The other machines are
marked with none, so the guard stays off there and the operator's sessions keep the mesh's tools, while the login `nox` serves the
modules run for `nox`. Where a person or an agent is present, its kept logins and the agent account mark change only
through a verb of the identity seat that only the operator calls, on an Approve; an assignment never sets the mark,
because an agent may call the verb that changes an assignment (ADR 0266 §4). The verb, and the controller at composition,
refuse an agent whose login on a machine would be `root`, a person's login there or a well-known service account
(ADR 0266 §5). The self-check judges every agent login,
marked or not. The seed: `jochen` on all four, kept logins `ace` on ace and `jochens` on novox (`jochen` on g14 and
shanks is the identity's own name); `nox` on all four, the agent account on novox.
marked or not. The seed: the operator on every machine, with the operator's existing login kept where it differs from the
identity's name; `nox` on every machine, the agent account on the control node.
```
identity seat controller each machine (node-engine)
───────────── ────────── ──────────────────────────
jochen person, its machines, composes, per machine: the operator's login (adopted)
the login kept on each the machine accounts present nox, root: never (adopted on novox,
nox agent, its machines the facts account, agent-account made elsewhere)
person operator, machines, composes, per machine: the operator's login (adopted)
the login kept on each the machine accounts present nox, root: never (adopted on the control node,
agent nox, its machines the facts account, agent-account made elsewhere)
each identity's bus password ──► its secret, owned by its login, 0600
```
@@ -156,29 +156,29 @@ shanks is the identity's own name); `nox` on all four, the agent account on novo
Every module runs as the operator account of its machine, as today, with no setting; running for the operator is that
default run. A manifest may declare that its module can **run for** an agent identity, at assignment, at start or both: serve one identity with that identity's machine account, home and bus password.
An assignment of such a module may name the identity it runs for, and the module may let the one who starts it
choose: claude-code started for `jochen` is the default run with the operator's configuration, and started for `nox`
choose: claude-code started for the operator is the default run with the operator's configuration, and started for `nox`
it runs for `nox` with the agent's home. A start
goes down only: a module is started for an identity by a process already running as that identity's login, or by the
operator's own login for an agent; an agent never starts one for a person, and the module refuses it, naming who asked
and for whom. A module may be assigned to one machine once per identity it runs for there, each its own process under
its own login, and the controller keys an assignment by machine, module and identity. The first two to declare it are
claude-code and ssh-client. On a machine the identity seat marks with an agent account, claude-code's assignment is
run for that agent (`nox` on novox), so its licence and home scope stay in the agent's home, and the controller refuses
run for that agent (`nox` on the control node), so its licence and home scope stay in the agent's home, and the controller refuses
one there that is not. ssh-client keeps its default assignment for
the operator wherever `nox` is present and gains a second one run for `nox`, which makes the agent's forge key in the
agent's home and closes issue 989; gitea's provider registers that key on the forge account `nox`. A module run for an identity calls as that
identity and gets no module identity of its own (this narrows ADR 0386 §4, which holds for every other assignment). A module with an account of its
own (`runs-as`, ADR 0259 §8) cannot declare it, and a run for an identity with no machine account on that machine is
refused at composition and at start. ADR 0266's guard
stands: on novox, a session started for the operator gets the operator's configuration and its tool calls are still
stands: on the control node, a session started for the operator gets the operator's configuration and its tool calls are still
refused.
### 5.3 A bus password per identity (ADR 0413)
Each person and agent identity has a bus account of its own (`person.jochen`, `agent.nox`), whose memberships are made
Each person and agent identity has a bus account of its own (`person.<name>` for the operator, `agent.nox`), whose memberships are made
from its role, and its password is a secret owned by its machine account at mode 0600 on each machine it is present
on, which no other account but root can read. A person's password is placed only on a machine that names an agent
account of its own judged unable to become root, by a verdict at most fifteen minutes old; on ace, g14 and shanks, where agents can still run as the operator,
account of its own judged unable to become root, by a verdict at most fifteen minutes old; on the other machines, where agents can still run as the operator,
it is not placed, and the controller says so. A module run for an identity reaches the bus with that password, can do
only what the identity's role allows, and every call is recorded as that identity's. Nox's role never holds an approval
grant, a trusted party's grant or a dangerous tool named in it (ADR 0387 §4 does not apply to it), and the identity seat
@@ -253,19 +253,19 @@ carry them:
From research 057 (ADR 0411 to ADR 0414):
6. The identity seat lists `jochen` and `nox` with their machines, kept logins and novox's agent account mark; a
6. The identity seat lists the operator and `nox` with their machines, kept logins and the control node's agent account mark; a
create or a presence change by any caller but the operator's Approve is refused.
7. On ace, g14 and shanks a login `nox` exists; on novox the login `nox` is adopted with its uid and home unchanged;
on all four the node-engine judges `nox` unable to become root; a login `nox` given a sudo rule in a test is left
7. On every other machine a login `nox` exists; on the control node the login `nox` is adopted with its uid and home unchanged;
on every machine the node-engine judges `nox` unable to become root; a login `nox` given a sudo rule in a test is left
unaltered and the self-check raises `agent-can-become-root` for it, on a machine that marks no agent account too;
the operator's logins `ace`, `jochen` and `jochens` are
the operator's existing logins are
unchanged.
8. No manifest in the catalogue declares a login for a person or an agent; the catalogue's check refuses one.
9. For every machine, the declaration before and after differs, for the modules not set to run for an identity, only
in the machine accounts' `user` resources (now the controller's, and `nox` added on ace, g14 and shanks); claude-code on novox, run for `nox`, places the same
files in the same home; on ace, g14 and shanks the guard stays off and the operator's sessions keep the mesh's tools.
10. A session started for `nox` on novox gets the agent's home configuration and one started for `jochen` the
operator's, with no tool call through; a session as `nox` that starts claude-code for `jochen` is refused; with
in the machine accounts' `user` resources (now the controller's, and `nox` added on the other machines); claude-code on the control node, run for `nox`, places the same
files in the same home; on the other machines the guard stays off and the operator's sessions keep the mesh's tools.
10. A session started for `nox` on the control node gets the agent's home configuration and one started for the operator the
operator's, with no tool call through; a session as `nox` that starts claude-code for the operator is refused; with
ssh-client run for `nox`, nox's key is on the forge account `nox` and the session pushes a branch over SSH as `nox`.
11. Nox's bus password is owned by `nox` at mode 0600 on every machine nox is present on; a call with it outside
nox's role is refused; a grant test finds no approval grant, trusted party's grant or dangerous tool in nox's
@@ -314,8 +314,8 @@ waits for nothing; 12 waits for milestone 6.
|---|---|---|---|---|
| 11 | The agent's forge account is `nox`, with its keys and its place in the agents' write team kept | test 12 | mesh-catalog gitea: the rename, keys registered on `nox`, every `forge-account` entry (993) | — |
| 12 | The mesh makes the operator's logins and nox's on every machine from the identities, and judges nox unable to become root everywhere | tests 6 to 9 | identity module: logins, machines, kept logins, the agent account mark, the operator's verb (994); the node-engine (`mesh-host`): existing logins adopted, every agent login judged (995); mesh-controller: machine accounts composed, node accounts read from the identities, the terminal lines retired (996); mesh-catalog: claude-code declares no login, the catalogue's check refuses one (997) | 6 |
| 13 | The operator and nox each reach the bus with their own password, held to their role; the operator's only where no agent runs as the operator | test 11 | mesh-controller: `person.jochen` and `agent.nox`, secrets at 0600, the fifteen-minute verdict (999); identity module: nox's role refuses approvals and dangerous tools (998) | 12 |
| 14 | The operator starts a claude-code session for nox or for themself, and nox pushes over SSH with its own key | test 10 | mesh-controller: run for, assignments keyed by identity, the refusals (1001); mesh-sdk: calls as the identity, a start goes down only (1002); claude-code: started for nox or jochen (1003); ssh-client and gitea: nox's own key, closing issue 989 (1004) | 11, 13 |
| 13 | The operator and nox each reach the bus with their own password, held to their role; the operator's only where no agent runs as the operator | test 11 | mesh-controller: the operator's and nox's bus accounts, secrets at 0600, the fifteen-minute verdict (999); identity module: nox's role refuses approvals and dangerous tools (998) | 12 |
| 14 | The operator starts a claude-code session for nox or for themself, and nox pushes over SSH with its own key | test 10 | mesh-controller: run for, assignments keyed by identity, the refusals (1001); mesh-sdk: calls as the identity, a start goes down only (1002); claude-code: started for nox or for the operator (1003); ssh-client and gitea: nox's own key, closing issue 989 (1004) | 11, 13 |
The agent's and the operator's accounts in Keycloak and mail (ADR 0414 §2 and §3) follow milestone 13 and are
tracked by issue 1000, which needs a design section first. A second agent identity is made only when a rule