Run durable admission locally
Start the v2 Worker and its SQLite Durable Object, then exercise proof of possession, finite capacity, sealed bidding, and single-use redemption in workerd.
Prerequisites
- Node.js 24 or newer. The reference uses Web Crypto Ed25519 support.
- Access to the private
x429-protocol/x429repository. - A Cloudflare account only when you are ready to deploy; local workerd tests do not need one.
@x429/* packages are private repository workspaces, not public npm installs. The production-profile v2 service is packages/admission-worker; @x429/client, @x429/payment-x402, and @x429/origin are implemented private workspaces. A release operator can build coordinated client-only tarballs with npm run sdk:bundle -- <directory>; that bundle excludes the Worker and console. The Hono middleware remains legacy v1 reference code.Install and prove the repository
git clone https://github.com/x429-protocol/x429.git
cd x429
npm ci
npm run check
npm run check runs Node tests, exact-payment adapter checks, strict Worker type checks, v2 unit and workerd tests, the controlled client-to-Worker exact-settlement flow, package tarball smoke tests, and the simulator. It does not move real funds.
Configure separate local signing keys
install -d -m 700 .x429/local-secrets
npm run keys:generate -- x429-local-2026-07 \
--secret-output .x429/local-secrets/issuer.json
npm run keys:generate -- x429-origin-local-2026-07 --origin \
--secret-output .x429/local-secrets/origin.json
cp packages/admission-worker/.dev.vars.example \
packages/admission-worker/.dev.vars
The commands print only public metadata. Import the private fields from the exclusive mode-0600 JSON files into .dev.vars or the approved secret manager without displaying them. Keep the two key ids distinct in Wrangler configuration. Never commit those files or place either private key in wrangler.jsonc.
cat, echo, shell-substitute, or put private fields in argv. These credential writers are POSIX-only. Native Windows is not supported: use reviewed secret-manager-native tooling that does not invoke them, or WSL with output on a private Linux filesystem—not /mnt/c or another shared mount. Otherwise, do not run them.Start the v2 admission Worker
npm run worker:dev
The checked-in development configuration listens at http://127.0.0.1:8787, exposes discovery, and uses explicit mock settlement.
curl -i http://127.0.0.1:8787/healthz
curl -i http://127.0.0.1:8787/.well-known/x429.json
Protected routes require a valid Ed25519 client proof; an unsigned curl /v1/infer is expected to fail. Run the integration suite to execute the complete signed flow:
npm run test:worker
npm run test:worker:exact
The suites are designed to fill capacity, obtain durable tickets, reject early and replayed redemption, clear sealed maxima, exercise mock and exact settlement paths, verify standard x402 headers, and redeem one paid permit. Retain a successful run for the release commit. Exact tests use a controlled facilitator stub, not a funded public chain.
Know which profile you are running
| Command | Profile | Use |
|---|---|---|
npm run worker:dev | v2 local mock | Durable GET/HEAD admission, proof of possession, finite lanes, sealed auction, and no-money settlement. |
npm run worker:preflight:staging | v2 exact staging | Validates the copied staging config before source deployment. The example uses Base Sepolia and the official x402.org facilitator. |
npm run worker:bootstrap:staging -- --secrets-file PRIVATE_JSON | first exact deployment | Validates the complete owner-only secret set and publishes the issuance-disabled Worker in one strict deployment. It avoids intermediate versions with only some secrets installed. |
npm run worker:preflight:production | v2 exact production candidate | Requires Base mainnet official USDC, authenticated CDP facilitator, fixed HTTPS upstream, two independently administered RPC providers agreeing on the Base safe boundary, and distinct administrator and read-only monitor secrets. Passing preflight is not funded-production evidence. |
Troubleshooting
| Problem | Likely cause | Fix |
|---|---|---|
npm run check fails on Node version. | Node is older than the Web Crypto Ed25519 support expected by the repo. | Install Node 24 or newer and retry. |
/healthz returns 503. | Either signing keypair is absent, reused, mismatched, or malformed. | Generate two distinct pairs and populate the local .dev.vars. |
| A protected request returns 401. | The proof is missing, stale, malformed, or does not match the exact target. | Sign the v2 canonical request object with the client private key. |
| A ticket redeems early or twice. | A protocol invariant was broken. | Block release and reproduce with npm run test:worker. |
| Exact settlement returns reconciliation pending, a 5xx, or malformed post-signature data. | The facilitator may have broadcast, or reported success before both RPC providers proved the same Base safe boundary and exact receipt/events. | The required gross budget and recovery WAL already committed before submission. Except for one same-authorization retry of explicit payment_confirmation_persistence_pending, retain the pending record and charged budget; do not resubmit. Use authenticated npm run payment:reconcile with the known transaction, or --discover-transaction for bounded finalized AuthorizationUsed discovery when the hash is genuinely lost. Discovery still performs normal verification. After confirmation call resumeExactPayment() with the same stores and no wallet signer. |
Before staging deployment
- Copy the staging Wrangler example to its untracked live filename and replace every
REPLACE_*value. - Prepare one current-user-owned mode-0600 flat JSON file containing exactly the secret names declared by
secrets.required. Include both complete, distinct keypairs, plus any production CDP credentials; never place them in source or Wrangler variables. Do not install first-deployment secrets one at a time. - Include URLs for two independently administered RPC providers and pairwise-distinct 32+ character
X429_ADMIN_TOKEN(mutating reconciliation/refund),X429_MONITOR_TOKEN(read-only inventory/export), andX429_POOL_INVENTORY_TOKENvalues. The bootstrap command validates names, keypair matching, file security, token separation, and different RPC hostnames before one strict deployment. Different hostnames alone do not prove provider independence. - Have the one deployed exact launch tester run
npm run client:identity -- --kid x429-client-<name> --output PRIVATE_FILE, import the new mode-0600 file into a secret manager, and send only the printed thumbprint/public key. Vet that pair and set exactly that thumbprint inX429_ALLOWED_CLIENTS; keep one paid slot, reserve equal to maximum, and one outstanding paid obligation. - Protect one existing GET or HEAD route behind a fixed upstream. Keep the origin private and verify
X429-Origin-Assertionwith durable nonce consumption. - Map that exact path (or a deliberately bounded terminal
/*prefix) to a named finite pool inX429_ROUTE_POOLS. Do not use a global catch-all. - If that route uses custom authentication, tenant, model, or cost-bearing headers, add them to
X429_BOUND_HEADERSbefore issuing tickets. Authorization, cookie, and x-api-key are included automatically. - Distribute client trust pins—issuer, audience, key id, and public key—through an independent channel.
- Keep launch timing explicit: Base
safe, 20-second payment timeout, 240,000ms chain-observation timeout, 60,000ms poll interval, four attempts, 10-second settlement grace, and a fixed 2-second delivery lead. Deployed exact config rejects an observation timeout below 180,000ms. Prove clients bid only when the latest possible paid slot fits their task deadline. - Choose
X429_MAX_FUTURE_WINDOWSso its interval span covers one interval + auction epoch + payment timeout + confirmation timeout + settlement grace + 2 seconds. Preflight rejects a shorter exact horizon; treat runtimeauction_horizon_fullas capacity exhaustion, not a retry signal. - Force confirmed reconciliation after the original slot and prove resume moves the entitlement into unused future paid capacity without creating a second payment.
- Set
X429_RELEASE_COMMITto the full lowercase clean Git commit under review. Keep the template's initialX429_ISSUANCE_DISABLED=trueand make the first secret-bearing deployment only withnpm run worker:bootstrap:staging -- --secrets-file PRIVATE_JSON. Later issuance-disabled code/config releases useworker:deploy:stagingwithout a secrets file. Then change only the ignored reviewed config tofalse. Create the separate offline opening-approval key and signed 15-minute evidence envelope described in the private operator runbook. Runworker:verifywith explicit disabled/service expectations, the exact release commit, protected resource, canonical config,--opening-evidence, and a new non-overwriting.x429/attestations/staging-open.jsonproof. - Only after upstream isolation, monitoring, rollback, inventory anchoring, alert delivery, and drain checks pass, open within the proof's ten-minute lifetime using
npm run worker:open:staging. The opener re-verifies every signed artifact against the current live head and burns the proof before Wrangler starts; a failure requires fresh evidence. The first tightly capped Base Sepolia open may defer its funded canary once. Every later staging open and every production review requires a verified paid-admission artifact.
There is no funded public-chain evidence or independent security audit in the repository today. Those remain launch gates, not implied results.
A successful admission does not guarantee response delivery. Protected-origin dispatch irrevocably consumes the credential because the application may execute without returning a response. The signed receipt proves consumption while the result may be unknown; later timeout, transport, body-stream, or client-delivery failure is not replayed or automatically refunded.