Skip to content

fix(oauth): bound unresolved refresh consumers independently of turns - #735

Open
luvs01 wants to merge 1 commit into
devfrom
codex/fix-oauth-refresh-consumers-20261014
Open

luvs01 wants to merge 1 commit into
devfrom
codex/fix-oauth-refresh-consumers-20261014

Conversation

@luvs01

@luvs01 luvs01 commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Preserve immediate active-turn release on client cancellation. Add an independent process-local limit of 256 unresolved OAuth refresh consumers, including callers joining an existing shared refresh. Each consumer keeps its reservation until its actual refresh wait settles, including on rejection.
  • Keep fresh cached credential reads outside this limit. Preserve the existing 32-flight limit, stale-flight handling, credential ownership and shared-refresh behavior. No request cancellation is allowed to cancel a refresh needed by other consumers.
  • Return a retryable HTTP 503 with Retry-After: 1 when initial Responses credential resolution reaches refresh capacity, rather than reporting a login failure. Request cancellation retains precedence, and capacity refusal does not quarantine credentials.
  • Add four production-resolver/handler regression cases to the existing OAuth suite and update the owning runtime contract. Exactly four files change.

This is a fork-only draft requested by the owner. Unlike the prior turn-lifetime proposal, this does not hold cancelled client-turn slots until upstream completion. It is a count bound on unresolved refresh consumers, not a global retained-byte bound or an unconditional refresh-duration guarantee. A nonsettling refresh can occupy finite refresh capacity, so independent operational review of the 256-consumer limit remains required.

Revision

Base: f5f73ff3970b3b238c4e2fade29ba3f64914f637.
Published head: ad6a49ef255493a6fa1db11ce29f5fca7bfcf2f5.
Exact tested/published tree: 080372791545407b96f6a0a4c204e445452a9553.

Changed files:

  • src/oauth/index.ts
  • src/server/responses/request-transport.ts
  • tests/oauth/oauth-refresh-generic-lock.test.ts
  • structure/runtime.md

The fresh source artifact was pinned to this base; tests used the repository-selected test runner Bun 1.4.3, not an older source snapshot. Auxiliary source-export, transport and publication files are absent from the candidate tree.

Verification — actual Linux / Bun 1.4.3

Focused aggregate: 165 passed, 0 failed, 1,851 assertions across eight files.

bun test --isolate --timeout 30000 tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-refresh.test.ts tests/oauth/oauth-status-privacy.test.ts tests/codex-integration/active-turn-disconnect.test.ts tests/codex-integration/active-registry-admission.test.ts tests/test-layout.test.ts tests/test-layout-tooling.test.ts tests/ci-workflows/file-size-ratchet.test.ts
bun node_modules/typescript/bin/tsc --noEmit
bun scripts/privacy-scan.ts
bun scripts/structure-ssot.ts
git diff --check

Root typecheck, privacy, structure and whitespace checks passed. The existing home/credential isolation and synthetic credential stores remain enabled; no real refresh credentials or live providers were used.

New coverage retains cancelled-but-pending resolver consumers under the separate gate, rejects excess consumers while reporting no retained client turns, exercises settlement and rejection cleanup, allows a fresh different credential under refresh pressure, and invokes the production Responses handler to verify retryable capacity refusal with no inference send. Existing disconnect and admission suites are included unchanged.

Red control: with the original resolver implementation restored and the new regression assertions retained, the selected three-case run produced 1 pass and 2 failures; the fresh-credential control already passed. Restoring the correction made the final aggregate above pass. This is deterministic accounting evidence, not a full end-to-end memory-exhaustion benchmark.

Publication run 38492130949 checked patch SHA-256, original preimages, the exact changed-file set and the complete resulting tree before atomically creating two new fork refs. No patched application code or dependency installation ran with its write token. This is transport verification, not another application test run.

Remaining gates

Full repository/import-connected coverage, live-provider refresh behavior, a complete HTTP/WebSocket resource-exhaustion run and native Windows/macOS acceptance were not executed. Focused coverage is the repository resource exception for this isolated executor. Current-head hosted CI and independent security/operational review remain required. Pending, skipped and older-head checks are not passes.

No upstream PR, merge, installation, deployment, live credential changes or Security Cloud finding closure is performed. Keep the finding open until a correction is integrated and verified.

Checklist

  • Scope stays focused and preserves release-on-cancel behavior.
  • Owning documentation records the consumer limit and its lifetime.
  • Focused repository regressions and root static gates passed on the published source tree.
  • Independent security and operational review is complete.
  • Required current-head hosted CI and remaining coverage are accepted.

Review readiness checklist

  • Required final validation and its scope are accepted.
  • Current dev ancestry is rechecked before readiness.
  • All correct review findings are resolved.
  • Ready for review. Retain draft pending the outstanding gates.

Summary by CodeRabbit

  • Reliability
    • OAuth token refreshes now have a limit on pending requests. When capacity is reached, affected requests receive a temporary service-unavailable response with a one-second retry interval.
    • Requests using fresh credentials can continue while refresh capacity is full, and failed refreshes release capacity for future attempts.

Publish the exact locally tested candidate tree. See the draft PR for
focused validation, remaining native/operational coverage and acceptance holds.
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: luvs01/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: ad64628a-13a0-4e43-9095-cb81d4737d43
📥 Commits

Reviewing files that changed from the base of the PR and between 9b31677 and ad6a49e.

📒 Files selected for processing: 4
  • src/oauth/index.ts
  • src/server/responses/request-transport.ts
  • structure/runtime.md
  • tests/oauth/oauth-refresh-generic-lock.test.ts

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

📝 Walkthrough

OAuth refresh resolution now limits pending consumers to 256, including callers joining an active refresh. Responses transport returns a retryable 503 when capacity is exhausted. Tests cover admission, cancellation, retries, fresh credentials, and the Responses error path.

Changes: OAuth refresh waiter admission

Layer / File(s) Summary
Limit OAuth refresh consumers
src/oauth/index.ts, tests/oauth/oauth-refresh-generic-lock.test.ts
src/oauth/index.ts (lines 135–137, 615–660) adds the shared 256-waiter limit and requires each caller to acquire a permit. Tests (lines 413–503) cover cancellation, saturation, release after failure, retry, and access to fresh credentials.
Handle refresh capacity exhaustion
src/server/responses/request-transport.ts, structure/runtime.md, tests/oauth/oauth-refresh-generic-lock.test.ts
request-transport.ts (lines 968–971) returns a cancellation response for aborted requests or HTTP 503 with retry-after: 1 for capacity errors. The runtime documentation (line 33) records the limit and its behavior. The integration test (lines 507–537) checks the 503 response and confirms that inference is not sent and reauthentication is not set.

Priority: ⬇️ Low

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

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ResponsesTransport
  participant OAuthResolver
  participant AdmissionGate
  ResponsesTransport->>OAuthResolver: Resolve OAuth credentials
  OAuthResolver->>AdmissionGate: Acquire waiter permit
  AdmissionGate-->>OAuthResolver: Return capacity error
  OAuthResolver-->>ResponsesTransport: Raise OAuthTokenRefreshBusyError
  ResponsesTransport-->>ResponsesTransport: Return HTTP 503 with retry-after: 1
Loading

Suggested reviewers: lidge-jun

Merge Risk: ⚪ Minimal · up to ad6a4

No identified issue prevents merging after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed 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 3 functions across 3 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed 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 main change: limiting unresolved OAuth refresh consumers independently from the existing turn limit.
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 3 functions across 3 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ 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
  • Autofix · 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

Copy link
Copy Markdown

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Oct 14, 2026
@luvs01
luvs01 marked this pull request as ready for review October 14, 2026 01:10
@luvs01

luvs01 commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

This branch has not been deployed

No deployments
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