Skip to content

fix(oauth): bound and classify ChatGPT token refresh failures - #6792

Merged
lidge-jun merged 1 commit into
devfrom
codex/auth-quota-carry
Oct 9, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/auth-quota-carry

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

The registered ChatGPT OAuth refresh provider dropped caller cancellation, had no fetch deadline, read token-endpoint bodies without a size bound, and classified refresh failures incompletely, so a stalled token service could hang a refresh and some failures could be treated the wrong way. This carries #6745 by @luvs01 onto current dev (after #6743's registry refactor) and adds the fixes found in review.

  • Browser token exchange and refresh compose the caller's cancellation with a fresh 30-second per-fetch deadline that covers headers and body. Each settled call removes its caller listener and clears its timer.
  • Error bodies are read through a bounded reader capped at 16 KiB and success JSON at 64 KiB; cancellation during a body read is propagated instead of becoming an unknown HTTP error.
  • ChatGptTokenError carries HTTP status and an allowlisted OAuth code. A failure is terminal only when an allowlisted terminal grant code is present (flat or nested invalid_grant, refresh_token_reused, refresh_token_invalidated, token_invalidated, refresh_token_expired); provider free-text such as error_description or a nested error.message never forces re-login. Terminal refusals mark only the matching credential generation needsReauth, so a refresh that fails after the credential was replaced cannot quarantine the replacement. The shared Codex classifier in src/codex/chatgpt-refresh-failure.ts is unchanged for its other callers.
  • Cancellation, deadline, transport and parse failures surface as fixed-message errors (AbortError/TimeoutError/generic) without the raw reason or cause, and never mark reauthentication. The registry's own stale-flight OAuthTokenRefreshStaleError path is preserved.
  • Updates the OAuth contract in structure/providers-and-adapters.md and the accounts reference page.

Carries #6745. Plan and review record: devlog/_plan/261009_L5-auth-quota/.

Co-authored-by: 김상훈 luvs01@hanmail.net

Verification

  • bun test tests/oauth/chatgpt-token-expiry.test.ts tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/chatgpt-device-auth.test.ts tests/oauth/chatgpt-token-boundaries.test.ts tests/codex-integration/codex-account-store-refresh-classification.test.ts tests/codex-integration/codex-main-account-refresh.test.ts tests/ci-workflows/file-size-ratchet.test.ts tests/test-layout.test.ts tests/test-layout-tooling.test.ts tests/lab/core-lab-boundary.test.ts → 162 pass, 0 fail.
  • Regressions for description-only, blank-code and nested message-only refusals failed before the terminality fix (5 fail) and pass now; flat and nested grant codes stay terminal.
  • New tests/oauth/chatgpt-token-boundaries.test.ts (registered in both layout files) covers headers-then-stalled-body deadlines, cancellation during body reads, byte ceilings, and an instrumented caller signal asserting zero outstanding listeners after success, HTTP failure, timeout, transport failure and parse failure.
  • bun run typecheck, bun run privacy:scan, bun run structure:check → pass.
  • Full bun run test and the docs-site build were not run locally (minimal local testing for this lane; several worktrees share the machine). Both are left to exact-head hosted CI. All token-endpoint responses in tests are synthetic; no real credentials or accounts were used.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults. (Independent security review of the auth boundary passed after one round of fixes; explicit maintainer security review per MAINTAINERS.md still applies before merge.)

Summary by CodeRabbit

  • Bug Fixes
    • ChatGPT sign-in and token refresh requests now time out instead of hanging indefinitely and respond to cancellation.
    • Temporary network, timeout, and cancellation failures no longer incorrectly require users to reauthenticate. Sensitive details are omitted from error messages.
  • Documentation
    • Updated provider sign-in guidance to explain reauthentication conditions, request timeouts, and the information shown for different errors.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 9, 2026 01:54
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T01:56:57.713449Z 2c0fc34 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: e911d7ce-8f96-44e0-ac6e-21198d8b5adf
📥 Commits

Reviewing files that changed from the base of the PR and between 2c0fc34 and e5da7e4.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: c03dac2c-a14e-4784-82d3-91fdb8aed3d6
📥 Commits

Reviewing files that changed from the base of the PR and between c15037b and 2c0fc34.

📒 Files selected for processing (12)
  • devlog/_plan/261009_L5-auth-quota/000_roadmap.md
  • devlog/_plan/261009_L5-auth-quota/010_ollama_balance_quota.md
  • devlog/_plan/261009_L5-auth-quota/020_chatgpt_refresh_hardening.md
  • docs-site/src/content/docs/reference/cli/providers-accounts.md
  • scripts/test-layout/layout.json
  • src/oauth/chatgpt.ts
  • src/oauth/index.ts
  • structure/providers-and-adapters.md
  • tests/fixtures/test-layout-expected.json
  • tests/oauth/chatgpt-token-boundaries.test.ts
  • tests/oauth/chatgpt-token-expiry.test.ts
  • tests/oauth/oauth-refresh-generic-lock.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

ChatGPT OAuth token exchange and refresh now use bounded requests with deadlines, cancellation handling, and sanitized errors. Provider refresh uses explicit terminal error classification. Tests and documentation cover these changes. Planning documents record the related carry PR scope and verification.

Changes

ChatGPT OAuth hardening

Layer / File(s) Summary
Bounded token requests
src/oauth/chatgpt.ts, devlog/_plan/261009_L5-auth-quota/020_chatgpt_refresh_hardening.md
Token exchange and refresh use a shared request helper. It applies a 30-second default deadline, limits success and error bodies, forwards caller cancellation, and returns sanitized errors. Refresh accepts a timeout override.
Provider refresh classification
src/oauth/index.ts, tests/oauth/oauth-refresh-generic-lock.test.ts
The provider forwards its AbortSignal. Request errors are non-terminal, while HTTP token errors use their terminal verdict. Tests cover terminal and retryable responses, stale flights, and late responses for replaced credentials.
Boundary tests and documentation
tests/oauth/chatgpt-token-boundaries.test.ts, tests/oauth/chatgpt-token-expiry.test.ts, docs-site/src/content/docs/reference/cli/providers-accounts.md, scripts/test-layout/layout.json, tests/fixtures/test-layout-expected.json, structure/providers-and-adapters.md, devlog/_plan/261009_L5-auth-quota/020_chatgpt_refresh_hardening.md
Tests cover body limits, cancellation, timeouts, cleanup, and error redaction. The CLI documentation and OAuth responsibility entry describe the request limits and error handling. The test-layout records include the new boundary test file.

Carry-PR planning

Layer / File(s) Summary
Roadmap and Ollama quota plan
devlog/_plan/261009_L5-auth-quota/000_roadmap.md, devlog/_plan/261009_L5-auth-quota/010_ollama_balance_quota.md
The roadmap records work order, verification conditions, and audit notes for the two carry PRs. The Ollama plan describes /api/balance and /api/usage endpoint handling and planned acceptance checks; it does not add the implementation.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Provider as ChatGPT registered provider
  participant Refresh as refreshChatGPTToken
  participant Request as bounded token-request helper
  participant Endpoint as OAuth endpoint
  Provider->>Refresh: refresh token and AbortSignal
  Refresh->>Request: form request and timeout option
  Request->>Endpoint: fetch with caller cancellation and deadline
  Endpoint-->>Request: headers and response body
  Request-->>Refresh: bounded response or sanitized error
  Refresh-->>Provider: token result or classified error
Loading

Merge Risk: ⚪ Minimal · up to 2c0fc

No confirmed merge-blocking issue remains; the planned exact-head checks can proceed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 5 files. (7 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the primary change: bounded requests and failure classification for ChatGPT OAuth token refresh. It matches the main implementation and test changes.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 5 files. (7 skipped: 7 unsupported.)

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Oct 9, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c0fc34c84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread devlog/_plan/261009_L5-auth-quota/020_chatgpt_refresh_hardening.md Outdated
@lidge-jun
lidge-jun force-pushed the codex/auth-quota-carry branch from 2c0fc34 to d9f3991 Compare October 9, 2026 02:08
Carry #6745 onto current OAuth refresh coordination.
Sanitize cancellation and transport failures, bound token bodies and deadlines,
and cover listener cleanup, generation fences and recovery regressions.

Carries #6745.

Co-authored-by: 김상훈 <luvs01@hanmail.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant