--- name: Backend Context description: Stack, two-listener architecture, route conventions, and auth flow for the Halo Bestie backend type: project --- Fastify.js REST API — single process, two HTTP listeners. **Listeners:** - Public `0.0.0.0:3000` → serves `client_app` + `mitra_app` - Internal `private-ip:3001` → serves `control_center` only (never expose publicly) **Route namespacing:** - `/api/client/` — client app routes - `/api/mitra/` — mitra app routes - `/api/shared/` — shared routes (auth, lookup, etc.) - `/internal/` — control center routes (internal listener only) **Auth flow:** 1. Firebase Auth issues JWT on mobile/web 2. Client sends `Authorization: Bearer ` 3. Fastify verifies via Firebase Admin SDK 4. User fetched from PostgreSQL by Firebase UID **Stack:** Fastify.js, PostgreSQL (GCP Cloud SQL), Firebase Admin SDK, Xendit, GCP Cloud Run **Conventions:** - Business logic in `services/` — never directly in route handlers - All routes authenticated unless explicitly marked public - Internal routes require additional `role: admin` check - Do not mix public and internal listener route registrations