@enricai/barnacle 1.0.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 (448) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +958 -0
  3. package/dist/api/errors.d.ts +88 -0
  4. package/dist/api/errors.d.ts.map +1 -0
  5. package/dist/api/errors.js +164 -0
  6. package/dist/api/errors.js.map +1 -0
  7. package/dist/api/helpers/envelope.d.ts +13 -0
  8. package/dist/api/helpers/envelope.d.ts.map +1 -0
  9. package/dist/api/helpers/envelope.js +20 -0
  10. package/dist/api/helpers/envelope.js.map +1 -0
  11. package/dist/api/helpers/reply.d.ts +9 -0
  12. package/dist/api/helpers/reply.d.ts.map +1 -0
  13. package/dist/api/helpers/reply.js +14 -0
  14. package/dist/api/helpers/reply.js.map +1 -0
  15. package/dist/api/plugins/auth.d.ts +27 -0
  16. package/dist/api/plugins/auth.d.ts.map +1 -0
  17. package/dist/api/plugins/auth.js +111 -0
  18. package/dist/api/plugins/auth.js.map +1 -0
  19. package/dist/api/plugins/error-handler.d.ts +12 -0
  20. package/dist/api/plugins/error-handler.d.ts.map +1 -0
  21. package/dist/api/plugins/error-handler.js +72 -0
  22. package/dist/api/plugins/error-handler.js.map +1 -0
  23. package/dist/api/plugins/request-context.d.ts +17 -0
  24. package/dist/api/plugins/request-context.d.ts.map +1 -0
  25. package/dist/api/plugins/request-context.js +61 -0
  26. package/dist/api/plugins/request-context.js.map +1 -0
  27. package/dist/api/routes/health.d.ts +55 -0
  28. package/dist/api/routes/health.d.ts.map +1 -0
  29. package/dist/api/routes/health.js +137 -0
  30. package/dist/api/routes/health.js.map +1 -0
  31. package/dist/api/routes/plugins-introspection.d.ts +17 -0
  32. package/dist/api/routes/plugins-introspection.d.ts.map +1 -0
  33. package/dist/api/routes/plugins-introspection.js +13 -0
  34. package/dist/api/routes/plugins-introspection.js.map +1 -0
  35. package/dist/api/schemas/common.d.ts +114 -0
  36. package/dist/api/schemas/common.d.ts.map +1 -0
  37. package/dist/api/schemas/common.js +109 -0
  38. package/dist/api/schemas/common.js.map +1 -0
  39. package/dist/api/schemas/telemetry.d.ts +66 -0
  40. package/dist/api/schemas/telemetry.d.ts.map +1 -0
  41. package/dist/api/schemas/telemetry.js +52 -0
  42. package/dist/api/schemas/telemetry.js.map +1 -0
  43. package/dist/cache/keyed-ttl-cache.d.ts +45 -0
  44. package/dist/cache/keyed-ttl-cache.d.ts.map +1 -0
  45. package/dist/cache/keyed-ttl-cache.js +69 -0
  46. package/dist/cache/keyed-ttl-cache.js.map +1 -0
  47. package/dist/cache/response-cache.d.ts +37 -0
  48. package/dist/cache/response-cache.d.ts.map +1 -0
  49. package/dist/cache/response-cache.js +114 -0
  50. package/dist/cache/response-cache.js.map +1 -0
  51. package/dist/config.d.ts +258 -0
  52. package/dist/config.d.ts.map +1 -0
  53. package/dist/config.js +138 -0
  54. package/dist/config.js.map +1 -0
  55. package/dist/lib/applicant-payload.d.ts +28 -0
  56. package/dist/lib/applicant-payload.d.ts.map +1 -0
  57. package/dist/lib/applicant-payload.js +20 -0
  58. package/dist/lib/applicant-payload.js.map +1 -0
  59. package/dist/lib/application-address.d.ts +16 -0
  60. package/dist/lib/application-address.d.ts.map +1 -0
  61. package/dist/lib/application-address.js +20 -0
  62. package/dist/lib/application-address.js.map +1 -0
  63. package/dist/lib/application-answers.d.ts +151 -0
  64. package/dist/lib/application-answers.d.ts.map +1 -0
  65. package/dist/lib/application-answers.js +95 -0
  66. package/dist/lib/application-answers.js.map +1 -0
  67. package/dist/lib/application-identity.d.ts +18 -0
  68. package/dist/lib/application-identity.d.ts.map +1 -0
  69. package/dist/lib/application-identity.js +20 -0
  70. package/dist/lib/application-identity.js.map +1 -0
  71. package/dist/lib/application-resume.d.ts +21 -0
  72. package/dist/lib/application-resume.d.ts.map +1 -0
  73. package/dist/lib/application-resume.js +23 -0
  74. package/dist/lib/application-resume.js.map +1 -0
  75. package/dist/lib/bedrock.d.ts +22 -0
  76. package/dist/lib/bedrock.d.ts.map +1 -0
  77. package/dist/lib/bedrock.js +35 -0
  78. package/dist/lib/bedrock.js.map +1 -0
  79. package/dist/lib/case-insensitive-headers.d.ts +15 -0
  80. package/dist/lib/case-insensitive-headers.d.ts.map +1 -0
  81. package/dist/lib/case-insensitive-headers.js +29 -0
  82. package/dist/lib/case-insensitive-headers.js.map +1 -0
  83. package/dist/lib/chromium-client-hints.d.ts +11 -0
  84. package/dist/lib/chromium-client-hints.d.ts.map +1 -0
  85. package/dist/lib/chromium-client-hints.js +17 -0
  86. package/dist/lib/chromium-client-hints.js.map +1 -0
  87. package/dist/lib/cookie-value.d.ts +8 -0
  88. package/dist/lib/cookie-value.d.ts.map +1 -0
  89. package/dist/lib/cookie-value.js +14 -0
  90. package/dist/lib/cookie-value.js.map +1 -0
  91. package/dist/lib/datadog.d.ts +8 -0
  92. package/dist/lib/datadog.d.ts.map +1 -0
  93. package/dist/lib/datadog.js +27 -0
  94. package/dist/lib/datadog.js.map +1 -0
  95. package/dist/lib/dd-metrics.d.ts +28 -0
  96. package/dist/lib/dd-metrics.d.ts.map +1 -0
  97. package/dist/lib/dd-metrics.js +62 -0
  98. package/dist/lib/dd-metrics.js.map +1 -0
  99. package/dist/lib/dispatch-metrics.d.ts +19 -0
  100. package/dist/lib/dispatch-metrics.d.ts.map +1 -0
  101. package/dist/lib/dispatch-metrics.js +65 -0
  102. package/dist/lib/dispatch-metrics.js.map +1 -0
  103. package/dist/lib/env.d.ts +37 -0
  104. package/dist/lib/env.d.ts.map +1 -0
  105. package/dist/lib/env.js +70 -0
  106. package/dist/lib/env.js.map +1 -0
  107. package/dist/lib/errors.d.ts +15 -0
  108. package/dist/lib/errors.d.ts.map +1 -0
  109. package/dist/lib/errors.js +20 -0
  110. package/dist/lib/errors.js.map +1 -0
  111. package/dist/lib/http.d.ts +7 -0
  112. package/dist/lib/http.d.ts.map +1 -0
  113. package/dist/lib/http.js +14 -0
  114. package/dist/lib/http.js.map +1 -0
  115. package/dist/lib/job-tracking.d.ts +17 -0
  116. package/dist/lib/job-tracking.d.ts.map +1 -0
  117. package/dist/lib/job-tracking.js +19 -0
  118. package/dist/lib/job-tracking.js.map +1 -0
  119. package/dist/lib/llm/anthropic-client.d.ts +12 -0
  120. package/dist/lib/llm/anthropic-client.d.ts.map +1 -0
  121. package/dist/lib/llm/anthropic-client.js +23 -0
  122. package/dist/lib/llm/anthropic-client.js.map +1 -0
  123. package/dist/lib/llm/judge.d.ts +57 -0
  124. package/dist/lib/llm/judge.d.ts.map +1 -0
  125. package/dist/lib/llm/judge.js +123 -0
  126. package/dist/lib/llm/judge.js.map +1 -0
  127. package/dist/lib/llm/judges/error-messages.d.ts +38 -0
  128. package/dist/lib/llm/judges/error-messages.d.ts.map +1 -0
  129. package/dist/lib/llm/judges/error-messages.js +72 -0
  130. package/dist/lib/llm/judges/error-messages.js.map +1 -0
  131. package/dist/lib/llm/judges/invalid-fields.d.ts +43 -0
  132. package/dist/lib/llm/judges/invalid-fields.d.ts.map +1 -0
  133. package/dist/lib/llm/judges/invalid-fields.js +80 -0
  134. package/dist/lib/llm/judges/invalid-fields.js.map +1 -0
  135. package/dist/lib/llm/judges/modal-priority.d.ts +41 -0
  136. package/dist/lib/llm/judges/modal-priority.d.ts.map +1 -0
  137. package/dist/lib/llm/judges/modal-priority.js +74 -0
  138. package/dist/lib/llm/judges/modal-priority.js.map +1 -0
  139. package/dist/lib/llm/judges/select-option.d.ts +49 -0
  140. package/dist/lib/llm/judges/select-option.d.ts.map +1 -0
  141. package/dist/lib/llm/judges/select-option.js +90 -0
  142. package/dist/lib/llm/judges/select-option.js.map +1 -0
  143. package/dist/lib/llm/judges/verify-submit.d.ts +68 -0
  144. package/dist/lib/llm/judges/verify-submit.d.ts.map +1 -0
  145. package/dist/lib/llm/judges/verify-submit.js +89 -0
  146. package/dist/lib/llm/judges/verify-submit.js.map +1 -0
  147. package/dist/lib/llm/schemas.d.ts +220 -0
  148. package/dist/lib/llm/schemas.d.ts.map +1 -0
  149. package/dist/lib/llm/schemas.js +239 -0
  150. package/dist/lib/llm/schemas.js.map +1 -0
  151. package/dist/lib/logging.d.ts +39 -0
  152. package/dist/lib/logging.d.ts.map +1 -0
  153. package/dist/lib/logging.js +219 -0
  154. package/dist/lib/logging.js.map +1 -0
  155. package/dist/lib/multipart.d.ts +34 -0
  156. package/dist/lib/multipart.d.ts.map +1 -0
  157. package/dist/lib/multipart.js +55 -0
  158. package/dist/lib/multipart.js.map +1 -0
  159. package/dist/lib/option-matcher.d.ts +15 -0
  160. package/dist/lib/option-matcher.d.ts.map +1 -0
  161. package/dist/lib/option-matcher.js +69 -0
  162. package/dist/lib/option-matcher.js.map +1 -0
  163. package/dist/lib/phone.d.ts +11 -0
  164. package/dist/lib/phone.d.ts.map +1 -0
  165. package/dist/lib/phone.js +17 -0
  166. package/dist/lib/phone.js.map +1 -0
  167. package/dist/lib/random.d.ts +22 -0
  168. package/dist/lib/random.d.ts.map +1 -0
  169. package/dist/lib/random.js +33 -0
  170. package/dist/lib/random.js.map +1 -0
  171. package/dist/lib/statsd.d.ts +11 -0
  172. package/dist/lib/statsd.d.ts.map +1 -0
  173. package/dist/lib/statsd.js +68 -0
  174. package/dist/lib/statsd.js.map +1 -0
  175. package/dist/lib/telemetry/call-capture.d.ts +89 -0
  176. package/dist/lib/telemetry/call-capture.d.ts.map +1 -0
  177. package/dist/lib/telemetry/call-capture.js +190 -0
  178. package/dist/lib/telemetry/call-capture.js.map +1 -0
  179. package/dist/lib/telemetry/call-types.d.ts +65 -0
  180. package/dist/lib/telemetry/call-types.d.ts.map +1 -0
  181. package/dist/lib/telemetry/call-types.js +68 -0
  182. package/dist/lib/telemetry/call-types.js.map +1 -0
  183. package/dist/lib/telemetry/run-state.d.ts +15 -0
  184. package/dist/lib/telemetry/run-state.d.ts.map +1 -0
  185. package/dist/lib/telemetry/run-state.js +23 -0
  186. package/dist/lib/telemetry/run-state.js.map +1 -0
  187. package/dist/lib/telemetry/s3-sink.d.ts +48 -0
  188. package/dist/lib/telemetry/s3-sink.d.ts.map +1 -0
  189. package/dist/lib/telemetry/s3-sink.js +229 -0
  190. package/dist/lib/telemetry/s3-sink.js.map +1 -0
  191. package/dist/lib/telemetry/submission-capture.d.ts +45 -0
  192. package/dist/lib/telemetry/submission-capture.d.ts.map +1 -0
  193. package/dist/lib/telemetry/submission-capture.js +57 -0
  194. package/dist/lib/telemetry/submission-capture.js.map +1 -0
  195. package/dist/lib/telemetry/telemetry-paths.d.ts +59 -0
  196. package/dist/lib/telemetry/telemetry-paths.d.ts.map +1 -0
  197. package/dist/lib/telemetry/telemetry-paths.js +103 -0
  198. package/dist/lib/telemetry/telemetry-paths.js.map +1 -0
  199. package/dist/lib/tracking-click.d.ts +20 -0
  200. package/dist/lib/tracking-click.d.ts.map +1 -0
  201. package/dist/lib/tracking-click.js +75 -0
  202. package/dist/lib/tracking-click.js.map +1 -0
  203. package/dist/lib/url-capture.d.ts +8 -0
  204. package/dist/lib/url-capture.d.ts.map +1 -0
  205. package/dist/lib/url-capture.js +17 -0
  206. package/dist/lib/url-capture.js.map +1 -0
  207. package/dist/lib/us-states.d.ts +20 -0
  208. package/dist/lib/us-states.d.ts.map +1 -0
  209. package/dist/lib/us-states.js +86 -0
  210. package/dist/lib/us-states.js.map +1 -0
  211. package/dist/lib/zod-multipart.d.ts +18 -0
  212. package/dist/lib/zod-multipart.d.ts.map +1 -0
  213. package/dist/lib/zod-multipart.js +35 -0
  214. package/dist/lib/zod-multipart.js.map +1 -0
  215. package/dist/plugins/config-plugin.d.ts +77 -0
  216. package/dist/plugins/config-plugin.d.ts.map +1 -0
  217. package/dist/plugins/config-plugin.js +216 -0
  218. package/dist/plugins/config-plugin.js.map +1 -0
  219. package/dist/plugins/discover.d.ts +72 -0
  220. package/dist/plugins/discover.d.ts.map +1 -0
  221. package/dist/plugins/discover.js +265 -0
  222. package/dist/plugins/discover.js.map +1 -0
  223. package/dist/plugins/json-schema-to-zod.d.ts +47 -0
  224. package/dist/plugins/json-schema-to-zod.d.ts.map +1 -0
  225. package/dist/plugins/json-schema-to-zod.js +85 -0
  226. package/dist/plugins/json-schema-to-zod.js.map +1 -0
  227. package/dist/plugins/loader.d.ts +34 -0
  228. package/dist/plugins/loader.d.ts.map +1 -0
  229. package/dist/plugins/loader.js +348 -0
  230. package/dist/plugins/loader.js.map +1 -0
  231. package/dist/plugins/plugin-api-version.d.ts +8 -0
  232. package/dist/plugins/plugin-api-version.d.ts.map +1 -0
  233. package/dist/plugins/plugin-api-version.js +11 -0
  234. package/dist/plugins/plugin-api-version.js.map +1 -0
  235. package/dist/plugins/plugin-manifest-envelope.d.ts +16 -0
  236. package/dist/plugins/plugin-manifest-envelope.d.ts.map +1 -0
  237. package/dist/plugins/plugin-manifest-envelope.js +19 -0
  238. package/dist/plugins/plugin-manifest-envelope.js.map +1 -0
  239. package/dist/scraper/behavioral-signals.d.ts +16 -0
  240. package/dist/scraper/behavioral-signals.d.ts.map +1 -0
  241. package/dist/scraper/behavioral-signals.js +30 -0
  242. package/dist/scraper/behavioral-signals.js.map +1 -0
  243. package/dist/scraper/errors.d.ts +193 -0
  244. package/dist/scraper/errors.d.ts.map +1 -0
  245. package/dist/scraper/errors.js +226 -0
  246. package/dist/scraper/errors.js.map +1 -0
  247. package/dist/scraper/fixtures.d.ts +23 -0
  248. package/dist/scraper/fixtures.d.ts.map +1 -0
  249. package/dist/scraper/fixtures.js +48 -0
  250. package/dist/scraper/fixtures.js.map +1 -0
  251. package/dist/scraper/flow-runner.d.ts +1319 -0
  252. package/dist/scraper/flow-runner.d.ts.map +1 -0
  253. package/dist/scraper/flow-runner.js +5637 -0
  254. package/dist/scraper/flow-runner.js.map +1 -0
  255. package/dist/scraper/graphql-client.d.ts +30 -0
  256. package/dist/scraper/graphql-client.d.ts.map +1 -0
  257. package/dist/scraper/graphql-client.js +14 -0
  258. package/dist/scraper/graphql-client.js.map +1 -0
  259. package/dist/scraper/http-client.d.ts +75 -0
  260. package/dist/scraper/http-client.d.ts.map +1 -0
  261. package/dist/scraper/http-client.js +189 -0
  262. package/dist/scraper/http-client.js.map +1 -0
  263. package/dist/scraper/http-status-classifier.d.ts +12 -0
  264. package/dist/scraper/http-status-classifier.d.ts.map +1 -0
  265. package/dist/scraper/http-status-classifier.js +29 -0
  266. package/dist/scraper/http-status-classifier.js.map +1 -0
  267. package/dist/scraper/metrics.d.ts +50 -0
  268. package/dist/scraper/metrics.d.ts.map +1 -0
  269. package/dist/scraper/metrics.js +85 -0
  270. package/dist/scraper/metrics.js.map +1 -0
  271. package/dist/scraper/navigate.d.ts +20 -0
  272. package/dist/scraper/navigate.d.ts.map +1 -0
  273. package/dist/scraper/navigate.js +30 -0
  274. package/dist/scraper/navigate.js.map +1 -0
  275. package/dist/scraper/oracle-sentinels.d.ts +22 -0
  276. package/dist/scraper/oracle-sentinels.d.ts.map +1 -0
  277. package/dist/scraper/oracle-sentinels.js +40 -0
  278. package/dist/scraper/oracle-sentinels.js.map +1 -0
  279. package/dist/scraper/parse-json-response.d.ts +16 -0
  280. package/dist/scraper/parse-json-response.d.ts.map +1 -0
  281. package/dist/scraper/parse-json-response.js +37 -0
  282. package/dist/scraper/parse-json-response.js.map +1 -0
  283. package/dist/scraper/pool.d.ts +37 -0
  284. package/dist/scraper/pool.d.ts.map +1 -0
  285. package/dist/scraper/pool.js +105 -0
  286. package/dist/scraper/pool.js.map +1 -0
  287. package/dist/scraper/rate-limited-json-client.d.ts +35 -0
  288. package/dist/scraper/rate-limited-json-client.d.ts.map +1 -0
  289. package/dist/scraper/rate-limited-json-client.js +29 -0
  290. package/dist/scraper/rate-limited-json-client.js.map +1 -0
  291. package/dist/scraper/raw-fetch.d.ts +49 -0
  292. package/dist/scraper/raw-fetch.d.ts.map +1 -0
  293. package/dist/scraper/raw-fetch.js +40 -0
  294. package/dist/scraper/raw-fetch.js.map +1 -0
  295. package/dist/scraper/require-response-field.d.ts +23 -0
  296. package/dist/scraper/require-response-field.d.ts.map +1 -0
  297. package/dist/scraper/require-response-field.js +42 -0
  298. package/dist/scraper/require-response-field.js.map +1 -0
  299. package/dist/scraper/retry.d.ts +33 -0
  300. package/dist/scraper/retry.d.ts.map +1 -0
  301. package/dist/scraper/retry.js +122 -0
  302. package/dist/scraper/retry.js.map +1 -0
  303. package/dist/scraper/session-browserbase.d.ts +35 -0
  304. package/dist/scraper/session-browserbase.d.ts.map +1 -0
  305. package/dist/scraper/session-browserbase.js +198 -0
  306. package/dist/scraper/session-browserbase.js.map +1 -0
  307. package/dist/scraper/session-shared.d.ts +29 -0
  308. package/dist/scraper/session-shared.d.ts.map +1 -0
  309. package/dist/scraper/session-shared.js +35 -0
  310. package/dist/scraper/session-shared.js.map +1 -0
  311. package/dist/scraper/session-steel.d.ts +31 -0
  312. package/dist/scraper/session-steel.d.ts.map +1 -0
  313. package/dist/scraper/session-steel.js +140 -0
  314. package/dist/scraper/session-steel.js.map +1 -0
  315. package/dist/scraper/session-warmup.d.ts +31 -0
  316. package/dist/scraper/session-warmup.d.ts.map +1 -0
  317. package/dist/scraper/session-warmup.js +46 -0
  318. package/dist/scraper/session-warmup.js.map +1 -0
  319. package/dist/scraper/session.d.ts +21 -0
  320. package/dist/scraper/session.d.ts.map +1 -0
  321. package/dist/scraper/session.js +28 -0
  322. package/dist/scraper/session.js.map +1 -0
  323. package/dist/scraper/stagehand-guard.d.ts +128 -0
  324. package/dist/scraper/stagehand-guard.d.ts.map +1 -0
  325. package/dist/scraper/stagehand-guard.js +337 -0
  326. package/dist/scraper/stagehand-guard.js.map +1 -0
  327. package/dist/scraper/throttle.d.ts +21 -0
  328. package/dist/scraper/throttle.d.ts.map +1 -0
  329. package/dist/scraper/throttle.js +45 -0
  330. package/dist/scraper/throttle.js.map +1 -0
  331. package/dist/scripts/hca-inbox-poll.d.ts +19 -0
  332. package/dist/scripts/hca-inbox-poll.d.ts.map +1 -0
  333. package/dist/scripts/hca-inbox-poll.js +151 -0
  334. package/dist/scripts/hca-inbox-poll.js.map +1 -0
  335. package/dist/scripts/judge-llm-batch.d.ts +98 -0
  336. package/dist/scripts/judge-llm-batch.d.ts.map +1 -0
  337. package/dist/scripts/judge-llm-batch.js +350 -0
  338. package/dist/scripts/judge-llm-batch.js.map +1 -0
  339. package/dist/scripts/llm-heal.d.ts +165 -0
  340. package/dist/scripts/llm-heal.d.ts.map +1 -0
  341. package/dist/scripts/llm-heal.js +595 -0
  342. package/dist/scripts/llm-heal.js.map +1 -0
  343. package/dist/scripts/migrate-telemetry-dir-names.d.ts +57 -0
  344. package/dist/scripts/migrate-telemetry-dir-names.d.ts.map +1 -0
  345. package/dist/scripts/migrate-telemetry-dir-names.js +156 -0
  346. package/dist/scripts/migrate-telemetry-dir-names.js.map +1 -0
  347. package/dist/scripts/probe-setinputfiles.d.ts +28 -0
  348. package/dist/scripts/probe-setinputfiles.d.ts.map +1 -0
  349. package/dist/scripts/probe-setinputfiles.js +95 -0
  350. package/dist/scripts/probe-setinputfiles.js.map +1 -0
  351. package/dist/scripts/recon-browser.d.ts +304 -0
  352. package/dist/scripts/recon-browser.d.ts.map +1 -0
  353. package/dist/scripts/recon-browser.js +1833 -0
  354. package/dist/scripts/recon-browser.js.map +1 -0
  355. package/dist/scripts/recon-generate.d.ts +182 -0
  356. package/dist/scripts/recon-generate.d.ts.map +1 -0
  357. package/dist/scripts/recon-generate.js +2572 -0
  358. package/dist/scripts/recon-generate.js.map +1 -0
  359. package/dist/scripts/recon-heal.d.ts +176 -0
  360. package/dist/scripts/recon-heal.d.ts.map +1 -0
  361. package/dist/scripts/recon-heal.js +584 -0
  362. package/dist/scripts/recon-heal.js.map +1 -0
  363. package/dist/scripts/recon-http.d.ts +19 -0
  364. package/dist/scripts/recon-http.d.ts.map +1 -0
  365. package/dist/scripts/recon-http.js +377 -0
  366. package/dist/scripts/recon-http.js.map +1 -0
  367. package/dist/scripts/recon-replay-jobs.d.ts +21 -0
  368. package/dist/scripts/recon-replay-jobs.d.ts.map +1 -0
  369. package/dist/scripts/recon-replay-jobs.js +221 -0
  370. package/dist/scripts/recon-replay-jobs.js.map +1 -0
  371. package/dist/scripts/recon-shared.d.ts +52 -0
  372. package/dist/scripts/recon-shared.d.ts.map +1 -0
  373. package/dist/scripts/recon-shared.js +68 -0
  374. package/dist/scripts/recon-shared.js.map +1 -0
  375. package/dist/scripts/recon-summarize.d.ts +15 -0
  376. package/dist/scripts/recon-summarize.d.ts.map +1 -0
  377. package/dist/scripts/recon-summarize.js +233 -0
  378. package/dist/scripts/recon-summarize.js.map +1 -0
  379. package/dist/scripts/smoke-test.d.ts +22 -0
  380. package/dist/scripts/smoke-test.d.ts.map +1 -0
  381. package/dist/scripts/smoke-test.js +236 -0
  382. package/dist/scripts/smoke-test.js.map +1 -0
  383. package/dist/server.d.ts +10 -0
  384. package/dist/server.d.ts.map +1 -0
  385. package/dist/server.js +189 -0
  386. package/dist/server.js.map +1 -0
  387. package/dist/site-plugin.d.ts +226 -0
  388. package/dist/site-plugin.d.ts.map +1 -0
  389. package/dist/site-plugin.js +13 -0
  390. package/dist/site-plugin.js.map +1 -0
  391. package/dist/testing/answers-fixture.d.ts +13 -0
  392. package/dist/testing/answers-fixture.d.ts.map +1 -0
  393. package/dist/testing/answers-fixture.js +37 -0
  394. package/dist/testing/answers-fixture.js.map +1 -0
  395. package/dist/testing/batch-email-confirmation.d.ts +58 -0
  396. package/dist/testing/batch-email-confirmation.d.ts.map +1 -0
  397. package/dist/testing/batch-email-confirmation.js +62 -0
  398. package/dist/testing/batch-email-confirmation.js.map +1 -0
  399. package/dist/testing/batch-report.d.ts +33 -0
  400. package/dist/testing/batch-report.d.ts.map +1 -0
  401. package/dist/testing/batch-report.js +30 -0
  402. package/dist/testing/batch-report.js.map +1 -0
  403. package/dist/testing/contract-parity-suite.d.ts +55 -0
  404. package/dist/testing/contract-parity-suite.d.ts.map +1 -0
  405. package/dist/testing/contract-parity-suite.js +39 -0
  406. package/dist/testing/contract-parity-suite.js.map +1 -0
  407. package/dist/testing/coverage-guard-suite.d.ts +46 -0
  408. package/dist/testing/coverage-guard-suite.d.ts.map +1 -0
  409. package/dist/testing/coverage-guard-suite.js +39 -0
  410. package/dist/testing/coverage-guard-suite.js.map +1 -0
  411. package/dist/testing/fixtures/resume.pdf +54 -0
  412. package/dist/testing/integration-runner.d.ts +62 -0
  413. package/dist/testing/integration-runner.d.ts.map +1 -0
  414. package/dist/testing/integration-runner.js +46 -0
  415. package/dist/testing/integration-runner.js.map +1 -0
  416. package/dist/testing/mock-fetch-response.d.ts +7 -0
  417. package/dist/testing/mock-fetch-response.d.ts.map +1 -0
  418. package/dist/testing/mock-fetch-response.js +16 -0
  419. package/dist/testing/mock-fetch-response.js.map +1 -0
  420. package/dist/testing/persona-fixture.d.ts +77 -0
  421. package/dist/testing/persona-fixture.d.ts.map +1 -0
  422. package/dist/testing/persona-fixture.js +83 -0
  423. package/dist/testing/persona-fixture.js.map +1 -0
  424. package/dist/testing/replay-integration-suite.d.ts +50 -0
  425. package/dist/testing/replay-integration-suite.d.ts.map +1 -0
  426. package/dist/testing/replay-integration-suite.js +45 -0
  427. package/dist/testing/replay-integration-suite.js.map +1 -0
  428. package/dist/testing/resume-fixture.d.ts +39 -0
  429. package/dist/testing/resume-fixture.d.ts.map +1 -0
  430. package/dist/testing/resume-fixture.js +38 -0
  431. package/dist/testing/resume-fixture.js.map +1 -0
  432. package/dist/testmail/client.d.ts +61 -0
  433. package/dist/testmail/client.d.ts.map +1 -0
  434. package/dist/testmail/client.js +190 -0
  435. package/dist/testmail/client.js.map +1 -0
  436. package/dist/testmail/errors.d.ts +18 -0
  437. package/dist/testmail/errors.d.ts.map +1 -0
  438. package/dist/testmail/errors.js +29 -0
  439. package/dist/testmail/errors.js.map +1 -0
  440. package/dist/types/dispatch-metrics.d.ts +46 -0
  441. package/dist/types/dispatch-metrics.d.ts.map +1 -0
  442. package/dist/types/dispatch-metrics.js +25 -0
  443. package/dist/types/dispatch-metrics.js.map +1 -0
  444. package/dist/types/logging.d.ts +11 -0
  445. package/dist/types/logging.d.ts.map +1 -0
  446. package/dist/types/logging.js +3 -0
  447. package/dist/types/logging.js.map +1 -0
  448. package/package.json +283 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Shared types and utilities for the recon pipeline scripts.
3
+ * Extracted so recon-summarize.ts and recon-generate.ts stay consistent
4
+ * without duplicating the core data model or header-tally logic.
5
+ */
6
+ export declare const CAPTURES_DIR = "/tmp/recon/graphql";
7
+ export declare const REPLAYS_DIR = "/tmp/recon/replays";
8
+ export declare const AUX_DIR = "/tmp/recon/aux";
9
+ export declare const STEP_FAILURES_DIR = "/tmp/recon/step-failures";
10
+ export interface Capture {
11
+ timestamp: string;
12
+ phase: string;
13
+ method: string;
14
+ url: string;
15
+ status: number;
16
+ requestHeaders: Record<string, string>;
17
+ requestPostData: string | null;
18
+ responseHeaders: Record<string, string>;
19
+ responseBody: unknown;
20
+ operationName: string | null;
21
+ query: string | null;
22
+ variables: unknown;
23
+ decodedParams: unknown;
24
+ }
25
+ export interface ReplayResult {
26
+ sourceCapture: string;
27
+ url: string;
28
+ method: string;
29
+ operationName: string | null;
30
+ requestBody: string | null;
31
+ replayStatus: number | null;
32
+ replayHeaders: Record<string, string>;
33
+ replayBody: unknown;
34
+ success: boolean;
35
+ error: string | null;
36
+ }
37
+ export interface RateLimitFinding {
38
+ endpoint: string;
39
+ safeRps: number | null;
40
+ triggerStatus: number | null;
41
+ triggerRps: number | null;
42
+ retryAfter: string | null;
43
+ xRateLimitHeaders: Record<string, string>;
44
+ }
45
+ export declare function readJsonDir<T>(dir: string, exclude?: string[]): T[];
46
+ /**
47
+ * Counts how often each response header appears across successful replays.
48
+ * Infrastructure headers that are never load-bearing on the request side are
49
+ * excluded so the caller sees only candidates worth committing as BASE_HEADERS.
50
+ */
51
+ export declare function tallyResponseHeaders(replays: ReplayResult[]): Map<string, number>;
52
+ //# sourceMappingURL=recon-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recon-shared.d.ts","sourceRoot":"","sources":["../../src/scripts/recon-shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,YAAY,uBAAuB,CAAC;AACjD,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAChD,eAAO,MAAM,OAAO,mBAAmB,CAAC;AACxC,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAE5D,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,CAAC,EAAE,CASvE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiCjF"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * Shared types and utilities for the recon pipeline scripts.
4
+ * Extracted so recon-summarize.ts and recon-generate.ts stay consistent
5
+ * without duplicating the core data model or header-tally logic.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.STEP_FAILURES_DIR = exports.AUX_DIR = exports.REPLAYS_DIR = exports.CAPTURES_DIR = void 0;
9
+ exports.readJsonDir = readJsonDir;
10
+ exports.tallyResponseHeaders = tallyResponseHeaders;
11
+ const node_fs_1 = require("node:fs");
12
+ const node_path_1 = require("node:path");
13
+ exports.CAPTURES_DIR = "/tmp/recon/graphql";
14
+ exports.REPLAYS_DIR = "/tmp/recon/replays";
15
+ exports.AUX_DIR = "/tmp/recon/aux";
16
+ exports.STEP_FAILURES_DIR = "/tmp/recon/step-failures";
17
+ function readJsonDir(dir, exclude = []) {
18
+ try {
19
+ return (0, node_fs_1.readdirSync)(dir)
20
+ .filter((f) => f.endsWith(".json") && !f.endsWith(".decoded.json") && !exclude.includes(f))
21
+ .sort()
22
+ .map((f) => JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, f), "utf8")));
23
+ }
24
+ catch {
25
+ return [];
26
+ }
27
+ }
28
+ /**
29
+ * Counts how often each response header appears across successful replays.
30
+ * Infrastructure headers that are never load-bearing on the request side are
31
+ * excluded so the caller sees only candidates worth committing as BASE_HEADERS.
32
+ */
33
+ function tallyResponseHeaders(replays) {
34
+ const IGNORE = new Set([
35
+ "date",
36
+ "content-length",
37
+ "transfer-encoding",
38
+ "connection",
39
+ "vary",
40
+ "server",
41
+ "x-request-id",
42
+ "x-correlation-id",
43
+ "cf-ray",
44
+ "cf-cache-status",
45
+ "age",
46
+ "via",
47
+ "etag",
48
+ "last-modified",
49
+ "expires",
50
+ "pragma",
51
+ "strict-transport-security",
52
+ "x-content-type-options",
53
+ "x-frame-options",
54
+ "x-xss-protection",
55
+ ]);
56
+ const counts = new Map();
57
+ const successfulReplays = replays.filter((r) => r.success && r.replayHeaders);
58
+ for (const replay of successfulReplays) {
59
+ for (const header of Object.keys(replay.replayHeaders)) {
60
+ const lower = header.toLowerCase();
61
+ if (IGNORE.has(lower))
62
+ continue;
63
+ counts.set(lower, (counts.get(lower) ?? 0) + 1);
64
+ }
65
+ }
66
+ return counts;
67
+ }
68
+ //# sourceMappingURL=recon-shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recon-shared.js","sourceRoot":"","sources":["../../src/scripts/recon-shared.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAgDH,kCASC;AAOD,oDAiCC;AA/FD,qCAAoD;AACpD,yCAAiC;AAEpB,QAAA,YAAY,GAAG,oBAAoB,CAAC;AACpC,QAAA,WAAW,GAAG,oBAAoB,CAAC;AACnC,QAAA,OAAO,GAAG,gBAAgB,CAAC;AAC3B,QAAA,iBAAiB,GAAG,0BAA0B,CAAC;AAwC5D,SAAgB,WAAW,CAAI,GAAW,EAAE,UAAoB,EAAE;IAChE,IAAI,CAAC;QACH,OAAO,IAAA,qBAAW,EAAC,GAAG,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;aAC1F,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAM,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,OAAuB;IAC1D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC;QACrB,MAAM;QACN,gBAAgB;QAChB,mBAAmB;QACnB,YAAY;QACZ,MAAM;QACN,QAAQ;QACR,cAAc;QACd,kBAAkB;QAClB,QAAQ;QACR,iBAAiB;QACjB,KAAK;QACL,KAAK;QACL,MAAM;QACN,eAAe;QACf,SAAS;QACT,QAAQ;QACR,2BAA2B;QAC3B,wBAAwB;QACxB,iBAAiB;QACjB,kBAAkB;KACnB,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC;IAC9E,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;QACvC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YACnC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAS;YAChC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Phase 4e: reads captures and replays produced by recon-browser.ts and
3
+ * recon-http.ts and generates docs/target-recon.md — the findings document
4
+ * a teammate needs when the integration breaks.
5
+ *
6
+ * Usage:
7
+ * pnpm tsx src/scripts/recon-summarize.ts \
8
+ * [--site-id <id>] [--out docs/target-recon.md]
9
+ *
10
+ * When --site-id is provided, path placeholders in the output (src/sites/<id>/...)
11
+ * are replaced with the real site ID and the default output path becomes
12
+ * docs/<site-id>-recon.md.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=recon-summarize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recon-summarize.d.ts","sourceRoot":"","sources":["../../src/scripts/recon-summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ /**
3
+ * Phase 4e: reads captures and replays produced by recon-browser.ts and
4
+ * recon-http.ts and generates docs/target-recon.md — the findings document
5
+ * a teammate needs when the integration breaks.
6
+ *
7
+ * Usage:
8
+ * pnpm tsx src/scripts/recon-summarize.ts \
9
+ * [--site-id <id>] [--out docs/target-recon.md]
10
+ *
11
+ * When --site-id is provided, path placeholders in the output (src/sites/<id>/...)
12
+ * are replaced with the real site ID and the default output path becomes
13
+ * docs/<site-id>-recon.md.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ const node_fs_1 = require("node:fs");
17
+ const node_path_1 = require("node:path");
18
+ const errors_1 = require("../lib/errors");
19
+ const logging_1 = require("../lib/logging");
20
+ const recon_shared_1 = require("../scripts/recon-shared");
21
+ const logger = (0, logging_1.getScriptLogger)("recon-summarize");
22
+ const DEFAULT_OUT = "docs/target-recon.md";
23
+ const PLACEHOLDER_ID = "<id>";
24
+ function formatDate(iso) {
25
+ return new Date(iso).toLocaleString("en-US", {
26
+ timeZone: "UTC",
27
+ dateStyle: "medium",
28
+ timeStyle: "short",
29
+ });
30
+ }
31
+ async function main() {
32
+ const args = process.argv.slice(2);
33
+ let siteId = PLACEHOLDER_ID;
34
+ let outPath = null;
35
+ for (let i = 0; i < args.length; i++) {
36
+ if (args[i] === "--site-id" && args[i + 1])
37
+ siteId = args[++i];
38
+ else if (args[i] === "--out" && args[i + 1])
39
+ outPath = args[++i];
40
+ }
41
+ // Default output path is scoped to site ID when one is provided.
42
+ outPath ??= siteId !== PLACEHOLDER_ID ? `docs/${siteId}-recon.md` : DEFAULT_OUT;
43
+ const captures = (0, recon_shared_1.readJsonDir)(recon_shared_1.CAPTURES_DIR);
44
+ const replays = (0, recon_shared_1.readJsonDir)(recon_shared_1.REPLAYS_DIR, [
45
+ "rate-limit.json",
46
+ "introspection-schema.json",
47
+ ]);
48
+ const rateLimitRaw = (() => {
49
+ try {
50
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(recon_shared_1.REPLAYS_DIR, "rate-limit.json"), "utf8"));
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ })();
56
+ const auxFiles = (() => {
57
+ try {
58
+ return (0, node_fs_1.readdirSync)(recon_shared_1.AUX_DIR)
59
+ .filter((f) => f.endsWith(".json"))
60
+ .sort();
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ })();
66
+ const now = new Date().toISOString();
67
+ const reconDate = captures[0]?.timestamp ? formatDate(captures[0].timestamp) : "unknown";
68
+ const uniqueEndpoints = new Map();
69
+ for (const c of captures) {
70
+ try {
71
+ const u = new URL(c.url);
72
+ const key = `${u.origin}${u.pathname}`;
73
+ const entry = uniqueEndpoints.get(key) ?? {
74
+ methods: new Set(),
75
+ operations: new Set(),
76
+ };
77
+ entry.methods.add(c.method);
78
+ if (c.operationName)
79
+ entry.operations.add(c.operationName);
80
+ uniqueEndpoints.set(key, entry);
81
+ }
82
+ catch {
83
+ // skip
84
+ }
85
+ }
86
+ const replayByUrl = new Map();
87
+ for (const r of replays) {
88
+ try {
89
+ const u = new URL(r.url);
90
+ replayByUrl.set(`${u.origin}${u.pathname}`, r);
91
+ }
92
+ catch {
93
+ // skip
94
+ }
95
+ }
96
+ const passed = replays.filter((r) => r.success).length;
97
+ const failed = replays.filter((r) => !r.success).length;
98
+ const has401 = replays.some((r) => r.replayStatus === 401);
99
+ const has403 = replays.some((r) => r.replayStatus === 403);
100
+ const rateLimitSummary = rateLimitRaw.length === 0
101
+ ? "Rate-limit probe not yet run."
102
+ : rateLimitRaw
103
+ .map((f) => {
104
+ const safe = f.safeRps !== null ? `${f.safeRps} rps` : "unknown";
105
+ const trigger = f.triggerStatus !== null
106
+ ? ` (triggered ${f.triggerStatus} at ${f.triggerRps} rps)`
107
+ : " (no trigger observed)";
108
+ const minTime = f.safeRps !== null ? Math.floor(1000 / f.safeRps) : null;
109
+ const snippet = minTime !== null
110
+ ? `\n \`\`\`typescript\n // Step 4c: commit this Bottleneck ceiling in your plugin's contract.ts\n const limiter = new Bottleneck({ minTime: ${minTime} }); // ${f.safeRps} rps safe ceiling\n \`\`\``
111
+ : "";
112
+ return `- \`${f.endpoint}\`: safe ceiling **${safe}**${trigger}${snippet}`;
113
+ })
114
+ .join("\n");
115
+ const headerCounts = (0, recon_shared_1.tallyResponseHeaders)(replays);
116
+ const successCount = replays.filter((r) => r.success).length;
117
+ const hazards = [];
118
+ if (has401)
119
+ hazards.push("Auth required on some endpoints (401)");
120
+ if (has403)
121
+ hazards.push("Bot detection active on some endpoints (403) — may need more headers or Stagehand-only");
122
+ const rateLimitHeaders = rateLimitRaw.flatMap((f) => Object.keys(f.xRateLimitHeaders ?? {}));
123
+ if (rateLimitHeaders.some((h) => h.toLowerCase().includes("akamai")))
124
+ hazards.push("Akamai edge detected");
125
+ if (rateLimitHeaders.some((h) => h.toLowerCase().includes("cf-")))
126
+ hazards.push("Cloudflare edge detected");
127
+ const lines = [
128
+ `# Target Recon Findings`,
129
+ ``,
130
+ `> Generated by \`recon-summarize.ts\` on ${formatDate(now)} from captures taken ${reconDate}.`,
131
+ `> Human review required — update this doc and \`src/sites/<id>/contract.ts\` then ship.`,
132
+ ``,
133
+ `## Summary`,
134
+ ``,
135
+ `| Stat | Value |`,
136
+ `|------|-------|`,
137
+ `| Captures | ${captures.length} |`,
138
+ `| Unique endpoints | ${uniqueEndpoints.size} |`,
139
+ `| Replay passed | ${passed} |`,
140
+ `| Replay failed | ${failed} |`,
141
+ `| Auth required | ${has401 ? "YES — see §Auth" : "No"} |`,
142
+ `| Bot detection | ${has403 ? "YES — see §Hazards" : "No"} |`,
143
+ `| Auxiliary fixtures | ${auxFiles.length} |`,
144
+ ``,
145
+ `## Endpoints Found`,
146
+ ``,
147
+ ...[...uniqueEndpoints.entries()].map(([endpoint, { methods, operations }]) => {
148
+ const replay = replayByUrl.get(endpoint);
149
+ const replayStatus = replay ? `\`${replay.replayStatus ?? "ERR"}\`` : "not replayed";
150
+ const ops = operations.size > 0 ? `operations: ${[...operations].join(", ")}` : "REST";
151
+ return `- \`${endpoint}\` — ${[...methods].join("/")} — ${ops} — replay: ${replayStatus}`;
152
+ }),
153
+ ``,
154
+ `## Public Endpoints`,
155
+ ``,
156
+ replays.filter((r) => r.success).length === 0
157
+ ? "_None confirmed — all replays failed. Check §Hazards._"
158
+ : replays
159
+ .filter((r) => r.success)
160
+ .map((r) => `- \`${r.url}\` — **public** (replayed ${r.replayStatus})`)
161
+ .join("\n"),
162
+ ``,
163
+ `## Auth Required`,
164
+ ``,
165
+ has401
166
+ ? replays
167
+ .filter((r) => r.replayStatus === 401)
168
+ .map((r) => `- \`${r.url}\` — 401. Capture token, determine lifetime, build refresh strategy.`)
169
+ .join("\n")
170
+ : "_No authenticated endpoints detected._",
171
+ ``,
172
+ `## Rate-Limit Ceiling`,
173
+ ``,
174
+ rateLimitSummary,
175
+ ``,
176
+ `## Codified Headers (Step 4b)`,
177
+ ``,
178
+ headerCounts.size === 0
179
+ ? "_No successful replays — run recon-http.ts first._"
180
+ : [
181
+ `_Headers present in successful replays, sorted by frequency. Headers appearing in all_`,
182
+ `_${successCount} successful replay(s) are likely load-bearing. Commit the load-bearing subset_`,
183
+ `_as \`BASE_HEADERS\` in \`src/sites/<id>/contract.ts\` and drop the rest._`,
184
+ ``,
185
+ `| Header | Replays present (of ${successCount}) | Likely load-bearing? |`,
186
+ `|--------|--------------------------------------|----------------------|`,
187
+ ...[...headerCounts.entries()]
188
+ .sort((a, b) => b[1] - a[1])
189
+ .map(([header, count]) => {
190
+ const loadBearing = count === successCount ? "**Yes**" : "No";
191
+ return `| \`${header}\` | ${count} | ${loadBearing} |`;
192
+ }),
193
+ ].join("\n"),
194
+ ``,
195
+ `## Hazards`,
196
+ ``,
197
+ hazards.length === 0 ? "_None detected._" : hazards.map((h) => `- ${h}`).join("\n"),
198
+ ``,
199
+ `## Auxiliary Fixtures`,
200
+ ``,
201
+ auxFiles.length === 0
202
+ ? "_No auxiliary fixtures detected. Run Phase 3B (recon-http.ts) to probe static endpoints._"
203
+ : [
204
+ `_Downloaded to \`${recon_shared_1.AUX_DIR}\` — commit each as a static fixture in \`src/sites/<id>/fixtures/\`._`,
205
+ ``,
206
+ ...auxFiles.map((f) => `- \`${f}\` — commit as \`src/sites/<id>/fixtures/${f}\``),
207
+ ].join("\n"),
208
+ ``,
209
+ `## Codified Query Location`,
210
+ ``,
211
+ `Run \`pnpm run recon:generate -- --site-id <id>\` to generate \`src/sites/<id>/contract.ts\``,
212
+ `from the captured JSON. Review and trim the generated file before registering.`,
213
+ ``,
214
+ `## Maintenance`,
215
+ ``,
216
+ `When smoke test fails: re-run \`pnpm tsx src/scripts/recon-browser.ts\` → diff`,
217
+ `\`/tmp/recon/graphql/*<operationName>*.json\` against \`src/sites/<id>/contract.ts\``,
218
+ `→ update query / headers / Zod schema → ship.`,
219
+ ``,
220
+ `---`,
221
+ `_Generated by barnacle recon pipeline. Do not edit by hand — re-run \`recon-summarize.ts\` after each recon run._`,
222
+ ``,
223
+ ];
224
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(outPath), { recursive: true });
225
+ const content = lines.join("\n").replaceAll(PLACEHOLDER_ID, siteId);
226
+ (0, node_fs_1.writeFileSync)(outPath, content);
227
+ logger.info(`findings written to ${outPath}`);
228
+ }
229
+ main().catch((err) => {
230
+ logger.error(`recon-summarize failed: ${(0, errors_1.toErrorMessage)(err)}`);
231
+ process.exit(1);
232
+ });
233
+ //# sourceMappingURL=recon-summarize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recon-summarize.js","sourceRoot":"","sources":["../../src/scripts/recon-summarize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Nightly validation: runs one request through a plugin's endpoint end-to-end
3
+ * and validates the response envelope shape and HTTP status. Exits 0 on
4
+ * success, non-zero on HTTP error or malformed envelope. Wire into CI and
5
+ * cron — this is the first rung of the drift-detection ladder.
6
+ *
7
+ * Usage:
8
+ * pnpm run smoke -- --site <siteId> --payload '{"key":"value"}' \
9
+ * [--host http://localhost:3000] [--route <path>] [--fallback] \
10
+ * [--response-schema <path>] [--timeout <ms>]
11
+ *
12
+ * --response-schema must point to a TypeScript/JS module whose default export is a
13
+ * Zod schema. The smoke test validates the full response body against it — not just
14
+ * the envelope wrapper — so schema drift on the data payload fails loud and fast.
15
+ *
16
+ * Requires:
17
+ * - The server to be running (or pass --host to point at staging/prod)
18
+ * - API_KEY env var with a plaintext key that matches one of API_KEYS_HASHED
19
+ * - The target plugin to be registered and healthy
20
+ */
21
+ export {};
22
+ //# sourceMappingURL=smoke-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke-test.d.ts","sourceRoot":"","sources":["../../src/scripts/smoke-test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ /**
3
+ * Nightly validation: runs one request through a plugin's endpoint end-to-end
4
+ * and validates the response envelope shape and HTTP status. Exits 0 on
5
+ * success, non-zero on HTTP error or malformed envelope. Wire into CI and
6
+ * cron — this is the first rung of the drift-detection ladder.
7
+ *
8
+ * Usage:
9
+ * pnpm run smoke -- --site <siteId> --payload '{"key":"value"}' \
10
+ * [--host http://localhost:3000] [--route <path>] [--fallback] \
11
+ * [--response-schema <path>] [--timeout <ms>]
12
+ *
13
+ * --response-schema must point to a TypeScript/JS module whose default export is a
14
+ * Zod schema. The smoke test validates the full response body against it — not just
15
+ * the envelope wrapper — so schema drift on the data payload fails loud and fast.
16
+ *
17
+ * Requires:
18
+ * - The server to be running (or pass --host to point at staging/prod)
19
+ * - API_KEY env var with a plaintext key that matches one of API_KEYS_HASHED
20
+ * - The target plugin to be registered and healthy
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ const node_path_1 = require("node:path");
24
+ const v4_1 = require("zod/v4");
25
+ const errors_1 = require("../lib/errors");
26
+ const http_1 = require("../lib/http");
27
+ const logging_1 = require("../lib/logging");
28
+ (0, http_1.configureHttpDispatcher)();
29
+ const logger = (0, logging_1.getScriptLogger)("smoke-test");
30
+ const DEFAULT_HOST = "http://localhost:3000";
31
+ const ResponseEnvelopeSchema = v4_1.z.object({
32
+ status: v4_1.z.object({
33
+ httpStatus: v4_1.z.string(),
34
+ dateTime: v4_1.z.string(),
35
+ details: v4_1.z.array(v4_1.z.unknown()),
36
+ }),
37
+ });
38
+ const DEFAULT_TIMEOUT_MS = 30_000;
39
+ function parseCli() {
40
+ const args = process.argv.slice(2);
41
+ let site = "";
42
+ let payloadStr = "{}";
43
+ let host = process.env.SMOKE_HOST ?? DEFAULT_HOST;
44
+ let route = null;
45
+ let runFallback = false;
46
+ let responseSchemaPath = null;
47
+ let timeoutMs = Number(process.env.SMOKE_TIMEOUT_MS ?? DEFAULT_TIMEOUT_MS);
48
+ for (let i = 0; i < args.length; i++) {
49
+ if (args[i] === "--site" && args[i + 1])
50
+ site = args[++i];
51
+ else if (args[i] === "--payload" && args[i + 1])
52
+ payloadStr = args[++i];
53
+ else if (args[i] === "--host" && args[i + 1])
54
+ host = args[++i];
55
+ else if (args[i] === "--route" && args[i + 1])
56
+ route = args[++i];
57
+ else if (args[i] === "--fallback")
58
+ runFallback = true;
59
+ else if (args[i] === "--response-schema" && args[i + 1])
60
+ responseSchemaPath = (0, node_path_1.resolve)(args[++i]);
61
+ else if (args[i] === "--timeout" && args[i + 1])
62
+ timeoutMs = Number(args[++i]);
63
+ }
64
+ if (!site) {
65
+ logger.error("usage: smoke-test.ts --site <siteId> [--payload <json>] [--host <url>] [--route <path>] [--fallback] [--response-schema <path>] [--timeout <ms>]");
66
+ process.exit(1);
67
+ }
68
+ let payload;
69
+ try {
70
+ payload = JSON.parse(payloadStr);
71
+ }
72
+ catch {
73
+ logger.error(`invalid --payload JSON: ${payloadStr}`);
74
+ process.exit(1);
75
+ }
76
+ return { site, payload, host, route, runFallback, responseSchemaPath, timeoutMs };
77
+ }
78
+ /**
79
+ * Dynamically imports a Zod schema from a module path. The module must
80
+ * export a Zod schema as its default export so the smoke test remains
81
+ * site-agnostic — it validates without knowing which plugin it targets.
82
+ */
83
+ async function loadResponseSchema(schemaPath) {
84
+ try {
85
+ const mod = (await import(schemaPath));
86
+ if (!mod.default || typeof mod.default.safeParse !== "function") {
87
+ logger.error(`--response-schema: default export from ${schemaPath} is not a Zod schema`);
88
+ process.exit(1);
89
+ }
90
+ return mod.default;
91
+ }
92
+ catch (err) {
93
+ logger.error(`--response-schema: failed to import ${schemaPath}: ${(0, errors_1.toErrorMessage)(err)}`);
94
+ process.exit(1);
95
+ }
96
+ }
97
+ async function main() {
98
+ const { site, payload, host, route, runFallback, responseSchemaPath, timeoutMs } = parseCli();
99
+ const responseSchema = responseSchemaPath ? await loadResponseSchema(responseSchemaPath) : null;
100
+ const apiKey = process.env.API_KEY;
101
+ if (!apiKey) {
102
+ logger.error("API_KEY env var required");
103
+ process.exit(1);
104
+ }
105
+ const url = route != null ? `${host}${route}` : `${host}/v1/${site}/run`;
106
+ logger.info(`smoke-test: POST ${url}${route != null ? " (routeOverride)" : ""} (timeout=${timeoutMs}ms)`);
107
+ logger.info(`payload: ${JSON.stringify(payload)}`);
108
+ const startMs = Date.now();
109
+ let response;
110
+ const controller = new AbortController();
111
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
112
+ try {
113
+ response = await fetch(url, {
114
+ method: "POST",
115
+ headers: {
116
+ "Content-Type": "application/json",
117
+ Authorization: `Bearer ${apiKey}`,
118
+ },
119
+ body: JSON.stringify(payload),
120
+ signal: controller.signal,
121
+ });
122
+ }
123
+ catch (err) {
124
+ if (err instanceof Error && err.name === "AbortError") {
125
+ logger.error(`smoke-test timed out after ${timeoutMs}ms`);
126
+ }
127
+ else {
128
+ logger.error(`fetch failed: ${(0, errors_1.toErrorMessage)(err)}`);
129
+ }
130
+ process.exit(1);
131
+ }
132
+ finally {
133
+ clearTimeout(timer);
134
+ }
135
+ const latencyMs = Date.now() - startMs;
136
+ logger.info(`response: ${response.status} in ${latencyMs}ms`);
137
+ let body;
138
+ try {
139
+ body = await response.json();
140
+ }
141
+ catch (err) {
142
+ logger.error(`response body is not JSON: ${(0, errors_1.toErrorMessage)(err)}`);
143
+ process.exit(1);
144
+ }
145
+ const envelope = ResponseEnvelopeSchema.safeParse(body);
146
+ if (!envelope.success) {
147
+ logger.error(`response does not match envelope schema: ${JSON.stringify(envelope.error.issues, null, 2)}`);
148
+ process.exit(1);
149
+ }
150
+ if (!response.ok) {
151
+ logger.error(`smoke-test FAILED — HTTP ${response.status}: ${JSON.stringify(body, null, 2)}`);
152
+ process.exit(1);
153
+ }
154
+ if (envelope.data.status.httpStatus !== "OK") {
155
+ logger.error(`smoke-test FAILED — envelope status: ${envelope.data.status.httpStatus}: ${JSON.stringify(body, null, 2)}`);
156
+ process.exit(1);
157
+ }
158
+ if (responseSchema) {
159
+ const dataResult = responseSchema.safeParse(body);
160
+ if (!dataResult.success) {
161
+ logger.error(`smoke-test FAILED — response body failed schema validation: ${JSON.stringify(dataResult.error.issues, null, 2)}`);
162
+ process.exit(1);
163
+ }
164
+ logger.info("schema validation PASSED");
165
+ }
166
+ logger.info(`smoke-test PASSED — site=${site} status=OK latency=${latencyMs}ms`);
167
+ if (runFallback) {
168
+ logger.info("smoke-test: running optional fallback-path probe...");
169
+ const fallbackStartMs = Date.now();
170
+ let fallbackResponse;
171
+ const fallbackController = new AbortController();
172
+ const fallbackTimer = setTimeout(() => fallbackController.abort(), timeoutMs);
173
+ try {
174
+ fallbackResponse = await fetch(url, {
175
+ method: "POST",
176
+ headers: {
177
+ "Content-Type": "application/json",
178
+ Authorization: `Bearer ${apiKey}`,
179
+ "X-Barnacle-Force-Fallback": "true",
180
+ },
181
+ body: JSON.stringify(payload),
182
+ signal: fallbackController.signal,
183
+ });
184
+ }
185
+ catch (err) {
186
+ if (err instanceof Error && err.name === "AbortError") {
187
+ logger.error(`smoke-test (fallback) timed out after ${timeoutMs}ms`);
188
+ }
189
+ else {
190
+ logger.error(`fallback probe fetch failed: ${(0, errors_1.toErrorMessage)(err)}`);
191
+ }
192
+ process.exit(1);
193
+ }
194
+ finally {
195
+ clearTimeout(fallbackTimer);
196
+ }
197
+ const fallbackLatencyMs = Date.now() - fallbackStartMs;
198
+ logger.info(`fallback response: ${fallbackResponse.status} in ${fallbackLatencyMs}ms`);
199
+ if (!fallbackResponse.ok) {
200
+ const body = await fallbackResponse.text().catch(() => "(unreadable body)");
201
+ logger.error(`smoke-test FAILED (fallback) — HTTP ${fallbackResponse.status}: ${body}`);
202
+ process.exit(1);
203
+ }
204
+ let fallbackBody;
205
+ try {
206
+ fallbackBody = await fallbackResponse.json();
207
+ }
208
+ catch (err) {
209
+ logger.error(`fallback response body is not JSON: ${(0, errors_1.toErrorMessage)(err)}`);
210
+ process.exit(1);
211
+ }
212
+ const fallbackEnvelope = ResponseEnvelopeSchema.safeParse(fallbackBody);
213
+ if (!fallbackEnvelope.success) {
214
+ logger.error(`fallback response does not match envelope schema: ${JSON.stringify(fallbackEnvelope.error.issues, null, 2)}`);
215
+ process.exit(1);
216
+ }
217
+ if (fallbackEnvelope.data.status.httpStatus !== "OK") {
218
+ logger.error(`smoke-test FAILED (fallback) — envelope status: ${fallbackEnvelope.data.status.httpStatus}: ${JSON.stringify(fallbackBody, null, 2)}`);
219
+ process.exit(1);
220
+ }
221
+ if (responseSchema) {
222
+ const fallbackDataResult = responseSchema.safeParse(fallbackBody);
223
+ if (!fallbackDataResult.success) {
224
+ logger.error(`smoke-test FAILED (fallback) — response body failed schema validation: ${JSON.stringify(fallbackDataResult.error.issues, null, 2)}`);
225
+ process.exit(1);
226
+ }
227
+ logger.info("schema validation PASSED (fallback)");
228
+ }
229
+ logger.info(`smoke-test PASSED (fallback) — site=${site} status=OK latency=${fallbackLatencyMs}ms`);
230
+ }
231
+ }
232
+ main().catch((err) => {
233
+ logger.error(`smoke-test error: ${(0, errors_1.toErrorMessage)(err)}`);
234
+ process.exit(1);
235
+ });
236
+ //# sourceMappingURL=smoke-test.js.map