NestJS conventions
These are PointNXT rules from AGENTS.md, docs/AI_CONTEXT.md, and the architecture check. They are not a generic NestJS tutorial.
Placement
src/modules/<area>/<feature>/
feature.module.ts
controllers/
services/
repositories/ when the feature uses them
listeners/
dto/
Areas: identity, commerce, operations, finance, automation.
- The area module imports the feature. The feature does not import the area module.
- Controllers do not inject
DatabaseService. - Do not import Shopify, Amazon, WooCommerce, or Razorpay SDKs from
src/modules. Put them insrc/integrations. - Inventory writes from outside stock go through
StockOperationsPort. - New Prisma models are classified in
tenancy.extension.ts. - Order side effects in order command use
OutboxWriterServiceinside the transaction.
HTTP
- Default version
1, so paths are/v1/...unlessVERSION_NEUTRAL. - DTOs use class-validator. The global pipe strips unknown fields and rejects them.
@TenantScoped()when the route is tenant data.@RequirePermissionswhen the route is not for every authenticated user. Omission allows.@AuditLogwhen the mutation should hit the audit listener.@DocResponseand@ApiOperationso Swagger stays the API reference.
Config
Add a variable to .env.example, to environment.validation.ts, and to a config factory under src/common/config. Read it with ConfigService.
Tests
Pair a spec under test/. yarn verify:test-pairs enforces pairing. yarn architecture:check enforces boundaries.
Workers
Run job bodies inside runWithTenantContext or runWithSystemContext. A Prisma call without that context is not tenant-filtered by the request, because there is no request.