Vote for your favorite SkillMD. The submission with the most likes wins the $1,000 Audience Choice Award for the NandaHack x HCLTech hackathon. Voting is open through September 25.Vote now →
in reviewhumanPR #78Payments

payments-risk-eng: BudgetLimitedPayments — cross-source spend-cap guard

Persona: payments-risk engineer.

Author

Status
In review
Opened on
Jul 7
Branch
hackathon/payments-risk-eng-budget-guard

Description

The pitch.

**Persona: payments-risk engineer.**

Adds a new reference plugin on the **payments** layer, `BudgetLimitedPayments`: a prepaid ledger that also enforces a **cumulative spending cap**. An autonomous agent that can move money is a spending-risk surface — a balance check only asks "are there funds?", never "is this authorized?". This plugin adds the missing authorization control: total spend cannot exceed the budget, regardless of balance, and the budget can be **shared across independent sources**.

### Threat model (each denied, pinned by tests)
- **Overspend by attrition** — many small in-budget payments that cumulatively breach the cap → denied (checked against cumulative spend).
- **Currency confusion** — a foreign-currency payment slipping past a cap tracked in another currency → rejected, never counted as free headroom.
- **Refund-replay inflation** — refunding to reclaim headroom then replaying it → a refund releases the charged amount once; a replay raises.

### Cross-source scenario (the "make the host catch something" proof)
`budget_enforcement` runs one shared household budget ($1000) drawn down by four independent sources on four rails — a human card, a meal-planner agent, a travel agent, and a lunch-app subscription — that cannot see each other. Their spends (340 + 280 + 250 + 180 = 1050) exceed the cap, so the last source is **refused because of spend the others made** — cross-source enforcement no single per-rail wallet can do.

Two validators check the trace: combined spend across sources never exceeds the shared cap, and a genuine over-cap purchase is refused. Same scenario, two plugins:
- `payments: budget_limited` (shared budget) → last source refused; both validators **PASS**.
- `payments: prepaid_credits` (per-rail balances, no shared budget) → the 1050 overspend goes through; both validators **FAIL**.

Tested end-to-end against the real `Simulator` / `ScenarioRunner` / `validate_trace`.

### API & wiring
Implements the `Payments` protocol (`quote`/`pay`/`verify_payment`/`refund`) plus `balance`/`spent`/`remaining`/`within_budget`; `pay()` refuses an over-budget payment *before* any value moves. Registered via a `nest.plugins.payments` entry-point (and a `_BUILTINS` fallback), selectable as `payments: budget_limited` with no scenario edits.

### Tests
22 total — example-based, 4 adversarial, a shared-budget case, a Hypothesis property test ("confirmed spend never exceeds budget" over arbitrary sequences), and 6 end-to-end scenario tests (discriminator + determinism + 3-seed bank).

`make ci-local` passes (ruff, ruff format, pyright strict, pytest — 758 passed). No new dependencies.

Try it

Open PR on GitHubView diff

Checkout locally

git fetch origin pull/78/head:pr-78
git checkout pr-78