# 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`.
