Files
alla-allaos-fullstack/docs/standards/architecture-rules.md
phaichayon c1ecd5ea50 commit
2026-06-23 22:13:08 +07:00

161 lines
5.9 KiB
Markdown

# 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/<feature>/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/<feature>/
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