@agent-score/commerce 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +19 -17
  2. package/dist/challenge/index.d.mts +31 -3
  3. package/dist/challenge/index.d.ts +31 -3
  4. package/dist/challenge/index.js +25 -9
  5. package/dist/challenge/index.js.map +1 -1
  6. package/dist/challenge/index.mjs +25 -9
  7. package/dist/challenge/index.mjs.map +1 -1
  8. package/dist/{checkout-B-MIzYzW.d.ts → checkout-C4RD7M0Z.d.ts} +117 -13
  9. package/dist/{checkout-Bn7ZKIBD.d.mts → checkout-CzB9f_jf.d.mts} +117 -13
  10. package/dist/core.d.mts +40 -7
  11. package/dist/core.d.ts +40 -7
  12. package/dist/core.js +52 -27
  13. package/dist/core.js.map +1 -1
  14. package/dist/core.mjs +52 -27
  15. package/dist/core.mjs.map +1 -1
  16. package/dist/discovery/index.d.mts +33 -3
  17. package/dist/discovery/index.d.ts +33 -3
  18. package/dist/discovery/index.js +50 -16
  19. package/dist/discovery/index.js.map +1 -1
  20. package/dist/discovery/index.mjs +49 -16
  21. package/dist/discovery/index.mjs.map +1 -1
  22. package/dist/gate-D2RP6bZg.d.ts +307 -0
  23. package/dist/gate-GCXy4FHI.d.mts +307 -0
  24. package/dist/identity/express.d.mts +28 -1
  25. package/dist/identity/express.d.ts +28 -1
  26. package/dist/identity/express.js +714 -31
  27. package/dist/identity/express.js.map +1 -1
  28. package/dist/identity/express.mjs +710 -30
  29. package/dist/identity/express.mjs.map +1 -1
  30. package/dist/identity/fastify.d.mts +14 -2
  31. package/dist/identity/fastify.d.ts +14 -2
  32. package/dist/identity/fastify.js +727 -31
  33. package/dist/identity/fastify.js.map +1 -1
  34. package/dist/identity/fastify.mjs +723 -30
  35. package/dist/identity/fastify.mjs.map +1 -1
  36. package/dist/identity/hono.d.mts +28 -1
  37. package/dist/identity/hono.d.ts +28 -1
  38. package/dist/identity/hono.js +696 -33
  39. package/dist/identity/hono.js.map +1 -1
  40. package/dist/identity/hono.mjs +692 -32
  41. package/dist/identity/hono.mjs.map +1 -1
  42. package/dist/identity/nextjs.d.mts +5 -0
  43. package/dist/identity/nextjs.d.ts +5 -0
  44. package/dist/identity/nextjs.js +695 -30
  45. package/dist/identity/nextjs.js.map +1 -1
  46. package/dist/identity/nextjs.mjs +691 -29
  47. package/dist/identity/nextjs.mjs.map +1 -1
  48. package/dist/identity/policy.d.mts +21 -2
  49. package/dist/identity/policy.d.ts +21 -2
  50. package/dist/identity/policy.js +22 -1
  51. package/dist/identity/policy.js.map +1 -1
  52. package/dist/identity/policy.mjs +21 -1
  53. package/dist/identity/policy.mjs.map +1 -1
  54. package/dist/identity/web.d.mts +26 -1
  55. package/dist/identity/web.d.ts +26 -1
  56. package/dist/identity/web.js +695 -30
  57. package/dist/identity/web.js.map +1 -1
  58. package/dist/identity/web.mjs +691 -29
  59. package/dist/identity/web.mjs.map +1 -1
  60. package/dist/index.d.mts +165 -4
  61. package/dist/index.d.ts +165 -4
  62. package/dist/index.js +3103 -534
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +3086 -545
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/payment/index.d.mts +1 -1
  67. package/dist/payment/index.d.ts +1 -1
  68. package/dist/payment/index.js +10 -2
  69. package/dist/payment/index.js.map +1 -1
  70. package/dist/payment/index.mjs +10 -2
  71. package/dist/payment/index.mjs.map +1 -1
  72. package/dist/stripe-multichain/index.js +1614 -266
  73. package/dist/stripe-multichain/index.js.map +1 -1
  74. package/dist/stripe-multichain/index.mjs +1614 -266
  75. package/dist/stripe-multichain/index.mjs.map +1 -1
  76. package/dist/types-D1slMt0H.d.mts +137 -0
  77. package/dist/types-D1slMt0H.d.ts +137 -0
  78. package/dist/{wwwauthenticate-CVaGUMjU.d.mts → wwwauthenticate-Dgm-_af9.d.mts} +11 -1
  79. package/dist/{wwwauthenticate-CVaGUMjU.d.ts → wwwauthenticate-Dgm-_af9.d.ts} +11 -1
  80. package/package.json +26 -21
@@ -68,7 +68,7 @@ var IDENTITY_VERIFICATION_REQUIRED_FALLBACK_INSTRUCTIONS = JSON.stringify({
68
68
  var API_ERROR_INSTRUCTIONS = JSON.stringify({
69
69
  action: "retry_with_backoff",
70
70
  steps: [
71
- "Verification is temporarily unavailable. Retry the request after 5\u201330 seconds with exponential backoff.",
71
+ "Verification is temporarily unavailable. Retry the request after 5-30 seconds with exponential backoff.",
72
72
  "This is NOT a compliance denial \u2014 the user does not need to re-verify their identity. Send the same identity headers (X-Wallet-Address or X-Operator-Token) on retry.",
73
73
  "If the request continues to fail after 3+ retries (~60 seconds total), surface the error to the user with the merchant's support contact."
74
74
  ],
@@ -155,7 +155,605 @@ function denialReasonToBody(reason) {
155
155
  return body;
156
156
  }
157
157
 
158
+ // src/aip/verify.ts
159
+ import { decodeJwt, decodeProtectedHeader, importJWK as importJWK2, jwtVerify } from "jose";
160
+
161
+ // src/aip/http-signature.ts
162
+ import { calculateJwkThumbprint, importJWK } from "jose";
163
+ var { subtle } = globalThis.crypto;
164
+ var b64ToBytes = (b64) => {
165
+ const bin = atob(b64);
166
+ const out = new Uint8Array(bin.length);
167
+ for (let i = 0; i < bin.length; i++) {
168
+ out[i] = bin.charCodeAt(i);
169
+ }
170
+ return out;
171
+ };
172
+ var AIP_COVERED_COMPONENTS = ["@method", "@authority", "@path", "agent-identity"];
173
+ var AIP_SIGNATURE_TAG = "agent-identity";
174
+ var DEFAULT_MAX_SKEW_SECONDS = 60;
175
+ var MAX_POP_WINDOW_SECONDS = 120;
176
+ var normalizeAuthority = (authority) => {
177
+ const lower = authority.trim().toLowerCase();
178
+ const colon = lower.lastIndexOf(":");
179
+ if (colon === -1) {
180
+ return lower;
181
+ }
182
+ if (lower.includes("]") && colon < lower.indexOf("]")) {
183
+ return lower;
184
+ }
185
+ const host = lower.slice(0, colon);
186
+ const port = lower.slice(colon + 1);
187
+ if (port === "80" || port === "443") {
188
+ return host;
189
+ }
190
+ return lower;
191
+ };
192
+ var componentValue = (name, input) => {
193
+ switch (name) {
194
+ case "@method":
195
+ return input.method.toUpperCase();
196
+ case "@authority":
197
+ return normalizeAuthority(input.authority);
198
+ case "@path":
199
+ return input.path;
200
+ case "agent-identity":
201
+ return input.agentIdentity.trim();
202
+ default:
203
+ return input.extra?.[name] ?? null;
204
+ }
205
+ };
206
+ var serializeComponentList = (components) => `(${components.map((c) => `"${c}"`).join(" ")})`;
207
+ var serializeParams = (p) => {
208
+ const parts = [];
209
+ if (p.created !== void 0) {
210
+ parts.push(`created=${p.created}`);
211
+ }
212
+ if (p.expires !== void 0) {
213
+ parts.push(`expires=${p.expires}`);
214
+ }
215
+ if (p.keyid !== void 0) {
216
+ parts.push(`keyid="${p.keyid}"`);
217
+ }
218
+ if (p.alg !== void 0) {
219
+ parts.push(`alg="${p.alg}"`);
220
+ }
221
+ if (p.tag !== void 0) {
222
+ parts.push(`tag="${p.tag}"`);
223
+ }
224
+ return parts.map((s) => `;${s}`).join("");
225
+ };
226
+ var buildSignatureBase = (params, input, rawSignatureParams) => {
227
+ const lines = [];
228
+ for (const name of params.components) {
229
+ const value = componentValue(name, input);
230
+ if (value === null) {
231
+ throw new MissingComponentError(name);
232
+ }
233
+ lines.push(`"${name}": ${value}`);
234
+ }
235
+ const paramsValue = rawSignatureParams ?? serializeComponentList(params.components) + serializeParams(params);
236
+ lines.push(`"@signature-params": ${paramsValue}`);
237
+ return lines.join("\n");
238
+ };
239
+ var MissingComponentError = class extends Error {
240
+ constructor(component) {
241
+ super(`signature base missing covered component: ${component}`);
242
+ this.component = component;
243
+ this.name = "MissingComponentError";
244
+ }
245
+ component;
246
+ };
247
+ var parseSignatureInput = (header, tag = AIP_SIGNATURE_TAG) => {
248
+ const members = splitDictionary(header);
249
+ if (members.length === 0) {
250
+ return null;
251
+ }
252
+ const parsed = members.map((m) => {
253
+ const params = parseInnerListMember(m.value);
254
+ return params ? { label: m.label, params, rawParams: m.value } : null;
255
+ }).filter((x) => x !== null);
256
+ if (parsed.length === 0) {
257
+ return null;
258
+ }
259
+ return parsed.find((p) => p.params.tag === tag) ?? null;
260
+ };
261
+ var parseSignatureValue = (header, label) => {
262
+ const members = splitDictionary(header);
263
+ const member = members.find((m) => m.label === label);
264
+ if (!member) {
265
+ return null;
266
+ }
267
+ const v = member.value.trim();
268
+ if (!v.startsWith(":") || !v.endsWith(":") || v.length < 2) {
269
+ return null;
270
+ }
271
+ const b64 = v.slice(1, -1);
272
+ try {
273
+ return b64ToBytes(b64);
274
+ } catch {
275
+ return null;
276
+ }
277
+ };
278
+ var splitDictionary = (header) => {
279
+ const out = [];
280
+ let depth = 0;
281
+ let inBytes = false;
282
+ let inString = false;
283
+ let current = "";
284
+ for (let i = 0; i < header.length; i++) {
285
+ const ch = header[i];
286
+ if (inString) {
287
+ current += ch;
288
+ if (ch === '"' && header[i - 1] !== "\\") {
289
+ inString = false;
290
+ }
291
+ continue;
292
+ }
293
+ if (ch === '"') {
294
+ inString = true;
295
+ current += ch;
296
+ continue;
297
+ }
298
+ if (ch === ":") {
299
+ inBytes = !inBytes;
300
+ current += ch;
301
+ continue;
302
+ }
303
+ if (!inBytes && ch === "(") {
304
+ depth++;
305
+ current += ch;
306
+ continue;
307
+ }
308
+ if (!inBytes && ch === ")") {
309
+ depth = Math.max(0, depth - 1);
310
+ current += ch;
311
+ continue;
312
+ }
313
+ if (!inBytes && depth === 0 && ch === ",") {
314
+ pushMember(out, current);
315
+ current = "";
316
+ continue;
317
+ }
318
+ current += ch;
319
+ }
320
+ pushMember(out, current);
321
+ return out;
322
+ };
323
+ var pushMember = (out, raw) => {
324
+ const trimmed = raw.trim();
325
+ if (!trimmed) {
326
+ return;
327
+ }
328
+ const eq = trimmed.indexOf("=");
329
+ if (eq === -1) {
330
+ return;
331
+ }
332
+ const label = trimmed.slice(0, eq).trim();
333
+ const value = trimmed.slice(eq + 1).trim();
334
+ if (label) {
335
+ out.push({ label, value });
336
+ }
337
+ };
338
+ var parseInnerListMember = (value) => {
339
+ const open = value.indexOf("(");
340
+ const close = value.indexOf(")", open + 1);
341
+ if (open === -1 || close === -1) {
342
+ return null;
343
+ }
344
+ const listBody = value.slice(open + 1, close).trim();
345
+ const components = listBody.length === 0 ? [] : (listBody.match(/"[^"]*"/g) ?? []).map((s) => s.slice(1, -1));
346
+ const params = { components };
347
+ const paramStr = value.slice(close + 1);
348
+ const re = /;\s*([a-zA-Z][a-zA-Z0-9_-]*)\s*=\s*("(?:[^"\\]|\\.)*"|-?\d+)/g;
349
+ let match;
350
+ while ((match = re.exec(paramStr)) !== null) {
351
+ const key = match[1];
352
+ const raw = match[2];
353
+ const val = raw.startsWith('"') ? raw.slice(1, -1) : Number(raw);
354
+ if (key === "created") {
355
+ params.created = val;
356
+ } else if (key === "expires") {
357
+ params.expires = val;
358
+ } else if (key === "keyid") {
359
+ params.keyid = val;
360
+ } else if (key === "tag") {
361
+ params.tag = val;
362
+ } else if (key === "alg") {
363
+ params.alg = val;
364
+ }
365
+ }
366
+ return params;
367
+ };
368
+ var verifyMessageSignature = async (input) => {
369
+ const selected = parseSignatureInput(input.signatureInput);
370
+ if (!selected) {
371
+ return { ok: false, reason: "no_aip_signature" };
372
+ }
373
+ const { label, params, rawParams } = selected;
374
+ if (params.alg !== void 0 && !["ed25519", "eddsa"].includes(params.alg.toLowerCase())) {
375
+ return { ok: false, reason: "unsupported_alg" };
376
+ }
377
+ for (const required of AIP_COVERED_COMPONENTS) {
378
+ if (!params.components.includes(required)) {
379
+ return { ok: false, reason: "missing_covered_component" };
380
+ }
381
+ }
382
+ if (params.created === void 0) {
383
+ return { ok: false, reason: "created_missing" };
384
+ }
385
+ if (params.expires === void 0) {
386
+ return { ok: false, reason: "expires_missing" };
387
+ }
388
+ if (params.expires < params.created || params.expires - params.created > MAX_POP_WINDOW_SECONDS) {
389
+ return { ok: false, reason: "pop_window_too_long" };
390
+ }
391
+ const now = input.now ?? Math.floor(Date.now() / 1e3);
392
+ const skew = input.maxSkewSeconds ?? DEFAULT_MAX_SKEW_SECONDS;
393
+ if (params.created > now + skew) {
394
+ return { ok: false, reason: "created_in_future" };
395
+ }
396
+ if (params.expires < now - skew) {
397
+ return { ok: false, reason: "expired" };
398
+ }
399
+ if (!params.keyid) {
400
+ return { ok: false, reason: "missing_keyid" };
401
+ }
402
+ const cnf = input.cnfJwk;
403
+ if (cnf.kty !== "OKP" || cnf.crv !== "Ed25519" || typeof cnf.x !== "string" || cnf.x.length === 0) {
404
+ return { ok: false, reason: "unsupported_cnf_key" };
405
+ }
406
+ let thumbprint;
407
+ try {
408
+ thumbprint = await calculateJwkThumbprint(input.cnfJwk, "sha256");
409
+ } catch {
410
+ return { ok: false, reason: "unsupported_cnf_key" };
411
+ }
412
+ if (params.keyid !== thumbprint) {
413
+ return { ok: false, reason: "keyid_mismatch" };
414
+ }
415
+ const sig = parseSignatureValue(input.signature, label);
416
+ if (!sig) {
417
+ return { ok: false, reason: "malformed_signature" };
418
+ }
419
+ let base;
420
+ try {
421
+ base = buildSignatureBase(params, {
422
+ method: input.method,
423
+ authority: input.authority,
424
+ path: input.path,
425
+ agentIdentity: input.agentIdentity,
426
+ extra: input.extraComponents
427
+ }, rawParams);
428
+ } catch (err) {
429
+ if (err instanceof MissingComponentError) {
430
+ return { ok: false, reason: "missing_covered_component" };
431
+ }
432
+ throw err;
433
+ }
434
+ let valid;
435
+ try {
436
+ const key = await importJWK(input.cnfJwk, "EdDSA");
437
+ if (!(key instanceof CryptoKey)) {
438
+ return { ok: false, reason: "signature_invalid" };
439
+ }
440
+ valid = await subtle.verify(
441
+ { name: "Ed25519" },
442
+ key,
443
+ sig,
444
+ new TextEncoder().encode(base)
445
+ );
446
+ } catch {
447
+ return { ok: false, reason: "signature_invalid" };
448
+ }
449
+ return valid ? { ok: true, params } : { ok: false, reason: "signature_invalid" };
450
+ };
451
+
452
+ // src/aip/types.ts
453
+ var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
454
+ var isNonEmptyString = (v) => typeof v === "string" && v.length > 0;
455
+ var isAitShape = (payload) => isObject(payload) && isObject(payload.cnf) && isObject(payload.agent);
456
+ var validateAitPayload = (payload) => {
457
+ if (!isObject(payload)) {
458
+ return { ok: false, reason: "not_an_object" };
459
+ }
460
+ if (!isNonEmptyString(payload.aip_version)) {
461
+ return { ok: false, reason: "missing_aip_version" };
462
+ }
463
+ if (!isNonEmptyString(payload.iss)) {
464
+ return { ok: false, reason: "missing_iss" };
465
+ }
466
+ if (!isNonEmptyString(payload.sub)) {
467
+ return { ok: false, reason: "missing_sub" };
468
+ }
469
+ if (typeof payload.iat !== "number") {
470
+ return { ok: false, reason: "missing_iat" };
471
+ }
472
+ if (typeof payload.exp !== "number") {
473
+ return { ok: false, reason: "missing_exp" };
474
+ }
475
+ if (!isObject(payload.cnf) || !isObject(payload.cnf.jwk)) {
476
+ return { ok: false, reason: "missing_cnf" };
477
+ }
478
+ if (!isObject(payload.agent) || !isNonEmptyString(payload.agent.provider)) {
479
+ return { ok: false, reason: "missing_agent_provider" };
480
+ }
481
+ if (payload.trust_level === "human_confirmed") {
482
+ const auth = payload.auth;
483
+ const amr = isObject(auth) ? auth.amr : void 0;
484
+ if (!Array.isArray(amr) || amr.length === 0) {
485
+ return { ok: false, reason: "human_confirmed_without_amr" };
486
+ }
487
+ }
488
+ return { ok: true, payload };
489
+ };
490
+
491
+ // src/aip/verify.ts
492
+ var AGENT_IDENTITY_HEADER = "agent-identity";
493
+ var verifyAit = async (ctx, opts) => {
494
+ if (ctx.agentIdentityHeaders.length === 0) {
495
+ return { ok: false, reason: "no_token" };
496
+ }
497
+ if (!ctx.signatureInput || !ctx.signature) {
498
+ return { ok: false, reason: "pop_signature_missing" };
499
+ }
500
+ const signatureInput = ctx.signatureInput;
501
+ const signature = ctx.signature;
502
+ let lastFailure = "malformed_token";
503
+ for (const raw of ctx.agentIdentityHeaders) {
504
+ const token = stripBearer(raw);
505
+ let header;
506
+ let payload;
507
+ try {
508
+ header = decodeProtectedHeader(token);
509
+ payload = decodeJwt(token);
510
+ } catch {
511
+ lastFailure = "malformed_token";
512
+ continue;
513
+ }
514
+ if (header.alg === void 0 || header.alg.toLowerCase() === "none") {
515
+ lastFailure = "malformed_token";
516
+ continue;
517
+ }
518
+ if (!isAitShape(payload)) {
519
+ lastFailure = "malformed_token";
520
+ continue;
521
+ }
522
+ const validated = validateAitPayload(payload);
523
+ if (!validated.ok) {
524
+ lastFailure = "invalid_claims";
525
+ continue;
526
+ }
527
+ const claims = validated.payload;
528
+ const keyLookup = await opts.jwks.getKey(claims.iss, header.kid);
529
+ if (!keyLookup.ok) {
530
+ lastFailure = keyLookup.reason === "untrusted_issuer" || keyLookup.reason === "insecure_issuer" ? "untrusted_issuer" : "key_unavailable";
531
+ continue;
532
+ }
533
+ const jwtClockTolerance = opts.maxSkewSeconds ?? 60;
534
+ try {
535
+ const idpKey = await importJWK2(keyLookup.key, normalizeAlg(header.alg));
536
+ await jwtVerify(token, idpKey, {
537
+ // Pin the signature algorithm allowlist (RFC 8725 §3.1) — also rejects `alg:none`. Without
538
+ // this, jose accepts whatever alg the resolved JWK supports, so a trusted IdP publishing a
539
+ // non-Ed25519 (e.g. RSA/EC) `use:sig` key would let an attacker present an RS256/ES256
540
+ // token that verifies. Matches the server-side allowlist in the AgentScore API verifier.
541
+ algorithms: AIT_SIGNING_ALGS,
542
+ clockTolerance: jwtClockTolerance,
543
+ currentDate: opts.now !== void 0 ? new Date(opts.now * 1e3) : void 0
544
+ });
545
+ } catch (err) {
546
+ lastFailure = isExpiry(err) ? "expired_token" : "idp_signature_invalid";
547
+ continue;
548
+ }
549
+ const nowSec = opts.now ?? Math.floor(Date.now() / 1e3);
550
+ if (claims.iat > nowSec + jwtClockTolerance) {
551
+ lastFailure = "expired_token";
552
+ continue;
553
+ }
554
+ if (claims.exp - claims.iat > (opts.maxLifetimeSeconds ?? 300)) {
555
+ lastFailure = "expired_token";
556
+ continue;
557
+ }
558
+ const popResult = await verifyMessageSignature({
559
+ method: ctx.method,
560
+ authority: ctx.authority,
561
+ path: ctx.path,
562
+ // The agent-identity covered component is the BARE AIT (a Bearer prefix, if present, is
563
+ // transport that `stripBearer` removed above). Verify over `token`, not `raw`, so the edge and
564
+ // the API — which verifies over the forwarded bare aip_token — reconstruct the identical base.
565
+ agentIdentity: token,
566
+ signatureInput,
567
+ signature,
568
+ cnfJwk: claims.cnf.jwk,
569
+ now: opts.now,
570
+ maxSkewSeconds: opts.maxSkewSeconds
571
+ });
572
+ if (!popResult.ok) {
573
+ lastFailure = "pop_signature_invalid";
574
+ continue;
575
+ }
576
+ return {
577
+ ok: true,
578
+ ait: {
579
+ payload: claims,
580
+ iss: claims.iss,
581
+ cnfJwk: claims.cnf.jwk,
582
+ token,
583
+ signatureMaterial: {
584
+ method: ctx.method,
585
+ authority: ctx.authority,
586
+ path: ctx.path,
587
+ signature_input: signatureInput,
588
+ signature
589
+ }
590
+ }
591
+ };
592
+ }
593
+ return { ok: false, reason: lastFailure };
594
+ };
595
+ var stripBearer = (value) => {
596
+ const trimmed = value.trim();
597
+ return /^bearer\s+/i.test(trimmed) ? trimmed.replace(/^bearer\s+/i, "") : trimmed;
598
+ };
599
+ var AIT_SIGNING_ALGS = ["EdDSA", "ES256"];
600
+ var normalizeAlg = (alg) => alg.toLowerCase() === "eddsa" ? "EdDSA" : alg;
601
+ var isExpiry = (err) => typeof err === "object" && err !== null && err.code === "ERR_JWT_EXPIRED";
602
+
603
+ // src/aip/request.ts
604
+ var readAgentIdentityHeaders = (headers) => {
605
+ const raw = headers.get(AGENT_IDENTITY_HEADER);
606
+ if (!raw) {
607
+ return [];
608
+ }
609
+ return raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
610
+ };
611
+ var deriveAuthority = (req, url) => req.headers.get("host") ?? url.host;
612
+ var buildVerifyContextFromRequest = (req, authority) => {
613
+ const url = new URL(req.url);
614
+ return {
615
+ method: req.method,
616
+ authority: authority ?? deriveAuthority(req, url),
617
+ path: url.pathname,
618
+ agentIdentityHeaders: readAgentIdentityHeaders(req.headers),
619
+ signatureInput: req.headers.get("signature-input"),
620
+ signature: req.headers.get("signature")
621
+ };
622
+ };
623
+ var hasAgentIdentityHeader = (req) => readAgentIdentityHeaders(req.headers).length > 0;
624
+
625
+ // src/aip/gate.ts
626
+ var aipErrorCode = (failure) => {
627
+ switch (failure) {
628
+ case "no_token":
629
+ case "pop_signature_missing":
630
+ return "agent_identity_required";
631
+ case "untrusted_issuer":
632
+ return "untrusted_issuer";
633
+ case "expired_token":
634
+ return "expired_token";
635
+ case "invalid_claims":
636
+ return "insufficient_claims";
637
+ case "key_unavailable":
638
+ return "idp_unavailable";
639
+ case "malformed_token":
640
+ case "idp_signature_invalid":
641
+ case "pop_signature_invalid":
642
+ return "invalid_signature";
643
+ default:
644
+ return "invalid_signature";
645
+ }
646
+ };
647
+ var aipErrorStatus = (failure) => {
648
+ switch (failure) {
649
+ case "key_unavailable":
650
+ return 503;
651
+ case "untrusted_issuer":
652
+ case "invalid_claims":
653
+ return 403;
654
+ default:
655
+ return 401;
656
+ }
657
+ };
658
+ var aipErrorDetail = (failure) => {
659
+ switch (failure) {
660
+ case "no_token":
661
+ return "No Agent-Identity token was presented.";
662
+ case "pop_signature_missing":
663
+ return "The request is missing the RFC 9421 HTTP Message Signature that proves possession of the token-bound key.";
664
+ case "untrusted_issuer":
665
+ return "The token's issuer is not in this service's trusted-issuer list.";
666
+ case "expired_token":
667
+ return "The Agent Identity Token has expired.";
668
+ case "invalid_claims":
669
+ return "The token is missing required claims for this endpoint.";
670
+ case "malformed_token":
671
+ return "The Agent-Identity header could not be parsed as an Agent Identity Token.";
672
+ case "idp_signature_invalid":
673
+ return "The identity provider's signature on the token failed verification.";
674
+ case "pop_signature_invalid":
675
+ return "The request signature did not match the key bound to the token.";
676
+ case "key_unavailable":
677
+ return "The identity provider's signing key could not be resolved.";
678
+ default:
679
+ return "Token verification failed.";
680
+ }
681
+ };
682
+ var buildAipErrorBody = (failure, requirements) => {
683
+ const code = aipErrorCode(failure);
684
+ const body = {
685
+ type: `urn:aip:error:${code}`,
686
+ title: code.replace(/_/g, " "),
687
+ status: aipErrorStatus(failure),
688
+ detail: aipErrorDetail(failure)
689
+ };
690
+ if (requirements) {
691
+ if (code === "untrusted_issuer" && requirements.trustedIssuers?.length) {
692
+ body.trusted_issuers = requirements.trustedIssuers;
693
+ }
694
+ if (code === "insufficient_claims") {
695
+ if (requirements.requiredClaims?.length) body.required_claims = requirements.requiredClaims;
696
+ if (requirements.requiredTrustLevel !== void 0) body.required_trust_level = requirements.requiredTrustLevel;
697
+ if (requirements.requiredAmr?.length) body.required_amr = requirements.requiredAmr;
698
+ }
699
+ }
700
+ return body;
701
+ };
702
+ var TRUST_RANK = { autonomous: 0, human_present: 1, human_confirmed: 2 };
703
+ var checkTrustRequirements = (payload, requiredTrustLevel, requiredAmr) => {
704
+ if (requiredTrustLevel !== void 0) {
705
+ const have = TRUST_RANK[payload.trust_level ?? "autonomous"] ?? 0;
706
+ const need = TRUST_RANK[requiredTrustLevel] ?? 0;
707
+ if (have < need) {
708
+ return `This endpoint requires trust_level '${requiredTrustLevel}'; the token asserts '${payload.trust_level ?? "autonomous"}'. Re-mint an AIT at the required trust level (human confirmation).`;
709
+ }
710
+ }
711
+ if (requiredAmr !== void 0 && requiredAmr.length > 0) {
712
+ const amr = Array.isArray(payload.auth?.amr) ? payload.auth.amr : [];
713
+ if (!amr.some((m) => requiredAmr.includes(m))) {
714
+ return `This endpoint requires an authentication method in [${requiredAmr.join(", ")}]; the token carries [${amr.join(", ") || "none"}].`;
715
+ }
716
+ }
717
+ return null;
718
+ };
719
+ var buildAipWeakAuthBody = (opts) => ({
720
+ type: "urn:aip:error:weak_auth",
721
+ title: "weak auth",
722
+ status: 403,
723
+ detail: opts.detail,
724
+ ...opts.requiredTrustLevel !== void 0 && { required_trust_level: opts.requiredTrustLevel },
725
+ ...opts.requiredAmr !== void 0 && opts.requiredAmr.length > 0 && { required_amr: opts.requiredAmr },
726
+ ...opts.trustedIssuers !== void 0 && opts.trustedIssuers.length > 0 && { trusted_issuers: opts.trustedIssuers }
727
+ });
728
+ var requirementsFromOptions = (opts) => ({
729
+ ...opts.trustedIssuers !== void 0 && { trustedIssuers: opts.trustedIssuers },
730
+ ...opts.requiredClaims !== void 0 && { requiredClaims: opts.requiredClaims },
731
+ ...opts.requireTrustLevel !== void 0 && { requiredTrustLevel: opts.requireTrustLevel },
732
+ ...opts.requireAmr !== void 0 && { requiredAmr: opts.requireAmr }
733
+ });
734
+ var evaluateFromContext = async (ctx, opts) => {
735
+ const result = await verifyAit(ctx, { jwks: opts.jwks, now: opts.now, maxSkewSeconds: opts.maxSkewSeconds });
736
+ if (!result.ok) {
737
+ return { ok: false, body: buildAipErrorBody(result.reason, requirementsFromOptions(opts)) };
738
+ }
739
+ const weak = checkTrustRequirements(result.ait.payload, opts.requireTrustLevel, opts.requireAmr);
740
+ if (weak !== null) {
741
+ return {
742
+ ok: false,
743
+ body: buildAipWeakAuthBody({
744
+ detail: weak,
745
+ ...opts.requireTrustLevel !== void 0 && { requiredTrustLevel: opts.requireTrustLevel },
746
+ ...opts.requireAmr !== void 0 && { requiredAmr: opts.requireAmr },
747
+ ...opts.trustedIssuers !== void 0 && { trustedIssuers: opts.trustedIssuers }
748
+ })
749
+ };
750
+ }
751
+ return { ok: true, ait: result.ait };
752
+ };
753
+ var evaluateAipRequest = (req, opts) => evaluateFromContext(buildVerifyContextFromRequest(req, opts.authority), opts);
754
+
158
755
  // src/core.ts
756
+ import { createHash } from "crypto";
159
757
  import {
160
758
  AgentScore,
161
759
  InvalidCredentialError,
@@ -231,7 +829,7 @@ function stripTrailingSlashes(s) {
231
829
  while (end > 0 && s.charCodeAt(end - 1) === 47) end--;
232
830
  return end === s.length ? s : s.slice(0, end);
233
831
  }
234
- var CANONICAL_AGENTSCORE_API = "https://api.agentscore.sh";
832
+ var CANONICAL_AGENTSCORE_API = "https://api.agentscore.com";
235
833
  var WALLET_SIGNER_MISMATCH_INSTRUCTIONS = JSON.stringify({
236
834
  action: "resign_or_switch_to_operator_token",
237
835
  steps: [
@@ -257,17 +855,22 @@ var INVALID_CREDENTIAL_INSTRUCTIONS = JSON.stringify({
257
855
  ],
258
856
  user_message: "The operator_token is not recognized. Use a different stored token, or restart the verification session flow to mint a new one."
259
857
  });
260
- function buildAgentMemoryHint() {
858
+ function buildAgentMemoryHint(aipTrustedIssuers) {
261
859
  const api = CANONICAL_AGENTSCORE_API;
860
+ const acceptsAip = aipTrustedIssuers !== void 0 && aipTrustedIssuers.length > 0;
262
861
  return {
263
862
  save_for_future_agentscore_gates: true,
264
863
  pattern_summary: "AgentScore is a cross-merchant identity substrate for agent commerce. Any endpoint that returns 403 missing_identity / identity_verification_required or 402 challenges referencing AgentScore uses the same identity system. One KYC works across all AgentScore merchants \u2014 no re-verification per site. Save this pattern (and the endpoints below) to persistent memory so future AgentScore encounters skip the cold-start session flow.",
265
- quickstart: "https://docs.agentscore.sh/guides/agent-identity",
864
+ quickstart: "https://docs.agentscore.com/guides/agent-identity",
266
865
  identity_check_endpoint: `${api}/v1/credentials`,
267
866
  identity_paths: {
268
867
  wallet: "If paying from a crypto wallet you have used before on any AgentScore merchant, send `X-Wallet-Address: 0x...`. Shortest path; no token lifecycle to manage.",
269
- operator_token: "For any rail (Stripe SPT, card, or a wallet you have not linked yet), send `X-Operator-Token: opc_...`. Reusable across merchants until the token expires."
868
+ operator_token: "For any rail (Stripe SPT, card, or a wallet you have not linked yet), send `X-Operator-Token: opc_...`. Reusable across merchants until the token expires.",
869
+ ...acceptsAip && {
870
+ agent_identity: 'If you hold an AIP Agent Identity Token from a trusted issuer (see aip_trusted_issuers), present it: send the JWT in an `Agent-Identity` header plus an RFC 9421 HTTP Message Signature (Signature-Input + Signature over @method @authority @path agent-identity, tag="agent-identity") signed with the token-bound cnf key. The merchant verifies it and applies its policy \u2014 no separate AgentScore credential needed.'
871
+ }
270
872
  },
873
+ ...acceptsAip && { aip_trusted_issuers: aipTrustedIssuers },
271
874
  bootstrap: "If you have neither a linked wallet nor a valid operator_token, follow the session/verify flow in the per-request `agent_instructions` block. This happens at most once per agent identity \u2014 after first verification, the operator_token and any subsequently used wallet are reusable everywhere.",
272
875
  do_not_persist_in_memory: ["operator_token", "poll_secret"],
273
876
  persist_in_credential_store: ["operator_token"]
@@ -275,7 +878,7 @@ function buildAgentMemoryHint() {
275
878
  }
276
879
  function createAgentScoreCore(options) {
277
880
  if (!options.apiKey) {
278
- throw new Error("AgentScore API key is required. Get one at https://agentscore.sh/sign-up");
881
+ throw new Error("AgentScore API key is required. Get one at https://www.agentscore.com/sign-up");
279
882
  }
280
883
  const {
281
884
  apiKey,
@@ -286,14 +889,15 @@ function createAgentScoreCore(options) {
286
889
  allowedJurisdictions,
287
890
  failOpen = false,
288
891
  cacheSeconds = 300,
289
- baseUrl: rawBaseUrl = "https://api.agentscore.sh",
892
+ baseUrl: rawBaseUrl = "https://api.agentscore.com",
290
893
  chain: gateChain,
291
894
  userAgent,
292
- createSessionOnMissing
895
+ createSessionOnMissing,
896
+ aipTrustedIssuers
293
897
  } = options;
294
898
  const baseUrl = stripTrailingSlashes(rawBaseUrl);
295
- const agentMemoryHint = buildAgentMemoryHint();
296
- const defaultUa = `@agent-score/commerce@${"2.4.0"}`;
899
+ const agentMemoryHint = buildAgentMemoryHint(aipTrustedIssuers);
900
+ const defaultUa = `@agent-score/commerce@${"2.6.0"}`;
297
901
  const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
298
902
  const sdk = new AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
299
903
  const sessionSdkCache = /* @__PURE__ */ new Map();
@@ -368,16 +972,21 @@ function createAgentScoreCore(options) {
368
972
  }
369
973
  }
370
974
  async function evaluate(identity, ctx, signer) {
371
- if (!identity || !identity.address && !identity.operatorToken) {
975
+ if (!identity || !identity.address?.trim() && !identity.operatorToken?.trim() && !identity.aipToken?.trim()) {
372
976
  if (failOpen) return { kind: "allow" };
373
977
  const sessionReason = await tryMintSessionDenial(ctx);
374
978
  if (sessionReason) return { kind: "deny", reason: sessionReason };
979
+ const acceptsAip = aipTrustedIssuers !== void 0 && aipTrustedIssuers.length > 0;
980
+ const aipStep = acceptsAip ? [
981
+ `If you hold an AIP Agent Identity Token from a trusted issuer (${aipTrustedIssuers.join(", ")}): present it \u2014 send the JWT in an Agent-Identity header plus an RFC 9421 HTTP Message Signature (Signature-Input + Signature over @method @authority @path agent-identity, tag="agent-identity") signed with the token-bound cnf key. This satisfies identity in one round trip without an AgentScore credential.`
982
+ ] : [];
375
983
  const missingIdentityInstructions = JSON.stringify({
376
984
  action: "probe_identity_then_session",
377
985
  steps: [
986
+ ...aipStep,
378
987
  "If you have a wallet AND this merchant accepts a wallet-signing rail (Tempo MPP or x402 \u2014 see openapi.json x-payment-info): send X-Wallet-Address and retry. If the wallet is already linked to an AgentScore operator (via prior SIWE claim or prior captureWallet), this passes in one round trip. If the wallet is unlinked or the account has no KYC, the 403 will include a verify_url \u2014 share it with the user to claim the wallet + complete KYC, then retry.",
379
988
  "If step 1 is denied or you already have a stored operator_token (valid + not expired): send X-Operator-Token: opc_... and retry.",
380
- "If neither applies: retry with NO identity header. Merchants that auto-create verification sessions (most AgentScore merchants do) return verify_url + session_id + poll_secret in the 403 body \u2014 share verify_url with the user, then poll poll_url every 5s with the X-Poll-Secret header until status=verified (the poll returns a one-time operator_token). If the retry returns the same bare 403, this merchant does not support self-service session bootstrapping \u2014 direct the user to https://agentscore.sh/sign-up to create an AgentScore identity and mint an operator_token from their dashboard (https://agentscore.sh/dashboard/verify). The user hands the opc_... to you, and you retry with X-Operator-Token."
989
+ "If neither applies: retry with NO identity header. Merchants that auto-create verification sessions (most AgentScore merchants do) return verify_url + session_id + poll_secret in the 403 body \u2014 share verify_url with the user, then poll poll_url every 5s with the X-Poll-Secret header until status=verified (the poll returns a one-time operator_token). If the retry returns the same bare 403, this merchant does not support self-service session bootstrapping \u2014 direct the user to https://www.agentscore.com/sign-up to create an AgentScore identity and mint an operator_token from their dashboard (https://www.agentscore.com/dashboard/verify). The user hands the opc_... to you, and you retry with X-Operator-Token."
381
990
  ],
382
991
  user_message: "Try X-Wallet-Address first if you have a wallet and the merchant accepts Tempo/x402; fall back to a stored X-Operator-Token, then to the session/verify flow described in agent_memory.bootstrap."
383
992
  });
@@ -390,21 +999,26 @@ function createAgentScoreCore(options) {
390
999
  }
391
1000
  };
392
1001
  }
393
- const cacheKey = identity.operatorToken?.toLowerCase() ?? (identity.address ? normalizeAddress(identity.address) : "");
1002
+ const identityKey = identity.aipToken ? `aip:${createHash("sha256").update(identity.aipToken).digest("hex")}` : identity.operatorToken?.toLowerCase() ?? (identity.address ? normalizeAddress(identity.address) : "");
1003
+ const cacheKey = signer ? JSON.stringify([identityKey, signer.network, normalizeAddress(signer.address)]) : JSON.stringify([identityKey]);
394
1004
  const cached = cache.get(cacheKey);
395
1005
  if (cached) {
1006
+ const cachedVerdict = cached.raw ? buildSignerVerdict(identity, cached.raw) : void 0;
396
1007
  if (cached.allow) {
397
1008
  const cachedRaw = cached.raw;
398
1009
  const cachedQuota = cachedRaw?.quota;
399
1010
  return {
400
1011
  kind: "allow",
401
1012
  data: cachedRaw,
402
- ...cachedQuota !== void 0 && { quota: cachedQuota }
1013
+ ...cachedQuota !== void 0 && { quota: cachedQuota },
1014
+ ...cachedVerdict !== void 0 && { signerVerdict: cachedVerdict }
403
1015
  };
404
1016
  }
405
1017
  if (isFixableDenial(cached.reasons)) {
406
1018
  const sessionReason = await tryMintSessionDenial(ctx);
407
- if (sessionReason) return { kind: "deny", reason: sessionReason };
1019
+ if (sessionReason) {
1020
+ return { kind: "deny", reason: sessionReason, ...cachedVerdict !== void 0 && { signerVerdict: cachedVerdict } };
1021
+ }
408
1022
  }
409
1023
  return {
410
1024
  kind: "deny",
@@ -414,7 +1028,8 @@ function createAgentScoreCore(options) {
414
1028
  reasons: cached.reasons,
415
1029
  verify_url: cached.raw?.verify_url,
416
1030
  data: cached.raw
417
- }
1031
+ },
1032
+ ...cachedVerdict !== void 0 && { signerVerdict: cachedVerdict }
418
1033
  };
419
1034
  }
420
1035
  const policy = {};
@@ -435,7 +1050,10 @@ function createAgentScoreCore(options) {
435
1050
  // regardless of policy.require_sanctions_clear (which gates the separate NAME screen).
436
1051
  ...signer && { signer: { address: signer.address, network: signer.network } }
437
1052
  };
438
- const result = identity.address ? await sdk.assess(identity.address, { ...opts, operatorToken: identity.operatorToken }) : await sdk.assess(null, { ...opts, operatorToken: identity.operatorToken });
1053
+ if (identity.aipToken !== void 0 && identity.aipSignature === void 0) {
1054
+ throw new Error("AgentScoreCore.evaluate: aipToken requires aipSignature (RFC 9421 proof-of-possession material).");
1055
+ }
1056
+ const result = identity.aipToken !== void 0 && identity.aipSignature !== void 0 ? await sdk.assess(null, { ...opts, aipToken: identity.aipToken, aipSignature: identity.aipSignature }) : identity.address ? await sdk.assess(identity.address, { ...opts, operatorToken: identity.operatorToken }) : await sdk.assess(null, { ...opts, operatorToken: identity.operatorToken });
439
1057
  data = result;
440
1058
  } catch (err) {
441
1059
  if (err instanceof PaymentRequiredError) {
@@ -506,17 +1124,21 @@ function createAgentScoreCore(options) {
506
1124
  const decisionReasons = data.decision_reasons ?? [];
507
1125
  const allow = decision === "allow" || decision == null;
508
1126
  cache.set(cacheKey, { allow, decision: decision ?? void 0, reasons: decisionReasons, raw: data });
1127
+ const signerVerdict = buildSignerVerdict(identity, data);
509
1128
  if (allow) {
510
1129
  const quota = data.quota;
511
1130
  return {
512
1131
  kind: "allow",
513
1132
  data,
514
- ...quota !== void 0 && { quota }
1133
+ ...quota !== void 0 && { quota },
1134
+ ...signerVerdict !== void 0 && { signerVerdict }
515
1135
  };
516
1136
  }
517
1137
  if (isFixableDenial(decisionReasons)) {
518
1138
  const sessionReason = await tryMintSessionDenial(ctx);
519
- if (sessionReason) return { kind: "deny", reason: sessionReason };
1139
+ if (sessionReason) {
1140
+ return { kind: "deny", reason: sessionReason, ...signerVerdict !== void 0 && { signerVerdict } };
1141
+ }
520
1142
  }
521
1143
  return {
522
1144
  kind: "deny",
@@ -526,7 +1148,8 @@ function createAgentScoreCore(options) {
526
1148
  reasons: decisionReasons,
527
1149
  verify_url: data.verify_url,
528
1150
  data
529
- }
1151
+ },
1152
+ ...signerVerdict !== void 0 && { signerVerdict }
530
1153
  };
531
1154
  }
532
1155
  async function captureWallet(options2) {
@@ -568,22 +1191,21 @@ function createAgentScoreCore(options) {
568
1191
  agentInstructions: sm.agent_instructions ?? WALLET_SIGNER_MISMATCH_INSTRUCTIONS
569
1192
  };
570
1193
  }
571
- function getSignerVerdict(claimedAddress) {
572
- const claimedNorm = normalizeAddress(claimedAddress);
573
- const cached = cache.get(claimedNorm);
574
- if (!cached) return void 0;
575
- const raw = cached.raw;
576
- if (!raw) return void 0;
1194
+ function buildSignerVerdict(identity, raw) {
1195
+ if (identity.address === void 0 || identity.operatorToken !== void 0 || identity.aipToken !== void 0) {
1196
+ return void 0;
1197
+ }
577
1198
  const rawMatch = raw.signer_match;
578
1199
  const rawSanctions = raw.signer_sanctions;
579
1200
  if (!rawMatch && !rawSanctions) return void 0;
1201
+ const claimedNorm = normalizeAddress(identity.address);
580
1202
  const signerNorm = rawMatch?.actual_signer ?? claimedNorm;
581
1203
  return {
582
1204
  signer_match: rawMatch ? projectSignerMatch(rawMatch, claimedNorm, signerNorm) : null,
583
1205
  signer_sanctions: rawSanctions ?? null
584
1206
  };
585
1207
  }
586
- return { evaluate, captureWallet, getSignerVerdict };
1208
+ return { evaluate, captureWallet };
587
1209
  }
588
1210
 
589
1211
  // src/signer.ts
@@ -688,7 +1310,8 @@ function createAgentScoreGate(options) {
688
1310
  const outcome = await core.evaluate(identity, req, signer);
689
1311
  if (outcome.kind === "allow") {
690
1312
  const captureWallet = identity?.operatorToken ? (opts) => core.captureWallet({ operatorToken: identity.operatorToken, ...opts }) : void 0;
691
- const getSignerVerdictBound = identity?.address && !identity?.operatorToken ? () => core.getSignerVerdict(identity.address) : void 0;
1313
+ const signerVerdict = outcome.signerVerdict;
1314
+ const getSignerVerdictBound = identity?.address && !identity?.operatorToken ? () => signerVerdict : void 0;
692
1315
  return {
693
1316
  allowed: true,
694
1317
  data: outcome.data,
@@ -702,6 +1325,42 @@ function createAgentScoreGate(options) {
702
1325
  return { allowed: false, response };
703
1326
  };
704
1327
  }
1328
+ var defaultAipResponse = (body) => new Response(JSON.stringify(body), { status: body.status, headers: { "content-type": "application/problem+json" } });
1329
+ function createAipGate(options) {
1330
+ const { onDenied, ...gateOpts } = options;
1331
+ return async (req) => {
1332
+ const result = await evaluateAipRequest(req, gateOpts);
1333
+ if (result.ok) {
1334
+ return { allowed: true, ait: result.ait };
1335
+ }
1336
+ const body = result.body;
1337
+ const response = onDenied ? await onDenied(req, body) : defaultAipResponse(body);
1338
+ return { allowed: false, response };
1339
+ };
1340
+ }
1341
+ function withAipGate(options, handler) {
1342
+ const guard = createAipGate(options);
1343
+ return async (req, ctx) => {
1344
+ const result = await guard(req);
1345
+ if (!result.allowed) {
1346
+ return result.response;
1347
+ }
1348
+ return handler(req, { ait: result.ait }, ctx);
1349
+ };
1350
+ }
1351
+ function withConditionalAipGate(options, handler) {
1352
+ const guard = createAipGate(options);
1353
+ return async (req, ctx) => {
1354
+ if (!hasAgentIdentityHeader(req)) {
1355
+ return handler(req, {}, ctx);
1356
+ }
1357
+ const result = await guard(req);
1358
+ if (!result.allowed) {
1359
+ return result.response;
1360
+ }
1361
+ return handler(req, { ait: result.ait }, ctx);
1362
+ };
1363
+ }
705
1364
 
706
1365
  // src/identity/nextjs.ts
707
1366
  function withAgentScoreGate(options, handler) {
@@ -750,7 +1409,10 @@ function conditionalAgentscoreMiddleware(options) {
750
1409
  export {
751
1410
  agentscoreMiddleware,
752
1411
  conditionalAgentscoreMiddleware,
1412
+ createAipGate,
753
1413
  withAgentScoreGate,
754
- withConditionalAgentScoreGate
1414
+ withAipGate,
1415
+ withConditionalAgentScoreGate,
1416
+ withConditionalAipGate
755
1417
  };
756
1418
  //# sourceMappingURL=nextjs.mjs.map