Repository navigation
fix(oauth): parse numeric-epoch expiresAt on the request-time refresh path - #16621
Merged
diegosouzapw merged 2 commits intoOct 15, 2026
Merged
Conversation
… path
expires_at is a TEXT column, so a numeric epoch written by an external
import reads back as a string and `new Date("1789012345678")` is an
Invalid Date. The background sweep already handled this through
parseTokenExpiryMs, but the three request-time paths did not:
- checkAndRefreshToken: a numeric string gave NaN, so the proactive
refresh never fired; an epoch-seconds number was read as ms (1970),
so it refreshed on every request.
- BaseExecutor.needsRefresh: same defect.
- the stale-token-from-DB check in getAccessToken: NaN discarded a
still-valid rotated DB token and issued a needless OAuth refresh.
All three now go through parseTokenExpiryMs; an unparseable or missing
expiry (0) never triggers a refresh, and ISO values behave as before.
Co-authored-by: Eliel Sousa <eliel@pathbit.co>
Inspired-by: decolua/9router#3997
Contributor
CI Coverage Report
Coverage artifact was not available for this run. |
diegosouzapw
added a commit
that referenced
this pull request
Oct 15, 2026
## Summary - Re-measure the five files this owner merge-batch pushed over the frozen ceilings, on release/v3.8.52 at d50cd80. No slack. - `open-sse/executors/base.ts` 1743→1745 (#16621), `open-sse/handlers/chatCore/streamingResponse.ts` 1308→1309 (#16705), `open-sse/handlers/chatCore.ts` 3938→3943 (#16720), `open-sse/translator/response/openai-responses.ts` 1547→1590 (#16645), `tests/unit/provider-validation-specialty.test.ts` 2912→2965 (#16625). - `node scripts/check/check-file-size.mjs` exits 0 on this branch. README drift (#16132) and the inherited doc-source drift were not stamped.⚠️ base-red inherited: #15306 Thanks @diegosouzapw.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
expiresAt(seconds or ms, as a number or as the string a TEXT column returns) the same way the background token sweep already does.Attribution
Thanks to @elielsousa-pathbit for the original implementation.
Changes
src/sse/services/tokenRefresh.ts—checkAndRefreshTokenusesparseTokenExpiryMs()and skips the regular-token check when the result is0.open-sse/executors/base.ts—BaseExecutor.needsRefreshusesparseTokenExpiryMs();<= 0means no refresh.open-sse/services/tokenRefresh.ts— the stale-token-from-DB check (_refreshWithFreshCredentials) usesparseTokenExpiryMs()fordbExpiresAt.src/lib/tokenHealthCheckExpiry.ts::parseTokenExpiryMs, which has no imports, so no import cycle is added. No new helper, no contract change.tests/unit/oauth-expiry-numeric-epoch-request-path.test.ts— 7 new regression tests.Test plan
ℹ tests 7 ℹ pass 2 ℹ fail 5. The two passing tests are the ISO/unknown-expiry controls. After the fix →ℹ tests 7 ℹ pass 7 ℹ fail 0.checkAndRefreshToken/needsRefresh/getAccessToken/parseTokenExpiryMs/executors/base.ts/services/tokenRefresh, run with thetest:unit:cipreamble and an isolatedDATA_DIR→ℹ tests 1456 ℹ pass 1456 ℹ fail 0 ℹ cancelled 0.npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files>→ exit 0.npx prettier --check <changed files>→ clean.npm run typecheck:core→ clean.node scripts/check/check-pr-test-policy.mjs→Result: PASS.GITHUB_BASE_REF=release/v3.8.52 npm run check:test-masking→OK — 0 modificado(s) … sem enfraquecimento.npm run check:cycles→ no cycle touches the changed files.