diff --git a/.changeset/bright-trees-retry.md b/.changeset/bright-trees-retry.md
new file mode 100644
index 00000000000..72cfb14b46a
--- /dev/null
+++ b/.changeset/bright-trees-retry.md
@@ -0,0 +1,7 @@
+---
+'@clerk/ui': patch
+'@clerk/localizations': patch
+'@clerk/shared': patch
+---
+
+Add a "Re-issue" action to pending self-serve SSO domains, which issues a fresh TXT record when the published one is stale. Each successful re-issue starts a five-minute cooldown, explained on the disabled button.
diff --git a/packages/localizations/src/ar-SA.ts b/packages/localizations/src/ar-SA.ts
index 412c5ad3367..a4eeed877cb 100644
--- a/packages/localizations/src/ar-SA.ts
+++ b/packages/localizations/src/ar-SA.ts
@@ -729,6 +729,7 @@ export const arSA: LocalizationResource = {
},
verifiedAtLabel: "تم التحقق في {{ date | shortDate('en-US') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'إضافة {{domain}}',
diff --git a/packages/localizations/src/be-BY.ts b/packages/localizations/src/be-BY.ts
index 6171efa76f1..296d62577bb 100644
--- a/packages/localizations/src/be-BY.ts
+++ b/packages/localizations/src/be-BY.ts
@@ -730,6 +730,7 @@ export const beBY: LocalizationResource = {
},
verifiedAtLabel: "Пацверджана {{ date | shortDate('be-BY') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Дадаць {{domain}}',
diff --git a/packages/localizations/src/bg-BG.ts b/packages/localizations/src/bg-BG.ts
index 5c24af73f66..8a526945ee9 100644
--- a/packages/localizations/src/bg-BG.ts
+++ b/packages/localizations/src/bg-BG.ts
@@ -731,6 +731,7 @@ export const bgBG: LocalizationResource = {
},
verifiedAtLabel: "Потвърден на {{ date | shortDate('bg-BG') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Добавяне на {{domain}}',
diff --git a/packages/localizations/src/bn-IN.ts b/packages/localizations/src/bn-IN.ts
index dd477c1dacd..f7d11ea4829 100644
--- a/packages/localizations/src/bn-IN.ts
+++ b/packages/localizations/src/bn-IN.ts
@@ -736,6 +736,7 @@ export const bnIN: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('bn-IN') }} তারিখে যাচাই করা হয়েছে",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} যোগ করুন',
diff --git a/packages/localizations/src/ca-ES.ts b/packages/localizations/src/ca-ES.ts
index c7a12dcd007..ccdb2689b1f 100644
--- a/packages/localizations/src/ca-ES.ts
+++ b/packages/localizations/src/ca-ES.ts
@@ -737,6 +737,7 @@ export const caES: LocalizationResource = {
},
verifiedAtLabel: "Verificat el {{ date | shortDate('ca-ES') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Afegeix {{domain}}',
diff --git a/packages/localizations/src/cs-CZ.ts b/packages/localizations/src/cs-CZ.ts
index 794f8c5b0a8..011d2df60f7 100644
--- a/packages/localizations/src/cs-CZ.ts
+++ b/packages/localizations/src/cs-CZ.ts
@@ -734,6 +734,7 @@ export const csCZ: LocalizationResource = {
},
verifiedAtLabel: "Ověřeno {{ date | shortDate('cs-CZ') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Přidat {{domain}}',
diff --git a/packages/localizations/src/da-DK.ts b/packages/localizations/src/da-DK.ts
index 7726dd8f310..15dc0386e96 100644
--- a/packages/localizations/src/da-DK.ts
+++ b/packages/localizations/src/da-DK.ts
@@ -729,6 +729,7 @@ export const daDK: LocalizationResource = {
},
verifiedAtLabel: "Bekræftet den {{ date | shortDate('da-DK') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Tilføj {{domain}}',
diff --git a/packages/localizations/src/de-DE.ts b/packages/localizations/src/de-DE.ts
index 2d615e35ee0..30802c28b35 100644
--- a/packages/localizations/src/de-DE.ts
+++ b/packages/localizations/src/de-DE.ts
@@ -736,6 +736,7 @@ export const deDE: LocalizationResource = {
},
verifiedAtLabel: "Verifiziert am {{ date | shortDate('de-DE') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} hinzufügen',
diff --git a/packages/localizations/src/el-GR.ts b/packages/localizations/src/el-GR.ts
index b0f43aabb26..b98af50af82 100644
--- a/packages/localizations/src/el-GR.ts
+++ b/packages/localizations/src/el-GR.ts
@@ -730,6 +730,7 @@ export const elGR: LocalizationResource = {
},
verifiedAtLabel: "Επαληθεύτηκε στις {{ date | shortDate('el-GR') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Προσθήκη {{domain}}',
diff --git a/packages/localizations/src/en-GB.ts b/packages/localizations/src/en-GB.ts
index 6c1415128ad..672cce5fe22 100644
--- a/packages/localizations/src/en-GB.ts
+++ b/packages/localizations/src/en-GB.ts
@@ -729,6 +729,7 @@ export const enGB: LocalizationResource = {
},
verifiedAtLabel: "Verified on {{ date | shortDate('en-GB') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Add {{domain}}',
diff --git a/packages/localizations/src/en-US.ts b/packages/localizations/src/en-US.ts
index 4c4e33bcd4c..df1e9126eb0 100644
--- a/packages/localizations/src/en-US.ts
+++ b/packages/localizations/src/en-US.ts
@@ -745,7 +745,8 @@ export const enUS: LocalizationResource = {
valueLabel: 'Value',
},
verifiedAtLabel: "Verified on {{ date | shortDate('en-US') }}",
- verifyAgainButton: 'Verify again',
+ verifyAgainButton: 'Re-issue',
+ verifyAgainButtonTooltip__throttled: 'A new record was just issued. You can issue another one shortly.',
},
domainSuggestion: {
formButtonPrimary__add: 'Add {{domain}}',
diff --git a/packages/localizations/src/es-CR.ts b/packages/localizations/src/es-CR.ts
index 051c1c8e592..ba1b831dfdb 100644
--- a/packages/localizations/src/es-CR.ts
+++ b/packages/localizations/src/es-CR.ts
@@ -730,6 +730,7 @@ export const esCR: LocalizationResource = {
},
verifiedAtLabel: "Verificado el {{ date | shortDate('es-CR') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Agregar {{domain}}',
diff --git a/packages/localizations/src/es-ES.ts b/packages/localizations/src/es-ES.ts
index a28358daa7e..84bc4dcadf2 100644
--- a/packages/localizations/src/es-ES.ts
+++ b/packages/localizations/src/es-ES.ts
@@ -736,6 +736,7 @@ export const esES: LocalizationResource = {
},
verifiedAtLabel: "Verificado el {{ date | shortDate('es-ES') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Añadir {{domain}}',
diff --git a/packages/localizations/src/es-MX.ts b/packages/localizations/src/es-MX.ts
index 43d21afac61..33703106b40 100644
--- a/packages/localizations/src/es-MX.ts
+++ b/packages/localizations/src/es-MX.ts
@@ -731,6 +731,7 @@ export const esMX: LocalizationResource = {
},
verifiedAtLabel: "Verificado el {{ date | shortDate('es-MX') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Agregar {{domain}}',
diff --git a/packages/localizations/src/es-UY.ts b/packages/localizations/src/es-UY.ts
index 59cf112290f..49bae67373d 100644
--- a/packages/localizations/src/es-UY.ts
+++ b/packages/localizations/src/es-UY.ts
@@ -730,6 +730,7 @@ export const esUY: LocalizationResource = {
},
verifiedAtLabel: "Verificado el {{ date | shortDate('es-UY') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Agregar {{domain}}',
diff --git a/packages/localizations/src/fa-IR.ts b/packages/localizations/src/fa-IR.ts
index 8b90baf9f22..d71d9fa0b72 100644
--- a/packages/localizations/src/fa-IR.ts
+++ b/packages/localizations/src/fa-IR.ts
@@ -735,6 +735,7 @@ export const faIR: LocalizationResource = {
},
verifiedAtLabel: "تأییدشده در {{ date | shortDate('fa-IR') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'افزودن {{domain}}',
diff --git a/packages/localizations/src/fi-FI.ts b/packages/localizations/src/fi-FI.ts
index c7ee3488ae9..dbfc401f3b7 100644
--- a/packages/localizations/src/fi-FI.ts
+++ b/packages/localizations/src/fi-FI.ts
@@ -736,6 +736,7 @@ export const fiFI: LocalizationResource = {
},
verifiedAtLabel: "Vahvistettu {{ date | shortDate('fi-FI') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Lisää {{domain}}',
diff --git a/packages/localizations/src/fr-FR.ts b/packages/localizations/src/fr-FR.ts
index aa019e5fa48..565f5b129a2 100644
--- a/packages/localizations/src/fr-FR.ts
+++ b/packages/localizations/src/fr-FR.ts
@@ -738,6 +738,7 @@ export const frFR: LocalizationResource = {
},
verifiedAtLabel: "Vérifié le {{ date | shortDate('fr-FR') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Ajouter {{domain}}',
diff --git a/packages/localizations/src/he-IL.ts b/packages/localizations/src/he-IL.ts
index a95959d3aab..16a0af7143b 100644
--- a/packages/localizations/src/he-IL.ts
+++ b/packages/localizations/src/he-IL.ts
@@ -729,6 +729,7 @@ export const heIL: LocalizationResource = {
},
verifiedAtLabel: "אומת בתאריך {{ date | shortDate('he-IL') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'הוסף {{domain}}',
diff --git a/packages/localizations/src/hi-IN.ts b/packages/localizations/src/hi-IN.ts
index 3331c95b3a3..d0cd1f54b29 100644
--- a/packages/localizations/src/hi-IN.ts
+++ b/packages/localizations/src/hi-IN.ts
@@ -736,6 +736,7 @@ export const hiIN: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('hi-IN') }} को सत्यापित",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} जोड़ें',
diff --git a/packages/localizations/src/hr-HR.ts b/packages/localizations/src/hr-HR.ts
index 3cd2486c91a..9645fe74204 100644
--- a/packages/localizations/src/hr-HR.ts
+++ b/packages/localizations/src/hr-HR.ts
@@ -737,6 +737,7 @@ export const hrHR: LocalizationResource = {
},
verifiedAtLabel: "Potvrđeno {{ date | shortDate('hr-HR') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Dodaj {{domain}}',
diff --git a/packages/localizations/src/hu-HU.ts b/packages/localizations/src/hu-HU.ts
index ecbc5857b1c..71205a85475 100644
--- a/packages/localizations/src/hu-HU.ts
+++ b/packages/localizations/src/hu-HU.ts
@@ -737,6 +737,7 @@ export const huHU: LocalizationResource = {
},
verifiedAtLabel: "Igazolva: {{ date | shortDate('hu-HU') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} hozzáadása',
diff --git a/packages/localizations/src/id-ID.ts b/packages/localizations/src/id-ID.ts
index 890a5432be7..b52d005b444 100644
--- a/packages/localizations/src/id-ID.ts
+++ b/packages/localizations/src/id-ID.ts
@@ -730,6 +730,7 @@ export const idID: LocalizationResource = {
},
verifiedAtLabel: "Diverifikasi pada {{ date | shortDate('id-ID') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Tambah {{domain}}',
diff --git a/packages/localizations/src/is-IS.ts b/packages/localizations/src/is-IS.ts
index bbea10b5afd..12bc9f56ffc 100644
--- a/packages/localizations/src/is-IS.ts
+++ b/packages/localizations/src/is-IS.ts
@@ -736,6 +736,7 @@ export const isIS: LocalizationResource = {
},
verifiedAtLabel: "Staðfest {{ date | shortDate('is-IS') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Bæta við {{domain}}',
diff --git a/packages/localizations/src/it-IT.ts b/packages/localizations/src/it-IT.ts
index 0919d7813ef..ac9b79722b0 100644
--- a/packages/localizations/src/it-IT.ts
+++ b/packages/localizations/src/it-IT.ts
@@ -736,6 +736,7 @@ export const itIT: LocalizationResource = {
},
verifiedAtLabel: "Verificato il {{ date | shortDate('it-IT') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Aggiungi {{domain}}',
diff --git a/packages/localizations/src/ja-JP.ts b/packages/localizations/src/ja-JP.ts
index 79b739b0e20..41c965b8c0e 100644
--- a/packages/localizations/src/ja-JP.ts
+++ b/packages/localizations/src/ja-JP.ts
@@ -737,6 +737,7 @@ export const jaJP: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('ja-JP') }} に確認",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} を追加',
diff --git a/packages/localizations/src/kk-KZ.ts b/packages/localizations/src/kk-KZ.ts
index 5739bb8e83f..ba8406ebf59 100644
--- a/packages/localizations/src/kk-KZ.ts
+++ b/packages/localizations/src/kk-KZ.ts
@@ -730,6 +730,7 @@ export const kkKZ: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('kk-KZ') }} күні расталды",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} қосу',
diff --git a/packages/localizations/src/ko-KR.ts b/packages/localizations/src/ko-KR.ts
index 4070b2a7d16..f236577d12c 100644
--- a/packages/localizations/src/ko-KR.ts
+++ b/packages/localizations/src/ko-KR.ts
@@ -733,6 +733,7 @@ export const koKR: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('ko-KR') }}에 확인됨",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} 추가',
diff --git a/packages/localizations/src/mn-MN.ts b/packages/localizations/src/mn-MN.ts
index 66ad147f594..40dffe38626 100644
--- a/packages/localizations/src/mn-MN.ts
+++ b/packages/localizations/src/mn-MN.ts
@@ -730,6 +730,7 @@ export const mnMN: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('mn-MN') }}-нд баталгаажсан",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} нэмэх',
diff --git a/packages/localizations/src/ms-MY.ts b/packages/localizations/src/ms-MY.ts
index 28f3b8fa362..1604f3a2309 100644
--- a/packages/localizations/src/ms-MY.ts
+++ b/packages/localizations/src/ms-MY.ts
@@ -738,6 +738,7 @@ export const msMY: LocalizationResource = {
},
verifiedAtLabel: "Disahkan pada {{ date | shortDate('ms-MY') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Tambah {{domain}}',
diff --git a/packages/localizations/src/nb-NO.ts b/packages/localizations/src/nb-NO.ts
index 634d14772cf..eddd40a1dea 100644
--- a/packages/localizations/src/nb-NO.ts
+++ b/packages/localizations/src/nb-NO.ts
@@ -737,6 +737,7 @@ export const nbNO: LocalizationResource = {
},
verifiedAtLabel: "Verifisert den {{ date | shortDate('nb-NO') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Legg til {{domain}}',
diff --git a/packages/localizations/src/nl-BE.ts b/packages/localizations/src/nl-BE.ts
index 7584091ffb9..ed31d02378c 100644
--- a/packages/localizations/src/nl-BE.ts
+++ b/packages/localizations/src/nl-BE.ts
@@ -730,6 +730,7 @@ export const nlBE: LocalizationResource = {
},
verifiedAtLabel: "Geverifieerd op {{ date | shortDate('nl-BE') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} toevoegen',
diff --git a/packages/localizations/src/nl-NL.ts b/packages/localizations/src/nl-NL.ts
index 3bc6bff7ac1..e42798d2b1f 100644
--- a/packages/localizations/src/nl-NL.ts
+++ b/packages/localizations/src/nl-NL.ts
@@ -730,6 +730,7 @@ export const nlNL: LocalizationResource = {
},
verifiedAtLabel: "Geverifieerd op {{ date | shortDate('nl-NL') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} toevoegen',
diff --git a/packages/localizations/src/pl-PL.ts b/packages/localizations/src/pl-PL.ts
index be54a14ff4e..4ecf0d19412 100644
--- a/packages/localizations/src/pl-PL.ts
+++ b/packages/localizations/src/pl-PL.ts
@@ -730,6 +730,7 @@ export const plPL: LocalizationResource = {
},
verifiedAtLabel: "Zweryfikowano {{ date | shortDate('pl-PL') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Dodaj {{domain}}',
diff --git a/packages/localizations/src/pt-BR.ts b/packages/localizations/src/pt-BR.ts
index 42e0c5b08f7..5d34ce28b37 100644
--- a/packages/localizations/src/pt-BR.ts
+++ b/packages/localizations/src/pt-BR.ts
@@ -736,6 +736,7 @@ export const ptBR: LocalizationResource = {
},
verifiedAtLabel: "Verificado em {{ date | shortDate('pt-BR') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Adicionar {{domain}}',
diff --git a/packages/localizations/src/pt-PT.ts b/packages/localizations/src/pt-PT.ts
index d136f7b6fca..08d29400c7f 100644
--- a/packages/localizations/src/pt-PT.ts
+++ b/packages/localizations/src/pt-PT.ts
@@ -738,6 +738,7 @@ export const ptPT: LocalizationResource = {
},
verifiedAtLabel: "Verificado em {{ date | shortDate('pt-PT') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Adicionar {{domain}}',
diff --git a/packages/localizations/src/ro-RO.ts b/packages/localizations/src/ro-RO.ts
index ffb22de2fc2..d197fb3791b 100644
--- a/packages/localizations/src/ro-RO.ts
+++ b/packages/localizations/src/ro-RO.ts
@@ -736,6 +736,7 @@ export const roRO: LocalizationResource = {
},
verifiedAtLabel: "Verificat pe {{ date | shortDate('ro-RO') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Adaugă {{domain}}',
diff --git a/packages/localizations/src/ru-RU.ts b/packages/localizations/src/ru-RU.ts
index a8552a376d7..214e3b26a70 100644
--- a/packages/localizations/src/ru-RU.ts
+++ b/packages/localizations/src/ru-RU.ts
@@ -730,6 +730,7 @@ export const ruRU: LocalizationResource = {
},
verifiedAtLabel: "Подтверждён {{ date | shortDate('ru-RU') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Добавить {{domain}}',
diff --git a/packages/localizations/src/sk-SK.ts b/packages/localizations/src/sk-SK.ts
index 386d4b8e6a2..e8dc2b08b04 100644
--- a/packages/localizations/src/sk-SK.ts
+++ b/packages/localizations/src/sk-SK.ts
@@ -730,6 +730,7 @@ export const skSK: LocalizationResource = {
},
verifiedAtLabel: "Overené {{ date | shortDate('sk-SK') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Pridať {{domain}}',
diff --git a/packages/localizations/src/sr-RS.ts b/packages/localizations/src/sr-RS.ts
index 729042ee9f9..8782ebf5ffc 100644
--- a/packages/localizations/src/sr-RS.ts
+++ b/packages/localizations/src/sr-RS.ts
@@ -730,6 +730,7 @@ export const srRS: LocalizationResource = {
},
verifiedAtLabel: "Potvrđeno {{ date | shortDate('sr-RS') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Dodaj {{domain}}',
diff --git a/packages/localizations/src/sv-SE.ts b/packages/localizations/src/sv-SE.ts
index 12cea3490e5..1b49c1a42b7 100644
--- a/packages/localizations/src/sv-SE.ts
+++ b/packages/localizations/src/sv-SE.ts
@@ -730,6 +730,7 @@ export const svSE: LocalizationResource = {
},
verifiedAtLabel: "Verifierad den {{ date | shortDate('sv-SE') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Lägg till {{domain}}',
diff --git a/packages/localizations/src/ta-IN.ts b/packages/localizations/src/ta-IN.ts
index c4c30019d93..f0f2f508bb7 100644
--- a/packages/localizations/src/ta-IN.ts
+++ b/packages/localizations/src/ta-IN.ts
@@ -738,6 +738,7 @@ export const taIN: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('ta-IN') }} அன்று சரிபார்க்கப்பட்டது",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} ஐச் சேர்',
diff --git a/packages/localizations/src/te-IN.ts b/packages/localizations/src/te-IN.ts
index 3e523d8d58d..b6baf26ade6 100644
--- a/packages/localizations/src/te-IN.ts
+++ b/packages/localizations/src/te-IN.ts
@@ -737,6 +737,7 @@ export const teIN: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('te-IN') }} న ధృవీకరించబడింది",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} జోడించు',
diff --git a/packages/localizations/src/th-TH.ts b/packages/localizations/src/th-TH.ts
index b86fd886f32..2abb81e961d 100644
--- a/packages/localizations/src/th-TH.ts
+++ b/packages/localizations/src/th-TH.ts
@@ -733,6 +733,7 @@ export const thTH: LocalizationResource = {
},
verifiedAtLabel: "ยืนยันเมื่อ {{ date | shortDate('th-TH') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'เพิ่ม {{domain}}',
diff --git a/packages/localizations/src/tr-TR.ts b/packages/localizations/src/tr-TR.ts
index 34ae01d2949..ad8ebbf56c6 100644
--- a/packages/localizations/src/tr-TR.ts
+++ b/packages/localizations/src/tr-TR.ts
@@ -730,6 +730,7 @@ export const trTR: LocalizationResource = {
},
verifiedAtLabel: "{{ date | shortDate('tr-TR') }} tarihinde doğrulandı",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '{{domain}} ekle',
diff --git a/packages/localizations/src/uk-UA.ts b/packages/localizations/src/uk-UA.ts
index d30dea0a59c..fb408990086 100644
--- a/packages/localizations/src/uk-UA.ts
+++ b/packages/localizations/src/uk-UA.ts
@@ -730,6 +730,7 @@ export const ukUA: LocalizationResource = {
},
verifiedAtLabel: "Підтверджено {{ date | shortDate('uk-UA') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Додати {{domain}}',
diff --git a/packages/localizations/src/vi-VN.ts b/packages/localizations/src/vi-VN.ts
index 266cc6d915e..f953808cc7b 100644
--- a/packages/localizations/src/vi-VN.ts
+++ b/packages/localizations/src/vi-VN.ts
@@ -736,6 +736,7 @@ export const viVN: LocalizationResource = {
},
verifiedAtLabel: "Đã xác minh vào {{ date | shortDate('vi-VN') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: 'Thêm {{domain}}',
diff --git a/packages/localizations/src/zh-CN.ts b/packages/localizations/src/zh-CN.ts
index 56a9b1b385a..34cddcdd6c3 100644
--- a/packages/localizations/src/zh-CN.ts
+++ b/packages/localizations/src/zh-CN.ts
@@ -729,6 +729,7 @@ export const zhCN: LocalizationResource = {
},
verifiedAtLabel: "验证于 {{ date | shortDate('zh-CN') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '添加 {{domain}}',
diff --git a/packages/localizations/src/zh-TW.ts b/packages/localizations/src/zh-TW.ts
index 3b8462c96ea..aa0583b1bd4 100644
--- a/packages/localizations/src/zh-TW.ts
+++ b/packages/localizations/src/zh-TW.ts
@@ -732,6 +732,7 @@ export const zhTW: LocalizationResource = {
},
verifiedAtLabel: "驗證於 {{ date | shortDate('zh-TW') }}",
verifyAgainButton: undefined,
+ verifyAgainButtonTooltip__throttled: undefined,
},
domainSuggestion: {
formButtonPrimary__add: '新增 {{domain}}',
diff --git a/packages/shared/src/types/localization.ts b/packages/shared/src/types/localization.ts
index efb96c465cc..9d8f976430d 100644
--- a/packages/shared/src/types/localization.ts
+++ b/packages/shared/src/types/localization.ts
@@ -1442,6 +1442,7 @@ export type __internal_LocalizationResource = {
expiredAtLabel: LocalizationValue<'date'>;
expiredLabel: LocalizationValue;
verifyAgainButton: LocalizationValue;
+ verifyAgainButtonTooltip__throttled: LocalizationValue;
removeButtonTooltip__lastVerifiedDomain: LocalizationValue;
removeButtonTooltip__lastVerifiedDomainActive: LocalizationValue;
txtRecord: {
diff --git a/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx b/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx
index b5309a864c5..6a5e7dcbdaf 100644
--- a/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx
+++ b/packages/ui/src/components/ConfigureSSO/__tests__/ConfigureSSO.test.tsx
@@ -1,7 +1,7 @@
-import { describe, expect, it } from 'vitest';
+import { afterEach, describe, expect, it, vi } from 'vitest';
import { bindCreateFixtures } from '@/test/create-fixtures';
-import { render, waitFor } from '@/test/utils';
+import { act, render, waitFor } from '@/test/utils';
import { ConfigureSSO } from '../ConfigureSSO';
@@ -23,10 +23,19 @@ const unverifiedDomain = {
ownershipVerification: { status: 'unverified', strategy: 'txt' },
} as any;
+const expiredDomain = {
+ ...unverifiedDomain,
+ ownershipVerification: { status: 'expired', strategy: 'txt', expiresAt: new Date('2026-01-01') },
+};
+
const mockOrganizationDomains = (fixtures: any, domains: any[]) =>
fixtures.clerk.organization?.getDomains.mockResolvedValue({ data: domains, total_count: domains.length } as any);
describe('ConfigureSSO', () => {
+ afterEach(() => {
+ vi.useRealTimers();
+ });
+
describe('within an organization', () => {
it('shows a warning if the active organization membership lacks the manage enterprise connections permission', async () => {
const { wrapper, fixtures } = await createFixtures(f => {
@@ -158,6 +167,113 @@ describe('ConfigureSSO', () => {
expect(queryByText(/select your identity provider/i)).not.toBeInTheDocument();
});
+ it('shows the verification retry action while domain ownership verification is pending', async () => {
+ const { wrapper, fixtures } = await createFixtures(f => {
+ f.withEnterpriseSso({ selfServeSSO: true });
+ f.withEmailAddress();
+ f.withOrganizations();
+ f.withUser({
+ email_addresses: ['test@clerk.com'],
+ organization_memberships: [{ name: 'Org1', permissions: ['org:sys_entconns:manage'] }],
+ });
+ });
+
+ fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]);
+ mockOrganizationDomains(fixtures, [unverifiedDomain]);
+
+ const { findByRole } = render(, { wrapper });
+
+ await findByRole('button', { name: /re-issue/i });
+ });
+
+ it('throttles domain verification retries for five minutes', async () => {
+ const { wrapper, fixtures } = await createFixtures(f => {
+ f.withEnterpriseSso({ selfServeSSO: true });
+ f.withEmailAddress();
+ f.withOrganizations();
+ f.withUser({
+ email_addresses: ['test@clerk.com'],
+ organization_memberships: [{ name: 'Org1', permissions: ['org:sys_entconns:manage'] }],
+ });
+ });
+
+ fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]);
+ mockOrganizationDomains(fixtures, [expiredDomain]);
+ fixtures.clerk.organization?.prepareOwnershipVerification.mockResolvedValue({ data: [expiredDomain] } as any);
+
+ const { findByRole, getByRole } = render(, { wrapper });
+ await findByRole('button', { name: /re-issue/i });
+
+ vi.useFakeTimers();
+ await act(() => {
+ getByRole('button', { name: /re-issue/i }).click();
+ return Promise.resolve();
+ });
+
+ expect(fixtures.clerk.organization?.prepareOwnershipVerification).toHaveBeenCalledWith([expiredDomain.id]);
+ expect(getByRole('button', { name: /re-issue/i })).toBeDisabled();
+
+ act(() => {
+ vi.advanceTimersByTime(5 * 60 * 1000);
+ });
+
+ expect(getByRole('button', { name: /re-issue/i })).not.toBeDisabled();
+ });
+
+ it('explains the cooldown while a domain verification retry is throttled', async () => {
+ const { wrapper, fixtures } = await createFixtures(f => {
+ f.withEnterpriseSso({ selfServeSSO: true });
+ f.withEmailAddress();
+ f.withOrganizations();
+ f.withUser({
+ email_addresses: ['test@clerk.com'],
+ organization_memberships: [{ name: 'Org1', permissions: ['org:sys_entconns:manage'] }],
+ });
+ });
+
+ fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]);
+ mockOrganizationDomains(fixtures, [expiredDomain]);
+ fixtures.clerk.organization?.prepareOwnershipVerification.mockResolvedValue({ data: [expiredDomain] } as any);
+
+ const { findByRole, getByRole, findByText, userEvent } = render(, { wrapper });
+ await userEvent.click(await findByRole('button', { name: /re-issue/i }));
+
+ const throttledButton = await waitFor(() => {
+ const button = getByRole('button', { name: /re-issue/i });
+ expect(button).toBeDisabled();
+ return button;
+ });
+
+ await userEvent.hover(throttledButton.parentElement as HTMLElement);
+ await findByText(/you can issue another one shortly/i);
+ });
+
+ it('does not throttle domain verification retries when the request fails', async () => {
+ const { wrapper, fixtures } = await createFixtures(f => {
+ f.withEnterpriseSso({ selfServeSSO: true });
+ f.withEmailAddress();
+ f.withOrganizations();
+ f.withUser({
+ email_addresses: ['test@clerk.com'],
+ organization_memberships: [{ name: 'Org1', permissions: ['org:sys_entconns:manage'] }],
+ });
+ });
+
+ fixtures.clerk.organization?.getEnterpriseConnections.mockResolvedValue([]);
+ mockOrganizationDomains(fixtures, [expiredDomain]);
+ fixtures.clerk.organization?.prepareOwnershipVerification.mockRejectedValue(new Error('nope'));
+
+ const { findByRole, getByRole } = render(, { wrapper });
+ await findByRole('button', { name: /re-issue/i });
+
+ await act(() => {
+ getByRole('button', { name: /re-issue/i }).click();
+ return Promise.resolve();
+ });
+
+ expect(getByRole('button', { name: /re-issue/i })).not.toBeDisabled();
+ });
+
it('short-circuits to the activate step for an active connection', async () => {
const { wrapper, fixtures } = await createFixtures(f => {
f.withEnterpriseSso({ selfServeSSO: true });
diff --git a/packages/ui/src/components/ConfigureSSO/steps/OrganizationDomainsStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/OrganizationDomainsStep.tsx
index 8c449089080..1d490563f31 100644
--- a/packages/ui/src/components/ConfigureSSO/steps/OrganizationDomainsStep.tsx
+++ b/packages/ui/src/components/ConfigureSSO/steps/OrganizationDomainsStep.tsx
@@ -36,6 +36,8 @@ import { Step } from '../elements/Step';
import { useWizard } from '../elements/Wizard/WizardContext';
import { RemoveDomainDialog } from '../RemoveDomainDialog';
+const OWNERSHIP_VERIFICATION_RETRY_THROTTLE_MS = 5 * 60 * 1000;
+
export const OrganizationDomainsStep = (): JSX.Element => {
const { t } = useLocalizations();
const {
@@ -81,14 +83,16 @@ export const OrganizationDomainsStep = (): JSX.Element => {
}
};
- const handlePrepareOwnershipVerification = async (domain: OrganizationDomainResource) => {
+ const handlePrepareOwnershipVerification = async (domain: OrganizationDomainResource): Promise => {
card.setError(undefined);
try {
await prepareOwnershipVerification([domain]);
+ return true;
} catch (err: any) {
const apiError = getFieldError(err) ?? getGlobalError(err);
card.setError(apiError);
+ return false;
}
};
@@ -371,10 +375,23 @@ const DomainCard = ({
}: {
domain: OrganizationDomainResource;
onRemove: () => void;
- onPrepareOwnershipVerification: () => Promise;
+ onPrepareOwnershipVerification: () => Promise;
isRemoveDisabled?: boolean;
removeDisabledTooltip?: ReturnType;
}): JSX.Element | null => {
+ const [isVerifying, setIsVerifying] = useState(false);
+ const [isRetryThrottled, setIsRetryThrottled] = useState(false);
+
+ useEffect(() => {
+ if (!isRetryThrottled) {
+ return;
+ }
+
+ const timeoutId = window.setTimeout(() => setIsRetryThrottled(false), OWNERSHIP_VERIFICATION_RETRY_THROTTLE_MS);
+
+ return () => window.clearTimeout(timeoutId);
+ }, [isRetryThrottled]);
+
if (!domain.name) {
return null;
}
@@ -384,6 +401,21 @@ const DomainCard = ({
const isExpired = ownershipVerification?.status === 'expired';
const cardId = ownershipVerification?.status ?? 'unverified';
+ const handleVerificationRetry = () => {
+ setIsVerifying(true);
+ void onPrepareOwnershipVerification()
+ .then(setIsRetryThrottled)
+ .finally(() => setIsVerifying(false));
+ };
+
+ const retryButton = (
+
+ );
+
const removeButton = (
) : ownershipVerification?.verifiedAt ? (
)}
@@ -498,18 +531,11 @@ const DomainCard = ({
const ExpiredNotice = ({
expiresAt,
- onPrepareOwnershipVerification,
+ retryButton,
}: {
expiresAt: Date | null;
- onPrepareOwnershipVerification: () => Promise;
+ retryButton: JSX.Element;
}): JSX.Element => {
- const [isVerifying, setIsVerifying] = useState(false);
-
- const handleVerifyAgain = () => {
- setIsVerifying(true);
- void onPrepareOwnershipVerification().finally(() => setIsVerifying(false));
- };
-
return (
-
+ {retryButton}
);
};
+const VerificationRetryButton = ({
+ isVerifying,
+ isThrottled,
+ onClick,
+}: {
+ isVerifying: boolean;
+ isThrottled: boolean;
+ onClick: () => void;
+}): JSX.Element => {
+ const button = (
+
+ );
+
+ if (!isThrottled) {
+ return button;
+ }
+
+ return (
+
+ {button}
+
+
+ );
+};
+
const TxtRecord = ({
ownershipVerification,
+ retryButton,
}: {
ownershipVerification: OrganizationDomainResource['ownershipVerification'];
+ retryButton: JSX.Element;
}): JSX.Element => {
return (
+
+ {retryButton}
);