Skip to content

feat(js,shared,ui): Add protect check as missing requirement with prepare/attempt pattern#7894

Open
zourzouvillys wants to merge 2 commits intomainfrom
theo/protect-check-prepare-attempt
Open

feat(js,shared,ui): Add protect check as missing requirement with prepare/attempt pattern#7894
zourzouvillys wants to merge 2 commits intomainfrom
theo/protect-check-prepare-attempt

Conversation

@zourzouvillys
Copy link
Contributor

@zourzouvillys zourzouvillys commented Feb 20, 2026

Summary

Implements protect check as a missing requirement field ('protect_check' in missingFields) handled via the prepare/attempt pattern with dedicated FAPI actions (prepare_protect_check / attempt_protect_check), replacing the previous auto-execution model.

This gives the backend full control over when to require a protect check — it can dynamically add protect_check to missing_fields based on rules and risk signals at any point in the sign-up flow.

How it works

  1. Any sign-up operation (create/update/verify) → backend adds 'protect_check' to missing_fields
  2. completeSignUpFlow detects 'protect_check' in missingFields (checked first, before everything else including enterprise_sso)
  3. Calls signUp.runProtectCheck() which internally:
    • POST prepare_protect_check → backend returns verifications.protect_check: { url: '...' }
    • Dynamic import(url), execute script in DOM container → script returns result
    • POST attempt_protect_check with result → backend clears protect_check from missing_fields
  4. completeSignUpFlow re-evaluates recursively and continues (email verification, phone verification, etc.)

Key design decisions

  • No auto-execution: create(), update(), prepareVerification(), attemptVerification(), and all SignUpFuture methods no longer auto-execute protect checks. The check only runs when explicitly called via runProtectCheck() or when completeSignUpFlow detects it in missingFields.
  • First in priority: protect_check is checked before enterprise_sso and all other missing requirements in completeSignUpFlow, since it can appear at any point in the flow.
  • Recursive re-evaluation: After runProtectCheck() completes, completeSignUpFlow calls itself again to re-evaluate the updated sign-up state and continue with the next requirement.

API changes

New type: ProtectCheckField

// packages/shared/src/types/signUpCommon.ts
export type ProtectCheckField = 'protect_check';
export type SignUpField = SignUpAttributeField | SignUpIdentificationField | ProtectCheckField;

'protect_check' can now appear in missingFields, requiredFields, and optionalFields arrays on SignUpResource / SignUpFutureResource.

New method: SignUpResource.runProtectCheck()

// packages/shared/src/types/signUp.ts
runProtectCheck: () => Promise<SignUpResource>;

Runs the full prepare → execute → attempt protect check flow. Called by completeSignUpFlow when 'protect_check' is in missingFields, or can be called directly in custom flows.

New method: SignUpFutureVerifications.runProtectCheck()

// packages/shared/src/types/signUpFuture.ts
runProtectCheck: () => Promise<{ error: ClerkError | null }>;

Same flow, wrapped in runAsyncResourceTask for the future API pattern (returns { error } instead of throwing).

New property: SignUpFutureVerifications.protectCheck

// packages/shared/src/types/signUpFuture.ts
readonly protectCheck: { url: string } | null;

Exposes the protect check URL from the underlying resource verifications.

New JSON field: SignUpVerificationsJSON.protect_check

// packages/shared/src/types/json.ts
protect_check: { url: string } | null;

FAPI version bump

SUPPORTED_FAPI_VERSION updated from '2025-11-10' to '2026-03-01' to support the new prepare_protect_check and attempt_protect_check actions.

Versioning impact

This is a minor version change for:

  • @clerk/shared: New types (ProtectCheckField, runProtectCheck on interfaces), new constant (PROTECT_CHECK_CONTAINER_ID), updated completeSignUpFlow behavior, FAPI version bump
  • @clerk/clerk-js: New runProtectCheck() method on SignUp class, new executeProtectCheck utility, updated SignUpVerifications class, updated SignUpFutureVerifications class
  • @clerk/ui: New ProtectCheckElement component rendered in sign-up forms

Breaking change considerations

  • completeSignUpFlow now handles protect_check automatically. Existing code that calls completeSignUpFlow will transparently handle protect checks without changes.
  • SignUpField type union is widened to include 'protect_check'. Code that exhaustively matches on SignUpField values will need to handle the new variant.
  • No auto-execution: If any code relied on protect checks being auto-executed after create() / update() / verification methods, it must now either use completeSignUpFlow (which handles it automatically) or call runProtectCheck() explicitly.

Files changed

File Change
packages/shared/src/types/signUpCommon.ts Add ProtectCheckField type, update SignUpField union, add protectCheck to SignUpVerificationsResource
packages/shared/src/types/signUp.ts Add runProtectCheck method to SignUpResource
packages/shared/src/types/signUpFuture.ts Add protectCheck getter and runProtectCheck method to SignUpFutureVerifications
packages/shared/src/types/json.ts Add protect_check to SignUpVerificationsJSON
packages/shared/src/internal/clerk-js/constants.ts Bump SUPPORTED_FAPI_VERSION to 2026-03-01, add PROTECT_CHECK_CONTAINER_ID
packages/shared/src/internal/clerk-js/completeSignUpFlow.ts Add protect_check as first check in missing_requirements branch
packages/clerk-js/src/core/resources/Verification.ts Add protectCheck field to SignUpVerifications class (deserialization + snapshot)
packages/clerk-js/src/core/resources/SignUp.ts Add runProtectCheck() to SignUp, add _runProtectCheck to SignUpFuture, wire through SignUpFutureVerifications, add container helpers
packages/clerk-js/src/utils/protectCheck/ New executeProtectCheck utility (dynamic import + script execution)
packages/ui/src/elements/ProtectCheckElement.tsx New React component providing DOM container for protect check scripts
packages/ui/src/components/SignUp/SignUpForm.tsx Render <ProtectCheckElement /> in sign-up form
packages/ui/src/components/SignUp/SignUpStart.tsx Render <ProtectCheckElement /> in sign-up start

Test plan

  • @clerk/shared builds cleanly (turbo build --filter=@clerk/shared)
  • @clerk/clerk-js builds cleanly with type declarations (turbo build --filter=@clerk/clerk-js)
  • SignUp.test.ts — 53 tests pass: serialization, create, password, sso, web3, ticket, finalize, reset, protect check (runProtectCheck prepare→execute→attempt flow, container cleanup, error handling, no auto-execution from create/password/sso)
  • protectCheck.test.ts — 5 tests pass: error code classification, script load behavior, barrel export
  • Integration test with backend returning protect_check in missing_fields
  • Verify completeSignUpFlow recursion works end-to-end with real FAPI responses

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added runProtectCheck() method to enable a new protect check step in the sign-up flow
    • Introduced UI component to support protect check rendering during sign-up
  • Tests

    • Added comprehensive test coverage for protect check integration and workflows
  • Chores

    • Updated supported API version

…pare/attempt pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Feb 20, 2026

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

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Feb 20, 2026 5:36pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Feb 20, 2026

⚠️ No Changeset found

Latest commit: b23b308

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 20, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7894

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7894

@clerk/expo

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: b23b308

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 20, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

This pull request introduces a new Protect Check flow to the Clerk sign-up authentication process. The changes add a runProtectCheck() method to both SignUp and SignUpFuture resources that executes a multi-step verification process (prepare, execute script, attempt). A new React component ProtectCheckElement renders a dedicated DOM container for protect check scripts. New utility functions handle dynamic script loading and execution. Type definitions across the shared package are updated to include the protect_check field and related interfaces. The flow is integrated into completeSignUpFlow to execute protect check when required. Comprehensive test coverage validates serialization, getter behavior, container lifecycle management, and error handling throughout the new functionality.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding protect check as a missing requirement field with prepare/attempt pattern, which is the core feature implemented throughout the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments