{"_id":"@ackrate/express-middleware","_rev":"4-1d9ee73d5ad89e8f857ee6b637cab94c","name":"@ackrate/express-middleware","dist-tags":{"latest":"0.3.0"},"versions":{"0.2.2":{"name":"@ackrate/express-middleware","version":"0.2.2","keywords":["ackrate","express","middleware","x402","stellar","soroban","agent-payments","payment-verification"],"license":"Apache-2.0","_id":"@ackrate/express-middleware@0.2.2","maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"homepage":"https://github.com/reapp-protocol/ackrate-research-arena#readme","bugs":{"url":"https://github.com/reapp-protocol/ackrate-research-arena/issues"},"dist":{"shasum":"85aff2262ee85d7e0a605c3fc8e997cc4648a202","tarball":"https://registry.npmjs.org/@ackrate/express-middleware/-/express-middleware-0.2.2.tgz","fileCount":18,"integrity":"sha512-a4fffyGG4MF8Zyi3RBwF8Z0YtDoXl2iooWh4jUcAw5GOBsj+SAIf+TA7zkoptzIgHoWXPJdydUrvAYD0M3JFLw==","signatures":[{"sig":"MEQCIDJ570qs6Ls96dyd+AvefToRmR7X3Pnjmg2ajDd4uCStAiAT2VP0nD1qkyiXle6DqjYEQPNzjQAxuAT0Ib0j0ougag==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70249},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"dd5e43133a11e178e220640a73defa9e8d96a048","scripts":{"test":"node --import tsx --test src/middleware.test.ts src/bound.test.ts src/bound-route.test.ts src/verification.test.ts","build":"tsc -p tsconfig.json"},"_npmUser":{"name":"ackrate","email":"drewgonzales2021@gmail.com"},"repository":{"url":"git+https://github.com/reapp-protocol/ackrate-research-arena.git","type":"git","directory":"packages/express-middleware"},"_npmVersion":"11.16.0","description":"Fail-closed Express middleware for ackrate agent-payment APIs with independent settlement verification.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.3.1","@ackrate/stellar":"^0.2.2","@stellar/stellar-sdk":"^14.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"express":"^5.2.1","typescript":"^5.7.2","@types/node":"^22.10.2","@types/express":"^5.0.6"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-middleware_0.2.2_1785558106000_0.46404338489609565","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@ackrate/express-middleware","version":"0.2.3","keywords":["ackrate","express","middleware","x402","stellar","soroban","agent-payments","payment-verification"],"license":"Apache-2.0","_id":"@ackrate/express-middleware@0.2.3","maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"homepage":"https://github.com/reapp-protocol/ackrate-research-arena#readme","bugs":{"url":"https://github.com/reapp-protocol/ackrate-research-arena/issues"},"dist":{"shasum":"41b749aa57d38b765880e8af461d533583b6ea36","tarball":"https://registry.npmjs.org/@ackrate/express-middleware/-/express-middleware-0.2.3.tgz","fileCount":18,"integrity":"sha512-L0iWlnUn78uCRS+QO3txCECkG/YuK8fu9Lv9lFa+KasG0f2RBV79yqobzelXm9q201VpjEs1p+i6IPp1EI2ghQ==","signatures":[{"sig":"MEYCIQCK7zCXdvn9oOAVM03EroJug/Ykt8PiTEdD2WjW8lB24gIhAO+1wx5BnlQ+HL6Ya93VDb/ZKInByJ9GJKBDL4xhRaZr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76592},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"0e0d1a2c01c73310ab4aa47ff2c84b1e0dc46e8d","_npmUser":{"name":"ackrate","email":"drewgonzales2021@gmail.com"},"repository":{"url":"git+https://github.com/reapp-protocol/ackrate-research-arena.git","type":"git","directory":"packages/express-middleware"},"_npmVersion":"11.16.0","description":"Fail-closed Express middleware for ackrate x402 APIs with independent on-chain settlement verification.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.3.2","@ackrate/stellar":"^0.2.3","@stellar/stellar-sdk":"^14.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-middleware_0.2.3_1785641039843_0.7091012402253074","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@ackrate/express-middleware","version":"0.2.4","keywords":["ackrate","express","middleware","x402","stellar","soroban","agent-payments","payment-verification"],"license":"Apache-2.0","_id":"@ackrate/express-middleware@0.2.4","maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"homepage":"https://github.com/ackrate/ackrate-protocol/tree/main/packages/express-middleware#readme","bugs":{"url":"https://github.com/ackrate/ackrate-protocol/issues"},"dist":{"shasum":"f5ec037e0e5ad35201a24258370c66806a5caedf","tarball":"https://registry.npmjs.org/@ackrate/express-middleware/-/express-middleware-0.2.4.tgz","fileCount":34,"integrity":"sha512-TVMoSb9OFgHFc8iMnVyNHAMTxCFOuDHvgSkknLRb96EQLpYIdVDCfSKl5gDFPcRVV8ZqLOz14iuGT0O6a3rCNA==","signatures":[{"sig":"MEQCIFYww9s0HjNa//QkKmt3SE6aRVHewbTfRuEgtDGscFUBAiArTRSjGFDpXZrSbUCd09Az7cYemt/rBBGQzG53Ru015g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCHt/SSbI7NrpCqEFbkymRyPwzIm1SvnlqPmPMFMGRWKAIhAIlrOhgiRBZisNIgeRFygkOh+VwLK5urnxpgLk/xL0QM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":135074},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"76dcd1ed93729dc54a87a253dc272ee4915addef","scripts":{"test":"node --import tsx --test src/middleware.test.ts src/bound.test.ts src/bound-route.test.ts src/verification.test.ts","build":"tsc -p tsconfig.json"},"_npmUser":{"name":"ackrate","email":"drewgonzales2021@gmail.com"},"repository":{"url":"git+https://github.com/ackrate/ackrate-protocol.git","type":"git","directory":"packages/express-middleware"},"_npmVersion":"11.16.0","description":"Fail-closed Express middleware for Ackrate x402 APIs with independent on-chain settlement verification.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.3.3","@ackrate/stellar":"^0.2.4","@stellar/stellar-sdk":"^14.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"express":"^5.2.1","typescript":"^5.7.2","@types/node":"^22.10.2","@types/express":"^5.0.6"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/express-middleware_0.2.4_1787742930407_0.6066790896570975","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"_id":"@ackrate/express-middleware@0.3.0","bugs":{"url":"https://github.com/ackrate/ackrate-protocol/issues"},"dist":{"shasum":"528a369748ebce4ca7c02303d09745430f92ee4e","tarball":"https://registry.npmjs.org/@ackrate/express-middleware/-/express-middleware-0.3.0.tgz","fileCount":34,"integrity":"sha512-mv2y8tAszijsqUtQ7evMPkX8BpnF0CdE34dKBu7u4A3VGQ53xv+rwlCY8pdy4iEl8K+kjNs7rIzSYJ9Vdp4NCw==","signatures":[{"sig":"MEUCIGZ4E4VaA/lA8N9V8xYGnWVMBHAg9sTQXAWe3hV4kTB+AiEA3Jw2zzfbP20vsU4Sdk0esWDFRrbhToKqZCN/L4KRbTc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDdQ9eG1vsfUCODfUZWqTfPtEBBfM8LfoMobvzRh7QhKAIgXQIQenB3njJH3WzCJAiDsLPdvTjlR6zazjpolR4VFxI="}],"unpackedSize":143068},"main":"./dist/index.js","name":"@ackrate/express-middleware","type":"module","_from":"file:/var/folders/t0/nkfkv7xj1bx7njmf7_mb7nhh0000gn/T/ackrate-verified-candidates-oWZbx4/ackrate-express-middleware-0.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"license":"Apache-2.0","scripts":{"test":"node --import tsx --test src/middleware.test.ts src/bound.test.ts src/bound-route.test.ts src/verification.test.ts","build":"tsc -p tsconfig.json"},"version":"0.3.0","_npmUser":{"name":"ackrate","email":"drewgonzales2021@gmail.com"},"homepage":"https://github.com/ackrate/ackrate-protocol/tree/main/packages/express-middleware#readme","keywords":["ackrate","express","middleware","x402","stellar","soroban","agent-payments","payment-verification"],"_resolved":"/var/folders/t0/nkfkv7xj1bx7njmf7_mb7nhh0000gn/T/ackrate-verified-candidates-oWZbx4/ackrate-express-middleware-0.3.0.tgz","_integrity":"sha512-mv2y8tAszijsqUtQ7evMPkX8BpnF0CdE34dKBu7u4A3VGQ53xv+rwlCY8pdy4iEl8K+kjNs7rIzSYJ9Vdp4NCw==","repository":{"url":"git+https://github.com/ackrate/ackrate-protocol.git","type":"git","directory":"packages/express-middleware"},"_npmVersion":"11.16.0","description":"ACKRATE x402 middleware for Stellar Mainnet USDC APIs with independent MandateRegistry settlement verification.","directories":{},"maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.4.0","@types/express":"^5.0.6","@ackrate/stellar":"^0.3.0","@stellar/stellar-sdk":"16.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"express":"^5.2.1","typescript":"^5.7.2","@types/node":"^22.10.2"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/express-middleware_0.3.0_1788729724734_0.03246502713120858"}}},"time":{"created":"2026-08-01T04:21:45.746Z","modified":"2026-09-06T21:22:04.948Z","0.2.2":"2026-08-01T04:21:46.139Z","0.2.3":"2026-08-02T03:23:59.982Z","0.2.4":"2026-08-26T11:15:30.490Z","0.3.0":"2026-09-06T21:22:04.813Z"},"bugs":{"url":"https://github.com/ackrate/ackrate-protocol/issues"},"license":"Apache-2.0","homepage":"https://github.com/ackrate/ackrate-protocol/tree/main/packages/express-middleware#readme","keywords":["ackrate","express","middleware","x402","stellar","soroban","agent-payments","payment-verification"],"repository":{"url":"git+https://github.com/ackrate/ackrate-protocol.git","type":"git","directory":"packages/express-middleware"},"description":"ACKRATE x402 middleware for Stellar Mainnet USDC APIs with independent MandateRegistry settlement verification.","maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"readme":"# @ackrate/express-middleware 0.3.0\n\nPaid JSON routes for Express 4/5, settled in USDC on Stellar Mainnet.\n\nThe package authenticates an exact-origin GET challenge, verifies the on-chain\nsettlement independently, atomically claims fulfillment, stores the exact JSON\nresult before sending it, and replays those bytes on recovery. A settlement can\nnever re-run arbitrary fulfillment work.\n\n## Mainnet contract\n\nThe merchant verifies payments against\n[`CCLZEBJXG4YVJEPBCR5F27N733BCK5HQJWZZGB3K54JVODY3VAGP4HWR`](https://stellar.expert/explorer/public/contract/CCLZEBJXG4YVJEPBCR5F27N733BCK5HQJWZZGB3K54JVODY3VAGP4HWR),\nusing the official `MAINNET` configuration from `@ackrate/stellar`.\nThis middleware never signs a consumer payment or receives the user's allowance.\nThe registry enforces the mandate; the merchant verifies the resulting settlement.\nAuthorized upgrades replace the registry implementation at the same contract\naddress. Re-check implementation compatibility and release evidence after upgrades.\n\n## Installation\n\nVersion **0.3.0** requires\n**Node.js 22+**, core **0.4.0**, Stellar binding **0.3.0**, and exact\n`@stellar/stellar-sdk@16.3.0`.\n\nInstall with:\n\n```bash\nnpm install --save-exact @ackrate/express-middleware@0.3.0 @ackrate/stellar@0.3.0 @stellar/stellar-sdk@16.3.0 express@5.2.1\n```\n\nSee the [coordinated release status](https://github.com/ackrate/ackrate-protocol/blob/main/docs/ackrate-sdk-npm.md)\nfor publication and clean-install verification.\n\n## Safe paid route\n\n`redemptionStore` is your shared durable `BoundRedemptionStore` implementation.\n`loadResearchOnce` represents application fulfillment. Configure a funded public\nread-source address, your merchant address, HTTPS origin, and a private challenge\nkey through your deployment's secret manager.\n\n```ts\nimport express from \"express\";\nimport { MAINNET } from \"@ackrate/stellar\";\nimport {\n  createBoundAckratePaidJsonRoute,\n} from \"@ackrate/express-middleware\";\n\nconst app = express();\n\nconst paidResearch = createBoundAckratePaidJsonRoute({\n  networkConfig: MAINNET,\n  network: \"stellar-mainnet\",\n  asset: MAINNET.settlementAsset.contractId,\n  decimals: MAINNET.settlementAsset.decimals,\n  merchant: process.env.ACKRATE_MERCHANT_ADDRESS!,\n  sourceAccount: process.env.ACKRATE_READ_SOURCE_ADDRESS!,\n  audience: \"https://api.example\", // exact public origin; never Host-derived\n  challengeSecret: process.env.ACKRATE_CHALLENGE_SECRET!, // at least 32 bytes\n  amount: \"0.01\", // USDC; callers authorize their own mandate and budget.\n  resource: (request) => request.originalUrl,\n  redemptionStore,\n}, async ({ request, payment }) => ({\n  body: {\n    ok: true,\n    resource: request.params.id,\n    data: await loadResearchOnce(request.params.id),\n    settledTx: payment.txHash,\n  },\n}));\n\napp.get(\"/source/:id\", paidResearch);\napp.listen(4021);\n```\n\nThe fulfillment callback receives no Express `Response` and cannot stream. Its\nJSON result is bounded, hashed, and committed to the same redemption store\nbefore any bytes are written to the client.\n\n## Bound-v2 authorization\n\nBefore fulfillment is claimed, the package requires:\n\n1. `ACKRATE-PAYMENT-CAPABILITIES: ackrate-bound-v2`; older clients receive `426`\n   before payment.\n2. An HMAC-authenticated challenge binding the exact public origin, GET method,\n   path and query, network identity, registry, merchant, asset, amount, decimals,\n   random id, and first-redemption deadline.\n3. A canonical proof whose Stellar Ed25519 signature binds that challenge,\n   transaction hash, and mandate id to the chain-derived mandate agent.\n4. The configured RPC's exact network passphrase and a successful fresh\n   transaction.\n5. One unambiguous payment event from the configured MandateRegistry.\n6. Current mandate user, agent, merchant, and asset identities.\n7. One matching same-transaction SEP-41 transfer from user to merchant.\n\nA copied public transaction hash cannot unlock data. Relaying a genuine quote\nthrough another origin fails before the client pays because the signed audience\nmust equal the requested URL origin.\n\n## Atomic fulfillment state\n\n`BoundRedemptionStore` owns settlement binding and immutable response bytes in\none linearizable state machine:\n\n```text\nmissing -> executing -> completed(exact JSON bytes)\n```\n\n- First valid proof: chain verification, atomic claim, one callback execution.\n- Same proof while executing: `503`; the callback is never started again.\n- Same proof after completion: exact stored bytes are replayed; no verifier or\n  callback runs.\n- Same transaction with another proof: `409`.\n- Store/RPC outage: `503`; no protected result is sent.\n- Callback exception: one sanitized terminal JSON result is stored and replayed.\n- Completion-store failure: no result bytes are sent and the claim remains\n  executing; recovery cannot re-run it automatically. After confirming the\n  execution owner is dead, trusted operator/outbox code calls\n  `resolveBoundAckrateInterruptedDelivery` to store one terminal result.\n\nThe first-redemption deadline does not prevent later replay of an already\ncompleted exact result. That replay is delivery recovery, not fresh payment\nauthorization.\n\n## Store deployment boundary\n\n`InMemoryBoundRedemptionStore` is only for one-process demos and tests.\n`FileBoundRedemptionStore` in the reference fulfillment app is restart-safe for\none Node.js process; instances targeting the same normalized path share one\nin-process queue and use fsynced atomic replacement. It is not multi-process or\nmulti-host storage.\n\nA production deployment must implement `BoundRedemptionStore.lookup`, `claim`,\nand `complete` in one shared durable linearizable database. Never add a lease\nthat silently turns an executing claim back into runnable work. Side effects\nmust be transactionally coordinated with the claim through a durable job/outbox.\n\n## Response behavior\n\n| Condition | Status |\n|---|---:|\n| Missing/wrong bound-v2 capability | `426` before payment |\n| Method other than GET | `405` |\n| Missing, malformed, expired-first-use, mismatched, or unverified proof | `402` |\n| Same settlement with a different proof | `409` |\n| Existing execution or infrastructure/store outage | `503`, retry exact proof |\n| New completed fulfillment | stored 2xx JSON |\n| Exact completed recovery | byte-identical stored 2xx JSON |\n\nAll responses are private/no-store. Proof and stored result material are\nsensitive and must not be logged or exposed.\n\n## Primary API\n\n### `createBoundAckratePaidJsonRoute(options, fulfill)`\n\nRequired options:\n\n| Option | Meaning |\n|---|---|\n| `merchant` | Stellar address that must receive the verified transfer. |\n| `amount` | Decimal price or request-specific resolver. |\n| `audience` | Exact configured public HTTP(S) origin or safe resolver. |\n| `challengeSecret` | Stable private 32–4096 byte challenge key. |\n| `redemptionStore` | Atomic claim/result store shared by all serving workers. |\n\nOptional controls include `resource`, `asset`, `networkConfig`, `network`,\n`decimals`, `sourceAccount`, verifier/polling/freshness/header limits,\n`challengeTtlSeconds`, development-only HTTP RPC, and `maxResponseBytes`.\n\nRuntime exports include `createBoundAckratePaidJsonRoute`,\n`resolveBoundAckrateInterruptedDelivery`, `InMemoryBoundRedemptionStore`,\n`createStellarPaymentVerifier`, strict event\nselection helpers, and all TypeScript store/evidence/result types.\n\nThe low-level bound authorization middleware is intentionally not exported from the\npackage root; public paid endpoints use the result-storing route wrapper.\n\n## Wire-format isolation\n\nx402 and AP2 evolve outside the MandateRegistry. HTTP/profile adapters may\nchange without changing contract storage or weakening `execute_payment`.\n\n## Configuration evidence\n\n- [Canonical Mainnet configuration](https://github.com/ackrate/ackrate-protocol/blob/main/packages/stellar/src/deployments.ts).\n- [Mainnet contract deployment, source, and original artifact](https://github.com/ackrate/ackrate-protocol-contracts/blob/main/contracts/mainnet-v2/README.md).\n- [Consumer payment and recovery workflow](https://github.com/ackrate/ackrate-protocol/blob/main/packages/sdk/README.md).\n\nApache-2.0.\n","readmeFilename":"README.md"}