RefundProof
RefundProof turns a customer refund into a durable, evidence-bound operation that can survive a lost provider response without blindly sending money twice.
Inspiration
The most dangerous payment failure is ambiguous success: a client times out, but the payment provider may already have accepted the financial effect. Support tools often respond by retrying, while approval tools authorize a mutable ticket rather than the exact payload that will be sent. We wanted a refund system that can prove what evidence was used, what a person approved, what reached PayPal, and why a retry did or did not happen.
What it does
- Encrypts original customer evidence and gives only a redacted copy to the proposal boundary.
- Reads the authoritative capture from PayPal Sandbox.
- Produces a schema-constrained AI or human refund proposal with verified evidence citations.
- Seals amount, currency, capture, policy, and evidence into an immutable revision digest.
- Requires a different human approver; full refunds require typed amount consent.
- Derives one durable operation and deterministic PayPal request ID from the approved facts.
- Dispatches through a worker that records every provider attempt.
- Reconciles an unknown outcome with PayPal instead of automatically sending again.
- Shows the complete proof trail in a production-style operator console.
How we built it
RefundProof uses Next.js 16 and React 19 for the console, PostgreSQL 17 for tenant-scoped durable state, and a separate TypeScript worker for outbox dispatch and reconciliation. The domain kernel uses integer minor units, canonical JSON, content digests, derived bound IDs, and explicit state machines. The PayPal adapter is locked to the Sandbox API and uses PayPal request idempotency. Customer evidence is encrypted at rest and redacted before model input.
The proposal boundary supports Anthropic, real local Ollama, and labelled fixture adapters. Model output is never trusted directly: money precision, reason codes, citations, source digests, capture identity, and policy bounds are independently verified before a person can approve it. A verified run called qwen3:4b through Ollama against a fresh real PayPal Sandbox capture. It produced an exact 84.00 USD proposal, all 3/3 required citations matched the evidence, and the revision had zero correction reasons. AI stopped before approval and execution.
Challenges we faced
A real Sandbox rehearsal exposed a production-shaped defect: PostgreSQL jsonb reordered object keys while the pre-dispatch guard compared snapshots with JSON.stringify. The values were identical, but key order differed, so the worker safely cancelled before calling PayPal. We reproduced the bug with a red test, changed the guard to canonical JSON comparison, restarted the worker, and completed the real PayPal Sandbox refund through the normal UI with one provider attempt.
The local-model rehearsal found another integration issue: some enum and const constraints were not enforced by Ollama's grammar path. We kept the verifier strict, generated native JSON Schema for Ollama, bound the exact capture ID and admitted evidence labels into that schema, and added regression tests. Malformed output remains durably recorded as rejected.
Accomplishments
- A real PayPal Sandbox capture read and completed refund, not a mocked central payment path.
- A real qwen3:4b call with 3/3 exact citations and an approval-ready revision.
- Exact approval-to-operation binding with role separation.
- Durable unknown-outcome state and reconciliation rather than blind retries.
- Encrypted evidence, redacted model input, and provider-safe public artifacts.
- Adversarial regression coverage for canonical comparison, retries, restart recovery, and tenant isolation.
What we learned
Idempotency is not a header added at the final API call. It is a system property that starts with immutable approval facts, continues through operation identity and durable attempts, and ends only after provider reconciliation. Real Sandbox rehearsals catch storage and process-lifecycle problems that happy-path mocks cannot.
Verifiable run
The final PayPal Sandbox refund returned HTTP 201 / COMPLETED in one provider attempt for 84.00 USD. The demo also shows a separate real Ollama proposal with exact evidence citations; that AI run deliberately stops before approval and money movement.
What's next
We plan to add proposal-quality evals, managed deployment profiles, external security review, and extend the same evidence-bound operation model to payouts, disputes, and multi-provider payment operations.
Source and complete setup: https://github.com/gnanam1990/paypal-refundproof
Built With
- docker
- next.js
- node.js
- ollama
- paypal
- paypal-rest-api
- postgresql
- qwen3
- react
- typescript
- zod