Skip to content

Handle managed vault rotation and redirect#8747

Merged
0xFirekeeper merged 2 commits intomainfrom
firekeeper/managed-vault-rotation
Apr 20, 2026
Merged

Handle managed vault rotation and redirect#8747
0xFirekeeper merged 2 commits intomainfrom
firekeeper/managed-vault-rotation

Conversation

@0xFirekeeper
Copy link
Copy Markdown
Member

@0xFirekeeper 0xFirekeeper commented Apr 20, 2026

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 SecretKeySection and related components to include a vaultConfigUrl property, which facilitates navigation to the vault configuration page. It also introduces error handling for the secret key rotation process.

Detailed summary

  • Added vaultConfigUrl to SecretKeySection and related components.
  • Modified IntegrateAPIKeySection to accept teamSlug and pass vaultConfigUrl.
  • Introduced RotateSecretKeyError class for structured error handling.
  • Updated rotateSecretKeyClient to parse and handle error responses.
  • Enhanced ProjectGeneralSettingsPageUI to include vault configuration paths.
  • Updated various components to use vaultConfigUrl for navigation during error handling.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • Bug Fixes

    • Improved error reporting for secret-key rotation failures, showing clearer messages and status details.
  • New Features

    • If rotation is blocked by managed vault settings, users see a specific notification, the modal closes, and they're redirected to the vault configuration page.
    • Vault configuration links are now included in secret-key sections to streamline access to rotation settings.

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.
@0xFirekeeper 0xFirekeeper requested review from a team as code owners April 20, 2026 18:24
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 20, 2026

⚠️ No Changeset found

Latest commit: d36e28e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 20, 2026

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

Project Deployment Actions Updated (UTC)
thirdweb-www Ready Ready Preview, Comment Apr 20, 2026 6:45pm
4 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs-v2 Skipped Skipped Apr 20, 2026 6:45pm
nebula Skipped Skipped Apr 20, 2026 6:45pm
thirdweb_playground Skipped Skipped Apr 20, 2026 6:45pm
wallet-ui Skipped Skipped Apr 20, 2026 6:45pm

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Apr 20, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 20, 2026

Walkthrough

This PR centralizes rotation error handling and vault routing: it adds a structured RotateSecretKeyError and MANAGED_VAULT_BLOCKS_ROTATION_CODE, removes an in-client vault-rotation side effect, and threads a vaultConfigUrl through FTUX and settings UI to show a vault-specific toast and redirect when managed vaults block rotation.

Changes

Cohort / File(s) Summary
Error Handling & API client
apps/dashboard/src/@/hooks/useApi.ts
Removed client-side vault rotation side effect; added MANAGED_VAULT_BLOCKS_ROTATION_CODE constant and exported RotateSecretKeyError class (with status and optional code); updated rotateSecretKeyClient to parse JSON error bodies and throw RotateSecretKeyError with extracted code and message.
FTUX components
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsx
Threaded teamSlug into IntegrateAPIKeySection and passed derived vaultConfigUrl down to SecretKeySectionRotateSecretKeyButton when secretKeyMasked is present.
Settings & rotation UI
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx
Wired vaultConfigUrl through ProjectKeyDetailsRotateSecretKeyButtonRotateSecretKeyModalContentRotateSecretKeyInitialScreen; updated mutation error handling to detect RotateSecretKeyError with MANAGED_VAULT_BLOCKS_ROTATION_CODE, show a specific toast, close modal, and redirect to the vault configuration URL; improved generic error toast messaging.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Handle managed vault rotation and redirect' accurately summarizes the main changes in the pull request, which center on adding structured error handling for managed vault rotation and implementing navigation/redirect functionality.
Description check ✅ Passed The pull request description provides comprehensive coverage of the changes, including structured error handling implementation, component prop propagation, and error messaging improvements. However, it does not follow the recommended template format (missing the title prefix format and 'How to test' section).

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch firekeeper/managed-vault-rotation

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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 existing paths map.

This adds another one-off dashboard route string right next to the existing centralized settings paths. Folding vaultConfigUrl into paths will 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.message here 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9017899 and f4ce53a.

📒 Files selected for processing (4)
  • apps/dashboard/src/@/hooks/useApi.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 20, 2026

size-limit report 📦

Path Size
@thirdweb-dev/nexus (esm) 105.66 KB (0%)
@thirdweb-dev/nexus (cjs) 319.47 KB (0%)

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.
@vercel vercel bot temporarily deployed to Preview – docs-v2 April 20, 2026 18:38 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground April 20, 2026 18:38 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula April 20, 2026 18:38 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui April 20, 2026 18:38 Inactive
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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 threading vaultConfigUrl through four layers.

This new prop now crosses multiple local components in the same file just to reach the error handler. A small RotateSecretKeyFlow component 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

📥 Commits

Reviewing files that changed from the base of the PR and between f4ce53a and d36e28e.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/settings/ProjectGeneralSettingsPage.tsx

@0xFirekeeper 0xFirekeeper merged commit dc07145 into main Apr 20, 2026
21 of 22 checks passed
@0xFirekeeper 0xFirekeeper deleted the firekeeper/managed-vault-rotation branch April 20, 2026 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Dashboard Involves changes to the Dashboard.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant