Skip to content

fix(oauth,settings): forward upstream oauth error contract and persist recovered config - #331

Merged
chriswritescode-dev merged 3 commits into
mainfrom
fix/oauth-error-categories
Jul 28, 2026
Merged

fix(oauth,settings): forward upstream oauth error contract and persist recovered config#331
chriswritescode-dev merged 3 commits into
mainfrom
fix/oauth-error-categories

Conversation

@chriswritescode-dev

@chriswritescode-devchriswritescode-dev commented Jul 28, 2026

Copy link
Copy Markdown
Owner

The OAuth route collapsed every upstream failure into a single generic message and matched invented substrings opencode never emits, leaving the frontend error map unreachable. Model opencode's structured ProviderAuthError / InvalidRequestError contract in @opencode-manager/shared, discriminate by name/_tag, and forward the exact code plus upstream detail so clients can map precisely. Pin the contract to @opencode-ai/sdk with a compile-time conformance assertion.

Separately, applying a default config with auto-removed fields wrote the stripped content to disk but left the stored record holding the rejected fields, so disk and database disagreed. Persist the applied content, return 409 when the config disappears mid-recovery, and accept provider-level api/npm/whitelist/blacklist fields so valid opencode provider configs survive a parse round-trip.

Summary

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Documentation

Checklist

  • Code follows project style (no comments, named imports)
  • TypeScript types are properly defined
  • Tests added/updated (80% coverage target)
  • pnpm lint passes locally
  • pnpm typecheck passes locally

Summary by CodeRabbit

  • New Features

    • Added support for provider API URLs, package identifiers, and model allowlists/blocklists in provider configuration.
    • OAuth authorization and callback errors now provide clearer, structured messages and validation details.
  • Bug Fixes

    • Improved OAuth error handling for unexpected upstream responses.
    • Recovered configuration changes are now saved consistently, including safeguards for concurrent removal.
  • Tests

    • Expanded coverage for OAuth flows, provider configuration preservation, and recovery scenarios.

The route boundary collapsed every upstream OAuth failure into a single
generic message, leaving all six mappings in the frontend's mapOAuthError
unreachable. Classify the failure and forward the matched category so
clients surface specific guidance.
Hoist the category list into @opencode-manager/shared as the single source
of truth for both sides; the frontend map is now typed
Record<OAuthErrorCategory, string> so a missing message fails typecheck.
…bstrings
The previous mapping matched invented substrings ("invalid code", "expired",
"access denied", ...) that opencode never emits, so every real failure fell
through to the generic message and left the frontend map unreachable. It also
returned 500 for what upstream reports as 400.
opencode serialises these failures as a structured contract: ProviderAuthError
({ name, data }) or InvalidRequestError ({ _tag, message }) at HTTP 400. Model
both shapes in shared, discriminate on name/_tag, and forward the exact code
plus upstream detail so clients can map errors precisely.
Pin the contract to upstream with a compile-time conformance assertion against
@opencode-ai/sdk's generated ProviderOauthAuthorizeErrors[400] and
ProviderOauthCallbackErrors[400], added as a type-only devDependency. Any
added, removed, renamed, or retyped upstream variant now fails typecheck.
Also stop discarding the structured error at the frontend boundary, where
handleApiError rewrapped FetchError in a bare Error and dropped the code that
fetchWrapper had already parsed.
Verified against a live opencode 1.18.7 server: callback without a pending
authorization returns 400 ProviderAuthOauthMissing and is now forwarded as
such. Tests are pinned to captured responses, including the multiline message
BadRequest carries.
…api/npm fields
Applying a default config with auto-removed fields wrote the stripped content
to disk but left the stored record holding the rejected fields, so the database
and the on-disk config disagreed until the next write. Persist the applied
content and return 409 when the config disappears mid-recovery.
Add the provider-level api, npm, whitelist, and blacklist fields so valid
opencode provider configs survive a parse round-trip instead of being stripped.
@coderabbitai

coderabbitaiBot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 353b3140-df89-45ee-bd4a-c67f7aaa6bf1

📥 Commits

Reviewing files that changed from the base of the PR and between e97ef8e and f5500bf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • backend/src/routes/oauth.test.ts
  • backend/src/routes/oauth.ts
  • backend/src/routes/settings.ts
  • backend/test/routes/settings.test.ts
  • backend/test/services/opencode-config-provider-schema.test.ts
  • frontend/src/api/oauth.ts
  • frontend/src/lib/oauthErrors.test.ts
  • frontend/src/lib/oauthErrors.ts
  • shared/package.json
  • shared/src/schemas/auth.ts
  • shared/src/schemas/settings.ts

📝 Walkthrough

Walkthrough

OAuth failures now use shared typed contracts, backend status/detail translation, and frontend code-based messages. Provider configuration schemas preserve additional fields, while recovered default-config updates persist sanitized content and handle concurrent removal with 409.

Changes

OAuth error flow

Layer / File(s)Summary
OAuth contract and backend translation
shared/package.json, shared/src/schemas/auth.ts, backend/src/routes/oauth.ts, backend/src/routes/oauth.test.ts
Shared OAuth error schemas and codes support backend parsing, status normalization, detail formatting, and authorize/callback error responses.
Frontend OAuth error mapping
frontend/src/api/oauth.ts, frontend/src/lib/oauthErrors.ts, frontend/src/lib/oauthErrors.test.ts
OAuth API methods expose fetch errors directly, while recognized OAuth codes map to typed messages with optional upstream detail.

Configuration management

Layer / File(s)Summary
Provider configuration schema
shared/src/schemas/settings.ts, backend/test/services/opencode-config-provider-schema.test.ts
Provider schemas accept and preserve API, NPM, whitelist, and blacklist fields.
Recovered configuration persistence
backend/src/routes/settings.ts, backend/test/routes/settings.test.ts
Recovered default-config content is persisted, and concurrent removal returns 409 with the recovered-field update attempted.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
participant OAuthClient
participant oauthApi
participant OAuthRoutes
participant openCodeClient
OAuthClient->>oauthApi: Start authorize or callback request
oauthApi->>OAuthRoutes: Send OAuth payload
OAuthRoutes->>openCodeClient: Forward OAuth operation
openCodeClient-->>OAuthRoutes: Return upstream response
OAuthRoutes-->>oauthApi: Return success or structured failure
oauthApi-->>OAuthClient: Expose response or FetchError
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/oauth-error-categories

Comment @coderabbitai help to get the list of available commands.

@chriswritescode-dev
chriswritescode-dev merged commit 29f154a into mainJul 28, 2026
1 of 2 checks passed
@chriswritescode-dev
chriswritescode-dev deleted the fix/oauth-error-categories branch August 10, 2026 14:42
Sign up for freeto 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

@chriswritescode-dev