@agent-score/commerce 2.3.0 → 2.5.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 +6 -6
  2. package/dist/challenge/index.d.mts +9 -5
  3. package/dist/challenge/index.d.ts +9 -5
  4. package/dist/challenge/index.js +11 -4
  5. package/dist/challenge/index.js.map +1 -1
  6. package/dist/challenge/index.mjs +11 -4
  7. package/dist/challenge/index.mjs.map +1 -1
  8. package/dist/{checkout-ChyOi7aU.d.ts → checkout-McfNpZJf.d.ts} +80 -12
  9. package/dist/{checkout-Ceo1_rVJ.d.mts → checkout-o17dIxHi.d.mts} +80 -12
  10. package/dist/core.d.mts +27 -7
  11. package/dist/core.d.ts +27 -7
  12. package/dist/core.js +25 -11
  13. package/dist/core.js.map +1 -1
  14. package/dist/core.mjs +25 -11
  15. package/dist/core.mjs.map +1 -1
  16. package/dist/discovery/index.d.mts +26 -10
  17. package/dist/discovery/index.d.ts +26 -10
  18. package/dist/discovery/index.js +58 -10
  19. package/dist/discovery/index.js.map +1 -1
  20. package/dist/discovery/index.mjs +58 -10
  21. package/dist/discovery/index.mjs.map +1 -1
  22. package/dist/gate-CWP10xPQ.d.mts +339 -0
  23. package/dist/gate-CWP10xPQ.d.ts +339 -0
  24. package/dist/identity/express.d.mts +26 -1
  25. package/dist/identity/express.d.ts +26 -1
  26. package/dist/identity/express.js +599 -25
  27. package/dist/identity/express.js.map +1 -1
  28. package/dist/identity/express.mjs +595 -24
  29. package/dist/identity/express.mjs.map +1 -1
  30. package/dist/identity/fastify.d.mts +12 -2
  31. package/dist/identity/fastify.d.ts +12 -2
  32. package/dist/identity/fastify.js +607 -25
  33. package/dist/identity/fastify.js.map +1 -1
  34. package/dist/identity/fastify.mjs +603 -24
  35. package/dist/identity/fastify.mjs.map +1 -1
  36. package/dist/identity/hono.d.mts +26 -1
  37. package/dist/identity/hono.d.ts +26 -1
  38. package/dist/identity/hono.js +588 -25
  39. package/dist/identity/hono.js.map +1 -1
  40. package/dist/identity/hono.mjs +584 -24
  41. package/dist/identity/hono.mjs.map +1 -1
  42. package/dist/identity/nextjs.d.mts +3 -0
  43. package/dist/identity/nextjs.d.ts +3 -0
  44. package/dist/identity/nextjs.js +593 -25
  45. package/dist/identity/nextjs.js.map +1 -1
  46. package/dist/identity/nextjs.mjs +589 -24
  47. package/dist/identity/nextjs.mjs.map +1 -1
  48. package/dist/identity/policy.js.map +1 -1
  49. package/dist/identity/policy.mjs.map +1 -1
  50. package/dist/identity/web.d.mts +24 -1
  51. package/dist/identity/web.d.ts +24 -1
  52. package/dist/identity/web.js +593 -25
  53. package/dist/identity/web.js.map +1 -1
  54. package/dist/identity/web.mjs +589 -24
  55. package/dist/identity/web.mjs.map +1 -1
  56. package/dist/index.d.mts +129 -14
  57. package/dist/index.d.ts +129 -14
  58. package/dist/index.js +978 -99
  59. package/dist/index.js.map +1 -1
  60. package/dist/index.mjs +956 -99
  61. package/dist/index.mjs.map +1 -1
  62. package/dist/{default_rails-DtR_E9N9.d.ts → network_kind-BIJM2peR.d.ts} +22 -8
  63. package/dist/{default_rails-K25PtWrL.d.mts → network_kind-C0EMkdzz.d.mts} +22 -8
  64. package/dist/payment/index.d.mts +16 -26
  65. package/dist/payment/index.d.ts +16 -26
  66. package/dist/payment/index.js +62 -57
  67. package/dist/payment/index.js.map +1 -1
  68. package/dist/payment/index.mjs +62 -57
  69. package/dist/payment/index.mjs.map +1 -1
  70. package/dist/{pricing-B3-aKxSz.d.ts → pricing-CytRwhC2.d.ts} +1 -1
  71. package/dist/{pricing-BReyZiqN.d.mts → pricing-KHDqMLd7.d.mts} +1 -1
  72. package/dist/{rail_spec-B1239jPp.d.mts → rail_spec-BFZmW9RN.d.mts} +3 -4
  73. package/dist/{rail_spec-B1239jPp.d.ts → rail_spec-BFZmW9RN.d.ts} +3 -4
  74. package/dist/stripe-multichain/index.d.mts +2 -9
  75. package/dist/stripe-multichain/index.d.ts +2 -9
  76. package/dist/stripe-multichain/index.js.map +1 -1
  77. package/dist/stripe-multichain/index.mjs.map +1 -1
  78. package/dist/{wwwauthenticate-D_FMnPgU.d.mts → wwwauthenticate-CVaGUMjU.d.mts} +8 -6
  79. package/dist/{wwwauthenticate-D_FMnPgU.d.ts → wwwauthenticate-CVaGUMjU.d.ts} +8 -6
  80. package/package.json +14 -13
package/dist/index.mjs CHANGED
@@ -329,19 +329,19 @@ function stableStringify(value) {
329
329
  }
330
330
  if (!Number.isInteger(value)) {
331
331
  throw new Error(
332
- `UCP profile canonicalization rejects non-integer Number ${value}. Use a decimal string (e.g. "9.99") for monetary or fractional fields to preserve cross-language byte-parity.`
332
+ `UCP profile canonicalization rejects non-integer Number ${value}. Use a decimal string (e.g. "9.99") for monetary or fractional fields so the signed canonical bytes stay stable for any verifier.`
333
333
  );
334
334
  }
335
335
  if (!Number.isSafeInteger(value)) {
336
336
  throw new Error(
337
- `stableStringify: integer ${value} exceeds Number.MAX_SAFE_INTEGER. For values >2^53, use a decimal string to preserve cross-language byte parity.`
337
+ `stableStringify: integer ${value} exceeds Number.MAX_SAFE_INTEGER. For values >2^53, use a decimal string to keep the signed bytes stable across implementations.`
338
338
  );
339
339
  }
340
340
  }
341
341
  if (typeof value === "string") {
342
342
  if (value.includes("\u2028") || value.includes("\u2029")) {
343
343
  throw new Error(
344
- "stableStringify: strings containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; cross-language byte parity requires neither be present (Node JSON.stringify on older V8 escapes them; Python json.dumps with ensure_ascii=False does not)."
344
+ "stableStringify: strings containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; stable canonical bytes require neither be present (some JSON encoders escape them, others emit them raw)."
345
345
  );
346
346
  }
347
347
  return JSON.stringify(value);
@@ -361,7 +361,7 @@ function stableStringify(value) {
361
361
  for (const k of keys) {
362
362
  if (k.includes("\u2028") || k.includes("\u2029")) {
363
363
  throw new Error(
364
- "stableStringify: object keys containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; cross-language byte parity (Node JSON.stringify on older V8 escapes them; Python json.dumps with ensure_ascii=False does not)."
364
+ "stableStringify: object keys containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; stable canonical bytes require neither be present (some JSON encoders escape them, others emit them raw)."
365
365
  );
366
366
  }
367
367
  }
@@ -581,12 +581,12 @@ async function buildEnvSigningKey(opts) {
581
581
  );
582
582
  }
583
583
  const canonicalPrivateJwk = detectedAlg === "EdDSA" ? { kty: jwkDict.kty, crv: jwkDict.crv, x: jwkDict.x, d: jwkDict.d } : { kty: jwkDict.kty, crv: jwkDict.crv, x: jwkDict.x, y: jwkDict.y, d: jwkDict.d };
584
- const { importJWK } = await import("jose");
584
+ const { importJWK: importJWK3 } = await import("jose");
585
585
  const { createPublicKey } = await import("crypto");
586
586
  let privateKey;
587
587
  let publicNodeKey;
588
588
  try {
589
- privateKey = await importJWK(
589
+ privateKey = await importJWK3(
590
590
  canonicalPrivateJwk,
591
591
  detectedAlg
592
592
  );
@@ -7949,13 +7949,13 @@ var init_schemas = __esm({
7949
7949
  }
7950
7950
  return propValues;
7951
7951
  });
7952
- const isObject2 = isObject;
7952
+ const isObject3 = isObject;
7953
7953
  const catchall2 = def.catchall;
7954
7954
  let value;
7955
7955
  inst._zod.parse = (payload, ctx) => {
7956
7956
  value ?? (value = _normalized.value);
7957
7957
  const input = payload.value;
7958
- if (!isObject2(input)) {
7958
+ if (!isObject3(input)) {
7959
7959
  payload.issues.push({
7960
7960
  expected: "object",
7961
7961
  code: "invalid_type",
@@ -8082,7 +8082,7 @@ var init_schemas = __esm({
8082
8082
  return (payload, ctx) => fn(shape, payload, ctx);
8083
8083
  };
8084
8084
  let fastpass;
8085
- const isObject2 = isObject;
8085
+ const isObject3 = isObject;
8086
8086
  const jit = !globalConfig.jitless;
8087
8087
  const allowsEval2 = allowsEval;
8088
8088
  const fastEnabled = jit && allowsEval2.value;
@@ -8091,7 +8091,7 @@ var init_schemas = __esm({
8091
8091
  inst._zod.parse = (payload, ctx) => {
8092
8092
  value ?? (value = _normalized.value);
8093
8093
  const input = payload.value;
8094
- if (!isObject2(input)) {
8094
+ if (!isObject3(input)) {
8095
8095
  payload.issues.push({
8096
8096
  expected: "object",
8097
8097
  code: "invalid_type",
@@ -20328,6 +20328,53 @@ var init_networks = __esm({
20328
20328
  }
20329
20329
  });
20330
20330
 
20331
+ // src/payment/amounts.ts
20332
+ function usdToAtomic(usd, opts) {
20333
+ const { decimals } = opts;
20334
+ if (!Number.isInteger(decimals) || decimals < 0) {
20335
+ throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
20336
+ }
20337
+ if (typeof usd === "number") {
20338
+ if (!Number.isFinite(usd)) {
20339
+ throw new RangeError(`usd must be finite, got ${usd}`);
20340
+ }
20341
+ if (usd < 0) {
20342
+ throw new RangeError(`usd must be non-negative, got ${usd}`);
20343
+ }
20344
+ }
20345
+ const s = (typeof usd === "number" ? usd.toString() : usd).trim();
20346
+ if (s.startsWith("-")) {
20347
+ throw new RangeError(`usd must be non-negative, got ${s}`);
20348
+ }
20349
+ if (s === "NaN" || s === "Infinity") {
20350
+ throw new RangeError(`usd must be finite, got ${s}`);
20351
+ }
20352
+ const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
20353
+ if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
20354
+ throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
20355
+ }
20356
+ const intPart = match[1] || "0";
20357
+ const fracPart = match[2] ?? "";
20358
+ if (fracPart.length <= decimals) {
20359
+ return BigInt(intPart + fracPart.padEnd(decimals, "0"));
20360
+ }
20361
+ const kept = fracPart.slice(0, decimals);
20362
+ const roundDigit = fracPart[decimals];
20363
+ let result = BigInt(intPart + kept);
20364
+ if (roundDigit >= "5") {
20365
+ result += 1n;
20366
+ }
20367
+ return result;
20368
+ }
20369
+ function formatUsdCents(cents, decimals = 2) {
20370
+ return (cents / 100).toFixed(decimals);
20371
+ }
20372
+ var init_amounts = __esm({
20373
+ "src/payment/amounts.ts"() {
20374
+ "use strict";
20375
+ }
20376
+ });
20377
+
20331
20378
  // src/payment/rails.ts
20332
20379
  function lookupRail(name) {
20333
20380
  return rails[name];
@@ -20427,8 +20474,7 @@ function buildPaymentRequestBlob({
20427
20474
  const decimalsResolved = decimals ?? railDef?.decimals ?? 6;
20428
20475
  const currencyResolved = currency ?? railDef?.currency ?? "usd";
20429
20476
  const chainIdResolved = chainId ?? railDef?.chainId;
20430
- const amountNum = typeof amountUsd === "string" ? Number(amountUsd) : amountUsd;
20431
- const amountRaw = BigInt(Math.round(amountNum * 10 ** decimalsResolved)).toString();
20477
+ const amountRaw = usdToAtomic(amountUsd, { decimals: decimalsResolved }).toString();
20432
20478
  const blob = { amount: amountRaw, currency: currencyResolved, decimals: decimalsResolved };
20433
20479
  if (recipient) blob.recipient = recipient;
20434
20480
  const methodDetails = {};
@@ -20455,6 +20501,7 @@ function paymentDirective({
20455
20501
  var init_directive = __esm({
20456
20502
  "src/payment/directive.ts"() {
20457
20503
  "use strict";
20504
+ init_amounts();
20458
20505
  init_rails();
20459
20506
  }
20460
20507
  });
@@ -20804,6 +20851,7 @@ var init_well_known = __esm({
20804
20851
  });
20805
20852
 
20806
20853
  // src/core.ts
20854
+ import { createHash } from "crypto";
20807
20855
  import {
20808
20856
  AgentScore,
20809
20857
  InvalidCredentialError,
@@ -21126,8 +21174,9 @@ var INVALID_CREDENTIAL_INSTRUCTIONS = JSON.stringify({
21126
21174
  ],
21127
21175
  user_message: "The operator_token is not recognized. Use a different stored token, or restart the verification session flow to mint a new one."
21128
21176
  });
21129
- function buildAgentMemoryHint() {
21177
+ function buildAgentMemoryHint(aipTrustedIssuers) {
21130
21178
  const api = CANONICAL_AGENTSCORE_API;
21179
+ const acceptsAip = aipTrustedIssuers !== void 0 && aipTrustedIssuers.length > 0;
21131
21180
  return {
21132
21181
  save_for_future_agentscore_gates: true,
21133
21182
  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.",
@@ -21135,8 +21184,12 @@ function buildAgentMemoryHint() {
21135
21184
  identity_check_endpoint: `${api}/v1/credentials`,
21136
21185
  identity_paths: {
21137
21186
  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.",
21138
- 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."
21187
+ 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.",
21188
+ ...acceptsAip && {
21189
+ 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.'
21190
+ }
21139
21191
  },
21192
+ ...acceptsAip && { aip_trusted_issuers: aipTrustedIssuers },
21140
21193
  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.",
21141
21194
  do_not_persist_in_memory: ["operator_token", "poll_secret"],
21142
21195
  persist_in_credential_store: ["operator_token"]
@@ -21158,11 +21211,12 @@ function createAgentScoreCore(options) {
21158
21211
  baseUrl: rawBaseUrl = "https://api.agentscore.sh",
21159
21212
  chain: gateChain,
21160
21213
  userAgent,
21161
- createSessionOnMissing
21214
+ createSessionOnMissing,
21215
+ aipTrustedIssuers
21162
21216
  } = options;
21163
21217
  const baseUrl = stripTrailingSlashes(rawBaseUrl);
21164
- const agentMemoryHint = buildAgentMemoryHint();
21165
- const defaultUa = `@agent-score/commerce@${"2.3.0"}`;
21218
+ const agentMemoryHint = buildAgentMemoryHint(aipTrustedIssuers);
21219
+ const defaultUa = `@agent-score/commerce@${"2.5.0"}`;
21166
21220
  const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
21167
21221
  const sdk = new AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
21168
21222
  const sessionSdkCache = /* @__PURE__ */ new Map();
@@ -21180,6 +21234,7 @@ function createAgentScoreCore(options) {
21180
21234
  return s;
21181
21235
  }
21182
21236
  const cache = new TTLCache(cacheSeconds * 1e3);
21237
+ const lastSignerRaw = /* @__PURE__ */ new Map();
21183
21238
  async function tryMintSessionDenial(ctx) {
21184
21239
  if (!createSessionOnMissing) return void 0;
21185
21240
  try {
@@ -21237,13 +21292,18 @@ function createAgentScoreCore(options) {
21237
21292
  }
21238
21293
  }
21239
21294
  async function evaluate(identity, ctx, signer) {
21240
- if (!identity || !identity.address && !identity.operatorToken) {
21295
+ if (!identity || !identity.address?.trim() && !identity.operatorToken?.trim() && !identity.aipToken?.trim()) {
21241
21296
  if (failOpen) return { kind: "allow" };
21242
21297
  const sessionReason = await tryMintSessionDenial(ctx);
21243
21298
  if (sessionReason) return { kind: "deny", reason: sessionReason };
21299
+ const acceptsAip = aipTrustedIssuers !== void 0 && aipTrustedIssuers.length > 0;
21300
+ const aipStep = acceptsAip ? [
21301
+ `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.`
21302
+ ] : [];
21244
21303
  const missingIdentityInstructions = JSON.stringify({
21245
21304
  action: "probe_identity_then_session",
21246
21305
  steps: [
21306
+ ...aipStep,
21247
21307
  "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.",
21248
21308
  "If step 1 is denied or you already have a stored operator_token (valid + not expired): send X-Operator-Token: opc_... and retry.",
21249
21309
  "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."
@@ -21259,7 +21319,7 @@ function createAgentScoreCore(options) {
21259
21319
  }
21260
21320
  };
21261
21321
  }
21262
- const cacheKey2 = identity.operatorToken?.toLowerCase() ?? (identity.address ? normalizeAddress(identity.address) : "");
21322
+ const cacheKey2 = identity.aipToken ? `aip:${createHash("sha256").update(identity.aipToken).digest("hex")}` : identity.operatorToken?.toLowerCase() ?? (identity.address ? normalizeAddress(identity.address) : "");
21263
21323
  const cached2 = cache.get(cacheKey2);
21264
21324
  if (cached2) {
21265
21325
  if (cached2.allow) {
@@ -21304,7 +21364,7 @@ function createAgentScoreCore(options) {
21304
21364
  // regardless of policy.require_sanctions_clear (which gates the separate NAME screen).
21305
21365
  ...signer && { signer: { address: signer.address, network: signer.network } }
21306
21366
  };
21307
- const result = identity.address ? await sdk.assess(identity.address, { ...opts, operatorToken: identity.operatorToken }) : await sdk.assess(null, { ...opts, operatorToken: identity.operatorToken });
21367
+ const result = identity.aipToken ? await sdk.assess(null, { ...opts, aipToken: identity.aipToken }) : identity.address ? await sdk.assess(identity.address, { ...opts, operatorToken: identity.operatorToken }) : await sdk.assess(null, { ...opts, operatorToken: identity.operatorToken });
21308
21368
  data = result;
21309
21369
  } catch (err) {
21310
21370
  if (err instanceof PaymentRequiredError) {
@@ -21375,6 +21435,9 @@ function createAgentScoreCore(options) {
21375
21435
  const decisionReasons = data.decision_reasons ?? [];
21376
21436
  const allow = decision === "allow" || decision == null;
21377
21437
  cache.set(cacheKey2, { allow, decision: decision ?? void 0, reasons: decisionReasons, raw: data });
21438
+ if (identity.address !== void 0 && identity.operatorToken === void 0 && identity.aipToken === void 0 && (data.signer_match !== void 0 || data.signer_sanctions !== void 0)) {
21439
+ lastSignerRaw.set(normalizeAddress(identity.address), data);
21440
+ }
21378
21441
  if (allow) {
21379
21442
  const quota = data.quota;
21380
21443
  return {
@@ -21439,9 +21502,7 @@ function createAgentScoreCore(options) {
21439
21502
  }
21440
21503
  function getSignerVerdict(claimedAddress) {
21441
21504
  const claimedNorm = normalizeAddress(claimedAddress);
21442
- const cached2 = cache.get(claimedNorm);
21443
- if (!cached2) return void 0;
21444
- const raw = cached2.raw;
21505
+ const raw = lastSignerRaw.get(claimedNorm) ?? cache.get(claimedNorm)?.raw;
21445
21506
  if (!raw) return void 0;
21446
21507
  const rawMatch = raw.signer_match;
21447
21508
  const rawSanctions = raw.signer_sanctions;
@@ -21502,6 +21563,18 @@ async function extractSolanaSignerFromCredential(credential) {
21502
21563
  }
21503
21564
  }
21504
21565
  async function extractPaymentSigner(request, x402PaymentHeader) {
21566
+ if (x402PaymentHeader) {
21567
+ try {
21568
+ const decoded = atob(x402PaymentHeader);
21569
+ const parsed = JSON.parse(decoded);
21570
+ const from9 = parsed?.payload?.authorization?.from;
21571
+ if (typeof from9 === "string" && /^0x[0-9a-fA-F]{40}$/.test(from9)) {
21572
+ return { address: from9.toLowerCase(), network: "evm" };
21573
+ }
21574
+ } catch (err) {
21575
+ console.warn("[gate] x402 signer extraction failed:", err instanceof Error ? err.message : err);
21576
+ }
21577
+ }
21505
21578
  const authHeader = request.headers.get("authorization");
21506
21579
  if (authHeader) {
21507
21580
  try {
@@ -21521,18 +21594,6 @@ async function extractPaymentSigner(request, x402PaymentHeader) {
21521
21594
  console.warn("[gate] MPP signer extraction failed:", err instanceof Error ? err.message : err);
21522
21595
  }
21523
21596
  }
21524
- if (x402PaymentHeader) {
21525
- try {
21526
- const decoded = atob(x402PaymentHeader);
21527
- const parsed = JSON.parse(decoded);
21528
- const from9 = parsed?.payload?.authorization?.from;
21529
- if (typeof from9 === "string" && /^0x[0-9a-fA-F]{40}$/.test(from9)) {
21530
- return { address: from9.toLowerCase(), network: "evm" };
21531
- }
21532
- } catch (err) {
21533
- console.warn("[gate] x402 signer extraction failed:", err instanceof Error ? err.message : err);
21534
- }
21535
- }
21536
21597
  return null;
21537
21598
  }
21538
21599
  async function extractPaymentSignerFromAuth(authHeader, x402PaymentHeader) {
@@ -21704,7 +21765,7 @@ function validateShippingAgainstPolicy(opts) {
21704
21765
  }
21705
21766
 
21706
21767
  // src/identity/tokens.ts
21707
- import { createHash } from "crypto";
21768
+ import { createHash as createHash2 } from "crypto";
21708
21769
 
21709
21770
  // src/payment/payment_header.ts
21710
21771
  function toTitleCase(name) {
@@ -21740,7 +21801,7 @@ function hasMppxHeader(input) {
21740
21801
 
21741
21802
  // src/identity/tokens.ts
21742
21803
  function hashOperatorToken(plaintext) {
21743
- return createHash("sha256").update(plaintext, "utf8").digest("hex");
21804
+ return createHash2("sha256").update(plaintext, "utf8").digest("hex");
21744
21805
  }
21745
21806
  function extractOwnerScope(input) {
21746
21807
  const headers = asHeaders(input);
@@ -21793,6 +21854,710 @@ function warnMissingApiKeyOnce(label) {
21793
21854
  );
21794
21855
  }
21795
21856
 
21857
+ // src/aip/verify.ts
21858
+ import { decodeJwt, decodeProtectedHeader, importJWK as importJWK2, jwtVerify } from "jose";
21859
+
21860
+ // src/aip/http-signature.ts
21861
+ import { calculateJwkThumbprint, importJWK } from "jose";
21862
+ var { subtle } = globalThis.crypto;
21863
+ var b64ToBytes = (b64) => {
21864
+ const bin = atob(b64);
21865
+ const out = new Uint8Array(bin.length);
21866
+ for (let i = 0; i < bin.length; i++) {
21867
+ out[i] = bin.charCodeAt(i);
21868
+ }
21869
+ return out;
21870
+ };
21871
+ var bytesToB64 = (bytes) => {
21872
+ let bin = "";
21873
+ for (let i = 0; i < bytes.length; i++) {
21874
+ bin += String.fromCharCode(bytes[i]);
21875
+ }
21876
+ return btoa(bin);
21877
+ };
21878
+ var AIP_COVERED_COMPONENTS = ["@method", "@authority", "@path", "agent-identity"];
21879
+ var AIP_SIGNATURE_TAG = "agent-identity";
21880
+ var DEFAULT_MAX_SKEW_SECONDS = 60;
21881
+ var normalizeAuthority = (authority) => {
21882
+ const lower = authority.trim().toLowerCase();
21883
+ const colon = lower.lastIndexOf(":");
21884
+ if (colon === -1) {
21885
+ return lower;
21886
+ }
21887
+ if (lower.includes("]") && colon < lower.indexOf("]")) {
21888
+ return lower;
21889
+ }
21890
+ const host = lower.slice(0, colon);
21891
+ const port = lower.slice(colon + 1);
21892
+ if (port === "80" || port === "443") {
21893
+ return host;
21894
+ }
21895
+ return lower;
21896
+ };
21897
+ var componentValue = (name, input) => {
21898
+ switch (name) {
21899
+ case "@method":
21900
+ return input.method.toUpperCase();
21901
+ case "@authority":
21902
+ return normalizeAuthority(input.authority);
21903
+ case "@path":
21904
+ return input.path;
21905
+ case "agent-identity":
21906
+ return input.agentIdentity.trim();
21907
+ default:
21908
+ return input.extra?.[name] ?? null;
21909
+ }
21910
+ };
21911
+ var serializeComponentList = (components) => `(${components.map((c) => `"${c}"`).join(" ")})`;
21912
+ var serializeParams = (p) => {
21913
+ const parts = [];
21914
+ if (p.created !== void 0) {
21915
+ parts.push(`created=${p.created}`);
21916
+ }
21917
+ if (p.expires !== void 0) {
21918
+ parts.push(`expires=${p.expires}`);
21919
+ }
21920
+ if (p.keyid !== void 0) {
21921
+ parts.push(`keyid="${p.keyid}"`);
21922
+ }
21923
+ if (p.alg !== void 0) {
21924
+ parts.push(`alg="${p.alg}"`);
21925
+ }
21926
+ if (p.tag !== void 0) {
21927
+ parts.push(`tag="${p.tag}"`);
21928
+ }
21929
+ return parts.map((s) => `;${s}`).join("");
21930
+ };
21931
+ var buildSignatureBase = (params, input) => {
21932
+ const lines = [];
21933
+ for (const name of params.components) {
21934
+ const value = componentValue(name, input);
21935
+ if (value === null) {
21936
+ throw new MissingComponentError(name);
21937
+ }
21938
+ lines.push(`"${name}": ${value}`);
21939
+ }
21940
+ const paramsValue = serializeComponentList(params.components) + serializeParams(params);
21941
+ lines.push(`"@signature-params": ${paramsValue}`);
21942
+ return lines.join("\n");
21943
+ };
21944
+ var MissingComponentError = class extends Error {
21945
+ constructor(component) {
21946
+ super(`signature base missing covered component: ${component}`);
21947
+ this.component = component;
21948
+ this.name = "MissingComponentError";
21949
+ }
21950
+ component;
21951
+ };
21952
+ var parseSignatureInput = (header, tag = AIP_SIGNATURE_TAG) => {
21953
+ const members = splitDictionary(header);
21954
+ if (members.length === 0) {
21955
+ return null;
21956
+ }
21957
+ const parsed = members.map((m) => {
21958
+ const params = parseInnerListMember(m.value);
21959
+ return params ? { label: m.label, params } : null;
21960
+ }).filter((x) => x !== null);
21961
+ if (parsed.length === 0) {
21962
+ return null;
21963
+ }
21964
+ const tagged = parsed.find((p) => p.params.tag === tag);
21965
+ if (tagged) {
21966
+ return tagged;
21967
+ }
21968
+ if (parsed.length === 1 && parsed[0].params.tag === void 0) {
21969
+ return parsed[0];
21970
+ }
21971
+ return null;
21972
+ };
21973
+ var parseSignatureValue = (header, label) => {
21974
+ const members = splitDictionary(header);
21975
+ const member = members.find((m) => m.label === label);
21976
+ if (!member) {
21977
+ return null;
21978
+ }
21979
+ const v = member.value.trim();
21980
+ if (!v.startsWith(":") || !v.endsWith(":") || v.length < 2) {
21981
+ return null;
21982
+ }
21983
+ const b64 = v.slice(1, -1);
21984
+ try {
21985
+ return b64ToBytes(b64);
21986
+ } catch {
21987
+ return null;
21988
+ }
21989
+ };
21990
+ var splitDictionary = (header) => {
21991
+ const out = [];
21992
+ let depth = 0;
21993
+ let inBytes = false;
21994
+ let inString = false;
21995
+ let current = "";
21996
+ for (let i = 0; i < header.length; i++) {
21997
+ const ch = header[i];
21998
+ if (inString) {
21999
+ current += ch;
22000
+ if (ch === '"' && header[i - 1] !== "\\") {
22001
+ inString = false;
22002
+ }
22003
+ continue;
22004
+ }
22005
+ if (ch === '"') {
22006
+ inString = true;
22007
+ current += ch;
22008
+ continue;
22009
+ }
22010
+ if (ch === ":") {
22011
+ inBytes = !inBytes;
22012
+ current += ch;
22013
+ continue;
22014
+ }
22015
+ if (!inBytes && ch === "(") {
22016
+ depth++;
22017
+ current += ch;
22018
+ continue;
22019
+ }
22020
+ if (!inBytes && ch === ")") {
22021
+ depth = Math.max(0, depth - 1);
22022
+ current += ch;
22023
+ continue;
22024
+ }
22025
+ if (!inBytes && depth === 0 && ch === ",") {
22026
+ pushMember(out, current);
22027
+ current = "";
22028
+ continue;
22029
+ }
22030
+ current += ch;
22031
+ }
22032
+ pushMember(out, current);
22033
+ return out;
22034
+ };
22035
+ var pushMember = (out, raw) => {
22036
+ const trimmed = raw.trim();
22037
+ if (!trimmed) {
22038
+ return;
22039
+ }
22040
+ const eq = trimmed.indexOf("=");
22041
+ if (eq === -1) {
22042
+ return;
22043
+ }
22044
+ const label = trimmed.slice(0, eq).trim();
22045
+ const value = trimmed.slice(eq + 1).trim();
22046
+ if (label) {
22047
+ out.push({ label, value });
22048
+ }
22049
+ };
22050
+ var parseInnerListMember = (value) => {
22051
+ const open = value.indexOf("(");
22052
+ const close = value.indexOf(")", open + 1);
22053
+ if (open === -1 || close === -1) {
22054
+ return null;
22055
+ }
22056
+ const listBody = value.slice(open + 1, close).trim();
22057
+ const components = listBody.length === 0 ? [] : (listBody.match(/"[^"]*"/g) ?? []).map((s) => s.slice(1, -1));
22058
+ const params = { components };
22059
+ const paramStr = value.slice(close + 1);
22060
+ const re = /;\s*([a-zA-Z][a-zA-Z0-9_-]*)\s*=\s*("(?:[^"\\]|\\.)*"|-?\d+)/g;
22061
+ let match;
22062
+ while ((match = re.exec(paramStr)) !== null) {
22063
+ const key = match[1];
22064
+ const raw = match[2];
22065
+ const val = raw.startsWith('"') ? raw.slice(1, -1) : Number(raw);
22066
+ if (key === "created") {
22067
+ params.created = val;
22068
+ } else if (key === "expires") {
22069
+ params.expires = val;
22070
+ } else if (key === "keyid") {
22071
+ params.keyid = val;
22072
+ } else if (key === "tag") {
22073
+ params.tag = val;
22074
+ } else if (key === "alg") {
22075
+ params.alg = val;
22076
+ }
22077
+ }
22078
+ return params;
22079
+ };
22080
+ var verifyMessageSignature = async (input) => {
22081
+ const selected = parseSignatureInput(input.signatureInput);
22082
+ if (!selected) {
22083
+ return { ok: false, reason: "no_aip_signature" };
22084
+ }
22085
+ const { label, params } = selected;
22086
+ if (params.alg !== void 0 && !["ed25519", "eddsa"].includes(params.alg.toLowerCase())) {
22087
+ return { ok: false, reason: "unsupported_alg" };
22088
+ }
22089
+ for (const required3 of AIP_COVERED_COMPONENTS) {
22090
+ if (!params.components.includes(required3)) {
22091
+ return { ok: false, reason: "missing_covered_component" };
22092
+ }
22093
+ }
22094
+ const now = input.now ?? Math.floor(Date.now() / 1e3);
22095
+ const skew = input.maxSkewSeconds ?? DEFAULT_MAX_SKEW_SECONDS;
22096
+ if (params.created !== void 0 && params.created > now + skew) {
22097
+ return { ok: false, reason: "created_in_future" };
22098
+ }
22099
+ if (params.expires !== void 0 && params.expires < now - skew) {
22100
+ return { ok: false, reason: "expired" };
22101
+ }
22102
+ if (!params.keyid) {
22103
+ return { ok: false, reason: "missing_keyid" };
22104
+ }
22105
+ const cnf = input.cnfJwk;
22106
+ if (cnf.kty !== "OKP" || cnf.crv !== "Ed25519" || typeof cnf.x !== "string" || cnf.x.length === 0) {
22107
+ return { ok: false, reason: "unsupported_cnf_key" };
22108
+ }
22109
+ let thumbprint;
22110
+ try {
22111
+ thumbprint = await calculateJwkThumbprint(input.cnfJwk, "sha256");
22112
+ } catch {
22113
+ return { ok: false, reason: "unsupported_cnf_key" };
22114
+ }
22115
+ if (params.keyid !== thumbprint) {
22116
+ return { ok: false, reason: "keyid_mismatch" };
22117
+ }
22118
+ const sig = parseSignatureValue(input.signature, label);
22119
+ if (!sig) {
22120
+ return { ok: false, reason: "malformed_signature" };
22121
+ }
22122
+ let base;
22123
+ try {
22124
+ base = buildSignatureBase(params, {
22125
+ method: input.method,
22126
+ authority: input.authority,
22127
+ path: input.path,
22128
+ agentIdentity: input.agentIdentity,
22129
+ extra: input.extraComponents
22130
+ });
22131
+ } catch (err) {
22132
+ if (err instanceof MissingComponentError) {
22133
+ return { ok: false, reason: "missing_covered_component" };
22134
+ }
22135
+ throw err;
22136
+ }
22137
+ let valid;
22138
+ try {
22139
+ const key = await importJWK(input.cnfJwk, "EdDSA");
22140
+ if (!(key instanceof CryptoKey)) {
22141
+ return { ok: false, reason: "signature_invalid" };
22142
+ }
22143
+ valid = await subtle.verify(
22144
+ { name: "Ed25519" },
22145
+ key,
22146
+ sig,
22147
+ new TextEncoder().encode(base)
22148
+ );
22149
+ } catch {
22150
+ return { ok: false, reason: "signature_invalid" };
22151
+ }
22152
+ return valid ? { ok: true, params } : { ok: false, reason: "signature_invalid" };
22153
+ };
22154
+ var signMessage = async (input) => {
22155
+ const label = input.label ?? "ait";
22156
+ const components = input.components ?? [...AIP_COVERED_COMPONENTS];
22157
+ const created = input.created ?? Math.floor(Date.now() / 1e3);
22158
+ const keyid = await calculateJwkThumbprint(input.publicJwk, "sha256");
22159
+ const params = {
22160
+ components,
22161
+ created,
22162
+ expires: input.expires,
22163
+ keyid,
22164
+ tag: AIP_SIGNATURE_TAG
22165
+ };
22166
+ const base = buildSignatureBase(params, {
22167
+ method: input.method,
22168
+ authority: input.authority,
22169
+ path: input.path,
22170
+ agentIdentity: input.agentIdentity,
22171
+ extra: input.extraComponents
22172
+ });
22173
+ const key = await importJWK(input.privateJwk, "EdDSA");
22174
+ if (!(key instanceof CryptoKey)) {
22175
+ throw new Error("signMessage: expected an Ed25519 private CryptoKey");
22176
+ }
22177
+ const sigBytes = await subtle.sign(
22178
+ "Ed25519",
22179
+ key,
22180
+ new TextEncoder().encode(base)
22181
+ );
22182
+ const b64 = bytesToB64(new Uint8Array(sigBytes));
22183
+ const signatureInput = `${label}=${serializeComponentList(components)}${serializeParams(params)}`;
22184
+ const signature2 = `${label}=:${b64}:`;
22185
+ return { signatureInput, signature: signature2 };
22186
+ };
22187
+
22188
+ // src/aip/types.ts
22189
+ var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
22190
+ var isNonEmptyString = (v) => typeof v === "string" && v.length > 0;
22191
+ var isAitShape = (payload) => isObject2(payload) && isObject2(payload.cnf) && isObject2(payload.agent);
22192
+ var validateAitPayload = (payload) => {
22193
+ if (!isObject2(payload)) {
22194
+ return { ok: false, reason: "not_an_object" };
22195
+ }
22196
+ if (!isNonEmptyString(payload.aip_version)) {
22197
+ return { ok: false, reason: "missing_aip_version" };
22198
+ }
22199
+ if (!isNonEmptyString(payload.iss)) {
22200
+ return { ok: false, reason: "missing_iss" };
22201
+ }
22202
+ if (!isNonEmptyString(payload.sub)) {
22203
+ return { ok: false, reason: "missing_sub" };
22204
+ }
22205
+ if (typeof payload.iat !== "number") {
22206
+ return { ok: false, reason: "missing_iat" };
22207
+ }
22208
+ if (typeof payload.exp !== "number") {
22209
+ return { ok: false, reason: "missing_exp" };
22210
+ }
22211
+ if (!isObject2(payload.cnf) || !isObject2(payload.cnf.jwk)) {
22212
+ return { ok: false, reason: "missing_cnf" };
22213
+ }
22214
+ if (!isObject2(payload.agent) || !isNonEmptyString(payload.agent.provider)) {
22215
+ return { ok: false, reason: "missing_agent_provider" };
22216
+ }
22217
+ if (payload.trust_level === "human_confirmed") {
22218
+ const auth = payload.auth;
22219
+ const amr = isObject2(auth) ? auth.amr : void 0;
22220
+ if (!Array.isArray(amr) || amr.length === 0) {
22221
+ return { ok: false, reason: "human_confirmed_without_amr" };
22222
+ }
22223
+ }
22224
+ return { ok: true, payload };
22225
+ };
22226
+
22227
+ // src/aip/verify.ts
22228
+ var AGENT_IDENTITY_HEADER = "agent-identity";
22229
+ var verifyAit = async (ctx, opts) => {
22230
+ if (ctx.agentIdentityHeaders.length === 0) {
22231
+ return { ok: false, reason: "no_token" };
22232
+ }
22233
+ if (!ctx.signatureInput || !ctx.signature) {
22234
+ return { ok: false, reason: "pop_signature_missing" };
22235
+ }
22236
+ let lastFailure = "malformed_token";
22237
+ for (const raw of ctx.agentIdentityHeaders) {
22238
+ const token = stripBearer(raw);
22239
+ let header;
22240
+ let payload;
22241
+ try {
22242
+ header = decodeProtectedHeader(token);
22243
+ payload = decodeJwt(token);
22244
+ } catch {
22245
+ lastFailure = "malformed_token";
22246
+ continue;
22247
+ }
22248
+ if (header.alg === void 0 || header.alg.toLowerCase() === "none") {
22249
+ lastFailure = "malformed_token";
22250
+ continue;
22251
+ }
22252
+ if (!isAitShape(payload)) {
22253
+ lastFailure = "malformed_token";
22254
+ continue;
22255
+ }
22256
+ const validated = validateAitPayload(payload);
22257
+ if (!validated.ok) {
22258
+ lastFailure = "invalid_claims";
22259
+ continue;
22260
+ }
22261
+ const claims = validated.payload;
22262
+ const keyLookup = await opts.jwks.getKey(claims.iss, header.kid);
22263
+ if (!keyLookup.ok) {
22264
+ lastFailure = keyLookup.reason === "untrusted_issuer" || keyLookup.reason === "insecure_issuer" ? "untrusted_issuer" : "key_unavailable";
22265
+ continue;
22266
+ }
22267
+ const jwtClockTolerance = opts.maxSkewSeconds ?? 60;
22268
+ try {
22269
+ const idpKey = await importJWK2(keyLookup.key, normalizeAlg(header.alg));
22270
+ await jwtVerify(token, idpKey, {
22271
+ // Pin the signature algorithm allowlist (RFC 8725 §3.1) — also rejects `alg:none`. Without
22272
+ // this, jose accepts whatever alg the resolved JWK supports, so a trusted IdP publishing a
22273
+ // non-Ed25519 (e.g. RSA/EC) `use:sig` key would let an attacker present an RS256/ES256
22274
+ // token that verifies. Matches the server-side allowlist in core/api aip-verify.
22275
+ algorithms: AIT_SIGNING_ALGS,
22276
+ clockTolerance: jwtClockTolerance,
22277
+ currentDate: opts.now !== void 0 ? new Date(opts.now * 1e3) : void 0
22278
+ });
22279
+ } catch (err) {
22280
+ lastFailure = isExpiry(err) ? "expired_token" : "idp_signature_invalid";
22281
+ continue;
22282
+ }
22283
+ const nowSec = opts.now ?? Math.floor(Date.now() / 1e3);
22284
+ if (claims.iat > nowSec + jwtClockTolerance) {
22285
+ lastFailure = "expired_token";
22286
+ continue;
22287
+ }
22288
+ const popResult = await verifyMessageSignature({
22289
+ method: ctx.method,
22290
+ authority: ctx.authority,
22291
+ path: ctx.path,
22292
+ agentIdentity: raw,
22293
+ signatureInput: ctx.signatureInput,
22294
+ signature: ctx.signature,
22295
+ cnfJwk: claims.cnf.jwk,
22296
+ now: opts.now,
22297
+ maxSkewSeconds: opts.maxSkewSeconds
22298
+ });
22299
+ if (!popResult.ok) {
22300
+ lastFailure = "pop_signature_invalid";
22301
+ continue;
22302
+ }
22303
+ return { ok: true, ait: { payload: claims, iss: claims.iss, cnfJwk: claims.cnf.jwk, token } };
22304
+ }
22305
+ return { ok: false, reason: lastFailure };
22306
+ };
22307
+ var stripBearer = (value) => {
22308
+ const trimmed = value.trim();
22309
+ return /^bearer\s+/i.test(trimmed) ? trimmed.replace(/^bearer\s+/i, "") : trimmed;
22310
+ };
22311
+ var AIT_SIGNING_ALGS = ["EdDSA", "ES256"];
22312
+ var normalizeAlg = (alg) => alg.toLowerCase() === "eddsa" ? "EdDSA" : alg;
22313
+ var isExpiry = (err) => typeof err === "object" && err !== null && err.code === "ERR_JWT_EXPIRED";
22314
+
22315
+ // src/aip/request.ts
22316
+ var readAgentIdentityHeaders = (headers) => {
22317
+ const raw = headers.get(AGENT_IDENTITY_HEADER);
22318
+ if (!raw) {
22319
+ return [];
22320
+ }
22321
+ return raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
22322
+ };
22323
+ var deriveAuthority = (req, url2) => req.headers.get("host") ?? url2.host;
22324
+ var buildVerifyContextFromRequest = (req) => {
22325
+ const url2 = new URL(req.url);
22326
+ return {
22327
+ method: req.method,
22328
+ authority: deriveAuthority(req, url2),
22329
+ path: url2.pathname,
22330
+ agentIdentityHeaders: readAgentIdentityHeaders(req.headers),
22331
+ signatureInput: req.headers.get("signature-input"),
22332
+ signature: req.headers.get("signature")
22333
+ };
22334
+ };
22335
+ var hasAgentIdentityHeader = (req) => readAgentIdentityHeaders(req.headers).length > 0;
22336
+ var readNodeHeader = (headers, name) => {
22337
+ const v = headers[name] ?? headers[name.toLowerCase()];
22338
+ if (v === void 0) {
22339
+ return void 0;
22340
+ }
22341
+ return Array.isArray(v) ? v.join(", ") : v;
22342
+ };
22343
+ var hasAgentIdentityHeaderNode = (headers) => {
22344
+ const raw = readNodeHeader(headers, "agent-identity");
22345
+ return raw !== void 0 && raw.split(",").some((s) => s.trim().length > 0);
22346
+ };
22347
+ var buildVerifyContextFromParts = (parts) => {
22348
+ const agentIdentityRaw = readNodeHeader(parts.headers, "agent-identity");
22349
+ const agentIdentityHeaders = agentIdentityRaw ? agentIdentityRaw.split(",").map((s) => s.trim()).filter((s) => s.length > 0) : [];
22350
+ const host = parts.authority ?? readNodeHeader(parts.headers, "host") ?? "";
22351
+ let path;
22352
+ try {
22353
+ path = new URL(parts.url, host ? `http://${host}` : "http://localhost").pathname;
22354
+ } catch {
22355
+ const q = parts.url.indexOf("?");
22356
+ path = q === -1 ? parts.url : parts.url.slice(0, q);
22357
+ }
22358
+ return {
22359
+ method: parts.method,
22360
+ authority: host,
22361
+ path,
22362
+ agentIdentityHeaders,
22363
+ signatureInput: readNodeHeader(parts.headers, "signature-input") ?? null,
22364
+ signature: readNodeHeader(parts.headers, "signature") ?? null
22365
+ };
22366
+ };
22367
+
22368
+ // src/aip/gate.ts
22369
+ var verifyFromContext = async (ctx, opts) => {
22370
+ const result = await verifyAit(ctx, { jwks: opts.jwks, now: opts.now, maxSkewSeconds: opts.maxSkewSeconds });
22371
+ return result.ok ? { ok: true, ait: result.ait } : { ok: false, failure: result.reason };
22372
+ };
22373
+ var verifyAitRequest = (req, opts) => verifyFromContext(buildVerifyContextFromRequest(req), opts);
22374
+ var verifyAitParts = (parts, opts) => verifyFromContext(buildVerifyContextFromParts(parts), opts);
22375
+ var aipErrorCode = (failure) => {
22376
+ switch (failure) {
22377
+ case "no_token":
22378
+ case "pop_signature_missing":
22379
+ return "agent_identity_required";
22380
+ case "untrusted_issuer":
22381
+ return "untrusted_issuer";
22382
+ case "expired_token":
22383
+ return "expired_token";
22384
+ case "invalid_claims":
22385
+ return "insufficient_claims";
22386
+ case "key_unavailable":
22387
+ return "idp_unavailable";
22388
+ case "malformed_token":
22389
+ case "idp_signature_invalid":
22390
+ case "pop_signature_invalid":
22391
+ return "invalid_signature";
22392
+ default:
22393
+ return "invalid_signature";
22394
+ }
22395
+ };
22396
+ var aipErrorStatus = (failure) => {
22397
+ switch (failure) {
22398
+ case "key_unavailable":
22399
+ return 503;
22400
+ case "untrusted_issuer":
22401
+ case "invalid_claims":
22402
+ return 403;
22403
+ default:
22404
+ return 401;
22405
+ }
22406
+ };
22407
+ var aipErrorDetail = (failure) => {
22408
+ switch (failure) {
22409
+ case "no_token":
22410
+ return "No Agent-Identity token was presented.";
22411
+ case "pop_signature_missing":
22412
+ return "The request is missing the RFC 9421 HTTP Message Signature that proves possession of the token-bound key.";
22413
+ case "untrusted_issuer":
22414
+ return "The token's issuer is not in this service's trusted-issuer list.";
22415
+ case "expired_token":
22416
+ return "The Agent Identity Token has expired.";
22417
+ case "invalid_claims":
22418
+ return "The token is missing required claims for this endpoint.";
22419
+ case "malformed_token":
22420
+ return "The Agent-Identity header could not be parsed as an Agent Identity Token.";
22421
+ case "idp_signature_invalid":
22422
+ return "The identity provider's signature on the token failed verification.";
22423
+ case "pop_signature_invalid":
22424
+ return "The request signature did not match the key bound to the token.";
22425
+ case "key_unavailable":
22426
+ return "The identity provider's signing key could not be resolved.";
22427
+ default:
22428
+ return "Token verification failed.";
22429
+ }
22430
+ };
22431
+ var buildAipErrorBody = (failure) => {
22432
+ const code = aipErrorCode(failure);
22433
+ return {
22434
+ type: `urn:aip:error:${code}`,
22435
+ title: code.replace(/_/g, " "),
22436
+ status: aipErrorStatus(failure),
22437
+ detail: aipErrorDetail(failure)
22438
+ };
22439
+ };
22440
+
22441
+ // src/aip/jwks.ts
22442
+ var JWKS_WELL_KNOWN_PATH = "/.well-known/agent-identity/jwks.json";
22443
+ var HARD_MAX_CACHE_SECONDS = 86400;
22444
+ var DEFAULT_CACHE_SECONDS = 300;
22445
+ var AGENTSCORE_CANONICAL_ISSUER = "https://agentscore.sh";
22446
+ var canonicalizeIssuer = (iss) => {
22447
+ let url2;
22448
+ try {
22449
+ url2 = new URL(iss.trim());
22450
+ } catch {
22451
+ return null;
22452
+ }
22453
+ const scheme = url2.protocol.toLowerCase();
22454
+ const host = url2.hostname.toLowerCase();
22455
+ const isDefaultPort = url2.port === "" || scheme === "https:" && url2.port === "443" || scheme === "http:" && url2.port === "80";
22456
+ const portPart = isDefaultPort ? "" : `:${url2.port}`;
22457
+ const path = url2.pathname === "/" ? "" : url2.pathname.replace(/\/$/, "");
22458
+ return `${scheme}//${host}${portPart}${path}`;
22459
+ };
22460
+ var resolveCacheSeconds = (cacheControl) => {
22461
+ if (!cacheControl) {
22462
+ return DEFAULT_CACHE_SECONDS;
22463
+ }
22464
+ if (/\bno-store\b/i.test(cacheControl) || /\bno-cache\b/i.test(cacheControl)) {
22465
+ return DEFAULT_CACHE_SECONDS;
22466
+ }
22467
+ const m = /\bmax-age\s*=\s*(\d+)/i.exec(cacheControl);
22468
+ if (!m) {
22469
+ return DEFAULT_CACHE_SECONDS;
22470
+ }
22471
+ const advertised = Number(m[1]);
22472
+ if (!Number.isFinite(advertised) || advertised <= 0) {
22473
+ return DEFAULT_CACHE_SECONDS;
22474
+ }
22475
+ return Math.min(advertised, HARD_MAX_CACHE_SECONDS);
22476
+ };
22477
+ var signingKeys = (keys) => keys.filter((k) => k.use === void 0 || k.use === "sig");
22478
+ var JwksCache = class {
22479
+ trusted;
22480
+ fetchImpl;
22481
+ now;
22482
+ userAgent;
22483
+ cache = /* @__PURE__ */ new Map();
22484
+ constructor(opts) {
22485
+ this.trusted = new Set(
22486
+ [AGENTSCORE_CANONICAL_ISSUER, ...opts.trustedIssuers ?? []].map(canonicalizeIssuer).filter((s) => s !== null)
22487
+ );
22488
+ this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
22489
+ this.now = opts.now ?? Date.now;
22490
+ this.userAgent = opts.userAgent ?? "@agentscore/commerce";
22491
+ }
22492
+ /** Is this issuer on the canonicalized trust list? */
22493
+ isTrusted(iss) {
22494
+ const canon = canonicalizeIssuer(iss);
22495
+ return canon !== null && this.trusted.has(canon);
22496
+ }
22497
+ /**
22498
+ * Resolve the signing key for `(iss, kid)`. Enforces trust + HTTPS, serves from cache when
22499
+ * fresh, and refetches once on a kid-miss before giving up.
22500
+ */
22501
+ async getKey(iss, kid) {
22502
+ const canon = canonicalizeIssuer(iss);
22503
+ if (canon === null || !this.trusted.has(canon)) {
22504
+ return { ok: false, reason: "untrusted_issuer" };
22505
+ }
22506
+ if (!canon.startsWith("https://")) {
22507
+ return { ok: false, reason: "insecure_issuer" };
22508
+ }
22509
+ const cached2 = this.cache.get(canon);
22510
+ if (cached2 && this.now() < cached2.expiresAt) {
22511
+ const hit2 = this.select(cached2.keys, kid);
22512
+ if (hit2) {
22513
+ return { ok: true, key: hit2 };
22514
+ }
22515
+ }
22516
+ const refreshed = await this.refresh(canon);
22517
+ if (!refreshed.ok) {
22518
+ return refreshed;
22519
+ }
22520
+ const hit = this.select(refreshed.keys, kid);
22521
+ return hit ? { ok: true, key: hit } : { ok: false, reason: "key_not_found" };
22522
+ }
22523
+ select(keys, kid) {
22524
+ const candidates = signingKeys(keys);
22525
+ if (kid !== void 0) {
22526
+ const byKid = candidates.find((k) => k.kid === kid);
22527
+ if (byKid) {
22528
+ return byKid;
22529
+ }
22530
+ return void 0;
22531
+ }
22532
+ return candidates.length === 1 ? candidates[0] : void 0;
22533
+ }
22534
+ async refresh(canonIssuer) {
22535
+ const url2 = `${canonIssuer}${JWKS_WELL_KNOWN_PATH}`;
22536
+ let res;
22537
+ try {
22538
+ res = await this.fetchImpl(url2, { headers: { "User-Agent": this.userAgent, Accept: "application/jwk-set+json, application/json" } });
22539
+ } catch {
22540
+ return { ok: false, reason: "fetch_failed" };
22541
+ }
22542
+ if (!res.ok) {
22543
+ return { ok: false, reason: "fetch_failed" };
22544
+ }
22545
+ let body;
22546
+ try {
22547
+ body = await res.json();
22548
+ } catch {
22549
+ return { ok: false, reason: "malformed_jwks" };
22550
+ }
22551
+ if (typeof body !== "object" || body === null || !Array.isArray(body.keys)) {
22552
+ return { ok: false, reason: "malformed_jwks" };
22553
+ }
22554
+ const keys = body.keys;
22555
+ const ttlSeconds = resolveCacheSeconds(res.headers.get("cache-control"));
22556
+ this.cache.set(canonIssuer, { keys, expiresAt: this.now() + ttlSeconds * 1e3 });
22557
+ return { ok: true, keys };
22558
+ }
22559
+ };
22560
+
21796
22561
  // src/payment/rail_spec.ts
21797
22562
  init_usdc();
21798
22563
  async function resolveRecipient(r) {
@@ -21945,10 +22710,11 @@ function buildAgentInstructions({
21945
22710
 
21946
22711
  // src/challenge/agent_memory.ts
21947
22712
  function firstEncounterAgentMemory({
21948
- firstEncounter
22713
+ firstEncounter,
22714
+ aipTrustedIssuers
21949
22715
  }) {
21950
22716
  if (!firstEncounter) return void 0;
21951
- return buildAgentMemoryHint();
22717
+ return buildAgentMemoryHint(aipTrustedIssuers);
21952
22718
  }
21953
22719
 
21954
22720
  // src/challenge/body.ts
@@ -22980,6 +23746,30 @@ function pickRail(rails2, key) {
22980
23746
  const spec = rails2[key];
22981
23747
  return spec === void 0 ? void 0 : spec;
22982
23748
  }
23749
+ function buildAipTrustedIssuers(externalIssuers) {
23750
+ const out = [AGENTSCORE_CANONICAL_ISSUER, ...externalIssuers ?? []];
23751
+ const seen = /* @__PURE__ */ new Set();
23752
+ const deduped = [];
23753
+ for (const iss of out) {
23754
+ const key = canonicalizeIssuer(iss) ?? iss;
23755
+ if (!seen.has(key)) {
23756
+ seen.add(key);
23757
+ deduped.push(iss);
23758
+ }
23759
+ }
23760
+ return deduped;
23761
+ }
23762
+ function aipTrustedIssuerSet(cfg) {
23763
+ return buildAipTrustedIssuers(cfg.trustedIssuers);
23764
+ }
23765
+ function resolveIssuerPolicy(issuerPolicies, iss) {
23766
+ const target = canonicalizeIssuer(iss);
23767
+ if (target === null) return void 0;
23768
+ for (const [key, policy] of Object.entries(issuerPolicies)) {
23769
+ if (canonicalizeIssuer(key) === target) return policy;
23770
+ }
23771
+ return void 0;
23772
+ }
22983
23773
  var Checkout = class {
22984
23774
  rails;
22985
23775
  url;
@@ -22997,6 +23787,15 @@ var Checkout = class {
22997
23787
  discoveryExtensions;
22998
23788
  discoveryProbe;
22999
23789
  _x402ServerGetter;
23790
+ /** Lazily-built JWKS cache for AIP verification, shared across requests so issuer keys
23791
+ * are fetched once and cached (per the verifier's hard 24h cap). Built on first AIT. */
23792
+ aipJwks;
23793
+ getAipJwks(cfg) {
23794
+ if (this.aipJwks === void 0) {
23795
+ this.aipJwks = new JwksCache(cfg.trustedIssuers !== void 0 ? { trustedIssuers: cfg.trustedIssuers } : {});
23796
+ }
23797
+ return this.aipJwks;
23798
+ }
23000
23799
  /**
23001
23800
  * True when the merchant has configured an identity-bearing policy flag —
23002
23801
  * `require_kyc`, `require_sanctions_clear` (name screening on the KYC
@@ -23284,7 +24083,64 @@ var Checkout = class {
23284
24083
  }
23285
24084
  return result;
23286
24085
  }
24086
+ const headers = normalizeHeadersToLowercase(ctx.request.headers);
24087
+ const walletAddress = headers["x-wallet-address"];
24088
+ const operatorToken = headers["x-operator-token"];
24089
+ let aipToken;
24090
+ let aipIssuer;
24091
+ if (gate.aip !== void 0 && hasAgentIdentityHeaderNode(headers)) {
24092
+ const aipResult = await verifyAitParts(
24093
+ {
24094
+ method: ctx.request.method,
24095
+ url: ctx.request.url,
24096
+ headers,
24097
+ ...gate.aip.authority !== void 0 && { authority: gate.aip.authority }
24098
+ },
24099
+ {
24100
+ jwks: this.getAipJwks(gate.aip),
24101
+ ...gate.aip.maxSkewSeconds !== void 0 && { maxSkewSeconds: gate.aip.maxSkewSeconds }
24102
+ }
24103
+ );
24104
+ if (!aipResult.ok) {
24105
+ const body2 = buildAipErrorBody(aipResult.failure);
24106
+ return {
24107
+ status: body2.status,
24108
+ body: body2,
24109
+ headers: {
24110
+ "content-type": "application/problem+json",
24111
+ // 503 = the IdP's JWKS was unreachable (transient infra, not a bad token). Hint a
24112
+ // short backoff so agents retry rather than uselessly re-signing.
24113
+ ...body2.status === 503 && { "retry-after": "5" }
24114
+ }
24115
+ };
24116
+ }
24117
+ aipToken = aipResult.ait.token;
24118
+ aipIssuer = aipResult.ait.iss;
24119
+ }
24120
+ const issuerPolicy = aipIssuer !== void 0 && gate.aip?.issuerPolicies !== void 0 ? resolveIssuerPolicy(gate.aip.issuerPolicies, aipIssuer) : void 0;
24121
+ const effPolicy = issuerPolicy ?? {
24122
+ ...gate.requireKyc !== void 0 && { requireKyc: gate.requireKyc },
24123
+ ...gate.requireSanctionsClear !== void 0 && { requireSanctionsClear: gate.requireSanctionsClear },
24124
+ ...gate.minAge !== void 0 && { minAge: gate.minAge },
24125
+ ...gate.blockedJurisdictions !== void 0 && { blockedJurisdictions: gate.blockedJurisdictions },
24126
+ ...gate.allowedJurisdictions !== void 0 && { allowedJurisdictions: gate.allowedJurisdictions }
24127
+ };
23287
24128
  if (gate.apiKey === void 0) {
24129
+ if (aipToken !== void 0) {
24130
+ const hasPolicy = effPolicy.requireKyc || effPolicy.requireSanctionsClear || effPolicy.minAge != null || effPolicy.blockedJurisdictions !== void 0 || effPolicy.allowedJurisdictions !== void 0;
24131
+ if (hasPolicy) {
24132
+ return {
24133
+ status: 403,
24134
+ body: {
24135
+ error: {
24136
+ code: "aip_policy_requires_api_key",
24137
+ message: "This gate declares compliance policy (KYC / age / sanctions / jurisdiction) but has no AgentScore apiKey, so the Agent Identity Token\u2019s claims cannot be evaluated. Configure gate.apiKey to enable policy enforcement on AITs."
24138
+ }
24139
+ }
24140
+ };
24141
+ }
24142
+ return null;
24143
+ }
23288
24144
  return this.runWalletSanctionsOnly(ctx);
23289
24145
  }
23290
24146
  let policyOverride;
@@ -23296,19 +24152,25 @@ var Checkout = class {
23296
24152
  apiKey: gate.apiKey,
23297
24153
  ...gate.baseUrl !== void 0 && { baseUrl: gate.baseUrl },
23298
24154
  ...gate.userAgent !== void 0 && { userAgent: gate.userAgent },
23299
- ...gate.requireKyc !== void 0 && { requireKyc: gate.requireKyc },
23300
- ...gate.requireSanctionsClear !== void 0 && { requireSanctionsClear: gate.requireSanctionsClear },
23301
- ...gate.minAge !== void 0 && { minAge: gate.minAge },
23302
- ...gate.blockedJurisdictions !== void 0 && { blockedJurisdictions: gate.blockedJurisdictions },
23303
- ...gate.allowedJurisdictions !== void 0 && { allowedJurisdictions: gate.allowedJurisdictions },
24155
+ // Compliance fields come from effPolicy the per-issuer override for the verified AIT's
24156
+ // issuer when one is configured, else the gate defaults (see effPolicy above). A whole-
24157
+ // policy replacement: an issuer override of `{ requireKyc, minAge }` sends ONLY those,
24158
+ // so sanctions / jurisdiction are not enforced for that issuer.
24159
+ ...effPolicy.requireKyc !== void 0 && { requireKyc: effPolicy.requireKyc },
24160
+ ...effPolicy.requireSanctionsClear !== void 0 && { requireSanctionsClear: effPolicy.requireSanctionsClear },
24161
+ ...effPolicy.minAge !== void 0 && { minAge: effPolicy.minAge },
24162
+ ...effPolicy.blockedJurisdictions !== void 0 && { blockedJurisdictions: effPolicy.blockedJurisdictions },
24163
+ ...effPolicy.allowedJurisdictions !== void 0 && { allowedJurisdictions: effPolicy.allowedJurisdictions },
23304
24164
  ...gate.failOpen !== void 0 && { failOpen: gate.failOpen },
23305
24165
  ...gate.cacheSeconds !== void 0 && { cacheSeconds: gate.cacheSeconds },
23306
24166
  ...gate.chain !== void 0 && { chain: gate.chain },
24167
+ // Surface AIP acceptance in the missing-identity recovery instructions + agent_memory
24168
+ // hint so agents holding an AIT learn they can present it instead of bootstrapping.
24169
+ ...gate.aip !== void 0 && { aipTrustedIssuers: aipTrustedIssuerSet(gate.aip) },
23307
24170
  // Auto-default `createSessionOnMissing` from gate config when the merchant
23308
- // didn't supply one. Matches python-commerce's behavior every gated route
23309
- // gets the bootstrap session-mint UX out of the box. Merchants who need
23310
- // custom session context or onBeforeSession side effects (goods merchants
23311
- // pre-minting an order_id) supply their own config instead.
24171
+ // didn't supply one, so every gated route gets the bootstrap session-mint UX
24172
+ // out of the box. Merchants who need custom session context or onBeforeSession
24173
+ // side effects (goods merchants pre-minting an order_id) supply their own config.
23312
24174
  createSessionOnMissing: gate.createSessionOnMissing ?? {
23313
24175
  apiKey: gate.apiKey,
23314
24176
  ...gate.baseUrl !== void 0 && { baseUrl: gate.baseUrl },
@@ -23318,10 +24180,7 @@ var Checkout = class {
23318
24180
  ...policyOverride ?? {}
23319
24181
  };
23320
24182
  const core = createAgentScoreCore(coreOpts);
23321
- const headers = normalizeHeadersToLowercase(ctx.request.headers);
23322
- const walletAddress = headers["x-wallet-address"];
23323
- const operatorToken = headers["x-operator-token"];
23324
- const identity = walletAddress !== void 0 || operatorToken !== void 0 ? {
24183
+ const identity = aipToken !== void 0 ? { aipToken } : walletAddress !== void 0 || operatorToken !== void 0 ? {
23325
24184
  ...walletAddress !== void 0 && { address: walletAddress },
23326
24185
  ...operatorToken !== void 0 && { operatorToken }
23327
24186
  } : void 0;
@@ -23340,7 +24199,7 @@ var Checkout = class {
23340
24199
  });
23341
24200
  };
23342
24201
  }
23343
- if (walletAddress !== void 0) {
24202
+ if (aipToken === void 0 && walletAddress !== void 0) {
23344
24203
  const verdict = core.getSignerVerdict(walletAddress);
23345
24204
  const sm = verdict?.signer_match;
23346
24205
  if (sm && sm.kind !== "pass") {
@@ -23685,8 +24544,13 @@ var Checkout = class {
23685
24544
  retryBody: ctx.request.body,
23686
24545
  // Merchants without an identity-bearing gate get a clean 402: no
23687
24546
  // AgentScore-identity bootstrap describing a verification flow they
23688
- // don't run. Wallet OFAC (the always-on default) doesn't need it.
23689
- agentMemory: firstEncounterAgentMemory({ firstEncounter: this.hasIdentityGate() }),
24547
+ // don't run. Wallet OFAC (the always-on default) doesn't need it. When the
24548
+ // merchant accepts AIP, advertise the agent_identity path too (AgentScore's
24549
+ // own issuer is always trusted, so this fires even with no external issuers).
24550
+ agentMemory: firstEncounterAgentMemory({
24551
+ firstEncounter: this.hasIdentityGate(),
24552
+ ...this.gate?.aip !== void 0 && { aipTrustedIssuers: aipTrustedIssuerSet(this.gate.aip) }
24553
+ }),
23690
24554
  ...ctx.pricing.product ? { product: ctx.pricing.product } : {},
23691
24555
  ...ctx.pricing.bodyExtras ? { extra: ctx.pricing.bodyExtras } : {},
23692
24556
  ...x402Accepts.length > 0 ? {
@@ -24045,47 +24909,8 @@ init_wwwauthenticate();
24045
24909
  init_directive();
24046
24910
  init_wwwauthenticate();
24047
24911
 
24048
- // src/payment/amounts.ts
24049
- function usdToAtomic(usd, opts) {
24050
- const { decimals } = opts;
24051
- if (!Number.isInteger(decimals) || decimals < 0) {
24052
- throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
24053
- }
24054
- if (typeof usd === "number") {
24055
- if (!Number.isFinite(usd)) {
24056
- throw new RangeError(`usd must be finite, got ${usd}`);
24057
- }
24058
- if (usd < 0) {
24059
- throw new RangeError(`usd must be non-negative, got ${usd}`);
24060
- }
24061
- }
24062
- const s = (typeof usd === "number" ? usd.toString() : usd).trim();
24063
- if (s.startsWith("-")) {
24064
- throw new RangeError(`usd must be non-negative, got ${s}`);
24065
- }
24066
- if (s === "NaN" || s === "Infinity") {
24067
- throw new RangeError(`usd must be finite, got ${s}`);
24068
- }
24069
- const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
24070
- if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
24071
- throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
24072
- }
24073
- const intPart = match[1] || "0";
24074
- const fracPart = match[2] ?? "";
24075
- if (fracPart.length <= decimals) {
24076
- return BigInt(intPart + fracPart.padEnd(decimals, "0"));
24077
- }
24078
- const kept = fracPart.slice(0, decimals);
24079
- const roundDigit = fracPart[decimals];
24080
- let result = BigInt(intPart + kept);
24081
- if (roundDigit >= "5") {
24082
- result += 1n;
24083
- }
24084
- return result;
24085
- }
24086
- function formatUsdCents(cents, decimals = 2) {
24087
- return (cents / 100).toFixed(decimals);
24088
- }
24912
+ // src/payment/index.ts
24913
+ init_amounts();
24089
24914
 
24090
24915
  // src/payment/solana.ts
24091
24916
  async function loadSolanaFeePayer(opts) {
@@ -24109,6 +24934,7 @@ async function loadSolanaFeePayer(opts) {
24109
24934
  }
24110
24935
 
24111
24936
  // src/payment/compose_rails.ts
24937
+ init_amounts();
24112
24938
  init_usdc();
24113
24939
  var warnedStripeBelowMinimum = false;
24114
24940
  function buildMppxComposeRails(opts) {
@@ -24153,7 +24979,13 @@ init_usdc();
24153
24979
  function buildDefaultCheckoutRails(opts) {
24154
24980
  const out = {};
24155
24981
  if (opts.tempo) {
24156
- out.tempo = { recipient: "", ...RAIL_SPEC_DEFAULTS.tempo, ...opts.tempo };
24982
+ const merged = { recipient: "", ...RAIL_SPEC_DEFAULTS.tempo, ...opts.tempo };
24983
+ if (merged.testnet) {
24984
+ if (opts.tempo.network === void 0) merged.network = "tempo-testnet";
24985
+ if (opts.tempo.chainId === void 0) merged.chainId = 42431;
24986
+ if (opts.tempo.token === void 0) merged.token = USDC.tempo.testnet.address;
24987
+ }
24988
+ out.tempo = merged;
24157
24989
  }
24158
24990
  if (opts.x402Base) {
24159
24991
  const merged = { recipient: "", ...RAIL_SPEC_DEFAULTS.x402Base, ...opts.x402Base };
@@ -24208,8 +25040,11 @@ function buildSuccessNextSteps(opts) {
24208
25040
  // src/discovery/index.ts
24209
25041
  init_well_known();
24210
25042
 
25043
+ // src/checkout_compute_first.ts
25044
+ init_amounts();
25045
+
24211
25046
  // src/quote_cache.ts
24212
- import { createHash as createHash2 } from "crypto";
25047
+ import { createHash as createHash3 } from "crypto";
24213
25048
 
24214
25049
  // src/_redis.ts
24215
25050
  async function tryCreateRedis(opts) {
@@ -24262,7 +25097,7 @@ function createQuoteCache(opts = {}) {
24262
25097
  return {
24263
25098
  bodyHashKey(prefix, body) {
24264
25099
  const canonical = JSON.stringify(canonicalize2(body));
24265
- const hash3 = createHash2("sha256").update(`${prefix}::${canonical}`).digest("hex").slice(0, 24);
25100
+ const hash3 = createHash3("sha256").update(`${prefix}::${canonical}`).digest("hex").slice(0, 24);
24266
25101
  return `${prefix}::${hash3}`;
24267
25102
  },
24268
25103
  async read(key) {
@@ -24776,15 +25611,26 @@ function defaultReadOnlyOnDenied(reason) {
24776
25611
  export {
24777
25612
  A2A_DEFAULT_TRANSPORT,
24778
25613
  A2A_PROTOCOL_VERSION,
25614
+ AGENTSCORE_CANONICAL_ISSUER,
24779
25615
  AGENTSCORE_UCP_CAPABILITY,
25616
+ AGENT_IDENTITY_HEADER,
25617
+ AIP_COVERED_COMPONENTS,
25618
+ AIP_SIGNATURE_TAG,
24780
25619
  Checkout,
24781
25620
  CheckoutValidationError,
24782
25621
  FIXABLE_DENIAL_REASONS,
25622
+ HARD_MAX_CACHE_SECONDS,
25623
+ JWKS_WELL_KNOWN_PATH,
25624
+ JwksCache,
24783
25625
  UCPSigningKey,
24784
25626
  UCPVerificationError,
24785
25627
  UCP_A2A_EXTENSION_URI,
25628
+ aipErrorCode,
25629
+ aipErrorStatus,
24786
25630
  buildA2AAgentCard,
24787
25631
  buildAgentMemoryHint,
25632
+ buildAipErrorBody,
25633
+ buildAipTrustedIssuers,
24788
25634
  buildContactSupportNextSteps,
24789
25635
  buildDefaultCheckoutRails,
24790
25636
  buildGateFromPolicy,
@@ -24793,6 +25639,8 @@ export {
24793
25639
  buildSignerMismatchBody,
24794
25640
  buildUCPProfile,
24795
25641
  buildVerificationRequiredBody,
25642
+ buildVerifyContextFromRequest,
25643
+ canonicalizeIssuer,
24796
25644
  computeFirstCheckout,
24797
25645
  createDefaultOnDenied,
24798
25646
  createQuoteCache,
@@ -24806,11 +25654,15 @@ export {
24806
25654
  formatUsdCents,
24807
25655
  generateUCPSigningKey,
24808
25656
  getIdentityStatus,
25657
+ hasAgentIdentityHeader,
24809
25658
  hasMppxHeader,
24810
25659
  hasPaymentHeader,
24811
25660
  hasX402Header,
24812
25661
  hashOperatorToken,
25662
+ isAitShape,
25663
+ isEvmNetwork,
24813
25664
  isFixableDenial,
25665
+ isSolanaNetwork,
24814
25666
  loadSolanaFeePayer,
24815
25667
  loadUCPSigningKeyFromEnv,
24816
25668
  makeMppxComposeHook,
@@ -24820,9 +25672,11 @@ export {
24820
25672
  runGateWithEnforcement,
24821
25673
  shippingCountryAllowed,
24822
25674
  shippingStateAllowed,
25675
+ signMessage,
24823
25676
  signUCPProfile,
24824
25677
  stripeSptPaymentHandler,
24825
25678
  ucpA2AExtension,
25679
+ validateAitPayload,
24826
25680
  validateShippingAgainstPolicy,
24827
25681
  validationEnvelope,
24828
25682
  validationResponseExpress,
@@ -24831,6 +25685,9 @@ export {
24831
25685
  validationResponseNextjs,
24832
25686
  validationResponseWeb,
24833
25687
  verificationAgentInstructions,
25688
+ verifyAit,
25689
+ verifyAitRequest,
25690
+ verifyMessageSignature,
24834
25691
  verifyUCPProfile,
24835
25692
  x402PaymentHandler
24836
25693
  };