Abstraction layers, idempotency by construction, signed webhooks with receipts, and a ledger where every number has a paper trail.
The payment layer is a clean abstraction — banking rails are pluggable providers behind it. Integrating new rails is an engineering task, not a rebuild.
Amounts move through the stack as minor units — cents and micro-USDC — never floats. Six-decimal precision for on-chain dollars, two for bank dollars.
Every money-moving call carries an idempotency key. Retries converge on the same outcome — no double conversions, no phantom withdrawals.
Provider events arrive with signatures that are verified before processing. Duplicate deliveries are deduplicated by identity, and processing failures retry with exponential backoff into a dead-letter queue — nothing is silently dropped.
Webhooks drive real-time state; a scheduled reconciliation pass independently verifies what the provider reports against the ledger. Either channel can recover the other.
Raw event payloads and processing outcomes are stored with an audit trail — you can always answer "what did we receive, and what did we do about it".
Balances are computed from an append-only, double-entry journal. Every dollar in, out, or converted has matching debit and credit entries — reconciliation is a property of the design, not a weekly chore.