diff --git a/modules/claude-code/README.md b/modules/claude-code/README.md index 5adbcd6c..fdd65134 100644 --- a/modules/claude-code/README.md +++ b/modules/claude-code/README.md @@ -8,12 +8,25 @@ configuration, and the consumer side of the Anthropic licence manager (design 39 Two directories, declared, so the mesh refuses a second module owning either: - `/etc/claude-code`, the agent's machine-wide managed directory, root's, `0755`. -- `~/.claude` under the operator account's home, the operator's, `0700`. The module owns the directory — +- `~/.claude` under the home of the account agents run as (the operator's, unless the machine names an agent + account of its own), that account's, `0700`. The module owns the directory — that it exists, who owns it, its mode — and of what is inside only what it writes. Everything else in it (memory, history, projects, local settings, a person's own rules and skills) is the person's and is never read or written (hq ADR 0182). Unassigned, the module leaves the directory: the host removes a directory only when it is empty. +And, for where the agent runs as an account of its own (hq ADR 0266): + +- **the account agents run as**, a `user` named by the machine fact `agent-account` — the operator's + account where the machine names none, which declares nothing new of it. Where it names one, the mesh + makes the account (its home, its own group, no password, no group of the mesh's) and asks the node-engine + to judge `root: never` on every look: that it is not root, is in no group that grants root, has no sudo + rule and can read no secret the mesh placed for another account. A way found is this module's condition, + and the controller's self-check says it urgently. +- `/usr/local/bin/claude-agent`, root's, `0755`: starts the agent as that account — `claude` itself when run + as it, otherwise `sudo -iu claude` through the operator's own sudo, carrying the guard's + override only when it is set in the operator's shell. + ## What it writes Under the agent's managed directory, `/etc/claude-code`, owned whole by this module and rewritten diff --git a/modules/claude-code/module.json b/modules/claude-code/module.json index 1e7082b1..46a9cb12 100644 --- a/modules/claude-code/module.json +++ b/modules/claude-code/module.json @@ -84,12 +84,25 @@ "path": "/etc/claude-code", "mode": "0755" }, + { + "id": "start", + "type": "file", + "path": "/usr/local/bin/claude-agent", + "mode": "0755", + "content": "#!/bin/sh\n# The mesh's (module claude-code, novox/hq ADR 0266): start the agent as the account agents run as on this\n# machine. Written whole at every push: an edit here is overwritten.\nagent='${machine:agent-account}'\nif [ \"$(id -un)\" = \"$agent\" ]; then\n\texec claude \"$@\"\nfi\n# Another account, the operator's, becomes the agent's through its own sudo: the person is the authority. The\n# operator's override of the guard travels only when it is set in this shell, as it would reach claude.\nif [ -n \"$MESH_GUARD_OVERRIDE\" ]; then\n\texec sudo -iu \"$agent\" env MESH_GUARD_OVERRIDE=\"$MESH_GUARD_OVERRIDE\" claude \"$@\"\nfi\nexec sudo -iu \"$agent\" claude \"$@\"\n" + }, + { + "id": "agent-account", + "type": "user", + "name": "${machine:agent-account}", + "root": "${machine:agent-root}" + }, { "id": "agent-home", "type": "directory", - "path": "${machine:account-home}/.claude", + "path": "${machine:agent-home}/.claude", "mode": "0700", - "owner": "${machine:account}" + "owner": "${machine:agent-account}" }, { "id": "state",