feat(v0.2.1): oauth subscription providers, fairness fixes, test coverage#107
Merged
Conversation
…endpoints (#100) Any path Routerly does not explicitly handle is now forwarded to the project's upstream provider with only the API key swapped, making Routerly a true drop-in replacement for OpenAI, Anthropic, Ollama and custom providers — today and for any future endpoints they add. - Extract `resolveProjectByToken()` helper from auth plugin (shared by the proxy handler so auth is never bypassed) - Add `passthrough.ts`: pure helpers (`pickUpstreamModel`, `buildUpstreamUrl`, `buildUpstreamHeaders`) + `passthroughHandler` registered as Fastify's global setNotFoundHandler - Register a `*` content-type parser in server.ts to capture non-JSON bodies as raw Buffer for verbatim forwarding - Upstream selection: body `model` field matched to project models, else first configured model; Anthropic uses x-api-key, all others Bearer — no config required - Reserved namespaces (`/`, `/health`, `/api/*`, `/dashboard*`) are guarded inside the handler and never proxied - 22 new tests covering all helpers and handler scenarios; existing server telemetry test updated to include the new mock stubs Closes #100 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pic-oauth and openai-oauth - Add anthropic-oauth provider: forwards requests verbatim with stored sk-ant-oat… token, adds required oauth-2025-04-20 beta header and dangerous-direct-browser-access header - Add openai-oauth provider: reads Codex token from ~/.codex/auth.json, auto-refreshes on expiry, translates chat/completions to ChatGPT Responses API SSE format - Register both providers in the adapter map and shared providers.json (priced at $0) - Update anthropic.ts and openai.ts routes with early bypass branches - Add POST /api/test/openai-oauth management endpoint to verify Codex token - Update dashboard ModelFormPage with subscription provider UI (instructions, token input) - Add user-facing guides for Claude and OpenAI subscription setup - Snapshot versioned docs for v0.2.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three bugs fixed in the fairness routing policy: - Cross-project contamination: fairness was reading usage records from all projects; added projectId filter so only records from the current project are counted - Stable-sort tie-breaking: when all policies abstained every candidate got 0.5, causing the first model in config to always win; replaced with Math.random() so traffic distributes uniformly over time - OAuth models invisible to fairness: forwardOpenAIOAuthSSE and forwardAnthropicOAuth never called trackUsage, so openai-oauth and anthropic-oauth always scored 1.0 and won every routing decision; trackUsage is now called on all exit paths (0 tokens, outcome success/error) in both forward functions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
anthropic-oauth(Claude Pro/Max viask-ant-oat…token) andopenai-oauth(ChatGPT Plus/Pro via Codex~/.codex/auth.jsontoken) — both routes forward requests verbatim to the upstream, swapping only the credentialtrackUsagewas never called in the passthrough pathsWhat changed
New providers
anthropic-oauth: verbatim forward withsk-ant-oat…token + required Anthropic OAuth headersopenai-oauth: reads/auto-refreshes Codex token, translates chat/completions to ChatGPT Responses API SSEFairness routing fixes
fairness.ts: addedprojectIdfilter — only records from the current project countrouter.ts:Math.random()fallback when all policies abstain, replacing the static 0.5 that always picked model[0]oauthForward.ts,openaiOAuthForward.ts:trackUsagecalled on all exit paths so OAuth models appear in usage recordsDashboard & CLI
ModelFormPage: subscription provider UI with instructions callout and token/path inputmodel.ts:--providerhelp text updated withanthropic-oauthandopenai-oauthDocs & website
docs/guides/claude-subscription.md,docs/guides/openai-subscription.mdTest plan
npm test --workspace=packages/service— 1077 tests, all greennpm run typecheck --workspace=packages/service— clean🤖 Generated with Claude Code