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:
@@ -38,11 +38,15 @@ them. Installed SDK is **0.2.59**; `package.json:31` pins `^0.2.41`.
|
|||||||
the SDK also needs to reach the spawned process in a way `setpriv` breaks, this whole approach is wrong and
|
the SDK also needs to reach the spawned process in a way `setpriv` breaks, this whole approach is wrong and
|
||||||
the fallback is the earlier plan (member turn as its own process).
|
the fallback is the earlier plan (member turn as its own process).
|
||||||
|
|
||||||
Second stale claim, already corrected once: `docs/per-user-linux-accounts.md:230` still says a member's
|
Second stale claim, already retracted once by the previous handoff §5:
|
||||||
`claude` "needs only `ANTHROPIC_BASE_URL` pointed at the proxy and no key of its own." The previous handoff
|
`docs/per-user-linux-accounts.md:230` said a member's `claude` "needs only `ANTHROPIC_BASE_URL` pointed at the
|
||||||
§5 retracted that. **Both passages need editing; neither has been edited.** Left alone deliberately so this
|
proxy and no key of its own." That is backwards — the proxy holds the **owner's** credential
|
||||||
document is the record of what was believed when the code was written, rather than the doc silently agreeing
|
(`sidecar/claude/proxy.ts:7` reads the owner's own `~/.claude/.credentials.json`), so pointing a member at it
|
||||||
with the code.
|
spends the owner's account on their turns.
|
||||||
|
|
||||||
|
**Both passages have now been corrected in `docs/per-user-linux-accounts.md`** (same commit range as the code).
|
||||||
|
The superseded text is in that file's git history. If you are reading this handoff against an older checkout,
|
||||||
|
the doc is the one that moved.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
- **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
|
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.
|
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
|
- **Agents come later** — but by less than this said. Two claims here were wrong and are corrected on
|
||||||
`@anthropic-ai/claude-agent-sdk`, which spawns `claude` itself and takes `env`/`cwd` but has nowhere to
|
2026-08-11; the superseded text is in the git history of this file, and the working state is
|
||||||
put a uid. Dropping privileges has to happen *outside* the SDK, which makes a member's turn its own
|
`COMMS/sidecar-app-store/2026-08-11-per-user-claude-handoff.md`.
|
||||||
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`
|
It said the SDK "has nowhere to put a uid", so dropping privileges had to happen *outside* it, making a
|
||||||
pointed at the proxy and no key of its own.
|
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
|
- **`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*
|
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
|
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