# Monie Backend Agent Guide ## Scope This file applies only to `monie-backend`. `monie-backend` is the source of truth for business logic across Monie apps: - `monie-web` - `monie-mobile` - `monie-widget` - `monie-landing` (limited, mostly public marketing integrations) Do not move backend rules to frontend projects "for convenience". --- ## Current Architecture NestJS monorepo with multiple apps in `apps/`: - `gateway` (`apps/gateway`) — public API entrypoint / aggregation layer - `auth` (`apps/auth`) — authentication and authorization - `bookings` (`apps/bookings`) — booking-related APIs - `tasks` (`apps/tasks`) — tasks domain APIs - `notifications` (`apps/notifications`) — notification domain APIs Default ports: - `AUTH_PORT=3000` - `GATEWAY_PORT=3001` - `TASKS_PORT=3002` - `NOTIFICATIONS_PORT=3003` - `BOOKING_PORT=3004` --- ## Runtime Commands Use npm scripts from `package.json`: - `npm run start:dev` — run all apps in watch mode - `npm run start:gateway` - `npm run start:auth` - `npm run start:bookings` - `npm run start:tasks` - `npm run start:notifications` - `npm run build` - `npm run test` - `npm run test:e2e` - `npm run check` (Biome check) - `npm run lint` (Biome lint with write) - `npm run format` (Biome format with write) --- ## Engineering Rules ### 1) Business Logic Ownership - Keep domain rules in domain apps/services (`auth`, `bookings`, `tasks`, `notifications`). - Keep `gateway` thin unless aggregation/proxy behavior is explicitly needed. - Do not keep critical decisions only in controllers. ### 2) API Design - Use clear route naming by domain. - Keep DTOs explicit; avoid loosely typed payloads. - Validate input on server side for all external entrypoints. - Return consistent response shapes for similar endpoints. ### 3) Security - Never hardcode secrets/tokens in source code. - Read secrets from environment variables. - Do not store plain passwords (use hashing once persistence is added). - Treat auth/session flows as high-risk changes: require tests. ### 4) Data and Contracts - Backend is canonical for entity rules and invariants. - Public/widget-safe endpoints must not expose internal-only fields. - Prefer stable identifiers for public integrations (`widgetKey`, slug, etc.), not internal DB IDs where avoidable. ### 5) Error Handling - Use HTTP exceptions intentionally with clear status codes. - Avoid swallowing upstream errors. - Keep error messages useful but do not leak secrets/internal stack details to clients. ### 6) Code Quality - Language: TypeScript. - Keep modules focused by domain. - Prefer readable code over clever abstractions. - Use Biome as the only formatter/linter in this project. --- ## Migration Notes (Old Backend) Legacy code exists in `../old/monie-backend`. When migrating: - migrate by domain, not by mass copy; - remove deprecated scaffolding and sample-only code; - do not copy insecure placeholders (e.g., hardcoded JWT secrets); - adapt old code to current monorepo structure and Biome formatting. Suggested migration order: 1. `auth` baseline (login/logout/profile + guards/roles) 2. `bookings` public read endpoints needed by widget/web 3. `tasks` and `notifications` 4. gateway aggregation behavior (if still needed) --- ## Testing Expectations For any non-trivial change: - add or update unit tests for changed services/controllers; - run `npm run test`; - run `npm run test:e2e` when routes/bootstrapping are touched. For auth, booking rules, and access-control changes, tests are mandatory. --- ## Done Criteria A backend task is considered done when: 1. scope is limited to required app/module(s); 2. API behavior is validated (tests and/or manual endpoint check); 3. `npm run check` passes; 4. `npm run build` passes; 5. no secrets or temporary hardcoded sensitive values are introduced. --- ## Commit Convention Use Conventional Commits with backend scope when useful: - `feat(backend): ...` - `fix(backend): ...` - `refactor(backend): ...` - `test(backend): ...` - `chore(backend): ...` If change is isolated to a backend app, scope can be more specific: - `feat(auth): ...` - `feat(bookings): ...` - `fix(gateway): ...`