1.2.0-rc.1 / Portability and clients
Independent paid client
Use the separate Node implementation for the demonstrated paid exchange.
The 1.2.0-draft.3 reference includes a second implementation of the ordinary fixed-quote paid flow. paid-client.mjs is a phased native Node client; paid-verifier.mjs implements its paid semantics. Neither imports Python, invokes Python validators or treats a successful schema check as semantic verification. Its Python harness supplies real HTTPS servers and independently provisioned test identities.
This independently implemented client supplies scoped paid-flow interoperability evidence within the project. The native asset graph client has separate evidence. Current combined results are recorded in current validation. The integrated technical review and corrections are complete; the owner has confirmed private security intake and the reviewed package is frozen for RC1. See release status; no external certification is claimed.
What is independently checked
| Boundary | Node behavior |
|---|---|
| Origin and service | Fetches exact policy/authority over certificate-verified HTTPS; selects the configured service/tenant/delegation and cumulative retrieval duties; retains revision, issuer, key identity and terminal-state history across processes |
| Quote | Checks the exact offered digest, offer/origin/service/payer/verifier binding, validity, approved currency/scale/payees/items and a positive exact sum using BigInt; resource and provider fees stay separate |
| Assent and receipt | Signs only exact agent assent; verifies the origin-appointed ES256 receipt, closed paid shape, pending state and exact accepted windows; receipt is neither a payer mandate nor a bearer |
| Payer | Uses a different credential and pinned signing key; signs the exact one-quote mandate; agent credentials/signatures are rejected by the Python payer endpoint |
| Payment verifier | Resolves its separate origin appointment before sending a scoped read-only credential and again after receiving the reply; verifies the provider’s original JWS and every accepted transaction field |
| Financial history | Replays sequence, event time, exact-check identity, provider reference and allowed transitions; distinguishes fresh assertions from read-only historical retries; expiry/reversal/revocation cannot restore access |
| Service agreement state | Compares the service’s state for the same check with the independently verified provider result; verifies signed status and rejects known terminal-state rollback |
| Delivery and reporting | Obtains an opaque token, fetches actual protected bytes, compares their independently configured digest and emits a client-reported retrieval; verifies the collector’s exact original intake and retry |
There is no debit, refund or payment initiation API. A signed provider assertion is not proof of bank settlement. A collector signature authenticates the participating client’s claim; it does not prove downstream model use.
Executed evidence
The final eight Python harness methods pass in the current wire run. They invoke 74 separate Node processes, each resuming a private journal. Two lifecycle scenarios execute 29 phases each:
- The origin hosts the agreement service directly; only the read-only verifier is delegated to the second HTTPS origin.
- Both the agreement service and read-only verifier are explicitly delegated to the second HTTPS origin.
Both scenarios cover pending and mandate-only denial, failed-to-confirmed recovery, exact retries, actual delivery, signed reporting, reversal, old-bearer denial, historical-check replay without resurrection, status and revocation. The other scenarios reject valid-but-unapproved prices/payees before assent, a correctly signed receipt falsely claiming active access, a wrong provider amount/signer, withdrawal after a provider response, observed origin rollback, altered known compromise history and a compromised key reintroduced under another identifier. The unsupported-duty scenario deliberately performs no network request. No outside provider/account is contacted; the payment server is a synthetic signed-status fixture.
The complete standalone Node run passes 140 tests, comprising the existing 91 and 49 new paid semantic cases. Those new cases include decimal/sum and fee separation, role separation, exact accepted bindings, current verifier authority, authenticated hostile responses, sequence/transaction conflicts, late financial confirmation without access extension, an original receipt after offer expiry and a stale new response distinguished from an exact historical retry. See native test source.
A preceding 10-method wire regression combined the then-six paid scenarios with the existing direct/delegated free and continuing-storage Node exchanges. Those four existing exchanges passed unchanged. The final paid-only run includes the two later scenarios and final client guards. Counts from these overlapping runs must not be added together or presented as a new complete Python suite. The current compatibility inventory records exact source/evidence hashes.
Reproduce
Use Node.js 24 and the documented Python environment from this source root:
node --test verification/test_paid_verifier.mjs
ODEXA_NODE="$(command -v node)" \
ODEXA_PAID_NODE_REPORT_DIR=verification/local-paid-node-run \
python -m unittest discover -s tests -p test_paid_node.py -v
The harness generates temporary private TLS/credential material, starts two local HTTPS origins and destroys the temporary deployment after the run. Optional saved reports contain scenario results, not private JWKs, passwords, verifier credentials or bearer tokens. The Node client itself uses native crypto, HTTPS and files, plus independently implemented JavaScript primitives already used by the free client. The free helper change only exports those existing primitives; it changes no free wire behavior.
Phases and private configuration
For an independently provisioned reference deployment, supply a private JSON config and a new journal filename inside an owner-only directory:
node verification/paid-client.mjs --config /private/path/client.json \
--state /private/path/paid-state.json --phase agree
The trusted config fields are:
| Fields | Source and meaning |
|---|---|
publisherOrigin, serviceId, baseUrl, delegationId |
Expected origin/service/tenant and explicit selected delegation; null only for a direct service |
caFile |
Absolute filename of the explicitly trusted CA bundle for the configured deployment |
request, accessSeconds, useSeconds |
Intended scope and accepted durations; this client supports retrieve / public_retrieval and attribution only |
expectedTermsDigest, expectedResourceDigest |
Independently approved terms and test-article digests; never learned solely from the untrusted response being checked |
agent |
clientId, principalId, password, keyId, reporterId, privateJwk provisioned for agent assent/reporting |
payer |
Different clientId, payerId, password, keyId, privateJwk, plus independently pinned publicJwk for the payer role |
verifier |
serviceId, providerId, exact endpoint, delegationId and explicitly scoped read-only authorization |
approvedQuote |
Exact currency, minor_unit_scale, total_minor and items approved out of band, before signing a payer mandate |
The verifier credential is supplied only for this independent read-only comparison. It is not implied by an agent’s ordinary agreement credential. A real payer should keep its signing/provisioning boundary separate; this same-owner fixture holds both roles solely to demonstrate that the wire service rejects role substitution.
Normal phases are observe, agree, acceptance-retry, mandate, verify, service-check, retrieve, resource, report, status and revoke. Use verify --check-id UUID to create/replay a particular check, then service-check --check-id UUID to compare the service’s application of that same independently observed check. resource deliberately reuses a privately retained bearer so the harness can verify denial after revocation. mandate-agent-credential and mandate-agent-signature are explicit negative-test phases against your own prepared test service. They are not alternate authorization methods.
Each process acquires an exclusive journal lock and atomically replaces/fsyncs the saved state. The config and journal must be regular, owner-only files on a POSIX host. The journal can contain a bearer token alongside exact assent, receipts, mandate, reporting material and historical observations. Never publish it or confuse it with a portable evidence archive. Scenario reports exclude those secrets. A crashed process may leave the lock; establish that its process has stopped before manually recovering that lock. There is no time-based automatic unlock or concurrent-writer merge.
The client uses a fixed independently configured service/payer/verifier identity and a currently supported retrieval policy. It declines other execution duties. It does not perform provider handover, transparently follow policy lineage changes, implement continuing storage or verify paid archives. Use the separately evidenced storage client, handover procedure, paid archive verifier and installed operator path for those capabilities. Keeping these capability boundaries explicit avoids presenting a retrieval test client as full Agent Core conformance.