@agentcash/discovery 1.3.0 → 1.4.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/cli.cjs CHANGED
@@ -14015,7 +14015,13 @@ async function parseBody(response, url2) {
14015
14015
  try {
14016
14016
  const payload = await response.json();
14017
14017
  const parsed = OpenApiParsedSchema.safeParse(payload);
14018
- if (!parsed.success) return null;
14018
+ if (!parsed.success) {
14019
+ return {
14020
+ parseFailure: true,
14021
+ fetchedUrl: url2,
14022
+ issues: parsed.error.issues.map((i) => ({ path: i.path, message: i.message }))
14023
+ };
14024
+ }
14019
14025
  return { raw: payload, ...parsed.data, fetchedUrl: url2 };
14020
14026
  } catch {
14021
14027
  return null;
@@ -14274,6 +14280,7 @@ var AUDIT_CODES = {
14274
14280
  OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND",
14275
14281
  WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND",
14276
14282
  // ─── OpenAPI quality ─────────────────────────────────────────────────────────
14283
+ OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR",
14277
14284
  OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES",
14278
14285
  // ─── L2 route-list checks ────────────────────────────────────────────────────
14279
14286
  L2_NO_ROUTES: "L2_NO_ROUTES",
@@ -14308,6 +14315,9 @@ var AUDIT_CODES = {
14308
14315
  };
14309
14316
 
14310
14317
  // src/audit/warnings/sources.ts
14318
+ function isOpenApiParseFailure(value) {
14319
+ return value !== null && "parseFailure" in value;
14320
+ }
14311
14321
  function getWarningsForOpenAPI(openApi) {
14312
14322
  if (openApi === null) {
14313
14323
  return [
@@ -14319,6 +14329,18 @@ function getWarningsForOpenAPI(openApi) {
14319
14329
  }
14320
14330
  ];
14321
14331
  }
14332
+ if (isOpenApiParseFailure(openApi)) {
14333
+ const details = openApi.issues.map((i) => ` ${i.path.map(String).join(".")}: ${i.message}`).join("\n");
14334
+ return [
14335
+ {
14336
+ code: AUDIT_CODES.OPENAPI_PARSE_ERROR,
14337
+ severity: "warn",
14338
+ message: `OpenAPI spec found at ${openApi.fetchedUrl} but failed schema validation:
14339
+ ${details}`,
14340
+ hint: "Fix the schema issues above so discovery can read the spec."
14341
+ }
14342
+ ];
14343
+ }
14322
14344
  const warnings = [];
14323
14345
  if (openApi.routes.length === 0) {
14324
14346
  warnings.push({
@@ -15591,6 +15613,11 @@ async function attachProbePayload(url2, advisories) {
15591
15613
  }
15592
15614
  }
15593
15615
 
15616
+ // src/core/types/sources.ts
15617
+ function isOpenApiSource(raw) {
15618
+ return raw !== null && !("parseFailure" in raw);
15619
+ }
15620
+
15594
15621
  // src/runtime/check-endpoint.ts
15595
15622
  function getAdvisoriesForOpenAPI(openApi, path) {
15596
15623
  return [...HTTP_METHODS].flatMap((method) => {
@@ -15629,7 +15656,8 @@ async function checkEndpointSchema(options) {
15629
15656
  return { found: false, origin, path, cause: "not_found" };
15630
15657
  }
15631
15658
  const openApiResult = await getOpenAPI(origin, options.headers, options.signal);
15632
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15659
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15660
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
15633
15661
  if (openApi) {
15634
15662
  const advisories2 = getAdvisoriesForOpenAPI(openApi, path);
15635
15663
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
@@ -15699,10 +15727,11 @@ Discovering ${origin}...
15699
15727
  getOpenAPI(origin),
15700
15728
  getWellKnown(origin)
15701
15729
  ]);
15702
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15730
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15703
15731
  const wellKnown = wellKnownResult.isOk() ? wellKnownResult.value : null;
15732
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
15704
15733
  const warnings = [
15705
- ...getWarningsForOpenAPI(openApi),
15734
+ ...getWarningsForOpenAPI(openApiRaw),
15706
15735
  ...getWarningsForWellKnown(wellKnown)
15707
15736
  ];
15708
15737
  if (openApi) {
package/dist/cli.js CHANGED
@@ -13985,7 +13985,13 @@ async function parseBody(response, url2) {
13985
13985
  try {
13986
13986
  const payload = await response.json();
13987
13987
  const parsed = OpenApiParsedSchema.safeParse(payload);
13988
- if (!parsed.success) return null;
13988
+ if (!parsed.success) {
13989
+ return {
13990
+ parseFailure: true,
13991
+ fetchedUrl: url2,
13992
+ issues: parsed.error.issues.map((i) => ({ path: i.path, message: i.message }))
13993
+ };
13994
+ }
13989
13995
  return { raw: payload, ...parsed.data, fetchedUrl: url2 };
13990
13996
  } catch {
13991
13997
  return null;
@@ -14244,6 +14250,7 @@ var AUDIT_CODES = {
14244
14250
  OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND",
14245
14251
  WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND",
14246
14252
  // ─── OpenAPI quality ─────────────────────────────────────────────────────────
14253
+ OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR",
14247
14254
  OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES",
14248
14255
  // ─── L2 route-list checks ────────────────────────────────────────────────────
14249
14256
  L2_NO_ROUTES: "L2_NO_ROUTES",
@@ -14278,6 +14285,9 @@ var AUDIT_CODES = {
14278
14285
  };
14279
14286
 
14280
14287
  // src/audit/warnings/sources.ts
14288
+ function isOpenApiParseFailure(value) {
14289
+ return value !== null && "parseFailure" in value;
14290
+ }
14281
14291
  function getWarningsForOpenAPI(openApi) {
14282
14292
  if (openApi === null) {
14283
14293
  return [
@@ -14289,6 +14299,18 @@ function getWarningsForOpenAPI(openApi) {
14289
14299
  }
14290
14300
  ];
14291
14301
  }
14302
+ if (isOpenApiParseFailure(openApi)) {
14303
+ const details = openApi.issues.map((i) => ` ${i.path.map(String).join(".")}: ${i.message}`).join("\n");
14304
+ return [
14305
+ {
14306
+ code: AUDIT_CODES.OPENAPI_PARSE_ERROR,
14307
+ severity: "warn",
14308
+ message: `OpenAPI spec found at ${openApi.fetchedUrl} but failed schema validation:
14309
+ ${details}`,
14310
+ hint: "Fix the schema issues above so discovery can read the spec."
14311
+ }
14312
+ ];
14313
+ }
14292
14314
  const warnings = [];
14293
14315
  if (openApi.routes.length === 0) {
14294
14316
  warnings.push({
@@ -15561,6 +15583,11 @@ async function attachProbePayload(url2, advisories) {
15561
15583
  }
15562
15584
  }
15563
15585
 
15586
+ // src/core/types/sources.ts
15587
+ function isOpenApiSource(raw) {
15588
+ return raw !== null && !("parseFailure" in raw);
15589
+ }
15590
+
15564
15591
  // src/runtime/check-endpoint.ts
15565
15592
  function getAdvisoriesForOpenAPI(openApi, path) {
15566
15593
  return [...HTTP_METHODS].flatMap((method) => {
@@ -15599,7 +15626,8 @@ async function checkEndpointSchema(options) {
15599
15626
  return { found: false, origin, path, cause: "not_found" };
15600
15627
  }
15601
15628
  const openApiResult = await getOpenAPI(origin, options.headers, options.signal);
15602
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15629
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15630
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
15603
15631
  if (openApi) {
15604
15632
  const advisories2 = getAdvisoriesForOpenAPI(openApi, path);
15605
15633
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
@@ -15669,10 +15697,11 @@ Discovering ${origin}...
15669
15697
  getOpenAPI(origin),
15670
15698
  getWellKnown(origin)
15671
15699
  ]);
15672
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15700
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15673
15701
  const wellKnown = wellKnownResult.isOk() ? wellKnownResult.value : null;
15702
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
15674
15703
  const warnings = [
15675
- ...getWarningsForOpenAPI(openApi),
15704
+ ...getWarningsForOpenAPI(openApiRaw),
15676
15705
  ...getWarningsForWellKnown(wellKnown)
15677
15706
  ];
15678
15707
  if (openApi) {
package/dist/index.cjs CHANGED
@@ -56,6 +56,7 @@ __export(index_exports, {
56
56
  getWarningsForWellKnown: () => getWarningsForWellKnown,
57
57
  getWellKnown: () => getWellKnown,
58
58
  getX402WellKnown: () => getX402WellKnown,
59
+ isOpenApiParseFailure: () => isOpenApiParseFailure,
59
60
  validatePaymentRequiredDetailed: () => validatePaymentRequiredDetailed
60
61
  });
61
62
  module.exports = __toCommonJS(index_exports);
@@ -14041,7 +14042,13 @@ async function parseBody(response, url2) {
14041
14042
  try {
14042
14043
  const payload = await response.json();
14043
14044
  const parsed = OpenApiParsedSchema.safeParse(payload);
14044
- if (!parsed.success) return null;
14045
+ if (!parsed.success) {
14046
+ return {
14047
+ parseFailure: true,
14048
+ fetchedUrl: url2,
14049
+ issues: parsed.error.issues.map((i) => ({ path: i.path, message: i.message }))
14050
+ };
14051
+ }
14045
14052
  return { raw: payload, ...parsed.data, fetchedUrl: url2 };
14046
14053
  } catch {
14047
14054
  return null;
@@ -14307,8 +14314,41 @@ var GuidanceMode = /* @__PURE__ */ ((GuidanceMode2) => {
14307
14314
  return GuidanceMode2;
14308
14315
  })(GuidanceMode || {});
14309
14316
 
14317
+ // src/core/types/sources.ts
14318
+ function isOpenApiSource(raw) {
14319
+ return raw !== null && !("parseFailure" in raw);
14320
+ }
14321
+
14310
14322
  // src/runtime/discover.ts
14311
14323
  var GUIDANCE_AUTO_INCLUDE_MAX_TOKENS_LENGTH = 1e3;
14324
+ function extractFromWellknown(raw) {
14325
+ if (Array.isArray(raw["ownershipProofs"])) {
14326
+ const proofs = raw["ownershipProofs"].filter(
14327
+ (p) => typeof p === "string"
14328
+ );
14329
+ if (proofs.length > 0) return proofs;
14330
+ }
14331
+ return void 0;
14332
+ }
14333
+ function extractFromOpenapi(raw) {
14334
+ const xDiscovery = raw["x-discovery"];
14335
+ if (xDiscovery && typeof xDiscovery === "object" && !Array.isArray(xDiscovery)) {
14336
+ const proofs = xDiscovery["ownershipProofs"];
14337
+ if (Array.isArray(proofs)) {
14338
+ const filtered = proofs.filter((p) => typeof p === "string");
14339
+ if (filtered.length > 0) return filtered;
14340
+ }
14341
+ }
14342
+ const legacy = raw["x-agentcash-provenance"];
14343
+ if (legacy && typeof legacy === "object" && !Array.isArray(legacy)) {
14344
+ const proofs = legacy["ownershipProofs"];
14345
+ if (Array.isArray(proofs)) {
14346
+ const filtered = proofs.filter((p) => typeof p === "string");
14347
+ if (filtered.length > 0) return filtered;
14348
+ }
14349
+ }
14350
+ return void 0;
14351
+ }
14312
14352
  function withGuidance(base, l4, guidanceMode) {
14313
14353
  if (guidanceMode === "never" /* Never */) return { ...base, guidanceAvailable: !!l4 };
14314
14354
  if (!l4) return { ...base, guidanceAvailable: false };
@@ -14327,10 +14367,12 @@ async function discoverOriginSchema(options) {
14327
14367
  options.signal,
14328
14368
  options.specificationOverrideUrl
14329
14369
  );
14330
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
14370
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
14371
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
14331
14372
  if (openApi) {
14332
14373
  const l22 = checkL2ForOpenAPI(openApi);
14333
14374
  const l42 = checkL4ForOpenAPI(openApi);
14375
+ const ownershipProofs2 = extractFromOpenapi(openApi.raw);
14334
14376
  const base2 = {
14335
14377
  found: true,
14336
14378
  origin,
@@ -14342,7 +14384,8 @@ async function discoverOriginSchema(options) {
14342
14384
  ...l22.version ? { version: l22.version } : {}
14343
14385
  }
14344
14386
  } : {},
14345
- endpoints: l22.routes
14387
+ endpoints: l22.routes,
14388
+ ...ownershipProofs2 ? { ownershipProofs: ownershipProofs2 } : {}
14346
14389
  };
14347
14390
  return withGuidance(base2, l42, guidanceMode);
14348
14391
  }
@@ -14359,6 +14402,7 @@ async function discoverOriginSchema(options) {
14359
14402
  if (!wellKnown) return { found: false, origin, cause: "not_found" };
14360
14403
  const l2 = checkL2ForWellknown(wellKnown);
14361
14404
  const l4 = checkL4ForWellknown(wellKnown);
14405
+ const ownershipProofs = extractFromWellknown(wellKnown.raw);
14362
14406
  const base = {
14363
14407
  found: true,
14364
14408
  origin,
@@ -14369,7 +14413,8 @@ async function discoverOriginSchema(options) {
14369
14413
  ...l2.description ? { description: l2.description } : {}
14370
14414
  }
14371
14415
  } : {},
14372
- endpoints: l2.routes
14416
+ endpoints: l2.routes,
14417
+ ...ownershipProofs ? { ownershipProofs } : {}
14373
14418
  };
14374
14419
  return withGuidance(base, l4, guidanceMode);
14375
14420
  }
@@ -15147,7 +15192,8 @@ async function checkEndpointSchema(options) {
15147
15192
  return { found: false, origin, path, cause: "not_found" };
15148
15193
  }
15149
15194
  const openApiResult = await getOpenAPI(origin, options.headers, options.signal);
15150
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15195
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15196
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
15151
15197
  if (openApi) {
15152
15198
  const advisories2 = getAdvisoriesForOpenAPI(openApi, path);
15153
15199
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
@@ -15258,6 +15304,7 @@ var AUDIT_CODES = {
15258
15304
  OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND",
15259
15305
  WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND",
15260
15306
  // ─── OpenAPI quality ─────────────────────────────────────────────────────────
15307
+ OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR",
15261
15308
  OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES",
15262
15309
  // ─── L2 route-list checks ────────────────────────────────────────────────────
15263
15310
  L2_NO_ROUTES: "L2_NO_ROUTES",
@@ -15745,6 +15792,9 @@ function validatePaymentRequiredDetailed(payload, options = {}) {
15745
15792
  }
15746
15793
 
15747
15794
  // src/audit/warnings/sources.ts
15795
+ function isOpenApiParseFailure(value) {
15796
+ return value !== null && "parseFailure" in value;
15797
+ }
15748
15798
  function getWarningsForOpenAPI(openApi) {
15749
15799
  if (openApi === null) {
15750
15800
  return [
@@ -15756,6 +15806,18 @@ function getWarningsForOpenAPI(openApi) {
15756
15806
  }
15757
15807
  ];
15758
15808
  }
15809
+ if (isOpenApiParseFailure(openApi)) {
15810
+ const details = openApi.issues.map((i) => ` ${i.path.map(String).join(".")}: ${i.message}`).join("\n");
15811
+ return [
15812
+ {
15813
+ code: AUDIT_CODES.OPENAPI_PARSE_ERROR,
15814
+ severity: "warn",
15815
+ message: `OpenAPI spec found at ${openApi.fetchedUrl} but failed schema validation:
15816
+ ${details}`,
15817
+ hint: "Fix the schema issues above so discovery can read the spec."
15818
+ }
15819
+ ];
15820
+ }
15759
15821
  const warnings = [];
15760
15822
  if (openApi.routes.length === 0) {
15761
15823
  warnings.push({
@@ -15909,5 +15971,6 @@ function getWarningsForL4(l4) {
15909
15971
  getWarningsForWellKnown,
15910
15972
  getWellKnown,
15911
15973
  getX402WellKnown,
15974
+ isOpenApiParseFailure,
15912
15975
  validatePaymentRequiredDetailed
15913
15976
  });
package/dist/index.d.cts CHANGED
@@ -78,6 +78,15 @@ interface OpenApiSource {
78
78
  guidance?: string;
79
79
  fetchedUrl: string;
80
80
  }
81
+ /** Returned when the spec was fetched successfully but failed schema validation. */
82
+ interface OpenApiParseFailure {
83
+ parseFailure: true;
84
+ fetchedUrl: string;
85
+ issues: Array<{
86
+ path: (string | number | symbol)[];
87
+ message: string;
88
+ }>;
89
+ }
81
90
  interface OpenApiRoute {
82
91
  path: string;
83
92
  method: HttpMethod;
@@ -188,6 +197,8 @@ interface DiscoverOriginSchemaSuccess {
188
197
  guidanceTokens?: number;
189
198
  /** Guidance text. Included when short enough (auto mode) or guidance='always'. */
190
199
  guidance?: string;
200
+ /** Ownership proof strings collected from the discovery document, if any. */
201
+ ownershipProofs?: string[];
191
202
  }
192
203
  interface DiscoverOriginSchemaNotFound {
193
204
  found: false;
@@ -245,7 +256,7 @@ interface FetchError {
245
256
  message: string;
246
257
  }
247
258
 
248
- declare function getOpenAPI(origin: string, headers?: Record<string, string>, signal?: AbortSignal, specificationOverrideUrl?: string): ResultAsync<OpenApiSource | null, FetchError>;
259
+ declare function getOpenAPI(origin: string, headers?: Record<string, string>, signal?: AbortSignal, specificationOverrideUrl?: string): ResultAsync<OpenApiSource | OpenApiParseFailure | null, FetchError>;
249
260
 
250
261
  /**
251
262
  * Fetches both `/.well-known/x402` and `/.well-known/mpp` in parallel and merges results.
@@ -373,6 +384,7 @@ declare function validatePaymentRequiredDetailed(payload: unknown, options?: Val
373
384
  declare const AUDIT_CODES: {
374
385
  readonly OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND";
375
386
  readonly WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND";
387
+ readonly OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR";
376
388
  readonly OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES";
377
389
  readonly L2_NO_ROUTES: "L2_NO_ROUTES";
378
390
  readonly L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH";
@@ -413,7 +425,9 @@ interface AuditWarning {
413
425
  path?: string;
414
426
  }
415
427
 
416
- declare function getWarningsForOpenAPI(openApi: OpenApiSource | null): AuditWarning[];
428
+ /** Type guard: true when the value is a parse-failure sentinel (spec fetched but invalid). */
429
+ declare function isOpenApiParseFailure(value: OpenApiSource | OpenApiParseFailure | null): value is OpenApiParseFailure;
430
+ declare function getWarningsForOpenAPI(openApi: OpenApiSource | OpenApiParseFailure | null): AuditWarning[];
417
431
  declare function getWarningsForWellKnown(wellKnown: WellKnownSource | null): AuditWarning[];
418
432
 
419
433
  declare function getWarningsForL2(l2: L2Result): AuditWarning[];
@@ -443,4 +457,4 @@ declare function getWarningsForL4(l4: L4Result | null): AuditWarning[];
443
457
  */
444
458
  declare function getWarningsForMppHeader(wwwAuthenticate: string | null | undefined): AuditWarning[];
445
459
 
446
- export { AUDIT_CODES, type AuditCode, type AuditSeverity, type AuditWarning, type AuthMode, type CheckEndpointNotFound, type CheckEndpointOptions, type CheckEndpointResult, type CheckEndpointSuccess, type DiscoverOriginSchemaNotFound, type DiscoverOriginSchemaOptions, type DiscoverOriginSchemaResult, type DiscoverOriginSchemaSuccess, type EndpointMethodAdvisory, GuidanceMode, type HttpMethod, type L2Result, type L2Route, type L3Result, type L4Result, type MetadataPreview, type MppPaymentOption, type NormalizedAccept, type NormalizedPaymentRequired, type OpenApiRoute, type OpenApiSource, type PaymentOption, type PricingMode, type ProbeResult, type TrustTier, VALIDATION_CODES, type ValidatePaymentRequiredDetailedResult, type ValidatePaymentRequiredOptions, type ValidationIssue, type ValidationSeverity, type ValidationStage, type ValidationSummary, type WellKnownRoute, type WellKnownSource, type X402PaymentOption, type X402V1PaymentOption, type X402V2PaymentOption, attachProbePayload, checkEndpointSchema, checkL2ForOpenAPI, checkL2ForWellknown, checkL4ForOpenAPI, checkL4ForWellknown, discoverOriginSchema, evaluateMetadataCompleteness, getL3, getL3ForOpenAPI, getL3ForProbe, getMppWellKnown, getOpenAPI, getProbe, getWarningsFor402Body, getWarningsForL2, getWarningsForL3, getWarningsForL4, getWarningsForMppHeader, getWarningsForOpenAPI, getWarningsForWellKnown, getWellKnown, getX402WellKnown, validatePaymentRequiredDetailed };
460
+ export { AUDIT_CODES, type AuditCode, type AuditSeverity, type AuditWarning, type AuthMode, type CheckEndpointNotFound, type CheckEndpointOptions, type CheckEndpointResult, type CheckEndpointSuccess, type DiscoverOriginSchemaNotFound, type DiscoverOriginSchemaOptions, type DiscoverOriginSchemaResult, type DiscoverOriginSchemaSuccess, type EndpointMethodAdvisory, GuidanceMode, type HttpMethod, type L2Result, type L2Route, type L3Result, type L4Result, type MetadataPreview, type MppPaymentOption, type NormalizedAccept, type NormalizedPaymentRequired, type OpenApiParseFailure, type OpenApiRoute, type OpenApiSource, type PaymentOption, type PricingMode, type ProbeResult, type TrustTier, VALIDATION_CODES, type ValidatePaymentRequiredDetailedResult, type ValidatePaymentRequiredOptions, type ValidationIssue, type ValidationSeverity, type ValidationStage, type ValidationSummary, type WellKnownRoute, type WellKnownSource, type X402PaymentOption, type X402V1PaymentOption, type X402V2PaymentOption, attachProbePayload, checkEndpointSchema, checkL2ForOpenAPI, checkL2ForWellknown, checkL4ForOpenAPI, checkL4ForWellknown, discoverOriginSchema, evaluateMetadataCompleteness, getL3, getL3ForOpenAPI, getL3ForProbe, getMppWellKnown, getOpenAPI, getProbe, getWarningsFor402Body, getWarningsForL2, getWarningsForL3, getWarningsForL4, getWarningsForMppHeader, getWarningsForOpenAPI, getWarningsForWellKnown, getWellKnown, getX402WellKnown, isOpenApiParseFailure, validatePaymentRequiredDetailed };
package/dist/index.d.ts CHANGED
@@ -78,6 +78,15 @@ interface OpenApiSource {
78
78
  guidance?: string;
79
79
  fetchedUrl: string;
80
80
  }
81
+ /** Returned when the spec was fetched successfully but failed schema validation. */
82
+ interface OpenApiParseFailure {
83
+ parseFailure: true;
84
+ fetchedUrl: string;
85
+ issues: Array<{
86
+ path: (string | number | symbol)[];
87
+ message: string;
88
+ }>;
89
+ }
81
90
  interface OpenApiRoute {
82
91
  path: string;
83
92
  method: HttpMethod;
@@ -188,6 +197,8 @@ interface DiscoverOriginSchemaSuccess {
188
197
  guidanceTokens?: number;
189
198
  /** Guidance text. Included when short enough (auto mode) or guidance='always'. */
190
199
  guidance?: string;
200
+ /** Ownership proof strings collected from the discovery document, if any. */
201
+ ownershipProofs?: string[];
191
202
  }
192
203
  interface DiscoverOriginSchemaNotFound {
193
204
  found: false;
@@ -245,7 +256,7 @@ interface FetchError {
245
256
  message: string;
246
257
  }
247
258
 
248
- declare function getOpenAPI(origin: string, headers?: Record<string, string>, signal?: AbortSignal, specificationOverrideUrl?: string): ResultAsync<OpenApiSource | null, FetchError>;
259
+ declare function getOpenAPI(origin: string, headers?: Record<string, string>, signal?: AbortSignal, specificationOverrideUrl?: string): ResultAsync<OpenApiSource | OpenApiParseFailure | null, FetchError>;
249
260
 
250
261
  /**
251
262
  * Fetches both `/.well-known/x402` and `/.well-known/mpp` in parallel and merges results.
@@ -373,6 +384,7 @@ declare function validatePaymentRequiredDetailed(payload: unknown, options?: Val
373
384
  declare const AUDIT_CODES: {
374
385
  readonly OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND";
375
386
  readonly WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND";
387
+ readonly OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR";
376
388
  readonly OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES";
377
389
  readonly L2_NO_ROUTES: "L2_NO_ROUTES";
378
390
  readonly L2_ROUTE_COUNT_HIGH: "L2_ROUTE_COUNT_HIGH";
@@ -413,7 +425,9 @@ interface AuditWarning {
413
425
  path?: string;
414
426
  }
415
427
 
416
- declare function getWarningsForOpenAPI(openApi: OpenApiSource | null): AuditWarning[];
428
+ /** Type guard: true when the value is a parse-failure sentinel (spec fetched but invalid). */
429
+ declare function isOpenApiParseFailure(value: OpenApiSource | OpenApiParseFailure | null): value is OpenApiParseFailure;
430
+ declare function getWarningsForOpenAPI(openApi: OpenApiSource | OpenApiParseFailure | null): AuditWarning[];
417
431
  declare function getWarningsForWellKnown(wellKnown: WellKnownSource | null): AuditWarning[];
418
432
 
419
433
  declare function getWarningsForL2(l2: L2Result): AuditWarning[];
@@ -443,4 +457,4 @@ declare function getWarningsForL4(l4: L4Result | null): AuditWarning[];
443
457
  */
444
458
  declare function getWarningsForMppHeader(wwwAuthenticate: string | null | undefined): AuditWarning[];
445
459
 
446
- export { AUDIT_CODES, type AuditCode, type AuditSeverity, type AuditWarning, type AuthMode, type CheckEndpointNotFound, type CheckEndpointOptions, type CheckEndpointResult, type CheckEndpointSuccess, type DiscoverOriginSchemaNotFound, type DiscoverOriginSchemaOptions, type DiscoverOriginSchemaResult, type DiscoverOriginSchemaSuccess, type EndpointMethodAdvisory, GuidanceMode, type HttpMethod, type L2Result, type L2Route, type L3Result, type L4Result, type MetadataPreview, type MppPaymentOption, type NormalizedAccept, type NormalizedPaymentRequired, type OpenApiRoute, type OpenApiSource, type PaymentOption, type PricingMode, type ProbeResult, type TrustTier, VALIDATION_CODES, type ValidatePaymentRequiredDetailedResult, type ValidatePaymentRequiredOptions, type ValidationIssue, type ValidationSeverity, type ValidationStage, type ValidationSummary, type WellKnownRoute, type WellKnownSource, type X402PaymentOption, type X402V1PaymentOption, type X402V2PaymentOption, attachProbePayload, checkEndpointSchema, checkL2ForOpenAPI, checkL2ForWellknown, checkL4ForOpenAPI, checkL4ForWellknown, discoverOriginSchema, evaluateMetadataCompleteness, getL3, getL3ForOpenAPI, getL3ForProbe, getMppWellKnown, getOpenAPI, getProbe, getWarningsFor402Body, getWarningsForL2, getWarningsForL3, getWarningsForL4, getWarningsForMppHeader, getWarningsForOpenAPI, getWarningsForWellKnown, getWellKnown, getX402WellKnown, validatePaymentRequiredDetailed };
460
+ export { AUDIT_CODES, type AuditCode, type AuditSeverity, type AuditWarning, type AuthMode, type CheckEndpointNotFound, type CheckEndpointOptions, type CheckEndpointResult, type CheckEndpointSuccess, type DiscoverOriginSchemaNotFound, type DiscoverOriginSchemaOptions, type DiscoverOriginSchemaResult, type DiscoverOriginSchemaSuccess, type EndpointMethodAdvisory, GuidanceMode, type HttpMethod, type L2Result, type L2Route, type L3Result, type L4Result, type MetadataPreview, type MppPaymentOption, type NormalizedAccept, type NormalizedPaymentRequired, type OpenApiParseFailure, type OpenApiRoute, type OpenApiSource, type PaymentOption, type PricingMode, type ProbeResult, type TrustTier, VALIDATION_CODES, type ValidatePaymentRequiredDetailedResult, type ValidatePaymentRequiredOptions, type ValidationIssue, type ValidationSeverity, type ValidationStage, type ValidationSummary, type WellKnownRoute, type WellKnownSource, type X402PaymentOption, type X402V1PaymentOption, type X402V2PaymentOption, attachProbePayload, checkEndpointSchema, checkL2ForOpenAPI, checkL2ForWellknown, checkL4ForOpenAPI, checkL4ForWellknown, discoverOriginSchema, evaluateMetadataCompleteness, getL3, getL3ForOpenAPI, getL3ForProbe, getMppWellKnown, getOpenAPI, getProbe, getWarningsFor402Body, getWarningsForL2, getWarningsForL3, getWarningsForL4, getWarningsForMppHeader, getWarningsForOpenAPI, getWarningsForWellKnown, getWellKnown, getX402WellKnown, isOpenApiParseFailure, validatePaymentRequiredDetailed };
package/dist/index.js CHANGED
@@ -13985,7 +13985,13 @@ async function parseBody(response, url2) {
13985
13985
  try {
13986
13986
  const payload = await response.json();
13987
13987
  const parsed = OpenApiParsedSchema.safeParse(payload);
13988
- if (!parsed.success) return null;
13988
+ if (!parsed.success) {
13989
+ return {
13990
+ parseFailure: true,
13991
+ fetchedUrl: url2,
13992
+ issues: parsed.error.issues.map((i) => ({ path: i.path, message: i.message }))
13993
+ };
13994
+ }
13989
13995
  return { raw: payload, ...parsed.data, fetchedUrl: url2 };
13990
13996
  } catch {
13991
13997
  return null;
@@ -14251,8 +14257,41 @@ var GuidanceMode = /* @__PURE__ */ ((GuidanceMode2) => {
14251
14257
  return GuidanceMode2;
14252
14258
  })(GuidanceMode || {});
14253
14259
 
14260
+ // src/core/types/sources.ts
14261
+ function isOpenApiSource(raw) {
14262
+ return raw !== null && !("parseFailure" in raw);
14263
+ }
14264
+
14254
14265
  // src/runtime/discover.ts
14255
14266
  var GUIDANCE_AUTO_INCLUDE_MAX_TOKENS_LENGTH = 1e3;
14267
+ function extractFromWellknown(raw) {
14268
+ if (Array.isArray(raw["ownershipProofs"])) {
14269
+ const proofs = raw["ownershipProofs"].filter(
14270
+ (p) => typeof p === "string"
14271
+ );
14272
+ if (proofs.length > 0) return proofs;
14273
+ }
14274
+ return void 0;
14275
+ }
14276
+ function extractFromOpenapi(raw) {
14277
+ const xDiscovery = raw["x-discovery"];
14278
+ if (xDiscovery && typeof xDiscovery === "object" && !Array.isArray(xDiscovery)) {
14279
+ const proofs = xDiscovery["ownershipProofs"];
14280
+ if (Array.isArray(proofs)) {
14281
+ const filtered = proofs.filter((p) => typeof p === "string");
14282
+ if (filtered.length > 0) return filtered;
14283
+ }
14284
+ }
14285
+ const legacy = raw["x-agentcash-provenance"];
14286
+ if (legacy && typeof legacy === "object" && !Array.isArray(legacy)) {
14287
+ const proofs = legacy["ownershipProofs"];
14288
+ if (Array.isArray(proofs)) {
14289
+ const filtered = proofs.filter((p) => typeof p === "string");
14290
+ if (filtered.length > 0) return filtered;
14291
+ }
14292
+ }
14293
+ return void 0;
14294
+ }
14256
14295
  function withGuidance(base, l4, guidanceMode) {
14257
14296
  if (guidanceMode === "never" /* Never */) return { ...base, guidanceAvailable: !!l4 };
14258
14297
  if (!l4) return { ...base, guidanceAvailable: false };
@@ -14271,10 +14310,12 @@ async function discoverOriginSchema(options) {
14271
14310
  options.signal,
14272
14311
  options.specificationOverrideUrl
14273
14312
  );
14274
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
14313
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
14314
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
14275
14315
  if (openApi) {
14276
14316
  const l22 = checkL2ForOpenAPI(openApi);
14277
14317
  const l42 = checkL4ForOpenAPI(openApi);
14318
+ const ownershipProofs2 = extractFromOpenapi(openApi.raw);
14278
14319
  const base2 = {
14279
14320
  found: true,
14280
14321
  origin,
@@ -14286,7 +14327,8 @@ async function discoverOriginSchema(options) {
14286
14327
  ...l22.version ? { version: l22.version } : {}
14287
14328
  }
14288
14329
  } : {},
14289
- endpoints: l22.routes
14330
+ endpoints: l22.routes,
14331
+ ...ownershipProofs2 ? { ownershipProofs: ownershipProofs2 } : {}
14290
14332
  };
14291
14333
  return withGuidance(base2, l42, guidanceMode);
14292
14334
  }
@@ -14303,6 +14345,7 @@ async function discoverOriginSchema(options) {
14303
14345
  if (!wellKnown) return { found: false, origin, cause: "not_found" };
14304
14346
  const l2 = checkL2ForWellknown(wellKnown);
14305
14347
  const l4 = checkL4ForWellknown(wellKnown);
14348
+ const ownershipProofs = extractFromWellknown(wellKnown.raw);
14306
14349
  const base = {
14307
14350
  found: true,
14308
14351
  origin,
@@ -14313,7 +14356,8 @@ async function discoverOriginSchema(options) {
14313
14356
  ...l2.description ? { description: l2.description } : {}
14314
14357
  }
14315
14358
  } : {},
14316
- endpoints: l2.routes
14359
+ endpoints: l2.routes,
14360
+ ...ownershipProofs ? { ownershipProofs } : {}
14317
14361
  };
14318
14362
  return withGuidance(base, l4, guidanceMode);
14319
14363
  }
@@ -15091,7 +15135,8 @@ async function checkEndpointSchema(options) {
15091
15135
  return { found: false, origin, path, cause: "not_found" };
15092
15136
  }
15093
15137
  const openApiResult = await getOpenAPI(origin, options.headers, options.signal);
15094
- const openApi = openApiResult.isOk() ? openApiResult.value : null;
15138
+ const openApiRaw = openApiResult.isOk() ? openApiResult.value : null;
15139
+ const openApi = isOpenApiSource(openApiRaw) ? openApiRaw : null;
15095
15140
  if (openApi) {
15096
15141
  const advisories2 = getAdvisoriesForOpenAPI(openApi, path);
15097
15142
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
@@ -15202,6 +15247,7 @@ var AUDIT_CODES = {
15202
15247
  OPENAPI_NOT_FOUND: "OPENAPI_NOT_FOUND",
15203
15248
  WELLKNOWN_NOT_FOUND: "WELLKNOWN_NOT_FOUND",
15204
15249
  // ─── OpenAPI quality ─────────────────────────────────────────────────────────
15250
+ OPENAPI_PARSE_ERROR: "OPENAPI_PARSE_ERROR",
15205
15251
  OPENAPI_NO_ROUTES: "OPENAPI_NO_ROUTES",
15206
15252
  // ─── L2 route-list checks ────────────────────────────────────────────────────
15207
15253
  L2_NO_ROUTES: "L2_NO_ROUTES",
@@ -15689,6 +15735,9 @@ function validatePaymentRequiredDetailed(payload, options = {}) {
15689
15735
  }
15690
15736
 
15691
15737
  // src/audit/warnings/sources.ts
15738
+ function isOpenApiParseFailure(value) {
15739
+ return value !== null && "parseFailure" in value;
15740
+ }
15692
15741
  function getWarningsForOpenAPI(openApi) {
15693
15742
  if (openApi === null) {
15694
15743
  return [
@@ -15700,6 +15749,18 @@ function getWarningsForOpenAPI(openApi) {
15700
15749
  }
15701
15750
  ];
15702
15751
  }
15752
+ if (isOpenApiParseFailure(openApi)) {
15753
+ const details = openApi.issues.map((i) => ` ${i.path.map(String).join(".")}: ${i.message}`).join("\n");
15754
+ return [
15755
+ {
15756
+ code: AUDIT_CODES.OPENAPI_PARSE_ERROR,
15757
+ severity: "warn",
15758
+ message: `OpenAPI spec found at ${openApi.fetchedUrl} but failed schema validation:
15759
+ ${details}`,
15760
+ hint: "Fix the schema issues above so discovery can read the spec."
15761
+ }
15762
+ ];
15763
+ }
15703
15764
  const warnings = [];
15704
15765
  if (openApi.routes.length === 0) {
15705
15766
  warnings.push({
@@ -15852,5 +15913,6 @@ export {
15852
15913
  getWarningsForWellKnown,
15853
15914
  getWellKnown,
15854
15915
  getX402WellKnown,
15916
+ isOpenApiParseFailure,
15855
15917
  validatePaymentRequiredDetailed
15856
15918
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/discovery",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Canonical OpenAPI-first discovery runtime for the agentcash ecosystem",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",