ADR-0011 — Frawl affiliate platform
Approved architecture and integrity boundaries for Frawl.
ADR-0011 — Frawl affiliate platform
Status: Implementation of the owner-approved plan, 2026-09-22; runtime adaptation documented below. Supersedes the template's product/runtime/locale assumptions in ADR-0002, ADR-0009 and ADR-0010.
Decision
Use Next.js 16, React and Node on Vercel for the merchant application, and Cloudflare Workers for tracking. Share type-safe domain contracts across both. PostgreSQL 17 on Neon is the financial source of truth; Prisma owns the schema and SQL migrations add RLS, partitions, append-only enforcement and balanced-entry constraints.
Organization is the tenant. Product rows and foreign keys carry organization and environment.
Runtime connections assume a role without BYPASSRLS. Narrow SECURITY DEFINER functions expose
only the minimum bootstrap lookup required to route provider events, API keys and scheduled work.
Identity tables are a separate authorization boundary rather than being granted a fictional tenant context.
Data flow
flowchart LR
SDK[Consent-aware SDK] --> Edge[Tracking Worker]
Edge --> Queue[Cloudflare Queue]
Queue --> Ingress[Signed durable batch ingress]
Ingress --> DB[(PostgreSQL)]
Merchant[Merchant backend] --> Claim[Signed referral claim]
Claim --> DB
PSP[Provider webhook] --> Verify[Signature and trusted retrieval]
Verify --> Inbox[Durable inbox]
Inbox --> Engine[Attribution, fraud and commission]
Engine --> DB
DB --> Outbox[Transactional outbox]
Outbox --> Jobs[Retry and reconciliation]
DB --> UI[Merchant and affiliate portals]The Worker queue currently forwards signed batches to the Node control plane, which commits
batched inserts. It does not open a PostgreSQL connection for every click. The database exports
createWorkerDatabase for a future direct consumer; if Hyperdrive is used, query caching must
be disabled for authorization and financial reads. This adapts the proposed direct Hyperdrive consumer
so the initial release shares one durable ingestion and financial processing implementation in Node.
The deployed latency and backlog gates remain mandatory before this path is accepted for production.
Integrity contracts
| Area | Contract |
|---|---|
| Money | Bigint minor units, explicit currency, immutable balanced ledger |
| Idempotency | Provider delivery key plus canonical payment/adjustment financial key |
| Attribution | Server-stamped touches, first/last policy, bounded window, pinned subscription association |
| Race handling | Pending attribution, durable inbox, transaction retries and tenant locks |
| Refunds | Cumulative delta capped at original commission; exported reservations remain held |
| Payouts | Separate prepare/approve/confirm grants; immutable export fingerprint and payment references |
| Billing | Internal subscription/cycle/attempt IDs; fixed Moyasar given_id across uncertain outcomes |
| Identity | Verified SSO trust, source-specific SCIM subjects, explicit group role projection |
| Browser privacy | Consent before persistent identity, no covert fingerprinting, no ITP bypass promise |
Boundaries and tradeoffs
A merchant's PSP payment, a Frawl subscription payment, and an affiliate external payout never share a payment model or webhook secret. Affiliates are not organization members by default. Manual payout approval is intentional; automated bank transfers are outside the approved release.
Queue and webhook delivery is at least once; all consumers must be idempotent. Ledger state, audit and outbox entries commit together. No migration or closure cascades through financial history. English is default; all user-facing flows also support Arabic and logical RTL properties.
A single primary region makes financial consistency tractable. Edge ingress minimizes the visitor's blocking work, while write batching separates app requests from click ingestion. Local benchmark numbers do not prove the 1,000 requests/second deployed target.
Commercial assumptions
Starter $49, Growth $149, Enterprise $499 monthly, annual billing at ten monthly payments; prices and limits are versioned. Twenty Starter, five Growth and one Enterprise account would produce $2,224/month, or SAR 8,340 at the illustrative 3.75 rate, before fees and operating costs. Confidence: low. Channel: Frawl subscriptions. This is a scenario, not a forecast.
References
ADR-0010: A daily-performance product with deterministic-first agents
The template's Saudi merchant vertical is replaced by one product module whose agents run on a local deterministic engine, with a model as an optional second implementation of the same output contract.
ADR-0012 — Diamond Cloud holding workspace
Relocate Frawl while preserving its repository, runtime boundaries and development context.