1.2.0-rc.1 / Payment profiles

Payment state

Durable state, exact retries and an ordered audit without initiating a charge.

profiles/payment_ledger.py persists the fixed-quote profile in a private SQLite database. It serializes concurrent writers with BEGIN IMMEDIATE, commits state and its audit entry together, and uses synchronous=FULL with SQLite’s rollback journal. It makes no network request and has no debit operation.

The accepted quote, accepted binding, separate payer mandate and applied verification responses retain their exact input bytes. A quote’s (provider_id, quote_id) identity belongs to one agreement and cannot change bytes. An agreement ID cannot acquire a different quote or accepted binding. Exact retries return current state without adding a duplicate verification. An invalid transition or failed transaction leaves no partial financial state or audit entry. A read applies the access deadline durably; revocation and expiry retain financial facts.

The application owns a private directory. The implementation requires mode 0700 for that directory and 0600 for its database, rejects symlink database files and never changes permissions on an existing file. Protect the directory, its parents and backups against replacement by other processes running as the same OS user. SQLite and filesystem durability are the boundary; this is not a replicated ledger or a guarantee against disk failure, malicious local modification or storage hardware that ignores sync.

The caller must authenticate the accepted agreement, payer, operator and provider response before invoking this module. A supplied string or dictionary is not proof of authentication. apply consumes the real delegation resolver’s allowed result, including the exact check and accepted-resource digests. Its audit context allowlists protocol fields rather than serializing an arbitrary authentication adapter. No password, bearer token or signing key belongs in any payment document. Audit rows are local records; their digests do not make them independently signed evidence.

ledger = PaymentLedger('/private/application-data/payments')
ledger.start(quote_bytes, accepted_binding_bytes, now=now)
ledger.authorize(agreement_id, mandate_bytes,
                 authenticated_payer_id=verified_payer_id, now=now)
ledger.apply(agreement_id, verified_response_bytes,
             expected_check_id=check_id, authority=current_authority, now=now)
state = ledger.get(agreement_id, now=now)

records returns local audit material for inspection. It is not a closed portable export or import protocol. The pure payment profile’s 256-check limit per agreement remains in force; the ledger does not silently discard history to admit another check. Free exchanges bypass the payment ledger. The local signed-response adapter verifies and retains the provider JWS against current origin-authorized keys before using this ledger. The network adapter now supplies trusted origin HTTPS observations and delegated provider verification. Agreement/gateway integration and closed export remain release gates. A fake authenticated context in a unit test does not satisfy them.

Tests exercise restart, concurrent writers, exact retries, quote immutability, failed authentication, rejected settlement transitions, revocation/expiry and an actual subprocess exit after SQLite writes but before commit. The crash test establishes SQLite recovery for that interruption point; it does not simulate storage hardware failures.

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/payment-ledger/
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.