Skip to content

fix(oauth): take over a lapsed refresh lease, share overlapping service-account key reads, and label unsearched accounts - #9537

Merged
waleedlatif1 merged 5 commits into
stagingfrom
fix/refresh-and-live-search-audit
Oct 31, 2026
Merged

waleedlatif1 merged 5 commits into
stagingfrom
fix/refresh-and-live-search-audit

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Follow-ups from a release audit of #9509 (OAuth refresh-ahead) and #9514 (live search latency), rebased on #9528's five-minute floor.

  • A follower takes over a lease its leader left to lapse.
    • The problem: a refresh can be abandoned with its process, as a Trigger.dev run does with detached work. Its leader lease then stays held until the TTL. A caller that has to wait (5 minutes or less left) followed that dead lease for the full wait and got no token.
    • The fix: withLeaderLock now tries the lock once more when a follower's wait and its last read both come up empty. If the follower wins, it leads the refresh itself. If it loses, a live holder has the lease, and it returns null as before.
    • This works for every provider and keeps fix(oauth): keep a five-minute floor on served tokens and refresh ahead earlier #9528's guarantee that a served token has at least five minutes left. Nothing serves a stored token below that floor.
  • The leader re-reads the dead flag under the lock, so taking over after a leader failed terminally never calls the provider again with a dead chain.
  • The refresh settle timeout now covers the follower wait plus one takeover lead. Before, the 30s coalesce timeout always fired before the follower's own 30s wait ended, so the follower's last read never counted. The timeout is derived from the lease constants.
  • Overlapping service-account key reads are shared.
    • Google delegation mints one token per subject concurrently, and each mint read and decrypted the same credential row.
    • Concurrent reads now go through coalesceLocally. A later mint still reads again, so revocation is re-checked on every mint.
    • A caller that joins a shared read can still cancel its own wait.
  • Accounts that were never searched are labelled accurately in diagnostics. They get an internal not_started reason instead of a provider timeout with provider_validation. The status and message users see are unchanged.
  • Doc fixes:
    • The refresh-ahead safety note now states only what Google and Microsoft document.
    • refresh-or-reuse now names Instagram as its only user.
    • The account-open concurrency note describes the shared key read.

Type of Change

  • Bug fix

Testing

New tests; each fails on the code before it:

  • Leader lock:
    • A follower whose leader vanished takes over once and leads.
    • A follower that loses the race returns null.
  • Orphaned lease:
    • Google and a non-allowlisted provider both get a freshly refreshed token, with one provider call.
    • A live holder yields no token, never a stored one.
    • The takeover finishes before the settle timeout.
    • Taking over after a dead flag makes no provider call.
    • A hung in-process leader is bounded by the settle timeout.
  • Account gone and dead flag: both fail even with ample validity left.
  • Service-account key: concurrent mints share one key read, and a cancelled mint stops waiting while the others finish.
  • Diagnostics: an account that was never searched is logged as not_started.
  • createConcurrencyLimit: FIFO order, peak never above the limit, and the slot is released on a throw.
  • Live search sessions: a session that never opens frees its slot, and a session that opens late is closed.

Checks run:

  • Targeted suites pass: lib/oauth, lib/concurrency, lib/sim-search/live, lib/knowledge/search, lib/core/utils.
  • bun run lint, type-check and check:audits pass.
  • The full suite runs 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.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 31, 2026 7:14pm UTC

Request Review

@greptile-apps

greptile-apps Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

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

Summary

The PR lets a waiting OAuth caller take over an expired refresh lease, shares overlapping service-account key reads, and labels accounts that never started searching.

  • OAuth callers can take over a refresh lease left by a departed process.
  • Concurrent Google service-account mints share one credential-key read.
  • Live-search diagnostics mark accounts that never started as not_started.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[OAuth refresh requested] --> B{Lock acquired?}
  B -->|Yes| C[Read current state and refresh]
  B -->|No| D[Poll stored result]
  D --> E{Result available?}
  E -->|Yes| F[Return result]
  E -->|No, wait ended| G{Acquire lock again?}
  G -->|Yes| C
  G -->|No| H[Return no result]
  C --> I[Save with refresh-token guard]
  I --> J[Release owned lock]
Loading

Reviews (4) · Last reviewed commit: "fix(oauth): take over a lapsed refresh l..." · Reviewed by Greptile

@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.

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@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.

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@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

…re overlapping service-account reads, and label unsearched accounts
…a held lease

- A failed blocking refresh now falls back to the stored token only on a distinct
  lease-held outcome: this caller followed another lease holder for its whole wait, its
  last read still found the chain it started from, and no leader flagged it dead. A dead
  flag, a terminal refresh error, a vanished account or a leader exception stay failures.
- The in-process refresh settles after the follower's full wait plus headroom instead of
  the default 30s, which fired before the follower's last read could count; a leader hung
  in this process still fails its callers, now at that bound.
…tored token

- A follower whose wait ends with nothing now tries the lock once more: a leader whose process
  died leaves its lease to lapse, and the follower leads the refresh instead of failing. Losing
  that try still returns nothing.
- Drops the stored-token fallback and its lease-held outcome, which served tokens below the
  five-minute floor a served token keeps.
- The leader rereads the dead flag under the lock, so a follower taking over after a leader
  that failed terminally does not call the provider again.
- The in-process refresh settles after the follower wait plus a full leader run and headroom.
@waleedlatif1
waleedlatif1 force-pushed the fix/refresh-and-live-search-audit branch from 905e9fd to 59bc945 Compare October 31, 2026 19:14
@waleedlatif1 waleedlatif1 changed the title fix(search): keep a valid token when a refresh lease is orphaned, share overlapping service-account reads, and label unsearched accounts fix(oauth): take over a lapsed refresh lease, share overlapping service-account key reads, and label unsearched accounts Oct 31, 2026
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@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 8 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

@waleedlatif1
waleedlatif1 merged commit a502fb2 into staging Oct 31, 2026
70 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/refresh-and-live-search-audit branch October 31, 2026 21:38

This branch was previously deployed

1 inactive deployment
Preview — 59bc9459 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