Skip to main content

presidio-hardened-x402

PyPI version Python GitHub release License: MIT CI OpenSSF Scorecard OpenSSF Best Practices

v0.12.0 — pay-to pinning and a quote-drift limit: an opt-in wallet_pinning="warn" | "block" pins the first pay_to seen per origin and network and flags or blocks a later change of recipient before signing; max_quote_increase_ratio blocks a quote that climbs past the route's reference price, including a walk up in small steps. Also raises the cryptography (CVE-2026-69247) and anyio (CVE-2026-63374, CVE-2026-64847) floors. Upgrade from any earlier version.

v0.11.1 — security patch: percent-encoded PII no longer evades the filter. alice%40example.com in a resource URL previously passed through unredacted; matching now runs against a bounded percent-decode, with spans mapped back so your own bytes are what you get returned. Upgrade from any earlier version.

Security middleware for the x402 payment protocol.

Intercepts x402 payment requests before transmission to servers and facilitators to enforce:

  • PII redaction — Presidio-based detection and redaction of personal data (emails, names, SSNs, credit cards, etc.) from payment metadata fields before they are sent to the payment server or facilitator API
  • Spending policy — per-agent, per-endpoint, and per-time-window budget limits that block or throttle payments before execution
  • Replay detection — HMAC-SHA256 fingerprinting of canonical payment fields to prevent duplicate and replayed payments; case-canonicalised on pay_to and currency (v0.4.0)
  • Audit logging — HMAC-chained JSON-L audit trail for every payment attempt (including blocked ones)
  • Multi-party authorization — n-of-m approval requirement for high-value payments, via webhook or HMAC-SHA256 cryptographic countersignature modes (v0.3.0)
  • Prometheus metrics — structured telemetry for every security control activation (v0.3.0)
  • Remote screening — opt-in remote_screening=True mode offloads PII analysis to the hosted screen.presidio-group.eu service via ScreeningClient; avoids the in-process spaCy dependency (v0.4.0)
  • Per-origin wallet allowlist — per-origin pay_to allowlist blocks payments to attacker-controlled addresses when a DNS-poisoned 402 response substitutes the recipient (chain-06 mitigation) (v0.4.0)
  • Rail-agnostic core + binding layer — the screening pipeline (ScreeningPipeline) is payment-protocol-independent; everything x402-specific lives in bindings/x402. Embed on a different rail by implementing PaymentProtocolBinding — the security guarantees travel with the core (v0.5.0)
  • OEM embed kit — semver/stability guarantees, partner-runnable conformance suite (python -m presidio_x402.conformance, 7 end-to-end checks, no network), and integration quickstarts for Coinbase CDP, LangChain, and CrewAI (v0.5.0)
  • Enterprise hardening — per-tenant replay namespaces, remote audit sinks, signed evidence verification, OpenTelemetry spans, hot-reloadable policy, release provenance, and latency-SLO CI gates (v0.6.0)

Part of the presidio-hardened-* toolkit family.


Installation

pip install presidio-hardened-x402

For full NLP-based PII detection (PERSON, ORG, location, etc.):

pip install "presidio-hardened-x402[nlp]"
python -m spacy download en_core_web_lg

en_core_web_lg is the model Presidio's default NLP engine loads, and the one the published evaluation used. Installing en_core_web_sm instead leaves mode="nlp" unable to start.

For production replay guard with cross-process deduplication:

pip install "presidio-hardened-x402[redis]"

For Prometheus metrics export:

pip install "presidio-hardened-x402[prometheus]"

For policy-as-code schema validation:

pip install "presidio-hardened-x402[schema]"

Quick Start

Before (bare x402 — no security controls)

import httpx

async def pay_and_fetch(url: str, signer) -> httpx.Response:
    async with httpx.AsyncClient() as client:
        resp = await client.get(url)
        if resp.status_code == 402:
            payment_details = parse_402_header(resp.headers)
            # No PII check. No policy check. No replay check.
            payment_token = await signer.sign(payment_details)
            resp = await client.get(url, headers={"X-PAYMENT": payment_token})
        return resp

After (presidio-hardened-x402)

from presidio_x402 import HardenedX402Client

async def my_signer(details):
    # Your existing signing logic (eth-account, solders, CDP SDK, etc.)
    ...

client = HardenedX402Client(
    payment_signer=my_signer,
    policy={
        "max_per_call_usd": 0.10,
        "daily_limit_usd": 5.0,
        "per_endpoint": {"https://api.example.com": 1.0},
    },
    pii_action="redact",          # redact | block | warn
    pii_entities=["EMAIL_ADDRESS", "PERSON", "US_SSN", "CREDIT_CARD"],
    replay_ttl=300,               # seconds
)

response = await client.get("https://api.example.com/resource")

What happens transparently:

  1. Client sends GET /resource → server returns 402 with payment details
  2. PIIFilter scans resource URL, description, and reason fields; redacts any PII
  3. PolicyEngine checks: amount ≤ per-call limit? daily spend within budget? endpoint limit OK?
  4. ReplayGuard checks: have we paid this exact request within the TTL window?
  5. AuditLog records the attempt (pass or block) as a tamper-evident JSON-L entry
  6. If all checks pass, signer is called → payment header sent → resource returned

Configuration

Policy

from presidio_x402 import HardenedX402Client, PolicyConfig

policy = PolicyConfig(
    max_per_call_usd=0.05,         # block if maxAmountRequired > this
    daily_limit_usd=2.00,          # block if 24h aggregate spend would exceed this
    per_endpoint={
        "https://premium-api.io": 0.50,  # per-endpoint daily limit
    },
    max_quote_increase_ratio=0.5,  # block a quote > 1.5x the route's reference quote
    window_seconds=86400,          # time window for aggregate limits (default: 24h)
    agent_id="my-agent-v1",        # tag audit events with an agent identifier
)

client = HardenedX402Client(payment_signer=signer, policy=policy)

PII Filter

# regex mode (default, zero-setup): catches structured PII
client = HardenedX402Client(
    payment_signer=signer,
    pii_mode="regex",
    pii_entities=["EMAIL_ADDRESS", "PHONE_NUMBER", "US_SSN", "CREDIT_CARD"],
    pii_action="redact",
)

# nlp mode: full spaCy NER (requires: pip install presidio-hardened-x402[nlp])
client = HardenedX402Client(
    payment_signer=signer,
    pii_mode="nlp",
    pii_entities=["EMAIL_ADDRESS", "PERSON", "LOCATION", "US_SSN"],
    pii_action="block",     # raise PIIBlockedError instead of redacting
)

Known detection limits

The filter canonicalises input before matching, so PII survives NFKC forms, zero-width characters, Cyrillic homoglyphs, non-ASCII hyphens, and — since the current release — percent-encoding, including one level of double-encoding (%2540). Encoded input is decoded for matching only; the string you get back is still yours, so benign escapes are never rewritten.

Two bounds are deliberate rather than accidental, and worth knowing:

  • Percent-decoding stops after two rounds. Triple-encoded PII (%252540) is not recovered. Decoding until stable would let a short hostile input amplify inside the filter, which is the worse trade for a control on the payment path.
  • regex mode detects structural PII only — emails, SSNs, credit cards, phone numbers, IBANs, IP addresses. Names, organisations, and locations need mode="nlp".

Detection gaps are measured, not assumed: experiments/surface_form_probe.py reports the current numbers, and the entity-level results are in experiments/results/.

Replay Guard

# In-memory (default, single-process)
client = HardenedX402Client(payment_signer=signer, replay_ttl=300)

# Redis-backed (production, cross-process)
client = HardenedX402Client(
    payment_signer=signer,
    replay_ttl=300,
    redis_url="redis://localhost:6379/0",
)

Audit Log

import sys
from presidio_x402 import HardenedX402Client
from presidio_x402.audit_log import StreamAuditWriter

client = HardenedX402Client(
    payment_signer=signer,
    audit_writer=StreamAuditWriter(sys.stdout),   # write JSON-L to stdout
)

Multi-Party Authorization (v0.3.0)

For high-value payments that require human or system oversight before execution:

from presidio_x402 import HardenedX402Client
from presidio_x402.mpa import MPAConfig, MPAApproverConfig, MPAEngine

mpa = MPAEngine(MPAConfig(
    threshold=2,               # require 2 of 3 approvals
    min_amount_usd=1.00,       # only for payments ≥ $1.00
    timeout_seconds=30,
    approvers=[
        MPAApproverConfig("alice", mode="webhook",
                          webhook_url="https://approvals.internal/alice"),
        MPAApproverConfig("bob",   mode="webhook",
                          webhook_url="https://approvals.internal/bob"),
        MPAApproverConfig("charlie", mode="webhook",
                          webhook_url="https://approvals.internal/charlie"),
    ],
))

client = HardenedX402Client(payment_signer=signer, mpa_engine=mpa)

Approval endpoints receive a POST with payment details and must return {"approved": true}. For machine-to-machine approvals, use mode="crypto" with HMAC-SHA256 countersignatures and pass them via mpa_signatures={"approver_id": "hex_sig", ...} in the request kwargs.


Prometheus Metrics (v0.3.0)

from presidio_x402 import HardenedX402Client
from presidio_x402.metrics import MetricsCollector

collector = MetricsCollector()
client = HardenedX402Client(payment_signer=signer, metrics_collector=collector)

# Expose /metrics endpoint (e.g., FastAPI)
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST

@app.get("/metrics")
def metrics():
    return Response(generate_latest(), media_type=CONTENT_TYPE_LATEST)

Available metrics: x402_payments_total, x402_payment_amount_usd (histogram), x402_pii_detections_total, x402_policy_violations_total, x402_replay_detections_total, x402_mpa_events_total.


Policy-as-Code (v0.3.0)

Define spending policy in a TOML or JSON file and validate it against the x402 policy JSON Schema:

# policy.toml
max_per_call_usd = 0.10
daily_limit_usd  = 5.00
agent_id         = "my-agent"

[per_endpoint]
"https://premium-api.io" = 0.50

[mpa]
threshold       = 2
min_amount_usd  = 1.00
timeout_seconds = 30

[[mpa.approvers]]
approver_id = "alice"
mode        = "webhook"
webhook_url = "https://approvals.internal/alice"
from presidio_x402.x402_policy_schema import load_policy_file

policy = load_policy_file("policy.toml")
client = HardenedX402Client(payment_signer=signer, policy=policy)

Remote Screening (v0.4.0)

Offload PII analysis to the hosted screen.presidio-group.eu service. Useful when you want to keep the agent process small (no in-process spaCy model) and centralise screening policy across many agents.

from presidio_x402 import HardenedX402Client

client = HardenedX402Client(
    payment_signer=signer,
    remote_screening=True,
    screening_api_key="...",   # obtain by registering at screen.presidio-group.eu
)

The free tier serves the regex-mode screening backend at 100 screenings/day per key. Falls back to local regex / NLP modes if the network is unhealthy, so the client never hard-fails on a screening-service outage.

Per-origin wallet allowlist (v0.4.0)

Defence against DNS-poisoning attacks that substitute the recipient wallet in a 402 response. Configure the trusted pay_to addresses per resource origin:

client = HardenedX402Client(
    payment_signer=signer,
    trusted_wallets={
        "https://api.example.com": {"0xAbC...123"},
    },
)

Payments to a pay_to not in the allowlist for the response's origin are blocked before signing.

Pay-to pinning (trust-on-first-use)

The allowlist only covers origins you enumerate. For everything else, wallet_pinning records the first pay_to observed per (origin, network) and reports every later divergence — a compromised server, a DNS/MITM swap that starts after the first paid call, or an endpoint that rotates its address per request. Independent measurement of the live catalogues (probe402, MCRI #001, 21–31 Aug 2026) found 33 of 6,835 quoted endpoints changing address between observations, one on nearly every probe.

client = HardenedX402Client(
    payment_signer=signer,
    wallet_pinning="block",   # or "warn": record WALLET_ROTATED and proceed
    redis_url="redis://...",  # optional: share the pin table across replicas
)

# A legitimate rotation is an explicit operator step; pins never advance on their own.
client.wallet_pins.pin("https://api.example.com", "base-mainnet", "0xNewWallet...")

First sight emits WALLET_PINNED; a different address later emits WALLET_ROTATED and, under "block", raises WalletRotationError before signing. Origins listed in trusted_wallets are skipped — the allowlist is the stronger statement. Trust on first use is exactly that: for origins whose recipient you know, use the allowlist.

Quote-drift limit

max_quote_increase_ratio bounds a quote against the reference quote for the same route (the redacted URL without query or fragment). The reference is the first quote seen and moves down freely, but never up on its own: an increase within the ratio is paid, not adopted, so a server cannot walk the price up by just under the ratio on every call. Raise the baseline explicitly with engine.set_reference_quote(url, usd). The same MCRI #001 window saw 73 endpoints change price; a cached quote is not a contract.


Kubernetes Deployment (v0.3.0)

Deploy as a sidecar using the bundled Helm chart:

helm install x402 ./helm \
  --set x402.agentId=my-agent \
  --set x402.maxPerCallUsd=0.10 \
  --set x402.dailyLimitUsd=5.00 \
  --set serviceMonitor.enabled=true

See docs/soc2-reference-architecture.md for SOC 2 TSC mapping, GDPR obligations, and deployment patterns.


SLO Payment Broker (v0.7.0)

Market-based SLO enforcement: when infrastructure degrades, the agent autonomously pays for a capacity upgrade via x402 micropayments instead of relying on pre-provisioned autoscaling. The broker acts only on a verified degradation signal — a signed evidence-ref@1 from a trusted presidio-hardened-arch-translucency signer — so a spoofed or misconfigured signal cannot trigger a payment (authorization, not metric).

from presidio_x402 import (
    HardenedX402Client, SLOPaymentBroker, SLOPaymentPolicy,
    X402CapacityProvider, ArchTranslucencyAdapter,
)

# arch-translucency's signed degradation feed → verified trigger (fail-closed).
adapter = ArchTranslucencyAdapter(
    {"presidio-hardened-arch-translucency": {"alg": "ed25519", "public_key": ARCH_PUB}},
    expected_signers=["presidio-hardened-arch-translucency"],
)
client = HardenedX402Client(payment_signer=signer)
broker = SLOPaymentBroker(
    client=client,
    slo_policy=SLOPaymentPolicy(
        cooldown_seconds=300,            # anti-drain
        max_per_slo_event_usd=0.50,
        max_daily_slo_usd=10.00,
        tier_escalation_rules=(1.0, 2.0, 4.0),  # step-up pricing for repeated degradation
    ),
    provider=X402CapacityProvider("compute", "https://compute.example/v1/capacity", client),
    base_event_usd=0.10,
)

for trigger in adapter.build_triggers(signed_envelope):  # verified or skipped
    await broker.handle_trigger(trigger)   # → paid / blocked / skipped, with audit event

The signing key lives in a separate bridge sidecar (arch-translucency stays key-less); x402 holds only the public key. The wire contract is pinned by the evidence-ref@1 golden-vector tests shared with arch-translucency.


Decision-ref emission (payment-decision@1)

A decision-ref is a signed, portable record of one payment decision that a third party verifies offline — without re-running the gateway. It binds the per-control gate verdicts (pii → trusted_wallet → policy → replay → mpa), the hashed inputs, and the effective policy hash into the family evidence-ref@1 envelope, with a thin, recomputable decision_ref correlation id. Emission is opt-in and off by default; when no emitter is configured, behaviour is byte-identical to prior releases and no decision-ref code runs. There is no network I/O on the emit path.

from presidio_x402 import HardenedX402Client, DecisionRefEmitter, verify_decision_ref
from presidio_x402.decision_ref import FileDecisionRefWriter

# Signer independence is claim-critical: a policy/approval identity distinct from the
# payment wallet — a self-signed record fails closed on verify (signer_equals_runtime).
emitter = DecisionRefEmitter(
    signing_key=POLICY_PRIVATE_KEY_HEX,          # Ed25519 (or an HMAC secret)
    signer="presidio-hardened-x402-policy",
    writer=FileDecisionRefWriter("/var/log/x402-decisions.jsonl"),
)
client = HardenedX402Client(payment_signer=signer, decision_ref_emitter=emitter)
# ... one signed payment-decision@1 record is emitted per paid payment.

# Verify offline against a pinned trust store (fail-closed, distinct reasons):
result = verify_decision_ref(envelope, {"presidio-hardened-x402-policy":
    {"alg": "ed25519", "public_key": POLICY_PUBLIC_KEY_HEX}})
assert result.ok and result.verdict == "ALLOW"

The verifier checks signature, hash integrity, that the recorded verdict re-derives from the recorded controls (verdict == f(controls) — the line between attested and admissible), that the signer is not the actor's own controller (self-approval fails closed), and — when the spending policy came from a capability chain (capability-grant@1) — parent linkage to the chain's terminal grant_hash. A minimal offline CLI is provided:

python -m presidio_x402.decision_ref envelope.jsonl trust-store.json

Honest bound. A decision-ref proves what the library concluded under a declared predicate, tamper-evidently and recomputably. It does not prove the process was uncompromised or that the declared controls are the real controls (no TEE claim). Wire format and decision_ref derivation are pinned by the conformance fixture under tests/conformance/decision-ref/ and the design note plan/presidio-evidence-decision-ref-design.md.

Treasury binding (settlement-ref@1) — v0.10.0

A decision-ref says why a payment was allowed. Reconciling it into a ledger's close also needs which settlement it authorized — and the shipped payment-decision@1 record carries no transaction hash. settlement-ref@1 is that join: a signed, off-chain statement, under the same policy signer, committing to {decision_ref, chain (CAIP-2), tx_hash, block_number, log_index}.

from presidio_x402 import FileSettlementWriter, HardenedX402Client

client = HardenedX402Client(
    payment_signer=signer,
    decision_ref_emitter=emitter,                       # as above
    settlement_writer=FileSettlementWriter("settlements.jsonl"),
)
# The paid response's PAYMENT-RESPONSE echo is parsed and correlated with this
# payment's decision_ref. It carries the tx hash and network — NOT a block number
# or log index, so the record is written with "complete": false and those two
# fields are completed by the operator from a chain lookup.
python -m presidio_x402.treasury_binding export decision.json \
    --settlement settle.json --trust trust.json --key-file policy.key > bundle.json
python -m presidio_x402.treasury_binding verify bundle.json trust.json   # exit 0 iff verified

Export is fail-closed: it re-runs the full decision-ref verification (signature included — which is why --trust is required) and refuses a non-verifying envelope, a non-terminal REFER verdict, an out-of-bound identity string, or a join signed by an identity other than the decision's own signer. The bundle carries no key material: trust_store_ref names the signer and key id, and the verifier resolves both against its own pinned store — a bundle-supplied key would make verification trust-on-first-use.

Honest bound. This is an off-chain join, not an on-chain anchor: an ERC-3009 settlement's calldata carries no decision digest, so there is nothing on chain to check it against. It asserts only what the signer can — this decision, that transaction, signed. Bundle shape, ingest contract and residual risks: docs/treasury-binding.md; the cross-language byte contract: tests/conformance/treasury-binding/.

Provisioning Metadata Redaction

Capacity-upgrade requests can reveal workload type, data classification, or access pattern. Those heuristics are intentionally opt-in so ordinary payment metadata keeps the v0.6 false-positive profile.

from presidio_x402 import PIIFilter, PROVISIONING_ENTITIES

filt = PIIFilter(
    entities=list(PROVISIONING_ENTITIES),
    redaction_template="<{entity_type}>",
)

clean, entities = filt.scan_and_redact(
    "ml training workload over CONFIDENTIAL data: SELECT email FROM customers"
)
# clean:
# "<WORKLOAD_CLASS> workload over <DATA_CLASSIFICATION> data: <QUERY_PATTERN>"

Exceptions

Exception Raised when
PIIBlockedError PII detected in metadata and pii_action="block"
PolicyViolationError Payment amount, aggregate spend, or quote drift exceeds a configured limit (.reason names which)
ReplayDetectedError Payment fingerprint matches a recent transaction
X402PaymentError Upstream payment signing or network error, or pay_to outside the origin's allowlist
WalletRotationError wallet_pinning="block" and the 402 names a different pay_to than first pinned for its origin + network (subclass of X402PaymentError)
MPADeniedError Multi-party authorization required but not enough approvals received
MPATimeoutError Multi-party authorization webhook approval timed out

All exceptions are importable from presidio_x402.


Research Artifacts

Artifact Location Description
Synthetic corpus vstantch/x402-pii-corpus on Hugging Face · corpus/ 2,000 labelled x402 metadata triples; generator (generate.py, seed=42) + metadata (corpus_meta.json); raw JSONL reproducible from seed
Precision/recall sweep experiments/ 42-configuration grid search (run_sweep.py); latency benchmark (run_latency.py)
Dune Analytics queries dune/ 6 Trino SQL queries used to characterise the live x402 ecosystem (20 projects, 96 wallets, 11 chains, ≥79M transactions); see dune/README.md

Roadmap

Version Milestone
v0.1.0 PII redaction + spending policy + replay detection
v0.2.0 Synthetic corpus + 42-configuration precision/recall sweep, LangChain/CrewAI adapters, compliance report · arXiv:2604.11430
v0.2.1 Live ecosystem characterisation via Dune Analytics (20 projects, 96 wallets, 11 chains, ≥79M transactions); IEEE S&P magazine article submitted; IEEE TIFS paper under review · Corpus: v0.2.1/dataport/, Hugging Face, IEEE DataPort (doi:10.21227/kpsz-nq73)
v0.3.0 Multi-party authorization (mpa.py: n-of-m, webhook + crypto modes) · Policy-as-code JSON Schema (IETF draft candidate) · Prometheus metrics exporter · Kubernetes Helm chart + Docker image · SOC2 reference architecture
v0.4.0 Screening API launch — hosted screen.presidio-group.eu free tier (regex mode, 100 req/day) · ScreeningClient + remote_screening=True mode · per-origin pay_to allowlist (chain-06 mitigation) · audit-cycle hardening (F-A/B 2026-05-03, F-C/D/E 2026-05-10, F1/F2/F3 2026-05-17); see CHANGELOG.md
v0.5.0 OEM embed kit — rail-agnostic ScreeningPipeline core + bindings/x402 layer (PaymentProtocolBinding protocol, hedge against rail fragmentation: ACP/Tempo, AP2) · SEMVER.md stability guarantees · partner conformance suite (python -m presidio_x402.conformance) · CDP/LangChain/CrewAI quickstarts · SBOM in CI · freshness-bound MPA countersignatures (F-8)
v0.6.0 Production hardening + evidence substrate — multi-tenant replay namespaces · enterprise audit sinks (S3 / Splunk / Datadog) · signed evidence-ref@1 verification · SLSA/OIDC release provenance · digest-pinned Docker base + hash-pinned spaCy model · latency SLO and all-matrix coverage CI gates · OTel spans · policy hot-reload · startup key gates · human-pentest retest closure
v0.7.0 SLO payment broker (library) — x402 micropayments as runtime infrastructure bids: SLOPaymentBroker + SLOPaymentPolicy + evidence-anchored ArchTranslucencyAdapter + provisioning PII entities; cross-repo validated against presidio-hardened-arch-translucency. cs.DC preprint + empirical eval tracked separately
v0.8.0 PII completeness + supply-chain hardening (library) — nlp mode is now a structural superset of regex (no structured-identifier misses) · composed-envelope screen_ref leg · action_ref byte-determinism (NFC + non-empty entity sets) · URL-redacted log hygiene · OpenSSF Scorecard workflow/badge + SLSA Build L3 provenance · independent multi-round security audit cleared
v0.12.0 Pay-to pinning + quote-drift limit — opt-in trust-on-first-use pay_to pinning per (origin, network) with WALLET_PINNED / WALLET_ROTATED audit events and WalletRotationError under "block" (WalletPinStore, in-memory or Redis) · PolicyConfig.max_quote_increase_ratio with an anti-ratchet reference quote · PolicyViolationError.reason · cryptography>=50.0.0 and anyio>=4.14.2 floors — latest feature release
v0.11.2 Patch — declares tomli so TOML policy files load on Python 3.10, and packaging instead of relying on transitives
v0.11.1 Security patch — percent-encoded PII no longer evades PIIFilter (matching runs against a bounded decode, spans mapped back so caller bytes are preserved) · MPA webhook response body bounded on the plain-httpx path (CWE-400) · NLP install pinned to en_core_web_lg, the model Presidio actually loads
v0.11.0 CapabilityEnforcer — opt-in, default-off capability-grant@1 enforcement stage on the payment path (PII → wallet → capability → policy → replay → MPA); reuses verify_chain / check_payment / policy_config_from_chain / decision_ref; StageTiming per-stage breakdown; byte-identical when unset
v0.10.1 Security patch — DecisionRefEmitter signing key no longer leaks via repr (F1, CWE-312)
v0.10.0 Treasury binding — settlement-ref@1 signed off-chain join record + fail-closed bundle export/verify CLI · client-side settlement-receipt capture · caller-identity value bounds · cross-language conformance vectors (non-ASCII escaping, lone surrogates, non-string keys, i64 bounds, depth 128/129)
v0.9.1 Security patch — dependency-audit floors for click / setuptools, missing-payment-header log exposure hardening, and setup-uv v8.3.2 CI action pin
v0.9.0 Proof-carrying x402 evidence — capability-grant@1 attenuable spending grants + opt-in payment-decision@1 decision refs with raw-offer digest binding, fail-closed offline verification, capability-chain provenance linkage, and PII-free emitted records
Future Deferred #23 prompt-injection / agent-bound response scanning threat-model work

Planned direction (next 12 months)

Intended direction, not a commitment — priorities shift with the ecosystem and security findings:

  • Toward v1.0 — stabilise the public API under SEMVER.md and clear the mainnet release gate (KYB / signing / legal controls) for the paid screening route.
  • Prompt-injection / agent-bound response scanning (deferred issue #23) — extend the threat model beyond outbound payment metadata to untrusted agent-facing responses.
  • Broader rail coverage — additional PaymentProtocolBinding implementations as agentic payment rails consolidate.
  • Evidence and conformance — grow the partner conformance suite and the proof-carrying evidence vocabulary alongside upstream standardisation.

See PRESIDIO-REQ.md for full deliberation and rationale.


Contributing and support

  • Bug reports and feature requests — open a GitHub issue.
  • Security vulnerabilities — do not open a public issue; follow the private reporting process in SECURITY.md.
  • Code contributions — see CONTRIBUTING.md for the pull-request process, coding standards, and the test policy. Participation is governed by the Code of Conduct.
  • Architecture and governance — ARCHITECTURE.md describes the components, payment flow, and trust boundaries; GOVERNANCE.md covers the governance model, roles, and project continuity; ASSURANCE.md is the security assurance case.

Install from PyPI: pip install presidio-hardened-x402.


License

MIT


SDLC

This repository is on the open-source baseline of the PRESIDIO hardened-family SDLC (report · PDF). The controls measured for it, and any open gaps, are its row in the applicability matrix.

The screening service built from this library (screen.presidio-group.eu) runs on the commercial-operated baseline; its full SDLC document set lives in the internal repository.

Metadata

Release files for presidio-hardened-x402 0.12.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for presidio-hardened-x402 0.12.1
File Size Uploaded
presidio_hardened_x402-0.12.1.tar.gz 635.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for presidio-hardened-x402 0.12.1
File Interpreter ABI Platform
presidio_hardened_x402-0.12.1-py3-none-any.whl Python 3 none any Details

Total release size: 811.4 kB

Release files / presidio_hardened_x402-0.12.1.tar.gz

Download URL presidio_hardened_x402-0.12.1.tar.gz
Size 635.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a7eb4b8220ab055aa0befe49d5b12f143df3231344d9c8a50e10462cc14d5dbf
BLAKE2b-256 checksum
How to use checksums
a3f8d2e5b19b254eeb58209c4119731861ccd40093f6158561d155bb8d9919e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / presidio_hardened_x402-0.12.1-py3-none-any.whl

Download URL presidio_hardened_x402-0.12.1-py3-none-any.whl
Size 176.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
219732df9e42e426d2ffaa4ada7e33f7119013bd803c4fe3e4953dec5cbfa997
BLAKE2b-256 checksum
How to use checksums
a25151f11b311f0b55744b606c2c41818aa8cbb3eb958ca122a3908996b9481b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.12.1 This release

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page