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
This commit is contained in:
@@ -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 <token>" \
|
||||
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.<id> 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.<id> 2>&1 | grep selfheal
|
||||
# Expected: "✓ Demo user OK — password matches, tier is premium"
|
||||
```
|
||||
|
||||
### 6.5 V2 Community Health
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer <token>" \
|
||||
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.
|
||||
Reference in New Issue
Block a user