> ## Documentation Index
> Fetch the complete documentation index at: https://docs.algovoi.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Mandate Cancellation Receipt Format

> AlgoVoi authored mandate cancellation receipt format: a closed four element reason enumeration under JCS RFC 8785, with a companion IETF Internet-Draft.

The cancellation receipt records that a recurring-payment mandate (or any standing payer→payee authorisation) has been cancelled, by whom, for what reason, and with what effective date. It closes the lifecycle gap between recurring execution (settlement attestations) and post-cancellation refund (where owed).

It is AlgoVoi-authored, specified in IETF Internet-Draft [`draft-hopley-x402-cancellation-receipt`](https://datatracker.ietf.org/doc/draft-hopley-x402-cancellation-receipt/) (POSTED on IETF datatracker 2026-05-25, Independent Submission, Informational), and published as a standalone reference implementation:

* Python: `algovoi-cancellation-receipt` (live on PyPI, v0.1.1)

Both packages depend on [`algovoi-substrate`](https://pypi.org/project/algovoi-substrate/) / [`@algovoi/substrate`](https://www.npmjs.com/package/@algovoi/substrate) for the JCS canonicalisation primitive. Apache 2.0.

## Lifecycle position

```
admission       settlement       cancellation     refund (if owed)
compliance  --> settlement   --> cancellation --> refund
receipt         attestation      receipt          receipt
```

All four formats anchor to the same canonicalisation discipline ([`urn:x402:canonicalisation:jcs-rfc8785-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/)). A verifier walking the audit chain confirms admission → recurring execution → termination → (optional) refund under one byte-deterministic pin.

## Why a four-state enumeration

Mandate termination is genuinely four-state. The regulatorily-load-bearing distinctions are:

* **Payer revocation** under PSD2 (Directive 2015/2366) Article 64 + UK Consumer Rights Act 2015 — MAY trigger refund obligations on debits already settled prior to the effective date.
* **Payee termination** under PSD2 Article 72 + contractual terms — does NOT trigger consumer-revocation refund-window obligations on already-settled debits.
* **Operator/compliance-forced termination** (sanctions, KYC, AML, court order) — anchors POCA s.330 / AML 5+6 evidence chain back to the originating compliance event.
* **Time-based expiry** — mandate's own terms terminated it. Standard record-keeping only.

A collapse to three-state (e.g. `PARTY_REQUESTED + AUTO_TERMINATED`) loses the payer-vs-payee distinction that drives the PSD2 Article 64 refund-window obligation.

## Receipt shape

A cancellation receipt is a seven-field JSON object canonicalised under RFC 8785 (JCS). Field names are sorted lexicographically by JCS during canonicalisation.

```json theme={null}
{
  "canon_version": "jcs-rfc8785-v1",
  "cancellation_provider_did": "did:web:api.algovoi.co.uk",
  "cancellation_reason": "USER_REQUESTED",
  "cancellation_timestamp_ms": 1716494400000,
  "effective_from_ms": 1716537600000,
  "jurisdiction_flags": ["UK", "EU"],
  "mandate_ref": "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f"
}
```

| Field                       | Type                 | Description                                                                                |
| --------------------------- | -------------------- | ------------------------------------------------------------------------------------------ |
| `canon_version`             | string               | In-band canonicalisation pin. Fixed `jcs-rfc8785-v1`.                                      |
| `cancellation_provider_did` | string               | DID URI of the issuing party.                                                              |
| `cancellation_reason`       | string (closed enum) | `USER_REQUESTED` / `MERCHANT_REQUESTED` / `COMPLIANCE_TERMINATED` / `EXPIRED`.             |
| `cancellation_timestamp_ms` | integer              | Epoch ms when the cancellation event was recorded. **Substrate Rule 2**.                   |
| `effective_from_ms`         | integer              | Epoch ms when the cancellation takes legal effect. MUST be `>= cancellation_timestamp_ms`. |
| `jurisdiction_flags`        | ordered array        | ISO-3166-1 codes. Order significant under RFC 8785.                                        |
| `mandate_ref`               | string               | `sha256:{hex}` reference to mandate setup record.                                          |

## The closed enumeration: `cancellation_reason`

| Value                   | Initiator         | Regulatory significance                                                                                                                            |
| ----------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `USER_REQUESTED`        | Payer             | PSD2 Article 64 right of revocation. UK Consumer Rights Act 2015. May trigger refund obligation under Article 64 if recent debits already settled. |
| `MERCHANT_REQUESTED`    | Payee             | PSD2 Article 72 + contractual terms. Does NOT trigger consumer-revocation refund-window obligations.                                               |
| `COMPLIANCE_TERMINATED` | Operator          | Sanctions / KYC / AML / court order. Triggers POCA s.330 / AML 5+6 evidence chain.                                                                 |
| `EXPIRED`               | None (time-based) | Mandate's own end-state. Standard record-keeping only.                                                                                             |

Each value produces a byte-distinct `content_hash`. Free-form "reason" strings or operator-internal codes are not acceptable substitutes.

## Two timestamps

The cancellation receipt records two epoch-millisecond integer timestamps independently:

* `cancellation_timestamp_ms` — when the cancellation event was observed and recorded by the issuing provider.
* `effective_from_ms` — when the cancellation takes legal effect.

For most cancellations these are equal. For PSD2 Article 64(3)(a) direct-debit revocations, the effective time is typically end-of-business-day prior to the next scheduled execution — distinct from the moment the revocation was recorded. The independent encoding supports that operational separation.

The format pins the invariant `effective_from_ms >= cancellation_timestamp_ms`. Implementations MUST reject receipts where the effective time precedes the recording time.

## Composition

A cancellation receipt `mandate_ref` MAY reference a compliance receipt `content_hash` (the receipt that admitted the mandate). A USER\_REQUESTED cancellation may chain forward to a refund receipt if PSD2 Article 64 refund is owed on a recently-settled debit:

```
compliance receipt (ALLOW for mandate setup)
    |
    v   (settled_payment_ref or operator-layer link)
settlement attestation (recurring execution N)
    |
    v   (chain via prev_hash)
cancellation receipt (USER_REQUESTED, effective T+1 day)
    |
    v   (original_payment_ref references settlement)
refund receipt (FULL, if Article 64 refund owed)
```

A verifier walking this chain confirms the full mandate lifecycle under one canonicalisation pin.

## Conformance vectors

8 byte-level reference vectors + 7 pair invariants + 3 chain invariants at [`vectors/cancellation_receipt_v1/`](https://github.com/chopmob-cloud/algovoi-jcs-conformance-vectors/tree/main/vectors/cancellation_receipt_v1).

The vector set pins:

1. Closed four-element `cancellation_reason` enumeration — four byte-distinct `content_hash` values.
2. `jurisdiction_flags` array order (RFC 8785 §3.2.3).
3. `canon_version` in-band pin.
4. `effective_from_ms >= cancellation_timestamp_ms` invariant.
5. `mandate_ref` content-addressing (`sha256:` prefix retained in canonical bytes).
6. Audit chain row linkage via `prev_hash`.

## Quick start

### TypeScript

```typescript theme={null}
import { buildCancellationReceipt } from "@algovoi/cancellation-receipt";
import { sha256Jcs } from "@algovoi/substrate";

const r = buildCancellationReceipt({
  cancellation_reason: "USER_REQUESTED",
  cancellation_timestamp_ms: 1716494400000,
  effective_from_ms: 1716537600000,
  cancellation_provider_did: "did:web:api.algovoi.co.uk",
  mandate_ref:
    "sha256:0dd5d0b76c9b9281fdeb2509ad38ab132b16a17385ca01d976ff9e6e12563a0f",
  jurisdiction_flags: ["UK", "EU"],
});
console.log(sha256Jcs(r));
// e50f8d4f9fcd8b0cf142bd65528a90d8814dd71127d4529ca77137b4b41ad407
```

## What this is NOT

* **Not a refund receipt.** Cancellation records the termination of a mandate; refund records the reversal of a settled payment. When a USER\_REQUESTED cancellation triggers a refund, both receipts are emitted and chained via the audit-chain.
* **Not a dispute receipt.** Disputes are state machines over multiple parties; cancellation is a single state transition.
* **Not an attestation of mandate validity.** The receipt records the termination of a previously-valid mandate; the mandate itself is specified elsewhere.

## Companion IETF Internet-Draft

[`draft-hopley-x402-cancellation-receipt`](https://datatracker.ietf.org/doc/draft-hopley-x402-cancellation-receipt/) (Independent Submission, Informational). AlgoVoi-authored. Normatively references [`draft-hopley-x402-canonicalisation-jcs-v1`](https://datatracker.ietf.org/doc/draft-hopley-x402-canonicalisation-jcs-v1/). Welcomes downstream-adopter contributions per the established Appendix C "Known Adopters" pattern.

## See also

* [Canonicalisation substrate](/canonicalisation-substrate) — the JCS discipline
* [Settlement attestation](/settlement-attestation) — recurring-execution counterpart
* [Refund receipt](/refund-receipt) — post-cancellation refund counterpart
* [Conformance vectors](/conformance-vectors) — full vector corpus
* [Substrate authorship and provenance](/substrate-authorship-provenance) — citable AlgoVoi authorship record
