{"_id":"@ackrate/ap2","_rev":"4-276836b428344cae384254e57500a222","name":"@ackrate/ap2","dist-tags":{"latest":"0.4.0"},"versions":{"0.3.0":{"name":"@ackrate/ap2","version":"0.3.0","keywords":["ap2","stellar","soroban","ackrate","intent-mandate","agent-payments","ai-agents"],"license":"Apache-2.0","_id":"@ackrate/ap2@0.3.0","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":"868ce26090947ab29cf4f442fd9faf959c791315","tarball":"https://registry.npmjs.org/@ackrate/ap2/-/ap2-0.3.0.tgz","fileCount":10,"integrity":"sha512-Oj8Nowjh6X5FybTnRJqU/wbM8s1fZQUeuaTz8OpEfjQT+cR1O3iuEFAaCVJBQZhpeMOiitfkU+UXBbor6TndHw==","signatures":[{"sig":"MEUCIBFsJbKo2i//nxTIeWMz95N0QaGBc3JO544eGl/XMT77AiEAjr+G+SYU3/vszL+oZzwq/SPU40jlWH5YjxmM9PVp8vs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37209},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"dd5e43133a11e178e220640a73defa9e8d96a048","scripts":{"test":"node --import tsx --test src/index.test.ts src/validator.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/ap2"},"_npmVersion":"11.16.0","description":"Signed AP2 mandate validation and bridging for ackrate contract-enforced Stellar payments.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.3.1","@stellar/stellar-sdk":"^14.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/ap2_0.3.0_1785558087165_0.9217479646440498","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@ackrate/ap2","version":"0.3.1","keywords":["ap2","stellar","soroban","ackrate","intent-mandate","agent-payments","ai-agents"],"license":"Apache-2.0","_id":"@ackrate/ap2@0.3.1","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":"dfd7e5928fdb251c33e1d58bf24ad7c2c7be1d5f","tarball":"https://registry.npmjs.org/@ackrate/ap2/-/ap2-0.3.1.tgz","fileCount":10,"integrity":"sha512-t2PZq0Yfiw2/dDmXgEHhl9ZTCeuUlB5pzpDtextjhdNF+KuoFEps9P5IBCeohR8S7V9+jGbOzcs6s4K00sCEoA==","signatures":[{"sig":"MEUCIQCMMHqszk5ABu8ZrHL52HgS1CzQOyRGIcXQuB3kblalzAIgXQE20+gS7ejbswFMQnsow0qCBUiAxEGSBWjgU+3XXdE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45828},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","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/ap2"},"_npmVersion":"11.16.0","description":"Signed AP2 mandate validation and binding for ackrate contract-enforced Stellar payments.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.3.2","@stellar/stellar-sdk":"^14.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/ap2_0.3.1_1785641037134_0.8785486689812037","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@ackrate/ap2","version":"0.3.2","keywords":["ap2","stellar","soroban","ackrate","intent-mandate","agent-payments","ai-agents"],"license":"Apache-2.0","_id":"@ackrate/ap2@0.3.2","maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"homepage":"https://github.com/ackrate/ackrate-protocol/tree/main/packages/ap2#readme","bugs":{"url":"https://github.com/ackrate/ackrate-protocol/issues"},"dist":{"shasum":"b8e55efc3c3e45b9824d424fa5e7edbbecf9c804","tarball":"https://registry.npmjs.org/@ackrate/ap2/-/ap2-0.3.2.tgz","fileCount":18,"integrity":"sha512-VGL32AixCUas15j/EPz3YtHSQO3y+4UJflAYabF1Xej0Ivyh0opRn0XnBB97Iw0UK2z5RbgmbKAYjx/vzXxgAQ==","signatures":[{"sig":"MEUCIBxBvJ5AStNzjmQWyBvG4AN5PusVkgjzB1aRn4r0cN+SAiEA3Psy4NWBQCLkC9Kluipgljn67plkhi6moJ5U+NPvgzQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75733},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"76dcd1ed93729dc54a87a253dc272ee4915addef","scripts":{"test":"node --import tsx --test src/index.test.ts src/validator.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/ap2"},"_npmVersion":"11.16.0","description":"Signed AP2 v0.1 Ackrate profile validator and IntentMandate bridge for contract-enforced Stellar payments.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"buffer":"6.0.3","@ackrate/core":"^0.3.3","@stellar/stellar-sdk":"^14.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/ap2_0.3.2_1787742855541_0.19282908782574504","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@ackrate/ap2","version":"0.4.0","description":"Signed AP2 intent validation and mandate bridge for ACKRATE contract-enforced USDC payments on Stellar Mainnet.","repository":{"type":"git","url":"git+https://github.com/ackrate/ackrate-protocol.git","directory":"packages/ap2"},"homepage":"https://github.com/ackrate/ackrate-protocol/tree/main/packages/ap2#readme","bugs":{"url":"https://github.com/ackrate/ackrate-protocol/issues"},"keywords":["ap2","stellar","soroban","ackrate","intent-mandate","agent-payments","ai-agents"],"type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.json","test":"node --import tsx --test src/index.test.ts src/validator.test.ts"},"dependencies":{"@ackrate/core":"^0.4.0","@stellar/stellar-sdk":"16.3.0","buffer":"6.0.3"},"license":"Apache-2.0","publishConfig":{"access":"public"},"engines":{"node":">=22.0.0"},"_id":"@ackrate/ap2@0.4.0","_integrity":"sha512-NB2KZwacCcTY/wLPF/QagHkr7sW88RDCCrdgNKiA0ajBazbZRog9jgn1K7gqHMzAjiyQuPI1RUBTPDfS9OpTGg==","_resolved":"/var/folders/t0/nkfkv7xj1bx7njmf7_mb7nhh0000gn/T/ackrate-verified-candidates-oWZbx4/ackrate-ap2-0.4.0.tgz","_from":"file:/var/folders/t0/nkfkv7xj1bx7njmf7_mb7nhh0000gn/T/ackrate-verified-candidates-oWZbx4/ackrate-ap2-0.4.0.tgz","_nodeVersion":"26.3.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-NB2KZwacCcTY/wLPF/QagHkr7sW88RDCCrdgNKiA0ajBazbZRog9jgn1K7gqHMzAjiyQuPI1RUBTPDfS9OpTGg==","shasum":"6acad2ee12c79d125f951b4d03f5e47b878d66ed","tarball":"https://registry.npmjs.org/@ackrate/ap2/-/ap2-0.4.0.tgz","fileCount":18,"unpackedSize":77501,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCvFNy4rap23vOfMD25COlxZw7xUv2Bk/U/r0RIqxZo2wIgaQnDhtnqjzLb4G7guE9e9wBCy5WNK1Y9Xqf5feZgbec="}]},"_npmUser":{"name":"ackrate","email":"drewgonzales2021@gmail.com"},"directories":{},"maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ap2_0.4.0_1788729626711_0.19120887192742853"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-01T04:21:26.947Z","modified":"2026-09-06T21:20:27.084Z","0.3.0":"2026-08-01T04:21:27.299Z","0.3.1":"2026-08-02T03:23:57.270Z","0.3.2":"2026-08-26T11:14:15.687Z","0.4.0":"2026-09-06T21:20:26.841Z"},"bugs":{"url":"https://github.com/ackrate/ackrate-protocol/issues"},"license":"Apache-2.0","homepage":"https://github.com/ackrate/ackrate-protocol/tree/main/packages/ap2#readme","keywords":["ap2","stellar","soroban","ackrate","intent-mandate","agent-payments","ai-agents"],"repository":{"type":"git","url":"git+https://github.com/ackrate/ackrate-protocol.git","directory":"packages/ap2"},"description":"Signed AP2 intent validation and mandate bridge for ACKRATE contract-enforced USDC payments on Stellar Mainnet.","maintainers":[{"name":"ackrate","email":"drewgonzales2021@gmail.com"}],"readme":"# @ackrate/ap2 0.4.0\n\nSigned AP2 v0.1 intent admission for contract-enforced USDC payments on Stellar Mainnet.\n\n`@ackrate/ap2` turns the supported AP2 v0.1 `IntentMandate` subset into a\nversioned Stellar Ed25519 credential, validates it at mandate admission, and\nreturns the exact Ackrate mandate that must be registered on-chain. The validator\nchecks the signature, trusted user, merchant scope, amount, expiry, binding\nhash, and one-time admission replay state.\n\nThis is deliberately a narrow **Ackrate profile for AP2 v0.1**, not a universal\nverifier for every upstream AP2 VC or JWS format. It has no HTTP or x402\ndependency, so later AP2 or x402 wire changes can be handled by adapters without\nredesigning `MandateRegistry`.\n\n## Mainnet contract\n\nRegistered mandates use\n[`CCLZEBJXG4YVJEPBCR5F27N733BCK5HQJWZZGB3K54JVODY3VAGP4HWR`](https://stellar.expert/explorer/public/contract/CCLZEBJXG4YVJEPBCR5F27N733BCK5HQJWZZGB3K54JVODY3VAGP4HWR)\nthrough `@ackrate/core` and its official `ackrate.mainnet` configuration.\nAP2 is a protocol bridge: it does not maintain a second network configuration,\nreceive token allowances, or move funds itself. Authorized contract upgrades\nreplace the implementation at this same address; compatibility and release\nevidence must still be checked when the implementation changes.\n\n## Installation\n\nVersion **0.4.0** requires\n**Node.js 22+**, core **0.4.0**, and exact `@stellar/stellar-sdk@16.3.0`.\nThe AP2 protocol profile remains v0.1; this package update does not change it.\n\nInstall the pinned set with:\n\n```bash\nnpm install --save-exact @ackrate/ap2@0.4.0 @ackrate/core@0.4.0 @stellar/stellar-sdk@16.3.0\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## Signed validator quick start\n\nThe example authorizes real USDC. Obtain the user's approval of the seller,\nbudget, and expiry before signing or submitting. `USER_KEY` and `AGENT_KEY` are\nsecurely managed Stellar `Keypair` objects; never put their secrets in source or\nlogs. `paymentJournal` and `saveMandate` are durable application storage.\n\n```ts\nimport {\n  InMemoryAp2ReplayStore,\n  createAp2ComplianceValidator,\n  signAp2Mandate,\n} from \"@ackrate/ap2\";\nimport { ackrate } from \"@ackrate/core\";\n\nconst credential = signAp2Mandate({\n  intent: {\n    user_cart_confirmation_required: false,\n    natural_language_description: \"Buy one research dataset\",\n    merchants: [MERCHANT_ADDRESS],\n    intent_expiry: new Date((Math.floor(Date.now() / 1000) + 3600) * 1000).toISOString(),\n  },\n  stellar: {\n    user: USER_KEY.publicKey(),\n    agent: AGENT_KEY.publicKey(),\n    asset: ackrate.mainnet.settlementAsset.contractId,\n    maxAmount: \"0.03\",\n  },\n}, USER_KEY);\n\nconst validator = createAp2ComplianceValidator({\n  replayStore: new InMemoryAp2ReplayStore(), // development only\n  replayNamespace: `stellar-mainnet:${ackrate.mainnet.mandateRegistryId}`,\n});\n\nconst accepted = await validator.validateAndConsume({\n  credential,\n  expectedUser: USER_KEY.publicKey(), // trusted session/account identity\n  merchant: MERCHANT_ADDRESS,         // trusted endpoint configuration\n  amount: \"0.01\",                    // semantic amount, not a wire-format claim\n});\n\nawait ackrate.registerMandate(accepted.binding.mandate, { signer: USER_KEY });\nawait saveMandate(accepted.binding.mandate); // Retain the returned on-chain ID.\nawait ackrate.approveBudget(accepted.binding.mandate, { signer: USER_KEY });\nawait ackrate.agent({ mandate: accepted.binding.mandate, signer: AGENT_KEY }).pay(\"0.01\", {\n  onPrepared: (pending) => paymentJournal.save(pending),\n});\n```\n\n`expectedUser`, `merchant`, and `amount` must come from trusted application\nstate. The validator never authorizes a payment from untrusted HTTP fields.\nThe user's USDC allowance goes to the registry, never the agent or AP2 package.\nThe budget is not deposited upfront; XLM pays network transaction fees.\n\n## Replay semantics\n\n`validateAndConsume` consumes a mandate hash once at signed-mandate admission or\nregistration. It is **not** called before every purchase: an Ackrate mandate is\nintentionally multi-use.\n\nAfter admission, every payment still goes through\n`MandateRegistry.execute_payment`. The contract atomically enforces the stored\nmerchant, cumulative budget, expiry, agent authorization, and monotonic\nsequence. The SDK and this validator are untrusted infrastructure; neither can\nbypass the on-chain money path.\n\n`InMemoryAp2ReplayStore` is only for tests, demos, and one-process development.\nProduction must provide a durable, shared, linearizable `consumeOnce(record)`\nimplementation. A store error or unsupported result fails closed.\n\n```ts\nimport type { Ap2ReplayStore } from \"@ackrate/ap2\";\n\nconst replayStore: Ap2ReplayStore = {\n  async consumeOnce(record) {\n    // Atomically insert record.key with a uniqueness constraint.\n    // Return \"consumed\" only for the winning insert, otherwise \"duplicate\".\n    return durableAtomicInsert(record);\n  },\n};\n```\n\n## What is signed\n\n`signAp2Mandate` first runs the same fail-closed AP2-to-Ackrate binding used by\n`bindIntentMandate`. The credential contains:\n\n- exact credential, AP2, data-key, binding, and signature algorithm versions;\n- the normalized one-merchant AP2 intent;\n- the Stellar user, agent, asset, maximum amount, decimals, and binding nonce;\n- the recomputed Ackrate mandate hash; and\n- a canonical 64-byte Stellar Ed25519 signature.\n\nThe signature is over a SHA-256 digest with the fixed\n`ACKRATE\\0AP2\\0SIGNED-MANDATE\\0V1\\0` domain, all version identifiers, the SHA-256\nof the full canonical credential payload, and the 32-byte mandate hash. The\npayload hash also binds client interpretation fields such as token decimals,\neven when they are not part of the core mandate id. The user public key is taken\nfrom the signed payload and must equal the separately trusted `expectedUser`;\nan attacker cannot authorize their own self-signed replacement.\n\nThe validator rejects unknown keys at every credential level. That is\nintentional: if a later AP2 version adds a constraint this implementation does\nnot understand, it fails closed instead of silently dropping the field.\n\n## Supported AP2 subset\n\nThe profile is pinned to [AP2 v0.1.0](https://github.com/google-agentic-commerce/AP2/releases/tag/v0.1.0)\nand its sample [`IntentMandate` data shape](https://github.com/google-agentic-commerce/AP2/blob/v0.1.0/src/ap2/types/mandate.py).\n\n| AP2 field | Ackrate behavior |\n|---|---|\n| `user_cart_confirmation_required` | Must be explicitly `false`; cart-confirmation state is not enforced by the contract. |\n| `natural_language_description` | Canonically bound into `intentHash`; evidence, not contract policy. |\n| `merchants` | Exactly one valid Stellar address; becomes the contract-enforced merchant scope. |\n| `intent_expiry` | Future ISO 8601 timestamp with timezone and whole-second precision; the signed credential stores canonical UTC. |\n| `skus` | Absent or empty because `MandateRegistry` does not enforce SKU constraints. |\n| `requires_refundability` | Absent or `false` because `MandateRegistry` does not enforce refundability. |\n\n## Binding algorithm\n\nThe bridge normalizes the supported AP2 fields, recursively sorts JSON object\nkeys, and computes:\n\n```text\nintent_hash = SHA-256(canonical AP2 JSON)\ncore_nonce  = \"ackrate-ap2/1:\" + intent_hash + \":\" + binding_nonce\nvc_hash     = existing @ackrate/core mandate hash, including core_nonce\n```\n\nThe default binding nonce comes from Web Crypto. Supply `stellar.nonce` only\nfor reproducible test vectors. Existing non-AP2 mandate ids and core field\nordering are unchanged.\n\n## Errors\n\n`validateAndConsume` throws `Ap2ValidationError` with a stable `code`:\n\n| Code | Meaning |\n|---|---|\n| `INVALID_CREDENTIAL` | Malformed, unknown, noncanonical, or invalid identity data. |\n| `UNSUPPORTED_VERSION` | Credential, AP2, data-key, binding, or signature version is unsupported. |\n| `INVALID_SIGNATURE` | Signature encoding or Ed25519 verification failed. |\n| `SIGNER_MISMATCH` | Signed user differs from trusted `expectedUser`. |\n| `BINDING_MISMATCH` | Payload does not recompute to the envelope mandate hash. |\n| `MERCHANT_MISMATCH` | Requested merchant is outside signed scope. |\n| `INVALID_AMOUNT` | Amount is zero, negative, malformed, over-precision, or outside i128. |\n| `AMOUNT_EXCEEDS_MANDATE` | Requested amount is greater than the signed maximum. |\n| `EXPIRED` | Expiry is equal to or earlier than the trusted clock. |\n| `REPLAYED` | The same mandate hash was already admitted in this namespace. |\n| `REPLAY_STORE_UNAVAILABLE` | Atomic replay storage failed or returned an invalid result. |\n\n## API\n\n| Export | Purpose |\n|---|---|\n| `signAp2Mandate(input, signer)` | Bind and sign the supported AP2 intent with the Stellar user key. |\n| `createAp2ComplianceValidator(options)` | Create the signature/scope/amount/expiry/replay validator with an injected store and clock. |\n| `Ap2ValidationError` | Typed fail-closed error with stable codes. |\n| `InMemoryAp2ReplayStore` | Single-process development and test replay store. |\n| `bindIntentMandate(input)` | Validate and bind without producing a signed envelope. |\n| `normalizeAp2Intent(intent)` | Normalize the exact enforceable AP2 subset. |\n| `canonicalizeJson(value)` | Deterministic recursively key-sorted JSON for binding evidence. |\n\nTypeScript declarations also expose the credential, validator input/result,\nreplay-store, intent, binding, and authorization interfaces.\n\n## Verification\n\n```bash\nnpm run build -w @ackrate/ap2\nnpm run test -w @ackrate/ap2\n```\n\nThe package's binding/vector and validator tests cover valid credentials,\ntampering, version boundaries, malformed\nsignatures, trusted signer and merchant scope, exact amount limits, overspend,\nexpiry, replay, 100-way concurrent admission, store outages, replay poisoning,\nand namespace isolation.\n\n## Configuration and recovery\n\nThe [canonical Mainnet configuration](https://github.com/ackrate/ackrate-protocol/blob/main/packages/stellar/src/deployments.ts)\nand [contract deployment record](https://github.com/ackrate/ackrate-protocol-contracts/blob/main/contracts/mainnet-v2/README.md)\ntie the coordinated packages to the registry above. Core uses that Mainnet\nconfiguration by default; AP2 adds signed intent admission, not another network.\n\nIf a submitted payment is uncertain, preserve its exact prepared transaction\nhash and reconcile it with Core. Do not sign a new intent or pay again to recover\nan existing purchase. See the [Core recovery workflow](https://github.com/ackrate/ackrate-protocol/blob/main/packages/sdk/README.md#recover-the-original-purchase).\n\nApache-2.0.\n","readmeFilename":"README.md"}