> ## Documentation Index
> Fetch the complete documentation index at: https://system.muzemus.online/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture decisions

> Key architectural decisions and their rationale

## Decision log

| #  | Decision                                  | Rationale                                                                     | Trade-off                                                          |
| -- | ----------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| 1  | Session-based auth over JWT               | Server-side revocation, no refresh token handling                             | Database lookup on every request                                   |
| 2  | Shared-database multi-tenancy             | Simple deployment, low cost, easy cross-client queries                        | No database-level isolation; relies on application-layer filtering |
| 3  | Prisma over raw SQL/TypeORM               | Type safety, generated client, migration management                           | Vendor lock-in; less query-level control                           |
| 4  | better-auth over Passport.js              | Modern API, less boilerplate, built-in session management                     | Smaller community, fewer plugins                                   |
| 5  | React Query over Redux                    | Server-state caching, deduplication, background refetching                    | Learning curve for Redux users                                     |
| 6  | shadcn/ui over Material UI                | Accessible primitives, full Tailwind control, no bundle bloat                 | More manual styling work                                           |
| 7  | Firebase Hosting over Vercel              | Free tier, simple deployment                                                  | Less framework-specific optimization                               |
| 8  | Render over AWS/GCP                       | Simple deployment, free tier, good NestJS support                             | Cold starts, limited customization                                 |
| 9  | Single-file Prisma schema                 | One source of truth, easy to review                                           | Large file, harder to navigate                                     |
| 10 | Client-side CSV export                    | No server load, instant download                                              | Browser memory limits for large datasets                           |
| 11 | Thin controllers with domain services     | Testable controllers, transaction-safe services                               | More service methods to maintain                                   |
| 12 | Admin-role gating for the Data Import Hub | Prevents permission-OR leaks to non-admin roles holding one import permission | An admin without import permissions sees an explicit empty state   |

## Key decisions in depth

### Staff-only portal

**Decision:** Employees have no login accounts. All ordering is done on their behalf by staff.

**Rationale:** Matches the operational model; eliminates employee self-service and simplifies authorization.

**Impact:** No employee-facing UI or authentication. A legacy `Role.EMPLOYEE` code path remains as documented technical debt pending removal.

### Entitlement logic as pure functions

**Decision:** Criteria matching and phase calculation live in pure functions with no Prisma or NestJS dependencies.

**Rationale:** The most complex business logic becomes independently testable and reusable by the reporting service.

**Impact:** The engine can be tested without a database and shared between order flow and reports.

### Scope guards for multi-tenancy

**Decision:** Data isolation is enforced by application-layer guards and service-level filtering, not database RLS.

**Rationale:** Faster to build, easier to reason about, sufficient for the current trust model.

**Impact:** A service-layer bug could theoretically leak cross-client data. RLS is a planned defense-in-depth measure.

### Linear order lifecycle

**Decision:** Orders follow a forward-only pipeline with server-enforced transitions.

**Rationale:** Matches the physical fulfilment process and is simple to reason about.

**Impact:** No partial approvals, split shipments, or parallel stages.

### In-app plus email notifications

**Decision:** Notifications are stored in-app (bell + notifications page) and sent by email, using Brevo (production) or SMTP (development).

**Rationale:** In-app records give every user a visible activity feed; email covers offline attention.

**Impact:** No push or SMS channels. A WhatsApp channel value is reserved in the schema but has no gateway yet.

## Anti-patterns to avoid

| Pattern                           | Why to avoid                                          |
| --------------------------------- | ----------------------------------------------------- |
| Adding a state management library | React Query plus component state is sufficient        |
| Creating custom UI components     | Use shadcn/ui primitives and shared common components |
| Using raw SQL                     | Use the Prisma query builder                          |
| Adding JWT authentication         | Session-based auth is the chosen approach             |
| Introducing microservices         | The monolith is sufficient for current scale          |
| Adding Redis caching              | PostgreSQL plus React Query caching is sufficient     |
