From 1e169c207b4a566cfec6dca7141f86c8cc3dc7ad Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Mon, 12 Oct 2026 15:21:20 -0500 Subject: [PATCH] plans: brief for the CLIProxyAPI stand-in-key test (#237, Q127) Co-Authored-By: Claude Opus 5.5 --- docs/plans/2026-10-12_local-model-proxy.md | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 docs/plans/2026-10-12_local-model-proxy.md diff --git a/docs/plans/2026-10-12_local-model-proxy.md b/docs/plans/2026-10-12_local-model-proxy.md new file mode 100644 index 000000000..7b170fd32 --- /dev/null +++ b/docs/plans/2026-10-12_local-model-proxy.md @@ -0,0 +1,94 @@ +Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`. +It answers Vikunja P19 #237. Jason confirmed it through Mos as "Q127: +yes" (sage-0110). Role sessions talk only to a local proxy, CLIProxyAPI +first, with keys the stack issues and rotates. The upstream tokens and +keys stay in the proxy, which is set once for the whole machine, and +nobody hand-edits a credential file. Decision 114's hold on session +traffic through CLIProxyAPI is lifted for #237 (lead decision 120). This +row is the test that comes before any design: it runs after rows 92 and +93, the redeploy and Jason's re-test. + +# A local model proxy for role sessions (2026-10-12) + +## Stand-in-key test of CLIProxyAPI for role sessions + +### Problem + +Every role session logs in with the token in +`~/.config/mosaic-dev/secrets/claude-session.env`, which Jason made by +hand (decision 119). He wants credentials set by the stack, not by him. +The session allowlist already passes `ANTHROPIC_BASE_URL`, +`ANTHROPIC_AUTH_TOKEN` and `ANTHROPIC_API_KEY` +(`packages/seat/src/session.mjs:62-64`), so a Claude Code session can +point at a gateway without a code change. Pi sessions can't, because no +OpenAI base-URL variable passes. CLIProxyAPI listens on +`127.0.0.1:8317` (`~/.local/opt/EasyCLIProxyAPI/cpa-core/cli-proxy-api`, +running since 2026-10-06). Nobody has checked whether Claude Code or pi +works through it. Nobody has checked whether it can issue a key per +agent without its WebUI either. + +### Owner and reviewer + +- Owner: Researcher. +- Reviewer: Dewey. Sage reruns every script at the gate. + +### Files owned + +- `agents/researcher/work/i1-proxy-test/`: scripts, a stand-in upstream, + logs, `REPORT.md` and a manifest. Nothing outside it. + +### What ships + +All of this runs against a second CLIProxyAPI process that the test +starts from the same binary. It gets its own made-up config, port, data +directory and management key under the packet directory. The running +proxy on 8317, its config and its data aren't touched, read or called. +The upstream is a stand-in HTTP server in the packet. It records every +request and answers like the Anthropic Messages API, including streamed +answers and tool calls. The stand-in proxy is configured to use it as its +Claude upstream. No real token or key exists anywhere in the test, and +no request leaves the machine. + +- The proxy's version, and the config fields and management endpoints the + test uses, each cited to its own docs or `--help` output. +- Claude Code (the pinned binary, `MOSAIC_CLAUDE_BIN`) and pi (the pinned + version) each run one non-interactive turn through the stand-in proxy, + using only the session's allowlisted variables. If pi can't, the report + names the variable or adapter change it needs. For each, the stand-in + upstream's log shows: + - a streamed answer arriving intact; + - a tool call and its result making the round trip; + - `cache_control` blocks and the `anthropic-beta` and + `anthropic-version` headers as the client sent them, or exactly + what the proxy dropped or changed; + - which client key the proxy saw, and that the upstream saw only the + proxy's own made-up upstream key. +- Per-agent keys from the command line: the test creates two client keys + through the stand-in proxy's management API or CLI, with no WebUI. A + session with key A works. Revoking A refuses A's next request and + leaves B working. Each request's key shows up in the proxy's usage or + logs. The report says how many steps that takes and whether a restart + is needed. +- The proxy's behavior with an unknown key, a missing key, and an + upstream that is down. The report gives the error each client prints. +- A cleanup script that stops the stand-in processes and leaves no + process, port or file outside the packet. The report says how to run + everything again. +- `REPORT.md` lists what holds, what doesn't, and what the #237 design row + has to settle. That includes where the issued keys live, how the bus + hands one to a session, and rotation. + +### Out of scope + +Any change to the running proxy, its config or its keys. That goes back +to Mos (sage-0110). Reading its management key: no agent does that, +ever. Real credentials or spend. Switching a live seat to the proxy, and +the subscription-terms question: both go to Jason after this test. The +#237 design and build rows. Containerized sessions (I1). + +### Gate + +Dewey approves on the row's issue, naming the packet manifest. Sage +reruns every script from the packet and checks that the running proxy's +process, port and config modification time are unchanged and that +nothing the test created is left behind.