Skip to content

feat(js,ui): mount and render the directory sync setup flow - #9592

Open
kalafut wants to merge 7 commits into
jim/dir-sync-2-hooksfrom
jim/dir-sync-3-ui
Open

feat(js,ui): mount and render the directory sync setup flow#9592
kalafut wants to merge 7 commits into
jim/dir-sync-2-hooksfrom
jim/dir-sync-3-ui

Conversation

@kalafut

@kalafut kalafut commented Aug 27, 2026

Copy link
Copy Markdown

Description

Part 3 of 4 of the self-serve Directory Sync stack. Stacked on jim/dir-sync-2-hooks; the changeset rides the first PR and the stack will be squashed on merge.

  • @clerk/clerk-js: __internal_mountConfigureDirectorySync with guards mirroring ConfigureSSO's (orgs enabled, active org, self-serve directory sync feature).
  • @clerk/ui: ConfigureDirectorySync wizard over the organization's enterprise connection and directory (show-once token held in wizard session state, read-only attribute mapping from the directory, test step polls provisioned users), plus a Directory Sync section on the Security page. Google-provider connections are directed to the Dashboard.

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:

🤖 Generated with Claude Code

https://claude.ai/code/session_01U54pszNFtqsBNpQhXaGvaa

@vercel

vercel Bot commented Aug 27, 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 Sep 2, 2026 10:47pm UTC
swingset Ready Ready Preview Sep 2, 2026 10:47pm UTC

Request Review

@kalafut kalafut changed the title feat(self-serve-ds): mount and render ConfigureDirectorySync feat(js,ui): mount and render the directory sync setup flow Aug 27, 2026
@changeset-bot

changeset-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 2b8cc8b

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 changesets to release 23 packages
Name Type
@clerk/clerk-js Minor
@clerk/localizations Minor
@clerk/react Minor
@clerk/shared Minor
@clerk/ui Minor
@clerk/chrome-extension Patch
@clerk/electron Patch
@clerk/expo Patch
@clerk/nextjs Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/headless Patch
@clerk/hono Patch
@clerk/msw Patch
@clerk/nuxt Patch
@clerk/testing Patch
@clerk/vue Patch
@clerk/swingset Patch

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

pkg-pr-new Bot commented Aug 28, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

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

@clerk/electron-passkeys

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

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: 2b8cc8b

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-09-02T22:52:58.283Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 2
🔴 Breaking changes 0
🟡 Non-breaking changes 4
🟢 Additions 7

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/clerk-js

Current version: 6.31.0
Recommended bump: MINOR → 6.32.0

Subpath .

🟢 Additions (2)

Added: Clerk.__internal_mountConfigureDirectorySync
+ __internal_mountConfigureDirectorySync: (node: HTMLDivElement, props?: ConfigureSSOProps) => void;

Added property Clerk.__internal_mountConfigureDirectorySync

Added: Clerk.__internal_unmountConfigureDirectorySync
+ __internal_unmountConfigureDirectorySync: (node: HTMLDivElement) => void;

Added property Clerk.__internal_unmountConfigureDirectorySync

Subpath ./no-rhc

🟢 Additions (2)

Added: Clerk.__internal_mountConfigureDirectorySync
+ __internal_mountConfigureDirectorySync: (node: HTMLDivElement, props?: ConfigureSSOProps) => void;

Added property Clerk.__internal_mountConfigureDirectorySync

Added: Clerk.__internal_unmountConfigureDirectorySync
+ __internal_unmountConfigureDirectorySync: (node: HTMLDivElement) => void;

Added property Clerk.__internal_unmountConfigureDirectorySync


@clerk/shared

Current version: 4.31.0
Recommended bump: MINOR → 4.32.0

Subpath ./internal/clerk-js/componentGuards

🟢 Additions (1)

Added: disabledSelfServeDirectorySyncFeature
+ disabledSelfServeDirectorySyncFeature: ComponentGuard

Added variable disabledSelfServeDirectorySyncFeature

Subpath ./internal/clerk-js/warnings

🟡 Non-breaking Changes (1)

Modified: warnings
// ... 7 unchanged lines elided ...
    cannotRenderSignInComponentWhenSessionExists: string;
    cannotRenderSignInComponentWhenTaskExists: string;
    cannotRenderComponentWhenUserDoesNotExist: string;
-   createCannotRenderComponentWhenOrgDoesNotExist: (componentName: "OrganizationProfile" | "InviteMembers" | "ConfigureSSO") => string;
+   createCannotRenderComponentWhenOrgDoesNotExist: (componentName: "OrganizationProfile" | "InviteMembers" | "ConfigureSSO" | "ConfigureDirectorySync") => string;
    createCannotRenderComponentWhenPermissionIsMissing: (componentName: "InviteMembers", permission: string) => string;
-   cannotRenderAnyOrganizationComponent: (componentName: "OrganizationProfile" | "InviteMembers" | "OrganizationSwitcher" | "OrganizationList" | "CreateOrganization" | "TaskChooseOrganization" | "ConfigureSSO") => string;
+   cannotRenderAnyOrganizationComponent: (componentName: "OrganizationProfile" | "InviteMembers" | "OrganizationSwitcher" | "OrganizationList" | "CreateOrganization" | "TaskChooseOrganization" | "ConfigureSSO" | "ConfigureDirectorySync") => string;
    cannotRenderAnyBillingComponent: (componentName: "PricingTable" | "Checkout" | "PlanDetails") => string;
    cannotOpenUserProfile: string;
    cannotOpenCheckout: string;
    cannotOpenSignInOrSignUp: string;
    cannotRenderAPIKeysComponent: string;
    cannotRenderAPIKeysComponentForOrgWhenUnauthorized: string;
    cannotRenderAPIKeysComponentForUserWhenDisabled: string;
    cannotRenderAPIKeysComponentForOrgWhenDisabled: string;
    cannotRenderOAuthConsentComponentWhenUserDoesNotExist: string;
    cannotRenderOAuthDeviceVerificationComponentWhenUserDoesNotExist: string;
    cannotRenderConfigureSSOComponentWhenUserDoesNotExist: string;
    cannotRenderConfigureSSOComponentWhenDisabled: string;
+   cannotRenderConfigureDirectorySyncComponentWhenDisabled: string;
    cannotRenderConfigureSSOComponentWhenEmailAddressDisabled: string;
  }

Static analyzer: Breaking change in variable warnings: Type changed: {proxyUrlAsFunctionNotSupported:string;domainAsFunctionNotSupported:string;cannotRenderComponentWhenSessionExists:strin…{proxyUrlAsFunctionNotSupported:string;domainAsFunctionNotSupported:string;cannotRenderComponentWhenSessionExists:strin…

🤖 AI review (reclassified as non-breaking) (90%): The changes are purely additive: two new string members (cannotRenderConfigureDirectorySyncComponentWhenDisabled) and the expansion of two function parameter union types to include "ConfigureDirectorySync". Adding a new property to the object does not break consumers who read the existing properties, and widening a parameter union (input position) is non-breaking by contravariance — callers who previously passed the narrower set of literals still satisfy the wider union.

Subpath ./types

🟡 Non-breaking Changes (3)

Modified: __internal_AttemptToEnableEnvironmentSettingParams
  type __internal_AttemptToEnableEnvironmentSettingParams = {
    for: 'organizations';
-   caller: 'OrganizationSwitcher' | 'OrganizationProfile' | 'InviteMembers' | 'OrganizationList' | 'CreateOrganization' | 'TaskChooseOrganization' | 'ConfigureSSO' | 'useOrganizationList' | 'useOrganization';
+   caller: 'OrganizationSwitcher' | 'OrganizationProfile' | 'InviteMembers' | 'OrganizationList' | 'CreateOrganization' | 'TaskChooseOrganization' | 'ConfigureSSO' | 'ConfigureDirectorySync' | 'useOrganizationList' | 'useOrganization';
    onClose?: () => void;
  };

Static analyzer: Breaking change in type alias __internal_AttemptToEnableEnvironmentSettingParams: Type changed: {for:'organizations';caller:'ConfigureSSO'|'CreateOrganization'|'InviteMembers'|'OrganizationList'|'OrganizationProfile…{for:'organizations';caller:'ConfigureDirectorySync'|'ConfigureSSO'|'CreateOrganization'|'InviteMembers'|'OrganizationL…

🤖 AI review (reclassified as non-breaking) (90%): The caller union was widened by adding 'ConfigureDirectorySync'; this type is used as a function parameter (input position), so widening the accepted values is non-breaking for existing callers who already pass one of the previous string literals.

Modified: __internal_LocalizationResource
// ... 1108 unchanged lines elided ...
          tooltip__noRole: LocalizationValue;
          tooltipLabel: LocalizationValue;
        };
+       directorySyncSection: {
+         title: LocalizationValue;
+         badge__unconfigured: LocalizationValue;
+         badge__ssoRequired: LocalizationValue;
+         badge__active: LocalizationValue;
+         badge__inactive: LocalizationValue;
+         description: LocalizationValue;
+         primaryButton__startConfiguration: LocalizationValue;
+         menuAction__edit: LocalizationValue;
+         menuAction__activate: LocalizationValue;
+         menuAction__deactivate: LocalizationValue;
+         menuAction__remove: LocalizationValue;
+         removeDialog: {
+           title: LocalizationValue;
+           subtitle: LocalizationValue;
+           confirmButton: LocalizationValue;
+         };
+       };
      };
      membersPage: {
        detailsTitle__emptyRow: LocalizationValue;
// ... 1004 unchanged lines elided ...

Static analyzer: Breaking change in type alias __internal_LocalizationResource: Type changed: {locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…{locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…

🤖 AI review (reclassified as non-breaking) (80%): __internal_LocalizationResource is used as an input to construct LocalizationResource (via DeepPartial<DeepLocalizationWithoutObjects<...>>); the diff adds new optional localization keys, which is non-breaking for consumers who supply a partial subset of localization strings.

Modified: ProfileSectionId
- type ProfileSectionId = 'profile' | 'username' | 'emailAddresses' | 'phoneNumbers' | 'connectedAccounts' | 'enterpriseAccounts' | 'web3Wallets' | 'password' | 'passkeys' | 'mfa' | 'danger' | 'activeDevices' | 'organizationProfile' | 'organizationDanger' | 'organizationDomains' | 'manageVerifiedDomains' | 'subscriptionsList' | 'paymentMethods' | 'sso' | 'ssoStatus' | 'enableSso' | 'ssoDomain' | 'ssoConfiguration' | 'configureAgain' | 'resetSso' | 'testSsoUrl' | 'testResults' | 'accountCredits';
+ type ProfileSectionId = 'profile' | 'username' | 'emailAddresses' | 'phoneNumbers' | 'connectedAccounts' | 'enterpriseAccounts' | 'web3Wallets' | 'password' | 'passkeys' | 'mfa' | 'danger' | 'activeDevices' | 'organizationProfile' | 'organizationDanger' | 'organizationDomains' | 'manageVerifiedDomains' | 'subscriptionsList' | 'paymentMethods' | 'sso' | 'directorySync' | 'ssoStatus' | 'enableSso' | 'ssoDomain' | 'ssoConfiguration' | 'configureAgain' | 'resetSso' | 'testSsoUrl' | 'testResults' | 'accountCredits';

Static analyzer: Breaking change in type alias ProfileSectionId: Type changed: 'accountCredits'|'activeDevices'|'configureAgain'|'connectedAccounts'|'danger'|'emailAddresses'|'enableSso'|'enterprise…'accountCredits'|'activeDevices'|'configureAgain'|'connectedAccounts'|'danger'|'directorySync'|'emailAddresses'|'enable…

🤖 AI review (reclassified as non-breaking) (85%): ProfileSectionId was widened by adding 'directorySync' to the union; MenuId consumes it as a union member (output/discriminated value), and existing consumers checking against prior literals are unaffected by an additional variant being introduced.

🟢 Additions (2)

Added: Clerk.__internal_mountConfigureDirectorySync
+ __internal_mountConfigureDirectorySync: (targetNode: HTMLDivElement, props?: ConfigureSSOProps) => void;

Added property Clerk.__internal_mountConfigureDirectorySync

Added: Clerk.__internal_unmountConfigureDirectorySync
+ __internal_unmountConfigureDirectorySync: (targetNode: HTMLDivElement) => void;

Added property Clerk.__internal_unmountConfigureDirectorySync


Report generated by Break Check

Last ran on 2b8cc8b.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

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: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Team

Run ID: 5bcf4dbe-46ea-4dc6-b506-dd86ee2c8b6f

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

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

kalafut and others added 7 commits September 2, 2026 15:44
- @clerk/clerk-js: __internal_mountConfigureDirectorySync with guards
  mirroring ConfigureSSO's (orgs enabled, active org, self-serve
  directory sync feature).
- @clerk/ui: ConfigureDirectorySync wizard over the organization's
  enterprise connection and directory (show-once token held in wizard
  session state, read-only attribute mapping from the directory, test step
  polls provisioned users), plus a Directory Sync section on the Security
  page. Google-provider connections are directed to the Dashboard.
1. Mock directory.update()/delete() on the resource instead of the removed organization.updateDirectorySync/deleteDirectorySync; also mock getDomains so a retry loop can't wedge the page's loading gate.
2. Security section + wizard:show spinner while loading and an error alert on failure instead of falsely rendering "unconfigured"; wizard shows the skeleton while loading.
3. Standalone mount:wrapped in the shared ConfigureSSOProtect permission gate.
4. Clerk API surface:added __internal_(un)mountConfigureDirectorySync to the shared Clerk interface and IsomorphicClerk, so framework SDKs can reach the mount; added @clerk/react to the changeset.
5. Activate step:"Done"/"Skip for now" render only when the host supplies onExit (they were no-ops standalone).
6. Navbar:DirectorySyncNavbar is now a thin wrapper over ConfigureSSONavbar (with a new title prop), restoring mobile behavior.
7. TestSyncStep:|| instead of ?? so an empty display name falls through.
8. Bundle limits: bumped via bundlewatch:fix (554KB / 81KB).
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.

1 participant