refund ยท diff
git:20260609.7560e07 to git:20260723.6e5370b
55 added, 130 removed. Audit A to A.
---
name: refund
- description: Govern one refund linked to a sealed original charge receipt, with quote, reservation, approval, settlement evidence, and refund receipt sealing.
+ description: Prepare a sealed-receipt-linked refund handoff under bounded authority without claiming money moved.
runx:
category: payments
---
# Refund
- Govern one refund linked to a sealed original charge receipt.
-
- This skill is the public provider-side refund verb. It quotes refundable bounds
- from the original receipt, reserves refund authority, gates the refund decision,
- settles through one runtime path, and emits evidence for a refund receipt. The
- original receipt link is mandatory; a refund without provenance is not a
- governed refund.
-
- The settlement family is a runtime path, not a separate public skill. Mock, MPP,
- and Stripe refunds share the same authority story: prove the original charge,
- quote the remaining refundable amount, reserve a refund under the same family,
- approve the reversal, settle once under idempotency, and seal the refund
- evidence.
-
- ## What this skill does
-
- 1. **Link the original receipt.** Require `original_receipt_ref` and a redacted
- original receipt summary before any refund authority is discussed.
- 2. **Quote refundable bounds.** Use `refund-quote` to calculate remaining amount,
- currency, settlement family, prior refund refs, and policy window.
- 3. **Reserve refund authority.** Use `refund-reserve` to bind the refund decision
- to the original receipt, selected amount, same settlement family, and
- idempotency key.
- 4. **Gate settlement.** Record the approval decision before any runtime path
- settles the refund.
- 5. **Settle and seal evidence.** Emit closure, proof ref, refund receipt ref,
- redactions, and recovery posture.
-
- It does not silently refund an open dispute, refund across a different
- settlement family, or infer authority from operator intent alone.
-
- ## When to use this skill
-
- - A provider needs to reverse a previously sealed charge.
- - A support or dispute workflow needs a receipt-linked refund artifact.
- - A harness needs to prove refund behavior across mock, MPP, or Stripe runtime
- paths without exposing rail credentials.
-
- ## When not to use this skill
-
- - To answer a chargeback or dispute without deciding a refund. Use
- `dispute-respond`.
- - To refund when the original charge receipt is missing or unsealed.
- - To perform a cross-family refund unless a future policy explicitly models that
- authority. The current graph requires same-family refund semantics.
- - To retry an ambiguous refund under a new idempotency key.
- - To print raw provider credentials, merchant secrets, or unrestricted rail
- tokens into output.
-
- ## Procedure
-
- 1. Validate `original_receipt_ref`, `original_receipt`, `refund_request`, and
- `parent_payment_authority`.
- 2. Confirm the original receipt is sealed and names amount, currency,
- counterparty, settlement family, and charge/refund lineage.
- 3. Run `refund-quote`. Stop when the original receipt, settlement family,
- refundable amount, prior refund set, or policy window is ambiguous.
- 4. Run `refund-reserve`. The reserved refund authority must bind to the original
- receipt and stay within remaining refundable bounds.
- 5. Pause at the refund approval gate. A denied or missing approval prevents
- settlement.
- 6. Settle through the selected runtime path and return refund closure, proof ref,
- refund receipt ref, redaction notes, and recovery posture.
- 7. If settlement is ambiguous, require recovery under the same idempotency key
- before retrying.
+ Prepare one refund against a real, sealed provider charge without losing the
+ lineage that makes a reversal auditable. A refund is not a negative spend and it
+ is not justified by an order id alone: the plan must link the original money
+ movement, provider proof, prior refunds, selected rail, payer, amount, and
+ single-use refund authority.
- ## Runtime paths
+ The current public skill plans only. It does not approve, reserve, execute, or
+ recover a provider refund and always reports `money_moved: false`. A matching
+ provider adapter must perform the reversal and return stable readback before a
+ receipt can say the refund settled.
- | Path | Use when | Required proof/evidence | Secret handling |
- |---|---|---|---|
- | `mock` | Deterministic local refund fixtures. | Mock refund proof ref, original receipt ref, refund idempotency key. | No real credentials; still redact fixture credential material. |
- | `mpp` | The original charge settled through MPP and policy allows refund. | MPP refund proof ref, original receipt ref, idempotency key, settlement family. | Output refs only; do not expose rail session material. |
- | `stripe` | The original charge settled through Stripe and policy allows refund. | Stripe refund proof/refund id when present, original charge receipt ref, idempotency key. | Never emit Stripe secret keys, webhook secrets, card data, PANs, or unrestricted tokens. |
+ ## When to use it
- There is no x402 refund runner in this skill. Current x402 support remains
- buyer-side `spend` unless a separate product decision adds seller-side x402
- refund semantics.
+ Use `refund` after a charge or payment receipt has sealed provider evidence and
+ the caller has a bounded refund `AuthorityTerm`. Use `dispute-respond` for a
+ provider dispute packet and `spend` for a new outbound payment. Do not use a
+ refund to compensate for missing original settlement proof.
- ## Edge cases and stop conditions
+ ## How it works
- - **Missing original receipt:** return `needs_agent`; a refund cannot be
- provenance-free.
- - **Unsealed original receipt:** return `needs_agent`; the reversal must link to
- sealed charge evidence.
- - **Prior refund already covers the amount:** return `denied` or `needs_agent`;
- do not double-refund.
- - **Settlement family mismatch:** return `needs_agent`; same-family is required.
- - **Approval denied or absent:** do not settle.
- - **Ambiguous settlement:** return `escalated` and require recovery under the
- same idempotency key.
- - **Dispute is open:** do not mask it with an untracked refund; route through
- `dispute-respond` or record the dispute linkage explicitly.
+ 1. Resolve the opaque original receipt reference through Runx's configured,
+ proof-verifying receipt store.
+ 2. Verify the original amount, currency, payer, rail, provider proof refs, and
+ money-movement status.
+ 3. Discover and verify every receipt linked to that charge, then account for
+ prior refunds so the request cannot exceed the remaining refundable ceiling.
+ 4. Validate a complete typed, single-use refund authority for the same payer,
+ currency, rail, realm, and operation.
+ 5. Produce the exact adapter handoff and idempotency binding for the selected
+ `mock`, `mpp`, or `stripe` path.
- ## Output schema (`refund_execution`)
+ References and redacted evidence are deliberately separate: the reference
+ finds the receipt, while the verified receipt content proves what may be
+ reversed. Caller-authored booleans such as `verified: true` have no authority.
- ```yaml
- decision: sealed | denied | needs_agent | escalated
- runtime_path: mock | mpp | stripe
- refund_quote_packet:
- refund_quote: object
- refundable_bounds: object
- original_receipt_link: object
- settlement_family: string
- refund_reservation_packet:
- payment_decision: object
- reserved_payment_authority: object
- idempotency: object
- reservation: object
- refund_approval:
- approved: boolean
- gate_id: string
- refund_rail_packet:
- refund_closure: object
- refund_proof: object
- refund_receipt_ref: string | null
- open_questions: [string]
- ```
+ ## Inputs and result
- A `sealed` decision requires the original receipt link, same-family reservation,
- approval, settlement proof, refund receipt ref, and no unresolved recovery
- state.
+ The caller supplies only the opaque original receipt ref, requested amount and
+ reason, selected rail, requested counterparty, and full parent refund
+ authority. Runx resolves the original receipt and refund history itself and
+ derives idempotency from those verified receipts plus the exact authority and
+ request. Caller-supplied receipt bodies, refunded totals, sealing flags, and
+ idempotency seeds are not accepted.
- ## Worked example
+ The result is a provider-refund plan and exact adapter handoff with original
+ receipt binding, remaining ceiling, authority validation, redactions, and
+ `provider_status: not_called`. It is not a settled-refund receipt.
- Receipt `receipt:charge:stripe:paid-search-001` proves a sealed Stripe charge
- for `1.25 USD`. The operator requests a full refund. `refund` quotes remaining
- refundable bounds of `1.25 USD`, reserves refund authority bound to that receipt,
- records approval, settles through the `stripe` runtime path, and emits
- `receipt:refund:stripe:paid-search-001`. The result is `decision: sealed`.
+ ## Stop conditions
- If a prior refund receipt already covers `1.25 USD`, the skill returns
- `decision: denied` or `needs_agent` with the prior receipt refs. It does not
- issue a second refund.
+ - Refuse an unsealed, reference-only, proofless, wrong-payer, wrong-rail, or
+ wrong-currency original charge.
+ - Refuse a refund above the original amount or remaining amount after prior
+ reversals.
+ - Refuse incomplete, expired, wildcard, reference-only, or reusable authority.
+ - Stop on amount, payer, counterparty, rail, operation, or idempotency drift.
+ - Do not expose raw provider credentials or claim money moved without provider
+ execution and readback.
- ## Inputs
+ ## Example
- - `original_receipt_ref` (required): linked sealed charge receipt reference.
- - `original_receipt` (required): redacted original charge receipt summary.
- - `refund_request` (required): requested amount and reason.
- - `parent_payment_authority` (required): parent payment authority term or ref.
- - `approval_context` (optional): prior approval evidence.
- - `idempotency_seed` (optional): stable refund idempotency seed.
+ A sealed Stripe charge proves `5000 AUD` moved and prior refund evidence shows
+ `1000 AUD` already reversed. A bounded authority permits one additional refund
+ to the original payer. The skill may prepare a `2000 AUD` Stripe handoff; it
+ must block `4500 AUD`, a different payer, or a receipt with no settlement proof.
+ The successful plan still says no money moved until the Stripe adapter proves
+ the reversal.