feat(orcarouter): OAuth 2.0 + PKCE connect and a live chat catalog alongside the API key - #6867
Merged
Hmbown merged 1 commit intoOct 6, 2026
Conversation
…ongside the API key Signed-off-by: hodeswildsmith455-boop <hodeswildsmith455-boop@users.noreply.github.com>
Hmbown
approved these changes
Oct 6, 2026
Hmbown
left a comment
Collaborator
There was a problem hiding this comment.
thank you so much for this!!!
Hmbown
pushed a commit
that referenced
this pull request
Oct 6, 2026
Reconcile the complete contributions from #6832 (@aboimpinto), #6867 (@hodeswildsmith455-boop), and #6805 (@LIghtJUNction) with the current Engine, provider identities, reviewed-plugin policy, and task lifecycle. Original contributor histories are recorded by subsequent resolved merges. Fix the already integrated contributor cases: snapshot corruption is an explicit unavailable/error result (#6817), malformed locales cannot select an incidental script (#6860), image metadata uses the exact uploaded bytes and respects available decoders (#6858), automation deletion waits for actual scheduler reconciliation (#6864), and blocking trust/skill reads stay off the async executor (#6869). Preserve #6857's compaction regression. Extend #6872's human-wait lifecycle guard to approval/elevation cards; retire only the matching ended parent request and refresh activity only after a delivered decision. Enforce configured finite approval deadlines in the Engine, including deadline/cancellation races and durable receipts. Serialize Native Windows ACL admission/retirement across Core processes with a logon-scoped kernel mutex, preserving exact SID/object validation. Add an actual child-process lock test; serialize DSH host tests in the existing extension-host lane. Windows execution proof remains hosted CI. Reconcile the vendored computer-use plugin with canonical main a656f67455fc while preserving Core's 0.12.1 embedding contract. Canonical b47/a656 tree passed Ubuntu/macOS/Windows source and package gates, including 28/28 Windows-focused tests and the controlled desktop fixture; this is separate from the new Engine head's CI verdict. Partial adaptation of the discovery-cache priority portion from PR #6393 by @AdityaVG13 (original ac33dd4). Preserve the best match under count and byte limits without importing the unfinished echolocation/fork design; the broader draft remains open. Validation: - npm test: 1286 passed, 0 failed, 7 skipped; web 767/767. - npm run check:web: lint, typecheck and production build passed. - Affected Rust selection: 801/803 initially passed; the two fixture/lifecycle expectation failures were corrected and each passed a focused rerun. - Additional focused Rust: approval 28/28, discovery cache 11/11, OrcaRouter synthetic catalog 3/3, and 33/33 lifecycle/API/routing checks. - Final CI-repair selection: 37/39 initially passed; the BMP feature-proxy and feature-registry summary failures were corrected; both corrected tests passed (2/2, 0 failures). - Qualified Clippy: six packages, all targets/all features, passed with the CI style allowances. Portable no-default-feature check passed; portable policy verifier 6/6 passed; formatting and diff checks passed. - Runtime contract: 55 measured metrics passed after explicit remeasurement; all 21 structural identities were unchanged. Twelve byte/token-estimate budgets account for bounded child-wait disclosure and contributor locale descriptions; no runtime field/prompt was removed to lower the budget. - Persistence budget was not qualified locally: the checker requires a clean tree and this shared checkout retains an unrelated operator file. Clean hosted CI, fresh stamped build and real DeepSeek TUI acceptance remain required before the integration PR can merge to main. Refs #6872, #6843, #6795. Co-authored-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com> Co-authored-by: hodeswildsmith455-boop <hodeswildsmith455-boop@users.noreply.github.com> Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com> Co-authored-by: AdityaVG13 <adityavgcode@gmail.com> Signed-off-by: CodeWhale Bot <bot@codewhale.net>
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.
What and why
Codewhale already routes OrcaRouter as a first-class provider — kind, config, defaults, and pricing surface all landed earlier — but it only accepted a pasted
ORCAROUTER_API_KEY. This adds the second credential entry point an OrcaRouter user can be missing (a browser sign-in), and makes the model control render the live OrcaRouter catalog instead of trusting the provider row alone.orcarouter(crates/config/src/provider_kind.rs), inference athttps://api.orcarouter.ai/v1codewhale auth set --provider orcarouter,/provider, orORCAROUTER_API_KEY, stored in the existingorcaroutersecret-store slot127.0.0.1; Flow B/C were not needed and are not implementedcrates/tui/src/oauth.rs— one credential seam, two adapterscrates/tui/src/client.rs— chat-scoped, fail-closed catalog filterdocs/PROVIDERS.md,docs/features.toml(orcarouter-sign-in), all shipped localesAffiliation disclosure: I'm an engineer on the OrcaRouter team. This work is made on behalf of OrcaRouter, in coordination with OrcaRouter.
How the credential works
The key belongs to the user, not to this project: it is billed to their OrcaRouter account, listed in their console, and revocable by them at any time. No client secret and no pre-registered redirect URI; PKCE binds the auth code to this process, so an intercepted code cannot be redeemed by anyone else.
Both entry points are adapters on one seam.
OrcaCredential::from_api_keyandexchange_orcarouter_codeproduce the same value, andactivate_orcarouter_credentialstores either under the existingorcarouterslot withauth_mode = "api_key"metadata. Nothing downstream, including catalog discovery, can tell which adapter ran. A PKCE-issued key is a durable API key, not refreshable token material, so OrcaRouter is deliberately not one of the ownedOAuthProvidergenerations: Codewhale reuses the stored key across restarts and never sends a refresh grant, and a401marks only the credential generation that actually failed as needing re-authentication.Authentication and inference stay on separate origins: authorize at
https://www.orcarouter.ai/auth, exchange atPOST https://www.orcarouter.ai/api/v1/auth/keys(never/v1/auth/keyson the API host), models and chat athttps://api.orcarouter.ai/v1. Self-hosted deployments can override each origin (ORCA_AUTH_BASE_URL,ORCA_API_BASE_URL/ORCAROUTER_BASE_URL); the explicit value wins. Remote origins must be HTTPS; plain HTTP is accepted only on loopback. S256 is used with a fresh verifier and state per attempt, and the callback state is compared in constant time before the code is used.Model discovery and capability filtering
crates/tui/src/client.rsrequestsGET https://api.orcarouter.ai/v1/models?capability=chatwith the configured key. Rows are kept only whensupported_endpoint_typesincludesopenai,anthropic,gemini, oropenai-response; image-generation,openai-video,jina-rerank, and embeddings rows are dropped instead of being guessed from a model name. A row that declares no endpoint type fails closed out of the chat selector rather than being served as text.architecture.input_modalitiesdrives the image-input selector: only rows that explicitly declareimagejoin it. Model ids keep theirvendor/modelnamespace (for exampledeepseek/deepseek-v4-proor theorcarouter/autorouter).Testing
python3 scripts/check_orcarouter_contract.py— PASS. Reads the sources named in the plan plus the live gateway: 16 chat rows, 2 image-input, live chat probeHTTP 200.cargo test -p codewhale-tui --lib --locked orcarouter— 18 passed, 1 ignored, 0 failed. Covers the API-key adapter shape, the shared credential result produced by both adapters, the S256 verifier/challenge pair, the authorize URL, the exchange origin/path/body, granted-scope handling, callback state mismatch and denial, terminal400, secret redaction, the separate HTTPS origins, and an end-to-end connect test (orcarouter_connect_adapter_runs_authorize_callback_exchange_end_to_end) over a local fake auth server using fake key and code only, asserting the verifier never appears in logs or errors.crates/tui/src/client/test_cases_08.rs— catalog tests for chat rows and their image-input fact, a fail-closed empty-roster case, malformed rows and401typing, plus the opt-in live testorcarouter_live_catalog_and_chat_through_the_provider_path.Limitation recorded honestly: the full Codewhale suite was not run end to end in this session — the
codewhale-tuibuild alone runs far past the session budget. The OrcaRouter-focused checks above are what was run and observed.UI
Local GUI evidence was generated with the repository's own provider settings surface driven by Playwright against the live catalog:
auth-methods.png— the API-key and "Connect with OrcaRouter" entries side by side, key maskedtext-model-dropdown.png— the open chat model selector (16 rows)multimodal-model-dropdown.png— the open image-input selector (2 rows)Provider evidence
base_url = https://api.orcarouter.ai/v1for the OpenAI SDK.https://www.orcarouter.ai/auth; exchangePOST /api/v1/auth/keys; revocation and account management athttps://www.orcarouter.ai/console/authorized-apps.GET https://api.orcarouter.ai/v1/models(verified live in this session).providers@orcarouter.aifor provider onboarding. The maintainers may ask me for the current terms URL and operating legal entity if those are required for registry promotion.providers@orcarouter.ai); verification date 2026-10-05.I'm an engineer on the OrcaRouter team. OrcaRouter is an OpenAI-compatible AI gateway that routes many providers behind one endpoint: OrcaRouter.
Issue
No-Issue: adds the OAuth 2.0 + PKCE credential path and live catalog filter to the OrcaRouter provider that already ships in
main; no tracking issue exists for this follow-up.