@agentcash/discovery 1.1.1 → 1.1.3
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/cli.cjs +31 -22
- package/dist/cli.js +31 -22
- package/dist/index.cjs +35 -21
- package/dist/index.d.cts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +35 -21
- package/dist/schemas.cjs +1 -2
- package/dist/schemas.d.cts +18 -90
- package/dist/schemas.d.ts +18 -90
- package/dist/schemas.js +1 -2
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -13807,7 +13807,7 @@ config(en_default());
|
|
|
13807
13807
|
|
|
13808
13808
|
// src/schemas.ts
|
|
13809
13809
|
var OpenApiPaymentInfoSchema = external_exports.object({
|
|
13810
|
-
pricingMode: external_exports.
|
|
13810
|
+
pricingMode: external_exports.string(),
|
|
13811
13811
|
price: external_exports.string().optional(),
|
|
13812
13812
|
minPrice: external_exports.string().optional(),
|
|
13813
13813
|
maxPrice: external_exports.string().optional(),
|
|
@@ -13864,7 +13864,6 @@ var WellKnownDocSchema = external_exports.object({
|
|
|
13864
13864
|
version: external_exports.number().optional(),
|
|
13865
13865
|
resources: external_exports.array(external_exports.string()).default([]),
|
|
13866
13866
|
mppResources: external_exports.array(external_exports.string()).optional(),
|
|
13867
|
-
// isMmmEnabled
|
|
13868
13867
|
description: external_exports.string().optional(),
|
|
13869
13868
|
ownershipProofs: external_exports.array(external_exports.string()).optional(),
|
|
13870
13869
|
instructions: external_exports.string().optional()
|
|
@@ -13929,7 +13928,11 @@ var DEFAULT_MISSING_METHOD = "POST";
|
|
|
13929
13928
|
// src/core/lib/url.ts
|
|
13930
13929
|
function ensureProtocol(target) {
|
|
13931
13930
|
const trimmed = target.trim();
|
|
13932
|
-
|
|
13931
|
+
if (/^https?:\/\//i.test(trimmed)) return trimmed;
|
|
13932
|
+
const host = trimmed.split("/")[0] ?? "";
|
|
13933
|
+
const hostname3 = host.split(":")[0] ?? "";
|
|
13934
|
+
const isLocal = hostname3 === "localhost" || hostname3 === "127.0.0.1" || hostname3 === "::1";
|
|
13935
|
+
return `${isLocal ? "http" : "https"}://${trimmed}`;
|
|
13933
13936
|
}
|
|
13934
13937
|
function normalizeOrigin(target) {
|
|
13935
13938
|
const url2 = new URL(ensureProtocol(target));
|
|
@@ -13970,9 +13973,6 @@ function fetchSafe(url2, init) {
|
|
|
13970
13973
|
return import_neverthrow.ResultAsync.fromPromise(fetch(url2, init), toFetchError);
|
|
13971
13974
|
}
|
|
13972
13975
|
|
|
13973
|
-
// src/mmm-enabled.ts
|
|
13974
|
-
var isMmmEnabled = () => "1.1.1".includes("-mmm");
|
|
13975
|
-
|
|
13976
13976
|
// src/core/source/openapi/index.ts
|
|
13977
13977
|
var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
|
|
13978
13978
|
const routes = [];
|
|
@@ -13981,11 +13981,8 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
|
|
|
13981
13981
|
const operation = pathItem[httpMethod.toLowerCase()];
|
|
13982
13982
|
if (!operation) continue;
|
|
13983
13983
|
const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
|
|
13984
|
-
if (!authMode) continue;
|
|
13985
13984
|
const p = operation["x-payment-info"];
|
|
13986
|
-
const protocols = (p?.protocols ?? []).filter(
|
|
13987
|
-
(proto) => proto !== "mpp" || isMmmEnabled()
|
|
13988
|
-
);
|
|
13985
|
+
const protocols = (p?.protocols ?? []).filter((proto) => proto.length > 0);
|
|
13989
13986
|
const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
|
|
13990
13987
|
pricingMode: p.pricingMode,
|
|
13991
13988
|
...p.price ? { price: p.price } : {},
|
|
@@ -14083,7 +14080,9 @@ function getWellKnown(origin, headers, signal) {
|
|
|
14083
14080
|
function formatPrice(pricing) {
|
|
14084
14081
|
if (pricing.pricingMode === "fixed") return `$${pricing.price}`;
|
|
14085
14082
|
if (pricing.pricingMode === "range") return `$${pricing.minPrice}-$${pricing.maxPrice}`;
|
|
14086
|
-
|
|
14083
|
+
if (pricing.pricingMode === "quote")
|
|
14084
|
+
return pricing.maxPrice ? `up to $${pricing.maxPrice}` : "quote";
|
|
14085
|
+
return `unknown pricing mode: ${pricing.pricingMode}`;
|
|
14087
14086
|
}
|
|
14088
14087
|
function checkL2ForOpenAPI(openApi) {
|
|
14089
14088
|
const routes = openApi.routes.map((route) => ({
|
|
@@ -14091,12 +14090,13 @@ function checkL2ForOpenAPI(openApi) {
|
|
|
14091
14090
|
method: route.method,
|
|
14092
14091
|
summary: route.summary ?? `${route.method} ${route.path}`,
|
|
14093
14092
|
...route.authMode ? { authMode: route.authMode } : {},
|
|
14094
|
-
...route.pricing ? { price: formatPrice(route.pricing) } : {},
|
|
14093
|
+
...route.pricing ? { price: formatPrice(route.pricing), pricingMode: route.pricing.pricingMode } : {},
|
|
14095
14094
|
...route.protocols?.length ? { protocols: route.protocols } : {}
|
|
14096
14095
|
}));
|
|
14097
14096
|
return {
|
|
14098
14097
|
...openApi.info.title ? { title: openApi.info.title } : {},
|
|
14099
14098
|
...openApi.info.description ? { description: openApi.info.description } : {},
|
|
14099
|
+
...openApi.info.version ? { version: openApi.info.version } : {},
|
|
14100
14100
|
routes,
|
|
14101
14101
|
source: "openapi"
|
|
14102
14102
|
};
|
|
@@ -14139,6 +14139,7 @@ var AUDIT_CODES = {
|
|
|
14139
14139
|
L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
|
|
14140
14140
|
L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
|
|
14141
14141
|
L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
|
|
14142
|
+
L2_PRICING_MODE_UNKNOWN: "L2_PRICING_MODE_UNKNOWN",
|
|
14142
14143
|
L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
|
|
14143
14144
|
// ─── L3 endpoint advisory checks ─────────────────────────────────────────────
|
|
14144
14145
|
L3_NOT_FOUND: "L3_NOT_FOUND",
|
|
@@ -14189,6 +14190,7 @@ function getWarningsForWellKnown(wellKnown) {
|
|
|
14189
14190
|
}
|
|
14190
14191
|
|
|
14191
14192
|
// src/audit/warnings/l2.ts
|
|
14193
|
+
var KNOWN_PRICING_MODES = /* @__PURE__ */ new Set(["fixed", "range", "quote"]);
|
|
14192
14194
|
var ROUTE_COUNT_HIGH = 40;
|
|
14193
14195
|
function getWarningsForL2(l2) {
|
|
14194
14196
|
const warnings = [];
|
|
@@ -14228,6 +14230,15 @@ function getWarningsForL2(l2) {
|
|
|
14228
14230
|
path: route.path
|
|
14229
14231
|
});
|
|
14230
14232
|
}
|
|
14233
|
+
if (route.pricingMode && !KNOWN_PRICING_MODES.has(route.pricingMode)) {
|
|
14234
|
+
warnings.push({
|
|
14235
|
+
code: AUDIT_CODES.L2_PRICING_MODE_UNKNOWN,
|
|
14236
|
+
severity: "warn",
|
|
14237
|
+
message: `Route ${loc} has unrecognized pricingMode "${route.pricingMode}".`,
|
|
14238
|
+
hint: `Expected one of: ${[...KNOWN_PRICING_MODES].join(", ")}.`,
|
|
14239
|
+
path: route.path
|
|
14240
|
+
});
|
|
14241
|
+
}
|
|
14231
14242
|
if (route.authMode === "paid") {
|
|
14232
14243
|
if (!route.price) {
|
|
14233
14244
|
warnings.push({
|
|
@@ -14958,7 +14969,7 @@ function detectProtocols(response) {
|
|
|
14958
14969
|
}
|
|
14959
14970
|
const authHeader = response.headers.get("www-authenticate")?.toLowerCase() ?? "";
|
|
14960
14971
|
if (authHeader.includes("x402")) protocols.add("x402");
|
|
14961
|
-
if (
|
|
14972
|
+
if (authHeader.includes("mpp")) protocols.add("mpp");
|
|
14962
14973
|
return [...protocols];
|
|
14963
14974
|
}
|
|
14964
14975
|
function buildProbeUrl(url2, method, inputBody) {
|
|
@@ -15038,7 +15049,7 @@ function parseAuthParams(segment) {
|
|
|
15038
15049
|
return params;
|
|
15039
15050
|
}
|
|
15040
15051
|
function extractPaymentOptions4(wwwAuthenticate) {
|
|
15041
|
-
if (!
|
|
15052
|
+
if (!wwwAuthenticate) return [];
|
|
15042
15053
|
const options = [];
|
|
15043
15054
|
for (const segment of wwwAuthenticate.split(/,\s*(?=Payment\s)/i)) {
|
|
15044
15055
|
const stripped = segment.replace(/^Payment\s+/i, "").trim();
|
|
@@ -15067,12 +15078,10 @@ function extractPaymentOptions4(wwwAuthenticate) {
|
|
|
15067
15078
|
if (!asset || !amount) continue;
|
|
15068
15079
|
options.push({
|
|
15069
15080
|
protocol: "mpp",
|
|
15070
|
-
// isMmmEnabled
|
|
15071
15081
|
paymentMethod,
|
|
15072
15082
|
intent,
|
|
15073
15083
|
realm,
|
|
15074
15084
|
network: `tempo:${String(chainId)}`,
|
|
15075
|
-
// isMmmEnabled
|
|
15076
15085
|
asset,
|
|
15077
15086
|
amount,
|
|
15078
15087
|
...decimals != null ? { decimals } : {},
|
|
@@ -15200,7 +15209,7 @@ function parseOperationProtocols(operation) {
|
|
|
15200
15209
|
const paymentInfo = operation["x-payment-info"];
|
|
15201
15210
|
if (!isRecord(paymentInfo) || !Array.isArray(paymentInfo.protocols)) return void 0;
|
|
15202
15211
|
const protocols = paymentInfo.protocols.filter(
|
|
15203
|
-
(protocol) => typeof protocol === "string" && protocol.length > 0
|
|
15212
|
+
(protocol) => typeof protocol === "string" && protocol.length > 0
|
|
15204
15213
|
);
|
|
15205
15214
|
return protocols.length > 0 ? protocols : void 0;
|
|
15206
15215
|
}
|
|
@@ -15231,8 +15240,7 @@ function getL3ForProbe(probe, path, method) {
|
|
|
15231
15240
|
const outputSchema = probeResult.paymentRequiredBody ? parseOutputSchema(probeResult.paymentRequiredBody) : void 0;
|
|
15232
15241
|
const paymentOptions = [
|
|
15233
15242
|
...probeResult.paymentRequiredBody ? extractPaymentOptions3(probeResult.paymentRequiredBody) : [],
|
|
15234
|
-
...
|
|
15235
|
-
// isMmmEnabled
|
|
15243
|
+
...extractPaymentOptions4(probeResult.wwwAuthenticate)
|
|
15236
15244
|
];
|
|
15237
15245
|
return {
|
|
15238
15246
|
source: "probe",
|
|
@@ -15272,7 +15280,7 @@ async function checkEndpointSchema(options) {
|
|
|
15272
15280
|
const endpoint = new URL(ensureProtocol(options.url));
|
|
15273
15281
|
const origin = normalizeOrigin(endpoint.origin);
|
|
15274
15282
|
const path = normalizePath(endpoint.pathname || "/");
|
|
15275
|
-
if (options.sampleInputBody !== void 0) {
|
|
15283
|
+
if (options.probe || options.sampleInputBody !== void 0) {
|
|
15276
15284
|
const probeResult2 = await getProbe(
|
|
15277
15285
|
endpoint.href,
|
|
15278
15286
|
options.headers,
|
|
@@ -15324,7 +15332,7 @@ function parseArgs(args) {
|
|
|
15324
15332
|
else positional.push(arg);
|
|
15325
15333
|
}
|
|
15326
15334
|
const [first, second] = positional;
|
|
15327
|
-
if (first &&
|
|
15335
|
+
if (first && first !== "discover" && first !== "check") {
|
|
15328
15336
|
return { command: "discover", target: first, flags };
|
|
15329
15337
|
}
|
|
15330
15338
|
return { command: first ?? null, target: second ?? null, flags };
|
|
@@ -15483,7 +15491,8 @@ async function getL3Warnings(url2) {
|
|
|
15483
15491
|
}
|
|
15484
15492
|
return result.advisories.flatMap((a) => getWarningsForL3(a));
|
|
15485
15493
|
}
|
|
15486
|
-
async function runCheck(
|
|
15494
|
+
async function runCheck(rawUrl, flags) {
|
|
15495
|
+
const url2 = ensureProtocol(rawUrl);
|
|
15487
15496
|
if (!flags.json) console.log(`
|
|
15488
15497
|
Checking ${url2}...
|
|
15489
15498
|
`);
|
package/dist/cli.js
CHANGED
|
@@ -13777,7 +13777,7 @@ config(en_default());
|
|
|
13777
13777
|
|
|
13778
13778
|
// src/schemas.ts
|
|
13779
13779
|
var OpenApiPaymentInfoSchema = external_exports.object({
|
|
13780
|
-
pricingMode: external_exports.
|
|
13780
|
+
pricingMode: external_exports.string(),
|
|
13781
13781
|
price: external_exports.string().optional(),
|
|
13782
13782
|
minPrice: external_exports.string().optional(),
|
|
13783
13783
|
maxPrice: external_exports.string().optional(),
|
|
@@ -13834,7 +13834,6 @@ var WellKnownDocSchema = external_exports.object({
|
|
|
13834
13834
|
version: external_exports.number().optional(),
|
|
13835
13835
|
resources: external_exports.array(external_exports.string()).default([]),
|
|
13836
13836
|
mppResources: external_exports.array(external_exports.string()).optional(),
|
|
13837
|
-
// isMmmEnabled
|
|
13838
13837
|
description: external_exports.string().optional(),
|
|
13839
13838
|
ownershipProofs: external_exports.array(external_exports.string()).optional(),
|
|
13840
13839
|
instructions: external_exports.string().optional()
|
|
@@ -13899,7 +13898,11 @@ var DEFAULT_MISSING_METHOD = "POST";
|
|
|
13899
13898
|
// src/core/lib/url.ts
|
|
13900
13899
|
function ensureProtocol(target) {
|
|
13901
13900
|
const trimmed = target.trim();
|
|
13902
|
-
|
|
13901
|
+
if (/^https?:\/\//i.test(trimmed)) return trimmed;
|
|
13902
|
+
const host = trimmed.split("/")[0] ?? "";
|
|
13903
|
+
const hostname3 = host.split(":")[0] ?? "";
|
|
13904
|
+
const isLocal = hostname3 === "localhost" || hostname3 === "127.0.0.1" || hostname3 === "::1";
|
|
13905
|
+
return `${isLocal ? "http" : "https"}://${trimmed}`;
|
|
13903
13906
|
}
|
|
13904
13907
|
function normalizeOrigin(target) {
|
|
13905
13908
|
const url2 = new URL(ensureProtocol(target));
|
|
@@ -13940,9 +13943,6 @@ function fetchSafe(url2, init) {
|
|
|
13940
13943
|
return ResultAsync.fromPromise(fetch(url2, init), toFetchError);
|
|
13941
13944
|
}
|
|
13942
13945
|
|
|
13943
|
-
// src/mmm-enabled.ts
|
|
13944
|
-
var isMmmEnabled = () => "1.1.1".includes("-mmm");
|
|
13945
|
-
|
|
13946
13946
|
// src/core/source/openapi/index.ts
|
|
13947
13947
|
var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
|
|
13948
13948
|
const routes = [];
|
|
@@ -13951,11 +13951,8 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
|
|
|
13951
13951
|
const operation = pathItem[httpMethod.toLowerCase()];
|
|
13952
13952
|
if (!operation) continue;
|
|
13953
13953
|
const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
|
|
13954
|
-
if (!authMode) continue;
|
|
13955
13954
|
const p = operation["x-payment-info"];
|
|
13956
|
-
const protocols = (p?.protocols ?? []).filter(
|
|
13957
|
-
(proto) => proto !== "mpp" || isMmmEnabled()
|
|
13958
|
-
);
|
|
13955
|
+
const protocols = (p?.protocols ?? []).filter((proto) => proto.length > 0);
|
|
13959
13956
|
const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
|
|
13960
13957
|
pricingMode: p.pricingMode,
|
|
13961
13958
|
...p.price ? { price: p.price } : {},
|
|
@@ -14053,7 +14050,9 @@ function getWellKnown(origin, headers, signal) {
|
|
|
14053
14050
|
function formatPrice(pricing) {
|
|
14054
14051
|
if (pricing.pricingMode === "fixed") return `$${pricing.price}`;
|
|
14055
14052
|
if (pricing.pricingMode === "range") return `$${pricing.minPrice}-$${pricing.maxPrice}`;
|
|
14056
|
-
|
|
14053
|
+
if (pricing.pricingMode === "quote")
|
|
14054
|
+
return pricing.maxPrice ? `up to $${pricing.maxPrice}` : "quote";
|
|
14055
|
+
return `unknown pricing mode: ${pricing.pricingMode}`;
|
|
14057
14056
|
}
|
|
14058
14057
|
function checkL2ForOpenAPI(openApi) {
|
|
14059
14058
|
const routes = openApi.routes.map((route) => ({
|
|
@@ -14061,12 +14060,13 @@ function checkL2ForOpenAPI(openApi) {
|
|
|
14061
14060
|
method: route.method,
|
|
14062
14061
|
summary: route.summary ?? `${route.method} ${route.path}`,
|
|
14063
14062
|
...route.authMode ? { authMode: route.authMode } : {},
|
|
14064
|
-
...route.pricing ? { price: formatPrice(route.pricing) } : {},
|
|
14063
|
+
...route.pricing ? { price: formatPrice(route.pricing), pricingMode: route.pricing.pricingMode } : {},
|
|
14065
14064
|
...route.protocols?.length ? { protocols: route.protocols } : {}
|
|
14066
14065
|
}));
|
|
14067
14066
|
return {
|
|
14068
14067
|
...openApi.info.title ? { title: openApi.info.title } : {},
|
|
14069
14068
|
...openApi.info.description ? { description: openApi.info.description } : {},
|
|
14069
|
+
...openApi.info.version ? { version: openApi.info.version } : {},
|
|
14070
14070
|
routes,
|
|
14071
14071
|
source: "openapi"
|
|
14072
14072
|
};
|
|
@@ -14109,6 +14109,7 @@ var AUDIT_CODES = {
|
|
|
14109
14109
|
L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
|
|
14110
14110
|
L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
|
|
14111
14111
|
L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
|
|
14112
|
+
L2_PRICING_MODE_UNKNOWN: "L2_PRICING_MODE_UNKNOWN",
|
|
14112
14113
|
L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
|
|
14113
14114
|
// ─── L3 endpoint advisory checks ─────────────────────────────────────────────
|
|
14114
14115
|
L3_NOT_FOUND: "L3_NOT_FOUND",
|
|
@@ -14159,6 +14160,7 @@ function getWarningsForWellKnown(wellKnown) {
|
|
|
14159
14160
|
}
|
|
14160
14161
|
|
|
14161
14162
|
// src/audit/warnings/l2.ts
|
|
14163
|
+
var KNOWN_PRICING_MODES = /* @__PURE__ */ new Set(["fixed", "range", "quote"]);
|
|
14162
14164
|
var ROUTE_COUNT_HIGH = 40;
|
|
14163
14165
|
function getWarningsForL2(l2) {
|
|
14164
14166
|
const warnings = [];
|
|
@@ -14198,6 +14200,15 @@ function getWarningsForL2(l2) {
|
|
|
14198
14200
|
path: route.path
|
|
14199
14201
|
});
|
|
14200
14202
|
}
|
|
14203
|
+
if (route.pricingMode && !KNOWN_PRICING_MODES.has(route.pricingMode)) {
|
|
14204
|
+
warnings.push({
|
|
14205
|
+
code: AUDIT_CODES.L2_PRICING_MODE_UNKNOWN,
|
|
14206
|
+
severity: "warn",
|
|
14207
|
+
message: `Route ${loc} has unrecognized pricingMode "${route.pricingMode}".`,
|
|
14208
|
+
hint: `Expected one of: ${[...KNOWN_PRICING_MODES].join(", ")}.`,
|
|
14209
|
+
path: route.path
|
|
14210
|
+
});
|
|
14211
|
+
}
|
|
14201
14212
|
if (route.authMode === "paid") {
|
|
14202
14213
|
if (!route.price) {
|
|
14203
14214
|
warnings.push({
|
|
@@ -14928,7 +14939,7 @@ function detectProtocols(response) {
|
|
|
14928
14939
|
}
|
|
14929
14940
|
const authHeader = response.headers.get("www-authenticate")?.toLowerCase() ?? "";
|
|
14930
14941
|
if (authHeader.includes("x402")) protocols.add("x402");
|
|
14931
|
-
if (
|
|
14942
|
+
if (authHeader.includes("mpp")) protocols.add("mpp");
|
|
14932
14943
|
return [...protocols];
|
|
14933
14944
|
}
|
|
14934
14945
|
function buildProbeUrl(url2, method, inputBody) {
|
|
@@ -15008,7 +15019,7 @@ function parseAuthParams(segment) {
|
|
|
15008
15019
|
return params;
|
|
15009
15020
|
}
|
|
15010
15021
|
function extractPaymentOptions4(wwwAuthenticate) {
|
|
15011
|
-
if (!
|
|
15022
|
+
if (!wwwAuthenticate) return [];
|
|
15012
15023
|
const options = [];
|
|
15013
15024
|
for (const segment of wwwAuthenticate.split(/,\s*(?=Payment\s)/i)) {
|
|
15014
15025
|
const stripped = segment.replace(/^Payment\s+/i, "").trim();
|
|
@@ -15037,12 +15048,10 @@ function extractPaymentOptions4(wwwAuthenticate) {
|
|
|
15037
15048
|
if (!asset || !amount) continue;
|
|
15038
15049
|
options.push({
|
|
15039
15050
|
protocol: "mpp",
|
|
15040
|
-
// isMmmEnabled
|
|
15041
15051
|
paymentMethod,
|
|
15042
15052
|
intent,
|
|
15043
15053
|
realm,
|
|
15044
15054
|
network: `tempo:${String(chainId)}`,
|
|
15045
|
-
// isMmmEnabled
|
|
15046
15055
|
asset,
|
|
15047
15056
|
amount,
|
|
15048
15057
|
...decimals != null ? { decimals } : {},
|
|
@@ -15170,7 +15179,7 @@ function parseOperationProtocols(operation) {
|
|
|
15170
15179
|
const paymentInfo = operation["x-payment-info"];
|
|
15171
15180
|
if (!isRecord(paymentInfo) || !Array.isArray(paymentInfo.protocols)) return void 0;
|
|
15172
15181
|
const protocols = paymentInfo.protocols.filter(
|
|
15173
|
-
(protocol) => typeof protocol === "string" && protocol.length > 0
|
|
15182
|
+
(protocol) => typeof protocol === "string" && protocol.length > 0
|
|
15174
15183
|
);
|
|
15175
15184
|
return protocols.length > 0 ? protocols : void 0;
|
|
15176
15185
|
}
|
|
@@ -15201,8 +15210,7 @@ function getL3ForProbe(probe, path, method) {
|
|
|
15201
15210
|
const outputSchema = probeResult.paymentRequiredBody ? parseOutputSchema(probeResult.paymentRequiredBody) : void 0;
|
|
15202
15211
|
const paymentOptions = [
|
|
15203
15212
|
...probeResult.paymentRequiredBody ? extractPaymentOptions3(probeResult.paymentRequiredBody) : [],
|
|
15204
|
-
...
|
|
15205
|
-
// isMmmEnabled
|
|
15213
|
+
...extractPaymentOptions4(probeResult.wwwAuthenticate)
|
|
15206
15214
|
];
|
|
15207
15215
|
return {
|
|
15208
15216
|
source: "probe",
|
|
@@ -15242,7 +15250,7 @@ async function checkEndpointSchema(options) {
|
|
|
15242
15250
|
const endpoint = new URL(ensureProtocol(options.url));
|
|
15243
15251
|
const origin = normalizeOrigin(endpoint.origin);
|
|
15244
15252
|
const path = normalizePath(endpoint.pathname || "/");
|
|
15245
|
-
if (options.sampleInputBody !== void 0) {
|
|
15253
|
+
if (options.probe || options.sampleInputBody !== void 0) {
|
|
15246
15254
|
const probeResult2 = await getProbe(
|
|
15247
15255
|
endpoint.href,
|
|
15248
15256
|
options.headers,
|
|
@@ -15294,7 +15302,7 @@ function parseArgs(args) {
|
|
|
15294
15302
|
else positional.push(arg);
|
|
15295
15303
|
}
|
|
15296
15304
|
const [first, second] = positional;
|
|
15297
|
-
if (first &&
|
|
15305
|
+
if (first && first !== "discover" && first !== "check") {
|
|
15298
15306
|
return { command: "discover", target: first, flags };
|
|
15299
15307
|
}
|
|
15300
15308
|
return { command: first ?? null, target: second ?? null, flags };
|
|
@@ -15453,7 +15461,8 @@ async function getL3Warnings(url2) {
|
|
|
15453
15461
|
}
|
|
15454
15462
|
return result.advisories.flatMap((a) => getWarningsForL3(a));
|
|
15455
15463
|
}
|
|
15456
|
-
async function runCheck(
|
|
15464
|
+
async function runCheck(rawUrl, flags) {
|
|
15465
|
+
const url2 = ensureProtocol(rawUrl);
|
|
15457
15466
|
if (!flags.json) console.log(`
|
|
15458
15467
|
Checking ${url2}...
|
|
15459
15468
|
`);
|
package/dist/index.cjs
CHANGED
|
@@ -13830,7 +13830,7 @@ config(en_default());
|
|
|
13830
13830
|
|
|
13831
13831
|
// src/schemas.ts
|
|
13832
13832
|
var OpenApiPaymentInfoSchema = external_exports.object({
|
|
13833
|
-
pricingMode: external_exports.
|
|
13833
|
+
pricingMode: external_exports.string(),
|
|
13834
13834
|
price: external_exports.string().optional(),
|
|
13835
13835
|
minPrice: external_exports.string().optional(),
|
|
13836
13836
|
maxPrice: external_exports.string().optional(),
|
|
@@ -13887,7 +13887,6 @@ var WellKnownDocSchema = external_exports.object({
|
|
|
13887
13887
|
version: external_exports.number().optional(),
|
|
13888
13888
|
resources: external_exports.array(external_exports.string()).default([]),
|
|
13889
13889
|
mppResources: external_exports.array(external_exports.string()).optional(),
|
|
13890
|
-
// isMmmEnabled
|
|
13891
13890
|
description: external_exports.string().optional(),
|
|
13892
13891
|
ownershipProofs: external_exports.array(external_exports.string()).optional(),
|
|
13893
13892
|
instructions: external_exports.string().optional()
|
|
@@ -13952,7 +13951,11 @@ var DEFAULT_MISSING_METHOD = "POST";
|
|
|
13952
13951
|
// src/core/lib/url.ts
|
|
13953
13952
|
function ensureProtocol(target) {
|
|
13954
13953
|
const trimmed = target.trim();
|
|
13955
|
-
|
|
13954
|
+
if (/^https?:\/\//i.test(trimmed)) return trimmed;
|
|
13955
|
+
const host = trimmed.split("/")[0] ?? "";
|
|
13956
|
+
const hostname3 = host.split(":")[0] ?? "";
|
|
13957
|
+
const isLocal = hostname3 === "localhost" || hostname3 === "127.0.0.1" || hostname3 === "::1";
|
|
13958
|
+
return `${isLocal ? "http" : "https"}://${trimmed}`;
|
|
13956
13959
|
}
|
|
13957
13960
|
function normalizeOrigin(target) {
|
|
13958
13961
|
const url2 = new URL(ensureProtocol(target));
|
|
@@ -13993,9 +13996,6 @@ function fetchSafe(url2, init) {
|
|
|
13993
13996
|
return import_neverthrow.ResultAsync.fromPromise(fetch(url2, init), toFetchError);
|
|
13994
13997
|
}
|
|
13995
13998
|
|
|
13996
|
-
// src/mmm-enabled.ts
|
|
13997
|
-
var isMmmEnabled = () => "1.1.1".includes("-mmm");
|
|
13998
|
-
|
|
13999
13999
|
// src/core/source/openapi/index.ts
|
|
14000
14000
|
var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
|
|
14001
14001
|
const routes = [];
|
|
@@ -14004,11 +14004,8 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
|
|
|
14004
14004
|
const operation = pathItem[httpMethod.toLowerCase()];
|
|
14005
14005
|
if (!operation) continue;
|
|
14006
14006
|
const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
|
|
14007
|
-
if (!authMode) continue;
|
|
14008
14007
|
const p = operation["x-payment-info"];
|
|
14009
|
-
const protocols = (p?.protocols ?? []).filter(
|
|
14010
|
-
(proto) => proto !== "mpp" || isMmmEnabled()
|
|
14011
|
-
);
|
|
14008
|
+
const protocols = (p?.protocols ?? []).filter((proto) => proto.length > 0);
|
|
14012
14009
|
const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
|
|
14013
14010
|
pricingMode: p.pricingMode,
|
|
14014
14011
|
...p.price ? { price: p.price } : {},
|
|
@@ -14106,7 +14103,9 @@ function getWellKnown(origin, headers, signal) {
|
|
|
14106
14103
|
function formatPrice(pricing) {
|
|
14107
14104
|
if (pricing.pricingMode === "fixed") return `$${pricing.price}`;
|
|
14108
14105
|
if (pricing.pricingMode === "range") return `$${pricing.minPrice}-$${pricing.maxPrice}`;
|
|
14109
|
-
|
|
14106
|
+
if (pricing.pricingMode === "quote")
|
|
14107
|
+
return pricing.maxPrice ? `up to $${pricing.maxPrice}` : "quote";
|
|
14108
|
+
return `unknown pricing mode: ${pricing.pricingMode}`;
|
|
14110
14109
|
}
|
|
14111
14110
|
function checkL2ForOpenAPI(openApi) {
|
|
14112
14111
|
const routes = openApi.routes.map((route) => ({
|
|
@@ -14114,12 +14113,13 @@ function checkL2ForOpenAPI(openApi) {
|
|
|
14114
14113
|
method: route.method,
|
|
14115
14114
|
summary: route.summary ?? `${route.method} ${route.path}`,
|
|
14116
14115
|
...route.authMode ? { authMode: route.authMode } : {},
|
|
14117
|
-
...route.pricing ? { price: formatPrice(route.pricing) } : {},
|
|
14116
|
+
...route.pricing ? { price: formatPrice(route.pricing), pricingMode: route.pricing.pricingMode } : {},
|
|
14118
14117
|
...route.protocols?.length ? { protocols: route.protocols } : {}
|
|
14119
14118
|
}));
|
|
14120
14119
|
return {
|
|
14121
14120
|
...openApi.info.title ? { title: openApi.info.title } : {},
|
|
14122
14121
|
...openApi.info.description ? { description: openApi.info.description } : {},
|
|
14122
|
+
...openApi.info.version ? { version: openApi.info.version } : {},
|
|
14123
14123
|
routes,
|
|
14124
14124
|
source: "openapi"
|
|
14125
14125
|
};
|
|
@@ -14190,7 +14190,13 @@ async function discoverOriginSchema(options) {
|
|
|
14190
14190
|
found: true,
|
|
14191
14191
|
origin,
|
|
14192
14192
|
source: "openapi",
|
|
14193
|
-
...l22.title ? {
|
|
14193
|
+
...l22.title ? {
|
|
14194
|
+
info: {
|
|
14195
|
+
title: l22.title,
|
|
14196
|
+
...l22.description ? { description: l22.description } : {},
|
|
14197
|
+
...l22.version ? { version: l22.version } : {}
|
|
14198
|
+
}
|
|
14199
|
+
} : {},
|
|
14194
14200
|
endpoints: l22.routes
|
|
14195
14201
|
};
|
|
14196
14202
|
return withGuidance(base2, l42, guidanceMode);
|
|
@@ -14644,7 +14650,7 @@ function detectProtocols(response) {
|
|
|
14644
14650
|
}
|
|
14645
14651
|
const authHeader = response.headers.get("www-authenticate")?.toLowerCase() ?? "";
|
|
14646
14652
|
if (authHeader.includes("x402")) protocols.add("x402");
|
|
14647
|
-
if (
|
|
14653
|
+
if (authHeader.includes("mpp")) protocols.add("mpp");
|
|
14648
14654
|
return [...protocols];
|
|
14649
14655
|
}
|
|
14650
14656
|
function buildProbeUrl(url2, method, inputBody) {
|
|
@@ -14724,7 +14730,7 @@ function parseAuthParams(segment) {
|
|
|
14724
14730
|
return params;
|
|
14725
14731
|
}
|
|
14726
14732
|
function extractPaymentOptions4(wwwAuthenticate) {
|
|
14727
|
-
if (!
|
|
14733
|
+
if (!wwwAuthenticate) return [];
|
|
14728
14734
|
const options = [];
|
|
14729
14735
|
for (const segment of wwwAuthenticate.split(/,\s*(?=Payment\s)/i)) {
|
|
14730
14736
|
const stripped = segment.replace(/^Payment\s+/i, "").trim();
|
|
@@ -14753,12 +14759,10 @@ function extractPaymentOptions4(wwwAuthenticate) {
|
|
|
14753
14759
|
if (!asset || !amount) continue;
|
|
14754
14760
|
options.push({
|
|
14755
14761
|
protocol: "mpp",
|
|
14756
|
-
// isMmmEnabled
|
|
14757
14762
|
paymentMethod,
|
|
14758
14763
|
intent,
|
|
14759
14764
|
realm,
|
|
14760
14765
|
network: `tempo:${String(chainId)}`,
|
|
14761
|
-
// isMmmEnabled
|
|
14762
14766
|
asset,
|
|
14763
14767
|
amount,
|
|
14764
14768
|
...decimals != null ? { decimals } : {},
|
|
@@ -14886,7 +14890,7 @@ function parseOperationProtocols(operation) {
|
|
|
14886
14890
|
const paymentInfo = operation["x-payment-info"];
|
|
14887
14891
|
if (!isRecord(paymentInfo) || !Array.isArray(paymentInfo.protocols)) return void 0;
|
|
14888
14892
|
const protocols = paymentInfo.protocols.filter(
|
|
14889
|
-
(protocol) => typeof protocol === "string" && protocol.length > 0
|
|
14893
|
+
(protocol) => typeof protocol === "string" && protocol.length > 0
|
|
14890
14894
|
);
|
|
14891
14895
|
return protocols.length > 0 ? protocols : void 0;
|
|
14892
14896
|
}
|
|
@@ -14917,8 +14921,7 @@ function getL3ForProbe(probe, path, method) {
|
|
|
14917
14921
|
const outputSchema = probeResult.paymentRequiredBody ? parseOutputSchema(probeResult.paymentRequiredBody) : void 0;
|
|
14918
14922
|
const paymentOptions = [
|
|
14919
14923
|
...probeResult.paymentRequiredBody ? extractPaymentOptions3(probeResult.paymentRequiredBody) : [],
|
|
14920
|
-
...
|
|
14921
|
-
// isMmmEnabled
|
|
14924
|
+
...extractPaymentOptions4(probeResult.wwwAuthenticate)
|
|
14922
14925
|
];
|
|
14923
14926
|
return {
|
|
14924
14927
|
source: "probe",
|
|
@@ -14962,7 +14965,7 @@ async function checkEndpointSchema(options) {
|
|
|
14962
14965
|
const endpoint = new URL(ensureProtocol(options.url));
|
|
14963
14966
|
const origin = normalizeOrigin(endpoint.origin);
|
|
14964
14967
|
const path = normalizePath(endpoint.pathname || "/");
|
|
14965
|
-
if (options.sampleInputBody !== void 0) {
|
|
14968
|
+
if (options.probe || options.sampleInputBody !== void 0) {
|
|
14966
14969
|
const probeResult2 = await getProbe(
|
|
14967
14970
|
endpoint.href,
|
|
14968
14971
|
options.headers,
|
|
@@ -15101,6 +15104,7 @@ var AUDIT_CODES = {
|
|
|
15101
15104
|
L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING",
|
|
15102
15105
|
L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES",
|
|
15103
15106
|
L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID",
|
|
15107
|
+
L2_PRICING_MODE_UNKNOWN: "L2_PRICING_MODE_UNKNOWN",
|
|
15104
15108
|
L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID",
|
|
15105
15109
|
// ─── L3 endpoint advisory checks ─────────────────────────────────────────────
|
|
15106
15110
|
L3_NOT_FOUND: "L3_NOT_FOUND",
|
|
@@ -15442,6 +15446,7 @@ function getWarningsForWellKnown(wellKnown) {
|
|
|
15442
15446
|
}
|
|
15443
15447
|
|
|
15444
15448
|
// src/audit/warnings/l2.ts
|
|
15449
|
+
var KNOWN_PRICING_MODES = /* @__PURE__ */ new Set(["fixed", "range", "quote"]);
|
|
15445
15450
|
var ROUTE_COUNT_HIGH = 40;
|
|
15446
15451
|
function getWarningsForL2(l2) {
|
|
15447
15452
|
const warnings = [];
|
|
@@ -15481,6 +15486,15 @@ function getWarningsForL2(l2) {
|
|
|
15481
15486
|
path: route.path
|
|
15482
15487
|
});
|
|
15483
15488
|
}
|
|
15489
|
+
if (route.pricingMode && !KNOWN_PRICING_MODES.has(route.pricingMode)) {
|
|
15490
|
+
warnings.push({
|
|
15491
|
+
code: AUDIT_CODES.L2_PRICING_MODE_UNKNOWN,
|
|
15492
|
+
severity: "warn",
|
|
15493
|
+
message: `Route ${loc} has unrecognized pricingMode "${route.pricingMode}".`,
|
|
15494
|
+
hint: `Expected one of: ${[...KNOWN_PRICING_MODES].join(", ")}.`,
|
|
15495
|
+
path: route.path
|
|
15496
|
+
});
|
|
15497
|
+
}
|
|
15484
15498
|
if (route.authMode === "paid") {
|
|
15485
15499
|
if (!route.price) {
|
|
15486
15500
|
warnings.push({
|
package/dist/index.d.cts
CHANGED
|
@@ -8,12 +8,14 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTION
|
|
|
8
8
|
|
|
9
9
|
interface MppPaymentOption {
|
|
10
10
|
protocol: 'mpp';
|
|
11
|
-
/** Payment method identifier, e.g. "tempo" (Tempo protocol). */
|
|
11
|
+
/** Payment method identifier, e.g. "tempo" (Tempo protocol). */
|
|
12
|
+
paymentMethod: string;
|
|
12
13
|
/** Payment intent type, e.g. "charge". */
|
|
13
14
|
intent: string;
|
|
14
15
|
/** Server protection realm. */
|
|
15
16
|
realm: string;
|
|
16
|
-
/** CAIP-2 style network identifier, e.g. "tempo:4217". */
|
|
17
|
+
/** CAIP-2 style network identifier, e.g. "tempo:4217". */
|
|
18
|
+
network: string;
|
|
17
19
|
/** Currency / token contract. */
|
|
18
20
|
asset: string;
|
|
19
21
|
/** Raw token-unit amount string. */
|
|
@@ -59,7 +61,7 @@ interface X402V2PaymentOption {
|
|
|
59
61
|
type X402PaymentOption = X402V1PaymentOption | X402V2PaymentOption;
|
|
60
62
|
type PaymentOption = X402PaymentOption | MppPaymentOption;
|
|
61
63
|
interface PricingHint {
|
|
62
|
-
pricingMode: PricingMode;
|
|
64
|
+
pricingMode: PricingMode | string;
|
|
63
65
|
price?: string;
|
|
64
66
|
minPrice?: string;
|
|
65
67
|
maxPrice?: string;
|
|
@@ -107,6 +109,7 @@ interface ProbeResult {
|
|
|
107
109
|
interface L2Result {
|
|
108
110
|
title?: string;
|
|
109
111
|
description?: string;
|
|
112
|
+
version?: string;
|
|
110
113
|
routes: L2Route[];
|
|
111
114
|
source: 'openapi' | 'well-known/x402' | null;
|
|
112
115
|
}
|
|
@@ -116,6 +119,7 @@ interface L2Route {
|
|
|
116
119
|
summary: string;
|
|
117
120
|
authMode?: AuthMode;
|
|
118
121
|
price?: string;
|
|
122
|
+
pricingMode?: string;
|
|
119
123
|
protocols?: string[];
|
|
120
124
|
}
|
|
121
125
|
interface L3Result {
|
|
@@ -163,6 +167,7 @@ interface DiscoverOriginSchemaSuccess {
|
|
|
163
167
|
info?: {
|
|
164
168
|
title: string;
|
|
165
169
|
description?: string;
|
|
170
|
+
version?: string;
|
|
166
171
|
};
|
|
167
172
|
/** Discovered endpoints with advisory pricing and auth metadata. */
|
|
168
173
|
endpoints: L2Route[];
|
|
@@ -195,6 +200,12 @@ interface CheckEndpointOptions {
|
|
|
195
200
|
*
|
|
196
201
|
*/
|
|
197
202
|
sampleInputBody?: Record<string, unknown>;
|
|
203
|
+
/**
|
|
204
|
+
* When true, skips OpenAPI lookup and probes the live endpoint directly.
|
|
205
|
+
* Use this to retrieve actual PaymentOptions (realm, payTo, network, asset, amount)
|
|
206
|
+
* from the 402 response rather than static OpenAPI metadata.
|
|
207
|
+
*/
|
|
208
|
+
probe?: boolean;
|
|
198
209
|
}
|
|
199
210
|
interface EndpointMethodAdvisory extends L3Result {
|
|
200
211
|
method: HttpMethod;
|
|
@@ -344,6 +355,7 @@ declare const AUDIT_CODES: {
|
|
|
344
355
|
readonly L2_AUTH_MODE_MISSING: "L2_AUTH_MODE_MISSING";
|
|
345
356
|
readonly L2_NO_PAID_ROUTES: "L2_NO_PAID_ROUTES";
|
|
346
357
|
readonly L2_PRICE_MISSING_ON_PAID: "L2_PRICE_MISSING_ON_PAID";
|
|
358
|
+
readonly L2_PRICING_MODE_UNKNOWN: "L2_PRICING_MODE_UNKNOWN";
|
|
347
359
|
readonly L2_PROTOCOLS_MISSING_ON_PAID: "L2_PROTOCOLS_MISSING_ON_PAID";
|
|
348
360
|
readonly L3_NOT_FOUND: "L3_NOT_FOUND";
|
|
349
361
|
readonly L3_INPUT_SCHEMA_MISSING: "L3_INPUT_SCHEMA_MISSING";
|