Shape
Edge functions by role
All functions deploy with
verify_jwt: false because they use custom cc_session or bearer authentication rather than Supabase Auth.
Keepers
The keeper is the platform’s only privileged runtime actor, and its privilege is liveness only.The keeper re-resolves the recipient on-chain via
effectiveRecipient and gates deploy and sweep on the re-derived address. It cannot be pointed at a different destination by tampering with the database.Indexers
pool-indexer-poll watches forwarder addresses and pool events, drives pool_deposit_intents through its status machine, and enriches payer addresses via transaction lookups.
It also re-derives the expected pool and forwarder independently and flags tamper_suspected rather than reconciling an unanchored pool.
RPC
Public keyless RPCs with CORS are the baseline:*.publicnode.com plus per-chain official endpoints. Alchemy is used where available. create-quote uses a viem fallback transport with two RPCs per chain and a 5-second per-attempt timeout.
CSP connect-src allowlists publicnode, base.org, optimism.io, arbitrum.io, avax.network, polygon-rpc.com, llamarpc, infura, and ankr.
Data model
Merchant surfaces are pool-only since 2026-07-01. They readpool_deposit_intents, pool_distributions, and merchant_pools. paid_events and payment_intents are the legacy atomic rail and are dropped from all merchant reads. Platform-admin surfaces still use paid_events.
Token amounts are stored in base units — USDC, USDT, and EURC are 6-decimal — and divided by 10^token_decimals for display.
Conventions
- All wallet addresses are lowercased before storage and comparison, via
_shared/wallet.ts:lc().
- The
cc_sessioncookie ishttpOnlyand must never be read from JavaScript. - EIP-1271 verification uses the per-chain
publicClient.verifyMessage, not viem’s top-levelverifyMessage, which is EOA-only.