@agent-score/commerce 2.1.1 → 2.3.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 (66) hide show
  1. package/README.md +2 -2
  2. package/dist/challenge/index.d.mts +3 -3
  3. package/dist/challenge/index.d.ts +3 -3
  4. package/dist/challenge/index.js +7 -5
  5. package/dist/challenge/index.js.map +1 -1
  6. package/dist/challenge/index.mjs +7 -5
  7. package/dist/challenge/index.mjs.map +1 -1
  8. package/dist/{checkout-BRw_caGr.d.mts → checkout-Ceo1_rVJ.d.mts} +38 -2
  9. package/dist/{checkout-CuSNUJFX.d.ts → checkout-ChyOi7aU.d.ts} +38 -2
  10. package/dist/core.js +4 -3
  11. package/dist/core.js.map +1 -1
  12. package/dist/core.mjs +4 -3
  13. package/dist/core.mjs.map +1 -1
  14. package/dist/{default_rails-C5gKZJMI.d.ts → default_rails-DtR_E9N9.d.ts} +1 -1
  15. package/dist/{default_rails-XFCuRddA.d.mts → default_rails-K25PtWrL.d.mts} +1 -1
  16. package/dist/discovery/index.d.mts +4 -4
  17. package/dist/discovery/index.d.ts +4 -4
  18. package/dist/identity/express.d.mts +4 -3
  19. package/dist/identity/express.d.ts +4 -3
  20. package/dist/identity/express.js +4 -3
  21. package/dist/identity/express.js.map +1 -1
  22. package/dist/identity/express.mjs +4 -3
  23. package/dist/identity/express.mjs.map +1 -1
  24. package/dist/identity/fastify.d.mts +4 -3
  25. package/dist/identity/fastify.d.ts +4 -3
  26. package/dist/identity/fastify.js +4 -3
  27. package/dist/identity/fastify.js.map +1 -1
  28. package/dist/identity/fastify.mjs +4 -3
  29. package/dist/identity/fastify.mjs.map +1 -1
  30. package/dist/identity/hono.d.mts +4 -3
  31. package/dist/identity/hono.d.ts +4 -3
  32. package/dist/identity/hono.js +4 -3
  33. package/dist/identity/hono.js.map +1 -1
  34. package/dist/identity/hono.mjs +4 -3
  35. package/dist/identity/hono.mjs.map +1 -1
  36. package/dist/identity/nextjs.js +4 -3
  37. package/dist/identity/nextjs.js.map +1 -1
  38. package/dist/identity/nextjs.mjs +4 -3
  39. package/dist/identity/nextjs.mjs.map +1 -1
  40. package/dist/identity/web.js +4 -3
  41. package/dist/identity/web.js.map +1 -1
  42. package/dist/identity/web.mjs +4 -3
  43. package/dist/identity/web.mjs.map +1 -1
  44. package/dist/index.d.mts +7 -7
  45. package/dist/index.d.ts +7 -7
  46. package/dist/index.js +139 -13
  47. package/dist/index.js.map +1 -1
  48. package/dist/index.mjs +139 -13
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/payment/index.d.mts +3 -3
  51. package/dist/payment/index.d.ts +3 -3
  52. package/dist/payment/index.js +2 -0
  53. package/dist/payment/index.js.map +1 -1
  54. package/dist/payment/index.mjs +2 -0
  55. package/dist/payment/index.mjs.map +1 -1
  56. package/dist/{pricing-DHfH3ogG.d.ts → pricing-B3-aKxSz.d.ts} +5 -3
  57. package/dist/{pricing-4n5Ota0D.d.mts → pricing-BReyZiqN.d.mts} +5 -3
  58. package/dist/{rail_spec-D6qzh3J0.d.mts → rail_spec-B1239jPp.d.mts} +25 -0
  59. package/dist/{rail_spec-D6qzh3J0.d.ts → rail_spec-B1239jPp.d.ts} +25 -0
  60. package/dist/stripe-multichain/index.d.mts +61 -11
  61. package/dist/stripe-multichain/index.d.ts +61 -11
  62. package/dist/stripe-multichain/index.js +84 -43
  63. package/dist/stripe-multichain/index.js.map +1 -1
  64. package/dist/stripe-multichain/index.mjs +83 -43
  65. package/dist/stripe-multichain/index.mjs.map +1 -1
  66. package/package.json +9 -9
package/dist/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { VerifyWalletSignerResult, DenialReason } from './core.js';
2
2
  export { AccountVerification, AgentIdentity, AgentMemoryHint, AgentScoreCore, AssessResult, CreateSessionOnMissing, DenialCode, EvaluateOutcome, OperatorVerification, PolicyCheck, PolicyResult, SignerVerdict, buildAgentMemoryHint } from './core.js';
3
3
  export { P as PaymentSigner, S as SignerNetwork, e as extractPaymentSigner, a as extractPaymentSignerFromAuth, b as extractSignerForPrecheck, r as readX402PaymentHeader } from './signer-3FAit11j.js';
4
- import { q as UCPSigningKey, n as UCPProfile } from './checkout-CuSNUJFX.js';
5
- export { A as AGENTSCORE_UCP_CAPABILITY, a as AgentScoreGatePolicy, C as Checkout, b as CheckoutContext, c as CheckoutGateConfig, d as CheckoutRailSpec, e as CheckoutRequest, f as CheckoutResult, g as ComposeMppxFn, D as DiscoveryProbeConfig, G as GateDenial, I as IsCachedAddressFn, M as MountUcpRoutesOptions, h as MppxComposeOutcome, O as OnSettledFn, P as PreValidateFn, i as PricingFn, j as PricingResult, R as RecipientsFn, k as ReferenceIdFn, l as RunGateFn, S as SettleOutcome, U as UCPCapabilityBinding, m as UCPPaymentHandlerBinding, o as UCPProfileBody, p as UCPServiceBinding, r as buildUCPProfile, s as getIdentityStatus, t as makeMppxComposeHook, u as mppPaymentHandler, v as pricingResult, w as stripeSptPaymentHandler, x as validationEnvelope, y as validationResponseExpress, z as validationResponseFastify, B as validationResponseHono, E as validationResponseNextjs, F as validationResponseWeb, H as x402PaymentHandler } from './checkout-CuSNUJFX.js';
4
+ import { q as UCPSigningKey, n as UCPProfile } from './checkout-ChyOi7aU.js';
5
+ export { A as AGENTSCORE_UCP_CAPABILITY, a as AgentScoreGatePolicy, C as Checkout, b as CheckoutContext, c as CheckoutGateConfig, d as CheckoutRailSpec, e as CheckoutRequest, f as CheckoutResult, g as ComposeMppxFn, D as DiscoveryProbeConfig, G as GateDenial, I as IsCachedAddressFn, M as MountUcpRoutesOptions, h as MppxComposeOutcome, O as OnSettledFn, P as PreValidateFn, i as PricingFn, j as PricingResult, R as RecipientsFn, k as ReferenceIdFn, l as RunGateFn, S as SettleOutcome, U as UCPCapabilityBinding, m as UCPPaymentHandlerBinding, o as UCPProfileBody, p as UCPServiceBinding, r as buildUCPProfile, s as getIdentityStatus, t as makeMppxComposeHook, u as mppPaymentHandler, v as pricingResult, w as stripeSptPaymentHandler, x as validationEnvelope, y as validationResponseExpress, z as validationResponseFastify, B as validationResponseHono, E as validationResponseNextjs, F as validationResponseWeb, H as x402PaymentHandler } from './checkout-ChyOi7aU.js';
6
6
  export { EnforcementMode, GateResult, IdentityStatus, PolicyBlock, buildGateFromPolicy, runGateWithEnforcement, shippingCountryAllowed, shippingStateAllowed, validateShippingAgainstPolicy } from './identity/policy.js';
7
- import { H as HeadersLike } from './default_rails-C5gKZJMI.js';
8
- export { c as buildDefaultCheckoutRails, d as buildMppxComposeRails, f as formatUsdCents, h as hasMppxHeader, e as hasPaymentHeader, g as hasX402Header, l as loadSolanaFeePayer } from './default_rails-C5gKZJMI.js';
9
- import { T as TempoRailSpec, X as X402BaseRailSpec, S as SolanaMppRailSpec, b as StripeRailSpec } from './rail_spec-D6qzh3J0.js';
10
- export { c as TempoSessionRailSpec } from './rail_spec-D6qzh3J0.js';
7
+ import { H as HeadersLike } from './default_rails-DtR_E9N9.js';
8
+ export { c as buildDefaultCheckoutRails, d as buildMppxComposeRails, f as formatUsdCents, h as hasMppxHeader, e as hasPaymentHeader, g as hasX402Header, l as loadSolanaFeePayer } from './default_rails-DtR_E9N9.js';
9
+ import { T as TempoRailSpec, X as X402BaseRailSpec, S as SolanaMppRailSpec, b as StripeRailSpec } from './rail_spec-B1239jPp.js';
10
+ export { c as TempoSessionRailSpec } from './rail_spec-B1239jPp.js';
11
11
  import { Context } from 'hono';
12
- import './pricing-DHfH3ogG.js';
12
+ import './pricing-B3-aKxSz.js';
13
13
  import './x402_server-Ciz2mls2.js';
14
14
 
15
15
  /**
package/dist/index.js CHANGED
@@ -20061,11 +20061,12 @@ function toClient(method, options) {
20061
20061
  };
20062
20062
  }
20063
20063
  function toServer(method, options) {
20064
- const { authorize, defaults, html, request, respond, stableBinding, transport, verify: verify3 } = options;
20064
+ const { authorize, defaults, extensions, html, request, respond, stableBinding, transport, verify: verify3 } = options;
20065
20065
  return {
20066
20066
  ...method,
20067
20067
  authorize,
20068
20068
  defaults,
20069
+ extensions,
20069
20070
  html,
20070
20071
  request,
20071
20072
  respond,
@@ -21221,7 +21222,7 @@ function createAgentScoreCore(options) {
21221
21222
  } = options;
21222
21223
  const baseUrl = stripTrailingSlashes(rawBaseUrl);
21223
21224
  const agentMemoryHint = buildAgentMemoryHint();
21224
- const defaultUa = `@agent-score/commerce@${"2.1.1"}`;
21225
+ const defaultUa = `@agent-score/commerce@${"2.3.0"}`;
21225
21226
  const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
21226
21227
  const sdk = new import_sdk.AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
21227
21228
  const sessionSdkCache = /* @__PURE__ */ new Map();
@@ -21358,8 +21359,9 @@ function createAgentScoreCore(options) {
21358
21359
  ...Object.keys(policy).length > 0 ? { policy } : {},
21359
21360
  // Pre-extracted payment signer (by the adapter middleware). When present, the API
21360
21361
  // composes BOTH signer_match (wallet-binding) and signer_sanctions (OFAC SDN wallet
21361
- // check) verdicts on the response in one round trip. Under
21362
- // policy.require_sanctions_clear, a signer_sanctions hit flips decision -> deny inline.
21362
+ // check) verdicts on the response in one round trip. Wallet-OFAC enforcement on the
21363
+ // signer block is unconditional — a signer_sanctions hit flips decision -> deny
21364
+ // regardless of policy.require_sanctions_clear (which gates the separate NAME screen).
21363
21365
  ...signer && { signer: { address: signer.address, network: signer.network } }
21364
21366
  };
21365
21367
  const result = identity.address ? await sdk.assess(identity.address, { ...opts, operatorToken: identity.operatorToken }) : await sdk.assess(null, { ...opts, operatorToken: identity.operatorToken });
@@ -21841,6 +21843,16 @@ async function deriveMppxReceiptMethod(raw) {
21841
21843
  return extractMppxReceiptMethod(header);
21842
21844
  }
21843
21845
 
21846
+ // src/_warnings.ts
21847
+ var warnedNoApiKey = false;
21848
+ function warnMissingApiKeyOnce(label) {
21849
+ if (warnedNoApiKey) return;
21850
+ warnedNoApiKey = true;
21851
+ console.warn(
21852
+ `[${label}] AGENTSCORE_API_KEY is not set \u2014 wallet OFAC SDN sanctions are NOT being enforced. Set the env var to enable strict-liability protection on settle.`
21853
+ );
21854
+ }
21855
+
21844
21856
  // src/payment/rail_spec.ts
21845
21857
  init_usdc();
21846
21858
  async function resolveRecipient(r) {
@@ -22072,14 +22084,16 @@ function buildHowToPay({
22072
22084
  const d = decimals ?? 2;
22073
22085
  const defaultMaxSpend = totalNum >= 1 ? (Math.ceil(totalNum) + 1).toFixed(d) : totalNum.toFixed(d);
22074
22086
  const maxSpendStr = String(maxSpend ?? defaultMaxSpend);
22087
+ const gateless = opTokenPlaceholder === null;
22075
22088
  const opToken = opTokenPlaceholder ?? "<your_opc_token>";
22089
+ const opTokenHeaderFlag = gateless ? "" : `-H 'X-Operator-Token: ${opToken}' `;
22076
22090
  const block = {};
22077
22091
  if (rails2.tempo) {
22078
22092
  const networkName = rails2.tempo.testnet ? "tempo-testnet" : rails2.tempo.network ?? RAIL_SPEC_DEFAULTS.tempo.network;
22079
22093
  const chainId = rails2.tempo.chainId ?? RAIL_SPEC_DEFAULTS.tempo.chainId;
22080
22094
  const recommend = rails2.tempo.recommend ?? RAIL_SPEC_DEFAULTS.tempo.recommend;
22081
- const tempoCommand = `tempo request -X POST -H 'X-Operator-Token: ${opToken}' -H 'Content-Type: application/json' --json '${retryBodyJson}' --max-spend ${maxSpendStr} ${url2}`;
22082
- const payCommand = `agentscore-pay pay POST ${url2} --chain tempo -H 'X-Operator-Token: ${opToken}' -H 'Content-Type: application/json' -d '${retryBodyJson}' --max-spend ${maxSpendStr}`;
22095
+ const tempoCommand = `tempo request -X POST ${opTokenHeaderFlag}-H 'Content-Type: application/json' --json '${retryBodyJson}' --max-spend ${maxSpendStr} ${url2}`;
22096
+ const payCommand = `agentscore-pay pay POST ${url2} --chain tempo ${opTokenHeaderFlag}-H 'Content-Type: application/json' -d '${retryBodyJson}' --max-spend ${maxSpendStr}`;
22083
22097
  block.tempo = {
22084
22098
  setup: TEMPO_SETUP,
22085
22099
  prerequisite: `Run \`tempo wallet whoami\` and confirm USDC.e balance on ${networkName} (chain ${chainId}) is at least $${maxSpendStr}. If the tempo CLI is not installed, run the setup commands above first.`,
@@ -22093,7 +22107,7 @@ function buildHowToPay({
22093
22107
  block.x402_base = {
22094
22108
  setup: PAY_SETUP_BASE,
22095
22109
  prerequisite: `Run \`agentscore-pay balance --chain base\` and confirm USDC balance on Base (${network}) is at least $${maxSpendStr}. If the CLI is not installed, run the setup commands above first.`,
22096
- command: `agentscore-pay pay POST ${url2} --chain base -H 'X-Operator-Token: ${opToken}' -H 'Content-Type: application/json' -d '${retryBodyJson}' --max-spend ${maxSpendStr}`,
22110
+ command: `agentscore-pay pay POST ${url2} --chain base ${opTokenHeaderFlag}-H 'Content-Type: application/json' -d '${retryBodyJson}' --max-spend ${maxSpendStr}`,
22097
22111
  what_it_does: "Pays via USDC on Base."
22098
22112
  };
22099
22113
  }
@@ -22102,7 +22116,7 @@ function buildHowToPay({
22102
22116
  block.solana_mpp = {
22103
22117
  setup: PAY_SETUP_SOLANA,
22104
22118
  prerequisite: `Run \`agentscore-pay balance --chain solana\` and confirm USDC balance on Solana (${network}) is at least $${maxSpendStr}. If the CLI is not installed, run the setup commands above first.`,
22105
- command: `agentscore-pay pay POST ${url2} --chain solana -H 'X-Operator-Token: ${opToken}' -H 'Content-Type: application/json' -d '${retryBodyJson}' --max-spend ${maxSpendStr}`,
22119
+ command: `agentscore-pay pay POST ${url2} --chain solana ${opTokenHeaderFlag}-H 'Content-Type: application/json' -d '${retryBodyJson}' --max-spend ${maxSpendStr}`,
22106
22120
  what_it_does: "Pays via USDC on Solana."
22107
22121
  };
22108
22122
  }
@@ -22124,7 +22138,7 @@ function buildHowToPay({
22124
22138
  ];
22125
22139
  stripe.command_link_cli = [
22126
22140
  `SPEND_ID=$(link-cli spend-request create --payment-method-id <csmrpd_id_from_payment_methods_list> --credential-type shared_payment_token --network-id ${stripeCfg.profileId} --amount ${amountCents} --context "${sptContext}" --request-approval --output-json | jq -r .id)`,
22127
- `link-cli mpp pay ${url2} --spend-request-id $SPEND_ID --method POST --data '${retryBodyJson}' --header 'X-Operator-Token: ${opToken}' --output-json`
22141
+ gateless ? `link-cli mpp pay ${url2} --spend-request-id $SPEND_ID --method POST --data '${retryBodyJson}' --output-json` : `link-cli mpp pay ${url2} --spend-request-id $SPEND_ID --method POST --data '${retryBodyJson}' --header 'X-Operator-Token: ${opToken}' --output-json`
22128
22142
  ];
22129
22143
  stripe.what_it_does_link_cli = "Mints a one-time-use SharedPaymentToken scoped to this purchase (user approves in Link wallet), then submits it as the payment credential.";
22130
22144
  } else if (linkCliBlocked) {
@@ -22344,11 +22358,13 @@ async function registerSolana(spec) {
22344
22358
  "createMppxServer: SolanaMppRailSpec requires a string recipient (per-order factories not supported here)."
22345
22359
  );
22346
22360
  }
22361
+ const ataCreationRequired = spec.ataCreationRequired !== false;
22347
22362
  const baseMethod = solanaMpp.charge({
22348
22363
  recipient: spec.recipient,
22349
22364
  currency: spec.token ?? defaultMint,
22350
22365
  decimals: spec.decimals ?? defaultDecimals,
22351
22366
  network,
22367
+ ...ataCreationRequired ? { splits: [{ recipient: spec.recipient, amount: "0", ataCreationRequired: true }] } : {},
22352
22368
  ...spec.rpcUrl ? { rpcUrl: spec.rpcUrl } : {},
22353
22369
  ...spec.signer ? { signer: spec.signer } : {},
22354
22370
  ...spec.tokenProgram ? { tokenProgram: spec.tokenProgram } : {}
@@ -23041,6 +23057,23 @@ var Checkout = class {
23041
23057
  discoveryExtensions;
23042
23058
  discoveryProbe;
23043
23059
  _x402ServerGetter;
23060
+ /**
23061
+ * True when the merchant has configured an identity-bearing policy flag —
23062
+ * `require_kyc`, `require_sanctions_clear` (name screening on the KYC
23063
+ * identity), `min_age`, or jurisdiction lists. Wallet OFAC SDN enforcement
23064
+ * (the always-on default) does NOT count as an identity gate; agents don't
23065
+ * need an AgentScore credential to satisfy it.
23066
+ *
23067
+ * Used to conditionally emit AgentScore identity boilerplate in 402 bodies
23068
+ * (`agent_memory`, `X-Operator-Token` references in per-rail commands).
23069
+ */
23070
+ hasIdentityGate() {
23071
+ const g = this.gate;
23072
+ if (!g) return false;
23073
+ return Boolean(
23074
+ g.requireKyc || g.requireSanctionsClear || g.minAge !== void 0 || g.allowedJurisdictions && g.allowedJurisdictions.length > 0 || g.blockedJurisdictions && g.blockedJurisdictions.length > 0
23075
+ );
23076
+ }
23044
23077
  constructor(opts) {
23045
23078
  const x402Server = opts.x402Server;
23046
23079
  let x402ServerGetter;
@@ -23238,8 +23271,8 @@ var Checkout = class {
23238
23271
  }
23239
23272
  }
23240
23273
  const hasPaymentHeader2 = hasX402Header(request.headers) || hasMppxHeader(request.headers);
23241
- if (this.gate !== void 0 && hasPaymentHeader2) {
23242
- const denial = await this.runGate(ctx);
23274
+ if (hasPaymentHeader2) {
23275
+ const denial = this.gate !== void 0 ? await this.runGate(ctx) : await this.runWalletSanctionsOnly(ctx);
23243
23276
  if (denial !== null) {
23244
23277
  return {
23245
23278
  status: denial.status,
@@ -23311,7 +23344,9 @@ var Checkout = class {
23311
23344
  }
23312
23345
  return result;
23313
23346
  }
23314
- if (gate.apiKey === void 0) return null;
23347
+ if (gate.apiKey === void 0) {
23348
+ return this.runWalletSanctionsOnly(ctx);
23349
+ }
23315
23350
  let policyOverride;
23316
23351
  if (gate.perRequestPolicy !== void 0) {
23317
23352
  policyOverride = await gate.perRequestPolicy(ctx);
@@ -23401,6 +23436,58 @@ var Checkout = class {
23401
23436
  const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
23402
23437
  return { status, body };
23403
23438
  }
23439
+ /**
23440
+ * Wallet OFAC SDN enforcement.
23441
+ *
23442
+ * Runs on settle (payment header present) when either `this.gate` is
23443
+ * undefined OR a gate is configured but has no `apiKey` to reach
23444
+ * `/v1/assess` for full policy enforcement (fallback to the
23445
+ * strict-liability default).
23446
+ *
23447
+ * Env knobs:
23448
+ * - `AGENTSCORE_API_KEY` — required. No key → one-time warning + skip
23449
+ * (dev/testnet pattern; production should always configure a key).
23450
+ * - `AGENTSCORE_BASE_URL` — optional override for staging/dev API
23451
+ * (e.g. `https://api-dev.agentscore.sh` or `http://localhost:3002`).
23452
+ *
23453
+ * Stripe SPT (no extractable wallet signer) → skip silently; Stripe runs
23454
+ * its own OFAC screen on the buyer's Stripe account at customer creation.
23455
+ *
23456
+ * Calls `/v1/assess` with the signer wallet as both the primary address
23457
+ * and the signer block. The API enforces signer-sanctions unconditionally
23458
+ * when a signer is present (no policy flag needed). Denies on OFAC SDN
23459
+ * hit; fail-closed on unavailable lookup (strict liability — falsely
23460
+ * allowing a sanctioned settle is an OFAC violation, falsely denying a
23461
+ * clean buyer is just bad UX).
23462
+ */
23463
+ async runWalletSanctionsOnly(ctx) {
23464
+ const apiKey = process.env.AGENTSCORE_API_KEY;
23465
+ if (!apiKey) {
23466
+ warnMissingApiKeyOnce("checkout");
23467
+ return null;
23468
+ }
23469
+ const headers = normalizeHeadersToLowercase(ctx.request.headers);
23470
+ const x402Header = headers["payment-signature"] ?? headers["x-payment"];
23471
+ const signer = await extractPaymentSignerFromAuth(headers["authorization"], x402Header);
23472
+ if (!signer) {
23473
+ return null;
23474
+ }
23475
+ const baseUrl = process.env.AGENTSCORE_BASE_URL;
23476
+ const core = createAgentScoreCore({
23477
+ apiKey,
23478
+ ...baseUrl !== void 0 && { baseUrl }
23479
+ });
23480
+ const outcome = await core.evaluate(
23481
+ { address: signer.address },
23482
+ ctx,
23483
+ signer
23484
+ );
23485
+ if (outcome.kind === "allow") return null;
23486
+ const reason = outcome.reason;
23487
+ const body = denialReasonToBody(reason);
23488
+ const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
23489
+ return { status, body };
23490
+ }
23404
23491
  async handleZeroSettle(ctx, rail) {
23405
23492
  if (!this.zeroSettleCarveOut || ctx.pricing === null) return null;
23406
23493
  const cents = Math.round(ctx.pricing.amountUsd * 100);
@@ -23616,6 +23703,10 @@ var Checkout = class {
23616
23703
  retryBodyJson: JSON.stringify(ctx.request.body),
23617
23704
  totalUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
23618
23705
  rails: howToPayRails,
23706
+ // Merchants without an identity-bearing policy flag get clean commands
23707
+ // without an X-Operator-Token header — agents don't need one to satisfy
23708
+ // wallet OFAC enforcement (the always-on default).
23709
+ ...this.hasIdentityGate() ? {} : { opTokenPlaceholder: null },
23619
23710
  ...ctx.pricing.decimals !== void 0 && { decimals: ctx.pricing.decimals }
23620
23711
  });
23621
23712
  const pricingBlock = ctx.pricing.block ?? buildPricingBlock({
@@ -23652,7 +23743,10 @@ var Checkout = class {
23652
23743
  pricing: pricingBlock,
23653
23744
  amountUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
23654
23745
  retryBody: ctx.request.body,
23655
- agentMemory: firstEncounterAgentMemory({ firstEncounter: true }),
23746
+ // Merchants without an identity-bearing gate get a clean 402: no
23747
+ // AgentScore-identity bootstrap describing a verification flow they
23748
+ // don't run. Wallet OFAC (the always-on default) doesn't need it.
23749
+ agentMemory: firstEncounterAgentMemory({ firstEncounter: this.hasIdentityGate() }),
23656
23750
  ...ctx.pricing.product ? { product: ctx.pricing.product } : {},
23657
23751
  ...ctx.pricing.bodyExtras ? { extra: ctx.pricing.bodyExtras } : {},
23658
23752
  ...x402Accepts.length > 0 ? {
@@ -24380,6 +24474,36 @@ function computeFirstCheckout(opts) {
24380
24474
  );
24381
24475
  return new Response(JSON.stringify(body402), { status: 402, headers });
24382
24476
  }
24477
+ async function enforceWalletSanctions(req, referenceId) {
24478
+ const apiKey = process.env.AGENTSCORE_API_KEY;
24479
+ if (!apiKey) {
24480
+ warnMissingApiKeyOnce(`${opts.name}.computeFirst`);
24481
+ return null;
24482
+ }
24483
+ const x402Header = readX402PaymentHeader(req);
24484
+ const signer = await extractPaymentSigner(req, x402Header);
24485
+ if (!signer) return null;
24486
+ const baseUrl = process.env.AGENTSCORE_BASE_URL;
24487
+ const core = createAgentScoreCore({
24488
+ apiKey,
24489
+ ...baseUrl !== void 0 && { baseUrl }
24490
+ });
24491
+ const outcome = await core.evaluate({ address: signer.address }, void 0, signer);
24492
+ if (outcome.kind === "allow") return null;
24493
+ const reason = outcome.reason;
24494
+ const body = denialReasonToBody(reason);
24495
+ const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
24496
+ return new Response(
24497
+ JSON.stringify({
24498
+ id: referenceId,
24499
+ endpoint: opts.name,
24500
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
24501
+ payment_status: "failed",
24502
+ ...body
24503
+ }),
24504
+ { status, headers: { "Content-Type": "application/json" } }
24505
+ );
24506
+ }
24383
24507
  async function handleX402Settle(req, referenceId, cachedBody, priceCents, recipients) {
24384
24508
  const verified = await verifyX402Request({
24385
24509
  request: req,
@@ -24578,6 +24702,8 @@ function computeFirstCheckout(opts) {
24578
24702
  { status: 400, headers: { "Content-Type": "application/json" } }
24579
24703
  );
24580
24704
  }
24705
+ const ofacDenial = await enforceWalletSanctions(req, referenceId);
24706
+ if (ofacDenial !== null) return ofacDenial;
24581
24707
  if (hasX402Header(req.headers)) return handleX402Settle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
24582
24708
  return handleMppSettle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
24583
24709
  }