From 14b34ad5322554d4149638b24d71002684d74600 Mon Sep 17 00:00:00 2001 From: Wmj Ismail Date: Tue, 18 Aug 2026 13:12:05 +0800 Subject: [PATCH] docs: add architecture visuals and RAMZ tenant isolation decision Clio/Stripe competitive benchmark, moslem03/04 backend reality check, and the moslem04 sync API spec, plus the resolved schema-per-tenant isolation decision that unblocks Phase 2 of the sync spec. --- docs/architecture/benchmark-clio-stripe.html | 445 ++++++++++++++++++ .../integration-reality-check.html | 259 ++++++++++ .../ramz-tenant-isolation-decision.md | 58 +++ docs/architecture/sync-api-spec.html | 224 +++++++++ 4 files changed, 986 insertions(+) create mode 100644 docs/architecture/benchmark-clio-stripe.html create mode 100644 docs/architecture/integration-reality-check.html create mode 100644 docs/architecture/ramz-tenant-isolation-decision.md create mode 100644 docs/architecture/sync-api-spec.html diff --git a/docs/architecture/benchmark-clio-stripe.html b/docs/architecture/benchmark-clio-stripe.html new file mode 100644 index 0000000..35d705c --- /dev/null +++ b/docs/architecture/benchmark-clio-stripe.html @@ -0,0 +1,445 @@ +Falah OS — Competitive Benchmark: Clio & Stripe + + +
+
+ Falah OS — Nur Falah Admin Console +

Competitive benchmark: Clio & Stripe Dashboard

+

Two reference products mapped against EstateOS and the cross-tenant super-admin surface. Every row ends in a call: steal the pattern, build it ourselves, or note it as a structural gap the reference product simply doesn't resolve.

+
+ +
+
+
+

Clio

+ vs. EstateOS +
+

Legal practice management — case files, billing, client portal, co-counsel collaboration.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature areaWhat Clio doesVerdict for EstateOS
Intake → billingClio Grow captures leads via custom forms, hands off to Clio Manage automatically once a matter opens.Steal
Document automationTemplate library with variable-filled document generation, version control.Steal
Billing & invoicingTimers, hourly/contingency billing, AI-drafted invoices with error flagging.Steal
Trust accountingClient trust ledgers, deposit/disbursement tracking, compliance reporting.Steal
Client portalEncrypted messaging, document sharing, payments — but single-brand, one firm per instance.Steal UX
Faraid / Syariah workflowsNo inheritance-share calculation, no Syariah Court filing templates — generic common-law matter types only.Build
Panel-lawyer vetting"Clio for Co-Counsel" assumes counsel is already chosen — it's a collaboration portal, not a credentialing tool.Build
Per-tenant brandingClient portal is single-brand per firm — no white-label capability for a platform serving multiple firms.Build
Multi-tenant backendClio is one firm, one instance — no shared-backend, multi-firm architecture exists to compare against.Structural gap
RAMZ row-level accessFirm-scoped permissions throughout — no concept of row-level, cross-tenant gating.Structural gap
+
+
+ +
+
+
+

Stripe Dashboard

+ vs. Falah OS super-admin +
+

Connect platform admin — connected-account management, roles, audit, API access.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature areaWhat Stripe doesVerdict for Falah OS
Admin role tiersAdmin vs. Super Administrator — Super Admin gates who can grant/revoke roles and manage environments.Steal
Audit loggingActivity Logs API — exportable, SOC 2/PCI-ready record of key changes, invitations, role changes.Steal
API key scopingRestricted keys limited to specific permission sets per integration.Steal
Tenant status viewConnected-account list with onboarding and risk status at a glance.Steal UX
Onboarding flowHosted or embedded onboarding, incremental — collects only what's currently required.Steal
Cross-regime compliance routingNo concept of routing tenants through different regulatory rule sets (Syariah Court vs. JKPTG vs. govt case routing).Build
Usage / billing-trigger eventsActivity Logs are security-focused, not usage-metering. Stripe's actual metering product wasn't covered — separate follow-up needed.Build / unclear
Tenant = product lineEvery connected account is a roughly uniform merchant entity — no support for managing distinct SaaS products per tenant.Structural gap
RAMZ row-level accessIsolation happens at the account level (own object graph per tenant) — closer to separate-DB than row-level gating.Structural gap
+
+
+ +
+ Steal pattern transfers directly + Build reference has nothing comparable + Structural gap reference's whole model doesn't apply +
+ +
+
+

Combined — steal list

+
    +
  1. Intake → billing handoff (Clio Grow → Manage)
  2. +
  3. Document automation + template library
  4. +
  5. Trust ledger compliance reporting
  6. +
  7. Two-tier Admin / Super Admin roles
  8. +
  9. Exportable audit log, scoped API keys
  10. +
+
+
+
+

Combined — build list

+
    +
  1. Faraid inheritance calculation engine
  2. +
  3. Panel-lawyer vetting / credentialing
  4. +
  5. Per-tenant white-labeled portal branding
  6. +
  7. RAMZ row-level, shared-schema isolation
  8. +
  9. Cross-regime compliance routing (Syariah / JKPTG / govt)
  10. +
+
+
+ +
+ Sources: clio.com, docs.stripe.com, support.stripe.com — full citations in the prior research turns. + Open: Core Ledger billing-event readiness still unconfirmed against Stripe's metering product. +
+
diff --git a/docs/architecture/integration-reality-check.html b/docs/architecture/integration-reality-check.html new file mode 100644 index 0000000..0ffba5f --- /dev/null +++ b/docs/architecture/integration-reality-check.html @@ -0,0 +1,259 @@ +Falah OS — Backend Integration Reality Check + + +
+
+ Falah OS — checked against the actual repos +

moslem03 has no backend either — same gap as moslem04

+

Verified against nur-muslim-companion-v2 and nur-falah-prevention source. Neither app talks to a Falah OS server. There is no existing pattern to copy — the admin console link has to be built from zero.

+
+ +
+

01 · What moslem03 actually does today

+
+
+
+ moslem03.falahos.my + Svelte 5 PWA · static build +
+
+
+ Public third-party APIs + Al Quran Cloud · Aladhan · Overpass +
+
+
+
+ ✕ No auth + Anyone opens the app, no login +
+
+ ✕ No Falah OS server + Never calls anything on the Contabo VPS +
+
+ ✕ No admin console link + Nothing to sync — data never leaves the browser +
+
+
+ Same for moslem04 + Same localStorage-only pattern +
+
+
+ +
+

02 · What has to be built — bottom up

+
+
+
+
+
+
+
casdoor (ummahid) identity service
+
Already running on the Contabo VPS :8000 — reuse it, don't rebuild login
+
+ Already exists +
+
+
+
1
+
+
+
Login screen in moslem04
+
App currently has zero auth UI — needs a casdoor sign-in flow bolted on
+
+ To build +
+
+
+
2
+
+
+
Sync API (new)
+
Push Faraid / Assets / Wassiyah / Hibah / Waqf drafts from localStorage to a server, encrypted
+
+ To build +
+
+
+
3
+
+
+
RAMZ tenant tagging
+
Every synced record gets stamped with which tenant/firm it belongs to
+
+ To build +
+
+
+
4
+
+
+
Admin console read view
+
Nur Falah Admin Console reads synced cases — view only, not edit
+
+ To build +
+
+
+
+ exists on the VPS today + needs to be built — nothing to copy from moslem03 +
+
+
+ +
+ Bottom line: moslem03 gave us one reusable piece — casdoor login. Everything else (sync, tenant tagging, admin visibility) starts from scratch. +
+
diff --git a/docs/architecture/ramz-tenant-isolation-decision.md b/docs/architecture/ramz-tenant-isolation-decision.md new file mode 100644 index 0000000..430e2ad --- /dev/null +++ b/docs/architecture/ramz-tenant-isolation-decision.md @@ -0,0 +1,58 @@ +# RAMZ Tenant Isolation — Decision + +**Status:** Resolved +**Blocks:** Phase 2 of the [moslem04 Sync API spec](./sync-api-spec.html) (admin console read view) +**Originally flagged in:** Nur Falah Admin Console PRD review + +## The question + +Falah OS runs one shared backend serving three tenants — EstateOS (law firm estate/probate, +Syariah Court), Tanah Hidup (waqf land lease, JKPTG), and Cair (govt case routing). How is +each tenant's data isolated from the others? + +Two options were on the table: + +1. **Separate database per tenant** — strongest isolation, highest ops overhead. +2. **Row-level RAMZ-gated access in a shared schema** — cheapest, weakest isolation story. + +## Decision + +**Schema-per-tenant on a single shared Postgres cluster.** + +Each tenant (EstateOS, Tanah Hidup, Cair) gets its own Postgres schema. Not a separate +server, not a shared table filtered by a `tenant_id` column. + +## Why + +- The three tenants aren't multiple firms sharing one product (the Clio model) — they're + three structurally different products, each answering to a different regulator + (Syariah Court, JKPTG, government agencies). A `WHERE tenant_id = ?` filter on a shared + table is not an answer a regulator's auditor will accept at face value; a schema + boundary is something that can actually be demonstrated. +- This was flagged as a trust/compliance blocker for the UK Innovator Visa pitch — the + isolation model isn't just an engineering choice, it's part of the pitch. +- Fully separate databases (or separate servers) solve the same trust problem but multiply + ops burden — separate backup policies, connection pools, migrations to run three times + instead of once. Not justified at current scale. +- Schema-per-tenant keeps one cluster, one backup policy, one connection pool — while still + giving each tenant a real, auditable namespace boundary. + +## What RAMZ still does + +RAMZ doesn't disappear — it moves down a level. Within each tenant's schema, RAMZ handles +the finer-grained access control that a schema boundary can't: which user or law firm +within EstateOS can see which case, which land officer within Tanah Hidup can see which +lease. RAMZ was never going to be strong enough to be the *only* thing standing between +tenants — now it doesn't have to be. + +## Consequence for the sync API + +The `tenant_id` field in the [sync spec](./sync-api-spec.html) becomes a schema selector, +not a row filter. The admin console's `/v1/admin/metadata` endpoint queries across schemas +explicitly, per-tenant — there is no accidental cross-tenant query path. + +## Still open + +This resolves the isolation *model*. It does not resolve whether Core Ledger already emits +the billing-trigger events Phase 2 needs, or who owns panel-lawyer vetting — both remain +open from the earlier PRD review. diff --git a/docs/architecture/sync-api-spec.html b/docs/architecture/sync-api-spec.html new file mode 100644 index 0000000..b5d06e2 --- /dev/null +++ b/docs/architecture/sync-api-spec.html @@ -0,0 +1,224 @@ +moslem04 Sync API — Architecture Spec + + +
+
+ Falah OS — Nur Falah Estate & Waqf Suite +

Sync API architecture — moslem04.falahos.my

+

A server-side sync layer for moslem04's six local-first modules, gated by casdoor login, encrypted client-side before it ever leaves the device, and surfacing only opt-in metadata to the admin console — never raw estate documents.

+
Out of scope: moslem03 (Muslim Companion) stays exactly as-is — free, zero signup, no account, no sync, forever. This spec touches nothing there.
+
+ +
+

01Data flow, end to end

+
+
+
+ moslem04 (browser) + localStorage stays the source of truth offline; sync is additive, not a replacement +
+
+
+ casdoor (existing) + OIDC login, issues JWT — nothing new to build here +
+
+
+ Sync API (new) + Accepts encrypted blobs, tags with tenant + user, never decrypts +
+
+
+ Postgres (new) + Ciphertext + RAMZ tenant column + a small plaintext metadata row +
+
+
+ Admin console + Reads metadata only — opt-in, read-only, per Phase 2 below +
+
+
+
+ +
+

02What gets encrypted vs. what admin can see

+

Estate plans are the most sensitive data a person will put into this app. The sync API is built so the server — and by extension the admin console — physically cannot read the contents of anyone's Faraid, Wassiyah, Hibah, or Waqf drafts. Encryption happens on-device before upload.

+
+ + + + + + + + + + +
FieldWho can read itNotes
payload_ciphertextUser onlyAES-GCM, key derived from casdoor session + on-device passphrase. Server stores bytes it cannot open.
moduleUser + adminWhich of the 6 modules the record belongs to — plaintext, needed for routing and counts only.
plan_completedUser + adminBoolean per module. Lets the console show "how many people finished their Wassiyah" without seeing a single will.
panel_lawyer_requestedUser + adminExplicit opt-in flag the user sets — the only trigger that surfaces a person to a panel lawyer at all.
tenant_id (RAMZ)Admin onlyWhich tenant/firm this record is scoped to — still pending the row-level isolation decision from the PRD review.
claims_payload (H2)Nobody, not syncedHorizon 2 Claims module is excluded from sync entirely until the Phase 0 legal gate in DEPLOY.md clears.
+
+
+ +
+

03Endpoints

+
+ + + + + + + + + + +
MethodPathPurpose
POST/v1/auth/exchangeTrade a casdoor OIDC token for a moslem04 session token
GET/v1/sync/pull?since=<ts>Fetch records changed since last sync — for restoring on a new device
POST/v1/sync/pushBatch upsert of encrypted blobs from the local device queue
DELETE/v1/sync/:record_idTombstone a record — deletes propagate across the user's own devices
POST/v1/consent/panel-lawyerThe one explicit opt-in action that makes a user visible to EstateOS admin at all
GET/v1/admin/metadataAdmin console read — returns only the plaintext metadata fields from §02, RAMZ-scoped
+
+
+ +
+

04Conflict handling

+

These are single-owner personal drafts, not shared documents — so last-write-wins by updated_at is sufficient for five of the six modules. Two exceptions: Family Waqf Designator can involve co-designators, so pushes there append to a change log instead of overwriting; Digital Claims (H2) doesn't sync at all, see §02.

+
+ +
+

05Rollout phases

+
+
+
+ Phase 0 + Auth + sync plumbing + Login, encrypted push/pull, cross-device restore. No admin visibility of any kind. +
+
+ Phase 1 + Opt-in metadata surface + Panel-lawyer request flag goes live. Admin sees only what §02 allows. +
+
+ Phase 2 · blocked + Full admin console read view + Waits on the RAMZ isolation decision and Core Ledger billing-event readiness — both still open from the earlier PRD review. +
+
+
+
+ + +