Skip to content

feat(oauth): Muse Code subscription device-flow login - #14267

Draft
caniko wants to merge 4 commits into
diegosouzapw:release/v3.8.51from
caniko:feat/muse-code-subscription-oauth
Draft

caniko wants to merge 4 commits into
diegosouzapw:release/v3.8.51from
caniko:feat/muse-code-subscription-oauth

Conversation

@caniko

@caniko caniko commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Adds Muse Code subscription OAuth via the existing device-code framework.

Status: device flow + execution path unit-verified; dashboard live demo pending

Device authorization, browser approval, key exchange, and model discovery against live Meta endpoints are verified (see below). Route-level discovery config, Chat-to-Responses format resolution, golden translate-path, persist/reload/restart, reconnect, disconnect, and redaction are covered by mocked tests. Not yet demonstrated: dashboard login and gateway inference against a running instance.

What

  • New muse-code OAuth provider (src/lib/oauth/providers/muse-code.ts): RFC 8628 device authorization against auth.meta.com (bounded timeouts, no redirects, strict URL validation), server-side polling through the generic device tail with an allowlisted error-code set, then a key exchange at api.meta.ai/muse-code/key (onboard: true) for the subscription inference key.
  • Inference authenticates with the exchanged subscription key (accessToken — the default executor prefers it for OAuth connections). The device account token authorizes the exchange and is discarded, never persisted. No refresh-token grant exists: reconnect replaces the stored key (dedup by persisted accountId, mirroring the Codex rule).
  • Registry: baseUrl https://api.meta.ai/v1 + /responses suffix (shared by OAuth and existing API-key connections), live modelsUrl for entitled Spark discovery, and static Spark entries (1.1–1.3, base + Contributor) tagged openai-responses so Chat callers translate correctly; live discovery stays authoritative so unentitled ids are rejected.
  • Public device client_id embedded via resolvePublicCred("muse_id") per docs/security/PUBLIC_CREDS.md (no literal in source).
  • Dashboard: OAuth catalog entry (subscription-risk notice + Contributor training note), device-code panel, wizard allowlist, dual-auth counting, connection-test config, icon mapping. Existing API-key muse-code connections are untouched.
  • Errors from the key exchange never propagate response bodies (a success body carries the key itself).

Verification

  • New tests: device validation/poll/key-exchange/redaction/mapping (muse-code-oauth.test.ts), persist→reload→restart→discovery-URL→headers→reconnect→disconnect with redaction (muse-code-oauth-persistence.test.ts), Spark targetFormat + discovery config (muse-code-spark-targetformat.test.ts).
  • Updated oauth-providers-config.test.ts, publicCreds.test.ts, translate-path golden (muse-code URLs now resolve to the Responses endpoint).
  • Live upstream validation with operator browser approval: device code issued, approved, poll + key exchange succeeded, exchanged key returned HTTP 200 from /v1/models including muse-spark-1.3-contributor. No secrets printed or persisted.
  • Focused suites green (97 tests across all touched areas); typecheck:core clean; changed files lint/format clean.

Still to demonstrate

  • Dashboard device login against a running gateway with browser approval
  • Gateway restart, persisted-connection reload, discovery via OmniRoute routes
  • Minimal Spark inference through the gateway (not direct Meta calls)
  • CI failure triage against base-red 🔴 Release branch not green: release/v3.8.51 #13866 (all current failures classified: reproduce on pristine base or sit in untouched files with environmental causes)

⚠️ base-red inherited: #13866.

@caniko
caniko marked this pull request as draft September 20, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant