Claude Subscription Routing Research¶
This document describes MUDIDI's isolated Claude subscription adapter and its credential boundary.
Status¶
ClaudeResearchBackend is available whenever subscription billing is selected.
Its status, errors, CLI output, API payloads, and dashboard surfaces expose
actionable authentication state without a blanket disclaimer or setup flag.
Availability¶
Claude login, refresh, completion, and logout are enabled by default. The dashboard shows the Claude account card alongside OpenAI and Google account cards whenever subscription billing is selected. No fallback to an API key, another provider, a gateway, or a relay is attempted.
Researched values and scope¶
The adapter keeps these values private to its module and uses them only for the research path:
- Authorization endpoint:
https://claude.com/cai/oauth/authorize - Token endpoint:
https://platform.claude.com/v1/oauth/token - Messages endpoint:
https://api.anthropic.com/v1/messages - OAuth client id:
9d1c250a-e61b-44d9-88ed-5944d1962f5e - Scope:
org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload - PKCE method:
S256
A fresh shared PKCE transaction and the fixed callback URI
http://localhost:54545/callback are used for each login. In non-container mode,
the receiver binds to loopback on 127.0.0.1:54545; in container mode, it
listens internally on all container interfaces on port 54545. Compose publishes port 54545 only on
the host loopback interface. The adapter rechecks callback state before sending
the authorization code to the shared OAuth client. Authorization-code and
refresh-token exchanges use bounded JSON POSTs with the researched Claude Code
user agent through the shared OAuth transport; endpoint redirects and oversized
responses are rejected. All values are observed/researched behavior, not a
public Anthropic OAuth contract.
Credential boundary¶
Access and refresh tokens are held in SubscriptionCredential only inside
the subscription backend and the separate encrypted SubscriptionStore.
When a real store is used, records are Fernet-encrypted in the subscription
SQLite database; the normal API-key credential path and its storage remain
separate. Token fields are excluded from ordinary model dumps and
representations. Status, errors, and metadata are redacted and contain only
safe account and expiry state.
The backend never reads or sets provider API-key environment variables. The
OAuth access token is sent as a bearer token in the provider request
Authorization header; it is not copied into the JSON body, status, logs,
subprocess arguments, or environment. The adapter does not send an x-api-key
header and never falls back to one.
Request, discovery, and response boundary¶
The adapter discovers the authenticated account catalog through Anthropic's
bounded, paginated /v1/models endpoint using the same OAuth bearer and Claude
Code headers as completion requests. It retains safe display, creation, and
provider-order metadata; a 401 may refresh once before discovery fails closed.
Completion translates the provider-neutral request into an Anthropic
Messages-compatible JSON request. OAuth requests prepend the identity system
block You are Claude Code, Anthropic's official CLI for Claude. before any
caller system text. The adapter supports text content, user image blocks (as
validated base64 data URIs or HTTPS image URLs), PDF document blocks (as
validated base64 data URIs, HTTPS URLs, or Anthropic file IDs), reviewed
extended-thinking budgets for older models, adaptive thinking plus
output_config.effort for current models, and the provider's structured
JSON-schema output shape. It normalizes visible text, stop reason, and
input/output/cached/reasoning usage.
Unsupported content, unsupported schema keywords, malformed responses, thought-only output, schema mismatches, authentication failures, and policy-restricted responses fail closed with typed subscription errors. A 401 may perform exactly one OAuth refresh and request retry; a second 401 is an expired-session error.
Removal path¶
To remove this integration, stop selecting the claude subscription provider,
remove the ClaudeResearchBackend module and its focused tests/documentation,
and delete the Claude row from the separate subscription store with the store's
provider logout operation. Removing this module does not require changing or
migrating the existing LiteLLM/API-key path.