1.2.0-rc.1 / Payment profiles

Paid agreements

Compose assent, payer mandates, verified payment assertions and protected delivery.

This 1.2.0-draft.3 profile is included in the implementation candidate. It joins an accepted fixed quote, separately authenticated payer mandate, read-only provider verification and protected gateway access. It introduces no required commercial provider and no debit API.

The implementation is PaidAgreementService in profiles/paid_service.py, with explicit contracts in paid_contracts.py and paid-agreement.schema.json. The same neutral token, introspection, reporting and revocation shapes are shared with the free service. Paid offer/receipt/status shapes remain distinct. No module changes the legacy global protocol version or signature-type registry.

Assent, spending authority and access

The paid exchange uses the ordinary five-field binding protocol_version, origin, service_id, issuer, delegation_id. These values distinguish the originator, appointed agreement service and its operator. The payment verifier has its own origin-appointed service, issuer, endpoint, key and delegation.

  1. An authenticated agent requests an offer, adding an explicit payer_id to the free offer-request shape. The trusted service quote factory produces exact fixed-quote bytes. The offered payment is exactly {required:true, quote_digest, quote_url}. The quote binds the offer, payer, origin and service; resource licence and provider service fees remain separate items. Its positive total is the exact sum of bounded decimal-string minor-unit amounts. An explicit zero resource price with a positive provider fee is supported. An entirely zero-price agreement uses the free profile and requires no payer or verifier.
  2. The agent obtains and checks the exact quote and other pinned contexts, then signs the ordinary acceptance binding the exact offer digest. Assent consumes that offer once. The signed paid receipt records state_at_issue:"pending_payment", payment_required:true and access_credential:false. Receipt windows must equal the accepted durations; issuance and assent must fit the offer interval. A receipt grants neither payment authority nor bearer access.
  3. A separately provisioned payer submits a signed payment.mandate authorizing the exact quote once. Authentication uses a payer credential and a pinned payer public key, separate from the agent credential/key. An agent’s assent or credential cannot act as a payer mandate. The signature role is explicitly odexa-payment-mandate+jws. The receipt, quote, amount, currency, payees, payer and provider bindings are verified before retention.
  4. A read-only provider check authenticates current origin appointment before transmission and after the reply. A signed assertion must bind the pending check, accepted request, agreement, quote and mandate, with exact amount/currency/payer and a monotonic provider sequence. The local service records the provider’s financial assertion; it does not independently prove settlement at a bank.
  5. Only a confirmed assertion and otherwise valid agreement/policy permit a token. Token issuance, introspection and active-status refresh obtain a new provider check while access is nonterminal. Pending or failed payment denies access. The publisher gateway uses its separate scoped credential for introspection before protected delivery. A reversal makes access terminally revoked; an expired or revoked agreement cannot be revived by a later confirmation or historical replay.

An explicit new payment check can retain a late financial confirmation while access remains expired. Exact historical receipt/assent retries retain their original bytes during origin outage and create no grant. A prior check replay still requires current verifier authority and an exact matching provider response; it returns the current state without reapplying the earlier transition.

Endpoints and authority

The service inherits offers, agreements, original-receipt retrieval, tokens, introspection, events, status and revoke routes from the free service. Two explicit paid routes are added:

Route below the appointed service base URL Request/authentication Result
POST agreements/{agreement_id}/payment-mandate Exact compact mandate JWS and separately provisioned payer Basic credential 201 on first durable retention; 200 for identical payer/payload retry; a changed mandate conflicts
POST agreements/{agreement_id}/payment-check JSON binding plus agreement_id and new check_id; owning agent or admin credential Current payment_state and access_state; no debit or new access credential

The resolver kinds are payment_mandate and payment_check, requiring issue_agreements, the exact agreement route, zero offer/access/use durations and payment_mode:"external". Neither uses an origin service signing role to authenticate the payer: payer provisioning is a separate trusted boundary. Current agreement authority and the pinned policy are checked for a new mandate. The verifier operation independently requires verify_payments and odexa-payment-status+jws.

The trusted constructor takes quote_factory, verifier_delegation_id and optional verifier_credential, alongside the free service’s explicit binding, key, exact terms, transport, history and live clock. A quote factory does not confer verifier authority. Current metadata must authorize the quoted verifier before any payment context leaves the host. A ScopedCredential permits transmission only to the intended HTTPS origin and tenant path. There is no ambient credential forwarding or redirect following.

The low-level verifier supports register_commit_guard for trusted adapters with a wider transaction. A new response must still fall within its inclusive 60-second checked-time window at that enclosing commit. Its current origin history, appointed signing key and delegation are rechecked there. A historical exact check replay is read-only and does not regain freshness by being retried.

Durability and failure boundaries

PaidStore has an explicit distinct storage version. It extends the free schema with pending access, immutable accepted quotes, payment states/audit and a separate payer registry/proof table. TransactionPayments performs no independent commit: agreement receipt, accepted payment binding, financial assertion, access state and status-version transitions share the enclosing SQLite write transaction.

Final guards run after application/signing and before commit. Expired offer/access/mandate deadlines, newer locally observed authority, revoked or expired verifier keys and stale new provider responses roll back the transaction. Authority observation remains a bounded remote read, not a distributed atomic transaction. Errors deny new access; preserved historical evidence is not upgraded to current authority.

Payer and agent secrets are hash-only in their separate registries. Exact signed mandates, their original nonsecret payer identity/key descriptors, and provider assertions are retained for audit. Payment quotes, audit and payer-proof records are append-only; accepted bindings are fixed and a mandate is set once. A payer client ID pins its identity and public key; a new key requires a new provisioned payer client ID in this reference. Credential hash/active state can change without rewriting prior proof. These objects may contain identity and financial metadata and require application access controls. The free portable-evidence entry point deliberately rejects this paid store. The explicit paid archive profiles now preserve its complete selected evidence and independently replay its payment history.

The reference fixed-quote state bounds each agreement to 256 distinct payment checks. At that bound it fails closed rather than discarding idempotency history. Because active token/introspection/status requests perform fresh checks, this is a material reference limit, not a production-scale ledger claim. Production retention/compaction must preserve exact replay and transition guarantees under an explicitly specified extension.

Reproduce and interpret the evidence

PYTHONPATH=tests:. python3 -m unittest test_paid_contracts test_paid_service test_paid_commit_boundaries test_paid_workflow test_paid_store -v

The paid service fixture uses actual TLS sockets on two distinct loopback origins, an explicitly trusted ephemeral CA, separate agent/payer/gateway/provider keys and credentials, and real protected response bytes. The provider is a synthetic signed status server. Tests cover pending denial, confirmation/delivery/reversal, wrong payer/amount/signer, appointment withdrawal, replay after reversal, atomic acceptance/payment retention, late financial confirmation and historical receipt recovery. The additional workflow tests cover failed-to-pending-to-confirmed recovery, exact proof retention after service reconstruction, actual paid delivery followed by signed gateway intake, and an aged historical check replay that creates neither a new financial application nor a token. Targeted commit regressions make only the separate verifier key or response freshness expire after ledger application, while agreement authority is still valid.

The free path remains exercised separately and imports no payment module. This service is a programmatic dispatcher with trusted provisioning APIs. The installed quickstart composes it with an explicit synthetic fixed-quote verifier and separate payer command; the legacy interactive CLI remains draft 2. A payment initiation/refund connector, commercial processor onboarding, transfer of funds and proof of real-world settlement are outside this reference. Paid portability retains the accepted financial evidence, and provider handover requires fresh successor agreements. The independent paid Node flow and independent native asset client have separate scoped checks. See current validation and release status; component results do not establish external certification or real settlement.

Odexa / Protocol explorer

This page. Your terms.

Inspect this website’s published policy and see how a proposed use is evaluated.

Current pagehttps://odexa.io/releases/1.2.0-rc.1/docs/paid-service/
Loading policy…

Published JSON
Open JSON

This is a local policy check, not a signed agreement or proof of agent compliance. Other published licences and applicable rights still apply. How policy evaluation works →

Odexa / Get in touch

Start a conversation.

Tell us what you have in mind. We’ll respond where we can.

We use these details to review and respond to your enquiry. Please leave out confidential information. Submitting does not subscribe you to marketing. Privacy policy.