{"_id":"@agnic/mandate-verifier","name":"@agnic/mandate-verifier","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@agnic/mandate-verifier","version":"0.1.0","description":"Offline verifier for Agnic Mandate IntentMandateTemplate and IntentMandateDerivation credentials (SD-JWT-VC, W3C Bitstring Status List 2023, did:web).","keywords":["agnic","mandate","intent","ap2","webauthn","sd-jwt","sd-jwt-vc","verifiable-credentials","w3c-vc","agent-commerce"],"homepage":"https://agnic.ai/mandate","repository":{"type":"git","url":"git+https://github.com/agnicpay/mandate-verifier-js.git"},"license":"MIT","author":{"name":"Agnic Labs","email":"hello@agnic.ai"},"type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./intent":{"types":"./dist/intent.d.ts","import":"./dist/intent.js"}},"engines":{"node":">=18"},"scripts":{"build":"tsc","prepublishOnly":"npm run build","typecheck":"tsc --noEmit"},"dependencies":{"jose":"^5.9.0"},"devDependencies":{"@types/node":"^20.11.0","typescript":"^5.3.3"},"_id":"@agnic/mandate-verifier@0.1.0","bugs":{"url":"https://github.com/agnicpay/mandate-verifier-js/issues"},"_nodeVersion":"24.10.0","_npmVersion":"11.6.1","dist":{"integrity":"sha512-TkvROOYx12/1ESzRmzySkWblvCgRQQMkljzGpWWIslWnjXT/PEel/7/E2h6Muvomq6uoC/gc5UaM5ILURTPCsw==","shasum":"5261bcaeb1e7d28d5de818425206db8a88cfe0df","tarball":"https://registry.npmjs.org/@agnic/mandate-verifier/-/mandate-verifier-0.1.0.tgz","fileCount":13,"unpackedSize":59048,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD3bXGJ0/zJutL2NJo2QovxoULFWyI0JFmIqOF3t62sqQIhAN26Wcf3qPsneI2ayfdaNvS/BpozuyrAaj0mGi9FgY5L"}]},"_npmUser":{"name":"agnic-ai","email":"agnicpay@gmail.com"},"directories":{},"maintainers":[{"name":"agnic-ai","email":"agnicpay@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mandate-verifier_0.1.0_1776952593191_0.8371373713278729"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-23T13:56:33.054Z","0.1.0":"2026-04-23T13:56:33.330Z","modified":"2026-04-23T13:56:33.615Z"},"maintainers":[{"name":"agnic-ai","email":"agnicpay@gmail.com"}],"description":"Offline verifier for Agnic Mandate IntentMandateTemplate and IntentMandateDerivation credentials (SD-JWT-VC, W3C Bitstring Status List 2023, did:web).","homepage":"https://agnic.ai/mandate","keywords":["agnic","mandate","intent","ap2","webauthn","sd-jwt","sd-jwt-vc","verifiable-credentials","w3c-vc","agent-commerce"],"repository":{"type":"git","url":"git+https://github.com/agnicpay/mandate-verifier-js.git"},"author":{"name":"Agnic Labs","email":"hello@agnic.ai"},"bugs":{"url":"https://github.com/agnicpay/mandate-verifier-js/issues"},"license":"MIT","readme":"# @agnic/mandate-verifier\n\nOffline verifier for **Agnic Mandate** credentials — the WebAuthn-signed AP2-compatible IntentMandate that proves a human user authorized an AI agent's purchase.\n\nMIT-licensed. Zero Agnic API calls at verify time. Ships as a tiny TypeScript package with one dependency (`jose`).\n\n## What you're verifying\n\nWhen an Agnic-enabled agent places an order on your site, the request carries two [SD-JWT-VC](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/) credentials:\n\n| Credential | Validity | Signed by | Contains |\n|---|---|---|---|\n| `IntentMandateTemplate` | 30 days | User's device passkey (WebAuthn) + Agnic | The user's standing scope: categories, max/tx, daily limit, merchant whitelist |\n| `IntentMandateDerivation` | 5 min | Agnic (scope-contained against template) | One specific transaction: merchant, cart hash, amount, the user's prompt |\n\nAs a merchant, you care about proving:\n1. The user's device really signed the template (legal non-repudiation)\n2. The derivation is a legitimate narrowing of the template (scope containment)\n3. The derivation matches the order you're about to fulfill\n\nThis library does all three in one call.\n\n## Install\n\n```bash\nnpm install @agnic/mandate-verifier\n```\n\n## Quick start\n\n```typescript\nimport { verifyIntentBundle } from '@agnic/mandate-verifier/intent';\n\n// In your /api/order (or /checkout) handler:\nconst header = req.headers.get('x-intent-mandate');\nif (!header) return reject('missing mandate');\n\nconst [templateSdJwt, derivationSdJwt] = header.split('~~');\n\nconst result = await verifyIntentBundle(templateSdJwt, derivationSdJwt, {\n  expectedMerchant: 'your-merchant-id',\n  expectedAmount: { value: '7.35', currency: 'CAD' },\n  expectedCategories: ['food_beverage'],\n});\n\nif (!result.valid) {\n  console.warn('intent verification failed', result.reasons);\n  // Decide: reject the order, or accept advisorily and log for disputes.\n}\n\n// Store these on your order row for chargeback defense:\nconst { template_jti, derivation_jti, template_claims, derivation_claims } = result;\n```\n\n## What gets checked\n\n`verifyIntentBundle` runs every check a merchant needs, and reports each one:\n\n```typescript\n{\n  valid: boolean,\n  template_jti: string,\n  derivation_jti: string,\n  checks: {\n    template_signature: boolean,       // issuer signature verified via did:web\n    derivation_signature: boolean,     // issuer signature verified via did:web\n    parent_match: boolean,             // derivation.parent_jti === template.jti\n    not_expired: boolean,              // neither credential past its exp\n    amount_in_scope: boolean,          // derivation.amount ≤ template.max_per_tx AND matches expectedAmount\n    merchant_in_scope: boolean,        // derivation.merchant allowed by template.merchant_whitelist AND matches expectedMerchant\n    categories_in_scope: boolean,      // derivation.categories ⊆ template.categories AND covers expectedCategories\n  },\n  reasons: string[],                   // human-readable failure reasons, empty when valid\n  template_claims: {...},              // raw claims, useful for chargeback bundle\n  derivation_claims: {...},\n}\n```\n\n### Step-up approvals\n\nIf the user faced an out-of-scope request, they complete a fresh WebAuthn ceremony and Agnic issues a derivation with `step_up: true` + `step_up_evidence`. For these, scope-containment against the parent template is *skipped* — the fresh assertion is stronger evidence than the template's prior grant. The verifier accepts this automatically; the `step_up_evidence` claim on the derivation (a WebAuthn assertion over `sha256(canonicalize(approval_context))`) is the authorization.\n\n## Just verifying a single credential\n\nIf you only need to verify one SD-JWT-VC (e.g. to inspect claims without the bundle context):\n\n```typescript\nimport { verifyCredential } from '@agnic/mandate-verifier';\n\nconst res = await verifyCredential(sdJwt);\nif (res.valid) {\n  console.log(res.claims, res.issuerDid, res.holderDid, res.vct);\n}\n```\n\n## Offline & cacheable\n\nThe verifier makes two HTTP calls, both to **public W3C-standard documents** on the issuer domain:\n\n- `GET https://{issuer}/.well-known/did.json` — issuer public key (DID Core)\n- `GET {statusListCredential}` — revocation bit vector (W3C Bitstring Status List 2023)\n\nBoth are static, cacheable, and served by the issuer. No authenticated Agnic API call happens at verification time. Agnic downtime does not block verification.\n\nCache both for 5 minutes and you pay roughly one HTTP round-trip per minute of throughput, regardless of mandate volume.\n\n## Spec compliance\n\n- **SD-JWT-VC** — [draft-ietf-oauth-sd-jwt-vc](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/)\n- **did:web** — [W3C DID Core](https://www.w3.org/TR/did-core/) + [did:web spec](https://w3c-ccg.github.io/did-method-web/)\n- **Revocation** — [W3C Bitstring Status List 2023](https://www.w3.org/TR/vc-bitstring-status-list/) (canonical); the older IETF SD-JWT-VC token-status-list draft shape is accepted as a legacy fallback for in-flight credentials\n- **Signature algorithm** — ES256 (P-256 ECDSA) with raw R||S signature bytes (IEEE P1363), JWS-compatible\n\nTested interop: Agnic's kya-service issuer, as of 2026-04-23.\n\n## Advanced options\n\n```typescript\nawait verifyCredential(sdJwt, {\n  issuerPublicKeyJwk: { /* JWK */ },  // skip did:web resolution\n  skipStatusCheck: true,              // skip revocation list\n  skipExpiryCheck: true,              // for chargeback analysis of expired creds\n  fetch: customFetch,                 // for testing or HTTP-proxy scenarios\n});\n```\n\n## License\n\nMIT. Copyright © 2026 Agnic Labs.\n\n## Links\n\n- Product: https://agnic.ai/mandate\n- Issuer source: https://github.com/agnicpay/kya-service (issuance is closed-source; **verification is MIT and lives here**)\n- Bugs / PRs: https://github.com/agnicpay/mandate-verifier-js\n","readmeFilename":"README.md","_rev":"1-4f43729c4d4170b8ca01d2bd462b146b"}