# Architecture Rules These rules describe the approved implementation patterns for ALLA OS. New work should extend these patterns instead of inventing parallel architecture. ## Frontend Architecture - Use Next.js App Router. - Prefer server components by default. - Use client components only for interactivity, browser APIs, or client-side state/query hooks. - Use `PageContainer` for dashboard page headers and top-level content framing. - Keep business-facing CRM UI aligned with `docs/business/crm-terminology.md` and `src/features/crm/shared/terminology.ts`. ### Data Loading Pattern - For data-heavy dashboard/app pages, prefer server prefetch plus `HydrationBoundary`. - Client tables and detail panes should consume prefetched data with `useSuspenseQuery()`. - Define query options and query keys in `src/features//api/queries.ts`. - Keep filters in URL state with `nuqs` when the page supports shareable filtering. Reference examples: - `src/features/users/components/user-listing.tsx` - `src/features/crm/customers/components/customer-listing.tsx` - `src/app/dashboard/crm/settings/user-role-assignments/page.tsx` ### UI Composition Rules - Reuse shadcn/ui primitives from `src/components/ui/**`. - Reuse table shell components from `src/components/ui/table/**`. - Reuse `useDataTable` for table state orchestration. - Reuse TanStack Form wrappers from `@/components/ui/tanstack-form` and field components from `@/components/forms/fields`. - Do not create a parallel CRM design system or terminology layer. ## Backend Architecture - Use Route Handlers under `src/app/api/**` as the HTTP boundary. - Keep route handlers thin: auth, validation, service call, response mapping, and audit. - Put business logic in feature or foundation service layers under `src/features/**`. - Use Drizzle ORM for database access. - Keep direct database access out of client components. ### Route Structure Pattern Approved structure: 1. `requireOrganizationAccess()` or another shared auth helper 2. request parsing and schema validation 3. build resolved access/security context when the feature is scope-sensitive 4. call feature/foundation service 5. emit audit/security events through shared audit services 6. return typed JSON/stream response Reference examples: - `src/app/api/crm/quotations/route.ts` - `src/app/api/crm/approvals/route.ts` - `src/app/api/crm/reports/pipeline/route.ts` - `src/app/api/crm/reports/export/route.ts` ## Module Structure Preferred feature layout: ```text src/features// api/ types.ts service.ts queries.ts mutations.ts components/ schemas/ server/ ``` Rules: - components import contracts from `api/types.ts` - UI calls query options from `api/queries.ts` - UI mutations reuse shared mutation configs from `api/mutations.ts` - services in `api/service.ts` call route handlers through `src/lib/api-client.ts` - server business logic stays under feature/foundation server services ## Service Layer Pattern - Services own business rules, persistence orchestration, and reusable data shaping. - Services may call other services when extending an existing foundation. - Services should not depend on UI concerns. - Report services must use dataset/builders/filter layers instead of embedding ad hoc SQL in routes. - PDF flows must use the PDF and artifact foundations instead of custom rendering paths. Reference services: - `src/features/crm/reports/server/service.ts` - `src/features/foundation/approval/server/service.ts` - `src/features/foundation/pdf-generator/server/service.ts` - `src/features/foundation/storage/service.ts` ## Query Pattern - Define centralized query key factories in each feature's `api/queries.ts`. - Keys should group into `all`, `lists()`, `list(filters)`, `details()`, `detail(id)`, and child-resource keys where applicable. - Server pages prefetch query options and dehydrate. - Clients read the same keys with `useSuspenseQuery()`. Reference examples: - `src/features/products/api/queries.ts` - `src/features/users/api/queries.ts` - `src/features/crm/reports/api/queries.ts` ## Mutation Pattern - Centralize mutation configs in `api/mutations.ts`. - Shared mutation configs must retain cache invalidation. - After create: invalidate list-level keys. - After update: invalidate list and detail keys. - After delete: invalidate lists and remove stale detail queries. - Refresh related tabs, counts, previews, and approval panels when they depend on the changed entity. ## Audit Pattern - Use `auditCreate()`, `auditUpdate()`, `auditDelete()`, or `auditAction()` from `src/features/foundation/audit-log/service.ts`. - Reuse existing entity types and action naming where possible. - Security-sensitive denials use `crm_security_access` through `auditCrmSecurityEvent()`. - Report view/export events use `crm_report`. Reference examples: - `src/features/foundation/audit-log/service.ts` - `src/features/crm/security/server/service.ts` - `src/features/crm/reports/server/exports/service.ts` ## Security Pattern - Organization access starts with `requireOrganizationAccess()`. - CRM authorization must use resolved access, not raw role strings. - Use `resolveCrmMembershipAccess()` for effective permission/scope unions. - Use `buildCrmSecurityContext()` for scope-aware CRM services. - Use `resolveCrmAccess()` / report-context builders for report routes. - Scope checks must enforce branch, product, ownership, and pricing visibility server-side. Reference docs: - `docs/security/crm-authorization-boundaries.md` - `docs/security/crm-access-enforcement-inventory.md` - `docs/security/team-scope-limitations.md` ## Explicitly Forbidden - business logic in route handlers - client-side only authorization - direct role-string CRM authorization - direct DB access from client code - duplicate export/report/PDF/approval/security foundations - new Clerk integration - new SWR or Redux data architecture for app-owned features - new React Hook Form usage in this repo