correct two claims about agents that the SDK disproves
docs/per-user-linux-accounts.md carried the reasoning that per-user agents were a large piece of work, and both halves of that reasoning were wrong. The SDK does have somewhere to put a uid — spawnClaudeCodeProcess, documented for running Claude Code in VMs and containers — so a member's turn does not have to become its own process. And the credential claim was backwards: the proxy holds the OWNER'S credential, reading the owner's own ~/.claude/.credentials.json, so pointing a member at it spends the owner's account on the member's turns. The previous handoff had already retracted that one; the doc had not caught up, which is how a retracted claim stays live. Corrected in place rather than deleted, with what was believed and why it was wrong, because the superseded version is the interesting part: the first claim is what made agents look like a later stage than they are. Adds the constraint that actually is out of scope, which the old text never stated: no platform process ever runs as a member, because the sidecar holds POSTGRES_URL and the JWT secret. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -223,12 +223,28 @@ crossed the ancestor that mattered.
|
||||
- **This is not a sandbox.** A member with a shell is on the machine. They cannot read the owner's files
|
||||
or another member's, and `sudo` is not theirs — but they can run code, see process names, and reach the
|
||||
network. It isolates members from each other and from accidents, not from the host.
|
||||
- **Agents come later.** `claude-manager.ts` drives turns through `query()` from
|
||||
`@anthropic-ai/claude-agent-sdk`, which spawns `claude` itself and takes `env`/`cwd` but has nowhere to
|
||||
put a uid. Dropping privileges has to happen *outside* the SDK, which makes a member's turn its own
|
||||
process — a change of shape rather than a flag. The credential is not the problem:
|
||||
`officer-anthropic-proxy` already holds it, so a member's `claude` needs only `ANTHROPIC_BASE_URL`
|
||||
pointed at the proxy and no key of its own.
|
||||
- **Agents come later** — but by less than this said. Two claims here were wrong and are corrected on
|
||||
2026-08-11; the superseded text is in the git history of this file, and the working state is
|
||||
`COMMS/sidecar-app-store/2026-08-11-per-user-claude-handoff.md`.
|
||||
|
||||
It said the SDK "has nowhere to put a uid", so dropping privileges had to happen *outside* it, making a
|
||||
member's turn its own process — "a change of shape rather than a flag". It is a flag: `sdk.d.ts:951`
|
||||
exposes `spawnClaudeCodeProcess`, documented for running Claude Code "in VMs, containers, or remote
|
||||
environments", and `node:child_process.spawn` already satisfies the `SpawnedProcess` shape it wants. So the
|
||||
existing sidecar wraps the CLI spawn in `runAsArgv` per turn and there is no second process to stand up.
|
||||
|
||||
It also said the credential is not the problem because `officer-anthropic-proxy` already holds it, so a
|
||||
member's `claude` "needs only `ANTHROPIC_BASE_URL` pointed at the proxy". That is backwards. The proxy holds
|
||||
the **owner's** credential (`sidecar/claude/proxy.ts:7` reads the owner's own
|
||||
`~/.claude/.credentials.json`), so pointing a member at it spends the owner's account on the member's
|
||||
turns. Per-user Claude means their own login in their own home, and `setpriv --reset-env` is what makes that
|
||||
the default rather than something to remember: nothing crosses into their process unless it is written into
|
||||
the argv.
|
||||
|
||||
What does remain out of scope: **no platform process ever runs as a member.** The agent sidecar needs
|
||||
`POSTGRES_URL` and the JWT signing secret, so a member-uid process holding them could read every account and
|
||||
sign a token as the owner — more than their shell can do, and already refused by `assertSecretsClosed`. The
|
||||
harness stays the service user's; only `claude` itself drops privileges.
|
||||
- **`pty`, `vault` and `opencode` receive no identity at all** (`TODO.md` → Multi-user). pty keys purely
|
||||
on a `sessionId` from the query string, and its `/_officer/sessions` endpoints list and kill *every*
|
||||
session on the box. Safe today only because terminal is owner-only. **The moment a member has a shell
|
||||
|
||||
Reference in New Issue
Block a user