Skip to content

SignedBudgetAuthorization (SBA)

Artifact Type: MPCP:SBA

Part of the Machine Payment Control Protocol (MPCP).

Purpose

The SignedBudgetAuthorization (SBA) defines a signed spending envelope for a machine payment scope.

It is a protocol-level MPCP artifact that defines the spending envelope the Trust Gateway enforces for a session.

Unlike application-specific budget concepts, SBA is generic and may be used across parking, charging, tolling, robotics, AI agents, and other machine-payment environments.

The SignedBudgetAuthorization (SBA) establishes the maximum spending envelope available to a machine for a defined payment scope.

It is issued after a PolicyGrant and presented to the Trust Gateway, which verifies the SBA signature and enforces the budget ceiling before submitting each XRPL payment.


Policy linkage fields

grantId and policyHash are the canonical linkage from an SBA to its PolicyGrant. They are the only PolicyGrant-origin fields required inside the SBA payload for binding to PA policy.

Deployments using gateway-only PolicyGrant presentation send the full PolicyGrant only to the Trust Gateway; merchants receive the SBA (which includes grantId and policyHash) without a copy of the grant. See Verification — Verification contexts.


Structure

BudgetAuthorization (inner payload)

Field Type Required Description
version string yes MPCP semantic version (e.g. "1.0")
budgetId string yes Unique identifier for this budget
grantId string yes References the PolicyGrant.grantId from which this budget was derived. Verifiers use this to resolve the grant and confirm policy chain linkage.
sessionId string yes Session this budget applies to
actorId string yes Actor identifier (vehicle, agent, robot, or any autonomous payment actor). When the PolicyGrant uses XRPL credential-based subject attestation (subjectCredentialIssuer / subjectCredentialType), actorId MUST be the agent's XRPL classic address (r...) — the same account that holds the on-chain credential — so verifiers can bind the SBA to the attested subject. See PolicyGrant — Subject Attestation.
scopeId string no Optional scope identifier
policyHash string yes SHA-256 hash of the canonical policy document under which this budget was authorized. Computed as SHA256("MPCP:Policy:<version>:" \|\| canonicalJson(policyDocument)).
currency string yes Informational: the fiat reference currency from which this budget was derived (e.g. "USD"). Not used in verification arithmetic.
minorUnit number yes Informational: decimal scale of the fiat reference currency (e.g. 2 for USD cents). Not used in verification arithmetic.
budgetScope string yes SESSION | DAY | VEHICLE | FLEET | TRIP
maxAmountMinor string yes Maximum authorized spend expressed in the on-chain asset's atomic units (e.g. drops for XRP). The session authority converts the fiat budget to on-chain units at SBA issuance time.
allowedRails Rail[] yes Conforming SBAs: MUST be exactly ["xrpl"]. Must match the PolicyGrant rail set.
allowedAssets Asset[] yes Permitted assets
destinationAllowlist string[] no Optional allowed destination addresses
expiresAt string yes ISO 8601 expiration timestamp

SignedBudgetAuthorization (envelope)

Field Type Required Description
authorization BudgetAuthorization yes The budget payload
issuer string conditional Identifier for the signing entity (e.g. DID, domain, or vehicle:id.fleet.example). Required when the verifier uses Trust Bundle key resolution. Optional when the verifier resolves the key via MPCP_SBA_SIGNING_PUBLIC_KEY_PEM or HTTPS well-known.
issuerKeyId string yes Identifies the specific key used to sign (alias: keyId retained for backward compatibility)
signature string yes Base64-encoded signature over SHA256("MPCP:SBA:1.0:"

Scope Model

SBA supports multiple budget scopes. All scopes are cumulative — maxAmountMinor represents the total authorized spending across all payments within the scope, regardless of how many individual payments are made.

Scope Meaning
SESSION Budget applies to a single session
DAY Budget applies across sessions for a calendar day
VEHICLE Budget applies across sessions for a specific vehicle
FLEET Budget applies across vehicles within a fleet authority
TRIP Budget applies across sessions for a single multi-day trip or project (human-to-agent delegation)

When present, scopeId identifies the entity the budget applies to.

Examples:

  • budgetScope: "SESSION" with scopeId = session identifier
  • budgetScope: "VEHICLE" with scopeId = vehicle identifier
  • budgetScope: "FLEET" with scopeId = fleet identifier

Budget and verification roles

Budget enforcement is split between roles. Merchant verifiers (offline acceptance) are stateless per payment. The Trust Gateway is not stateless for the PA-signed budgetMinor ceiling — it MUST maintain durable cumulative spend state and velocity counters (see Trust Model — Gateway durable spend state and PolicyGrant — Velocity limit enforcement).

Role Responsibility
Session authority (agent) Tracks cumulative spending per scope. Presents SBAs within the remaining authorized envelope (maxAmountMinor).
Trust Gateway Enforces PA-signed budgetMinor, authorizedGateway, velocityLimit, and optional gateway credentials; persists spend state across restarts.
Merchant verifier Checks that the SBA maxAmountMinor does not exceed the PA-signed offlineMaxSinglePayment cap (offline mode only).

Per-payment check at the gateway (in addition to durable budgetMinor tally):

currentPayment ≤ remainingAuthorizedEnvelope (from SBA and grant constraints)

Both values are in the on-chain asset's atomic units — the comparison is a direct numeric check with no currency conversion required. The session authority is responsible for converting the fiat budget into on-chain units at SBA issuance time, using the exchange rate and asset precision applicable at that moment.

Cumulative enforcement (session authority)

To align session-level totals with the gateway, callers MAY pass the running total of prior spending via cumulativeSpentMinor when invoking verifier helpers.

When provided, a stateless helper may apply:

cumulativeSpentMinor + currentPayment <= maxAmountMinor

instead of the bare single-payment check. This does not replace the gateway's durable budgetMinor enforcement.

Session authority responsibility: - MUST track cumulative spending per scope (SESSION, DAY, VEHICLE, FLEET) - MAY pass cumulativeSpentMinor to verifier helpers for local checks - MUST NOT present SBAs when cumulative spending would exceed maxAmountMinor

Offline trust assumption: In offline or air-gapped environments (e.g., vehicles without real-time connectivity), cumulative enforcement relies on the session authority (typically the vehicle wallet) maintaining the spending counter in trusted local storage. The verifier cannot independently verify the counter's accuracy in offline mode; this is an accepted trust assumption for offline deployments.

Example

{
  "authorization": {
    "version": "1.0",
    "budgetId": "550e8400-e29b-41d4-a716-446655440000",
    "grantId": "grant_abc123",
    "sessionId": "sess_456",
    "actorId": "ev-847",
    "policyHash": "a1b2c3...",
    "currency": "USD",
    "minorUnit": 2,
    "budgetScope": "SESSION",
    "maxAmountMinor": "30000000",
    "allowedRails": ["xrpl"],
    "allowedAssets": [{ "kind": "IOU", "currency": "USDC", "issuer": "rIssuer..." }],
    "destinationAllowlist": ["rDest..."],
    "expiresAt": "2026-03-08T14:00:00Z"
  },
  "issuer": "did:web:fleet.example.com",
  "issuerKeyId": "budget-auth-key-1",
  "signature": "base64..."
}

Verification

All MPCP signatures MUST use domain-separated hashing before signing.

For SBA artifacts the domain prefix is:

MPCP:SBA:<version>:

Example hash computation:

hash = SHA256("MPCP:SBA:1.0:" || canonicalJson(authorization))

This prevents cross-protocol and cross-artifact hash collisions and ensures compatibility with MPCP verifier implementations.

A verifier MUST:

  1. Resolve the public key (as JWK) using one of the following, in order of precedence:
  2. Trust Bundle — if trustBundles are provided, look up issuer in the bundle's issuers list and retrieve the JWK by issuerKeyId. This path works fully offline.
  3. Pre-configured key — if MPCP_SBA_SIGNING_PUBLIC_KEY_PEM is set (or equivalent), use it directly.
  4. HTTPS well-known — fetch https://{issuerDomain}/.well-known/mpcp-keys.json and look up by issuerKeyId.

Then validate the signature over SHA256("MPCP:SBA::" || canonicalJson(authorization)). 2. Check expiresAt has not passed 3. When verifying against a payment decision or settlement context: ensure sessionId, policyHash, budgetScope, allowedRails, allowedAssets, optional destination constraints, and amount constraints match — except in SBA-only merchant context, where PolicyGrant subset checks are skipped because the grant is not available.


Relationship to Pipeline

PolicyGrant
    ↓
SignedBudgetAuthorization (SBA)
    ↓
Trust Gateway (verifies SBA + enforces budgetMinor ceiling)
    ↓
XRPL Settlement + Receipt

See Also