Skip to content

test: cover ensureFreshAccessToken refresh, cooldown, and dedup paths#571

Merged
ndycode merged 2 commits into
mainfrom
claude/audit-52-rotation-token-refresh-tests
Jun 11, 2026
Merged

test: cover ensureFreshAccessToken refresh, cooldown, and dedup paths#571
ndycode merged 2 commits into
mainfrom
claude/audit-52-rotation-token-refresh-tests

Conversation

@ndycode

@ndycode ndycode commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Eleventh suite in the direct-coverage wave (siblings: #559#561, #563#567, #569, #570; all independent, based on main). lib/runtime/rotation-token-refresh.ts decides on the proxy hot path whether an account's token is usable, refreshes it through the queue, and applies the auth-failure cooldowns — including the issue #495 invalidation handling. This adds test/rotation-token-refresh.test.ts (9 tests).

Like #570, the suite drives a real AccountManager — the cooldown bookkeeping, commitRefreshedAuth's snapshot/rollback machinery, and the live in-memory pool all run. Only queuedRefresh and the storage-transaction seam are mocked, and the real isTokenInvalidationError/isTokenRefreshRetryable predicates classify the failures.

What the tests pin

  • Fresh-token short-circuit: a token outside the skew window is used as-is, with no refresh-queue call.
  • Rotate-and-commit: a stale token refreshes and the rotated credentials land in both the result and the in-memory pool.
  • Concurrent-commit dedup: two callers refreshing the same account share one in-flight commitRefreshedAuth and both receive the committed token (the transaction is gated open so the dedup window genuinely exists during the test).
  • Failure taxonomy: a 401 with a generic message → 30s auth-failure cooldown, retryable: false, invalidated: false; a network error → retryable: true; an explicit "OAuth token has been invalidated" body → the long invalidation cooldown plus invalidated: true, telling the caller to stop rotating instead of parading other accounts' tokens from the same IP (issue Rotation gateway triggers mass OAuth token invalidation across accounts #495).
  • Monotonic cooldown guard: a later generic 30s failure must never truncate a concurrent 5-minute invalidation cooldown; applyMonotonicAuthCooldown only ever extends deadlines.
  • Commit failure: a failed persistence cools the account down and reports retryable: true with the rollback machinery exercised.

Validation

  • vitest run test/rotation-token-refresh.test.ts — 9/9 passing
  • npm run typecheck — clean
  • npx eslint test/rotation-token-refresh.test.ts --max-warnings=0 — clean

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB


Generated by Claude Code

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

adds test/rotation-token-refresh.test.ts with 9 tests for ensureFreshAccessToken and applyMonotonicAuthCooldown, driving a real AccountManager with only queuedRefresh and the storage-transaction seam mocked.

  • fresh-token short-circuit, rotate-and-commit, concurrent dedup, commit-null fallback — all four success-path branches are now pinned, including the previously-flagged null-return fallback added in this PR.
  • failure taxonomy — non-retryable 401, retryable network error, invalidation cooldown with invalidated: true, monotonic guard, and commit-exception paths are all covered with real isTokenInvalidationError/isTokenRefreshRetryable predicates classifying the failures.
  • the dedup test correctly gates withAccountStorageTransaction so both concurrent callers genuinely overlap in the in-flight window before the gate opens.

Confidence Score: 5/5

test-only PR adding 9 vitest tests with no production code changes; safe to merge

the change is purely additive test code. all 9 tests drive the real AccountManager and pass according to the author's validation run. the two notes above are minor gaps in assertion coverage that leave some production behaviors under-pinned but do not introduce regressions.

no files require special attention; all changes are in the test file

Important Files Changed

Filename Overview
test/rotation-token-refresh.test.ts new test suite covering 9 paths through ensureFreshAccessToken and applyMonotonicAuthCooldown; well-structured with real AccountManager; minor coverage gaps in side-effect assertions for failure paths

Sequence Diagram

sequenceDiagram
    participant T as Test
    participant E as ensureFreshAccessToken
    participant Q as queuedRefresh (mock)
    participant D as commitRefreshedAuthOnce
    participant C as AccountManager.commitRefreshedAuth
    participant S as withAccountStorageTransaction (mock)

    T->>E: params (stale token)
    E->>E: hasUsableAccessToken → false
    E->>Q: queuedRefresh(refreshToken)
    Q-->>E: "{type:success, access:access-new}"
    E->>D: commitRefreshedAuthOnce(manager, account, auth)
    D->>C: accountManager.commitRefreshedAuth(account, auth)
    C->>S: withAccountStorageTransaction(handler)
    S-->>C: handler(null, persist)
    C-->>D: liveAccount (updated in-memory)
    D-->>E: liveAccount
    E-->>T: "{ok:true, accessToken:access-new, account}"

    Note over D: dedup: 2nd concurrent caller returns same in-flight promise
    Note over E: on failure: applyMonotonicAuthCooldown only extends, never shortens
Loading

Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
test/rotation-token-refresh.test.ts:183-211
**failure side-effects not asserted in three failure tests**

the three refresh-failure tests (`non-retryable auth failure`, `marks transient failures retryable`, `revoked token`) assert on the `result` shape and `coolingDownUntil`, but none assert that `accountManager.recordFailure` and `accountManager.incrementAuthFailures` were called. if either call is accidentally removed from the `refreshResult.type === "failed"` branch in `rotation-token-refresh.ts`, the suite stays green while health-tracking and auth-failure counters stop updating silently. spying on both methods in these tests would pin the full side-effect contract.

### Issue 2 of 2
test/rotation-token-refresh.test.ts:156-181
**dedup test does not assert queuedRefresh is called twice**

by design, `queuedRefresh` is not deduplicated here — only the commit step is. two independent callers each issue their own `queuedRefresh`, and the dedup queue merges only the `commitRefreshedAuth` leg. the test correctly checks `commit` called once, but adding `expect(queuedRefreshMock).toHaveBeenCalledTimes(2)` would document and lock down that intentional difference so future refactors don't accidentally merge the refresh calls too.

Reviews (2): Last reviewed commit: "test: cover the commit-null token fallba..." | Re-trigger Greptile

Direct coverage for the phase-2-extracted rotation token-refresh
helper, driven through a REAL AccountManager (cooldown bookkeeping,
commitRefreshedAuth rollback machinery, and the live in-memory pool
all run; only the refresh queue and the storage transaction seam are
mocked):

- a fresh token short-circuits without touching the refresh queue
- a stale token refreshes and the rotated credentials land in both
  the result and the in-memory pool
- concurrent callers share one in-flight commit (gated transaction so
  the dedup window is actually open) and receive the same token
- a non-retryable 401 applies the 30s auth-failure cooldown and
  reports retryable=false, invalidated=false; a network error reports
  retryable=true
- an explicit revocation message applies the long invalidation
  cooldown and signals invalidated=true (issue #495)
- the monotonic guard never lets a later 30s generic failure truncate
  a concurrent 5-minute invalidation cooldown, and
  applyMonotonicAuthCooldown only ever extends deadlines
- a failed commit cools the account down and stays retryable

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ndycode, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 9 minutes and 25 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bcc3095e-b2d3-4d41-b0c5-0f789a5792c1

📥 Commits

Reviewing files that changed from the base of the PR and between b566656 and 9480f3f.

📒 Files selected for processing (1)
  • test/rotation-token-refresh.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/audit-52-rotation-token-refresh-tests
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/audit-52-rotation-token-refresh-tests

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 and usage tips.

Comment thread test/rotation-token-refresh.test.ts
When commitRefreshedAuth cannot resolve the account after persist it
returns null, and the caller must fall back to the refresh result's
access token (never the stale token on the original account object,
which would 401 downstream and falsely trigger invalidation cooldown).

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
@ndycode ndycode merged commit 5ddd970 into main Jun 11, 2026
2 checks passed
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.

2 participants