# Phase 1 Plan — Authentication ## Overview Three separate auth flows across three apps, backed by one Fastify backend, Firebase Auth, and PostgreSQL. --- ## Database Schema ### `customers` | Column | Type | Notes | |---|---|---| | `id` | UUID PK | | | `firebase_uid` | VARCHAR | null if anonymous | | `phone` | VARCHAR | null if anonymous | | `display_name` | VARCHAR | user-chosen, never from social | | `is_anonymous` | BOOLEAN | true until phone/social linked | | `created_at` | TIMESTAMP | | ### `mitras` | Column | Type | Notes | |---|---|---| | `id` | UUID PK | | | `firebase_uid` | VARCHAR | set on first login | | `phone` | VARCHAR | primary identifier | | `display_name` | VARCHAR | | | `is_active` | BOOLEAN | toggled by control center | | `created_at` | TIMESTAMP | | ### `control_center_users` | Column | Type | Notes | |---|---|---| | `id` | UUID PK | | | `firebase_uid` | VARCHAR | | | `email` | VARCHAR | | | `display_name` | VARCHAR | | | `role_id` | FK → `roles` | | | `created_at` | TIMESTAMP | | ### `roles` | Column | Type | Notes | |---|---|---| | `id` | UUID PK | | | `name` | VARCHAR | e.g. `super_admin`, `operator` | | `permissions` | JSONB | flexible permissions object | | `created_at` | TIMESTAMP | | --- ## Backend (`/backend`) ### Public routes (port 3000) - `POST /api/shared/customer/anonymous` — create anonymous customer with display name - `POST /api/shared/customer/link` — link phone/social to existing anonymous customer - `POST /api/client/auth/verify` — verify Firebase JWT, return customer profile - `POST /api/mitra/auth/verify` — verify Firebase JWT, return mitra profile ### Internal routes (port 3001) - `POST /internal/mitras` — create mitra record - `PATCH /internal/mitras/:id/status` — activate/deactivate mitra - `POST /internal/control-center-users` — create control center user - `GET /internal/control-center-users` — list users - `POST /internal/auth/verify` — verify Firebase JWT, return CC user + role + permissions - `GET /internal/config/anonymity` — get anonymity setting - `PATCH /internal/config/anonymity` — toggle anonymity on/off --- ## client_app (`/client_app`) **Screens:** 1. **Welcome** — "Continue as Guest" or "Register" 2. **Pick Display Name** — shown to all users (anonymous and registering) 3. **Register** — phone OTP or social login (Google/Apple) 4. **Force Register Wall** — shown after session ends if anonymity is disabled; display name pre-filled **Firebase Auth flows:** - Phone OTP via `firebase_auth` - Google Sign-In via `google_sign_in` - Apple Sign-In via `sign_in_with_apple` --- ## mitra_app (`/mitra_app`) **Screens:** 1. **Login** — phone number input 2. **OTP Verification** 3. **Home** (post-login, Phase 1 placeholder) **Notes:** - No self-register screen — login only - If phone not found in `mitras` table → show error "Account not found. Contact your administrator." - If mitra `is_active = false` → show error "Account is inactive. Contact your administrator." --- ## control_center (`/control_center`) **Screens:** 1. **Login** — email + password (Firebase Auth) 2. **Mitra Management** — create mitra, toggle active/inactive 3. **Control Center User Management** — create users, assign roles 4. **Settings** — toggle anonymity on/off --- ## Seed Script - Creates first `super_admin` role with full permissions - Creates first control center user (email + password via Firebase Auth + DB record) --- ## Out of Scope for Phase 1 - Mitra onboarding flow (documents, verification) - Chat / session features - Payment / trial period - Real-time features - Specific role definitions (RBAC scaffolded, roles defined later)