milieu-cli 0.1.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.
Files changed (159) hide show
  1. package/LICENSE +200 -0
  2. package/README.md +153 -0
  3. package/dist/bridges/index.d.ts +5 -0
  4. package/dist/bridges/index.d.ts.map +1 -0
  5. package/dist/bridges/index.js +6 -0
  6. package/dist/bridges/index.js.map +1 -0
  7. package/dist/bridges/reachability/crawler-policy.d.ts +36 -0
  8. package/dist/bridges/reachability/crawler-policy.d.ts.map +1 -0
  9. package/dist/bridges/reachability/crawler-policy.js +110 -0
  10. package/dist/bridges/reachability/crawler-policy.js.map +1 -0
  11. package/dist/bridges/reachability/http-status.d.ts +7 -0
  12. package/dist/bridges/reachability/http-status.d.ts.map +1 -0
  13. package/dist/bridges/reachability/http-status.js +74 -0
  14. package/dist/bridges/reachability/http-status.js.map +1 -0
  15. package/dist/bridges/reachability/https-check.d.ts +14 -0
  16. package/dist/bridges/reachability/https-check.d.ts.map +1 -0
  17. package/dist/bridges/reachability/https-check.js +38 -0
  18. package/dist/bridges/reachability/https-check.js.map +1 -0
  19. package/dist/bridges/reachability/index.d.ts +13 -0
  20. package/dist/bridges/reachability/index.d.ts.map +1 -0
  21. package/dist/bridges/reachability/index.js +115 -0
  22. package/dist/bridges/reachability/index.js.map +1 -0
  23. package/dist/bridges/reachability/meta-robots.d.ts +16 -0
  24. package/dist/bridges/reachability/meta-robots.d.ts.map +1 -0
  25. package/dist/bridges/reachability/meta-robots.js +119 -0
  26. package/dist/bridges/reachability/meta-robots.js.map +1 -0
  27. package/dist/bridges/reachability/robots-parser.d.ts +26 -0
  28. package/dist/bridges/reachability/robots-parser.d.ts.map +1 -0
  29. package/dist/bridges/reachability/robots-parser.js +105 -0
  30. package/dist/bridges/reachability/robots-parser.js.map +1 -0
  31. package/dist/bridges/reachability/robots-txt.d.ts +14 -0
  32. package/dist/bridges/reachability/robots-txt.d.ts.map +1 -0
  33. package/dist/bridges/reachability/robots-txt.js +80 -0
  34. package/dist/bridges/reachability/robots-txt.js.map +1 -0
  35. package/dist/bridges/separation/api-presence.d.ts +14 -0
  36. package/dist/bridges/separation/api-presence.d.ts.map +1 -0
  37. package/dist/bridges/separation/api-presence.js +96 -0
  38. package/dist/bridges/separation/api-presence.js.map +1 -0
  39. package/dist/bridges/separation/developer-docs.d.ts +21 -0
  40. package/dist/bridges/separation/developer-docs.d.ts.map +1 -0
  41. package/dist/bridges/separation/developer-docs.js +81 -0
  42. package/dist/bridges/separation/developer-docs.js.map +1 -0
  43. package/dist/bridges/separation/index.d.ts +20 -0
  44. package/dist/bridges/separation/index.d.ts.map +1 -0
  45. package/dist/bridges/separation/index.js +63 -0
  46. package/dist/bridges/separation/index.js.map +1 -0
  47. package/dist/bridges/separation/sdk-references.d.ts +12 -0
  48. package/dist/bridges/separation/sdk-references.d.ts.map +1 -0
  49. package/dist/bridges/separation/sdk-references.js +93 -0
  50. package/dist/bridges/separation/sdk-references.js.map +1 -0
  51. package/dist/bridges/separation/webhook-support.d.ts +19 -0
  52. package/dist/bridges/separation/webhook-support.d.ts.map +1 -0
  53. package/dist/bridges/separation/webhook-support.js +94 -0
  54. package/dist/bridges/separation/webhook-support.js.map +1 -0
  55. package/dist/bridges/standards/index.d.ts +13 -0
  56. package/dist/bridges/standards/index.d.ts.map +1 -0
  57. package/dist/bridges/standards/index.js +79 -0
  58. package/dist/bridges/standards/index.js.map +1 -0
  59. package/dist/bridges/standards/json-ld.d.ts +16 -0
  60. package/dist/bridges/standards/json-ld.d.ts.map +1 -0
  61. package/dist/bridges/standards/json-ld.js +63 -0
  62. package/dist/bridges/standards/json-ld.js.map +1 -0
  63. package/dist/bridges/standards/llms-txt.d.ts +19 -0
  64. package/dist/bridges/standards/llms-txt.d.ts.map +1 -0
  65. package/dist/bridges/standards/llms-txt.js +64 -0
  66. package/dist/bridges/standards/llms-txt.js.map +1 -0
  67. package/dist/bridges/standards/mcp.d.ts +13 -0
  68. package/dist/bridges/standards/mcp.d.ts.map +1 -0
  69. package/dist/bridges/standards/mcp.js +72 -0
  70. package/dist/bridges/standards/mcp.js.map +1 -0
  71. package/dist/bridges/standards/openapi.d.ts +14 -0
  72. package/dist/bridges/standards/openapi.d.ts.map +1 -0
  73. package/dist/bridges/standards/openapi.js +424 -0
  74. package/dist/bridges/standards/openapi.js.map +1 -0
  75. package/dist/bridges/standards/schema-org.d.ts +12 -0
  76. package/dist/bridges/standards/schema-org.d.ts.map +1 -0
  77. package/dist/bridges/standards/schema-org.js +101 -0
  78. package/dist/bridges/standards/schema-org.js.map +1 -0
  79. package/dist/bridges/standards/well-known.d.ts +16 -0
  80. package/dist/bridges/standards/well-known.d.ts.map +1 -0
  81. package/dist/bridges/standards/well-known.js +77 -0
  82. package/dist/bridges/standards/well-known.js.map +1 -0
  83. package/dist/bridges/stubs.d.ts +4 -0
  84. package/dist/bridges/stubs.d.ts.map +1 -0
  85. package/dist/bridges/stubs.js +25 -0
  86. package/dist/bridges/stubs.js.map +1 -0
  87. package/dist/cli/index.d.ts +4 -0
  88. package/dist/cli/index.d.ts.map +1 -0
  89. package/dist/cli/index.js +83 -0
  90. package/dist/cli/index.js.map +1 -0
  91. package/dist/core/explanations.d.ts +11 -0
  92. package/dist/core/explanations.d.ts.map +1 -0
  93. package/dist/core/explanations.js +128 -0
  94. package/dist/core/explanations.js.map +1 -0
  95. package/dist/core/index.d.ts +6 -0
  96. package/dist/core/index.d.ts.map +1 -0
  97. package/dist/core/index.js +6 -0
  98. package/dist/core/index.js.map +1 -0
  99. package/dist/core/scan.d.ts +3 -0
  100. package/dist/core/scan.d.ts.map +1 -0
  101. package/dist/core/scan.js +89 -0
  102. package/dist/core/scan.js.map +1 -0
  103. package/dist/core/types.d.ts +119 -0
  104. package/dist/core/types.d.ts.map +1 -0
  105. package/dist/core/types.js +3 -0
  106. package/dist/core/types.js.map +1 -0
  107. package/dist/core/version.d.ts +2 -0
  108. package/dist/core/version.d.ts.map +1 -0
  109. package/dist/core/version.js +7 -0
  110. package/dist/core/version.js.map +1 -0
  111. package/dist/index.d.ts +2 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +4 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/render/colors.d.ts +7 -0
  116. package/dist/render/colors.d.ts.map +1 -0
  117. package/dist/render/colors.js +28 -0
  118. package/dist/render/colors.js.map +1 -0
  119. package/dist/render/format-bridge.d.ts +3 -0
  120. package/dist/render/format-bridge.d.ts.map +1 -0
  121. package/dist/render/format-bridge.js +39 -0
  122. package/dist/render/format-bridge.js.map +1 -0
  123. package/dist/render/format-scan.d.ts +3 -0
  124. package/dist/render/format-scan.d.ts.map +1 -0
  125. package/dist/render/format-scan.js +44 -0
  126. package/dist/render/format-scan.js.map +1 -0
  127. package/dist/render/format-verbose.d.ts +3 -0
  128. package/dist/render/format-verbose.d.ts.map +1 -0
  129. package/dist/render/format-verbose.js +14 -0
  130. package/dist/render/format-verbose.js.map +1 -0
  131. package/dist/render/index.d.ts +7 -0
  132. package/dist/render/index.d.ts.map +1 -0
  133. package/dist/render/index.js +8 -0
  134. package/dist/render/index.js.map +1 -0
  135. package/dist/render/progress-bar.d.ts +10 -0
  136. package/dist/render/progress-bar.d.ts.map +1 -0
  137. package/dist/render/progress-bar.js +21 -0
  138. package/dist/render/progress-bar.js.map +1 -0
  139. package/dist/render/symbols.d.ts +10 -0
  140. package/dist/render/symbols.d.ts.map +1 -0
  141. package/dist/render/symbols.js +21 -0
  142. package/dist/render/symbols.js.map +1 -0
  143. package/dist/utils/http-client.d.ts +25 -0
  144. package/dist/utils/http-client.d.ts.map +1 -0
  145. package/dist/utils/http-client.js +235 -0
  146. package/dist/utils/http-client.js.map +1 -0
  147. package/dist/utils/index.d.ts +6 -0
  148. package/dist/utils/index.d.ts.map +1 -0
  149. package/dist/utils/index.js +7 -0
  150. package/dist/utils/index.js.map +1 -0
  151. package/dist/utils/ssrf.d.ts +29 -0
  152. package/dist/utils/ssrf.d.ts.map +1 -0
  153. package/dist/utils/ssrf.js +134 -0
  154. package/dist/utils/ssrf.js.map +1 -0
  155. package/dist/utils/url.d.ts +53 -0
  156. package/dist/utils/url.d.ts.map +1 -0
  157. package/dist/utils/url.js +64 -0
  158. package/dist/utils/url.js.map +1 -0
  159. package/package.json +74 -0
@@ -0,0 +1,424 @@
1
+ import { httpGet } from "../../utils/http-client.js";
2
+ // ---------------------------------------------------------------------------
3
+ // Constants
4
+ // ---------------------------------------------------------------------------
5
+ /** Spec paths -- expect raw JSON/YAML */
6
+ const SPEC_PATHS = [
7
+ "/openapi.json",
8
+ "/swagger.json",
9
+ "/api-docs",
10
+ "/v3/api-docs",
11
+ "/v2/api-docs",
12
+ "/swagger/v1/swagger.json",
13
+ "/api/openapi.json",
14
+ "/api/swagger.json",
15
+ "/.well-known/openapi.json",
16
+ "/openapi.yaml",
17
+ "/api/v1/openapi.json",
18
+ "/api/v1/swagger.json",
19
+ "/v3/api-docs.yaml",
20
+ "/v2/swagger.json",
21
+ "/api/v2/openapi.json",
22
+ "/api/v3/openapi.json",
23
+ "/spec.json",
24
+ ];
25
+ /** Doc UI paths -- expect HTML with embedded spec URL */
26
+ const DOC_UI_PATHS = [
27
+ "/",
28
+ "/swagger-ui.html",
29
+ "/swagger-ui/",
30
+ "/docs",
31
+ "/redoc",
32
+ "/api/docs",
33
+ "/documentation",
34
+ ];
35
+ /** All paths combined */
36
+ const ALL_PATHS = [...SPEC_PATHS, ...DOC_UI_PATHS];
37
+ const HTML_TYPES = new Set(["text/html", "application/xhtml+xml"]);
38
+ const JSON_TYPES = new Set([
39
+ "application/json",
40
+ "application/vnd.oai.openapi+json",
41
+ ]);
42
+ const YAML_TYPES = new Set([
43
+ "application/yaml",
44
+ "text/yaml",
45
+ "application/x-yaml",
46
+ "application/vnd.oai.openapi",
47
+ ]);
48
+ // ---------------------------------------------------------------------------
49
+ // Helpers
50
+ // ---------------------------------------------------------------------------
51
+ /** Extract the media type portion of a Content-Type header (before ;) */
52
+ function mediaType(headers) {
53
+ return (headers["content-type"] ?? "").split(";")[0].trim().toLowerCase();
54
+ }
55
+ /**
56
+ * Validate that an HTTP response contains a genuine OpenAPI / Swagger spec.
57
+ * Returns true only when the body is confirmed to contain spec content.
58
+ */
59
+ function isOpenApiResponse(response) {
60
+ const ct = mediaType(response.headers);
61
+ // Reject HTML responses (Swagger UI pages)
62
+ if (HTML_TYPES.has(ct))
63
+ return false;
64
+ // JSON content types -- parse and check for top-level key
65
+ if (JSON_TYPES.has(ct)) {
66
+ return jsonHasSpecKey(response.body);
67
+ }
68
+ // YAML content types -- regex check
69
+ if (YAML_TYPES.has(ct)) {
70
+ return /^(openapi|swagger):/m.test(response.body);
71
+ }
72
+ // Unknown Content-Type -- try JSON.parse fallback if body looks like JSON
73
+ if (response.body.trimStart().startsWith("{")) {
74
+ return jsonHasSpecKey(response.body);
75
+ }
76
+ return false;
77
+ }
78
+ /** Parse JSON and check for top-level "openapi" or "swagger" key */
79
+ function jsonHasSpecKey(body) {
80
+ try {
81
+ const parsed = JSON.parse(body);
82
+ return "openapi" in parsed || "swagger" in parsed;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ /** Determine whether the response is JSON (parseable) or YAML */
89
+ function isJsonParseable(body) {
90
+ try {
91
+ JSON.parse(body);
92
+ return true;
93
+ }
94
+ catch {
95
+ return false;
96
+ }
97
+ }
98
+ /** Extract version, spec type, and endpoint count from a JSON body */
99
+ function extractJsonInfo(body) {
100
+ try {
101
+ const parsed = JSON.parse(body);
102
+ const specType = "openapi" in parsed
103
+ ? "openapi"
104
+ : "swagger" in parsed
105
+ ? "swagger"
106
+ : null;
107
+ if (!specType)
108
+ return null;
109
+ const version = String(parsed[specType]);
110
+ const endpointCount = parsed.paths
111
+ ? Object.keys(parsed.paths).length
112
+ : 0;
113
+ return { version, specType, endpointCount };
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ }
119
+ /** Extract version, spec type, and endpoint count from YAML via regex */
120
+ function extractYamlInfo(body) {
121
+ const versionMatch = body.match(/^(openapi|swagger):\s*["']?(\d+\.\d+(?:\.\d+)?)/m);
122
+ if (!versionMatch)
123
+ return null;
124
+ // Count paths in YAML (lines that start with / at indent level 2)
125
+ const pathMatches = body.match(/^ {2}\/\S+:/gm);
126
+ return {
127
+ version: versionMatch[2],
128
+ specType: versionMatch[1],
129
+ endpointCount: pathMatches?.length ?? 0,
130
+ };
131
+ }
132
+ /** Patterns that extract spec URLs from HTML or JS content */
133
+ const SPEC_URL_PATTERNS = [
134
+ // 1. Swagger UI initializer: SwaggerUIBundle({ url: "/openapi.json" })
135
+ /SwaggerUI(?:Bundle|Standalone)?\s*\(\s*\{[^}]*url\s*:\s*["']([^"']+)["']/g,
136
+ // 2. Swagger UI configUrl: SwaggerUIBundle({ configUrl: "/swagger-config" })
137
+ /SwaggerUI(?:Bundle|Standalone)?\s*\(\s*\{[^}]*configUrl\s*:\s*["']([^"']+)["']/g,
138
+ // 3. Swagger UI swaggerUrl (older): swaggerUrl: "/api/swagger.json"
139
+ /swaggerUrl\s*:\s*["']([^"']+)["']/g,
140
+ // 4. ReDoc spec-url attribute: <redoc spec-url="/api/openapi.json">
141
+ /(?:spec-url|data-spec-url)\s*=\s*["']([^"']+)["']/g,
142
+ // 5. Generic spec path (relative): "/some-path/openapi.json"
143
+ /["'](\/[^"']*(?:openapi|swagger)\.(?:json|yaml))["']/g,
144
+ // 6. Generic spec URL (absolute): "https://host/path/openapi.json"
145
+ /["'](https?:\/\/[^"']*(?:openapi|swagger)\.(?:json|yaml))["']/g,
146
+ // 7. fetch() call to JSON/YAML (Flasgger pattern): fetch("/spec.json")
147
+ /fetch\(\s*["']([^"']+\.(?:json|yaml))["']\s*\)/g,
148
+ // 8. Unquoted spec URLs in JS (template literals, config strings)
149
+ /(https?:\/\/[^\s,`"'<>]+(?:openapi|swagger)\.(?:json|yaml))/g,
150
+ ];
151
+ /**
152
+ * Extract spec URLs from text content (HTML or JS).
153
+ * Returns deduplicated, same-origin, absolute URLs.
154
+ */
155
+ function extractSpecUrls(body, pageUrl) {
156
+ const origin = new URL(pageUrl).origin;
157
+ const seen = new Set();
158
+ const results = [];
159
+ for (const pattern of SPEC_URL_PATTERNS) {
160
+ pattern.lastIndex = 0;
161
+ let match;
162
+ while ((match = pattern.exec(body)) !== null) {
163
+ const raw = match[1];
164
+ if (!raw)
165
+ continue;
166
+ let absolute;
167
+ try {
168
+ absolute = new URL(raw, pageUrl).href;
169
+ }
170
+ catch {
171
+ continue;
172
+ }
173
+ try {
174
+ if (new URL(absolute).origin !== origin)
175
+ continue;
176
+ }
177
+ catch {
178
+ continue;
179
+ }
180
+ if (!seen.has(absolute)) {
181
+ seen.add(absolute);
182
+ results.push(absolute);
183
+ }
184
+ }
185
+ }
186
+ return results;
187
+ }
188
+ /**
189
+ * Extract Swagger UI config script URLs from HTML.
190
+ * Returns URLs of JS files that likely contain spec URL configuration.
191
+ */
192
+ function extractSwaggerScriptUrls(html, pageUrl) {
193
+ const origin = new URL(pageUrl).origin;
194
+ // Match <script src="...swagger...js"> or <script src="...swagger...js">
195
+ const pattern = /<script[^>]+src=["']([^"']*swagger[^"']*\.js)["']/gi;
196
+ const results = [];
197
+ let match;
198
+ while ((match = pattern.exec(html)) !== null) {
199
+ const raw = match[1];
200
+ if (!raw)
201
+ continue;
202
+ try {
203
+ const absolute = new URL(raw, pageUrl).href;
204
+ if (new URL(absolute).origin !== origin)
205
+ continue;
206
+ results.push(absolute);
207
+ }
208
+ catch {
209
+ continue;
210
+ }
211
+ }
212
+ return results;
213
+ }
214
+ /** Returns true if response is a 401/403 HTTP error (not bot-protected) */
215
+ function isProtectedResponse(response) {
216
+ if (response.ok)
217
+ return false;
218
+ const { error } = response;
219
+ return (error.kind === "http_error" &&
220
+ error.statusCode !== undefined &&
221
+ (error.statusCode === 401 || error.statusCode === 403));
222
+ }
223
+ // ---------------------------------------------------------------------------
224
+ // Public API
225
+ // ---------------------------------------------------------------------------
226
+ /**
227
+ * Probe 19 common OpenAPI / Swagger spec paths in parallel, then try
228
+ * extracting spec URLs from HTML doc pages, and finally detect protected specs.
229
+ *
230
+ * Returns a Check with id "openapi_spec" and a boolean indicating whether
231
+ * any valid spec was detected (for ctx.shared.openApiDetected).
232
+ */
233
+ export async function checkOpenApi(baseUrl, timeout) {
234
+ const id = "openapi_spec";
235
+ const label = "OpenAPI Spec";
236
+ // Phase 1: Fire all 19 probes in parallel
237
+ const responses = await Promise.all([
238
+ ...SPEC_PATHS.map((path) => httpGet(new URL(path, baseUrl).href, {
239
+ timeout,
240
+ headers: { Accept: "application/json, application/yaml, */*" },
241
+ })),
242
+ ...DOC_UI_PATHS.map((path) => httpGet(new URL(path, baseUrl).href, {
243
+ timeout,
244
+ headers: { Accept: "text/html, */*" },
245
+ })),
246
+ ]);
247
+ const specPathResponses = responses.slice(0, SPEC_PATHS.length);
248
+ const docUiResponses = responses.slice(SPEC_PATHS.length);
249
+ // Phase 2: Check spec-path responses for direct spec hits
250
+ for (let i = 0; i < specPathResponses.length; i++) {
251
+ const response = specPathResponses[i];
252
+ if (!response.ok)
253
+ continue;
254
+ if (!isOpenApiResponse(response))
255
+ continue;
256
+ const path = SPEC_PATHS[i];
257
+ if (isJsonParseable(response.body)) {
258
+ const info = extractJsonInfo(response.body);
259
+ if (info) {
260
+ return {
261
+ check: {
262
+ id,
263
+ label,
264
+ status: "pass",
265
+ detail: `OpenAPI ${info.version} found with ${info.endpointCount} endpoints`,
266
+ data: {
267
+ version: info.version,
268
+ specType: info.specType,
269
+ endpointCount: info.endpointCount,
270
+ path,
271
+ },
272
+ },
273
+ detected: true,
274
+ };
275
+ }
276
+ }
277
+ const yamlInfo = extractYamlInfo(response.body);
278
+ if (yamlInfo) {
279
+ return {
280
+ check: {
281
+ id,
282
+ label,
283
+ status: "partial",
284
+ detail: `OpenAPI ${yamlInfo.version} found (YAML format)`,
285
+ data: {
286
+ version: yamlInfo.version,
287
+ specType: yamlInfo.specType,
288
+ endpointCount: yamlInfo.endpointCount,
289
+ path,
290
+ },
291
+ },
292
+ detected: true,
293
+ };
294
+ }
295
+ }
296
+ // Phase 3: Check doc-UI-path responses for HTML with extractable spec URLs
297
+ const allProbedUrls = new Set(ALL_PATHS.map((p) => new URL(p, baseUrl).href));
298
+ const specCandidateUrls = [];
299
+ const scriptUrls = [];
300
+ for (let i = 0; i < docUiResponses.length; i++) {
301
+ const response = docUiResponses[i];
302
+ if (!response.ok)
303
+ continue;
304
+ const ct = mediaType(response.headers);
305
+ if (!HTML_TYPES.has(ct))
306
+ continue;
307
+ const pageUrl = new URL(DOC_UI_PATHS[i], baseUrl).href;
308
+ // Extract spec URLs directly from HTML
309
+ const extracted = extractSpecUrls(response.body, pageUrl);
310
+ for (const url of extracted) {
311
+ if (!allProbedUrls.has(url) && !specCandidateUrls.includes(url)) {
312
+ specCandidateUrls.push(url);
313
+ }
314
+ }
315
+ // Extract Swagger UI config script URLs for secondary fetching
316
+ if (specCandidateUrls.length === 0) {
317
+ const scripts = extractSwaggerScriptUrls(response.body, pageUrl);
318
+ for (const url of scripts) {
319
+ if (!scriptUrls.includes(url)) {
320
+ scriptUrls.push(url);
321
+ }
322
+ }
323
+ }
324
+ }
325
+ // Phase 3a: Fetch external Swagger UI config scripts and extract spec URLs from them
326
+ if (specCandidateUrls.length === 0 && scriptUrls.length > 0) {
327
+ const scriptResponses = await Promise.all(scriptUrls.slice(0, 3).map((url) => httpGet(url, {
328
+ timeout,
329
+ headers: { Accept: "*/*" },
330
+ })));
331
+ for (let i = 0; i < scriptResponses.length; i++) {
332
+ const response = scriptResponses[i];
333
+ if (!response.ok)
334
+ continue;
335
+ const scriptUrl = scriptUrls[i];
336
+ const extracted = extractSpecUrls(response.body, scriptUrl);
337
+ for (const url of extracted) {
338
+ if (!allProbedUrls.has(url) && !specCandidateUrls.includes(url)) {
339
+ specCandidateUrls.push(url);
340
+ }
341
+ }
342
+ }
343
+ }
344
+ // Phase 3b: Fetch candidate spec URLs and validate
345
+ if (specCandidateUrls.length > 0) {
346
+ const secondaryResponses = await Promise.all(specCandidateUrls.slice(0, 3).map((url) => httpGet(url, {
347
+ timeout,
348
+ headers: { Accept: "application/json, application/yaml, */*" },
349
+ })));
350
+ for (let i = 0; i < secondaryResponses.length; i++) {
351
+ const response = secondaryResponses[i];
352
+ if (!response.ok)
353
+ continue;
354
+ if (!isOpenApiResponse(response))
355
+ continue;
356
+ const path = new URL(specCandidateUrls[i]).pathname;
357
+ if (isJsonParseable(response.body)) {
358
+ const info = extractJsonInfo(response.body);
359
+ if (info) {
360
+ return {
361
+ check: {
362
+ id,
363
+ label,
364
+ status: "pass",
365
+ detail: `OpenAPI ${info.version} found with ${info.endpointCount} endpoints`,
366
+ data: {
367
+ version: info.version,
368
+ specType: info.specType,
369
+ endpointCount: info.endpointCount,
370
+ path,
371
+ },
372
+ },
373
+ detected: true,
374
+ };
375
+ }
376
+ }
377
+ const yamlInfo = extractYamlInfo(response.body);
378
+ if (yamlInfo) {
379
+ return {
380
+ check: {
381
+ id,
382
+ label,
383
+ status: "partial",
384
+ detail: `OpenAPI ${yamlInfo.version} found (YAML format)`,
385
+ data: {
386
+ version: yamlInfo.version,
387
+ specType: yamlInfo.specType,
388
+ endpointCount: yamlInfo.endpointCount,
389
+ path,
390
+ },
391
+ },
392
+ detected: true,
393
+ };
394
+ }
395
+ }
396
+ }
397
+ // Phase 4: Check spec-path responses for 401/403 (not bot_protected)
398
+ for (let i = 0; i < specPathResponses.length; i++) {
399
+ const response = specPathResponses[i];
400
+ if (isProtectedResponse(response)) {
401
+ return {
402
+ check: {
403
+ id,
404
+ label,
405
+ status: "partial",
406
+ detail: "OpenAPI spec appears to exist but requires authentication",
407
+ data: { protected: true, path: SPEC_PATHS[i] },
408
+ },
409
+ detected: true,
410
+ };
411
+ }
412
+ }
413
+ // Phase 5: No valid spec found at any path
414
+ return {
415
+ check: {
416
+ id,
417
+ label,
418
+ status: "fail",
419
+ detail: "No OpenAPI spec found",
420
+ },
421
+ detected: false,
422
+ };
423
+ }
424
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../../src/bridges/standards/openapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Check } from "../../core/types.js";
2
+ /**
3
+ * Check for Schema.org markup via JSON-LD vocabulary and Microdata attributes.
4
+ *
5
+ * Takes the JSON-LD Check result (from checkJsonLd) to avoid re-parsing HTML
6
+ * for JSON-LD blocks. Also scans raw HTML for Microdata itemtype attributes
7
+ * containing schema.org URLs.
8
+ *
9
+ * Pure function -- no HTTP calls.
10
+ */
11
+ export declare function checkSchemaOrg(html: string, jsonLdCheck: Check): Check;
12
+ //# sourceMappingURL=schema-org.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-org.d.ts","sourceRoot":"","sources":["../../../src/bridges/standards/schema-org.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,KAAK,GACjB,KAAK,CAmFP"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Check for Schema.org markup via JSON-LD vocabulary and Microdata attributes.
3
+ *
4
+ * Takes the JSON-LD Check result (from checkJsonLd) to avoid re-parsing HTML
5
+ * for JSON-LD blocks. Also scans raw HTML for Microdata itemtype attributes
6
+ * containing schema.org URLs.
7
+ *
8
+ * Pure function -- no HTTP calls.
9
+ */
10
+ export function checkSchemaOrg(html, jsonLdCheck) {
11
+ const id = "schema_org";
12
+ const label = "Schema.org Markup";
13
+ const types = [];
14
+ const sources = [];
15
+ // Check JSON-LD blocks for schema.org @context
16
+ if (jsonLdCheck.status === "pass" &&
17
+ jsonLdCheck.data &&
18
+ Array.isArray(jsonLdCheck.data.blocks)) {
19
+ const blocks = jsonLdCheck.data.blocks;
20
+ let foundSchemaOrg = false;
21
+ for (const block of blocks) {
22
+ if (isSchemaOrgContext(block.context)) {
23
+ foundSchemaOrg = true;
24
+ const typeNames = flattenType(block.type);
25
+ for (const t of typeNames) {
26
+ if (!types.includes(t)) {
27
+ types.push(t);
28
+ }
29
+ }
30
+ }
31
+ }
32
+ if (foundSchemaOrg) {
33
+ sources.push("json-ld");
34
+ }
35
+ }
36
+ // Check Microdata itemtype attributes for schema.org
37
+ const microdataRegex = /itemtype=["'](https?:\/\/schema\.org\/[^"']+)["']/gi;
38
+ let match;
39
+ const microdataTypes = [];
40
+ while ((match = microdataRegex.exec(html)) !== null) {
41
+ const typeUrl = match[1];
42
+ const typeName = typeUrl.split("/").pop();
43
+ if (typeName && !microdataTypes.includes(typeName)) {
44
+ microdataTypes.push(typeName);
45
+ }
46
+ }
47
+ if (microdataTypes.length > 0) {
48
+ sources.push("microdata");
49
+ for (const t of microdataTypes) {
50
+ if (!types.includes(t)) {
51
+ types.push(t);
52
+ }
53
+ }
54
+ }
55
+ if (types.length === 0) {
56
+ return {
57
+ id,
58
+ label,
59
+ status: "fail",
60
+ detail: "No Schema.org markup found",
61
+ };
62
+ }
63
+ // Build detail string based on sources
64
+ const typesStr = types.join(", ");
65
+ let detail;
66
+ if (sources.includes("json-ld") && sources.includes("microdata")) {
67
+ detail = `Schema.org types found via JSON-LD and Microdata: ${typesStr}`;
68
+ }
69
+ else if (sources.includes("json-ld")) {
70
+ detail = `Schema.org types found via JSON-LD: ${typesStr}`;
71
+ }
72
+ else {
73
+ detail = `Schema.org types found via Microdata: ${typesStr}`;
74
+ }
75
+ return {
76
+ id,
77
+ label,
78
+ status: "pass",
79
+ detail,
80
+ data: { types, sources },
81
+ };
82
+ }
83
+ /**
84
+ * Check if a JSON-LD @context value references schema.org.
85
+ */
86
+ function isSchemaOrgContext(context) {
87
+ if (typeof context === "string") {
88
+ return context.includes("schema.org");
89
+ }
90
+ if (Array.isArray(context)) {
91
+ return context.some((item) => typeof item === "string" && item.includes("schema.org"));
92
+ }
93
+ return false;
94
+ }
95
+ /**
96
+ * Flatten a @type value to an array of type name strings.
97
+ */
98
+ function flattenType(type) {
99
+ return Array.isArray(type) ? type : [type];
100
+ }
101
+ //# sourceMappingURL=schema-org.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-org.js","sourceRoot":"","sources":["../../../src/bridges/standards/schema-org.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Check } from "../../core/types.js";
2
+ /**
3
+ * Check for security.txt at /.well-known/security.txt.
4
+ *
5
+ * Per RFC 9116: must contain at least a Contact field.
6
+ * Returns pass if Contact present, partial if file exists but no Contact, fail if missing.
7
+ */
8
+ export declare function checkSecurityTxt(baseUrl: string, timeout?: number): Promise<Check>;
9
+ /**
10
+ * Check for ai-plugin.json at /.well-known/ai-plugin.json.
11
+ *
12
+ * Validates required fields: schema_version (string), name_for_human (string), api (object).
13
+ * Returns pass if all present, partial if JSON but missing fields, fail if missing.
14
+ */
15
+ export declare function checkAiPlugin(baseUrl: string, timeout?: number): Promise<Check>;
16
+ //# sourceMappingURL=well-known.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.d.ts","sourceRoot":"","sources":["../../../src/bridges/standards/well-known.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC,CA2BhB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC,CA4ChB"}
@@ -0,0 +1,77 @@
1
+ import { httpGet } from "../../utils/http-client.js";
2
+ /**
3
+ * Check for security.txt at /.well-known/security.txt.
4
+ *
5
+ * Per RFC 9116: must contain at least a Contact field.
6
+ * Returns pass if Contact present, partial if file exists but no Contact, fail if missing.
7
+ */
8
+ export async function checkSecurityTxt(baseUrl, timeout) {
9
+ const id = "security_txt";
10
+ const label = "security.txt";
11
+ const result = await httpGet(`${baseUrl}/.well-known/security.txt`, {
12
+ timeout,
13
+ });
14
+ if (!result.ok || result.body.trim().length === 0) {
15
+ return { id, label, status: "fail", detail: "No security.txt found" };
16
+ }
17
+ if (/^Contact:/mi.test(result.body)) {
18
+ return {
19
+ id,
20
+ label,
21
+ status: "pass",
22
+ detail: "security.txt found with Contact field",
23
+ };
24
+ }
25
+ return {
26
+ id,
27
+ label,
28
+ status: "partial",
29
+ detail: "security.txt found but missing Contact field",
30
+ };
31
+ }
32
+ /**
33
+ * Check for ai-plugin.json at /.well-known/ai-plugin.json.
34
+ *
35
+ * Validates required fields: schema_version (string), name_for_human (string), api (object).
36
+ * Returns pass if all present, partial if JSON but missing fields, fail if missing.
37
+ */
38
+ export async function checkAiPlugin(baseUrl, timeout) {
39
+ const id = "ai_plugin";
40
+ const label = "ai-plugin.json";
41
+ const result = await httpGet(`${baseUrl}/.well-known/ai-plugin.json`, {
42
+ timeout,
43
+ headers: { Accept: "application/json" },
44
+ });
45
+ if (!result.ok) {
46
+ return { id, label, status: "fail", detail: "No ai-plugin.json found" };
47
+ }
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(result.body);
51
+ }
52
+ catch {
53
+ return { id, label, status: "fail", detail: "No ai-plugin.json found" };
54
+ }
55
+ if (typeof parsed.schema_version === "string" &&
56
+ typeof parsed.name_for_human === "string" &&
57
+ typeof parsed.api === "object" &&
58
+ parsed.api !== null) {
59
+ return {
60
+ id,
61
+ label,
62
+ status: "pass",
63
+ detail: `ai-plugin.json found: ${parsed.name_for_human}`,
64
+ data: {
65
+ nameForHuman: parsed.name_for_human,
66
+ schemaVersion: parsed.schema_version,
67
+ },
68
+ };
69
+ }
70
+ return {
71
+ id,
72
+ label,
73
+ status: "partial",
74
+ detail: "ai-plugin.json found but missing required fields",
75
+ };
76
+ }
77
+ //# sourceMappingURL=well-known.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.js","sourceRoot":"","sources":["../../../src/bridges/standards/well-known.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,OAAgB;IAEhB,MAAM,EAAE,GAAG,cAAc,CAAC;IAC1B,MAAM,KAAK,GAAG,cAAc,CAAC;IAE7B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,2BAA2B,EAAE;QAClE,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IACxE,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,EAAE;YACF,KAAK;YACL,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,uCAAuC;SAChD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE;QACF,KAAK;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,8CAA8C;KACvD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,OAAgB;IAEhB,MAAM,EAAE,GAAG,WAAW,CAAC;IACvB,MAAM,KAAK,GAAG,gBAAgB,CAAC;IAE/B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,6BAA6B,EAAE;QACpE,OAAO;QACP,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC1E,CAAC;IAED,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAA4B,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC1E,CAAC;IAED,IACE,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;QACzC,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;QACzC,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;QAC9B,MAAM,CAAC,GAAG,KAAK,IAAI,EACnB,CAAC;QACD,OAAO;YACL,EAAE;YACF,KAAK;YACL,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,yBAAyB,MAAM,CAAC,cAAc,EAAE;YACxD,IAAI,EAAE;gBACJ,YAAY,EAAE,MAAM,CAAC,cAAc;gBACnC,aAAa,EAAE,MAAM,CAAC,cAAc;aACrC;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE;QACF,KAAK;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,kDAAkD;KAC3D,CAAC;AACJ,CAAC"}