Inspiration

A support agent can read a refund request, but the customer's message should not define the agent's payment authority. An injected instruction or a repeated tool call should not become permission to move money. Spendwall explores a practical boundary: let AI handle the conversation while explicit code checks the payment request against trusted context and merchant policy.

What it does

Spendwall checks an AI support agent's refund requests before execution. Its local demo combines ticket scope, trusted payment context, deterministic policy evaluation, persisted spending reservations, bound human approval and an audit trail. Missing trustworthy context results in denial. The policy decision path does not use an LLM.

The default demo runs five recorded scenarios with synthetic payment responses: a small refund, a refund requiring approval, out-of-ticket refund attempts, a repeated-refund limit and a buyer-side shopping order captured after scripted buyer approval. It executes real firewall modules and PostgreSQL operations, but it does not move PayPal funds. Human approval is scripted in this mode; the agent can request a refund and check status, but cannot approve its own request. An optional live Claude mode uses the same synthetic payment boundary.

A separate local React dashboard uses AG Studio to display audit results from its own synthetic fixtures. Three audit prompts show large refund attempts, denial groups and agent reservation history. Its policy workshop provides a YAML draft, a diff and historical replay results; confirmation downloads the draft without changing the running policy. The local preview labels synthetic data and retains evaluation watermarks. A hosted read-only dashboard at https://spendwall-dashboard.onrender.com displays synthetic refund and audit data from a scheduled writer. It provides statistics, charts and audit history; model queries, the policy workshop, reconciliation and payment or approval actions are unavailable in the hosted deployment.

The separate sandbox proxy has recorded PayPal MCP/SSE connectivity and REST refund evidence. It does not compose the demo's policy and approval pipeline, so this project does not claim an integrated production payment service. The separate opt-in human-approval recording does compose those controls with a sandbox refund adapter; one iPhone approval executed a bound sandbox refund on October 27. The default recorded demo remains synthetic.

How we built it

The core is a TypeScript workspace with a framework-independent YAML/CEL policy package and PostgreSQL-backed audit, velocity and approval modules. The demo exposes scoped MCP tools through the Claude Agent SDK and supplies a synthetic payment adapter. Approval is bound to the request context, and the refund executor preserves execution identity across retries.

The sandbox proxy uses NestJS and the MCP SDK; its documented successful upstream observation used SSE, while refund execution used PayPal REST. React and AG Studio provide the local dashboard. A separate Flutter app implements an approval flow for iOS and Android. An iPhone received a real push, approved with Face ID and observed the bound sandbox refund in the recording flow; additional iOS edge checks have dated evidence. Android approval and physical-device dispute deadline delivery remain unverified.

Codex assisted development, tests, documentation and code review. It was the only AI development tool used. Claude is an application runtime integration, described separately in the AI disclosure below.

Challenges

The main challenge was keeping model intent separate from execution authority. An approval must authorize the specific request, and repeated or concurrent attempts must not silently consume the budget or execute a second refund. Tests exercise denial, approval binding, persisted reservations and retry behavior using synthetic providers.

Another challenge was describing the evidence accurately. In a live Claude rehearsal, the injection fixture did not produce the out-of-ticket tool calls seen in recorded replay. That live observation was a model choice, not proof that the firewall rejected those calls. The recorded fixture separately verifies the denial path and zero synthetic writes.

The PayPal integration also required an explicit transport distinction: the dated sandbox observation succeeded over SSE, while upstream HTTP initialization returned 404. The project preserves that boundary rather than claiming both transports worked.

What's next

Extend sandbox verification beyond the one observed iPhone approval and the one direct-dashboard refund webhook, preserving the existing denial, recovery and retry contracts. Complete Android approval checks, live matched-refund reconciliation, trusted dispute customer integration and physical-device dispute deadline delivery. Extend operational observation beyond the November 3–5, 2026 synthetic dashboard/writer window reviewed in Render and audit records. The demonstration video is complete with English narration and full English closed captions. Extend the verified scenarios while keeping model behavior, synthetic tests and provider execution evidence distinct.

Built with

TypeScript, Node.js, PostgreSQL, YAML, CEL, Model Context Protocol, Claude Agent SDK, NestJS, React, AG Studio, Flutter/Dart and Docker. The separate sandbox tools use PayPal MCP and Orders/Payments REST; the opt-in sandbox recording uses PayPal Payments REST. The default local demo uses synthetic responses. The webhook receiver observed one real direct-dashboard sandbox refund through temporary ingress; persistent hosted ingress and live matched-refund reconciliation remain unverified. Codex is the development assistant; Claude is the optional runtime model integration.

AI tool disclosure

Development: Codex assisted implementation, test development, documentation and review. Codex was the only AI development tool used.

Application runtime: Claude can generate support-agent tool calls, advisory approval summaries, a bounded audit-query intent or a proposed policy draft when explicitly configured. The default demo replays recorded calls, and the dashboard preview uses a labelled synthetic classifier. Claude output does not grant payment authority: deterministic code evaluates policies, the server computes audit queries, and policy confirmation only exports a draft. The live support-agent rehearsal used real Claude responses with synthetic payment responses.

Media: The video uses synthetic English narration generated locally with Kokoro-82M's stock af_heart voice, plus full English closed captions. The video has no background music.

Lessons learned

A model declining an injected request and a firewall rejecting an actual tool call are different observations. The video labels the adversarial sequence as replay and keeps its denial evidence separate from seeded audit examples. Human approval needs the same precision: the approved request must stay bound to the payment facts and execution identity through retries.

Judge access

Source code: AndrewDongminYoo/spendwall. Follow the judge guide for the credential-free local run and its prerequisites. The separate sandbox setup requires private credentials and explicit payment-operation approval; it is not required for the synthetic Quickstart. Demonstration video: Spendwall on YouTube. The video is 2 minutes 43 seconds and includes actual Claude support-agent execution, a live Studio intent query, recorded adversarial tool-call replay, a real push for a synthetic request and the separate original iPhone PayPal sandbox approval. The desktop payment and audit data and the reconciliation observations are synthetic. Browser-only review: open the hosted read-only dashboard and use the read-only token in the private judge testing instructions. All hosted refunds and payment outcomes are synthetic; the dashboard cannot execute payments or approve requests and does not connect to PayPal Sandbox. Render records for November 3 at 06:00 UTC through November 5 at 06:00 UTC show 24 successful scheduled writer batches, matched to 96 audit decisions, and a running dashboard instance without a recorded deployment or restart during that window. This is a dated platform-record observation, not a guarantee of continuous HTTP availability or PayPal connectivity. The complete credential-free local Quickstart and local dashboard evaluation remain available in the judge guide. Evaluation watermarks apply to the separate local preview.

Built With

Share this project:

Updates

Submission history