From 5b08f8b041c56a36d95ca54bebdbf580c01b1e2d Mon Sep 17 00:00:00 2001 From: WMJ Ismail Date: Sun, 28 Jun 2026 21:29:54 +0200 Subject: [PATCH] docs: add system auth architecture reference (28 June 2026) Comprehensive document covering: - Auth chain (how login works end-to-end) - Three-database architecture (UmmahID SQLite, V1 Mobile SQLite, Postgres) - Password management (self-heal = single source of truth) - FLH Islamic Finance endpoints and data flow - Testing checklist for future verification - Troubleshooting history --- docs/auth-architecture-reference.md | 249 ++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 docs/auth-architecture-reference.md diff --git a/docs/auth-architecture-reference.md b/docs/auth-architecture-reference.md new file mode 100644 index 0000000..2162e89 --- /dev/null +++ b/docs/auth-architecture-reference.md @@ -0,0 +1,249 @@ +# Falah Mobile — System Reference & Auth Architecture + +> **Last updated:** 28 June 2026 +> **Purpose:** Single source of truth for understanding the database architecture, auth chain, password management, and FLH Islamic Finance setup across all FalahOS services. + +--- + +## 1. Auth Chain (How Login Works) + +``` +Browser ──POST /mobile/api/auth/login──▶ V1 Mobile (Next.js) + │ + Proxy to UmmahID + │ + ▼ + UmmahID (Node.js) + │ + SQLite ledger.db + │ + bcrypt.compare(password, hash) + │ + ┌─────┴─────┐ + ▼ ▼ + ✅ 200 ❌ 401 + (JWT) (Invalid credentials) +``` + +### Detailed flow + +1. Browser sends `POST /mobile/api/auth/login` with `{email, password}` to V1 Mobile. +2. V1 Mobile proxies the request to UmmahID service (`falah_ummahid:3000`). +3. UmmahID looks up user in **SQLite** (`/data/ledger.db`), compares password with bcrypt. +4. If valid, UmmahID returns a **JWT** token + user info. +5. V1 Mobile then **finds or creates** a local `User` record in its own SQLite (`/app/data/dev.db`) for app features (wallet balance, gamification, etc.). +6. Browser receives the JWT and uses it for subsequent API calls. + +--- + +## 2. Database Architecture (Three Databases) + +### 2.1 UmmahID SQLite — `ledger.db` + +| Property | Value | +|----------|-------| +| **Container** | `falah_ummahid` (Swarm service) | +| **Path** | `/data/ledger.db` | +| **Host bind** | `/root/falah-ummahid-db/ledger.db` | +| **Engine** | sql.js (SQLite via Node.js) | +| **Auth** | **Yes** — single source of truth for passwords | +| **Tables** | `users`, `accounts`, `transactions`, `zakat_*`, `sadaqah_*`, `hibah_records`, `waqf_*`, `forum_*`, `learn_*` | + +**Password column:** `password_hash` (bcrypt hash) + +**GOOGLE_CRITICAL:** This is the **only** place where passwords are verified. The self-heal script (`startup-selfheal.js`) is the **sole authority** for the demo user's password. + +### 2.2 V1 Mobile SQLite — `dev.db` + +| Property | Value | +|----------|-------| +| **Container** | `falah_falah-mobile` (Swarm service) | +| **Path** | `/app/data/dev.db` | +| **Engine** | Prisma with SQLite provider | +| **Auth** | **No** — `passwordHash` field is NULL for all users | +| **Tables** | `User`, `Listing`, `Purchase`, `Review`, `LearnCourse`, `ForumPost`, etc. | + +**Password column:** `passwordHash` (always NULL — not used for auth) + +**Purpose:** Stores app-level data: user profile, FLH balance cache, gamification (XP, streaks, levels), marketplace, learning progress, etc. + +### 2.3 Postgres — `falahdb` (Community V2) + +| Property | Value | +|----------|-------| +| **Container** | `falah_postgres` (Swarm service) | +| **Connection** | `ummahid-community` container via `DATABASE_URL=postgresql://postgres:@falah_postgres:5432/falahdb` | +| **Auth** | **No** — `password_hash` column **removed** (28 June 2026) | +| **Tables** | `users`, `accounts`, `zakat_*`, `sadaqah_*`, `hibah_records`, `waqf_*`, `forum_*`, `learn_*` | + +**Password column:** ❌ DELETED — this was the source of confusion. Auth is delegated to UmmahID SQLite or JWT verification. + +**Purpose:** FLH Islamic Finance engine (zakat, sadaqah, hibah, waqf), community features (content, qard hasan, learn). + +--- + +## 3. Password Management (The Self-Heal Script) + +**File:** `/root/falah-ummahid-db/startup-selfheal.js` + +**Mount:** Bind-mounted from host `/root/falah-ummahid-db/` → container `/data/` + +### Behaviour + +- Runs **every time** the `falah_ummahid` container starts. +- Re-hashes the demo password if it doesn't match `DEMO_PASSWORD`. +- Ensures `license_tier = 'premium'`. +- Creates the demo user + account if missing (100,000 FLH). +- **Single source of truth** — nothing else should write to the `users` or `accounts` tables in SQLite. + +### Changing the Demo Password + +```bash +# 1. Edit the self-heal script +vim /root/falah-ummahid-db/startup-selfheal.js +# Change: DEMO_PASSWORD='***' + +# 2. Restart the UmmahID service +docker service update --force falah_ummahid + +# 3. Done — no other database needs updating +``` + +### What NOT to do + +- ❌ Do NOT write directly to SQLite `users.password_hash` +- ❌ Do NOT add `password_hash` column back to Postgres +- ❌ Do NOT run seed scripts that write passwords to Postgres + +--- + +## 4. FLH Islamic Finance Architecture + +### 4.1 Endpoints + +| Category | V1 Mobile Proxy Route | V2 Community Backend Route | +|----------|----------------------|---------------------------| +| **Summary** | `/mobile/api/flh/summary` → | `/api/v2/flh/summary` | +| **Zakat** | `/mobile/api/flh/zakat/*` → | `/api/v2/zakat/*` | +| **Sadaqah** | `/mobile/api/flh/sadaqah/*` → | `/api/v2/sadaqah/*` | +| **Hibah** | `/mobile/api/flh/hibah/*` → | `/api/v2/hibah/*` | +| **Waqf** | `/mobile/api/flh/waqf/*` → | `/api/v2/waqf/*` | +| **Cron Health** | — | `/api/v2/flh/cron-health` | + +### 4.2 Data Flow + +``` +V1 Mobile UI ──▶ V1 Mobile API Route (proxy) ──▶ ummahid-community (Postgres) + │ + JWT auth via: + 1. UmmahID API (preferred) + 2. Local JWT verify (fallback) +``` + +### 4.3 Zakat Agents (18 pre-seeded) + +Covers 9 countries: UAE, Bangladesh, Egypt, Indonesia, Malaysia, Pakistan, Saudi Arabia, Turkey. + +### 4.4 Cron Jobs (6 scripts) + +Located in `/root/ummahid-community/cron/`: + +| Script | Schedule | Purpose | +|--------|----------|---------| +| `00-health.sh` | Every 15 min | Heartbeat check | +| `10-sadaqah-process.sh` | Every 6h | Process due recurring sadaqah | +| `20-hibah-expiry.sh` | Every 1h | Expire unaccepted hibah gifts | +| `30-waqf-yield.sh` | Daily midnight | Accrue waqf yield | +| `40-nisab-update.sh` | Daily 6am | Update nisab threshold | +| `50-zakat-reconcile.sh` | Weekly Mon 2am | Reconcile zakat pool | + +--- + +## 5. Key Configuration Files + +| File | Purpose | +|------|---------| +| `/root/falah-ummahid-db/startup-selfheal.js` | **Self-heal — single source of truth for demo password** | +| `/root/falah-mobile/.env.local` | V1 Mobile env vars (`COMMUNITY_URL`, `UMMAHID_URL`) | +| `/root/ummahid-community/config/community.env` | Community V2 env vars (`JWT_SECRET`, `UMMAHID_HOST`, `DATABASE_URL`) | +| `/root/falah-mobile/src/app/api/flh/zakat/calculate/route.ts` | Zakat calculate proxy (handles `amount=0` as status check) | +| `/root/falah-core/docker/services/ummahid-community/pg.js` | Postgres persistence layer for community V2 | + +--- + +## 6. Testing Checklist + +### 6.1 Login Verification + +```bash +curl -X POST -H 'Content-Type: application/json' \ + -d '{"email":"demo@falahos.my","password":"demo123"}' \ + https://falahos.my/mobile/api/auth/login +# Expected: 200 with {"token":"eyJ...", "user":{...}} +``` + +### 6.2 FLH Dashboard + +```bash +# Login first, extract token, then: +curl -H "Authorization: Bearer " \ + https://falahos.my/mobile/api/flh/summary +# Expected: {"success":true,"totalFlhBalance":5000,"pillars":{...}} +``` + +### 6.3 Password Consistency + +Check that `password_hash` does NOT exist in Postgres: + +```bash +docker exec falah_postgres.1. psql -U postgres -d falahdb \ + -c "SELECT column_name FROM information_schema.columns \ + WHERE table_name='users' AND column_name='password_hash'" +# Expected: 0 rows +``` + +### 6.4 Self-Heal Status + +```bash +docker logs falah_ummahid.1. 2>&1 | grep selfheal +# Expected: "✓ Demo user OK — password matches, tier is premium" +``` + +### 6.5 V2 Community Health + +```bash +curl -H "Authorization: Bearer " \ + https://falahos.my/api/v2/flh/cron-health +# Expected: 200 with health status +``` + +--- + +## 7. Troubleshooting History + +### 28 June 2026 — Login Failure & Resolution + +**Symptom:** `401 Invalid credentials` when logging in with `TestPass123!`. + +**Root cause:** Three different passwords across three databases: +- Self-heal script had `DEMO_PASSWORD='falahdemo2026'` +- Postgres had stale hash for `password123` +- User expected `TestPass123!` + +**Fix:** +1. Unified all references to `demo123`. +2. Deleted `password_hash` column from Postgres `users` table. +3. Locked self-heal as single source of truth. +4. Updated all debug scripts, seed files, and test suites. + +### Previous — JWT_SECRET Mismatch + +**Symptom:** Auth worked then failed after container restart. + +**Root cause:** `falah_ummahid` used 64-char JWT_SECRET, but `ummahid-community` had a different one. + +**Fix:** Harmonized JWT_SECRET across all services to the 64-char value from `falah_ummahid`. + +--- + +> **⚠️ Golden Rule:** Auth = UmmahID SQLite. Postgres has NO password_hash. The self-heal script is the ONLY authority for the demo password. Do not add password storage anywhere else.