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 constrains subsequent SignedPaymentAuthorization (SPA) artifacts.
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 constrains subsequent SignedPaymentAuthorizations (SPAs).
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) |
| 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 — the same denomination as SPA.amount. The session authority converts the fiat budget to on-chain units at SBA issuance time. |
| allowedRails | Rail[] | yes | Permitted payment rails (xrpl, evm, stripe, hosted) |
| 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 (SPAs) 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"withscopeId= session identifierbudgetScope: "VEHICLE"withscopeId= vehicle identifierbudgetScope: "FLEET"withscopeId= fleet identifier
Stateless Verification Model
MPCP verifiers are stateless. They do not track cumulative spending across payments.
This ensures that MPCP verification is deployable across independent, parallel, or ephemeral verifier instances without shared state.
Budget enforcement is split between two roles:
| Role | Responsibility |
|---|---|
| Session authority | Tracks cumulative spending per scope. Only issues SPAs within the remaining authorized envelope for the scope. |
| Verifier | Checks that the current SPA amount does not exceed maxAmountMinor. Does not track prior payments. |
The verifier's stateless check is:
SPA.amount ≤ SBA.maxAmountMinor
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.
This confirms the current payment fits within the authorized envelope. The session authority's signature on each SPA is the cryptographic attestation that cumulative spending remains within bounds — the verifier trusts this by validating the signature.
Verifiers MUST NOT attempt to track or reconstruct cumulative session spending.
Cumulative Enforcement
To enable accurate cumulative budget enforcement within a session, callers MAY pass the running total of prior spending to the verifier via cumulativeSpentMinor.
When provided, the verifier applies:
cumulativeSpentMinor + currentPayment <= maxAmountMinor
instead of the bare single-payment check. This allows a stateless verifier to correctly reject payments that would exceed the cumulative budget even if each individual payment would fit.
Session authority responsibility:
- MUST track cumulative spending per scope (SESSION, DAY, VEHICLE, FLEET)
- MUST pass cumulativeSpentMinor to the verifier for correct enforcement
- MUST NOT issue new SPAs 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:
- Resolve the public key (as JWK) using one of the following, in order of precedence:
- Trust Bundle — if
trustBundlesare provided, look upissuerin the bundle'sissuerslist and retrieve the JWK byissuerKeyId. This path works fully offline. - Pre-configured key — if
MPCP_SBA_SIGNING_PUBLIC_KEY_PEMis set (or equivalent), use it directly. - HTTPS well-known — fetch
https://{issuerDomain}/.well-known/mpcp-keys.jsonand look up byissuerKeyId.
Then validate the signature over SHA256("MPCP:SBA: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
Relationship to Pipeline
PolicyGrant
↓
SignedBudgetAuthorization (SBA)
↓
SignedPaymentAuthorization (SPA)
↓
Settlement
See Also
- MPCP Reference Flow — EV Charging — Demonstrates how SBA is used during runtime authorization.