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

5.9 KiB

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:

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