Admission control, not identity
V2 proves possession, scope, timing, and one-time use. It does not prove a human, account, wallet balance, or honest bidder.
What v2 enforces
- Ed25519 proof from the private key matching
X429-Client-Keyon every operation. - Proof binding to method, trusted authority, exact target, body digest, credential digest, time, nonce, and idempotency key.
- Exact issuer signature, algorithm, key ID, type, issuer, audience, subject, resource, method, window, and configuration hash.
- Atomic SQLite state transitions for proof nonces, reservations, bids, awards, payment intents, settlements, execution leases, and permits.
- Finite instant, free, and paid capacity; no credential can bypass its assigned lane or slot.
- Fail-closed behavior on coordinator, storage, configuration, or signature uncertainty.
The legacy v1 workspace compares a public-key string and should not be described as theft-resistant. Only v2 requires a signature from the corresponding private key.
Threat model
| Threat | Defense | Required test |
|---|---|---|
| Copied public key or ticket | Fresh client signature plus exact credential digest. | Attacker key and copied public-key string both fail. |
| Edited window, amount, scope, or issuer | Exact signed envelope and context checks. | Every single-field mutation fails. |
| Concurrent double redemption | Guarded SQLite transition inside one Durable Object. | Exactly one request changes state and admits. |
| Paid bypasses free/total capacity | Fixed lane quotas and unique paid slot indexes. | Awards never exceed K; permits admit only in their slot. |
| Proof or settlement replay | Unique proof nonces and idempotent state keys. | Exact duplicate returns defined state; changed duplicate conflicts. |
| Origin bypass | Private or separately authenticated fixed upstream. | Direct public origin access is impossible. |
| Forged edge request | Short-lived signed X429-Origin-Assertion plus durable nonce consumption at the upstream. | Wrong audience, target, receipt digest, key, expiry, and replay all fail. |
| Unknown settlement outcome | Locked global payment intent, conservative post-signature client classification, and authenticated dual-RPC reconciliation. | Transport/5xx/malformed responses do not trigger a new authorization; no permit until both operator-selected providers agree on exact chain evidence. |
| Confirmed payment after its slot | Capacity-backed recovery into one unused future paid slot with a rotated permit nonce. | Recovery never shares an auction target, never exceeds configured paid capacity, and fails closed when the horizon is full. |
| Paid horizon exhaustion | Hard X429_MAX_FUTURE_WINDOWS bound and 503 auction_horizon_full. | Preflight rejects an unsafe minimum; runtime collision exhaustion does not schedule beyond the bound or trigger a client retry loop. |
| Coordinator saturation | Outer DDoS/rate controls and no retry loop. | 503 does not trigger amplification. |
Known limits
- No independent security audit or formal proof has been completed.
- A client key is cheap and pseudonymous. Exact mode binds a winning authorization to a payer, but bids are still not funded when submitted and there is no general Sybil resistance.
- Unfunded sealed maxima can influence the clearing price even though only a winner that settles receives a permit.
- Every named capacity pool uses one coordinator and one pool-wide auction at a time. Routes mapped to the same pool compete for the same finite paid lane, so each pool has a deliberate hot-object throughput limit.
- The server controls auction seeds. Winners can verify the seed commitment, but the full public transcript is not yet independently reconstructible.
- The application profile is GET/HEAD only and does not provide origin-level response replay for side effects.
- Protected-origin dispatch irrevocably consumes a credential. The signed receipt proves consumption while the application result may be unknown; later timeout/transport/body/client failure is not replayed or automatically refunded.
- Authorization, cookie, and x-api-key are always committed. Add every custom authentication, tenant, model, or cost-bearing application header to
X429_BOUND_HEADERS; discovery publishes the canonical list and the client hashes those values. Put any remaining semantic selector in the signed query. - Every inbound
CF-*header is stripped before origin forwarding because edge-injected values cannot be committed by the signing client. Do not authorize origin work fromCF-Access-Jwt-Assertionin this profile without a separately reviewed verified-context binding.
Key management
- Use separate issuer keys per environment.
- Use a second, distinct origin-assertion keypair per environment. Pin its public key at the protected origin; compromise of the protocol issuer key must not authorize direct origin access.
- Publish public keys through the v2 Worker's
/.well-known/x429.json, and give clients the expected issuer, audience, key id, and public key through an independent trust channel. - Never store either private key in the repo, client bundle, or public Pages site.
- The current Worker verifies one exact active
kid. Overlapping key rotation, revocation, and KMS/HSM signing are still required before a mature release. - Until a keyring exists, rotate only through a full drain: deploy
X429_ISSUANCE_DISABLED=true, resolve indeterminate payments, let every credential, execution lease, and the discovery cache expire, then deploy a new key under a newkidand distribute the new pin out of band. - The issuance drain still accepts existing credentials. For suspected issuer-key compromise or unsafe forwarding,
X429_SERVICE_DISABLED=trueblocks protected and normal client traffic while leaving authenticated payment maintenance available. Its sole client-path exception binds and durably rejects a valid exact request already carryingPAYMENT-SIGNATUREbefore facilitator I/O; malformed or response-lost attempts remain ambiguous.
Production boundary
- Put DDoS, WAF, bot-risk, account, and coarse IP controls before the Durable Object.
- Route production through an owned hostname; disable public
workers.devaccess. - Keep the upstream private and verify
X429-Origin-Assertionwith durable one-time nonce storage. Reject any direct request without it. - Use separate accounts, namespaces, routes, and keys for development, staging, and production.
- Redact tickets, raw bid maxima, proofs, private keys, and authorization values from logs.
- Alert on any valid in-window ticket breach, over-capacity admission, or replay success.
- Exact settlement requires two independently administered reconciliation RPC providers (the runtime rejects identical hostnames but cannot prove independence), a dedicated administrator token, the Base
safesynchronous boundary with minimum depth measured inside the agreed boundary, at least a 180,000ms timeout, monitoring, funded staging evidence, and legal review. Basesafetypically takes about two minutes and is not irreversible;finalized, typically about 20 minutes, is reserved for delayed recovery/refund/discovery in the launch profile. - Require an awaited durable recovery commit before
PAYMENT-SIGNATURE; commit failure must send no payment request. After transmission, treat transport failure, every 5xx, invalid/missing payment receipt, malformed success data, and unrecognized responses as potentially submitted. One retry is allowed only for explicitpayment_confirmation_persistence_pendingwith the same authorization/body/idempotency; otherwise retain the pending record and never create a replacement authorization on that evidence alone. - Deployed exact mode must prove exactly one vetted
X429_ALLOWED_CLIENTSthumbprint, one paid slot, reserve equal to maximum, and one outstanding paid obligation. Competitive real-value bidding remains disabled while bids are uncollateralized.
The code implements exact x402 settlement and reconciliation. That is not a claim of a funded public-chain launch transaction, retained live-provider reconciliation exercise, or independent security audit; none has been completed yet.