@agentcash/discovery 1.0.0 → 1.0.2

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 CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  Canonical discovery runtime for the agentcash ecosystem.
4
4
 
5
- Use one library for CLI, server, and client so discovery behavior is identical everywhere.
5
+ Use one library for MCP, CLI, router, and audit so discovery behavior is identical everywhere.
6
6
 
7
7
  ## Why One Library
8
8
 
9
9
  - Same parsing logic across surfaces: no CLI/server/client drift.
10
+ - Shared Zod schema that the router can test against at compile-time.
10
11
  - Same warning codes and precedence rules: fewer integration surprises.
11
12
  - Same compatibility adapters in one place: legacy behavior is isolated and removable.
12
- - Same L0-L5 harness model: easier context-budget auditing and rollout decisions.
13
13
 
14
14
  ## L0-L5 Mental Model
15
15
 
@@ -22,196 +22,128 @@ Use one library for CLI, server, and client so discovery behavior is identical e
22
22
 
23
23
  Design rule: `L0` + `L1` are zero-hop critical. `L2+` should be fetched on demand.
24
24
 
25
+ In practice, each layer should guide the agent to discover the next:
26
+
27
+ | Layer | Surface | What the agent gets |
28
+ | ------ | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
29
+ | **L0** | MCP tool description / `agentcash --help` | First impression of agentcash. Should encourage the agent to use it and explicitly explain `discoverOriginSchema` and `checkEndpointSchema`. |
30
+ | **L1** | Same location as L0 | List of domains available to the agent. Each entry should be descriptive enough for the agent to understand what it does at a high level. |
31
+ | **L2** | `discoverOriginSchema` result | Detailed description of the origin and its supported endpoints. |
32
+ | **L3** | `checkEndpointSchema` result | Specific guidance for a single endpoint: input/output schema, auth mode, and a detailed description of what the endpoint does. |
33
+ | **L4** | `discoverOriginSchema` with `includeGuidance: true` | Composition guidance for 2+ resources at an origin. Sourced from the `guidance` field in OpenAPI. |
34
+
25
35
  ## Install
26
36
 
27
37
  ```bash
28
38
  pnpm add @agentcash/discovery
29
39
  ```
30
40
 
31
- ## CLI Usage
41
+ ## CLI
32
42
 
33
- Quick audit:
43
+ Two commands: `discover` (list endpoints at an origin) and `check` (inspect a specific URL).
34
44
 
35
45
  ```bash
46
+ # Discover all endpoints at an origin
36
47
  npx @agentcash/discovery stabletravel.dev
37
- ```
48
+ npx @agentcash/discovery discover stabletravel.dev
38
49
 
39
- Verbose matrices:
40
-
41
- ```bash
42
- npx @agentcash/discovery stabletravel.dev -v
50
+ # Inspect a specific endpoint URL
51
+ npx @agentcash/discovery check https://stabletravel.dev/search
43
52
  ```
44
53
 
45
- Machine-readable output:
54
+ Flags:
46
55
 
47
- ```bash
48
- npx @agentcash/discovery stabletravel.dev --json
49
- ```
56
+ | Flag | Description |
57
+ | -------- | -------------------------------------------------- |
58
+ | `--json` | Machine-readable JSON output |
59
+ | `-v` | Verbose — includes guidance text and warning hints |
50
60
 
51
- L0-L5 context harness summary for a client:
61
+ JSON output shape (`discover`):
52
62
 
53
- ```bash
54
- npx @agentcash/discovery stabletravel.dev --harness --client claude-code
63
+ ```json
64
+ {
65
+ "ok": true,
66
+ "selectedStage": "openapi",
67
+ "resources": [{ "resourceKey": "GET /search", "method": "GET", "path": "/search" }],
68
+ "warnings": [],
69
+ "meta": { "origin": "https://stabletravel.dev", "specUrl": "..." }
70
+ }
55
71
  ```
56
72
 
57
- L0-L5 harness verbose with explicit budget:
58
-
59
- ```bash
60
- npx @agentcash/discovery stabletravel.dev --harness -v --client skill-cli --context-window-tokens 200000
73
+ JSON output shape (`check`):
74
+
75
+ ```json
76
+ {
77
+ "url": "https://stabletravel.dev/search",
78
+ "found": true,
79
+ "origin": "https://stabletravel.dev",
80
+ "path": "/search",
81
+ "advisories": [{ "method": "GET", "authMode": "bearer", "estimatedPrice": "$0.01" }],
82
+ "warnings": []
83
+ }
61
84
  ```
62
85
 
63
- Useful flags:
64
-
65
- - `--compat on|off|strict`
66
- - `--probe`
67
- - `--timeout-ms <ms>`
68
- - `--no-truncate`
69
- - `--no-color`
70
-
71
86
  ## Programmatic Usage
72
87
 
73
88
  ```ts
74
- import {
75
- auditContextHarness,
76
- discover,
77
- discoverDetailed,
78
- validatePaymentRequiredDetailed,
79
- type HarnessClientId,
80
- } from '@agentcash/discovery';
81
-
82
- const progressive = await discover({
83
- target: 'stabletravel.dev',
84
- compatMode: 'on',
85
- });
86
-
87
- const detailed = await discoverDetailed({
88
- target: 'stabletravel.dev',
89
- compatMode: 'strict',
90
- rawView: 'full',
91
- });
92
-
93
- const client: HarnessClientId = 'claude-code';
94
- const harness = await auditContextHarness({
95
- target: 'stabletravel.dev',
96
- client,
97
- contextWindowTokens: 200000,
98
- compatMode: 'on',
99
- });
100
-
101
- const validation = validatePaymentRequiredDetailed(payload, {
102
- compatMode: 'strict',
103
- metadata: {
104
- title: 'Example API',
105
- description: 'Sample description',
106
- favicon: 'https://example.com/favicon.ico',
107
- ogImages: [{ url: 'https://example.com/og.png' }],
108
- },
109
- });
110
- ```
111
-
112
- ## MCP Adapter Contract
113
-
114
- This section is the canonical contract for MCP-facing discovery adapters:
115
-
116
- - `discoverForMcp(options)` for L2 resources + L4 guidance policy projection.
117
- - `inspectEndpointForMcp(options)` for L3 OpenAPI advisory projection.
118
-
119
- `discoverForMcp` guarantees:
120
-
121
- - `guidanceAvailable` is always present.
122
- - `guidanceTokens` is present when guidance exists.
123
- - `guidance` is included when `includeGuidance=true`, excluded when
124
- `includeGuidance=false`, and auto-included under the token threshold when not
125
- specified.
126
-
127
- `inspectEndpointForMcp` guarantees:
128
-
129
- - Spec-derived HTTP methods for the selected endpoint path.
130
- - Per-method advisory data: summary, estimated price, protocols, auth mode, and
131
- input schema.
132
-
133
- Ownership boundary:
134
-
135
- - `@agentcash/discovery` owns discovery/advisory contracts.
136
- - Runtime probe truth (live 402 parsing/payment option extraction/divergence)
137
- belongs to the `agentcash` MCP package.
138
-
139
- Reference integration boundary:
140
-
141
- - `https://github.com/Merit-Systems/agentcash/blob/main/packages/external/mcp/docs/discovery-boundary.md`
89
+ import { discoverOriginSchema, checkEndpointSchema } from '@agentcash/discovery';
142
90
 
143
- ## Discovery Waterfall
91
+ // Discover all endpoints at an origin
92
+ const result = await discoverOriginSchema({ target: 'stabletravel.dev' });
93
+ // result.found === true → result.endpoints (L2Route[]), result.guidance?, result.guidanceTokens?
144
94
 
145
- Default order:
146
-
147
- 1. Explicit override URLs (if provided)
148
- 2. OpenAPI (`/openapi.json`, then `/.well-known/openapi.json`)
149
- 3. `/.well-known/x402` (compat)
150
- 4. DNS TXT `_x402` pointers (compat)
151
- 5. Probe fallback (only when probe candidates are provided)
95
+ // Inspect a specific endpoint URL
96
+ const check = await checkEndpointSchema({ url: 'https://stabletravel.dev/search' });
97
+ // check.found === true check.advisories (per-method: authMode, estimatedPrice, protocols, inputSchema)
98
+ ```
152
99
 
153
- Behavior:
100
+ ## Exported API
154
101
 
155
- - `discover(...)` stops at first valid non-empty stage.
156
- - `discoverDetailed(...)` runs full waterfall and merges deterministically.
102
+ ### Core discovery
157
103
 
158
- Validation behavior:
104
+ | Export | Description |
105
+ | ------------------------ | --------------------------------------------------------- |
106
+ | `discoverOriginSchema()` | Progressive discovery — returns endpoints + advisory data |
107
+ | `checkEndpointSchema()` | Per-endpoint inspection — returns per-method advisories |
159
108
 
160
- - `validatePaymentRequiredDetailed(...)` uses Coinbase `@x402/core` schemas as the structural base gate.
161
- - Product policy diagnostics (network/schema/metadata) are layered on top with stable issue codes.
109
+ ### Layer fetchers (low-level)
162
110
 
163
- ## Compatibility Modes
111
+ | Export | Layer | Description |
112
+ | -------------------------- | ----- | ------------------------------------- |
113
+ | `getOpenAPI(origin)` | — | Fetch OpenAPI spec from origin |
114
+ | `getWellKnown(origin)` | — | Fetch `/.well-known/x402` document |
115
+ | `getProbe(url, body?)` | — | Live endpoint probe |
116
+ | `checkL2ForOpenAPI(spec)` | L2 | Extract route list from OpenAPI |
117
+ | `checkL2ForWellknown(doc)` | L2 | Extract route list from well-known |
118
+ | `getL3(origin, path)` | L3 | Get detailed metadata for an endpoint |
119
+ | `checkL4ForOpenAPI(spec)` | L4 | Extract guidance from OpenAPI |
120
+ | `checkL4ForWellknown(doc)` | L4 | Extract guidance from well-known |
164
121
 
165
- - `on` (default): legacy adapters enabled.
166
- - `off`: canonical-only behavior.
167
- - `strict`: legacy adapters enabled, selected warnings escalated.
122
+ ### Validation
168
123
 
169
- ## Contract Guarantees
124
+ | Export | Description |
125
+ | ----------------------------------- | -------------------------------------------- |
126
+ | `validatePaymentRequiredDetailed()` | Full 402 payload validation with diagnostics |
127
+ | `evaluateMetadataCompleteness()` | Metadata quality score |
128
+ | `VALIDATION_CODES` | Stable issue code constants |
170
129
 
171
- Resource identity:
130
+ ### Audit
172
131
 
173
- ```text
174
- ${origin} ${method} ${path}
175
- ```
132
+ | Export | Description |
133
+ | --------------------------- | ------------------------------ |
134
+ | `getWarningsForOpenAPI()` | Warnings for OpenAPI source |
135
+ | `getWarningsForWellKnown()` | Warnings for well-known source |
136
+ | `getWarningsForL2()` | Warnings for route list |
137
+ | `getWarningsForL3()` | Warnings for endpoint metadata |
138
+ | `getWarningsForL4()` | Warnings for guidance layer |
139
+ | `AUDIT_CODES` | Stable audit code constants |
176
140
 
177
- Required normalized fields:
141
+ Ownership boundary:
178
142
 
179
- - `resourceKey`
180
- - `origin`
181
- - `method`
182
- - `path`
183
- - `source`
184
- - `verified` (default `false`)
143
+ - `@agentcash/discovery` owns discovery/advisory contracts.
144
+ - `@agentcash` should own all signing logic, but should be composable with the methods for probing built in this package.
185
145
 
186
146
  Philosophy boundary:
187
147
 
188
148
  - Machine-parsable discovery metadata belongs in OpenAPI.
189
- - `llms.txt` is optional, unstructured guidance.
190
149
  - Discovery is advisory. Runtime payment challenge/probe is authoritative.
191
-
192
- ## Internal Registry Audit Harness
193
-
194
- For x402scan registry benchmarking:
195
-
196
- ```bash
197
- SCAN_DATABASE_URL='postgresql://...' pnpm audit:registry
198
- ```
199
-
200
- Quick sample:
201
-
202
- ```bash
203
- SCAN_DATABASE_URL='postgresql://...' pnpm audit:registry:quick
204
- ```
205
-
206
- Output:
207
-
208
- - `audit/registry-audit-<timestamp>.json`
209
- - `audit/registry-audit-latest.json`
210
-
211
- ## Deeper Docs
212
-
213
- Architecture and planning artifacts live in `.claude/`.
214
-
215
- Validation design doc:
216
-
217
- - `docs/VALIDATION_DIAGNOSTICS_DESIGN_2026-03-03.md`
package/dist/cli.cjs CHANGED
@@ -76,6 +76,7 @@ var OpenApiDocSchema = import_zod.z.object({
76
76
  description: import_zod.z.string().optional(),
77
77
  guidance: import_zod.z.string().optional()
78
78
  }),
79
+ security: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string()))).optional(),
79
80
  servers: import_zod.z.array(import_zod.z.object({ url: import_zod.z.string() })).optional(),
80
81
  tags: import_zod.z.array(import_zod.z.object({ name: import_zod.z.string() })).optional(),
81
82
  components: import_zod.z.object({ securitySchemes: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional() }).optional(),
@@ -105,20 +106,31 @@ var WellKnownParsedSchema = import_zod.z.object({
105
106
  function isRecord(value) {
106
107
  return value !== null && typeof value === "object" && !Array.isArray(value);
107
108
  }
108
- function hasSecurity(operation, scheme) {
109
- return operation.security?.some((s) => scheme in s) ?? false;
110
- }
111
- function has402Response(operation) {
112
- return Boolean(operation.responses?.["402"]);
109
+ function resolveSecurityFlags(requirements, securitySchemes) {
110
+ let hasApiKey = false;
111
+ let hasSiwx = false;
112
+ for (const requirement of requirements) {
113
+ for (const schemeName of Object.keys(requirement)) {
114
+ if (schemeName === "siwx") {
115
+ hasSiwx = true;
116
+ continue;
117
+ }
118
+ if (schemeName === "apiKey") {
119
+ hasApiKey = true;
120
+ continue;
121
+ }
122
+ const def = securitySchemes[schemeName];
123
+ if (isRecord(def) && def["type"] === "apiKey") hasApiKey = true;
124
+ }
125
+ }
126
+ return { hasApiKey, hasSiwx };
113
127
  }
114
- function inferAuthMode(operation) {
128
+ function inferAuthMode(operation, globalSecurity, securitySchemes) {
115
129
  const hasXPaymentInfo = Boolean(operation["x-payment-info"]);
116
- const hasPayment = hasXPaymentInfo || has402Response(operation);
117
- const hasApiKey = hasSecurity(operation, "apiKey");
118
- const hasSiwx = hasSecurity(operation, "siwx");
119
- if (hasPayment && hasApiKey) return "apiKey+paid";
130
+ const effectiveSecurity = operation.security !== void 0 && operation.security.length > 0 ? operation.security : globalSecurity ?? [];
131
+ const { hasApiKey, hasSiwx } = resolveSecurityFlags(effectiveSecurity, securitySchemes ?? {});
132
+ if (hasXPaymentInfo && hasApiKey) return "apiKey+paid";
120
133
  if (hasXPaymentInfo) return "paid";
121
- if (hasPayment) return hasSiwx ? "siwx" : "paid";
122
134
  if (hasApiKey) return "apiKey";
123
135
  if (hasSiwx) return "siwx";
124
136
  return void 0;
@@ -138,10 +150,12 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
138
150
  var DEFAULT_MISSING_METHOD = "POST";
139
151
 
140
152
  // src/core/lib/url.ts
141
- function normalizeOrigin(target) {
153
+ function ensureProtocol(target) {
142
154
  const trimmed = target.trim();
143
- const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
144
- const url = new URL(withProtocol);
155
+ return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
156
+ }
157
+ function normalizeOrigin(target) {
158
+ const url = new URL(ensureProtocol(target));
145
159
  url.pathname = "";
146
160
  url.search = "";
147
161
  url.hash = "";
@@ -180,7 +194,7 @@ function fetchSafe(url, init) {
180
194
  }
181
195
 
182
196
  // src/mmm-enabled.ts
183
- var isMmmEnabled = () => "1.0.0".includes("-mmm");
197
+ var isMmmEnabled = () => "1.0.2".includes("-mmm");
184
198
 
185
199
  // src/core/source/openapi/index.ts
186
200
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -189,15 +203,13 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
189
203
  for (const httpMethod of [...HTTP_METHODS]) {
190
204
  const operation = pathItem[httpMethod.toLowerCase()];
191
205
  if (!operation) continue;
192
- const authMode = inferAuthMode(operation) ?? void 0;
206
+ const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
193
207
  if (!authMode) continue;
194
208
  const p = operation["x-payment-info"];
195
209
  const protocols = (p?.protocols ?? []).filter(
196
210
  (proto) => proto !== "mpp" || isMmmEnabled()
197
211
  );
198
- if ((authMode === "paid" || authMode === "siwx") && !has402Response(operation)) continue;
199
- if (authMode === "paid" && protocols.length === 0) continue;
200
- const pricing = authMode === "paid" && p ? {
212
+ const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
201
213
  pricingMode: p.pricingMode,
202
214
  ...p.price ? { price: p.price } : {},
203
215
  ...p.minPrice ? { minPrice: p.minPrice } : {},
@@ -643,10 +655,12 @@ function extractSchemas3(payload) {
643
655
  return {};
644
656
  }
645
657
  function parseInputSchema(payload) {
646
- return extractSchemas3(payload).inputSchema;
658
+ const schema = extractSchemas3(payload).inputSchema;
659
+ return schema;
647
660
  }
648
661
  function parseOutputSchema(payload) {
649
- return extractSchemas3(payload).outputSchema;
662
+ const schema = extractSchemas3(payload).outputSchema;
663
+ return schema;
650
664
  }
651
665
 
652
666
  // src/core/protocols/x402/v1/parse-payment-required.ts
@@ -874,6 +888,20 @@ function extractRequestBodySchema(operationSchema) {
874
888
  }
875
889
  return void 0;
876
890
  }
891
+ function extractOutputSchema(operationSchema) {
892
+ const responses = operationSchema.responses;
893
+ if (!isRecord(responses)) return void 0;
894
+ const candidate = responses["200"] ?? responses["201"] ?? Object.entries(responses).find(([k]) => k.startsWith("2"))?.[1];
895
+ if (!isRecord(candidate)) return void 0;
896
+ const content = candidate.content;
897
+ if (!isRecord(content)) return void 0;
898
+ const json = content["application/json"];
899
+ if (isRecord(json) && isRecord(json.schema)) return json.schema;
900
+ for (const mediaType of Object.values(content)) {
901
+ if (isRecord(mediaType) && isRecord(mediaType.schema)) return mediaType.schema;
902
+ }
903
+ return void 0;
904
+ }
877
905
  function extractParameters(operationSchema) {
878
906
  const params = operationSchema.parameters;
879
907
  if (!Array.isArray(params)) return [];
@@ -932,7 +960,7 @@ function getL3ForOpenAPI(openApi, path, method) {
932
960
  estimatedPrice: parseOperationPrice(resolvedOperation),
933
961
  protocols: parseOperationProtocols(resolvedOperation),
934
962
  inputSchema: extractInputSchema(resolvedOperation),
935
- outputSchema: resolvedOperation
963
+ outputSchema: extractOutputSchema(resolvedOperation)
936
964
  };
937
965
  }
938
966
  function getL3ForProbe(probe, path, method) {
@@ -969,12 +997,12 @@ function getAdvisoriesForProbe(probe, path) {
969
997
  });
970
998
  }
971
999
  async function checkEndpointSchema(options) {
972
- const endpoint = new URL(options.url);
1000
+ const endpoint = new URL(ensureProtocol(options.url));
973
1001
  const origin = normalizeOrigin(endpoint.origin);
974
1002
  const path = normalizePath(endpoint.pathname || "/");
975
1003
  if (options.sampleInputBody !== void 0) {
976
1004
  const probeResult2 = await getProbe(
977
- options.url,
1005
+ endpoint.href,
978
1006
  options.headers,
979
1007
  options.signal,
980
1008
  options.sampleInputBody
@@ -999,7 +1027,7 @@ async function checkEndpointSchema(options) {
999
1027
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
1000
1028
  return { found: false, origin, path, cause: "not_found" };
1001
1029
  }
1002
- const probeResult = await getProbe(options.url, options.headers, options.signal);
1030
+ const probeResult = await getProbe(endpoint.href, options.headers, options.signal);
1003
1031
  if (probeResult.isErr()) {
1004
1032
  return {
1005
1033
  found: false,
package/dist/cli.js CHANGED
@@ -50,6 +50,7 @@ var OpenApiDocSchema = z.object({
50
50
  description: z.string().optional(),
51
51
  guidance: z.string().optional()
52
52
  }),
53
+ security: z.array(z.record(z.string(), z.array(z.string()))).optional(),
53
54
  servers: z.array(z.object({ url: z.string() })).optional(),
54
55
  tags: z.array(z.object({ name: z.string() })).optional(),
55
56
  components: z.object({ securitySchemes: z.record(z.string(), z.unknown()).optional() }).optional(),
@@ -79,20 +80,31 @@ var WellKnownParsedSchema = z.object({
79
80
  function isRecord(value) {
80
81
  return value !== null && typeof value === "object" && !Array.isArray(value);
81
82
  }
82
- function hasSecurity(operation, scheme) {
83
- return operation.security?.some((s) => scheme in s) ?? false;
84
- }
85
- function has402Response(operation) {
86
- return Boolean(operation.responses?.["402"]);
83
+ function resolveSecurityFlags(requirements, securitySchemes) {
84
+ let hasApiKey = false;
85
+ let hasSiwx = false;
86
+ for (const requirement of requirements) {
87
+ for (const schemeName of Object.keys(requirement)) {
88
+ if (schemeName === "siwx") {
89
+ hasSiwx = true;
90
+ continue;
91
+ }
92
+ if (schemeName === "apiKey") {
93
+ hasApiKey = true;
94
+ continue;
95
+ }
96
+ const def = securitySchemes[schemeName];
97
+ if (isRecord(def) && def["type"] === "apiKey") hasApiKey = true;
98
+ }
99
+ }
100
+ return { hasApiKey, hasSiwx };
87
101
  }
88
- function inferAuthMode(operation) {
102
+ function inferAuthMode(operation, globalSecurity, securitySchemes) {
89
103
  const hasXPaymentInfo = Boolean(operation["x-payment-info"]);
90
- const hasPayment = hasXPaymentInfo || has402Response(operation);
91
- const hasApiKey = hasSecurity(operation, "apiKey");
92
- const hasSiwx = hasSecurity(operation, "siwx");
93
- if (hasPayment && hasApiKey) return "apiKey+paid";
104
+ const effectiveSecurity = operation.security !== void 0 && operation.security.length > 0 ? operation.security : globalSecurity ?? [];
105
+ const { hasApiKey, hasSiwx } = resolveSecurityFlags(effectiveSecurity, securitySchemes ?? {});
106
+ if (hasXPaymentInfo && hasApiKey) return "apiKey+paid";
94
107
  if (hasXPaymentInfo) return "paid";
95
- if (hasPayment) return hasSiwx ? "siwx" : "paid";
96
108
  if (hasApiKey) return "apiKey";
97
109
  if (hasSiwx) return "siwx";
98
110
  return void 0;
@@ -112,10 +124,12 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
112
124
  var DEFAULT_MISSING_METHOD = "POST";
113
125
 
114
126
  // src/core/lib/url.ts
115
- function normalizeOrigin(target) {
127
+ function ensureProtocol(target) {
116
128
  const trimmed = target.trim();
117
- const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
118
- const url = new URL(withProtocol);
129
+ return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
130
+ }
131
+ function normalizeOrigin(target) {
132
+ const url = new URL(ensureProtocol(target));
119
133
  url.pathname = "";
120
134
  url.search = "";
121
135
  url.hash = "";
@@ -154,7 +168,7 @@ function fetchSafe(url, init) {
154
168
  }
155
169
 
156
170
  // src/mmm-enabled.ts
157
- var isMmmEnabled = () => "1.0.0".includes("-mmm");
171
+ var isMmmEnabled = () => "1.0.2".includes("-mmm");
158
172
 
159
173
  // src/core/source/openapi/index.ts
160
174
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -163,15 +177,13 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
163
177
  for (const httpMethod of [...HTTP_METHODS]) {
164
178
  const operation = pathItem[httpMethod.toLowerCase()];
165
179
  if (!operation) continue;
166
- const authMode = inferAuthMode(operation) ?? void 0;
180
+ const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
167
181
  if (!authMode) continue;
168
182
  const p = operation["x-payment-info"];
169
183
  const protocols = (p?.protocols ?? []).filter(
170
184
  (proto) => proto !== "mpp" || isMmmEnabled()
171
185
  );
172
- if ((authMode === "paid" || authMode === "siwx") && !has402Response(operation)) continue;
173
- if (authMode === "paid" && protocols.length === 0) continue;
174
- const pricing = authMode === "paid" && p ? {
186
+ const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
175
187
  pricingMode: p.pricingMode,
176
188
  ...p.price ? { price: p.price } : {},
177
189
  ...p.minPrice ? { minPrice: p.minPrice } : {},
@@ -617,10 +629,12 @@ function extractSchemas3(payload) {
617
629
  return {};
618
630
  }
619
631
  function parseInputSchema(payload) {
620
- return extractSchemas3(payload).inputSchema;
632
+ const schema = extractSchemas3(payload).inputSchema;
633
+ return schema;
621
634
  }
622
635
  function parseOutputSchema(payload) {
623
- return extractSchemas3(payload).outputSchema;
636
+ const schema = extractSchemas3(payload).outputSchema;
637
+ return schema;
624
638
  }
625
639
 
626
640
  // src/core/protocols/x402/v1/parse-payment-required.ts
@@ -848,6 +862,20 @@ function extractRequestBodySchema(operationSchema) {
848
862
  }
849
863
  return void 0;
850
864
  }
865
+ function extractOutputSchema(operationSchema) {
866
+ const responses = operationSchema.responses;
867
+ if (!isRecord(responses)) return void 0;
868
+ const candidate = responses["200"] ?? responses["201"] ?? Object.entries(responses).find(([k]) => k.startsWith("2"))?.[1];
869
+ if (!isRecord(candidate)) return void 0;
870
+ const content = candidate.content;
871
+ if (!isRecord(content)) return void 0;
872
+ const json = content["application/json"];
873
+ if (isRecord(json) && isRecord(json.schema)) return json.schema;
874
+ for (const mediaType of Object.values(content)) {
875
+ if (isRecord(mediaType) && isRecord(mediaType.schema)) return mediaType.schema;
876
+ }
877
+ return void 0;
878
+ }
851
879
  function extractParameters(operationSchema) {
852
880
  const params = operationSchema.parameters;
853
881
  if (!Array.isArray(params)) return [];
@@ -906,7 +934,7 @@ function getL3ForOpenAPI(openApi, path, method) {
906
934
  estimatedPrice: parseOperationPrice(resolvedOperation),
907
935
  protocols: parseOperationProtocols(resolvedOperation),
908
936
  inputSchema: extractInputSchema(resolvedOperation),
909
- outputSchema: resolvedOperation
937
+ outputSchema: extractOutputSchema(resolvedOperation)
910
938
  };
911
939
  }
912
940
  function getL3ForProbe(probe, path, method) {
@@ -943,12 +971,12 @@ function getAdvisoriesForProbe(probe, path) {
943
971
  });
944
972
  }
945
973
  async function checkEndpointSchema(options) {
946
- const endpoint = new URL(options.url);
974
+ const endpoint = new URL(ensureProtocol(options.url));
947
975
  const origin = normalizeOrigin(endpoint.origin);
948
976
  const path = normalizePath(endpoint.pathname || "/");
949
977
  if (options.sampleInputBody !== void 0) {
950
978
  const probeResult2 = await getProbe(
951
- options.url,
979
+ endpoint.href,
952
980
  options.headers,
953
981
  options.signal,
954
982
  options.sampleInputBody
@@ -973,7 +1001,7 @@ async function checkEndpointSchema(options) {
973
1001
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
974
1002
  return { found: false, origin, path, cause: "not_found" };
975
1003
  }
976
- const probeResult = await getProbe(options.url, options.headers, options.signal);
1004
+ const probeResult = await getProbe(endpoint.href, options.headers, options.signal);
977
1005
  if (probeResult.isErr()) {
978
1006
  return {
979
1007
  found: false,
package/dist/index.cjs CHANGED
@@ -97,6 +97,7 @@ var OpenApiDocSchema = import_zod.z.object({
97
97
  description: import_zod.z.string().optional(),
98
98
  guidance: import_zod.z.string().optional()
99
99
  }),
100
+ security: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string()))).optional(),
100
101
  servers: import_zod.z.array(import_zod.z.object({ url: import_zod.z.string() })).optional(),
101
102
  tags: import_zod.z.array(import_zod.z.object({ name: import_zod.z.string() })).optional(),
102
103
  components: import_zod.z.object({ securitySchemes: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional() }).optional(),
@@ -126,20 +127,31 @@ var WellKnownParsedSchema = import_zod.z.object({
126
127
  function isRecord(value) {
127
128
  return value !== null && typeof value === "object" && !Array.isArray(value);
128
129
  }
129
- function hasSecurity(operation, scheme) {
130
- return operation.security?.some((s) => scheme in s) ?? false;
131
- }
132
- function has402Response(operation) {
133
- return Boolean(operation.responses?.["402"]);
130
+ function resolveSecurityFlags(requirements, securitySchemes) {
131
+ let hasApiKey = false;
132
+ let hasSiwx = false;
133
+ for (const requirement of requirements) {
134
+ for (const schemeName of Object.keys(requirement)) {
135
+ if (schemeName === "siwx") {
136
+ hasSiwx = true;
137
+ continue;
138
+ }
139
+ if (schemeName === "apiKey") {
140
+ hasApiKey = true;
141
+ continue;
142
+ }
143
+ const def = securitySchemes[schemeName];
144
+ if (isRecord(def) && def["type"] === "apiKey") hasApiKey = true;
145
+ }
146
+ }
147
+ return { hasApiKey, hasSiwx };
134
148
  }
135
- function inferAuthMode(operation) {
149
+ function inferAuthMode(operation, globalSecurity, securitySchemes) {
136
150
  const hasXPaymentInfo = Boolean(operation["x-payment-info"]);
137
- const hasPayment = hasXPaymentInfo || has402Response(operation);
138
- const hasApiKey = hasSecurity(operation, "apiKey");
139
- const hasSiwx = hasSecurity(operation, "siwx");
140
- if (hasPayment && hasApiKey) return "apiKey+paid";
151
+ const effectiveSecurity = operation.security !== void 0 && operation.security.length > 0 ? operation.security : globalSecurity ?? [];
152
+ const { hasApiKey, hasSiwx } = resolveSecurityFlags(effectiveSecurity, securitySchemes ?? {});
153
+ if (hasXPaymentInfo && hasApiKey) return "apiKey+paid";
141
154
  if (hasXPaymentInfo) return "paid";
142
- if (hasPayment) return hasSiwx ? "siwx" : "paid";
143
155
  if (hasApiKey) return "apiKey";
144
156
  if (hasSiwx) return "siwx";
145
157
  return void 0;
@@ -159,10 +171,12 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
159
171
  var DEFAULT_MISSING_METHOD = "POST";
160
172
 
161
173
  // src/core/lib/url.ts
162
- function normalizeOrigin(target) {
174
+ function ensureProtocol(target) {
163
175
  const trimmed = target.trim();
164
- const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
165
- const url = new URL(withProtocol);
176
+ return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
177
+ }
178
+ function normalizeOrigin(target) {
179
+ const url = new URL(ensureProtocol(target));
166
180
  url.pathname = "";
167
181
  url.search = "";
168
182
  url.hash = "";
@@ -201,7 +215,7 @@ function fetchSafe(url, init) {
201
215
  }
202
216
 
203
217
  // src/mmm-enabled.ts
204
- var isMmmEnabled = () => "1.0.0".includes("-mmm");
218
+ var isMmmEnabled = () => "1.0.2".includes("-mmm");
205
219
 
206
220
  // src/core/source/openapi/index.ts
207
221
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -210,15 +224,13 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
210
224
  for (const httpMethod of [...HTTP_METHODS]) {
211
225
  const operation = pathItem[httpMethod.toLowerCase()];
212
226
  if (!operation) continue;
213
- const authMode = inferAuthMode(operation) ?? void 0;
227
+ const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
214
228
  if (!authMode) continue;
215
229
  const p = operation["x-payment-info"];
216
230
  const protocols = (p?.protocols ?? []).filter(
217
231
  (proto) => proto !== "mpp" || isMmmEnabled()
218
232
  );
219
- if ((authMode === "paid" || authMode === "siwx") && !has402Response(operation)) continue;
220
- if (authMode === "paid" && protocols.length === 0) continue;
221
- const pricing = authMode === "paid" && p ? {
233
+ const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
222
234
  pricingMode: p.pricingMode,
223
235
  ...p.price ? { price: p.price } : {},
224
236
  ...p.minPrice ? { minPrice: p.minPrice } : {},
@@ -816,10 +828,12 @@ function extractSchemas3(payload) {
816
828
  return {};
817
829
  }
818
830
  function parseInputSchema(payload) {
819
- return extractSchemas3(payload).inputSchema;
831
+ const schema = extractSchemas3(payload).inputSchema;
832
+ return schema;
820
833
  }
821
834
  function parseOutputSchema(payload) {
822
- return extractSchemas3(payload).outputSchema;
835
+ const schema = extractSchemas3(payload).outputSchema;
836
+ return schema;
823
837
  }
824
838
 
825
839
  // src/core/protocols/x402/v1/parse-payment-required.ts
@@ -1047,6 +1061,20 @@ function extractRequestBodySchema(operationSchema) {
1047
1061
  }
1048
1062
  return void 0;
1049
1063
  }
1064
+ function extractOutputSchema(operationSchema) {
1065
+ const responses = operationSchema.responses;
1066
+ if (!isRecord(responses)) return void 0;
1067
+ const candidate = responses["200"] ?? responses["201"] ?? Object.entries(responses).find(([k]) => k.startsWith("2"))?.[1];
1068
+ if (!isRecord(candidate)) return void 0;
1069
+ const content = candidate.content;
1070
+ if (!isRecord(content)) return void 0;
1071
+ const json = content["application/json"];
1072
+ if (isRecord(json) && isRecord(json.schema)) return json.schema;
1073
+ for (const mediaType of Object.values(content)) {
1074
+ if (isRecord(mediaType) && isRecord(mediaType.schema)) return mediaType.schema;
1075
+ }
1076
+ return void 0;
1077
+ }
1050
1078
  function extractParameters(operationSchema) {
1051
1079
  const params = operationSchema.parameters;
1052
1080
  if (!Array.isArray(params)) return [];
@@ -1105,7 +1133,7 @@ function getL3ForOpenAPI(openApi, path, method) {
1105
1133
  estimatedPrice: parseOperationPrice(resolvedOperation),
1106
1134
  protocols: parseOperationProtocols(resolvedOperation),
1107
1135
  inputSchema: extractInputSchema(resolvedOperation),
1108
- outputSchema: resolvedOperation
1136
+ outputSchema: extractOutputSchema(resolvedOperation)
1109
1137
  };
1110
1138
  }
1111
1139
  function getL3ForProbe(probe, path, method) {
@@ -1146,12 +1174,12 @@ function getAdvisoriesForProbe(probe, path) {
1146
1174
  });
1147
1175
  }
1148
1176
  async function checkEndpointSchema(options) {
1149
- const endpoint = new URL(options.url);
1177
+ const endpoint = new URL(ensureProtocol(options.url));
1150
1178
  const origin = normalizeOrigin(endpoint.origin);
1151
1179
  const path = normalizePath(endpoint.pathname || "/");
1152
1180
  if (options.sampleInputBody !== void 0) {
1153
1181
  const probeResult2 = await getProbe(
1154
- options.url,
1182
+ endpoint.href,
1155
1183
  options.headers,
1156
1184
  options.signal,
1157
1185
  options.sampleInputBody
@@ -1176,7 +1204,7 @@ async function checkEndpointSchema(options) {
1176
1204
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
1177
1205
  return { found: false, origin, path, cause: "not_found" };
1178
1206
  }
1179
- const probeResult = await getProbe(options.url, options.headers, options.signal);
1207
+ const probeResult = await getProbe(endpoint.href, options.headers, options.signal);
1180
1208
  if (probeResult.isErr()) {
1181
1209
  return {
1182
1210
  found: false,
package/dist/index.js CHANGED
@@ -50,6 +50,7 @@ var OpenApiDocSchema = z.object({
50
50
  description: z.string().optional(),
51
51
  guidance: z.string().optional()
52
52
  }),
53
+ security: z.array(z.record(z.string(), z.array(z.string()))).optional(),
53
54
  servers: z.array(z.object({ url: z.string() })).optional(),
54
55
  tags: z.array(z.object({ name: z.string() })).optional(),
55
56
  components: z.object({ securitySchemes: z.record(z.string(), z.unknown()).optional() }).optional(),
@@ -79,20 +80,31 @@ var WellKnownParsedSchema = z.object({
79
80
  function isRecord(value) {
80
81
  return value !== null && typeof value === "object" && !Array.isArray(value);
81
82
  }
82
- function hasSecurity(operation, scheme) {
83
- return operation.security?.some((s) => scheme in s) ?? false;
84
- }
85
- function has402Response(operation) {
86
- return Boolean(operation.responses?.["402"]);
83
+ function resolveSecurityFlags(requirements, securitySchemes) {
84
+ let hasApiKey = false;
85
+ let hasSiwx = false;
86
+ for (const requirement of requirements) {
87
+ for (const schemeName of Object.keys(requirement)) {
88
+ if (schemeName === "siwx") {
89
+ hasSiwx = true;
90
+ continue;
91
+ }
92
+ if (schemeName === "apiKey") {
93
+ hasApiKey = true;
94
+ continue;
95
+ }
96
+ const def = securitySchemes[schemeName];
97
+ if (isRecord(def) && def["type"] === "apiKey") hasApiKey = true;
98
+ }
99
+ }
100
+ return { hasApiKey, hasSiwx };
87
101
  }
88
- function inferAuthMode(operation) {
102
+ function inferAuthMode(operation, globalSecurity, securitySchemes) {
89
103
  const hasXPaymentInfo = Boolean(operation["x-payment-info"]);
90
- const hasPayment = hasXPaymentInfo || has402Response(operation);
91
- const hasApiKey = hasSecurity(operation, "apiKey");
92
- const hasSiwx = hasSecurity(operation, "siwx");
93
- if (hasPayment && hasApiKey) return "apiKey+paid";
104
+ const effectiveSecurity = operation.security !== void 0 && operation.security.length > 0 ? operation.security : globalSecurity ?? [];
105
+ const { hasApiKey, hasSiwx } = resolveSecurityFlags(effectiveSecurity, securitySchemes ?? {});
106
+ if (hasXPaymentInfo && hasApiKey) return "apiKey+paid";
94
107
  if (hasXPaymentInfo) return "paid";
95
- if (hasPayment) return hasSiwx ? "siwx" : "paid";
96
108
  if (hasApiKey) return "apiKey";
97
109
  if (hasSiwx) return "siwx";
98
110
  return void 0;
@@ -112,10 +124,12 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
112
124
  var DEFAULT_MISSING_METHOD = "POST";
113
125
 
114
126
  // src/core/lib/url.ts
115
- function normalizeOrigin(target) {
127
+ function ensureProtocol(target) {
116
128
  const trimmed = target.trim();
117
- const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
118
- const url = new URL(withProtocol);
129
+ return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
130
+ }
131
+ function normalizeOrigin(target) {
132
+ const url = new URL(ensureProtocol(target));
119
133
  url.pathname = "";
120
134
  url.search = "";
121
135
  url.hash = "";
@@ -154,7 +168,7 @@ function fetchSafe(url, init) {
154
168
  }
155
169
 
156
170
  // src/mmm-enabled.ts
157
- var isMmmEnabled = () => "1.0.0".includes("-mmm");
171
+ var isMmmEnabled = () => "1.0.2".includes("-mmm");
158
172
 
159
173
  // src/core/source/openapi/index.ts
160
174
  var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
@@ -163,15 +177,13 @@ var OpenApiParsedSchema = OpenApiDocSchema.transform((doc) => {
163
177
  for (const httpMethod of [...HTTP_METHODS]) {
164
178
  const operation = pathItem[httpMethod.toLowerCase()];
165
179
  if (!operation) continue;
166
- const authMode = inferAuthMode(operation) ?? void 0;
180
+ const authMode = inferAuthMode(operation, doc.security, doc.components?.securitySchemes) ?? void 0;
167
181
  if (!authMode) continue;
168
182
  const p = operation["x-payment-info"];
169
183
  const protocols = (p?.protocols ?? []).filter(
170
184
  (proto) => proto !== "mpp" || isMmmEnabled()
171
185
  );
172
- if ((authMode === "paid" || authMode === "siwx") && !has402Response(operation)) continue;
173
- if (authMode === "paid" && protocols.length === 0) continue;
174
- const pricing = authMode === "paid" && p ? {
186
+ const pricing = (authMode === "paid" || authMode === "apiKey+paid") && p ? {
175
187
  pricingMode: p.pricingMode,
176
188
  ...p.price ? { price: p.price } : {},
177
189
  ...p.minPrice ? { minPrice: p.minPrice } : {},
@@ -769,10 +781,12 @@ function extractSchemas3(payload) {
769
781
  return {};
770
782
  }
771
783
  function parseInputSchema(payload) {
772
- return extractSchemas3(payload).inputSchema;
784
+ const schema = extractSchemas3(payload).inputSchema;
785
+ return schema;
773
786
  }
774
787
  function parseOutputSchema(payload) {
775
- return extractSchemas3(payload).outputSchema;
788
+ const schema = extractSchemas3(payload).outputSchema;
789
+ return schema;
776
790
  }
777
791
 
778
792
  // src/core/protocols/x402/v1/parse-payment-required.ts
@@ -1000,6 +1014,20 @@ function extractRequestBodySchema(operationSchema) {
1000
1014
  }
1001
1015
  return void 0;
1002
1016
  }
1017
+ function extractOutputSchema(operationSchema) {
1018
+ const responses = operationSchema.responses;
1019
+ if (!isRecord(responses)) return void 0;
1020
+ const candidate = responses["200"] ?? responses["201"] ?? Object.entries(responses).find(([k]) => k.startsWith("2"))?.[1];
1021
+ if (!isRecord(candidate)) return void 0;
1022
+ const content = candidate.content;
1023
+ if (!isRecord(content)) return void 0;
1024
+ const json = content["application/json"];
1025
+ if (isRecord(json) && isRecord(json.schema)) return json.schema;
1026
+ for (const mediaType of Object.values(content)) {
1027
+ if (isRecord(mediaType) && isRecord(mediaType.schema)) return mediaType.schema;
1028
+ }
1029
+ return void 0;
1030
+ }
1003
1031
  function extractParameters(operationSchema) {
1004
1032
  const params = operationSchema.parameters;
1005
1033
  if (!Array.isArray(params)) return [];
@@ -1058,7 +1086,7 @@ function getL3ForOpenAPI(openApi, path, method) {
1058
1086
  estimatedPrice: parseOperationPrice(resolvedOperation),
1059
1087
  protocols: parseOperationProtocols(resolvedOperation),
1060
1088
  inputSchema: extractInputSchema(resolvedOperation),
1061
- outputSchema: resolvedOperation
1089
+ outputSchema: extractOutputSchema(resolvedOperation)
1062
1090
  };
1063
1091
  }
1064
1092
  function getL3ForProbe(probe, path, method) {
@@ -1099,12 +1127,12 @@ function getAdvisoriesForProbe(probe, path) {
1099
1127
  });
1100
1128
  }
1101
1129
  async function checkEndpointSchema(options) {
1102
- const endpoint = new URL(options.url);
1130
+ const endpoint = new URL(ensureProtocol(options.url));
1103
1131
  const origin = normalizeOrigin(endpoint.origin);
1104
1132
  const path = normalizePath(endpoint.pathname || "/");
1105
1133
  if (options.sampleInputBody !== void 0) {
1106
1134
  const probeResult2 = await getProbe(
1107
- options.url,
1135
+ endpoint.href,
1108
1136
  options.headers,
1109
1137
  options.signal,
1110
1138
  options.sampleInputBody
@@ -1129,7 +1157,7 @@ async function checkEndpointSchema(options) {
1129
1157
  if (advisories2.length > 0) return { found: true, origin, path, advisories: advisories2 };
1130
1158
  return { found: false, origin, path, cause: "not_found" };
1131
1159
  }
1132
- const probeResult = await getProbe(options.url, options.headers, options.signal);
1160
+ const probeResult = await getProbe(endpoint.href, options.headers, options.signal);
1133
1161
  if (probeResult.isErr()) {
1134
1162
  return {
1135
1163
  found: false,
package/dist/schemas.cjs CHANGED
@@ -76,6 +76,7 @@ var OpenApiDocSchema = import_zod.z.object({
76
76
  description: import_zod.z.string().optional(),
77
77
  guidance: import_zod.z.string().optional()
78
78
  }),
79
+ security: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string()))).optional(),
79
80
  servers: import_zod.z.array(import_zod.z.object({ url: import_zod.z.string() })).optional(),
80
81
  tags: import_zod.z.array(import_zod.z.object({ name: import_zod.z.string() })).optional(),
81
82
  components: import_zod.z.object({ securitySchemes: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional() }).optional(),
@@ -300,6 +300,7 @@ declare const OpenApiDocSchema: z.ZodObject<{
300
300
  description: z.ZodOptional<z.ZodString>;
301
301
  guidance: z.ZodOptional<z.ZodString>;
302
302
  }, z.core.$strip>;
303
+ security: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>>;
303
304
  servers: z.ZodOptional<z.ZodArray<z.ZodObject<{
304
305
  url: z.ZodString;
305
306
  }, z.core.$strip>>>;
package/dist/schemas.d.ts CHANGED
@@ -300,6 +300,7 @@ declare const OpenApiDocSchema: z.ZodObject<{
300
300
  description: z.ZodOptional<z.ZodString>;
301
301
  guidance: z.ZodOptional<z.ZodString>;
302
302
  }, z.core.$strip>;
303
+ security: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>>;
303
304
  servers: z.ZodOptional<z.ZodArray<z.ZodObject<{
304
305
  url: z.ZodString;
305
306
  }, z.core.$strip>>>;
package/dist/schemas.js CHANGED
@@ -47,6 +47,7 @@ var OpenApiDocSchema = z.object({
47
47
  description: z.string().optional(),
48
48
  guidance: z.string().optional()
49
49
  }),
50
+ security: z.array(z.record(z.string(), z.array(z.string()))).optional(),
50
51
  servers: z.array(z.object({ url: z.string() })).optional(),
51
52
  tags: z.array(z.object({ name: z.string() })).optional(),
52
53
  components: z.object({ securitySchemes: z.record(z.string(), z.unknown()).optional() }).optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/discovery",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Canonical OpenAPI-first discovery runtime for the agentcash ecosystem",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",