@agent-score/commerce 2.1.0 → 2.1.1
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/README.md +1 -1
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs.map +1 -1
- package/dist/{checkout-Bd_4aQ6c.d.mts → checkout-BRw_caGr.d.mts} +1 -22
- package/dist/{checkout-BH-I_Ns8.d.ts → checkout-CuSNUJFX.d.ts} +1 -22
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/core.mjs.map +1 -1
- package/dist/{default_rails-BxBzcCA1.d.ts → default_rails-C5gKZJMI.d.ts} +11 -1
- package/dist/{default_rails-BWAquZeu.d.mts → default_rails-XFCuRddA.d.mts} +11 -1
- package/dist/discovery/index.d.mts +1 -1
- package/dist/discovery/index.d.ts +1 -1
- package/dist/identity/express.js +1 -1
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +1 -1
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.js +1 -1
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +1 -1
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.js +1 -1
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +1 -1
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.js +1 -1
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +1 -1
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/policy.js +22 -23363
- package/dist/identity/policy.js.map +1 -1
- package/dist/identity/policy.mjs +1 -23366
- package/dist/identity/policy.mjs.map +1 -1
- package/dist/identity/web.js +1 -1
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +1 -1
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +72 -5
- package/dist/index.d.ts +72 -5
- package/dist/index.js +256 -136
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +253 -134
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/express.js.map +1 -1
- package/dist/middleware/express.mjs.map +1 -1
- package/dist/middleware/fastify.js.map +1 -1
- package/dist/middleware/fastify.mjs.map +1 -1
- package/dist/middleware/hono.js.map +1 -1
- package/dist/middleware/hono.mjs.map +1 -1
- package/dist/middleware/nextjs.js.map +1 -1
- package/dist/middleware/nextjs.mjs.map +1 -1
- package/dist/middleware/web.js.map +1 -1
- package/dist/middleware/web.mjs.map +1 -1
- package/dist/payment/index.d.mts +13 -17
- package/dist/payment/index.d.ts +13 -17
- package/dist/payment/index.js +80 -4
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +79 -4
- package/dist/payment/index.mjs.map +1 -1
- package/dist/stripe-multichain/index.js +53 -4
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs +53 -4
- package/dist/stripe-multichain/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -20825,6 +20825,7 @@ __export(index_exports, {
|
|
|
20825
20825
|
buildMppxComposeRails: () => buildMppxComposeRails,
|
|
20826
20826
|
buildSignerMismatchBody: () => buildSignerMismatchBody,
|
|
20827
20827
|
buildUCPProfile: () => buildUCPProfile,
|
|
20828
|
+
buildVerificationRequiredBody: () => buildVerificationRequiredBody,
|
|
20828
20829
|
computeFirstCheckout: () => computeFirstCheckout,
|
|
20829
20830
|
createDefaultOnDenied: () => createDefaultOnDenied,
|
|
20830
20831
|
createQuoteCache: () => createQuoteCache,
|
|
@@ -21049,6 +21050,20 @@ var RESERVED_FIELDS = /* @__PURE__ */ new Set([
|
|
|
21049
21050
|
"actual_signer",
|
|
21050
21051
|
"linked_wallets"
|
|
21051
21052
|
]);
|
|
21053
|
+
function buildVerificationRequiredBody(reason, opts = {}) {
|
|
21054
|
+
const body = denialReasonToBody(reason);
|
|
21055
|
+
body.error = {
|
|
21056
|
+
code: "operator_verification_required",
|
|
21057
|
+
message: opts.message ?? "Identity verification is required."
|
|
21058
|
+
};
|
|
21059
|
+
if (opts.agentInstructions !== void 0) {
|
|
21060
|
+
body.agent_instructions = opts.agentInstructions;
|
|
21061
|
+
}
|
|
21062
|
+
if (opts.extra) {
|
|
21063
|
+
for (const [k, v] of Object.entries(opts.extra)) body[k] = v;
|
|
21064
|
+
}
|
|
21065
|
+
return body;
|
|
21066
|
+
}
|
|
21052
21067
|
function denialReasonToBody(reason) {
|
|
21053
21068
|
const message = reason.message ?? DEFAULT_MESSAGES[reason.code];
|
|
21054
21069
|
const body = { error: { code: reason.code, message } };
|
|
@@ -21206,7 +21221,7 @@ function createAgentScoreCore(options) {
|
|
|
21206
21221
|
} = options;
|
|
21207
21222
|
const baseUrl = stripTrailingSlashes(rawBaseUrl);
|
|
21208
21223
|
const agentMemoryHint = buildAgentMemoryHint();
|
|
21209
|
-
const defaultUa = `@agent-score/commerce@${"2.1.
|
|
21224
|
+
const defaultUa = `@agent-score/commerce@${"2.1.1"}`;
|
|
21210
21225
|
const userAgentHeader = userAgent ? `${userAgent} (${defaultUa})` : defaultUa;
|
|
21211
21226
|
const sdk = new import_sdk.AgentScore({ apiKey, baseUrl, userAgent: userAgentHeader });
|
|
21212
21227
|
const sessionSdkCache = /* @__PURE__ */ new Map();
|
|
@@ -21664,9 +21679,140 @@ var A2A_DEFAULT_TRANSPORT = DEFAULT_TRANSPORT;
|
|
|
21664
21679
|
init_ucp();
|
|
21665
21680
|
init_ucp_jwks();
|
|
21666
21681
|
|
|
21667
|
-
// src/
|
|
21682
|
+
// src/errors.ts
|
|
21683
|
+
var CheckoutValidationError = class extends Error {
|
|
21684
|
+
code;
|
|
21685
|
+
action;
|
|
21686
|
+
status;
|
|
21687
|
+
extra;
|
|
21688
|
+
constructor(opts) {
|
|
21689
|
+
super(opts.message);
|
|
21690
|
+
this.name = "CheckoutValidationError";
|
|
21691
|
+
this.code = opts.code;
|
|
21692
|
+
this.action = opts.action ?? "fix_request";
|
|
21693
|
+
this.status = opts.status ?? 400;
|
|
21694
|
+
this.extra = opts.extra;
|
|
21695
|
+
}
|
|
21696
|
+
};
|
|
21697
|
+
|
|
21698
|
+
// src/identity/policy.ts
|
|
21699
|
+
function buildGateFromPolicy(policy, base) {
|
|
21700
|
+
if (!policy || !policy.enforcement) return null;
|
|
21701
|
+
return {
|
|
21702
|
+
apiKey: base.apiKey,
|
|
21703
|
+
...base.baseUrl !== void 0 && { baseUrl: base.baseUrl },
|
|
21704
|
+
...policy.requireKyc !== void 0 && { requireKyc: policy.requireKyc },
|
|
21705
|
+
...policy.requireSanctionsClear !== void 0 && {
|
|
21706
|
+
requireSanctionsClear: policy.requireSanctionsClear
|
|
21707
|
+
},
|
|
21708
|
+
...policy.minAge !== void 0 && { minAge: policy.minAge },
|
|
21709
|
+
...policy.allowedJurisdictions !== void 0 && {
|
|
21710
|
+
allowedJurisdictions: [...policy.allowedJurisdictions]
|
|
21711
|
+
}
|
|
21712
|
+
};
|
|
21713
|
+
}
|
|
21714
|
+
async function runGateWithEnforcement(enforcement, runGate) {
|
|
21715
|
+
if (!runGate || !enforcement) return { status: "anonymous" };
|
|
21716
|
+
const outcome = await runGate();
|
|
21717
|
+
if (outcome.ok) return { status: "verified" };
|
|
21718
|
+
if (enforcement === "hard") {
|
|
21719
|
+
return {
|
|
21720
|
+
status: "denied",
|
|
21721
|
+
denialStatus: outcome.status,
|
|
21722
|
+
denialBody: outcome.body,
|
|
21723
|
+
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
21724
|
+
};
|
|
21725
|
+
}
|
|
21726
|
+
return {
|
|
21727
|
+
status: "unverified",
|
|
21728
|
+
denialStatus: outcome.status,
|
|
21729
|
+
denialBody: outcome.body,
|
|
21730
|
+
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
21731
|
+
};
|
|
21732
|
+
}
|
|
21733
|
+
function shippingCountryAllowed(country, policy) {
|
|
21734
|
+
if (!policy?.allowedShippingCountries || policy.allowedShippingCountries.length === 0) return true;
|
|
21735
|
+
const allowed = new Set(policy.allowedShippingCountries.map((c) => c.toUpperCase()));
|
|
21736
|
+
return allowed.has(country.toUpperCase());
|
|
21737
|
+
}
|
|
21738
|
+
function shippingStateAllowed(state, country, policy) {
|
|
21739
|
+
if (!policy?.allowedShippingStates || policy.allowedShippingStates.length === 0) return true;
|
|
21740
|
+
if (country.toUpperCase() !== "US") return true;
|
|
21741
|
+
const allowed = new Set(policy.allowedShippingStates.map((s) => s.toUpperCase()));
|
|
21742
|
+
return allowed.has(state.toUpperCase());
|
|
21743
|
+
}
|
|
21744
|
+
function validateShippingAgainstPolicy(opts) {
|
|
21745
|
+
const code = opts.errorCode ?? "unsupported_jurisdiction";
|
|
21746
|
+
const action = opts.errorAction ?? "change_shipping_state";
|
|
21747
|
+
const item = opts.productName ? `'${opts.productName}'` : "this item";
|
|
21748
|
+
if (!shippingCountryAllowed(opts.country, opts.policy)) {
|
|
21749
|
+
throw new CheckoutValidationError({
|
|
21750
|
+
code,
|
|
21751
|
+
message: opts.countryMessage ?? `We can't ship ${item} to ${opts.country.toUpperCase() || "<unset>"}.`,
|
|
21752
|
+
action
|
|
21753
|
+
});
|
|
21754
|
+
}
|
|
21755
|
+
if (!shippingStateAllowed(opts.state, opts.country, opts.policy)) {
|
|
21756
|
+
throw new CheckoutValidationError({
|
|
21757
|
+
code,
|
|
21758
|
+
message: opts.stateMessage ?? `We can't ship ${item} to ${opts.state.toUpperCase() || "<unset>"}.`,
|
|
21759
|
+
action
|
|
21760
|
+
});
|
|
21761
|
+
}
|
|
21762
|
+
}
|
|
21763
|
+
|
|
21764
|
+
// src/identity/tokens.ts
|
|
21668
21765
|
var import_node_crypto = require("crypto");
|
|
21669
21766
|
|
|
21767
|
+
// src/payment/payment_header.ts
|
|
21768
|
+
function toTitleCase(name) {
|
|
21769
|
+
return name.replace(/(^|-)([a-z])/g, (_m, sep, c) => sep + c.toUpperCase());
|
|
21770
|
+
}
|
|
21771
|
+
function readHeader(headers, name) {
|
|
21772
|
+
if (typeof headers.get === "function") {
|
|
21773
|
+
return headers.get(name);
|
|
21774
|
+
}
|
|
21775
|
+
const rec = headers;
|
|
21776
|
+
const v = rec[name] ?? rec[name.toLowerCase()] ?? rec[toTitleCase(name)];
|
|
21777
|
+
if (typeof v === "string") return v;
|
|
21778
|
+
if (Array.isArray(v) && typeof v[0] === "string") return v[0];
|
|
21779
|
+
return null;
|
|
21780
|
+
}
|
|
21781
|
+
function asHeaders(input) {
|
|
21782
|
+
return typeof input.headers === "object" && input instanceof Request ? input.headers : input;
|
|
21783
|
+
}
|
|
21784
|
+
function hasPaymentHeader(input) {
|
|
21785
|
+
const headers = asHeaders(input);
|
|
21786
|
+
return Boolean(
|
|
21787
|
+
readHeader(headers, "payment-signature") || readHeader(headers, "x-payment") || readHeader(headers, "authorization")?.startsWith("Payment ")
|
|
21788
|
+
);
|
|
21789
|
+
}
|
|
21790
|
+
function hasX402Header(input) {
|
|
21791
|
+
const headers = asHeaders(input);
|
|
21792
|
+
return Boolean(readHeader(headers, "payment-signature") || readHeader(headers, "x-payment"));
|
|
21793
|
+
}
|
|
21794
|
+
function hasMppxHeader(input) {
|
|
21795
|
+
const headers = asHeaders(input);
|
|
21796
|
+
return Boolean(readHeader(headers, "authorization")?.startsWith("Payment "));
|
|
21797
|
+
}
|
|
21798
|
+
|
|
21799
|
+
// src/identity/tokens.ts
|
|
21800
|
+
function hashOperatorToken(plaintext) {
|
|
21801
|
+
return (0, import_node_crypto.createHash)("sha256").update(plaintext, "utf8").digest("hex");
|
|
21802
|
+
}
|
|
21803
|
+
function extractOwnerScope(input) {
|
|
21804
|
+
const headers = asHeaders(input);
|
|
21805
|
+
const walletAddress = readHeader(headers, "x-wallet-address");
|
|
21806
|
+
const operatorToken = readHeader(headers, "x-operator-token");
|
|
21807
|
+
return {
|
|
21808
|
+
...walletAddress ? { walletAddress } : {},
|
|
21809
|
+
...operatorToken ? { operatorTokenHash: hashOperatorToken(operatorToken) } : {}
|
|
21810
|
+
};
|
|
21811
|
+
}
|
|
21812
|
+
|
|
21813
|
+
// src/checkout.ts
|
|
21814
|
+
var import_node_crypto2 = require("crypto");
|
|
21815
|
+
|
|
21670
21816
|
// src/_mppx_receipt.ts
|
|
21671
21817
|
function extractMppxReceiptHeaderFromRaw(raw) {
|
|
21672
21818
|
if (!raw || typeof raw !== "object" || !("withReceipt" in raw)) return null;
|
|
@@ -22073,6 +22219,12 @@ function buildValidationError({
|
|
|
22073
22219
|
return body;
|
|
22074
22220
|
}
|
|
22075
22221
|
|
|
22222
|
+
// src/payment/constants.ts
|
|
22223
|
+
var STRIPE_MIN_CHARGE_USD = 0.5;
|
|
22224
|
+
|
|
22225
|
+
// src/payment/mppx_server.ts
|
|
22226
|
+
var import_node_async_hooks = require("async_hooks");
|
|
22227
|
+
|
|
22076
22228
|
// src/stripe-multichain/mppx_stripe.ts
|
|
22077
22229
|
async function createMppxStripe({
|
|
22078
22230
|
profileId,
|
|
@@ -22253,6 +22405,31 @@ function wrapSolanaChargeWithFinalizedBlockhash(baseMethod, rpcUrl) {
|
|
|
22253
22405
|
}
|
|
22254
22406
|
};
|
|
22255
22407
|
}
|
|
22408
|
+
var mppxCapture = new import_node_async_hooks.AsyncLocalStorage();
|
|
22409
|
+
var consoleErrorPatched = false;
|
|
22410
|
+
function ensureConsoleErrorPatch() {
|
|
22411
|
+
if (consoleErrorPatched) return;
|
|
22412
|
+
consoleErrorPatched = true;
|
|
22413
|
+
const original = console.error.bind(console);
|
|
22414
|
+
console.error = function captureMppxInternal(...args) {
|
|
22415
|
+
if (args[0] === "mppx: internal verification error" && args[1] !== void 0) {
|
|
22416
|
+
const ctx = mppxCapture.getStore();
|
|
22417
|
+
if (ctx) {
|
|
22418
|
+
const e = args[1];
|
|
22419
|
+
const reason = typeof e?.shortMessage === "string" ? e.shortMessage : typeof e?.message === "string" ? e.message : String(args[1]);
|
|
22420
|
+
const details = e?.details;
|
|
22421
|
+
ctx.reason = typeof details === "string" && details.length > 0 ? `${reason} (${details})` : reason;
|
|
22422
|
+
}
|
|
22423
|
+
}
|
|
22424
|
+
return original(...args);
|
|
22425
|
+
};
|
|
22426
|
+
}
|
|
22427
|
+
async function runWithMppxFailureCapture(fn) {
|
|
22428
|
+
ensureConsoleErrorPatch();
|
|
22429
|
+
const ctx = { reason: null };
|
|
22430
|
+
const result = await mppxCapture.run(ctx, fn);
|
|
22431
|
+
return { result, failureReason: ctx.reason };
|
|
22432
|
+
}
|
|
22256
22433
|
|
|
22257
22434
|
// src/payment/x402_server.ts
|
|
22258
22435
|
init_networks();
|
|
@@ -22394,40 +22571,28 @@ function lazyMppxServer(opts) {
|
|
|
22394
22571
|
};
|
|
22395
22572
|
}
|
|
22396
22573
|
|
|
22397
|
-
// src/
|
|
22398
|
-
|
|
22399
|
-
|
|
22400
|
-
|
|
22401
|
-
|
|
22402
|
-
|
|
22403
|
-
|
|
22404
|
-
|
|
22405
|
-
|
|
22406
|
-
|
|
22574
|
+
// src/payment/mppx_failures.ts
|
|
22575
|
+
var TEMPO_KEY_NOT_REGISTERED = {
|
|
22576
|
+
code: "tempo_key_not_registered",
|
|
22577
|
+
status: 401,
|
|
22578
|
+
message: "Tempo rejected the transaction: signer wallet is not registered with Tempo's keychain.",
|
|
22579
|
+
nextSteps: {
|
|
22580
|
+
action: "register_tempo_key",
|
|
22581
|
+
user_message: "Your wallet is not enrolled with Tempo. Run `tempo wallet login` to complete the one-time WebAuthn enrollment (or use `tempo request` directly), then retry. To skip enrollment, switch to the Base or Solana rail on this 402."
|
|
22582
|
+
},
|
|
22583
|
+
extra: { upstream_error: "KeyNotFound", chain: "tempo" }
|
|
22584
|
+
};
|
|
22585
|
+
function classifyMppxFailure(reason) {
|
|
22586
|
+
if (!reason) return null;
|
|
22587
|
+
const lower = reason.toLowerCase();
|
|
22588
|
+
if (lower.includes("keychain validation failed") || lower.includes("keynotfound")) {
|
|
22589
|
+
return TEMPO_KEY_NOT_REGISTERED;
|
|
22407
22590
|
}
|
|
22408
|
-
const rec = headers;
|
|
22409
|
-
const v = rec[name] ?? rec[name.toLowerCase()] ?? rec[toTitleCase(name)];
|
|
22410
|
-
if (typeof v === "string") return v;
|
|
22411
|
-
if (Array.isArray(v) && typeof v[0] === "string") return v[0];
|
|
22412
22591
|
return null;
|
|
22413
22592
|
}
|
|
22414
|
-
|
|
22415
|
-
|
|
22416
|
-
|
|
22417
|
-
function hasPaymentHeader(input) {
|
|
22418
|
-
const headers = asHeaders(input);
|
|
22419
|
-
return Boolean(
|
|
22420
|
-
readHeader(headers, "payment-signature") || readHeader(headers, "x-payment") || readHeader(headers, "authorization")?.startsWith("Payment ")
|
|
22421
|
-
);
|
|
22422
|
-
}
|
|
22423
|
-
function hasX402Header(input) {
|
|
22424
|
-
const headers = asHeaders(input);
|
|
22425
|
-
return Boolean(readHeader(headers, "payment-signature") || readHeader(headers, "x-payment"));
|
|
22426
|
-
}
|
|
22427
|
-
function hasMppxHeader(input) {
|
|
22428
|
-
const headers = asHeaders(input);
|
|
22429
|
-
return Boolean(readHeader(headers, "authorization")?.startsWith("Payment "));
|
|
22430
|
-
}
|
|
22593
|
+
|
|
22594
|
+
// src/checkout.ts
|
|
22595
|
+
init_network_kind();
|
|
22431
22596
|
|
|
22432
22597
|
// src/payment/x402_settle.ts
|
|
22433
22598
|
function classifyX402SettleResult(result) {
|
|
@@ -22750,20 +22915,6 @@ function getIdentityStatus(ctx) {
|
|
|
22750
22915
|
if (decision === "allow") return "verified";
|
|
22751
22916
|
return "unverified";
|
|
22752
22917
|
}
|
|
22753
|
-
var CheckoutValidationError = class extends Error {
|
|
22754
|
-
code;
|
|
22755
|
-
action;
|
|
22756
|
-
status;
|
|
22757
|
-
extra;
|
|
22758
|
-
constructor(opts) {
|
|
22759
|
-
super(opts.message);
|
|
22760
|
-
this.name = "CheckoutValidationError";
|
|
22761
|
-
this.code = opts.code;
|
|
22762
|
-
this.action = opts.action ?? "fix_request";
|
|
22763
|
-
this.status = opts.status ?? 400;
|
|
22764
|
-
this.extra = opts.extra;
|
|
22765
|
-
}
|
|
22766
|
-
};
|
|
22767
22918
|
function resolveIdentityMetadata(ctx) {
|
|
22768
22919
|
const h = normalizeHeadersToLowercase(ctx.request.headers);
|
|
22769
22920
|
const wallet = h["x-wallet-address"];
|
|
@@ -23100,7 +23251,14 @@ var Checkout = class {
|
|
|
23100
23251
|
}
|
|
23101
23252
|
}
|
|
23102
23253
|
ctx.pricing = await this.computePricing(ctx);
|
|
23103
|
-
|
|
23254
|
+
try {
|
|
23255
|
+
await this.resolveRecipientsForCtx(ctx);
|
|
23256
|
+
} catch (err) {
|
|
23257
|
+
if (err instanceof Error && err.name === "CheckoutValidationError") {
|
|
23258
|
+
return this.validationErrorResult(ctx, err);
|
|
23259
|
+
}
|
|
23260
|
+
throw err;
|
|
23261
|
+
}
|
|
23104
23262
|
const x402ServerOk = this.x402ServerAvailable() && this.x402BaseNetwork !== null;
|
|
23105
23263
|
if (hasX402Header(request.headers) && x402ServerOk) {
|
|
23106
23264
|
const zero = await this.handleZeroSettle(ctx, "x402-base");
|
|
@@ -23171,8 +23329,16 @@ var Checkout = class {
|
|
|
23171
23329
|
...gate.failOpen !== void 0 && { failOpen: gate.failOpen },
|
|
23172
23330
|
...gate.cacheSeconds !== void 0 && { cacheSeconds: gate.cacheSeconds },
|
|
23173
23331
|
...gate.chain !== void 0 && { chain: gate.chain },
|
|
23174
|
-
|
|
23175
|
-
|
|
23332
|
+
// Auto-default `createSessionOnMissing` from gate config when the merchant
|
|
23333
|
+
// didn't supply one. Matches python-commerce's behavior — every gated route
|
|
23334
|
+
// gets the bootstrap session-mint UX out of the box. Merchants who need
|
|
23335
|
+
// custom session context or onBeforeSession side effects (goods merchants
|
|
23336
|
+
// pre-minting an order_id) supply their own config instead.
|
|
23337
|
+
createSessionOnMissing: gate.createSessionOnMissing ?? {
|
|
23338
|
+
apiKey: gate.apiKey,
|
|
23339
|
+
...gate.baseUrl !== void 0 && { baseUrl: gate.baseUrl },
|
|
23340
|
+
...gate.context !== void 0 && { context: gate.context },
|
|
23341
|
+
...gate.merchantName !== void 0 && { productName: gate.merchantName }
|
|
23176
23342
|
},
|
|
23177
23343
|
...policyOverride ?? {}
|
|
23178
23344
|
};
|
|
@@ -23269,7 +23435,7 @@ var Checkout = class {
|
|
|
23269
23435
|
return await this.buildSuccess(ctx, outcome);
|
|
23270
23436
|
}
|
|
23271
23437
|
async mintRefId(request) {
|
|
23272
|
-
if (this.mintReferenceId === void 0) return (0,
|
|
23438
|
+
if (this.mintReferenceId === void 0) return (0, import_node_crypto2.randomUUID)();
|
|
23273
23439
|
const seedCtx = { request, referenceId: "", pricing: null, recipients: {}, state: {} };
|
|
23274
23440
|
return await this.mintReferenceId(seedCtx);
|
|
23275
23441
|
}
|
|
@@ -23372,7 +23538,9 @@ var Checkout = class {
|
|
|
23372
23538
|
if (this.composeMppx === void 0) {
|
|
23373
23539
|
throw new Error("Checkout.handleMppx: composeMppx hook not configured");
|
|
23374
23540
|
}
|
|
23375
|
-
const composed = await
|
|
23541
|
+
const { result: composed, failureReason } = await runWithMppxFailureCapture(
|
|
23542
|
+
async () => this.composeMppx(ctx)
|
|
23543
|
+
);
|
|
23376
23544
|
if (composed.status === 200) {
|
|
23377
23545
|
const paymentReceiptHeader = composed.paymentReceiptHeader ?? extractMppxReceiptHeaderFromRaw(composed.raw);
|
|
23378
23546
|
const directMethod = composed.raw?.receipt?.method;
|
|
@@ -23391,6 +23559,22 @@ var Checkout = class {
|
|
|
23391
23559
|
};
|
|
23392
23560
|
return await this.buildSuccess(ctx, outcome);
|
|
23393
23561
|
}
|
|
23562
|
+
const classified = classifyMppxFailure(failureReason);
|
|
23563
|
+
if (classified !== null) {
|
|
23564
|
+
return {
|
|
23565
|
+
status: classified.status,
|
|
23566
|
+
body: buildValidationError({
|
|
23567
|
+
code: classified.code,
|
|
23568
|
+
message: classified.message,
|
|
23569
|
+
nextSteps: classified.nextSteps,
|
|
23570
|
+
...classified.extra && { extra: classified.extra }
|
|
23571
|
+
}),
|
|
23572
|
+
headers: { ...composed.headers ?? {} },
|
|
23573
|
+
referenceId: ctx.referenceId,
|
|
23574
|
+
settled: false,
|
|
23575
|
+
settlePhase: "verify_failed"
|
|
23576
|
+
};
|
|
23577
|
+
}
|
|
23394
23578
|
return {
|
|
23395
23579
|
status: 400,
|
|
23396
23580
|
body: buildValidationError({
|
|
@@ -23409,7 +23593,11 @@ var Checkout = class {
|
|
|
23409
23593
|
throw new Error("Checkout.emit402: pricing not computed");
|
|
23410
23594
|
}
|
|
23411
23595
|
await this.resolveRecipientsForCtx(ctx);
|
|
23412
|
-
|
|
23596
|
+
let emitRails = applyRecipientOverrides(this.rails, ctx.recipients);
|
|
23597
|
+
if (ctx.pricing.amountUsd < STRIPE_MIN_CHARGE_USD && emitRails.stripe !== void 0) {
|
|
23598
|
+
const { stripe: _stripe, ...rest } = emitRails;
|
|
23599
|
+
emitRails = rest;
|
|
23600
|
+
}
|
|
23413
23601
|
const accepted = await buildAcceptedMethods({
|
|
23414
23602
|
tempo: pickRail(emitRails, "tempo"),
|
|
23415
23603
|
x402_base: pickRail(emitRails, "x402_base"),
|
|
@@ -23812,87 +24000,6 @@ Checkout.prototype.mountUcpRoutesFastify = function(app, opts) {
|
|
|
23812
24000
|
app.options(jwksPath, preflight);
|
|
23813
24001
|
};
|
|
23814
24002
|
|
|
23815
|
-
// src/identity/policy.ts
|
|
23816
|
-
function buildGateFromPolicy(policy, base) {
|
|
23817
|
-
if (!policy || !policy.enforcement) return null;
|
|
23818
|
-
return {
|
|
23819
|
-
apiKey: base.apiKey,
|
|
23820
|
-
...base.baseUrl !== void 0 && { baseUrl: base.baseUrl },
|
|
23821
|
-
...policy.requireKyc !== void 0 && { requireKyc: policy.requireKyc },
|
|
23822
|
-
...policy.requireSanctionsClear !== void 0 && {
|
|
23823
|
-
requireSanctionsClear: policy.requireSanctionsClear
|
|
23824
|
-
},
|
|
23825
|
-
...policy.minAge !== void 0 && { minAge: policy.minAge },
|
|
23826
|
-
...policy.allowedJurisdictions !== void 0 && {
|
|
23827
|
-
allowedJurisdictions: [...policy.allowedJurisdictions]
|
|
23828
|
-
}
|
|
23829
|
-
};
|
|
23830
|
-
}
|
|
23831
|
-
async function runGateWithEnforcement(enforcement, runGate) {
|
|
23832
|
-
if (!runGate || !enforcement) return { status: "anonymous" };
|
|
23833
|
-
const outcome = await runGate();
|
|
23834
|
-
if (outcome.ok) return { status: "verified" };
|
|
23835
|
-
if (enforcement === "hard") {
|
|
23836
|
-
return {
|
|
23837
|
-
status: "denied",
|
|
23838
|
-
denialStatus: outcome.status,
|
|
23839
|
-
denialBody: outcome.body,
|
|
23840
|
-
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
23841
|
-
};
|
|
23842
|
-
}
|
|
23843
|
-
return {
|
|
23844
|
-
status: "unverified",
|
|
23845
|
-
denialStatus: outcome.status,
|
|
23846
|
-
denialBody: outcome.body,
|
|
23847
|
-
...outcome.reason !== void 0 && { denialReason: outcome.reason }
|
|
23848
|
-
};
|
|
23849
|
-
}
|
|
23850
|
-
function shippingCountryAllowed(country, policy) {
|
|
23851
|
-
if (!policy?.allowedShippingCountries || policy.allowedShippingCountries.length === 0) return true;
|
|
23852
|
-
const allowed = new Set(policy.allowedShippingCountries.map((c) => c.toUpperCase()));
|
|
23853
|
-
return allowed.has(country.toUpperCase());
|
|
23854
|
-
}
|
|
23855
|
-
function shippingStateAllowed(state, country, policy) {
|
|
23856
|
-
if (!policy?.allowedShippingStates || policy.allowedShippingStates.length === 0) return true;
|
|
23857
|
-
if (country.toUpperCase() !== "US") return true;
|
|
23858
|
-
const allowed = new Set(policy.allowedShippingStates.map((s) => s.toUpperCase()));
|
|
23859
|
-
return allowed.has(state.toUpperCase());
|
|
23860
|
-
}
|
|
23861
|
-
function validateShippingAgainstPolicy(opts) {
|
|
23862
|
-
const code = opts.errorCode ?? "unsupported_jurisdiction";
|
|
23863
|
-
const action = opts.errorAction ?? "change_shipping_state";
|
|
23864
|
-
const item = opts.productName ? `'${opts.productName}'` : "this item";
|
|
23865
|
-
if (!shippingCountryAllowed(opts.country, opts.policy)) {
|
|
23866
|
-
throw new CheckoutValidationError({
|
|
23867
|
-
code,
|
|
23868
|
-
message: opts.countryMessage ?? `We can't ship ${item} to ${opts.country.toUpperCase() || "<unset>"}.`,
|
|
23869
|
-
action
|
|
23870
|
-
});
|
|
23871
|
-
}
|
|
23872
|
-
if (!shippingStateAllowed(opts.state, opts.country, opts.policy)) {
|
|
23873
|
-
throw new CheckoutValidationError({
|
|
23874
|
-
code,
|
|
23875
|
-
message: opts.stateMessage ?? `We can't ship ${item} to ${opts.state.toUpperCase() || "<unset>"}.`,
|
|
23876
|
-
action
|
|
23877
|
-
});
|
|
23878
|
-
}
|
|
23879
|
-
}
|
|
23880
|
-
|
|
23881
|
-
// src/identity/tokens.ts
|
|
23882
|
-
var import_node_crypto2 = require("crypto");
|
|
23883
|
-
function hashOperatorToken(plaintext) {
|
|
23884
|
-
return (0, import_node_crypto2.createHash)("sha256").update(plaintext, "utf8").digest("hex");
|
|
23885
|
-
}
|
|
23886
|
-
function extractOwnerScope(input) {
|
|
23887
|
-
const headers = asHeaders(input);
|
|
23888
|
-
const walletAddress = readHeader(headers, "x-wallet-address");
|
|
23889
|
-
const operatorToken = readHeader(headers, "x-operator-token");
|
|
23890
|
-
return {
|
|
23891
|
-
...walletAddress ? { walletAddress } : {},
|
|
23892
|
-
...operatorToken ? { operatorTokenHash: hashOperatorToken(operatorToken) } : {}
|
|
23893
|
-
};
|
|
23894
|
-
}
|
|
23895
|
-
|
|
23896
24003
|
// src/payment/index.ts
|
|
23897
24004
|
init_directive();
|
|
23898
24005
|
init_networks();
|
|
@@ -23969,6 +24076,7 @@ async function loadSolanaFeePayer(opts) {
|
|
|
23969
24076
|
|
|
23970
24077
|
// src/payment/compose_rails.ts
|
|
23971
24078
|
init_usdc();
|
|
24079
|
+
var warnedStripeBelowMinimum = false;
|
|
23972
24080
|
function buildMppxComposeRails(opts) {
|
|
23973
24081
|
const rails2 = [];
|
|
23974
24082
|
if (opts.tempoRecipient) {
|
|
@@ -23990,7 +24098,17 @@ function buildMppxComposeRails(opts) {
|
|
|
23990
24098
|
}]);
|
|
23991
24099
|
}
|
|
23992
24100
|
if (opts.includeStripe !== false) {
|
|
23993
|
-
|
|
24101
|
+
const amountUsdNumeric = Number(opts.amountUsd);
|
|
24102
|
+
if (Number.isFinite(amountUsdNumeric) && amountUsdNumeric < STRIPE_MIN_CHARGE_USD) {
|
|
24103
|
+
if (!warnedStripeBelowMinimum) {
|
|
24104
|
+
warnedStripeBelowMinimum = true;
|
|
24105
|
+
console.warn(
|
|
24106
|
+
`[buildMppxComposeRails] Dropping stripe/charge rail: amountUsd=${opts.amountUsd} is below Stripe's $${STRIPE_MIN_CHARGE_USD.toFixed(2)} USD minimum. Stripe's fixed ~$0.30 fee makes sub-50-cent charges unprofitable (and many accounts reject PI creation with amount_too_small below this floor). Pass includeStripe: false to suppress this warning.`
|
|
24107
|
+
);
|
|
24108
|
+
}
|
|
24109
|
+
} else {
|
|
24110
|
+
rails2.push(["stripe/charge", { amount: opts.amountUsd, currency: "usd", decimals: 2 }]);
|
|
24111
|
+
}
|
|
23994
24112
|
}
|
|
23995
24113
|
return rails2;
|
|
23996
24114
|
}
|
|
@@ -24181,10 +24299,11 @@ function computeFirstCheckout(opts) {
|
|
|
24181
24299
|
const tempoRecipient = recipients.tempo;
|
|
24182
24300
|
const x402BaseRecipient = recipients.x402_base;
|
|
24183
24301
|
const solanaRecipient = recipients.solana_mpp;
|
|
24302
|
+
const includeStripeInDiscovery = opts.rails.stripe !== void 0 && Number(totalUsd) >= STRIPE_MIN_CHARGE_USD;
|
|
24184
24303
|
const accepted = await buildAcceptedMethods({
|
|
24185
24304
|
...tempoRecipient && opts.rails.tempo && { tempo: { ...opts.rails.tempo, recipient: tempoRecipient } },
|
|
24186
24305
|
...solanaRecipient && opts.rails.solana_mpp && { solana_mpp: { ...opts.rails.solana_mpp, recipient: solanaRecipient } },
|
|
24187
|
-
...
|
|
24306
|
+
...includeStripeInDiscovery && { stripe: opts.rails.stripe }
|
|
24188
24307
|
});
|
|
24189
24308
|
if (x402BaseRecipient && opts.rails.x402_base) {
|
|
24190
24309
|
try {
|
|
@@ -24608,6 +24727,7 @@ function defaultReadOnlyOnDenied(reason) {
|
|
|
24608
24727
|
buildMppxComposeRails,
|
|
24609
24728
|
buildSignerMismatchBody,
|
|
24610
24729
|
buildUCPProfile,
|
|
24730
|
+
buildVerificationRequiredBody,
|
|
24611
24731
|
computeFirstCheckout,
|
|
24612
24732
|
createDefaultOnDenied,
|
|
24613
24733
|
createQuoteCache,
|