# Architecture ## Monorepo Structure ``` lunarfront/ packages/ shared/ @lunarfront/shared — Zod schemas, types, business logic, utils backend/ @lunarfront/backend — Fastify API server admin/ @lunarfront/admin — Admin UI (React + Vite) planning/ Domain planning docs (01-26) docs/ Technical documentation ``` Managed with Turborepo and Bun workspaces. `@lunarfront/shared` is a dependency of both `backend` and `admin`. ## Backend **Fastify** API server with a plugin-based architecture. ``` src/ main.ts App entry, plugin registration, server start plugins/ database.ts Drizzle ORM + PostgreSQL connection auth.ts JWT auth, permission checking, inheritance redis.ts Valkey/Redis (ioredis) cors.ts CORS configuration storage.ts File storage provider registration error-handler.ts Centralized error → HTTP response mapping dev-auth.ts Dev-only auth bypass routes/v1/ auth.ts Register, login, password change, reset, profile accounts.ts Accounts, members, identifiers, payment methods, etc. rbac.ts Users list, roles CRUD, role assignments, permissions files.ts File upload/download/delete services/ account.service.ts Account + member business logic rbac.service.ts Roles, permissions, user role management file.service.ts File validation, storage, metadata product.service.ts Products + inventory lookup.service.ts Lookup table management inventory.service.ts Stock receipts, unit tracking db/ schema/ Drizzle table definitions migrations/ SQL migrations (drizzle-kit) seeds/ System permission + role definitions storage/ provider.ts StorageProvider interface local.ts Local filesystem provider s3.ts S3 provider (placeholder) utils/ pagination.ts withPagination, withSort, buildSearchCondition, paginatedResponse ``` ### Request Flow 1. Fastify receives request 2. `authenticate` preHandler verifies JWT, loads permissions, checks `is_active` 3. `requirePermission` preHandler checks user has required permission slug 4. Route handler validates input with Zod, calls service, returns response 5. Error handler catches typed errors and maps to HTTP status codes ### Permission Inheritance Permissions follow a hierarchy: `admin` implies `edit`, which implies `view` for the same domain. Having `accounts.admin` automatically grants `accounts.edit` and `accounts.view`. Non-hierarchical actions (`upload`, `delete`, `send`, `export`) don't cascade. ## Frontend (Admin UI) **React** SPA with TanStack Router (file-based routing) and TanStack Query (data fetching). ``` src/ routes/ _authenticated.tsx Layout with sidebar, permission-gated nav _authenticated/ accounts/ Account list + detail pages members/ Member list + detail pages users.tsx Users admin page roles/ Roles list + create/edit pages profile.tsx User profile + settings help.tsx In-app wiki login.tsx Login page api/ React Query options + mutations per domain components/ ui/ shadcn/ui primitives shared/ DataTable, AvatarUpload accounts/ Domain-specific forms stores/ auth.store.ts Zustand — token, user, permissions theme.store.ts Zustand — color theme + light/dark mode hooks/ use-pagination.ts URL-based pagination state lib/ api-client.ts Fetch wrapper with JWT + error handling themes.ts Color theme definitions wiki/ index.ts In-app help content ``` ### State Management | Concern | Solution | |---------|----------| | Auth + permissions | Zustand store, persisted to sessionStorage | | Server data | TanStack Query (cache, refetch, invalidation) | | URL state (pagination) | TanStack Router search params | | Theme | Zustand store, persisted to localStorage | | Component state | React `useState` | ## Deployment Model Each customer runs as a fully isolated deployment — their own Kubernetes namespace on DOKS, their own database on the shared managed Postgres instance. There is no multi-tenancy in the application layer. No `company_id`, no row-level isolation. One instance = one customer. ## Database PostgreSQL 16 with Drizzle ORM. Migrations are generated with `bunx drizzle-kit generate` and applied with `bunx drizzle-kit migrate`. Schema files live in `packages/backend/src/db/schema/`. Key tables: `company`, `location`, `user`, `account`, `member`, `member_identifier`, `product`, `inventory_unit`, `role`, `permission`, `user_role_assignment`, `role_permission`, `file`.