Skip to main content

FPSF-CPP-001 — CashPack Protocol

Document Metadata

FieldValue
Spec IDFPSF-CPP-001
TitleCashPack Protocol
Version1.0.0
StatusDraft
Date2026-03-25
AuthorAdalton Reis — reis@fabricpaymentstandards.org
OrganizationFabric Payment Standards Foundation
Contactspecs@fabricpaymentstandards.org>
LicenseApache-2.0
AdoptsFPSF-CPD-001 v1.0.0

Scope

This document specifies the CashPack Protocol (CPP-1.0): a standard for issuing, transferring, and redeeming signed bearer instruments over any settlement infrastructure. It defines:

  • All data structures and their fields
  • Cryptographic algorithms and requirements
  • Protocol obligations for conforming Operators at issuance, renewal, and redemption
  • The relationship between the CashPack instrument and the FPSF-CPD-001 Payment model
  • Versioning and extension rules
  • Normative references

Out of scope: key management architectures (see FPSF-MPC-001), banking system integration, currency exchange, inter-Operator settlement (Phase 2), and any distributed consensus mechanism.


1. Normative Language

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL are to be interpreted as described in RFC 2119.


2. Relationship to FPSF-CPD-001

This specification adopts the Canonical Payment Definition (FPSF-CPD-001 v1.0.0) as its foundational payment model. The CashPack instrument represents a specialized Digital Payment in which:

  • The Payer is the Principal who locks funds at issuance
  • The Payee is the final bearer who redeems the instrument
  • The Value is the locked amount and currency
  • The AuthorizationProof is the cryptographic signature chain embedded in the instrument's renewal_chain and at each operation
  • The PaymentState lifecycle maps as follows:
CPD-001 StateCashPack Equivalent
CREATEDLock Request submitted; instrument not yet issued
AUTHORIZEDOperator issues signed instrument (status: ACTIVE)
IN_FLIGHTInstrument in transit between bearers (renewal in progress)
SETTLEDInstrument redeemed (status: REDEEMED)
FAILEDInstrument expired (status: EXPIRED)
CANCELLEDInstrument cancelled by Operator (status: CANCELLED)

All CPD-001 invariants (uniqueness, integrity, authorization binding, deterministic state, finality) MUST be preserved by conformant Operators.


3. Cryptographic Requirements

PrimitiveRequirement
Asymmetric signingEd25519 REQUIRED. ECDSA P-256 OPTIONAL for implementations with HSM constraints.
Hash functionSHA-256 for all chain digest computation.
Key encodingBase64url (RFC 4648 §5), no padding.
Signature encodingBase64url, no padding.
Canonical JSONRFC 8785 (JCS) MUST be applied to all JSON objects before signing.
Timestamp formatISO 8601 / RFC 3339, UTC. Example: 2026-03-25T14:30:00Z.

3.1 Chain Digest Computation

chain_digest[0] = SHA256(canonical_json(lock_request))
chain_digest[n] = SHA256(chain_digest[n-1] || canonical_json(renewal_entry[n]))

|| denotes concatenation of raw bytes.

3.2 Disposable Key Pairs

Bearer keys SHOULD be disposable — generated for a single instrument and discarded after the instrument is renewed or redeemed. The FPSF-MPC-001 system is the RECOMMENDED mechanism for generating disposable bearer keys in high-privacy deployments.


4. Data Structures

4.1 Lock Request

Constructed by the Principal. Signed with the Principal's private key. Submitted to the Issuance endpoint.

FieldTypeDescription
versionstringMUST be "CPP-1.0".
request_idstring (UUIDv4)Unique ID generated by the Principal.
timestampstring (RFC 3339)Creation time.
operator_idstringUnique identifier of the target Operator.
principal_pkstring (Base64url)Principal's public key.
initial_bearer_pkstring (Base64url)Public key of the intended first bearer.
amountintegerAmount in smallest currency unit (e.g., cents).
currencystring (ISO 4217)e.g., "USD", "EUR", "BRL".
expirystring (RFC 3339)Expiry set by Operator policy.
memo_hashstring (hex, optional)SHA-256 of a private memo. Not stored in plaintext.
principal_signaturestring (Base64url)Ed25519 signature over canonical JSON of all fields above.

4.2 CashPack Instrument

Constructed by the Operator at issuance. Operator-signed. Updated at each renewal.

FieldTypeDescription
versionstringMUST be "CPP-1.0".
pack_idstring (UUIDv4)Globally unique. Assigned by Operator at issuance.
operator_idstringIssuing Operator identifier.
amountintegerLocked amount. Immutable after issuance.
currencystring (ISO 4217)Currency. Immutable after issuance.
issued_atstring (RFC 3339)Operator's issuance timestamp.
expirystring (RFC 3339)Expiry datetime.
statusstring (enum)ACTIVE, REDEEMED, EXPIRED, or CANCELLED.
current_bearer_pkstring (Base64url)Public key of the current authorized bearer.
lock_requestobjectFull original Lock Request object.
renewal_chainarrayOrdered array of Renewal Entry objects. Empty at issuance.
chain_digeststring (hex)Current chain digest.
operator_signaturestring (Base64url)Operator signature over canonical JSON of all above fields (excluding this field).

4.3 Renewal Entry

Constructed by the outgoing bearer. Counter-signed by the Operator. Appended to renewal_chain.

FieldTypeDescription
renewal_idstring (UUIDv4)Unique ID for this renewal.
timestampstring (RFC 3339)Renewal request time.
outgoing_bearer_pkstring (Base64url)Current bearer's public key. MUST match current_bearer_pk.
incoming_bearer_pkstring (Base64url)New bearer's public key.
prev_chain_digeststring (hex)Chain digest before this renewal.
outgoing_bearer_signaturestring (Base64url)Signature over canonical JSON of all above fields.
operator_renewal_signaturestring (Base64url)Operator countersignature over canonical JSON of all fields including bearer signature.

4.4 Redemption Request

Constructed by the current bearer. Signed with the redeemer's private key.

FieldTypeDescription
pack_idstring (UUIDv4)Instrument being redeemed.
timestampstring (RFC 3339)Request time.
redeemer_pkstring (Base64url)Redeemer's public key. MUST match current_bearer_pk.
destinationobjectOperator-defined payout destination schema.
redeemer_signaturestring (Base64url)Signature over canonical JSON of all above fields.

5. Protocol Obligations

5.1 Issuance

  1. Operator MUST authenticate the Principal (account holder verification).
  2. Operator MUST verify principal_signature on the Lock Request.
  3. Operator MUST verify available balance ≥ amount.
  4. Operator MUST verify amount ≤ Operator's configured maximum.
  5. Operator MUST lock the amount before issuing the instrument.
  6. Operator MUST set current_bearer_pk = initial_bearer_pk from the Lock Request.
  7. Operator MUST compute chain_digest[0] = SHA256(canonical_json(lock_request)).
  8. Operator MUST sign the full instrument and return it to the Principal.

5.2 Renewal

  1. Operator MUST verify its own prior operator_signature on the submitted instrument.
  2. Operator MUST verify instrument status = ACTIVE and expiry has not passed.
  3. Operator MUST verify outgoing_bearer_pk = current_bearer_pk.
  4. Operator MUST verify outgoing_bearer_signature on the Renewal Entry.
  5. Operator MUST verify prev_chain_digest matches the instrument's current chain_digest.
  6. Operator MUST verify renewal chain depth has not exceeded its configured maximum.
  7. Operator MUST update current_bearer_pk = incoming_bearer_pk.
  8. Operator MUST compute the new chain_digest and re-sign the updated instrument.
  9. Operator MUST record the renewal_id and MUST reject duplicate renewal_id values (replay prevention).

5.3 Redemption

  1. Operator MUST verify the full instrument signature chain.
  2. Operator MUST verify redeemer_pk = current_bearer_pk.
  3. Operator MUST verify redeemer_signature on the Redemption Request.
  4. Operator MUST verify instrument status = ACTIVE and not expired.
  5. Operator MUST verify the redeemer's identity per its compliance policy.
  6. Operator MUST mark the instrument REDEEMED before releasing funds.
  7. Operator MUST release locked funds to the specified destination.

6. Instrument Status Values

StatusTerminalDescription
ACTIVENoInstrument is valid; may be renewed or redeemed.
REDEEMEDYesRedeemed; funds released.
EXPIREDYesReached expiry without redemption; funds returned to Principal.
CANCELLEDYesCancelled by Operator (typically in response to a legal order); funds held.

7. Mandatory API Endpoints

EndpointDescription
POST /v1/cashpack/issueSubmit a Lock Request. Returns a signed instrument on success.
POST /v1/cashpack/renewSubmit an instrument plus a Renewal Entry. Returns updated signed instrument.
POST /v1/cashpack/redeemSubmit a Redemption Request plus the instrument. Returns Redemption Confirmation.
GET /v1/cashpack/{pack_id}/statusQuery instrument status. Restricted to issuing Principal and Operator.

8. Transport Requirements

  • All endpoints MUST be served over TLS 1.3 or higher.
  • Content-Type: application/json on all requests and responses.
  • The issue and status endpoints MUST require authenticated sessions.
  • The renew and redeem endpoints accept unauthenticated sessions; bearer authorization is derived from cryptographic signature verification.

9. Well-Known Resources

URLPurpose
/.well-known/cashpack-policy.jsonOperator Policy Document (see Governance layer).
/.well-known/cashpack-pubkey.jsonOperator's current public signing key in JWK format (RFC 7517).

10. Versioning and Extensions

The version field is set to "CPP-1.0" for this specification.

  • Future versions increment the minor version for backward-compatible additions.
  • Future versions increment the major version for breaking changes.
  • Operators MUST reject instruments with unrecognized major versions.
  • Extensions MAY be added in an extensions object within any structure and MUST be ignored by non-recognizing implementations.

11. Error Codes

Error CodeMeaning
INSUFFICIENT_BALANCEPrincipal's available balance is less than the requested amount.
AMOUNT_EXCEEDS_LIMITAmount exceeds the Operator's configured maximum.
INVALID_SIGNATUREOne or more signatures failed verification.
BEARER_MISMATCHSubmitting public key does not match current_bearer_pk.
CHAIN_DIGEST_MISMATCHprev_chain_digest does not match the instrument's current chain_digest.
INSTRUMENT_NOT_ACTIVEInstrument status is REDEEMED, EXPIRED, or CANCELLED.
CHAIN_DEPTH_EXCEEDEDrenewal_chain has reached the Operator's configured maximum depth.
REDEEMER_NOT_IDENTIFIEDRedeemer could not be verified to the required identity level.
DUPLICATE_IDrequest_id or renewal_id has been seen before (replay prevention).
EXPIRY_INVALIDRequested expiry is outside the Operator's permitted range.

12. Conformance

A conformant Operator implementation MUST:

  • Accept and process Lock Requests per Section 5.1
  • Accept and process Renewal Entries per Section 5.2
  • Accept and process Redemption Requests per Section 5.3
  • Enforce all cryptographic requirements of Section 3
  • Expose all mandatory API endpoints of Section 7
  • Publish a Policy Document at the well-known URL defined in Section 9
  • Preserve all CPD-001 invariants as mapped in Section 2

Normative References

ReferenceDescription
FPSF-CPD-001 v1.0.0Canonical Payment Definition
RFC 2119Key words for use in RFCs to Indicate Requirement Levels
RFC 3339Date and Time on the Internet: Timestamps
RFC 4648The Base16, Base32, and Base64 Data Encodings
RFC 7517JSON Web Key (JWK)
RFC 8032Edwards-Curve Digital Signature Algorithm (EdDSA)
RFC 8785JSON Canonicalization Scheme (JCS)
ISO 4217Currency Codes
FIPS 180-4Secure Hash Standard (SHA-2 family)

FPSF-CPP-001 v1.0.0 · Draft · Fabric Payment Standards Foundation · Apache-2.0