Skip to content

fix(mosaic): count resend cooldowns down from the clock - #10619

Open
alexcarpenter wants to merge 3 commits into
mainfrom
carp/mosaic-timing
Open

alexcarpenter wants to merge 3 commits into
mainfrom
carp/mosaic-timing

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Description

The add email, add phone and MFA SMS dialogs counted their resend cooldown down with a one-second TICK event per machine. When the tab is throttled or the device sleeps, those ticks fall behind, so Resend stays locked well past the cooldown. They now keep the unlock time in the machine, like reverification already does, and show the seconds left with a shared useResendSeconds hook.

  • resendUnlockTime / isResendUnlocked (src/utils/verification.ts) set and check the unlock time inside each machine.
  • useResendSeconds (src/hooks/) reads the time through useNow, which gains an until option so its timer stops once the cooldown ends.
  • Mosaic's AGENTS.md reuse table and docs/models.md point to the new helpers.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@changeset-bot

changeset-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f3baf74

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@clerk/mosaic Patch
@clerk/swingset Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
clerk-js-sandbox Ready Ready Preview Nov 4, 2026 12:34pm UTC
swingset Ready Ready Preview Nov 4, 2026 12:34pm UTC

Request Review

@github-actions github-actions Bot added the mosaic label Nov 3, 2026
@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Verification controllers now store resend unlock timestamps instead of decrementing countdown state. The shared useResendSeconds hook derives the displayed countdown from each timestamp and updates it while time remains. Email, phone, MFA, and reverification flows use the shared timing logic. New tests cover delayed timers and clock changes, and a patch changeset records the change.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Severity of issue fixed: Medium

Possibly related PRs

  • clerk/javascript#10382: Defines and renders the reverification resend countdown label that this change supplies with hook-derived seconds.
  • clerk/javascript#10560: Centralizes CODE_RESEND_SECONDS in the verification utility used by this change.
  • clerk/javascript#10446: Changes email and phone verification startup and resend timing in controllers updated here.
Merge Risk: Minimal · up to f3baf

Countdowns now use elapsed time. No merge-blocking issue was established.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: correcting resend cooldown countdown behavior in Mosaic.
Description check Passed The description directly explains the resend cooldown bug, the affected dialogs, and the timestamp-based fix using shared helpers.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 8 functions across 12 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Linked repositories: Some configured repositories could not be included in this review. Cross-repository analysis may be incomplete. Please check linked-repository access and settings.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between beda022 and f3baf74.

Files selected for processing: 5
  • packages/mosaic/AGENTS.md
  • packages/mosaic/docs/models.md
  • packages/mosaic/src/hooks/__tests__/use-now.test.tsx
  • packages/mosaic/src/hooks/use-now.ts
  • packages/mosaic/src/hooks/use-resend-seconds.ts
Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.

@pkg-pr-new

pkg-pr-new Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@10619

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@10619

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@10619

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@10619

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@10619

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@10619

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@10619

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@10619

@clerk/expo-biometrics

npm i https://pkg.pr.new/@clerk/expo-biometrics@10619

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@10619

@clerk/expo-native-components

npm i https://pkg.pr.new/@clerk/expo-native-components@10619

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@10619

@clerk/express

npm i https://pkg.pr.new/@clerk/express@10619

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@10619

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@10619

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@10619

@clerk/mosaic

npm i https://pkg.pr.new/@clerk/mosaic@10619

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@10619

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@10619

@clerk/react

npm i https://pkg.pr.new/@clerk/react@10619

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@10619

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@10619

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@10619

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@10619

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@10619

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@10619

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@10619

commit: f3baf74

@alexcarpenter
alexcarpenter requested review from Ephem and austincalvelage and removed request for austincalvelage November 3, 2026 21:00

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

  • Fix comments: Fix CodeRabbit comments on this PR

@blacksmith-sh

blacksmith-sh Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Matches Add phone Resend unlocks after a frozen tab

After the timers were held past the cooldown, Resend was enabled and clicking it sent a new code and re-locked at 30; before, it stayed locked at 26.

Merge-base

Phone dialog after hold

This PR f3baf74e

Phone dialog after hold

Merge-base

Phone hold log

This PR f3baf74e

Phone hold log

Resend re-locks after click

Also checked · 3 match

Matches Add email and MFA SMS unlock the same way
Matches Normal countdown still ticks each second
Matches Reverification resend timer unchanged

Proof on f3baf74e (from beda0221) · Did Proof get it right? Yes · No

View full Proof report

import { useEffect, useState } from 'react';

export function useResendSeconds(resendAvailableAt: number | undefined, maxSeconds: number): number {
const [now, setNow] = useState(() => Date.now());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not SSR compatible, feels like this hook could reuse the useNow hook we built to pave the way for that in the future? Might need to add an enabled option to that hook for the countingDown case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good call, done in the latest commit. useNow takes an until time and stops its timer once it reaches it (an enabled flag would need the countdown before the hook returns it), and useResendSeconds now reads the time through it, so it goes through MosaicNowProvider. I also dropped the "exception" line from docs/models.md.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

also adding a lint rule here #10641

This branch was successfully deployed

2 active deployments
Preview – swingset — f3baf74e Deployed Nov 4, 2026 by vercel[bot]
Preview – clerk-js-sandbox — f3baf74e Deployed Nov 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants