Design 58 and 36: identities carry logins, run for an identity, a bus password per identity (ADR 0411 to 0414, research 057)
mesh/merge-gate head 98b731d5d1ff merged into trunk 375e77690b8a — pass: the change touches no module of the mesh's graph
mesh/repo-check head 98b731d5d1ff merged into trunk 375e77690b8a — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate head 98b731d5d1ff merged into trunk 375e77690b8a — pass: the change touches no module of the mesh's graph
mesh/repo-check head 98b731d5d1ff merged into trunk 375e77690b8a — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
This commit is contained in:
+22
-12
@@ -98,6 +98,9 @@ and repair).
|
||||
*Not:* ~~tools-sdk~~
|
||||
- **invokes** — the manifest word for the tools a module calls, `<module>.<tool>` each or `*` for every
|
||||
one. A grant on the publish side and nothing else; a module that declares none calls nothing.
|
||||
- **run for** — an assignment, or a start of a module, that serves one agent identity with that identity's machine
|
||||
account, home and bus password. Only a module whose manifest declares it may be run for an identity; running for
|
||||
the operator is the default run, as the operator account, with no setting (ADR 0412).
|
||||
- **upgrade policy** — how a module's new builds reach its nodes: `roll` (one node first, judged, then
|
||||
the rest), `together`, or `record` (register the build, send it nowhere)
|
||||
(ADR 0236).
|
||||
@@ -231,7 +234,7 @@ every other domain has something to run on. **Recorded by** the controller and t
|
||||
|
||||
**Purpose.** To decide, send and apply what each node runs, and to say why.
|
||||
**Recorded by** the controller's `inventory` database. **Upstream of** Provisioning, Connectivity, Data
|
||||
and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 0252, 0261.
|
||||
and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 0252, 0261, 0411.
|
||||
**Uses:** node, machine, module, seat, manifest (Module), config value (Config).
|
||||
|
||||
- **assignment** — a module put on a node. Its config values on that node (module-assignment config,
|
||||
@@ -264,15 +267,15 @@ and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 02
|
||||
other things (see [Homonyms](#homonyms)).
|
||||
- **apply** — the node-engine making its node match its declaration; **reconcile** is doing so again
|
||||
until nothing differs.
|
||||
- **operator account** — the login name of the person who works on a node, stated on the node record;
|
||||
empty for a node nobody logs into. Everything the mesh places under a person's home is resolved
|
||||
against this account's home and owned by it
|
||||
(ADR 0181).
|
||||
- **operator account** — the machine account of the operator's person identity on a node, read from the
|
||||
identity and no longer stated on the node record; empty for a node nobody logs into. Everything the mesh
|
||||
places under a person's home is resolved against this account's home and owned by it
|
||||
(ADR 0181, ADR 0411).
|
||||
Not a name a manifest carries.
|
||||
- **agent account** — the login every coding agent on a node runs as, when the node names one of its own;
|
||||
stated on the node record at the controller's terminal, never by a verb or a config value. Empty means agents
|
||||
run as the operator account. It cannot become root without a person, and the node-engine judges that on
|
||||
every look (ADR 0266).
|
||||
- **agent account** — the machine account of the agent identity the identity seat marks as a node's agent account,
|
||||
on the operator's Approve, never by an assignment or a config value. Where none is marked, agents run as the
|
||||
operator account. It cannot
|
||||
become root without a person, and the node-engine judges that on every look (ADR 0266, ADR 0411).
|
||||
- **account group** — a group of the machine's group database that a module puts an account in, by
|
||||
declaring the account with that group and nothing else of it. Several modules may each add one to the
|
||||
same account; the mesh takes back only an account group it added
|
||||
@@ -341,7 +344,7 @@ and vault (Identity and access).
|
||||
**Purpose.** To issue, hold, rotate and check the credentials and grants by which modules, nodes, agents
|
||||
and the operator act. **Recorded by** the controller's `identity` and `licences` databases and the vault.
|
||||
**Upstream of** Provisioning, Change and delivery, and Operator and conversation.
|
||||
**Decided by** ADR 0085, 0113, 0183, 0225, 0234, 0386, 0387, 0388.
|
||||
**Decided by** ADR 0085, 0113, 0183, 0225, 0234, 0386, 0387, 0388, 0411, 0413, 0414.
|
||||
**Uses:** module, node, seat, tool (Module), operator, consumer and provision (Provisioning), agent and ask (Operator and conversation).
|
||||
|
||||
- **credential** — anything that proves an identity: a password, a key, a token. A **pair credential**
|
||||
@@ -355,8 +358,13 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
|
||||
- **vault** — the module that owns every secret (`mesh-vault`,
|
||||
[24 — The secrets vault](../03-DESIGN/01-to-be/24-the-secrets-vault.md)).
|
||||
- **identity** — a person, an agent or a module as the mesh knows it: a name, a kind, a role, and whether it
|
||||
is switched on. Every identity and role is held by the identity seat, in the bus's key-value store, and
|
||||
changes only through its verbs (ADR 0386).
|
||||
is switched on; a person or an agent also has a login name, the machines it is present on and, for a person,
|
||||
the login kept on a machine where it differs. Every identity and role is held by the identity seat, in the
|
||||
bus's key-value store, and changes only through its verbs (ADR 0386, ADR 0411). Each person and agent
|
||||
identity has a bus account of its own, carrying its role (ADR 0413).
|
||||
- **machine account** — an identity's login on one machine, made by the mesh from the identity: the
|
||||
controller composes it and the node-engine applies it, adopting a login that exists and never renaming or
|
||||
deleting one (ADR 0411).
|
||||
- **role** — what an identity may call, as a set of grants (ADR 0386). Not a seat: a bare *role* is a
|
||||
homonym (see [Homonyms](#homonyms)).
|
||||
- **grant** — one line of a role: an effect everywhere, an effect on one seat, or one named tool, and may be
|
||||
@@ -817,6 +825,8 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
|
||||
| record | a numbered decision | **decision record** | The record |
|
||||
| | the literal reader of this repository, searched first for a symptom | **the record** (the `records` module) | Operator and conversation |
|
||||
| | the upgrade policy that sends nowhere | `record` | Module |
|
||||
| nox | the mesh's one agent identity, its logins and accounts (ADR 0414) | **`nox`, the agent** | Identity and access |
|
||||
| | the operator's terminal command, `mesh-cli` | **the `nox` command** | Operator and conversation |
|
||||
| knowledge base | the module holding the decision records and research efforts whole | **knowledge base** | The record |
|
||||
| | the predecessor's operational memory, in older playbooks (issue 430) | none: it no longer exists | — |
|
||||
| check | a pull request's two statuses | **merge check**, **merge gate**, **repository check** | Change and delivery |
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-catalog modules/claude-code]
|
||||
updated: 2026-10-13
|
||||
updated: 2026-10-17
|
||||
decisions:
|
||||
- "ADR 0411"
|
||||
- "ADR 0412"
|
||||
- "ADR 0343"
|
||||
- "ADR 0274"
|
||||
- "ADR 0273"
|
||||
@@ -306,21 +308,27 @@ operator's word — and, for the operator's own home, only at the terminal or on
|
||||
|
||||
## 9. The account the agent runs as
|
||||
|
||||
*Added 2026-10-08 by ADR 0266.*
|
||||
Everywhere above, "the operator's home" and "the operator account" mean **the account the agent runs as**.
|
||||
That is the operator account, unless the node names an **agent account** of its own. The control node does.
|
||||
*Added 2026-10-08 by ADR 0266; changed 2026-10-17 by ADR 0411 and ADR 0412.*
|
||||
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
|
||||
machine where no agent is marked as the agent account, its assignment is the default run, as every module's is.
|
||||
|
||||
**The fact.** The operator states the agent account at the controller's terminal. No verb and no setting
|
||||
writes it. The controller resolves the machine facts `agent-account`, `agent-home` and `agent-root`, and gives
|
||||
the tool runner the account and its home. Where the node names none, the facts name the operator account and
|
||||
`agent-root` is empty, so nothing changes there.
|
||||
**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
|
||||
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`
|
||||
is empty, so nothing changes there, though a login `nox` exists for the modules run for it.
|
||||
|
||||
**What the module declares.**
|
||||
|
||||
- A `user` named by `agent-account`, with `root` set from `agent-root`. Where the account is the agent's own,
|
||||
the mesh creates it (home, own group, no password) and the node-engine judges on every look that it cannot
|
||||
become root without a person, by the ways ADR 0266 §3 lists. It detects those ways and no others; it
|
||||
prevents nothing.
|
||||
- No login. The mesh makes the agent's machine account (home, own group, no password) from the identity, and the
|
||||
node-engine judges on every look that it cannot become root without a person, by the ways ADR 0266 §3 lists.
|
||||
It detects those ways and no others; it prevents nothing. The `user` resource named by `agent-account`,
|
||||
which this module declared until ADR 0411, goes.
|
||||
- `~/.claude` under that account's home, owned by it.
|
||||
- `claude-agent`, a command that starts the agent as that account through the operator's own sudo, or
|
||||
directly when already run as it.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
layer: to-be
|
||||
status: designed
|
||||
code: [mesh-catalog, mesh-media-catalog, mesh-sdk, mesh-tools, mesh-controller, mesh-host, mesh-lab]
|
||||
updated: 2026-10-16
|
||||
updated: 2026-10-17
|
||||
decisions:
|
||||
- "ADR 0383"
|
||||
- "ADR 0384"
|
||||
@@ -12,6 +12,10 @@ decisions:
|
||||
- "ADR 0388"
|
||||
- "ADR 0389"
|
||||
- "ADR 0390"
|
||||
- "ADR 0411"
|
||||
- "ADR 0412"
|
||||
- "ADR 0413"
|
||||
- "ADR 0414"
|
||||
---
|
||||
|
||||
# 58 — Agent work as the mesh's own
|
||||
@@ -21,8 +25,10 @@ bus by a thread seat; a thread handler on an always-on node runs the agent harne
|
||||
of its own, with the thread's own branch on the forge as its workspace; the agent works through a workspace toolkit
|
||||
and named tools, never a general command runner. Every person, agent and module is an identity held by one identity
|
||||
seat, with a role made of grants; the bus checks each login by its signature, and the tool runner checks each call
|
||||
against the role, tool by tool, by the effect every tool carries.**
|
||||
(ADR 0383 to ADR 0390, from research 053.)
|
||||
against the role, tool by tool, by the effect every tool carries. An identity is also its logins: the mesh makes each
|
||||
person's and agent's machine account on every machine it is present on, gives each its own bus password, and runs a
|
||||
module for an identity only where the module is set to; everything else runs as the operator.**
|
||||
(ADR 0383 to ADR 0390, from research 053; ADR 0411 to ADR 0414, from research 057.)
|
||||
|
||||
**Acceptance.** The operator starts a thread from the terminal client, an agent on an always-on node works it in a
|
||||
sandbox, asks a question the operator answers in place, and the thread moves to another node and carries on with
|
||||
@@ -106,6 +112,95 @@ agent carries a token the identity seat signed for that agent, and the tool runn
|
||||
refusal names the missing grant; every call is recorded with its identity and thread. A session on an operator's
|
||||
machine calls as the operator's person identity or as an agent, never through the machine's tool-runner login.
|
||||
|
||||
### 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
|
||||
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
|
||||
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.
|
||||
|
||||
An identity's login on one machine is its **machine account**. The controller composes the machine account of every
|
||||
identity present on a machine into that machine's declaration, and the node-engine applies it with its `user`
|
||||
resource. A login that exists is adopted under its name, uid and home; the mesh never renames or deletes one. An
|
||||
agent's machine account has its own home and group, no password, no root group and no sudo rule, and the node-engine
|
||||
judges on every look that it cannot become root without a person (ADR 0266 §3). No module declares a login for a
|
||||
person or an agent: claude-code's `agent-account` resource goes, and the catalogue's check refuses a manifest that
|
||||
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
|
||||
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.
|
||||
|
||||
```
|
||||
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)
|
||||
each identity's bus password ──► its secret, owned by its login, 0600
|
||||
```
|
||||
|
||||
### 5.2 Run for an identity (ADR 0412)
|
||||
|
||||
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`
|
||||
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
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
refuses one; each dangerous act of nox's is asked one by one. The break-glass agent (§6) keeps its own rules and gets
|
||||
no login and no bus password from this. This changes ADR 0259 §8, which kept every bus credential out of an agent's account; the rest of §8 stands.
|
||||
The password lives in today's list of bus accounts and is replaced by a signed login for the same role at the bus
|
||||
switch (§7, §8).
|
||||
|
||||
### 5.4 Traced to GENESIS
|
||||
|
||||
Checked on 2026-10-17 (playbook 02, step 1); no conflict was found.
|
||||
|
||||
- [Mission](../../00-META/mission.md): agents "hold identity", and there is one kind of participant, some of them
|
||||
human; persons and agents are held alike, with the same fields, and differ in what their role allows, which the
|
||||
mission calls modality. "The mesh brokers credentials": the bus password per identity and the service accounts made
|
||||
from it. "The mesh owns the truth": logins are derived from identities, no longer stated per node. "Dogfood": logins
|
||||
go through the node-engine's existing resource.
|
||||
- [Context](../../00-META/context.md): "Identity is mesh-internal", with no directory and no SSO, so the identity seat
|
||||
holds it and Keycloak only receives accounts; "Nodes are personal" and the mesh is a guest, so existing logins are
|
||||
adopted, never renamed; human agents are few, often one, so the seat holds two identities and one agent.
|
||||
- [Effect](../../00-META/effect.md): a human agent's environment is part of the mesh, its login included.
|
||||
|
||||
## 6. Effects, asks and break-glass (ADR 0387)
|
||||
|
||||
Every seat verb and module tool is one permission and carries one **effect**, set in its module's manifest:
|
||||
@@ -156,6 +251,28 @@ carry them:
|
||||
`research/053-signed-bus-logins`, loses nothing and leaves every identity on the new bus.
|
||||
5. The acceptance sentence at the top, end to end.
|
||||
|
||||
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
|
||||
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, 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
|
||||
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 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
|
||||
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
|
||||
role; the operator's password is placed only on a machine with an agent account judged root-free within fifteen
|
||||
minutes, and the controller says so for every other.
|
||||
12. The forge account `nox-agent` is renamed `nox`, keeps every machine's key, stays in the agents' write team, and
|
||||
every `forge-account` entry names `nox`.
|
||||
|
||||
## 11. Milestones
|
||||
|
||||
Each milestone is one feature step (playbook 07), usable as soon as its delivery plan is done, and starts when
|
||||
|
||||
Reference in New Issue
Block a user