Repository navigation
Conversation
…state The native Messages lane needs fixed codes for a pooled OAuth decline, a caller beta it refused to forward and opaque thinking state it removed. New codes: contract 2026-09-25.2.
A caller's anthropic-beta can change what the provider accepts and bills. Only listed values survive, re-spelled from the list, per first-party or compatible destination.
…main Signatures and redacted_thinking can only be verified where they were minted. A native send keeps them for api.anthropic.com and removes them, copy-on-write, everywhere else.
…plies The native Messages lane must authenticate an OAuth account exactly as the adapter does. Moving the block into applyAnthropicOAuthAuth changes no header and no order.
…nd opaque state The builder takes the caller's beta header explicitly, keeps signatures for first-party Anthropic only, and shapes an OAuth request as the adapter does, to api.anthropic.com only.
Behind managedMessagesNativeOAuth, the anthropic OAuth provider to api.anthropic.com is eligible. A pooled account set declines: its rotation and affinity stay in the bridge.
Mirrors the unpooled transport steps: capture, resolve, commit against the capture, and re-check before each send. A pooled set fails closed; renamed tool names map back.
…d opaque guard The lane resolves an OAuth account at dispatch only, re-checks it before each send, maps renamed tools back, and records dropped betas and stripped opaque state by fixed code.
… state at ingress The ingress supplies the OAuth quorum fact, passes only anthropic-beta to the lane, and under reject refuses a non-Anthropic native route that would lose thinking signatures.
The preview reads config only; the stored-account quorum is a dispatch-time fact, so a preview never touches the OAuth store.
…shape Unknown betas never reach the wire, a compatible host gets none, and an OAuth build matches the adapter's headers, prefixes client tools only, and refuses any host but Anthropic's.
Signatures stay with first-party Anthropic and rebuild from the envelope per domain; OAuth needs both switches, is judged from config in planning, and a pool declines.
…te and betas The selected account's token is sent and never the caller's, tool names map back, reject refuses before a send, and dropped betas appear in the trace by code only.
…state and OAuth protocol-paths owns the three PF-10 rules and their tests; the 040 inventory records OAuth native, the pooled-account decline and the opaque-state rule on the native lane.
…rivacy scan A literal bearer header and a userinfo URL read as secrets to privacy:scan; constructing them from parts keeps the same assertions without tripping the scanner.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: lidge-jun/opencodex/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6af9cce397
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| function pooled(config: OcxConfig): boolean { | ||
| return isAnthropicAccountPoolEnabled(config) || hasAnthropicFailoverQuorum(); | ||
| } |
There was a problem hiding this comment.
Re-read the OAuth quorum at dispatch
hasAnthropicFailoverQuorum() caches results for two seconds, but adding an account through saveCredential does not invalidate that cache. If a request caches false while one account exists and the operator then logs in a second usable account, both ingress eligibility and this dispatch guard reuse false, so a request is sent through the native lane even though the bridge is now required to provide account rotation and affinity. Invalidate the quorum cache on account-store changes or use an uncached roster check for this dispatch-time guard.
Useful? React with 👍 / 👎.
| const renames = (name: unknown): name is string => typeof name === "string" && declared.has(name); | ||
| if (isRec(body.tool_choice) && body.tool_choice.type === "tool" && renames(body.tool_choice.name)) { | ||
| out.tool_choice = { ...body.tool_choice, name: wireName(body.tool_choice.name) }; | ||
| } | ||
| const isRenamedUse = (block: unknown): block is Rec & { name: string } => isRec(block) && block.type === "tool_use" && renames(block.name); |
There was a problem hiding this comment.
Prefix historical custom tools even when no longer declared
The history rewrite is restricted to names present in the current tools array. A valid continuation can retain an earlier assistant tool_use/user tool_result pair while omitting that old tool from the current declarations; in that case an ordinary name such as lookup is sent unchanged even though Anthropic OAuth rejects arbitrary unprefixed tool names, whereas the existing adapter transforms every historical tool call. Rewrite historical custom names independently of current declarations, or decline the native lane when their classification is ambiguous.
AGENTS.md reference: src/AGENTS.md:L19-L20
Useful? React with 👍 / 👎.
|
✅ Deterministic PR hygiene checks passed. |
리뷰 · 우선순위 58 / 80이 변경은 Messages 요청을 프록시가 Anthropic에게 직접 보내는 길에, 로그인 계정(OAuth)도 올라탈 수 있게 한다. 스위치는 두 개고, 둘 다 기본이 꺼져 있다. 타는 조건은 좁다. 프로바이더 이름이 호출자가 보낸 생각 블록의 서명과 로그인으로 보낼 때는 기존 어댑터와 같은 헤더를 쓴다. src/adapters/anthropic/passthrough.ts src/server/messages-native-oauth.ts src/protocols/opaque-state.ts 메인테이너의 판단이 필요한 지점 베이스가 계획 미리보기는 계정 저장소를 안 읽는다. 풀 스위치만 본다. 계정은 둘인데 풀이 꺼져 있으면 미리보기는 네이티브라고 하고, 실제 요청은 본문은 이 헤드에서 너의 추천 토큰을 본사 주소로만 보내고, 풀은 다리에 남기며, 스위치 기본값이 꺼진 줄기는 유지하면 된다. 머지 전에 위 세 곳만 손보는 게 좋다. 2초 기억 때문에 계정이 둘인 요청이 네이티브로 새는 것과, 예전 도구 이름이 접두사 없이 나가는 것이 먼저다. 이 댓글은 grok-bot이 작성했습니다 |
|
Maintainer triage: Criteria (P3): Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/roadmap, or long-stale branch. Related / overlapping PRs:
|
Summary
PF-10 of the protocol-first-class unit (
devlog/_plan/260924_protocol_first_class/020_engine_and_codecs.md#pf-10-auth-and-opaque-state). Stacked on #5817 (PF-11).Extends the managed native Messages lane (PF-08) to Anthropic OAuth and makes what it forwards explicit. Everything stays behind switches that default off.
anthropic-betaallowlist (src/adapters/anthropic/beta-allowlist.ts): the native builder takes the caller'santhropic-betaheader only as an explicit argument and re-emits allowlisted values from the allowlist's own spelling, so no caller bytes reach the wire. The allowlist starts withinterleaved-thinking-2025-05-14, first-party Anthropic only; Anthropic-compatible hosts get no caller betas. Dropped values are traced with the fixed reasonanthropic-beta-dropped(never the header text).managedMessagesNativeOAuth(effective only withmanagedMessagesNative): the unpooledanthropicprovider onhttps://api.anthropic.com. The account is resolved at dispatch the way the bridge resolves an unpooled account (capture, resolve, commit against the capture) and re-checked before every send; planning never selects or refreshes. The OAuth header placement moves unchanged into an exported helper the adapter and the native builder share. An OAuth request never carriesx-api-key, and an OAuth token is refused for any other host. Pooled OAuth (anthropicAccountPool.enabledor a failover quorum) declines withoauth-account-pooland stays on the bridge. Declared tool names get the OAuth prefix and are mapped back in streamed and JSON answers; a prefix collision is refused.src/protocols/opaque-state.ts): on the native lane, thinking signatures andredacted_thinkingblocks are kept only for first-party Anthropic. For any other destination they are removed from a copy and traced asopaque-state-stripped; underunrepresentable: "reject"the request is refused before any send.oauth-account-pool,anthropic-beta-dropped,opaque-state-stripped;PROTOCOL_CONTRACT_VERSION→2026-09-25.2.Verification
bun x tsc --noEmit: exit 0 on this head.bun run structure:check,bun run privacy:scan: passed.Tests (
tests/adapters/anthropic/anthropic-beta-allowlist.test.ts,anthropic-messages-passthrough-oauth.test.ts,tests/responses/protocol-opaque-state.test.ts,messages-native-oauth-eligibility.test.ts,tests/claude-integration/messages-native-oauth.test.ts,messages-native-opaque-state.test.ts) are registered and run in the full local suite below.Full local run on the stack head (feat(protocols): protocol paths as a first-class concern — PF-01..PF-12 #5820, which contains this change):
bun run test— the only failures are Lab CL-03/CL-07/CL-08/SEC-02 andrelease helpertimeouts, which fail identically on a checkout without this stack (local environment), plus service/toggle cases that pass when run alone;cd gui && bun test --isolate tests— 2398 pass, 0 fail.CI on this head: all required checks pass.
Checklist