You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Session Minter (edge token minting) shipped to clerk-js on main between March and May 2026 across five small PRs. Until now, only the touch-intent change (#8135) was backported to release/core-2. The other five SDK changes have to land on core-2 too so v5 consumers can opt into edge-minted tokens once their instance flag is flipped on.
This is a behavior-preserving backport: every code path is gated behind auth_config.session_minter, which defaults to false. With the gate off, clerk-js v5 sends the same /tokens request body and runs the same retry path it does today.
#8097 - monotonic cross-tab token replacement via pickFreshestJwt, so a stale edge-minted broadcast cannot clobber a fresher cached token
#8105 - send the previous session token in the /tokens POST body when auth_config.session_minter is true
#8108 - skip the missing_expired_token retry when Session Minter is enabled (the token is now in the body, so the retry-with-expired-token fallback is unnecessary). Legacy retry preserved when the flag is off.
#8106 - send forceOrigin=true in the body when skipCache is true, so FAPI routes to origin instead of the Session Minter edge
A sixth commit cleans up a review-pass finding: rather than introduce a new __internal_environment getter on Clerk (which exists on main but not on core-2), the code now reads the existing __unstable__environment getter that has been on core-2 since v3. Same commit also backports the Session test coverage from #8105 and #8106 that wasn't worth porting until the env-getter question was settled.
Packages affected
@clerk/clerk-js: AuthConfig gains a sessionMinter field, Session sends the new body fields when the flag is on, tokenCache compares broadcast tokens with pickFreshestJwt. All behavior is gated.
@clerk/shared: AuthConfigResource.sessionMinter, AuthConfigJSON.session_minter?, JwtHeader.oiat?. All additive.
Test plan
pnpm vitest run src/core in clerk-js: 380/380 pass
pnpm test in shared: 641/641 pass
New unit tests in tokenFreshness.test.ts cover the broadcast-side guard's edge cases (legacy tokens, equal oiat, tie-break)
New Session.test.ts blocks assert the /tokens body shape for both sessionMinter: true and sessionMinter: false
Manual: smoke test in a v5 host app against a staging instance with the flag on
Auto reviews are disabled on base/target branches other than the default branch.
Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ae76f5f0-3dce-48f5-b972-30695445e273
You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.
Use the checkbox below for a quick retry:
🔍 Trigger review
✨ Finishing Touches🧪 Generate unit tests (beta)
Create PR with unit tests
Commit unit tests in branch nikos/port-minter-to-core-2
Comment @coderabbitai help to get the list of available commands and usage tips.
The two failing checks (Integration Tests (machine, chrome) and Integration Tests (machine, chrome, RQ)) are pre-existing on release/core-2, not introduced by this PR.
#8633, the most recently merged PR against release/core-2 (a pure CI version-bump with no code changes), has the same two failures. The earlier PRs #8321, #8310, #8239 all had these checks passing, so the M2M test regressed somewhere between then and now.
The failure is m2m.test.ts:139 "authorizes M2M requests when sender machine has proper access to receiver machine" - it sends an M2M bearer token to a protected endpoint and expects 200, but gets 401. M2M tokens are a separate auth flow from user session tokens; nothing in this port touches the M2M code path.
Static analysis (including bundlewatch) is now green after I bumped the clerk.headless*.js limit from 67 KB to 68 KB.
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
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.
Why
Session Minter (edge token minting) shipped to clerk-js on
mainbetween March and May 2026 across five small PRs. Until now, only the touch-intent change (#8135) was backported torelease/core-2. The other five SDK changes have to land on core-2 too so v5 consumers can opt into edge-minted tokens once their instance flag is flipped on.This is a behavior-preserving backport: every code path is gated behind
auth_config.session_minter, which defaults tofalse. With the gate off, clerk-js v5 sends the same/tokensrequest body and runs the same retry path it does today.What changed
Five upstream PRs ported, one per commit:
oiatfield toJwtHeaderpickFreshestJwt, so a stale edge-minted broadcast cannot clobber a fresher cached token/tokensPOST body whenauth_config.session_minteris truemissing_expired_tokenretry when Session Minter is enabled (the token is now in the body, so the retry-with-expired-token fallback is unnecessary). Legacy retry preserved when the flag is off.forceOrigin=truein the body whenskipCacheis true, so FAPI routes to origin instead of the Session Minter edgeA sixth commit cleans up a review-pass finding: rather than introduce a new
__internal_environmentgetter on Clerk (which exists onmainbut not on core-2), the code now reads the existing__unstable__environmentgetter that has been on core-2 since v3. Same commit also backports the Session test coverage from #8105 and #8106 that wasn't worth porting until the env-getter question was settled.Packages affected
@clerk/clerk-js: AuthConfig gains asessionMinterfield, Session sends the new body fields when the flag is on, tokenCache compares broadcast tokens withpickFreshestJwt. All behavior is gated.@clerk/shared:AuthConfigResource.sessionMinter,AuthConfigJSON.session_minter?,JwtHeader.oiat?. All additive.Test plan
pnpm vitest run src/corein clerk-js: 380/380 passpnpm testin shared: 641/641 passtokenFreshness.test.tscover the broadcast-side guard's edge cases (legacy tokens, equal oiat, tie-break)Session.test.tsblocks assert the/tokensbody shape for bothsessionMinter: trueandsessionMinter: false