Inspiration
AI agents are starting to buy things for people. That brings problems a normal checkout never had: an agent can be manipulated by a malicious message, can leak private details to a model, and, worst of all, when a payment response is lost, a simple retry can charge the customer twice. I wanted a layer that lets an agent help with purchasing without giving it authority over money.
What it does
OutProvenance Pay sits between an AI agent and PayPal. The rule is: AI suggests. Policy decides. Humans approve when required. PayPal confirms payment.
- Privacy: emails, phone numbers and card-like numbers are redacted before anything reaches the AI.
- AI suggestion only: the AI proposes one catalogue product. Its output is schema-checked, and it cannot change prices or approve anything.
- Agent verification: the agent's Ed25519-signed manifest is checked on every purchase.
- Deterministic policy: fixed rules use the trusted catalogue price (up to $75 allowed, up to $100 needs approval, above that denied).
- Exact-transaction approval: bound to the product, seller, amount and currency. It expires and works once.
- PayPal Orders API (Sandbox): the backend creates and captures the payment, and a payment counts as complete only when PayPal's server confirms it.
- Lost-response recovery: if a response is lost, the payment becomes an explicit
PENDING_RECONCILIATIONstate. A retry asks PayPal first, so it never blindly pays twice. - Signed receipts and an evidence chain: every step is a signed, hash-linked event, and tampering is detected by independent verification.
- Rogue Agent page and a 14-scenario Attack Lab that run real attacks against the real backend code.
How I built it
A FastAPI backend (SQLite, Ed25519 via cryptography, a PayPal Orders v2 client) and a React + TypeScript frontend. The payment state machine uses atomic compare-and-set transitions, and PayPal idempotency keys are used on create and capture. PayPal behaviour is tested with an in-memory mock that can inject failures such as a lost response. I built it with an AI coding assistant (Claude Code) under my direction, which is also listed in the repository's tools disclosure.
Challenges
- Making "unknown" a first-class payment state instead of guessing success or failure.
- Proving concurrency safety: my own concurrent-request test found a real bug (two receipts for one capture), which I fixed with a database unique index.
- Keeping claims honest about what a signature proves (integrity, not truth).
Accomplishments
141 automated tests pass, and all 14 Attack Lab scenarios pass, with each result computed from observed responses rather than hardcoded.
What I learned
Payment safety is mostly about handling uncertainty, and any "success" that doesn't come from the processor's own response shouldn't be trusted.
Honest status
This is a Sandbox prototype. The video does not show a live PayPal payment, and the lost-response scenarios run against a controlled PayPal simulator. There is no user login yet, keys are development files, and the evidence format is TRACE-inspired, not a conformant standard.
What's next
User authentication and roles, PayPal webhooks, KMS-backed key management, a hosted demo, and a live Sandbox run.
Built With
- cryptography
- ed25519
- fastapi
- httpx
- paypal
- paypal-orders-api
- pydantic
- pytest
- python
- react
- sqlalchemy
- sqlite
- typescript
- vite