From 32af97e2608a915ec4223e8fd27d95715fc670c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 12 Aug 2026 22:52:23 +0000 Subject: [PATCH] secret-store: the anthropic proxy secret moves in too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third value for the store, agreed in conversation. Neither an encryption nor a signing key — a bearer credential the agent presents to the proxy on localhost — but it qualifies on the same properties: generated once, shared between two core processes, fatal to regenerate silently. It makes the case better than the other two, because it is not in .env. It is in $DATA_PATH/sidecar/claude-state.json, which is the exact location decision 3 rules out by name: DATA_PATH is what gets backed up. Also records the rename. ANTHROPIC_API_KEY is wrong in both halves — not Anthropic's, not an API key; Anthropic's real credential is the OAuth token in ~/.claude/.credentials.json that the proxy swaps this one for. It is anthropic-proxy-secret everywhere we control, and keeps the CLI's name only on the assignment `claude` itself reads. Co-Authored-By: Claude Opus 5 (1M context) --- docs/secret-store.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/secret-store.md b/docs/secret-store.md index 5f674757..cd1b9c26 100644 --- a/docs/secret-store.md +++ b/docs/secret-store.md @@ -116,6 +116,24 @@ one value — or comes from a file read on demand. - `JWT_SECRET` — a signing key rather than an encryption key, but it has the same properties: must survive restarts, must never be regenerated silently, and benefits from versioning during a rotation. Leaving one in a store and one in `.env` would be the scattering this is meant to end. +- **The anthropic proxy secret**, purpose `anthropic-proxy`. Agreed 2026-08-12. Neither an encryption + key nor a signing key — a bearer credential, generated once by `ensureProxySecret` and presented by + `officer-agent` to `officer-anthropic-proxy` on `127.0.0.1`. It qualifies on the same three + properties: generated once, shared between two processes, fatal to regenerate silently. + + It is in the store for a sharper reason than the other two, though. It is not in `.env` today — it + is in `$DATA_PATH/sidecar/claude-state.json`, mixed in with session records. That is the one + location [decision 3](#3-where-the-file-goes) rules out by name: `DATA_PATH` is what people back up, + so the secret already travels in the same tarball as the data it protects. + + **Naming.** It is called `ANTHROPIC_API_KEY` in `ensureAnthropicEnv`, and that name is wrong in both + halves — it is not Anthropic's and it is not an API key. Anthropic's real credential is the OAuth + token in `~/.claude/.credentials.json`, which the proxy swaps this one for on the way out. Our name + for it is **anthropic-proxy-secret** everywhere we control. + + The exception is the last line before the spawn. `claude` reads the variable `ANTHROPIC_API_KEY` and + format-checks the `sk-ant-api03-` prefix, so both are the CLI's contract rather than ours and both + stay. That one assignment keeps the CLI's name, with a comment saying why. ---