Files
lunarfront-app/docs/architecture.md
Ryan Moon 9400828f62 Rename Forte to LunarFront, generalize for any small business
Rebrand from Forte (music-store-specific) to LunarFront (any small business):
- Package namespace @forte/* → @lunarfront/*
- Database forte/forte_test → lunarfront/lunarfront_test
- Docker containers, volumes, connection strings
- UI branding, localStorage keys, test emails
- All documentation and planning docs

Generalize music-specific terminology:
- instrumentDescription → itemDescription
- instrumentCount → itemCount
- instrumentType → itemCategory (on service templates)
- New migration 0027_generalize_terminology for column renames
- Seed data updated with generic examples
- RBAC descriptions updated
2026-03-30 08:51:54 -05:00

4.9 KiB

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. onRequest hook sets companyId from header
  3. authenticate preHandler verifies JWT, loads permissions, checks is_active
  4. requirePermission preHandler checks user has required permission slug
  5. Route handler validates input with Zod, calls service, returns response
  6. 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

Multi-Tenancy

Every domain table has a company_id column. All queries filter by the authenticated user's company. Location-scoped tables (inventory, transactions) additionally filter by location_id.

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.