Register a Module Everywhere
What you'll learn
~25 min- Identify the 5 registration points every new module must touch
- Use a single prompt to update all 5 files consistently
- Diagnose a silently broken module by checking registration completeness
The registration problem
You scaffolded 7 files in the previous lesson. The table migration is ready, the API route compiles, the page renders in isolation. You deploy to the dev environment, click the nav link — and nothing happens. Or worse: the page loads but every API call returns 403. Or the module appears for admins but not for the operational role that actually needs it.
The module exists but the platform does not know it exists. That is the registration problem.
Every new module must be registered in 5 places. Miss one and the failure mode is silent — no error in the console, no build failure, no test red. Just a feature that does not work for the people who need it.
The 5 registration points
1. RBAC types file (src/types/rbac.ts)
Add the module’s permission key to the ModulePermission union type:
// Beforetype ModulePermission = 'dashboard' | 'user-admin' | 'case-tracker' | ...;
// Aftertype ModulePermission = 'dashboard' | 'user-admin' | 'case-tracker' | 'vehicle-fleet' | ...;If the module name is not in the union, withPermission('vehicle-fleet', method) in your API route will reject every request with a type error at build time — or silently return 403 at runtime if the types are not strict enough.
2. Permission matrix (src/config/permissions.ts)
Map each role to the CRUD operations it can perform on the new module:
'vehicle-fleet': { admin: ['read', 'create', 'update', 'delete'], manager: ['read', 'create', 'update'], superadmin: ['read', 'create', 'update', 'delete'], operator: ['read', 'create', 'update'], viewer: ['read'],}This is where you decide who can do what. A missing entry means the role gets zero permissions on the module — withPermission() denies everything.
3. Nav routes config (src/config/nav-routes.ts)
Add the module to the sidebar navigation:
{ label: 'Vehicle Fleet', path: '/vehicle-fleet', icon: 'DirectionsCar', requiredPermission: 'vehicle-fleet:read', group: 'operations',}If you forget this, the page is accessible by direct URL but invisible in the sidebar. Users will never find it.
4. Provenance map (src/config/provenance-map.ts)
Register which tables the module owns:
'vehicle-fleet': { tables: ['vehicle_fleet'], dataSourceDefault: 'manual',}The provenance system uses this to track data lineage. Without it, the vehicle_fleet table is orphaned — no module claims ownership, and data audits cannot trace who populated it or how.
5. Module status enum (src/config/module-status.ts)
Add the module to the status registry:
'vehicle-fleet': { status: 'development', // 'development' | 'staging' | 'production' | 'deprecated' version: '1.0.0', owner: 'your-team-name',}This controls feature flags and the admin module dashboard. A module in 'development' status is hidden from production users unless they have the admin role.
Here is what happens when you miss each registration point:
- RBAC types: build error or runtime 403 on every API call
- Permission matrix: 403 for all roles — even admin
- Nav routes: module works but is invisible in navigation
- Provenance map: data audit reports the table as unowned
- Module status: module may be hidden in production or visible before it is ready
The prompt
This prompt updates all 5 registration points for the vehicle-fleet module you scaffolded in Lesson 5:
Register the "vehicle-fleet" module in the DS platform. Update these 5 files:
1. src/types/rbac.ts - Add 'vehicle-fleet' to the ModulePermission union type - Do NOT remove any existing entries
2. src/config/permissions.ts - Add vehicle-fleet permissions: superadmin: ['read', 'create', 'update', 'delete'] admin: ['read', 'create', 'update', 'delete'] manager: ['read', 'create', 'update'] operator: ['read', 'create', 'update'] viewer: ['read']
3. src/config/nav-routes.ts - Add to the 'operations' group: label: 'Vehicle Fleet' path: '/vehicle-fleet' icon: 'DirectionsCar' requiredPermission: 'vehicle-fleet:read' - Place it after the last existing operations item
4. src/config/provenance-map.ts - Add: 'vehicle-fleet': { tables: ['vehicle_fleet'], dataSourceDefault: 'manual' }
5. src/config/module-status.ts - Add: 'vehicle-fleet': { status: 'development', version: '1.0.0', owner: 'ds-core' }
IMPORTANT:- Do NOT modify any existing entries in any file- Only ADD the new vehicle-fleet entries- Preserve the existing formatting and sort order- Show me the diff for each file so I can review before committingAI tools sometimes “clean up” files they are editing — removing comments, reordering imports, or consolidating entries. In a shared config file, that creates merge conflicts and breaks other modules. The explicit instruction to only add prevents this.
Watch it work
The registration audit
After the AI updates the files, verify registration completeness. This is a manual check you do once — but it catches the bugs that automated tests miss.
Quick verification script you can run in your AI CLI:
Search the codebase for every occurrence of 'vehicle-fleet' and confirm itappears in exactly these files:- src/types/rbac.ts (in the ModulePermission type)- src/config/permissions.ts (permission mapping)- src/config/nav-routes.ts (nav entry)- src/config/provenance-map.ts (table ownership)- src/config/module-status.ts (status entry)- src/app/api/vehicle-fleet/route.ts (API route)- src/hooks/useVehicleFleet.ts (SWR hook)- src/app/(protected)/vehicle-fleet/page.tsx (page)- src/types/vehicle-fleet.ts (Zod schemas)- src/tests/vehicle-fleet.test.ts (tests)
If 'vehicle-fleet' is missing from any of the first 5 files, that is aregistration gap. Report which files are missing.You could write a script that checks registration completeness. Some teams do. But on a platform where new modules ship quarterly, a 30-second manual check after the AI runs is pragmatic. The cost of the script exceeds the cost of the check for the volume of new modules you actually ship.
Common registration mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Module name typo in one file | 403 on API calls even though nav link works | Search for the module name across all 5 files. One of them has a different spelling. |
| Permission matrix has role but no operations | User sees the nav link, clicks it, gets “Access Denied” on data load | Check that the role has at least ['read'] in the permission matrix. An empty array means no access. |
Nav route uses wrong requiredPermission | Link visible to wrong roles, or hidden from correct roles | The requiredPermission must match the format 'module-name:operation'. Confirm it matches the RBAC types. |
| Provenance map points to wrong table name | Data audit reports an orphaned table | The table name in the provenance map must match the actual SQL table name in the migration (snake_case). |
Module status set to 'production' prematurely | Unfinished module visible to all users | Set status to 'development' until the module passes QA. Only promote to 'production' when it is ready. |
You register a new module in all 5 files and deploy. Users with the 'operator' role can see the module in the sidebar and load the page, but clicking 'Add New' returns a 403 error. Users with the 'manager' role can add records without issue. What is the most likely cause?
What’s next
Your module is scaffolded and registered. In the next lesson, you will build out the API route handler with the platform’s response helpers, safe error handling, pagination, and Zod validation — the patterns that make every route consistent and auditable.