Adding a New Module
Follow the V-Model workflow for implementing any feature in Tonnex.
Step 1: Define Validators
Create Zod schemas in packages/utils/src/validators/<module>.ts:
Export from packages/utils/src/validators/index.ts and packages/utils/src/index.ts.
Step 2: Define Database Schema
Create the Drizzle schema in packages/db/src/schema/<module>.ts:
Then export from packages/db/src/schema/index.ts and run:
Step 3: Add Resource Type for Scoping (if applicable)
If this module’s data should be filterable by location/warehouse, add the resource type to resourceTypeEnum in packages/db/src/schema/rbac.ts:
Then regenerate and migrate.
Step 4: Create API Module
Create the NestJS module in apps/api/src/<module>/:
Module — Import RbacModule
Controller — Add RBAC Guards
Service — Add Scope Filtering
Step 5: Register in App Module
Add to apps/api/src/app.module.ts:
Step 6: Create Frontend Pages
In apps/web/app/(dashboard)/vehicles/page.tsx, use DiceUI Data Table for the list view.
Step 7: Update Documentation
Create a guide at apps/docs/guides/<module>.mdx with:
- Architecture diagram
- Schema reference
- API endpoint table
- Usage examples
Every table MUST include org_id for RLS. Tables without org_id will not be protected by Row Level Security.
Every controller MUST use @UseGuards(SupabaseGuard, RbacGuard) and every method MUST have @RequirePermission.
NEVER create per-module junction tables for scoping. ALWAYS use the resource_scopes table via ScopeService.