1.2.0-rc.1 / Portability and clients

Paid evidence archives

Retain accepted quotes, payer authority and exact payment audit evidence.

This profile preserves the exact agreement, payer and provider evidence for selected draft-3 paid archives. It is part of the 1.2.0-rc.1 implementation candidate. Verification establishes the declared archive closure and authenticated assertions; it does not independently verify settlement. See current validation and release status.

Explicit profiles and interfaces

profiles/paid_evidence.py extends the same closed inventory and inert archive infrastructure as the free archive. The public free entry points still reject paid material. There are four explicit paid selections:

Profile Agreement and dependency selection Schema
odexa-paid-evidence-snapshot-1 Ordinary fixed-quote agreement paid-portable
odexa-storage-paid-evidence-snapshot-1 Signed storage_sessions_v1 agreement and exact copy-parent closure storage-paid-portable
odexa-assets-paid-evidence-snapshot-1 Ordinary paid agreement plus native asset/version/derivation closure assets-paid-portable
odexa-assets-storage-paid-evidence-snapshot-1 Both selected storage and native asset closure assets-storage-paid-portable

All have protocol_version:"1.2.0-draft.3". Their source_scope is respectively all_retained_paid_material_for_one_agreement_at_sqlite_snapshot, all_retained_storage_paid_material_for_one_agreement_at_sqlite_snapshot, all_retained_assets_paid_material_for_one_agreement_at_sqlite_snapshot or all_retained_assets_storage_paid_material_for_one_agreement_at_sqlite_snapshot. An import does not infer or downgrade this selection.

from profiles.paid_evidence import (
    build_bundle, verify_bundle, PaidExternalTrust, PaidEvidenceArchive,
)

trust = PaidExternalTrust(
    current_snapshot=current_origin_snapshot,
    pinned_documents=independently_retained_origin_documents,
    client_keys=independently_configured_agent_and_gateway_public_keys,
    payer_keys=independently_configured_payer_public_keys,
    # asset_trust=independent_asset_trust,  # required for assets=True
)

bundle = build_bundle(
    paid_store, agreement_id=agreement_id,
    snapshot=current_origin_snapshot, history=authority_history,
    export_operation=export_operation,
    private_key=export_private_key, key_id=export_key_id,
    now=trusted_clock,
    storage=False, assets=False,
)
report = verify_bundle(bundle, trust=trust, now=trusted_clock)
archive = PaidEvidenceArchive("/private/archive/evidence.sqlite3")
archive.import_bundle(bundle, trust=trust, now=trusted_clock)

For selected storage, pass storage=True consistently and use a StoragePaidStore. For native assets, pass assets=True consistently, asset_bundle_bytes and asset_trust to the builder, and independent asset_trust in PaidExternalTrust. Ordinary paid storage format is paid-agreement-2; selected storage is storage-paid-agreement-1. Imports use an inert archive database, not either operational store.

The caller authenticates/authorises the export request. These are in-process APIs, not an unauthenticated HTTP exporter. No network request, debit, token issuance, new agreement or credential transfer occurs during archive verification/import.

Exact retained payment artifacts

The ordinary archive defines the outer closed envelope, signed inventory, exact blobs, export authority, independent origin/reporter trust and base artifact kinds. Paid profiles additionally require:

Artifact kind / logical identifier Exact content
payment_quote / original quote UUID Original accepted payment.quote JSON bytes
payment_accepted / agreement UUID Original payment.accepted_binding bytes in the paid ledger
payment_state / agreement UUID Current retained scalar state, excluding separately carried quote, accepted binding and mandate bytes
payer_proof / agreement UUID, only when a mandate exists Closed {payer_client_id,mandate_jws,payload_b64url,public_identity_b64url}
payment_audit / canonical decimal source sequence Closed {sequence,kind,recorded_at,state_digest,input_b64url,context_b64url}

The decoded public payer identity is exactly {payer_client_id,payer_id,key_id,public_jwk}. It contains no secret, secret hash or account access credential. mandate_jws uses odexa-payment-mandate+jws; the retained payload must match its decoded bytes exactly. The decoded scalar state is exactly payment_state,access_state,checks,last_sequence,last_effective_at,provider_reference. Each checks entry is the original check UUID and exact provider-response payload digest in retained order.

The signed source cut adds payment_audit_count, payment_audit_max_seq and payer_proofs_count. One SQLite read transaction selects these artifacts together with the agreement, status attestations, reports, admissions and decisions. The original immutable quote registry must match the retained state. Payment-verifier authority/policy bytes come from the separately retained origin-history store, matching the digests in each original verification context; they are not fetched from an exporter-selected URL.

The reference bound is 256 distinct payment checks and at most 260 changing audit entries, within the outer archive’s 2,048 items and 16 MiB. Payment artifacts remain at most 1 MiB each. Selected nested asset evidence retains its separate 8 MiB limit. A larger history fails explicitly; it is never silently truncated. Source sequence gaps are allowed because other agreements can occupy the intervening database rows. Reordering uses the numeric retained sequence, not lexical sorting of its string identifier.

Independent payer and verifier trust

payer_keys is independent trusted configuration mapping key ID to {payer_client_id,payer_id,key_id,public_jwk,revoked}. Its public fields must equal the carried descriptor and revoked must be false. A valid signature from an exporter-carried key alone is insufficient. Known revoked public material cannot be rescued through another key alias. Payer authorisation remains separate from the agent’s agreement assent.

The original quote must match the paid offer’s exact quote digest, and the ledger’s accepted binding must match the exact offer, principal, request and original receipt’s recording/access/use times. Selected storage uses its original signed bytes; an internal projection is never substituted for the accepted digest. A paid context must also have explicit paid operational authority.

For each provider verification, the importer reconstructs the exact canonical payment-check request from the retained quote, acceptance and mandate. It reconstructs the scoped verify_payment operation and recomputes authority from independently pinned historical origin/policy documents at the retained observation time. The result’s authority fields must match the original context exactly. The original odexa-payment-status+jws must verify with that appointed key and preserve the exact response payload.

The paid state machine checks the response’s agreement, check, quote, payer, amount/currency, provider, mandate, accepted resource scope, sequence, freshness and transition. A correct signature does not excuse a wrong amount or scope. Current/independently known historical compromise causes rejection. A retired historical verifier can remain valid for historical evidence; its service/key identity cannot be rebound to a different issuer/public key. Historical validity does not restore current verification authority.

The export signer must remain currently authorised at the beginning and end of verification. Archive import repeats verification after its write lock, using a fresh clock. These are bounded local checks, not global instantaneous revocation consensus.

Ordered replay and access correlation

Audit kinds are exactly accepted, payer_mandate, verification, expired and revoked. The first entry must reproduce the accepted binding. A mandate step must preserve the original separately authenticated payer proof. A verification step must preserve the original signed provider response and exact authority context. Expiry/revocation steps carry no invented payment input. Non-changing duplicate audit steps, unknown kinds, regressing/future recorded times and mismatching identities are rejected.

After every step, the importer recomputes the canonical scalar state and checks its exact SHA-256 against state_digest. The final replay must equal the complete retained scalar bytes, including every retained check ID/digest. This detects missing/reordered/substituted entries against the retained state even if an authorised exporter repairs and re-signs the outer inventory. It cannot detect an exporter that falsifies an entire self-consistent source selection before making its declaration; the existing no-global-completeness qualification still applies.

The original receipt remains pending_payment. Access begins at lifecycle version 1 and changes only when its replayed access state changes. Failed/pending payment observations do not manufacture a new access grant. Confirmation can activate access, and reversal/expiry terminate it; later financial facts cannot restore terminal access. The indexed state/version must correlate with those transitions and every retained signed status.

An explicit owner/client revocation requires its original signed service status. A reversal recorded by the authenticated payment verifier can terminate the access index without a separately emitted status; the importer labels the index as correlated exporter evidence, not a signed status that never existed. Expiry remains fixed to the original receipt’s access deadline. An index that has not yet lazily recorded expiry is still reported expired for access at a later snapshot.

Activation/reversal effect times must lie in the retained observation interval. Explicit revocation can be recorded within the service’s bounded transaction window after its signed effect time. A paid admission must name a confirmed active lifecycle and a contemporaneously retained confirmed check; an old confirmation alone is insufficient. Whole-second timestamps cannot resolve ordering within the same second as a transition, and the report expressly leaves that ordering unverified.

Recorded audit times and synthesized historical observations are exporter testimony correlated with independently pinned bytes and signed statements. They are not independently witnessed timestamps or proof that every intermediate authority withdrawal was observed.

Storage, asset closure and assurance

Selected storage additionally preserves exact related-event and copy-parent dependencies and derives qualified storage metrics from the accepted terms. Native asset variants require the exact root set for all selected report asset/derivation references, complete signed dependency closure, independent current knowledge for each source origin and per-report correlation. A paid result does not waive either dependency check. The catalogue cut remains distinct from the agreement SQL cut; changed report roots fail closure rather than claiming a global atomic cut.

The returned payment report includes replayed financial/access state, access at the snapshot, quote digest, mandate-authentication flag, verification/audit counts and last provider sequence. It explicitly reports bank_settlement_verified:false, recorded_times_independently_witnessed:false, global_payment_history_complete:false and reactivates_access:false. Client use assertions and gateway testimony retain their original source qualifications. Matching asset evidence does not prove model use or receipt by a remote client.

PaidEvidenceArchive inherits the private owned database, no operational-table reuse, exact retry/conflict, append-only retention and historical-only retrieval rules. Its read API returns original bytes and the earlier import report; reading it later does not assert current trust or permission. Reimport performs current checks again. No secrets or live tokens are exported.

Evidence and limits

tests/test_paid_evidence.py has 18 methods covering actual HTTPS assent/payer/verifier flows, pending without a payer, failed-to-confirmed recovery, exact verification retry, reversal, late confirmation, pending expiry, original signed revocation, protected delivery/intake, independent payer trust, correctly signed wrong amount, altered audit/state/counts/order, retired versus revoked verifier, source/archive restart, credential exclusion, post-lock expiry and all four archive variants. Asset variants exercise transitive-parent omission after the exporter re-signs the inventory. Storage execution itself retains its separately recorded Node evidence; these new storage archive tests authenticate signed claims.

The earlier component checkpoint recorded a passing focused run, an 80-method regression slice, 571 Python tests, 56 new structural cases and 245 combined cases across 15 schemas. These are historical checkpoint counts, not the current totals. Structural positives are not independent semantic proofs. Use current validation for the current commands, totals and overlap limits.

The handover procedure preserves original paid evidence while requiring explicit fresh successor agreements. The independent paid client, independent asset client and installed operator tooling retain their own bounded checks. Archive verification alone does not prove those capabilities or authorize continued access. The integrated technical review and corrections are complete; the remaining security intake and publication gates are listed in release status.

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/guides/paid-portability/
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.