Handle managed vault rotation and redirect#8747
Conversation
Add structured handling for secret key rotation when a managed vault blocks rotation: introduce MANAGED_VAULT_BLOCKS_ROTATION_CODE and a RotateSecretKeyError class, parse JSON error bodies from the API, and throw the structured error with status and code. Propagate a vaultConfigUrl prop through FTUX, SecretKeySection, and ProjectGeneralSettingsPage, and update the rotation modal to detect the managed-vault error, show an explanatory toast, close the modal, and redirect the user to the vault configuration page. Also remove the now-unused direct vault rotation import and improve error messaging so the UI can react appropriately.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR centralizes rotation error handling and vault routing: it adds a structured Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Client
participant Server
participant Vault as Managed Vault
User->>Client: Click "Rotate Secret Key"
Client->>Server: POST /api/rotate-secret-key
Server->>Vault: Verify rotation is allowed
alt Vault blocks rotation
Vault-->>Server: Blocked (error.code = MANAGED_VAULT_BLOCKS_ROTATION_CODE)
Server-->>Client: 4xx error with JSON { error: { code, message } }
Client->>Client: Parse error, throw RotateSecretKeyError(code, status)
Client->>Client: Show vault-specific toast
Client->>Client: Close modal and redirect to vaultConfigUrl
Client->>User: Display redirect message
else Rotation allowed
Vault-->>Server: Allowed
Server->>Server: Rotate key and return success
Server-->>Client: 200 OK
Client->>User: Show success toast
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx (2)
348-349: Keep the new vault route with the existingpathsmap.This adds another one-off dashboard route string right next to the existing centralized settings paths. Folding
vaultConfigUrlintopathswill make the redirect target easier to reuse and less likely to drift later.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/dashboard/src/app/`(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx around lines 348 - 349, The new one-off route assigned to vaultConfigUrl should be added to the existing paths map and used there instead of an inline string; update the paths object (used in ProjectGeneralSettingsPage) to include a vaultConfig key whose value is `/team/${props.teamSlug}/${project.slug}/wallets/server-wallets/configuration`, then replace the inline vaultConfigUrl prop with paths.vaultConfig so redirects and reuse reference the centralized paths map (ensure props.teamSlug and project.slug are used when building the paths entry).
1080-1095: Use the parsed backend message in the fallback toast.The managed-vault branch is specific now, but every other failure still collapses to the same generic toast. Using
err.messagehere would let the rest of the new structured error handling reach the user too.Suggested change
if ( err instanceof RotateSecretKeyError && err.code === MANAGED_VAULT_BLOCKS_ROTATION_CODE ) { toast.error("Eject your server-wallet vault first", { description: "This project has a managed vault. Redirecting you to the vault configuration page so you can eject it before rotating the secret key.", }); props.closeModal(); router.push(props.vaultConfigUrl); return; } - toast.error("Failed to rotate secret key"); + toast.error("Failed to rotate secret key", { + description: err instanceof Error ? err.message : undefined, + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/dashboard/src/app/`(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx around lines 1080 - 1095, In the onError handler for the secret-key rotation (the onError callback that currently checks RotateSecretKeyError and MANAGED_VAULT_BLOCKS_ROTATION_CODE), change the generic fallback toast to include the backend-provided message by using the parsed error message (e.g., err.message or err?.message) instead of the hardcoded "Failed to rotate secret key"; keep the existing managed-vault branch behavior (props.closeModal and router.push(props.vaultConfigUrl)) and only use the parsed message for the other error cases so users see the structured backend error text.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@apps/dashboard/src/app/`(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx:
- Around line 348-349: The new one-off route assigned to vaultConfigUrl should
be added to the existing paths map and used there instead of an inline string;
update the paths object (used in ProjectGeneralSettingsPage) to include a
vaultConfig key whose value is
`/team/${props.teamSlug}/${project.slug}/wallets/server-wallets/configuration`,
then replace the inline vaultConfigUrl prop with paths.vaultConfig so redirects
and reuse reference the centralized paths map (ensure props.teamSlug and
project.slug are used when building the paths entry).
- Around line 1080-1095: In the onError handler for the secret-key rotation (the
onError callback that currently checks RotateSecretKeyError and
MANAGED_VAULT_BLOCKS_ROTATION_CODE), change the generic fallback toast to
include the backend-provided message by using the parsed error message (e.g.,
err.message or err?.message) instead of the hardcoded "Failed to rotate secret
key"; keep the existing managed-vault branch behavior (props.closeModal and
router.push(props.vaultConfigUrl)) and only use the parsed message for the other
error cases so users see the structured backend error text.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b07210b5-db5d-4a56-b899-a33163869264
📒 Files selected for processing (4)
apps/dashboard/src/@/hooks/useApi.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx
size-limit report 📦
|
Add a new vaultConfig entry to ProjectSettingPaths and include it in the paths map to centralize the server-wallets configuration URL. Replace a hardcoded vault config URL in ProjectKeyDetails with paths.vaultConfig. Also enhance the secret key rotation error handling by including the actual error message in the toast description for better debugging.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx (2)
347-351: Extract the rotation flow instead of threadingvaultConfigUrlthrough four layers.This new prop now crosses multiple local components in the same file just to reach the error handler. A small
RotateSecretKeyFlowcomponent that owns the modal, redirect, and toast logic would keep this page flatter and easier to change later.As per coding guidelines, "Limit each TypeScript file to one stateless, single-responsibility function for clarity and testability".
Also applies to: 850-904, 983-1065
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/dashboard/src/app/`(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx around lines 347 - 351, The ProjectKeyDetails prop vaultConfigUrl is being threaded through multiple local components; extract a new RotateSecretKeyFlow component that owns the modal, redirect, and toast logic instead of passing vaultConfigUrl down. Create RotateSecretKeyFlow (stateless function component) which accepts rotateSecretKey and project (or just the minimal handlers) and internally manages vaultConfigUrl, opening/closing the modal, invoking props.rotateSecretKey, handling errors, performing the redirect, and showing toasts; replace the nested prop threading by rendering <RotateSecretKeyFlow project={project} rotateSecretKey={props.rotateSecretKey} /> where ProjectKeyDetails was receiving vaultConfigUrl, and remove vaultConfigUrl from the intermediate components/signatures so the prop no longer crosses those layers. Ensure error handling logic currently referencing vaultConfigUrl is moved into RotateSecretKeyFlow and update any affected component props/signatures accordingly.
850-858: Add explicit return types to the modified components.Since these signatures changed in this PR, please make their return types explicit as well (
JSX.Element/JSX.Element | null) instead of relying on inference.As per coding guidelines, "Write idiomatic TypeScript with explicit function declarations and return types".
Also applies to: 983-987, 1034-1040, 1072-1077
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/dashboard/src/app/`(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx around lines 850 - 858, The ProjectKeyDetails component currently lacks an explicit return type; update its signature to declare the return type (e.g., change the function declaration to include ": JSX.Element" or ": JSX.Element | null" as appropriate) and do the same for the other modified components in this file referenced in the PR (the components changed around the other comment ranges), ensuring each function signature explicitly specifies the correct JSX return type (use JSX.Element when it always renders and JSX.Element | null if it can return null).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@apps/dashboard/src/app/`(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx:
- Around line 347-351: The ProjectKeyDetails prop vaultConfigUrl is being
threaded through multiple local components; extract a new RotateSecretKeyFlow
component that owns the modal, redirect, and toast logic instead of passing
vaultConfigUrl down. Create RotateSecretKeyFlow (stateless function component)
which accepts rotateSecretKey and project (or just the minimal handlers) and
internally manages vaultConfigUrl, opening/closing the modal, invoking
props.rotateSecretKey, handling errors, performing the redirect, and showing
toasts; replace the nested prop threading by rendering <RotateSecretKeyFlow
project={project} rotateSecretKey={props.rotateSecretKey} /> where
ProjectKeyDetails was receiving vaultConfigUrl, and remove vaultConfigUrl from
the intermediate components/signatures so the prop no longer crosses those
layers. Ensure error handling logic currently referencing vaultConfigUrl is
moved into RotateSecretKeyFlow and update any affected component
props/signatures accordingly.
- Around line 850-858: The ProjectKeyDetails component currently lacks an
explicit return type; update its signature to declare the return type (e.g.,
change the function declaration to include ": JSX.Element" or ": JSX.Element |
null" as appropriate) and do the same for the other modified components in this
file referenced in the PR (the components changed around the other comment
ranges), ensuring each function signature explicitly specifies the correct JSX
return type (use JSX.Element when it always renders and JSX.Element | null if it
can return null).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fb5075a9-bc72-4c43-84b8-396b38a02704
📒 Files selected for processing (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx
Add structured handling for secret key rotation when a managed vault blocks rotation: introduce MANAGED_VAULT_BLOCKS_ROTATION_CODE and a RotateSecretKeyError class, parse JSON error bodies from the API, and throw the structured error with status and code. Propagate a vaultConfigUrl prop through FTUX, SecretKeySection, and ProjectGeneralSettingsPage, and update the rotation modal to detect the managed-vault error, show an explanatory toast, close the modal, and redirect the user to the vault configuration page. Also remove the now-unused direct vault rotation import and improve error messaging so the UI can react appropriately.
PR-Codex overview
This PR focuses on enhancing the
SecretKeySectionand related components to include avaultConfigUrlproperty, which facilitates navigation to the vault configuration page. It also introduces error handling for the secret key rotation process.Detailed summary
vaultConfigUrltoSecretKeySectionand related components.IntegrateAPIKeySectionto acceptteamSlugand passvaultConfigUrl.RotateSecretKeyErrorclass for structured error handling.rotateSecretKeyClientto parse and handle error responses.ProjectGeneralSettingsPageUIto include vault configuration paths.vaultConfigUrlfor navigation during error handling.Summary by CodeRabbit
Bug Fixes
New Features