## Customer Portal - AI Coding Rules (Focused) These rules are the fast “guardrails” for AI agents in this repo. Detailed patterns live in docs; when unsure, read them first. ### Read before coding - `docs/README.md` (entrypoint) - `docs/development/` (BFF/Portal/Domain patterns) - `docs/architecture/` (boundaries) - `docs/integrations/` (external API details) Rule: **Never guess** endpoint behavior or payload shapes. Find docs or an existing implementation first. ### Repo boundaries (non-negotiable) - **Domain (`packages/domain/`)**: shared contracts + Zod validation + cross-app utilities. Framework-agnostic. - **BFF (`apps/bff/`)**: NestJS HTTP boundary + orchestration + integrations (Salesforce/WHMCS/Freebit). - **Portal (`apps/portal/`)**: Next.js UI; pages are thin wrappers over feature modules. ### Import rules (enforced by ESLint) - **Allowed (Portal + BFF)**: - `@customer-portal/domain/` - `@customer-portal/domain/toolkit` - **Allowed (BFF only)**: - `@customer-portal/domain//providers` - **Forbidden everywhere**: - `@customer-portal/domain` (root import) - any deep import like `@customer-portal/domain//**` - any deep import like `@customer-portal/domain//providers/**` - **Forbidden in Portal**: - `@customer-portal/domain/*/providers` (Portal must never import provider adapters) Examples: ```ts // ✅ correct (apps) import type { Invoice } from "@customer-portal/domain/billing"; import { invoiceSchema } from "@customer-portal/domain/billing"; // ✅ correct (BFF integrations only) import { Whmcs } from "@customer-portal/domain/billing/providers"; // ❌ forbidden import { Billing } from "@customer-portal/domain"; import { Invoice } from "@customer-portal/domain/billing/contract"; import { transformWhmcsInvoice } from "@customer-portal/domain/billing/providers/whmcs/mapper"; ``` ### Validation rules (Zod-first) - **Schemas live in domain**: `packages/domain//schema.ts` - **Derive types from schemas**: `export type X = z.infer` - **Query params**: use `z.coerce.*` for URL strings. ### BFF rules (NestJS) - **Controllers are thin**: - no business logic - no `zod` imports in controllers - use `createZodDto(schema)` + global `ZodValidationPipe` - **Integrations are thin**: - build queries in `apps/bff/src/integrations//utils` - fetch data - transform once via domain mappers - return domain types - **Errors**: - never leak sensitive details to clients - log details server-side, return generic user messages ### Portal rules (Next.js) - **Pages are wrappers** under `apps/portal/src/app/**` (no API calls in pages) - **Feature modules own logic** under `apps/portal/src/features//**` - hooks (React Query) - services (API client calls) - components/views (UI composition) - **No provider imports** from domain in Portal. ### Naming & safety - No `any` in public APIs - Avoid unsafe assertions - No `console.log` in production code (use logger) - Avoid `V2` suffix in service names ### References - `docs/development/domain/import-hygiene.md` - `docs/development/bff/integration-patterns.md` - `docs/development/portal/architecture.md`