Uh oh!
There was an error while loading. Please reload this page.
auth: multi-account OAuth subscription failover - #5754
Conversation
jroth1111
commented
Dec 18, 2025
Heads up: I tightened this PR further to maximize mergeability and keep it focused on the core value (multi-account OAuth subscription failover w/ same-request rotation). Key points:
If you’d prefer a different storage gate (flag/config) or want this to wait until #4318 lands, I can adjust. |
2e53591 to
2e7e08fCompare4b867d8 to
41e38d7CompareHey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
41e38d7 to
c5691fdComparejroth1111
commented
Jan 15, 2026
Closing in favor of #8590 (OAuth Marathon). Why superseded:
The core rotation logic and goals remain the same, but the implementation is more refined and maintainable. |
Implements the missing piece of #5391 for OAuth-based subscription providers: store multiple OAuth accounts per provider and automatically fail over within the same user request when an account is rate limited or its session expires.
This PR is intentionally scoped to the core value (no TUI, no model discovery, no vault CLI).
Why
Today an OAuth login is effectively single-account-per-provider. When that account hits
429or expires, the request fails and disrupts the user.Goal: allow multiple “subscription” accounts (OAuth, not API-billing) and make inference resilient by retrying with the next account automatically.
Storage
Bun.secrets(serviceopencode); disk stores only non-secret OAuth metadata (labels, pool order, cooldowns, last status).auth.json(unchanged) to avoid overlapping with [FEATURE]: Allow storage of secrets in system credential store. #4318’s broader keyring work.Existing
auth.jsonis migrated to a v2 format on first read; OAuth secrets are moved into the keychain.What changed
429→ Retry-After-aware cooldown + rotate to next account and retry in the same request401/403→ force a refresh (by clearing access/expires) and retry once; if still unauthorized, rotateAuth.set()updates the correct OAuth record by matching therefreshtoken (works with/auth/:providerID).opencode auth loginOAuth paths now add accounts instead of overwriting.Review order
feat(auth): keychain-backed oauth records(store + migration)feat(auth): rotate oauth subscriptions on 429/401(rotation + provider integration + CLI)test(auth): cover oauth failoverfix(auth): keep api tokens in file, update oauth selection(avoid [FEATURE]: Allow storage of secrets in system credential store. #4318 overlap + robust refresh targeting)test(auth): auth.set selects oauth record by refreshfix(auth): only require keychain for oauth migrationtest(auth): isolate oauth rotation provider idHow to test
opencode auth logintwice for the same OAuth provider (e.g. Anthropic “Claude Pro/Max”, Copilot) to create multiple subscription accounts.packages/opencode:bun test test/auth/oauth-rotation.test.tsNotes