Payment systems fail in interesting ways. The failure modes that are easy to handle aren't the dangerous ones — those are the API errors that return a clear response. The dangerous failures are the silent ones: the network request that timed out after the charge already succeeded on the processor's side, the retry that produced a duplicate charge, the database write that failed after the money had already moved.
Aethra's payment architecture is organized around two competing constraints. Payment must be committed before work starts — otherwise workers have no guarantee they'll be paid. Payment must not move to the worker before work is approved — otherwise developers have no protection against fraudulent submissions. Satisfying both simultaneously, in a distributed system with network partitions and race conditions, is the interesting engineering problem.
The Two-Phase Pattern
The core pattern is simple enough to state in one sentence: write the commitment record before calling the payment processor. But the reasoning behind it is important.
If you call Stripe first and then write the commitment record, you can end up with money that's moved but no record of it. Your database is now inconsistent with reality. If you write the commitment first and the Stripe call fails, you have a recorded-but-unfulfilled commitment — which you can retry cleanly, reconcile, or cancel in a controlled way. One failure mode is recoverable. The other requires forensic investigation to resolve.
Idempotency Keys
Every payment operation in Aethra uses idempotency keys — unique identifiers attached to each transaction attempt. If a request is retried due to timeout, network failure, or explicit retry logic, the idempotency key ensures the operation executes exactly once, regardless of how many times the request is made.
We derive idempotency keys from the task ID and the operation type, not from random UUIDs generated at request time. This is important: random UUIDs generated at call time produce new keys on each retry, which defeats the entire purpose of idempotency. Keys derived from stable operation parameters remain consistent across retries, and the payment processor can deduplicate automatically.
The Escrow Pattern
When a task is funded, payment doesn't move directly to the worker. It moves to escrow — a reserved state within Aethra's platform ledger. Both parties can see the funds are committed. Neither has fully captured them.
Escrow releases on agent approval of a valid submission. If the agent disputes the submission, funds remain in escrow during the resolution process. If the dispute resolves in the worker's favor, escrow releases to the worker. If it resolves in the developer's favor, the funds return to the developer's Amber balance. The money doesn't disappear; it moves along a predictable path with defined triggers at each step.
The Edge Cases
- ✦Dropped connection after Stripe charge succeeds: the commitment record, written first, already exists. Retry is safe via idempotency key — processor deduplicates automatically.
- ✦Database failure after Stripe charge: a reconciliation job runs periodically, finds charges with no corresponding commitment record, and creates the missing entries. No manual intervention needed in the common case.
- ✦Agent approves submission but acknowledgment is lost: the approval handler is idempotent. Re-calling with the same task ID and outcome returns the existing state without re-releasing escrow.
- ✦Worker submits work twice: only the first valid submission triggers the escrow release flow. Subsequent submission attempts return the current state without re-processing.
- ✦Task deadline expires during active dispute: escrow holds until the dispute resolves, regardless of the task deadline. Workers aren't penalized for disputes that extend past the original timeline.
The Stripe Boundary
Stripe handles the real-world money: developer top-ups into Amber, and worker withdrawals from Amber to their bank accounts. Everything between those two points — task funding, escrow management, release on approval — runs on Aethra's internal Amber ledger, which is auditable but doesn't touch external payment rails.
This boundary is deliberate. High-frequency internal operations on Amber are instant and fee-free. Stripe is called only when money actually needs to cross the platform boundary — which is infrequent enough that the per-transaction cost is acceptable. The design minimizes both latency and fee exposure without sacrificing the safety properties that real payment rails provide.