@agent-score/commerce 2.1.1 → 2.2.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.
- package/dist/challenge/index.d.mts +2 -2
- package/dist/challenge/index.d.ts +2 -2
- package/dist/challenge/index.js +7 -5
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs +7 -5
- package/dist/challenge/index.mjs.map +1 -1
- package/dist/{checkout-BRw_caGr.d.mts → checkout-CKQE2QpJ.d.mts} +37 -1
- package/dist/{checkout-CuSNUJFX.d.ts → checkout-CfgxgPZL.d.ts} +37 -1
- package/dist/core.js +4 -3
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +4 -3
- package/dist/core.mjs.map +1 -1
- package/dist/discovery/index.d.mts +3 -3
- package/dist/discovery/index.d.ts +3 -3
- package/dist/identity/express.d.mts +4 -3
- package/dist/identity/express.d.ts +4 -3
- package/dist/identity/express.js +4 -3
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +4 -3
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.d.mts +4 -3
- package/dist/identity/fastify.d.ts +4 -3
- package/dist/identity/fastify.js +4 -3
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +4 -3
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.d.mts +4 -3
- package/dist/identity/hono.d.ts +4 -3
- package/dist/identity/hono.js +4 -3
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +4 -3
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.js +4 -3
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +4 -3
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/web.js +4 -3
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +4 -3
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +137 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -13
- package/dist/index.mjs.map +1 -1
- package/dist/{pricing-4n5Ota0D.d.mts → pricing-dSI3ePmE.d.mts} +4 -2
- package/dist/{pricing-DHfH3ogG.d.ts → pricing-uFGRNoGl.d.ts} +4 -2
- package/dist/stripe-multichain/index.js +2 -1
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs +2 -1
- package/dist/stripe-multichain/index.mjs.map +1 -1
- package/package.json +6 -6
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.
|
|
21225
|
+
const defaultUa = `@agent-score/commerce@${"2.2.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.
|
|
21362
|
-
//
|
|
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
|
|
22082
|
-
const payCommand = `agentscore-pay pay POST ${url2} --chain tempo
|
|
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
|
|
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
|
|
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) {
|
|
@@ -23041,6 +23055,23 @@ var Checkout = class {
|
|
|
23041
23055
|
discoveryExtensions;
|
|
23042
23056
|
discoveryProbe;
|
|
23043
23057
|
_x402ServerGetter;
|
|
23058
|
+
/**
|
|
23059
|
+
* True when the merchant has configured an identity-bearing policy flag —
|
|
23060
|
+
* `require_kyc`, `require_sanctions_clear` (name screening on the KYC
|
|
23061
|
+
* identity), `min_age`, or jurisdiction lists. Wallet OFAC SDN enforcement
|
|
23062
|
+
* (the always-on default) does NOT count as an identity gate; agents don't
|
|
23063
|
+
* need an AgentScore credential to satisfy it.
|
|
23064
|
+
*
|
|
23065
|
+
* Used to conditionally emit AgentScore identity boilerplate in 402 bodies
|
|
23066
|
+
* (`agent_memory`, `X-Operator-Token` references in per-rail commands).
|
|
23067
|
+
*/
|
|
23068
|
+
hasIdentityGate() {
|
|
23069
|
+
const g = this.gate;
|
|
23070
|
+
if (!g) return false;
|
|
23071
|
+
return Boolean(
|
|
23072
|
+
g.requireKyc || g.requireSanctionsClear || g.minAge !== void 0 || g.allowedJurisdictions && g.allowedJurisdictions.length > 0 || g.blockedJurisdictions && g.blockedJurisdictions.length > 0
|
|
23073
|
+
);
|
|
23074
|
+
}
|
|
23044
23075
|
constructor(opts) {
|
|
23045
23076
|
const x402Server = opts.x402Server;
|
|
23046
23077
|
let x402ServerGetter;
|
|
@@ -23238,8 +23269,8 @@ var Checkout = class {
|
|
|
23238
23269
|
}
|
|
23239
23270
|
}
|
|
23240
23271
|
const hasPaymentHeader2 = hasX402Header(request.headers) || hasMppxHeader(request.headers);
|
|
23241
|
-
if (
|
|
23242
|
-
const denial = await this.runGate(ctx);
|
|
23272
|
+
if (hasPaymentHeader2) {
|
|
23273
|
+
const denial = this.gate !== void 0 ? await this.runGate(ctx) : await this.runWalletSanctionsOnly(ctx);
|
|
23243
23274
|
if (denial !== null) {
|
|
23244
23275
|
return {
|
|
23245
23276
|
status: denial.status,
|
|
@@ -23311,7 +23342,9 @@ var Checkout = class {
|
|
|
23311
23342
|
}
|
|
23312
23343
|
return result;
|
|
23313
23344
|
}
|
|
23314
|
-
if (gate.apiKey === void 0)
|
|
23345
|
+
if (gate.apiKey === void 0) {
|
|
23346
|
+
return this.runWalletSanctionsOnly(ctx);
|
|
23347
|
+
}
|
|
23315
23348
|
let policyOverride;
|
|
23316
23349
|
if (gate.perRequestPolicy !== void 0) {
|
|
23317
23350
|
policyOverride = await gate.perRequestPolicy(ctx);
|
|
@@ -23401,6 +23434,58 @@ var Checkout = class {
|
|
|
23401
23434
|
const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
|
|
23402
23435
|
return { status, body };
|
|
23403
23436
|
}
|
|
23437
|
+
/**
|
|
23438
|
+
* Wallet OFAC SDN enforcement.
|
|
23439
|
+
*
|
|
23440
|
+
* Runs on settle (payment header present) when either `this.gate` is
|
|
23441
|
+
* undefined OR a gate is configured but has no `apiKey` to reach
|
|
23442
|
+
* `/v1/assess` for full policy enforcement (fallback to the
|
|
23443
|
+
* strict-liability default).
|
|
23444
|
+
*
|
|
23445
|
+
* Env knobs:
|
|
23446
|
+
* - `AGENTSCORE_API_KEY` — required. No key → one-time warning + skip
|
|
23447
|
+
* (dev/testnet pattern; production should always configure a key).
|
|
23448
|
+
* - `AGENTSCORE_BASE_URL` — optional override for staging/dev API
|
|
23449
|
+
* (e.g. `https://api-dev.agentscore.sh` or `http://localhost:3002`).
|
|
23450
|
+
*
|
|
23451
|
+
* Stripe SPT (no extractable wallet signer) → skip silently; Stripe runs
|
|
23452
|
+
* its own OFAC screen on the buyer's Stripe account at customer creation.
|
|
23453
|
+
*
|
|
23454
|
+
* Calls `/v1/assess` with the signer wallet as both the primary address
|
|
23455
|
+
* and the signer block. The API enforces signer-sanctions unconditionally
|
|
23456
|
+
* when a signer is present (no policy flag needed). Denies on OFAC SDN
|
|
23457
|
+
* hit; fail-closed on unavailable lookup (strict liability — falsely
|
|
23458
|
+
* allowing a sanctioned settle is an OFAC violation, falsely denying a
|
|
23459
|
+
* clean buyer is just bad UX).
|
|
23460
|
+
*/
|
|
23461
|
+
async runWalletSanctionsOnly(ctx) {
|
|
23462
|
+
const apiKey = process.env.AGENTSCORE_API_KEY;
|
|
23463
|
+
if (!apiKey) {
|
|
23464
|
+
warnMissingApiKeyOnce("checkout");
|
|
23465
|
+
return null;
|
|
23466
|
+
}
|
|
23467
|
+
const headers = normalizeHeadersToLowercase(ctx.request.headers);
|
|
23468
|
+
const x402Header = headers["payment-signature"] ?? headers["x-payment"];
|
|
23469
|
+
const signer = await extractPaymentSignerFromAuth(headers["authorization"], x402Header);
|
|
23470
|
+
if (!signer) {
|
|
23471
|
+
return null;
|
|
23472
|
+
}
|
|
23473
|
+
const baseUrl = process.env.AGENTSCORE_BASE_URL;
|
|
23474
|
+
const core = createAgentScoreCore({
|
|
23475
|
+
apiKey,
|
|
23476
|
+
...baseUrl !== void 0 && { baseUrl }
|
|
23477
|
+
});
|
|
23478
|
+
const outcome = await core.evaluate(
|
|
23479
|
+
{ address: signer.address },
|
|
23480
|
+
ctx,
|
|
23481
|
+
signer
|
|
23482
|
+
);
|
|
23483
|
+
if (outcome.kind === "allow") return null;
|
|
23484
|
+
const reason = outcome.reason;
|
|
23485
|
+
const body = denialReasonToBody(reason);
|
|
23486
|
+
const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
|
|
23487
|
+
return { status, body };
|
|
23488
|
+
}
|
|
23404
23489
|
async handleZeroSettle(ctx, rail) {
|
|
23405
23490
|
if (!this.zeroSettleCarveOut || ctx.pricing === null) return null;
|
|
23406
23491
|
const cents = Math.round(ctx.pricing.amountUsd * 100);
|
|
@@ -23616,6 +23701,10 @@ var Checkout = class {
|
|
|
23616
23701
|
retryBodyJson: JSON.stringify(ctx.request.body),
|
|
23617
23702
|
totalUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
|
|
23618
23703
|
rails: howToPayRails,
|
|
23704
|
+
// Merchants without an identity-bearing policy flag get clean commands
|
|
23705
|
+
// without an X-Operator-Token header — agents don't need one to satisfy
|
|
23706
|
+
// wallet OFAC enforcement (the always-on default).
|
|
23707
|
+
...this.hasIdentityGate() ? {} : { opTokenPlaceholder: null },
|
|
23619
23708
|
...ctx.pricing.decimals !== void 0 && { decimals: ctx.pricing.decimals }
|
|
23620
23709
|
});
|
|
23621
23710
|
const pricingBlock = ctx.pricing.block ?? buildPricingBlock({
|
|
@@ -23652,7 +23741,10 @@ var Checkout = class {
|
|
|
23652
23741
|
pricing: pricingBlock,
|
|
23653
23742
|
amountUsd: ctx.pricing.amountUsd.toFixed(pricingDecimals),
|
|
23654
23743
|
retryBody: ctx.request.body,
|
|
23655
|
-
|
|
23744
|
+
// Merchants without an identity-bearing gate get a clean 402: no
|
|
23745
|
+
// AgentScore-identity bootstrap describing a verification flow they
|
|
23746
|
+
// don't run. Wallet OFAC (the always-on default) doesn't need it.
|
|
23747
|
+
agentMemory: firstEncounterAgentMemory({ firstEncounter: this.hasIdentityGate() }),
|
|
23656
23748
|
...ctx.pricing.product ? { product: ctx.pricing.product } : {},
|
|
23657
23749
|
...ctx.pricing.bodyExtras ? { extra: ctx.pricing.bodyExtras } : {},
|
|
23658
23750
|
...x402Accepts.length > 0 ? {
|
|
@@ -24380,6 +24472,36 @@ function computeFirstCheckout(opts) {
|
|
|
24380
24472
|
);
|
|
24381
24473
|
return new Response(JSON.stringify(body402), { status: 402, headers });
|
|
24382
24474
|
}
|
|
24475
|
+
async function enforceWalletSanctions(req, referenceId) {
|
|
24476
|
+
const apiKey = process.env.AGENTSCORE_API_KEY;
|
|
24477
|
+
if (!apiKey) {
|
|
24478
|
+
warnMissingApiKeyOnce(`${opts.name}.computeFirst`);
|
|
24479
|
+
return null;
|
|
24480
|
+
}
|
|
24481
|
+
const x402Header = readX402PaymentHeader(req);
|
|
24482
|
+
const signer = await extractPaymentSigner(req, x402Header);
|
|
24483
|
+
if (!signer) return null;
|
|
24484
|
+
const baseUrl = process.env.AGENTSCORE_BASE_URL;
|
|
24485
|
+
const core = createAgentScoreCore({
|
|
24486
|
+
apiKey,
|
|
24487
|
+
...baseUrl !== void 0 && { baseUrl }
|
|
24488
|
+
});
|
|
24489
|
+
const outcome = await core.evaluate({ address: signer.address }, void 0, signer);
|
|
24490
|
+
if (outcome.kind === "allow") return null;
|
|
24491
|
+
const reason = outcome.reason;
|
|
24492
|
+
const body = denialReasonToBody(reason);
|
|
24493
|
+
const status = reason.code === "token_expired" || reason.code === "invalid_credential" ? 401 : reason.code === "api_error" ? 503 : 403;
|
|
24494
|
+
return new Response(
|
|
24495
|
+
JSON.stringify({
|
|
24496
|
+
id: referenceId,
|
|
24497
|
+
endpoint: opts.name,
|
|
24498
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24499
|
+
payment_status: "failed",
|
|
24500
|
+
...body
|
|
24501
|
+
}),
|
|
24502
|
+
{ status, headers: { "Content-Type": "application/json" } }
|
|
24503
|
+
);
|
|
24504
|
+
}
|
|
24383
24505
|
async function handleX402Settle(req, referenceId, cachedBody, priceCents, recipients) {
|
|
24384
24506
|
const verified = await verifyX402Request({
|
|
24385
24507
|
request: req,
|
|
@@ -24578,6 +24700,8 @@ function computeFirstCheckout(opts) {
|
|
|
24578
24700
|
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
24579
24701
|
);
|
|
24580
24702
|
}
|
|
24703
|
+
const ofacDenial = await enforceWalletSanctions(req, referenceId);
|
|
24704
|
+
if (ofacDenial !== null) return ofacDenial;
|
|
24581
24705
|
if (hasX402Header(req.headers)) return handleX402Settle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
|
|
24582
24706
|
return handleMppSettle(req, referenceId, quote2.body, quote2.priceCents, quote2.recipients);
|
|
24583
24707
|
}
|