') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); fix(ui): make verify domain step complete when any domain is verified by iagodahlem · Pull Request #9002 · clerk/javascript · GitHub
Skip to content

fix(ui): make verify domain step complete when any domain is verified - #9002

Closed
iagodahlem wants to merge 2 commits into
mainfrom
iago/update-domain-is-complete
Closed

fix(ui): make verify domain step complete when any domain is verified#9002
iagodahlem wants to merge 2 commits into
mainfrom
iago/update-domain-is-complete

Conversation

@iagodahlem

@iagodahlemiagodahlem commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Description

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:

Summary by CodeRabbit

  • New Features

    • Updated the SSO setup flow to recognize the domain verification step as complete once any domain is successfully verified.
    • Improved step progression in the setup wizard so later steps unlock more accurately based on current connection and verification status.
  • Bug Fixes

    • Fixed cases where the SSO wizard could appear incomplete even after a successful domain verification.
    • Refined reachability and completion states for setup steps to better match the actual setup progress.

Mark the Domains step complete when any organization domain is verified via the new `hasAnyOrganizationDomainsVerified` helper, and require all domains to be verified before the Connection, Test, and Activate steps become reachable.
Document the patch that marks the verify domain step as complete once any domain is verified.
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bdf2fe9

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

This PR includes changesets to release 3 packages
NameType
@clerk/uiPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch

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

vercelBot commented Jun 25, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJun 25, 2026 6:34pm
swingsetReadyReadyPreview, CommentJun 25, 2026 6:34pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: a32f94ca-8212-41db-aca5-38c8bde0e80f

📥 Commits

Reviewing files that changed from the base of the PR and between 34c653a and bdf2fe9.

📒 Files selected for processing (3)
  • .changeset/tall-banks-invite.md
  • packages/ui/src/components/ConfigureSSO/ConfigureSSOWizard.tsx
  • packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts

📝 Walkthrough

Walkthrough

The PR adds a helper for detecting whether any organization domain is verified, updates ConfigureSSOWizard to mark the verify-domain step complete on that condition, and revises later step gating to keep requiring full domain verification.

Changes

Configure SSO domain verification

Layer / File(s)Summary
Any-domain verification predicate
packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts, .changeset/tall-banks-invite.md
Adds hasAnyOrganizationDomainsVerified and updates the changeset note to describe completion when at least one domain is verified.
Wizard step gating
packages/ui/src/components/ConfigureSSO/ConfigureSSOWizard.tsx
Uses the new helper for verify-domain completion and adjusts configure/test/activate reachability and completion checks plus memo dependencies.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • clerk/javascript#8799 — Also touches ConfigureSSOWizard and organizationEnterpriseConnection.ts, with related SSO wizard and domain-flow changes.
  • clerk/javascript#8864 — Overlaps with the same wizard state and step-navigation flow affected by the updated gating logic here.

Suggested reviewers

  • LauraBeatris

Poem

I hopped by moonlight through the gate,
One verified domain said, “You’re great!”
The wizard twitched and gave a cheer,
While farther steps stayed neatly near. 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly and accurately summarizes the main UI behavior change in the PR.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@github-actions

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-06-25T18:37:11.965Z

Summary

MetricCount
Packages analyzed19
Packages with changes2
🔴 Breaking changes5
🟡 Non-breaking changes2
🟢 Additions0

Warning
5 breaking change(s) detected - Major version bump required

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

🔴 Breaking changes index (5)

Every breaking change, up front. Full diffs are in the package sections below.

PackageSubpathChange
@clerk/shared./typesOrganizationDomainOwnershipVerification.status
@clerk/shared./typesOrganizationDomainOwnershipVerificationJSON.status
@clerk/shared./typesOrganizationDomainOwnershipVerificationStatus
@clerk/shared./typesOrganizationDomainOwnershipVerificationStrategy
@clerk/shared./typesOrganizationDomainVerificationStatus

@clerk/shared

Version: 4.22.0 → 4.21.0
Recommended bump: MAJOR

Subpath ./types

🔴 Breaking Changes (5)

Changed: OrganizationDomainOwnershipVerification.status
- status: OrganizationDomainOwnershipVerificationStatus;+ status: OrganizationDomainVerificationStatus;

Static analyzer: Breaking change in property OrganizationDomainOwnershipVerification.status: Type changed: import("@clerk/shared").OrganizationDomainOwnershipVerificationStatusimport("@clerk/shared").OrganizationDomainVerificationStatus

🤖 AI review (confirmed) (85%): The status property of OrganizationDomainOwnershipVerification changed from OrganizationDomainOwnershipVerificationStatus ('expired'|'unverified'|'verified') to OrganizationDomainVerificationStatus ('unverified'|'verified'), removing the 'expired' variant; consumers who switch/match on 'expired' will have type errors.

Migration: Remove or remap any code that handles the 'expired' status value on OrganizationDomainOwnershipVerification.status, as it is no longer part of the type.

Changed: OrganizationDomainOwnershipVerificationJSON.status
- status: OrganizationDomainOwnershipVerificationStatus;+ status: OrganizationDomainVerificationStatus;

Static analyzer: Breaking change in property OrganizationDomainOwnershipVerificationJSON.status: Type changed: import("@clerk/shared").OrganizationDomainOwnershipVerificationStatusimport("@clerk/shared").OrganizationDomainVerificationStatus

🤖 AI review (confirmed) (85%): Same narrowing as b73ffcd5d145 but on the JSON variant; OrganizationDomainOwnershipVerificationJSON.status loses the 'expired' variant, breaking consumers who pattern-match on it.

Migration: Remove or remap any code that handles the 'expired' status value on OrganizationDomainOwnershipVerificationJSON.status, as it is no longer part of the type.

Changed: OrganizationDomainOwnershipVerificationStatus
- type OrganizationDomainOwnershipVerificationStatus = 'unverified' | 'verified' | 'expired';

Static analyzer: Removed type alias OrganizationDomainOwnershipVerificationStatus

🤖 AI review (confirmed) (95%): OrganizationDomainOwnershipVerificationStatus is a fully removed export; any consumer that imported or referenced this type alias will fail to compile.

Migration: Replace usages of OrganizationDomainOwnershipVerificationStatus with OrganizationDomainVerificationStatus, and remove handling for the 'expired' value if present.

Changed: OrganizationDomainOwnershipVerificationStrategy
- type OrganizationDomainOwnershipVerificationStrategy = 'txt' | 'legacy' | 'manual_override' | 'parent_domain';+ type OrganizationDomainOwnershipVerificationStrategy = 'txt' | 'legacy' | 'manual_override';

Static analyzer: Breaking change in type alias OrganizationDomainOwnershipVerificationStrategy: Type changed: 'legacy'|'manual_override'|'parent_domain'|'txt''legacy'|'manual_override'|'txt'

🤖 AI review (confirmed) (90%): OrganizationDomainOwnershipVerificationStrategy lost the 'parent_domain' member; consumers who assign or compare against 'parent_domain' will encounter type errors.

Migration: Remove any code that references or handles the 'parent_domain' strategy value in OrganizationDomainOwnershipVerificationStrategy.

Changed: OrganizationDomainVerificationStatus
- type OrganizationDomainVerificationStatus = 'unverified' | 'verified' | 'failed' | 'expired';+ type OrganizationDomainVerificationStatus = 'unverified' | 'verified';

Static analyzer: Breaking change in type alias OrganizationDomainVerificationStatus: Type changed: 'expired'|'failed'|'unverified'|'verified''unverified'|'verified'

🤖 AI review (confirmed) (90%): OrganizationDomainVerificationStatus was narrowed from 'expired'|'failed'|'unverified'|'verified' to 'unverified'|'verified', removing 'expired' and 'failed'; consumers who handle those variants will have type errors.

Migration: Remove or remap any code that handles 'expired' or 'failed' values for OrganizationDomainVerificationStatus.

🟡 Non-breaking Changes (1)

Modified: __internal_LocalizationResource
// ... 1297 unchanged lines elided ...
domainCard: {
badge__verified: LocalizationValue;
badge__unverified: LocalizationValue;
- badge__expired: LocalizationValue;
verifiedAtLabel: LocalizationValue<'date'>;
- expiredAtLabel: LocalizationValue<'date'>;- expiredLabel: LocalizationValue;- verifyAgainButton: LocalizationValue;
removeButtonTooltip__lastVerifiedDomain: LocalizationValue;
removeButtonTooltip__lastVerifiedDomainActive: LocalizationValue;
txtRecord: {
// ... 639 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) (55%): The before/after snippets differ by only 4 elided lines (1867 vs 1863), indicating minor removals/additions within the localization resource; __internal_LocalizationResource is used only as the source for LocalizationResource which extends DeepPartial<DeepLocalizationWithoutObjects<...>>, making consumers read optional fields from it (output/partial direction), so removing a few optional keys is unlikely to break well-typed consumers — however without seeing exactly which keys changed, confidence is moderate.


@clerk/ui

Version: 1.23.0 → 1.22.0
Recommended bump: MINOR

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 490 unchanged lines elided ...
configureSSOVerifyDomainErrorSubtitle: WithOptions;
configureSSOVerifyDomainList: WithOptions;
configureSSOVerifyDomainSuggestion: WithOptions;
- configureSSOVerifyDomainCard: WithOptions<'verified' | 'unverified' | 'expired'>;- configureSSOVerifyDomainCardBadge: WithOptions<'verified' | 'unverified' | 'expired'>;+ configureSSOVerifyDomainCard: WithOptions<'verified' | 'unverified'>;+ configureSSOVerifyDomainCardBadge: WithOptions<'verified' | 'unverified'>;
configureSSOVerifyDomainCardRemoveButton: WithOptions;
configureSSOVerifyDomainCardTxtRecord: WithOptions;
configureSSOVerifyDomainCardTxtRecordValue: WithOptions;
- configureSSOVerifyDomainCardExpired: WithOptions;
configureSSOEmailVerificationForm: WithOptions<string>;
configureSSOEmailVerificationIcon: WithOptions<string>;
configureSSOEmailVerificationTitle: WithOptions<string>;
// ... 51 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (70%): The diff shows one fewer elided line (473→472) in the middle section but all visible keys and value types are identical; ElementsConfig is consumed only via the Elements mapped type which is an output type, so no well-typed consumer constructs an ElementsConfig object directly.


Report generated by Break Check

Last ran on bdf2fe9.

Sign up for freeto 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.

1 participant

@iagodahlem