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_RECONCILIATION state. 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

Share this project:

Updates

Submission history