- 
                Notifications
    
You must be signed in to change notification settings  - Fork 402
 
chore(clerk-js,backend): Remove secret key column in API keys component #7107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
          🦋 Changeset detectedLatest commit: 4aeab7b The changes in this PR will be included in the next version bump. This PR includes changesets to release 15 packages
 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  | 
    
| 
           The latest updates on your projects. Learn more about Vercel for GitHub. 
  | 
    
          
WalkthroughSecrets for API keys are shown only once immediately after creation via a one-time modal; the persistent Key column and backend/frontend getSecret() method were removed. Created API key responses may include an optional  Changes
 Sequence Diagram(s)sequenceDiagram
    actor User
    participant UI as API Keys UI
    participant Backend as Backend API
    participant Modal as CopyApiKeyModal
    participant Clipboard as Clipboard
    User->>UI: Click "Create API Key"
    UI->>Backend: POST /api_keys (create)
    Backend-->>UI: 201 { id, name, secret? }
    UI->>Modal: Open with apiKeyName + secret
    User->>Modal: Click "Copy & Close"
    Modal->>Clipboard: write(secret)
    Clipboard-->>User: secret copied
    Modal->>UI: Close modal
    Note right of UI: Secret not retrievable after creation
    sequenceDiagram
    participant Old as Old Flow (removed)
    participant New as New Flow (current)
    Note over Old: Persistent table + getSecret() allowed viewing later
    Old->>Old: Secret column shows secret
    Old->>Old: API client can call getSecret(id)
    Note over New: One-time modal, no later retrieval
    New->>New: Create API key -> response contains secret
    New->>New: Modal shows secret once -> user copies -> modal closes
    New->>New: No getSecret() API available anymore
    Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 
 Poem
 Pre-merge checks and finishing touches✅ Passed checks (4 passed)
 ✨ Finishing touches
 🧪 Generate unit tests (beta)
 Comment   | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
integration/testUtils/usersService.ts (1)
209-209: Let me check the usage of the secret from createFakeAPIKey and any context around this change:Now let me check how the secret from
createFakeAPIKeyis actually used in tests:Improve error handling by validating API key secret presence instead of using empty string fallback.
The empty string fallback masks potential API contract violations. Since
APIKey.secretis optional butFakeAPIKey.secretis required, consider one of these approaches:
- Throw a clear error if secret is missing — Helps catch API issues immediately during tests
 - Add explicit validation — Document why the fallback exists if it's intentional
 - Verify secret is always present in create response — Confirm this is guaranteed by Clerk's API
 Using an empty string as a fallback could cause confusing auth failures in integration tests that use this fake key, making it harder to debug actual issues.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
integration/testUtils/usersService.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
integration/testUtils/usersService.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
integration/testUtils/usersService.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
integration/testUtils/usersService.ts
integration/**
📄 CodeRabbit inference engine (.cursor/rules/global.mdc)
Framework integration templates and E2E tests should be placed under the integration/ directory
Files:
integration/testUtils/usersService.ts
integration/**/*
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
End-to-end tests and integration templates must be located in the 'integration/' directory.
Files:
integration/testUtils/usersService.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
integration/testUtils/usersService.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Analyze (javascript-typescript)
 - GitHub Check: semgrep-cloud-platform/scan
 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️  Outside diff range comments (1)
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx (1)
39-43: Localize revoke input and handle API errors
- Replace hard-coded label/placeholder with localization keys.
 - Wrap revoke() in try/catch and use handleError to surface failures.
 Example:
- const revokeField = useFormControl('apiKeyRevokeConfirmation', '', { - type: 'text', - label: `Type "Revoke" to confirm`, - placeholder: 'Revoke', - isRequired: true, - }); + const revokeField = useFormControl('apiKeyRevokeConfirmation', '', { + type: 'text', + label: localizationKeys('formFieldLabel__confirmDeletion'), + placeholder: localizationKeys('apiKeys.revokeConfirmation.confirmationText'), + isRequired: true, + }); @@ - await clerk.apiKeys.revoke({ apiKeyID: apiKeyId }); + try { + await clerk.apiKeys.revoke({ apiKeyID: apiKeyId }); + } catch (e) { + // Use the standard error utility to report and localize the error + // handleError(e); + return; + }Note: import and exact handleError path per project conventions. Based on coding guidelines.
Also applies to: 52-63
♻️ Duplicate comments (1)
packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
13-15: Fix a11y and form behavior; add return type (same as previously requested)
- Remove tabIndex={-1} to keep the button focusable.
 - Add aria-label and type='button' to avoid accidental form submit.
 - Add explicit return type for the exported component.
 -export const ClipboardInput = (props: ClipboardInputProps) => { +export const ClipboardInput = (props: ClipboardInputProps): JSX.Element => { @@ - <Button + <Button elementDescriptor={descriptors.formFieldInputCopyToClipboardButton} variant='ghost' - tabIndex={-1} onClick={onCopy} + aria-label='Copy to clipboard' + type='button' sx={{ position: 'absolute', right: 0, }} >Optional: defensively coerce value for useClipboard:
- const { onCopy, hasCopied } = useClipboard(value as string); + const { onCopy, hasCopied } = useClipboard(String(value ?? ''));Also applies to: 30-46
🧹 Nitpick comments (6)
packages/localizations/src/he-IL.ts (1)
20-24: LGTM - Structure is correct for the new copy secret modal.The nested
copySecretobject correctly extends the API keys localization with the required fields for the one-time secret display modal. While the values areundefined(no Hebrew translations provided yet), this is consistent with the community-contributed nature of this file where many translations are pending.Consider providing Hebrew translations for these new fields to improve the user experience for Hebrew-speaking users, though this can be deferred to a future contribution.
packages/localizations/src/es-UY.ts (2)
20-24: Structure looks good; consider adding Spanish translations.The
copySecretnested object follows the established pattern and correctly implements the localization structure for the one-time API key secret display feature. The undefined values are consistent with this file's community-maintained status.However, since this is a security-critical feature, providing Spanish translations for these fields would significantly improve the user experience for Uruguayan Spanish speakers.
Consider adding translations for:
formButtonPrimary__copyAndClose: e.g., "Copiar y cerrar"formHint: Appropriate hint text about the one-time nature of the secret displayformTitle: e.g., "Clave secreta de API" or similarcopySecret: { - formButtonPrimary__copyAndClose: undefined, - formHint: undefined, - formTitle: undefined, + formButtonPrimary__copyAndClose: 'Copiar y cerrar', + formHint: 'Guardá esta clave de forma segura. Solo se mostrará una vez.', + formTitle: 'Clave secreta de API', },
230-230: Label field correctly added; translation recommended.The
formFieldLabel__apiKeyfield is properly positioned and follows the established naming convention. The undefined value is consistent with the file's current state.Consider adding a Spanish translation to improve UX:
- formFieldLabel__apiKey: undefined, + formFieldLabel__apiKey: 'Clave de API',integration/tests/machine-auth/component.test.ts (1)
133-147: Consider moving permission cleanup to ensure it runs even on test failure.The clipboard permissions are granted and cleared within the test flow, but if the test fails before reaching line 146, permissions may not be cleaned up. Consider using a try-finally block or moving the cleanup to an appropriate lifecycle hook.
Example approach:
- // Grant clipboard permissions before clicking the button await context.grantPermissions(['clipboard-read']); + + try { + // Click "Copy & Close" button which will copy the secret and close the modal + const copyAndCloseButton = copyModal.locator('.cl-apiKeysCopyModalSubmitButton'); + await copyAndCloseButton.waitFor({ state: 'attached' }); + await copyAndCloseButton.click(); - // Click "Copy & Close" button which will copy the secret and close the modal - const copyAndCloseButton = copyModal.locator('.cl-apiKeysCopyModalSubmitButton'); - await copyAndCloseButton.waitFor({ state: 'attached' }); - await copyAndCloseButton.click(); + // Wait for modal to close + await copyModal.waitFor({ state: 'detached' }); - // Wait for modal to close - await copyModal.waitFor({ state: 'detached' }); + // Read clipboard contents to verify the secret was copied + const clipboardText = await page.evaluate('navigator.clipboard.readText()'); + expect(clipboardText).toBe(secret); + } finally { + await context.clearPermissions(); + } - - // Read clipboard contents to verify the secret was copied - const clipboardText = await page.evaluate('navigator.clipboard.readText()'); - await context.clearPermissions(); - expect(clipboardText).toBe(secret);packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (2)
32-36: Use a more descriptive ID for the form control.The form control ID is set to
'name', but this field displays the API key secret, not a name. Consider using a more descriptive identifier like'apiKeySecret'or'apiKey'to improve code clarity and avoid potential conflicts.Apply this diff:
- const apiKeyField = useFormControl('name', apiKeySecret, { + const apiKeyField = useFormControl('apiKeySecret', apiKeySecret, { type: 'text', label: localizationKeys('formFieldLabel__apiKey'), isRequired: false, });
76-84: Consider simplifying the read-only field implementation.The
useFormControlhook provides interactive form field machinery (onChange, onFocus, validation, etc.), butClipboardInputis inherently read-only and disabled. The form control logic isn't actively used here. Consider whether a simpler approach with just a label and theClipboardInputwould be more appropriate.Alternative approach:
<Form.ControlRow elementDescriptor={descriptors.apiKeysCopyModalInput} sx={{ flex: 1 }} > <Form.Label localizationKey={localizationKeys('formFieldLabel__apiKey')} /> <ClipboardInput value={apiKeySecret} readOnly sx={{ width: '100%' }} copyIcon={ClipboardOutline} copiedIcon={Check} /> </Form.ControlRow>However, if
Form.CommonInputWrapperprovides necessary styling or structure for consistency with other forms, the current approach is acceptable.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (59)
integration/tests/machine-auth/component.test.ts(2 hunks)packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx(5 hunks)packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx(2 hunks)packages/clerk-js/src/ui/components/ApiKeys/utils.ts(1 hunks)packages/clerk-js/src/ui/customizables/elementDescriptors.ts(1 hunks)packages/clerk-js/src/ui/elements/ClipboardInput.tsx(2 hunks)packages/clerk-js/src/ui/elements/Form.tsx(1 hunks)packages/localizations/src/ar-SA.ts(2 hunks)packages/localizations/src/be-BY.ts(2 hunks)packages/localizations/src/bg-BG.ts(2 hunks)packages/localizations/src/bn-IN.ts(2 hunks)packages/localizations/src/ca-ES.ts(2 hunks)packages/localizations/src/cs-CZ.ts(2 hunks)packages/localizations/src/da-DK.ts(2 hunks)packages/localizations/src/de-DE.ts(2 hunks)packages/localizations/src/el-GR.ts(2 hunks)packages/localizations/src/en-GB.ts(2 hunks)packages/localizations/src/en-US.ts(2 hunks)packages/localizations/src/es-CR.ts(2 hunks)packages/localizations/src/es-ES.ts(2 hunks)packages/localizations/src/es-MX.ts(2 hunks)packages/localizations/src/es-UY.ts(2 hunks)packages/localizations/src/fa-IR.ts(2 hunks)packages/localizations/src/fi-FI.ts(2 hunks)packages/localizations/src/fr-FR.ts(2 hunks)packages/localizations/src/he-IL.ts(2 hunks)packages/localizations/src/hi-IN.ts(2 hunks)packages/localizations/src/hr-HR.ts(2 hunks)packages/localizations/src/hu-HU.ts(2 hunks)packages/localizations/src/id-ID.ts(2 hunks)packages/localizations/src/is-IS.ts(2 hunks)packages/localizations/src/it-IT.ts(2 hunks)packages/localizations/src/ja-JP.ts(2 hunks)packages/localizations/src/kk-KZ.ts(2 hunks)packages/localizations/src/ko-KR.ts(2 hunks)packages/localizations/src/mn-MN.ts(2 hunks)packages/localizations/src/ms-MY.ts(2 hunks)packages/localizations/src/nb-NO.ts(2 hunks)packages/localizations/src/nl-BE.ts(2 hunks)packages/localizations/src/nl-NL.ts(2 hunks)packages/localizations/src/pl-PL.ts(2 hunks)packages/localizations/src/pt-BR.ts(2 hunks)packages/localizations/src/pt-PT.ts(2 hunks)packages/localizations/src/ro-RO.ts(2 hunks)packages/localizations/src/ru-RU.ts(2 hunks)packages/localizations/src/sk-SK.ts(2 hunks)packages/localizations/src/sr-RS.ts(2 hunks)packages/localizations/src/sv-SE.ts(2 hunks)packages/localizations/src/ta-IN.ts(2 hunks)packages/localizations/src/te-IN.ts(2 hunks)packages/localizations/src/th-TH.ts(2 hunks)packages/localizations/src/tr-TR.ts(2 hunks)packages/localizations/src/uk-UA.ts(2 hunks)packages/localizations/src/vi-VN.ts(2 hunks)packages/localizations/src/zh-CN.ts(2 hunks)packages/localizations/src/zh-TW.ts(2 hunks)packages/shared/src/types/appearance.ts(1 hunks)packages/shared/src/types/localization.ts(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (33)
- packages/localizations/src/kk-KZ.ts
 - packages/localizations/src/is-IS.ts
 - packages/localizations/src/es-MX.ts
 - packages/localizations/src/mn-MN.ts
 - packages/localizations/src/ru-RU.ts
 - packages/localizations/src/tr-TR.ts
 - packages/localizations/src/en-US.ts
 - packages/localizations/src/pt-BR.ts
 - packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
 - packages/localizations/src/de-DE.ts
 - packages/localizations/src/es-ES.ts
 - packages/localizations/src/hr-HR.ts
 - packages/localizations/src/it-IT.ts
 - packages/localizations/src/uk-UA.ts
 - packages/localizations/src/es-CR.ts
 - packages/localizations/src/th-TH.ts
 - packages/localizations/src/ar-SA.ts
 - packages/localizations/src/zh-TW.ts
 - packages/localizations/src/ms-MY.ts
 - packages/localizations/src/fi-FI.ts
 - packages/localizations/src/pl-PL.ts
 - packages/localizations/src/nb-NO.ts
 - packages/localizations/src/fa-IR.ts
 - packages/localizations/src/ca-ES.ts
 - packages/localizations/src/en-GB.ts
 - packages/localizations/src/ja-JP.ts
 - packages/localizations/src/sr-RS.ts
 - packages/localizations/src/pt-PT.ts
 - packages/localizations/src/hu-HU.ts
 - packages/localizations/src/fr-FR.ts
 - packages/shared/src/types/localization.ts
 - packages/localizations/src/bn-IN.ts
 - packages/localizations/src/nl-BE.ts
 
🧰 Additional context used
📓 Path-based instructions (14)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/clerk-js/src/ui/elements/Form.tsxpackages/clerk-js/src/ui/customizables/elementDescriptors.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
packages/localizations/**/*
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Localization files must be placed in 'packages/localizations/'.
Files:
packages/localizations/src/zh-CN.tspackages/localizations/src/vi-VN.tspackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tspackages/localizations/src/id-ID.tspackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/clerk-js/src/ui/elements/Form.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/clerk-js/src/ui/elements/Form.tsx
integration/**
📄 CodeRabbit inference engine (.cursor/rules/global.mdc)
Framework integration templates and E2E tests should be placed under the integration/ directory
Files:
integration/tests/machine-auth/component.test.ts
integration/**/*
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
End-to-end tests and integration templates must be located in the 'integration/' directory.
Files:
integration/tests/machine-auth/component.test.ts
integration/**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Integration tests should use Playwright.
Files:
integration/tests/machine-auth/component.test.ts
packages/clerk-js/src/ui/customizables/elementDescriptors.ts
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
Append new element descriptors to APPEARANCE_KEYS in packages/clerk-js/src/ui/customizables/elementDescriptors.ts
Files:
packages/clerk-js/src/ui/customizables/elementDescriptors.ts
🧠 Learnings (1)
📚 Learning: 2025-07-18T15:25:18.331Z
Learnt from: CR
Repo: clerk/javascript PR: 0
File: .cursor/rules/clerk-js-ui.mdc:0-0
Timestamp: 2025-07-18T15:25:18.331Z
Learning: Applies to packages/clerk-js/src/ui/customizables/elementDescriptors.ts : Append new element descriptors to APPEARANCE_KEYS in packages/clerk-js/src/ui/customizables/elementDescriptors.ts
Applied to files:
packages/clerk-js/src/ui/customizables/elementDescriptors.ts
🧬 Code graph analysis (4)
packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
packages/clerk-js/src/ui/styledSystem/types.ts (1)
ThemableCssProp(58-58)
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx (1)
packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
getApiKeyModalContainerStyles(8-29)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (6)
packages/clerk-js/src/ui/utils/useFormControl.ts (1)
useFormControl(97-189)packages/clerk-js/src/ui/elements/Modal.tsx (1)
Modal(25-108)packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
getApiKeyModalContainerStyles(8-29)packages/clerk-js/src/ui/elements/FormContainer.tsx (1)
FormContainer(20-61)packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
ClipboardInput(13-48)packages/clerk-js/src/ui/elements/FormButtons.tsx (1)
FormButtons(16-36)
packages/clerk-js/src/ui/elements/ClipboardInput.tsx (2)
packages/clerk-js/src/ui/styledSystem/types.ts (1)
PropsOfComponent(58-58)packages/clerk-js/src/ui/customizables/index.ts (1)
Flex(16-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build Packages
 - GitHub Check: Analyze (javascript-typescript)
 - GitHub Check: semgrep-cloud-platform/scan
 - GitHub Check: semgrep-cloud-platform/scan
 
🔇 Additional comments (35)
packages/localizations/src/nl-NL.ts (2)
20-24: LGTM! New localization structure added correctly.The new
copySecretnested object underapiKeysis properly structured and follows the established pattern of usingundefinedfor untranslated strings in this community-maintained locale file. This addition supports the new one-time API key secret display modal feature.
228-228: LGTM! Form field label added correctly.The new
formFieldLabel__apiKeyfield is properly placed among the other form field labels and follows the consistent pattern of usingundefinedfor missing translations in this community-maintained locale.packages/localizations/src/te-IN.ts (2)
20-24: LGTM! New API key copy secret localization structure added correctly.The new
copySecretnested object follows the correct structure and naming conventions. Theundefinedvalues are appropriate for this community-contributed locale, allowing fallback to the default language until Telugu translations are provided.
228-228: LGTM! API key form field label added correctly.The new
formFieldLabel__apiKeyfield is correctly placed in the form field labels section and follows the established naming convention. Theundefinedvalue is appropriate for this community-contributed locale.packages/localizations/src/be-BY.ts (2)
20-24: LGTM! Localization structure correctly added for one-time secret display.The
copySecretnested object is properly structured to support the new one-time API key secret display modal. The field names follow established conventions, andundefinedvalues are appropriate for this community-maintained locale pending translation.
230-230: LGTM! API key form field label correctly added.The
formFieldLabel__apiKeyfield is properly placed among other form field labels and follows the established naming convention. Theundefinedvalue is appropriate for this community-maintained locale.packages/localizations/src/ta-IN.ts (2)
20-24: Structure for "copy secret" modal added correctly.The nested
copySecretobject with its three fields follows the existing naming conventions and aligns with the PR's objective to support one-time secret display functionality. Theundefinedvalues indicate that Tamil translations are pending, which is acceptable for this community-contributed locale file (as noted in the file's disclaimer).
229-229: API key label field added correctly.The
formFieldLabel__apiKeyfield follows the established naming pattern and is positioned logically within the form field labels section. Theundefinedvalue indicates that a Tamil translation is pending, consistent with other untranslated fields in this community-contributed locale file.packages/localizations/src/he-IL.ts (1)
228-228: LGTM - Correctly adds API key form field label.The
formFieldLabel__apiKeyfield is properly placed within the form field labels section and follows the established naming convention. Like other fields in this community-contributed localization file, the Hebrew translation is pending (undefined).packages/localizations/src/id-ID.ts (2)
20-24: LGTM! Structure follows established patterns.The new
copySecretobject is correctly structured and follows the same pattern as other nested objects in this file (e.g.,revokeConfirmationat lines 48-53). Theundefinedvalues are appropriate for this community-maintained localization file awaiting Indonesian translations.
228-228: LGTM! Correctly placed and named.The new
formFieldLabel__apiKeyfield follows the established naming convention and is appropriately placed among other form field labels. Theundefinedvalue is consistent with this community-maintained localization file.packages/localizations/src/el-GR.ts (2)
20-24: LGTM! Structure is consistent with localization patterns.The new
copySecretnested group follows the established structure and naming conventions. Theundefinedvalues are appropriate for this community-contributed locale—translations can be provided by Greek-speaking contributors in the future.
229-229: LGTM! Consistent placement and naming.The
formFieldLabel__apiKeyfield is correctly placed alongside other form field labels and follows the established naming convention. Theundefinedvalue is expected for this community-contributed locale.packages/localizations/src/da-DK.ts (2)
20-24: Structural changes look good.The addition of the
copySecretobject underapiKeysaligns with the PR objective to display API key secrets one-time after creation. The field names follow proper naming conventions and the structure matches the expected localization pattern.Note: The
undefinedvalues mean Danish users will see fallback strings (likely English) for these new features, which is acceptable for a community-contributed localization file per the disclaimer at the top of the file.
229-229: Field addition is correct.The
formFieldLabel__apiKeyfield is properly placed among other form field labels and follows the established naming convention. This supports the new API key UI elements introduced in this PR.packages/localizations/src/sv-SE.ts (2)
20-24: LGTM! Structure is correct for the new API key secret copy feature.The nested
copySecretgroup follows the established localization pattern and aligns with the PR's one-time secret display functionality. Theundefinedvalues are acceptable for this community-maintained locale file per the disclaimer at the top—Swedish users will see fallback translations until community contributors provide Swedish text.
229-229: LGTM! New form field label follows conventions.The
formFieldLabel__apiKeykey follows the established naming pattern and is correctly positioned among other form field labels. Theundefinedvalue is consistent with this community-maintained file.packages/localizations/src/hi-IN.ts (2)
20-24: LGTM! Structure is correct for the one-time API key secret modal.The new
copySecretnested object underapiKeysfollows the correct structure for the one-time secret display feature. Theundefinedvalues are consistent with this file's pattern as a community-contributed locale where translations are not fully provided.
228-228: LGTM! Correctly adds the API key field label.The new
formFieldLabel__apiKeyfield is properly placed at the root level, following the naming convention and pattern used throughout the file. Theundefinedvalue is appropriate for this community-contributed locale.packages/localizations/src/ko-KR.ts (2)
20-24: LGTM! Structure and placement are correct.The new
copySecretobject is properly nested withinapiKeysand follows the established naming conventions. Theundefinedvalues are expected for this community-contributed localization file as noted in the disclaimer.
229-229: LGTM! Consistent placement and naming.The new
formFieldLabel__apiKeykey is correctly placed at the root level alongside otherformFieldLabel__*keys, following the established pattern in this localization file.packages/localizations/src/cs-CZ.ts (2)
20-24: Structure is correct; translations pending.The new
copySecretlocalization group is properly structured and follows established naming conventions. Theundefinedvalues are consistent with the file's disclaimer indicating this is a community-maintained localization that may have incomplete translations.Note: Czech translations for the new API key secret copy modal are missing. While this is acceptable given the community-maintained nature of this locale, consider tracking these for future translation completion to ensure Czech users have a complete experience.
233-233: Field addition is correct; translation missing.The new
formFieldLabel__apiKeyfield is properly placed and follows the established naming convention for form field labels. Theundefinedvalue is consistent with this locale's pattern for untranslated strings.As with the
copySecretgroup, consider adding this to the translation backlog for Czech locale completion.packages/localizations/src/ro-RO.ts (2)
20-24: LGTM: Copy secret modal localization structure added correctly.The new
copySecretnested object follows the established pattern and supports the one-time API key secret display feature. Usingundefinedvalues is appropriate for this community-contributed localization file, as stated in the file header disclaimer.
235-235: LGTM: API key form field label added correctly.The new
formFieldLabel__apiKeyproperty is properly placed among other form field labels and follows the established naming convention. Theundefinedvalue is appropriate given this is a community-contributed localization file.packages/localizations/src/vi-VN.ts (2)
233-233: LGTM: Form field label key added in correct location.The
formFieldLabel__apiKeyfield is properly placed within the form field labels section with appropriate naming convention. Theundefinedvalue is consistent with other untranslated strings in this community-contributed locale file.
20-24: Localization structure correctly aligned with source locale.The
copySecretnested group in vi-VN.ts has the correct structure matching the English locale, with appropriately named fields (formButtonPrimary__copyAndClose,formHint,formTitle). The undefined values are expected for this community-contributed file where Vietnamese translations are pending—the application will automatically fall back to English text for these strings.packages/localizations/src/bg-BG.ts (1)
20-24: Locales surface aligned for copy-secret flowKeys and shapes look correct; OK to ship with undefined placeholders (falls back to default locale). Please ensure all locales include these keys consistently.
Also applies to: 229-229
packages/localizations/src/zh-CN.ts (1)
20-24: Locales surface aligned for copy-secret flowAdditions match shared typings and other locales. Good to merge.
Also applies to: 228-229
packages/localizations/src/sk-SK.ts (1)
20-24: Locales surface aligned for copy-secret flowKeys are correct and consistent. Approved.
Also applies to: 229-229
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx (1)
75-76: Centralized modal container styling LGTMUsing getApiKeyModalContainerStyles improves consistency. Good change.
packages/shared/src/types/appearance.ts (1)
633-636: Appearance types updated for API key copy modalNew element entries look correct and align with UI usage.
packages/clerk-js/src/ui/customizables/elementDescriptors.ts (1)
498-501: Descriptors synced with new appearance keysAdditions are correct and camelCase. Good to go.
packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
1-29: LGTM!The utility function is well-structured with clear JSDoc documentation. The conditional styling logic correctly handles both custom modal root and default scenarios, and the type safety is properly maintained with
ThemableCssProp.packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
49-96: Excellent accessibility and security implementation.The modal correctly uses
role='alertdialog'for accessibility andcanCloseModal={false}to ensure users cannot accidentally dismiss the one-time secret display without explicitly copying it. All user-facing text is properly localized, and element descriptors follow the camelCase convention for consistent theming.
| 
          
 Found 9 test failures on Blacksmith runners: 
  | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (2)
31-35: Simplify:useFormControlappears unnecessary for read-only display.The form control state is initialized with
apiKeySecretbut never modified, and theClipboardInputreceives its value directly (line 76) rather than from the form control state. Since this is a read-only display, consider removinguseFormControland passing only the label toForm.CommonInputWrapper.If the label is the only needed metadata, refactor to:
- const apiKeyField = useFormControl('name', apiKeySecret, { - type: 'text', - label: localizationKeys('formFieldLabel__apiKey'), - isRequired: false, - }); + const label = localizationKeys('formFieldLabel__apiKey');Then update the wrapper:
- <Form.CommonInputWrapper {...apiKeyField.props}> + <Form.CommonInputWrapper label={label}> <ClipboardInput value={apiKeySecret} readOnly sx={{ width: '100%' }} copyIcon={ClipboardOutline} copiedIcon={Check} /> </Form.CommonInputWrapper>Note: Verify that
Form.CommonInputWrapperaccepts a simplelabelprop. If it requires the full form control props structure, this change may not be applicable and the current pattern is acceptable despite appearing redundant.
31-31: Use a more descriptive form control ID.The form control ID is set to
'name', which doesn't clearly describe the field's purpose. Consider using'apiKeySecret'or'apiKey'for better semantic clarity.Apply this diff:
- const apiKeyField = useFormControl('name', apiKeySecret, { + const apiKeyField = useFormControl('apiKeySecret', apiKeySecret, {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx
 
🧰 Additional context used
📓 Path-based instructions (9)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
🧬 Code graph analysis (2)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
packages/clerk-js/src/ui/elements/Modal.tsx (1)
Modal(25-108)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (6)
packages/clerk-js/src/ui/utils/useFormControl.ts (1)
useFormControl(97-189)packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
ApiKeyModal(36-44)packages/clerk-js/src/ui/elements/FormContainer.tsx (1)
FormContainer(20-61)packages/clerk-js/src/ui/elements/Form.tsx (1)
Form(309-322)packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
ClipboardInput(13-48)packages/clerk-js/src/ui/elements/FormButtons.tsx (1)
FormButtons(16-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Packages
 - GitHub Check: Formatting | Dedupe | Changeset
 - GitHub Check: Analyze (javascript-typescript)
 - GitHub Check: semgrep-cloud-platform/scan
 - GitHub Check: semgrep-cloud-platform/scan
 
🔇 Additional comments (2)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
48-94: Security and UX implementation aligns with PR objectives.The modal correctly implements one-time secret display:
canCloseModal={false}prevents accidental dismissal before copyingrole='alertdialog'provides appropriate accessibility semanticshandleSubmitensures the secret is copied before closing- Read-only
 ClipboardInputprevents modificationThis aligns with the security enhancement described in USER-3698.
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
1-44: LGTM! Clean portal-scoped modal wrapper implementation.The
ApiKeyModalcomponent provides a well-structured abstraction for rendering modals within scoped containers (e.g., UserProfile, OrganizationProfile):
getScopedPortalContainerStylescorrectly handles both document-root and scoped portal scenarios with appropriate positioning (absolute vs. fixed) and backdrop styling.- JSDoc clearly documents the rationale for custom container styles.
 - Props are properly typed by extending
 Modalprops.- Style merging via array syntax allows consumer-provided
 containerSxto override defaults.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (2)
71-76: Reuse of list cache key for mutation causes cache conflicts and stale list data.This issue was flagged in a previous review but remains unaddressed. Using
cacheKeyfor both the list query and the create mutation can cause:
- Cache shape conflicts (list returns array/paginated data, create returns a single API key object)
 - The newly created API key won't appear in the list until manual refresh
 Apply this fix:
+import { useSWRConfig } from 'swr'; + export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPageProps) => { // ... existing code ... const clerk = useClerk(); const { data: createdApiKey, trigger: createApiKey, isMutating, - } = useSWRMutation(cacheKey, (_key, { arg }: { arg: CreateAPIKeyParams }) => clerk.apiKeys.create(arg)); + } = useSWRMutation(`${cacheKey}/create`, (_key, { arg }: { arg: CreateAPIKeyParams }) => clerk.apiKeys.create(arg)); + const { mutate } = useSWRConfig();Then in
handleCreateApiKey, revalidate the list after successful creation:const handleCreateApiKey = async (params: OnCreateParams) => { try { await createApiKey({ ...params, subject, }); + await mutate(cacheKey); // Refresh the list card.setError(undefined); setIsCopyModalOpen(true); } catch (err: any) {
160-167: Gate modal opening on secret presence—secret field is optional and can be undefined.The
secretfield inAPIKeyResourceis defined as optional (secret?: string;in APIKey.ts). WhenhandleCreateApiKeysucceeds, the modal opens unconditionally without verifying that the secret was returned from the backend. If the API response omits the secret field,CopyApiKeyModaldisplays an empty field and the user cannot retrieve their newly created API key.Update
handleCreateApiKeyto verify the secret exists before opening the modal:const handleCreateApiKey = async (params: OnCreateParams) => { try { - await createApiKey({ + const result = await createApiKey({ ...params, subject, }); card.setError(undefined); - setIsCopyModalOpen(true); + if (result?.secret) { + setIsCopyModalOpen(true); + } else { + card.setError('API key created but secret not available'); + } } catch (err: any) {
🧹 Nitpick comments (1)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (1)
82-97: Signature change correct; consider comprehensive error handling.The removal of
closeCardFnparameter aligns with the new modal flow.However, error handling only covers the 409 conflict case. Other API errors may not set a user-visible error message.
Consider handling generic errors:
} catch (err: any) { if (isClerkAPIResponseError(err)) { if (err.status === 409) { card.setError('API Key name already exists'); + } else { + card.setError(err.errors?.[0]?.message || 'Failed to create API key'); } + } else { + card.setError('An unexpected error occurred'); } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx(4 hunks)packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
 
🧰 Additional context used
📓 Path-based instructions (9)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
🧬 Code graph analysis (1)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (3)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
CopyApiKeyModal(24-98)packages/shared/src/types/clerk.ts (1)
CreateAPIKeyParams(1973-1979)packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx (1)
OnCreateParams(23-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Formatting | Dedupe | Changeset
 - GitHub Check: Analyze (javascript-typescript)
 - GitHub Check: semgrep-cloud-platform/scan
 - GitHub Check: semgrep-cloud-platform/scan
 
🔇 Additional comments (3)
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx (2)
30-30: LGTM - Signature simplification aligns with new modal flow.Removing
closeCardFnfrom theonCreatecallback is correct. The form no longer needs to close the card on successful creation since the parent now opens a copy modal instead.
165-172: LGTM - Call site correctly updated.The
onCreatecall correctly passes only the params object, matching the updated signature.packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (1)
45-49: LGTM - Proper lazy loading.The
CopyApiKeyModalis correctly lazy-loaded with appropriate webpack chunk naming, consistent with the existing modal pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (3)
32-36: Simplify by removing unnecessary useFormControl.The
useFormControlhook is not needed here since theClipboardInputis read-only and receives theapiKeySecretvalue directly. The form control adds unnecessary state management overhead without providing validation, transformation, or user interaction capabilities.Apply this diff to simplify:
- const apiKeyField = useFormControl('name', apiKeySecret, { - type: 'text', - label: localizationKeys('formFieldLabel__apiKey'), - isRequired: false, - }); -And update the Form.ControlRow to remove the wrapper:
- <Form.ControlRow - elementDescriptor={descriptors.apiKeysCopyModalInput} - sx={{ flex: 1 }} - > - <Form.CommonInputWrapper {...apiKeyField.props}> - <ClipboardInput - value={apiKeySecret} - readOnly - sx={{ width: '100%' }} - copyIcon={ClipboardOutline} - copiedIcon={Check} - /> - </Form.CommonInputWrapper> - </Form.ControlRow> + <Form.ControlRow + elementDescriptor={descriptors.apiKeysCopyModalInput} + sx={{ flex: 1 }} + > + <ClipboardInput + value={apiKeySecret} + readOnly + sx={{ width: '100%' }} + copyIcon={ClipboardOutline} + copiedIcon={Check} + /> + </Form.ControlRow>And remove the import:
-import { useFormControl } from '@/ui/utils/useFormControl';
38-47: Clarify duplicate copy mechanism and setTimeout delay.Two observations:
Duplicate clipboard management: Both the component-level
useClipboard(line 38) and theClipboardInput(line 80) manage clipboard operations independently. Users can copy via the ClipboardInput's copy button OR the form's submit button, both triggering separate copy actions. Consider whether both copy mechanisms are intentional or if the submit button should only close the modal (since ClipboardInput already provides copy functionality).Unexplained delay: The
setTimeoutwith a 100ms delay before closing the action card (line 44-46) lacks explanation. Document why this delay is necessary (e.g., animation timing, state cleanup) or consider removing it if it's not required.
60-72: Consider adding ARIA attributes for enhanced accessibility.The
role='alertdialog'is appropriate for a modal requiring user action. To further improve accessibility, consider addingaria-labelledbyandaria-describedbyattributes pointing to the form title and hint elements.Example enhancement:
<Card.Root role='alertdialog' + aria-labelledby='copy-api-key-title' + aria-describedby='copy-api-key-hint' elementDescriptor={descriptors.apiKeysCopyModal} >And ensure the FormContainer's header elements have corresponding IDs (may require adjustments to FormContainer component to accept id props).
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
🧬 Code graph analysis (1)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (5)
packages/clerk-js/src/ui/utils/useFormControl.ts (1)
useFormControl(97-189)packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
ApiKeyModal(36-44)packages/clerk-js/src/ui/elements/FormContainer.tsx (1)
FormContainer(20-61)packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
ClipboardInput(13-48)packages/clerk-js/src/ui/elements/FormButtons.tsx (1)
FormButtons(16-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Formatting | Dedupe | Changeset
 - GitHub Check: Analyze (javascript-typescript)
 - GitHub Check: semgrep-cloud-platform/scan
 - GitHub Check: semgrep-cloud-platform/scan
 
🔇 Additional comments (1)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
53-99: Well-structured implementation of one-time secret display.The modal correctly implements the PR objective of showing API key secrets only once:
canCloseModal={false}prevents accidental dismissal- Explicit user action (copy and close) required
 - Proper localization and theming throughout
 - Clean component structure with appropriate hooks
 The implementation aligns with security best practices for sensitive credential display.
Description
This PR replaces the persistent key column in the API keys table with a one-time modal that displays the secret immediately after creation. It also removes the
clerkClient.apiKeys.getSecretKey()method in backend as we're only going to provide the API key secret once after creation.Screen.Recording.2025-11-03.at.9.24.27.AM.mov
Resolves USER-3698
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change
Summary by CodeRabbit
New Features
Localization
Refactor
Tests