Skip to content

improvement(oauth): serve still-valid tokens while refreshing ahead of expiry - #9509

Merged
waleedlatif1 merged 1 commit into
stagingfrom
improvement/oauth-refresh-ahead
Oct 31, 2026
Merged

waleedlatif1 merged 1 commit into
stagingfrom
improvement/oauth-refresh-ahead

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Every caller inside the 5-minute OAuth refresh window blocked on the provider refresh, even though its access token was still valid for minutes. Polls, workflow tools, selectors and live search all paid that wait, and a stalled refresh held them for up to 30s
  • One decision, planAccessTokenRefresh, replaces the three copies in getOAuthToken, resolveCredentialTokenBundle and refreshTokenIfNeeded:
    • For Google and Microsoft providers with more than 2 minutes left, the caller gets the still-valid token now and the existing coalesced refresh runs in the background. These providers keep a refreshed-away access token valid and the old refresh token usable, so an abandoned refresh loses nothing
    • The start of the window is jittered per account, so credentials that expire together don't refresh together
  • Every other provider, and any token with 2 minutes or less left, waits exactly as before. Rotation guards, revocation-against-version, dead flags, the leader lock, Microsoft refresh-token aging and Instagram renewal are unchanged
  • resolveCredentialTokenBundle's existing signal now also stops a caller waiting on a shared OAuth refresh (via waitWithAbort), without cancelling the refresh for anyone else
  • Live search passes its deadline signal into account resolution, so a hung token resolution can no longer hold a 20s search past its deadline. Document reads now start their 15s deadline before resolving the account

Type of Change

  • Bug fix

Testing

  • New tests, each failing on staging:
    • A Google token with 4 minutes left returns at once while the provider is still pending, and the background refresh then rotates the row
    • The headroom table runs per reader
    • A cancelled caller stops waiting while a concurrent caller still gets the refreshed token, with one provider call
    • Live search settles by its 20s deadline, and reads by 15s, when token resolution never settles
  • Guards proven by breaking the code: providers outside Google/Microsoft and tokens under the 2-minute floor still wait
  • lib/oauth, lib/sim-search/live, lib/concurrency and app/api/auth/oauth all pass (827 tests). bun run lint, block registry check, type-check and check:audits pass, except check:unused-exports, which flags an apps/docs generated import not built in a local checkout
  • Integration suites (credential-revocation, shopify, managed-mcp, provider-discovery) and the full test suite run in CI

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Oct 31, 2026 8:15am UTC

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 6 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] This PR appears safe to merge; no actionable issues were found.

Summary

This PR shares the refresh decision across three OAuth token readers.

  • Google and Microsoft callers get valid tokens while refresh runs.
  • Live searches and reads stop waiting when account resolution hits its deadline.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Read stored token] --> B{Refresh needed?}
  B -->|No| C[Return stored token]
  B -->|Yes| D{Google or Microsoft with enough time left?}
  D -->|Yes| E[Start shared background refresh]
  E --> C
  D -->|No| F[Wait for shared refresh]
  F --> G{Caller cancels?}
  G -->|Yes| H[Stop this caller's wait]
  G -->|No| I[Return refresh result]
  H --> J[Shared refresh keeps running]
Loading

Reviews (1) · Last reviewed commit: "improvement(oauth): serve still-valid to..." · Reviewed by Greptile

This branch was successfully deployed

1 active deployment
Preview — eb55d0b5 Deployed Oct 31, 2026 by vercel[bot]
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