docs/superpowers/plans/2026-04-13-project-database-detail-catalog-react-parity.md
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Remove the Vue bridge from the project database detail catalog tab and restore full catalog parity with a React-native implementation built from the repo's shadcn-style React primitives.
Architecture: Reintroduce a React-owned DatabaseCatalogPanel that orchestrates catalog flattening, permissions, feature gating, row selection, inline edits, delete cleanup, and grant-access dialog state. Keep the UI split into a page-specific panel shell, a presentational SensitiveColumnTable, and a focused GrantAccessDialog, all backed by existing Vue/Pinia stores through useVueState.
Tech Stack: React, TypeScript, useVueState, Pinia stores, protobuf-generated types, shadcn-style UI components on @base-ui/react, Tailwind CSS v4, Vitest
Files:
Modify: frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.tsx
Reference: frontend/src/components/Database/DatabaseSensitiveDataPanel.vue
Reference: frontend/src/components/SensitiveData/types.ts
Reference: frontend/src/components/SensitiveData/utils.ts
Step 1: Replace the Vue bridge with a React implementation
Rework DatabaseCatalogPanel.tsx so it no longer imports createApp, NConfigProvider, OverlayStackManager, or DatabaseSensitiveDataPanel.vue. Use the earlier React panel from commit 79dd009d2c as the behavioral baseline, but keep the current branch's import style and file structure.
The panel should own:
useDatabaseCatalog(database.name, false)useVueStateMaskData[]Keep the helper logic inside this file unless a helper becomes reused by both tests and the table component.
Implement the same write paths used by the Vue panel:
updateDatabaseCatalogupdateDatabaseCatalogContinue using:
useDatabaseCatalogV1Store()
usePolicyV1Store()
useSettingV1Store()
featureToRef(PlanFeature.FEATURE_DATA_MASKING)
instanceV1MaskingForNoSQL(...)
Step 3: Keep parity for NoSQL and feature gating
Carry forward the Vue panel's NoSQL branching:
object-schema flattening must still surface nested fields
row selection must be disabled when instanceV1MaskingForNoSQL(...) says bulk grant access is unavailable
rows with unsupported semantic type or classification targets must stay read-only
missing masking subscription should open the feature dialog instead of the grant-access dialog
Step 4: Run focused type-check for the panel
Run:
pnpm --dir frontend type-check
git add frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.tsx
git commit -m "feat(frontend): restore react database catalog panel"
Files:
Create: frontend/src/react/pages/project/database-detail/catalog/SensitiveColumnTable.tsx
Create: frontend/src/react/pages/project/database-detail/catalog/GrantAccessDialog.tsx
Reference: frontend/src/components/SensitiveData/components/SensitiveColumnTable.vue
Reference: frontend/src/components/SensitiveData/exemptionDataUtils.ts
Reference: frontend/src/components/SensitiveData/utils.ts
Step 1: Create SensitiveColumnTable.tsx
Port the old React SensitiveColumnTable back into the tree, but align it with the repo's current React UI conventions instead of copying raw markup unchanged.
Requirements:
Table primitives if they fit cleanly; otherwise keep a narrow custom table wrapper only for what the shared table cannot expressButton and Select components- placeholders consistently with the Vue panelKeep the component presentational:
no direct store calls
all mutations bubble up through callbacks
selected rows are controlled by props
Step 2: Create GrantAccessDialog.tsx
Restore the earlier React grant-access dialog and keep its policy-writing logic intact.
Requirements:
rewriteResourceDatabase(...)Do not reintroduce the Vue drawer or a bridge wrapper.
Update DatabaseCatalogPanel.tsx to use the new components and verify:
SensitiveColumnTable receives checked rows, filtered rows, option lists, and callbacks
GrantAccessDialog receives the selected rows converted to the SensitiveColumn shape expected by the shared utilities
closing the dialog clears checked rows only when the current Vue behavior does so
Step 4: Run fixers and type-check
Run:
pnpm --dir frontend fix
pnpm --dir frontend type-check
git add frontend/src/react/pages/project/database-detail/catalog/SensitiveColumnTable.tsx frontend/src/react/pages/project/database-detail/catalog/GrantAccessDialog.tsx frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.tsx
git commit -m "feat(frontend): restore react catalog interactions"
Files:
Create: frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx
Modify: frontend/src/react/pages/project/ProjectDatabaseDetailPage.test.tsx
Step 1: Restore panel-level tests
Recreate DatabaseCatalogPanel.test.tsx using the earlier React test file from commit 79dd009d2c as the baseline. Mock the same stores and utilities, then keep or add coverage for:
rendering flattened relational rows
selection enabling the grant-access button
missing masking feature opening the feature dialog
permission inputs passed to the guard
deleting a selected row clearing it from the checked selection
inline semantic type and classification updates
undefined catalog state before the store has loaded
Step 2: Add parity tests that were easy to miss in the old version
Add explicit tests for:
bb.databaseCatalogs.update is missingThese are the most likely parity regressions after restoring older React code.
Do not move detailed workflow assertions into ProjectDatabaseDetailPage.test.tsx. Keep that file focused on:
Only update it if the import path, test id expectations, or mounting assumptions change.
Run:
pnpm --dir frontend test -- --run frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx frontend/src/react/pages/project/ProjectDatabaseDetailPage.test.tsx
git add frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx frontend/src/react/pages/project/ProjectDatabaseDetailPage.test.tsx
git commit -m "test(frontend): cover react database catalog parity"
Files:
Modify: frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.tsx
Modify: frontend/src/react/pages/project/database-detail/catalog/SensitiveColumnTable.tsx
Modify: frontend/src/react/pages/project/database-detail/catalog/GrantAccessDialog.tsx
Modify: frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx
Step 1: Remove all page-local Vue bridge dependencies
Confirm the final catalog implementation no longer imports or depends on:
createAppNConfigProviderthemeOverridesOverlayStackManager.vueDatabaseSensitiveDataPanel.vueNaiveUIThe catalog tab should now be fully React-owned even though it still reads from Vue-backed stores.
Run:
pnpm --dir frontend fix
pnpm --dir frontend check
pnpm --dir frontend type-check
pnpm --dir frontend test -- --run frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx frontend/src/react/pages/project/ProjectDatabaseDetailPage.test.tsx
Run:
git diff -- frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.tsx frontend/src/react/pages/project/database-detail/catalog/SensitiveColumnTable.tsx frontend/src/react/pages/project/database-detail/catalog/GrantAccessDialog.tsx frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx frontend/src/react/pages/project/ProjectDatabaseDetailPage.test.tsx
Verify the final diff shows a React-native catalog flow and no accidental changes outside the catalog scope.
git add frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.tsx frontend/src/react/pages/project/database-detail/catalog/SensitiveColumnTable.tsx frontend/src/react/pages/project/database-detail/catalog/GrantAccessDialog.tsx frontend/src/react/pages/project/database-detail/panels/DatabaseCatalogPanel.test.tsx frontend/src/react/pages/project/ProjectDatabaseDetailPage.test.tsx
git commit -m "fix(frontend): finish react database catalog parity"