Files
falah-mobile/docs/auth-architecture-reference.md
T
wmj 5b08f8b041 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
2026-06-28 21:29:54 +02:00

9.0 KiB

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 NopasswordHash 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 Nopassword_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

# 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

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

# 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:

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

docker logs falah_ummahid.1.<id> 2>&1 | grep selfheal
# Expected: "✓ Demo user OK — password matches, tier is premium"

6.5 V2 Community Health

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.