@blamejs/blamejs-shop 0.0.44

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 (1220) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +17 -0
  3. package/README.md +117 -0
  4. package/SECURITY.md +139 -0
  5. package/lib/admin.js +952 -0
  6. package/lib/analytics.js +267 -0
  7. package/lib/cart.js +279 -0
  8. package/lib/catalog-import.js +344 -0
  9. package/lib/catalog.js +769 -0
  10. package/lib/checkout.js +320 -0
  11. package/lib/config.js +151 -0
  12. package/lib/customers.js +322 -0
  13. package/lib/email.js +242 -0
  14. package/lib/externaldb-d1.js +283 -0
  15. package/lib/index.js +57 -0
  16. package/lib/inventory-alerts.js +198 -0
  17. package/lib/newsletter.js +142 -0
  18. package/lib/order.js +380 -0
  19. package/lib/payment.js +318 -0
  20. package/lib/pricing.js +185 -0
  21. package/lib/r2-bridge.js +169 -0
  22. package/lib/shipping.js +185 -0
  23. package/lib/storefront.js +2160 -0
  24. package/lib/subscriptions.js +410 -0
  25. package/lib/tax.js +161 -0
  26. package/lib/theme.js +194 -0
  27. package/lib/vendor/MANIFEST.json +19 -0
  28. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +23 -0
  29. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +34 -0
  30. package/lib/vendor/blamejs/.clusterfuzzlite/project.yaml +16 -0
  31. package/lib/vendor/blamejs/.dockerignore +45 -0
  32. package/lib/vendor/blamejs/.gitattributes +42 -0
  33. package/lib/vendor/blamejs/.github/CODEOWNERS +4 -0
  34. package/lib/vendor/blamejs/.github/FUNDING.yml +2 -0
  35. package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/bug_report.md +58 -0
  36. package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/config.yml +8 -0
  37. package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/feature_request.md +99 -0
  38. package/lib/vendor/blamejs/.github/PULL_REQUEST_TEMPLATE.md +77 -0
  39. package/lib/vendor/blamejs/.github/dependabot.yml +37 -0
  40. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +148 -0
  41. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +107 -0
  42. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +122 -0
  43. package/lib/vendor/blamejs/.github/workflows/ci.yml +511 -0
  44. package/lib/vendor/blamejs/.github/workflows/codeql.yml +50 -0
  45. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +655 -0
  46. package/lib/vendor/blamejs/.github/workflows/release-container.yml +406 -0
  47. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +101 -0
  48. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +134 -0
  49. package/lib/vendor/blamejs/.gitignore +102 -0
  50. package/lib/vendor/blamejs/.gitleaks.toml +166 -0
  51. package/lib/vendor/blamejs/.hadolint.yaml +18 -0
  52. package/lib/vendor/blamejs/.npmrc +5 -0
  53. package/lib/vendor/blamejs/.pinact.yaml +17 -0
  54. package/lib/vendor/blamejs/ARCHITECTURE.md +158 -0
  55. package/lib/vendor/blamejs/CHANGELOG.md +1351 -0
  56. package/lib/vendor/blamejs/CODE_OF_CONDUCT.md +86 -0
  57. package/lib/vendor/blamejs/CONTRIBUTING.md +156 -0
  58. package/lib/vendor/blamejs/GOVERNANCE.md +201 -0
  59. package/lib/vendor/blamejs/LICENSE +201 -0
  60. package/lib/vendor/blamejs/LTS-CALENDAR.md +29 -0
  61. package/lib/vendor/blamejs/MIGRATING.md +29 -0
  62. package/lib/vendor/blamejs/NOTICE +81 -0
  63. package/lib/vendor/blamejs/README.md +304 -0
  64. package/lib/vendor/blamejs/SECURITY.md +432 -0
  65. package/lib/vendor/blamejs/api-snapshot.json +48709 -0
  66. package/lib/vendor/blamejs/assets/BlameJS_Logo.png +0 -0
  67. package/lib/vendor/blamejs/assets/BlameJS_Logo.svg +129 -0
  68. package/lib/vendor/blamejs/bench/README.md +77 -0
  69. package/lib/vendor/blamejs/bench/_helpers.js +70 -0
  70. package/lib/vendor/blamejs/bench/baseline.json +183 -0
  71. package/lib/vendor/blamejs/bench/crypto-hash.bench.js +19 -0
  72. package/lib/vendor/blamejs/bench/crypto-symmetric.bench.js +28 -0
  73. package/lib/vendor/blamejs/bench/run.js +140 -0
  74. package/lib/vendor/blamejs/bench/safe-json.bench.js +31 -0
  75. package/lib/vendor/blamejs/bin/blamejs.js +13 -0
  76. package/lib/vendor/blamejs/docker/caddy/Caddyfile +46 -0
  77. package/lib/vendor/blamejs/docker/coredns/Corefile +37 -0
  78. package/lib/vendor/blamejs/docker/haproxy/haproxy.cfg +52 -0
  79. package/lib/vendor/blamejs/docker/init/generate-certs.sh +118 -0
  80. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +87 -0
  81. package/lib/vendor/blamejs/docker/mitmproxy/config.yaml +16 -0
  82. package/lib/vendor/blamejs/docker/mongo/init-tls.sh +17 -0
  83. package/lib/vendor/blamejs/docker/mysql/my.cnf +12 -0
  84. package/lib/vendor/blamejs/docker/nats/nats.conf +33 -0
  85. package/lib/vendor/blamejs/docker/postgres/init-tls.sh +17 -0
  86. package/lib/vendor/blamejs/docker/postgres/postgresql.conf +18 -0
  87. package/lib/vendor/blamejs/docker/rabbitmq/rabbitmq.conf +18 -0
  88. package/lib/vendor/blamejs/docker/redis/redis.conf +15 -0
  89. package/lib/vendor/blamejs/docker/squid/squid.conf +24 -0
  90. package/lib/vendor/blamejs/docker/syslog/syslog-ng.conf +34 -0
  91. package/lib/vendor/blamejs/docker-compose.test.yml +545 -0
  92. package/lib/vendor/blamejs/docs/cis-postgres-crosswalk.md +102 -0
  93. package/lib/vendor/blamejs/docs/cis-sqlite-equivalent.md +92 -0
  94. package/lib/vendor/blamejs/eslint.config.mjs +204 -0
  95. package/lib/vendor/blamejs/examples/wiki/Caddyfile +40 -0
  96. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +218 -0
  97. package/lib/vendor/blamejs/examples/wiki/Dockerfile +120 -0
  98. package/lib/vendor/blamejs/examples/wiki/README.md +157 -0
  99. package/lib/vendor/blamejs/examples/wiki/cli-snapshot.json +250 -0
  100. package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +231 -0
  101. package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +166 -0
  102. package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +217 -0
  103. package/lib/vendor/blamejs/examples/wiki/lib/auto-site-entries.js +139 -0
  104. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +555 -0
  105. package/lib/vendor/blamejs/examples/wiki/lib/harvest-cli.js +507 -0
  106. package/lib/vendor/blamejs/examples/wiki/lib/harvest-env-vars.js +435 -0
  107. package/lib/vendor/blamejs/examples/wiki/lib/harvest-errors.js +282 -0
  108. package/lib/vendor/blamejs/examples/wiki/lib/harvest-vendored-deps.js +321 -0
  109. package/lib/vendor/blamejs/examples/wiki/lib/nav.js +15 -0
  110. package/lib/vendor/blamejs/examples/wiki/lib/opts-resolver.js +75 -0
  111. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +508 -0
  112. package/lib/vendor/blamejs/examples/wiki/lib/section.js +276 -0
  113. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +587 -0
  114. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +318 -0
  115. package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +122 -0
  116. package/lib/vendor/blamejs/examples/wiki/migrations/0001-pages-schema.js +74 -0
  117. package/lib/vendor/blamejs/examples/wiki/package.json +18 -0
  118. package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.png +0 -0
  119. package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.svg +129 -0
  120. package/lib/vendor/blamejs/examples/wiki/public/robots.txt +5 -0
  121. package/lib/vendor/blamejs/examples/wiki/public/vendor/MANIFEST.json +30 -0
  122. package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.css +1 -0
  123. package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.js +15 -0
  124. package/lib/vendor/blamejs/examples/wiki/public/wiki.css +1250 -0
  125. package/lib/vendor/blamejs/examples/wiki/routes/admin.js +366 -0
  126. package/lib/vendor/blamejs/examples/wiki/routes/integration.js +230 -0
  127. package/lib/vendor/blamejs/examples/wiki/routes/pages.js +266 -0
  128. package/lib/vendor/blamejs/examples/wiki/scripts/backfill-module-metadata.js +214 -0
  129. package/lib/vendor/blamejs/examples/wiki/seeders/prod/0001-default-pages.js +35 -0
  130. package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/_index.js +34 -0
  131. package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/api.js +76 -0
  132. package/lib/vendor/blamejs/examples/wiki/server.js +129 -0
  133. package/lib/vendor/blamejs/examples/wiki/site.config.js +197 -0
  134. package/lib/vendor/blamejs/examples/wiki/snippets/README.md +38 -0
  135. package/lib/vendor/blamejs/examples/wiki/snippets/auth/password-hash.example.js +15 -0
  136. package/lib/vendor/blamejs/examples/wiki/src/editor.js +103 -0
  137. package/lib/vendor/blamejs/examples/wiki/src/wiki.js +349 -0
  138. package/lib/vendor/blamejs/examples/wiki/test/AUDIT.md +155 -0
  139. package/lib/vendor/blamejs/examples/wiki/test/codebase-patterns.test.js +594 -0
  140. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +741 -0
  141. package/lib/vendor/blamejs/examples/wiki/test/find-missing-pages.js +254 -0
  142. package/lib/vendor/blamejs/examples/wiki/test/integration.js +391 -0
  143. package/lib/vendor/blamejs/examples/wiki/test/validate-cli-snapshot.js +379 -0
  144. package/lib/vendor/blamejs/examples/wiki/test/validate-env-snapshot.js +346 -0
  145. package/lib/vendor/blamejs/examples/wiki/test/validate-nav-coverage.js +212 -0
  146. package/lib/vendor/blamejs/examples/wiki/test/validate-site-coverage.js +252 -0
  147. package/lib/vendor/blamejs/examples/wiki/test/validate-source-comment-blocks.js +107 -0
  148. package/lib/vendor/blamejs/examples/wiki/views/_layout.html +115 -0
  149. package/lib/vendor/blamejs/examples/wiki/views/admin/api-keys.html +51 -0
  150. package/lib/vendor/blamejs/examples/wiki/views/admin/dashboard.html +22 -0
  151. package/lib/vendor/blamejs/examples/wiki/views/admin/edit.html +17 -0
  152. package/lib/vendor/blamejs/examples/wiki/views/home.html +85 -0
  153. package/lib/vendor/blamejs/examples/wiki/views/login.html +18 -0
  154. package/lib/vendor/blamejs/examples/wiki/views/page.html +5 -0
  155. package/lib/vendor/blamejs/examples/wiki/views/partials/nav.html +13 -0
  156. package/lib/vendor/blamejs/examples/wiki/views/search.html +19 -0
  157. package/lib/vendor/blamejs/examples/wiki/wiki.config.js +15 -0
  158. package/lib/vendor/blamejs/fuzz/README.md +137 -0
  159. package/lib/vendor/blamejs/fuzz/_expected.js +35 -0
  160. package/lib/vendor/blamejs/fuzz/guard-agent-registry.fuzz.js +22 -0
  161. package/lib/vendor/blamejs/fuzz/guard-csv.fuzz.js +16 -0
  162. package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/01-basic.csv +3 -0
  163. package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/02-formula.csv +1 -0
  164. package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/03-hyperlink.csv +1 -0
  165. package/lib/vendor/blamejs/fuzz/guard-dsn.fuzz.js +22 -0
  166. package/lib/vendor/blamejs/fuzz/guard-email.fuzz.js +16 -0
  167. package/lib/vendor/blamejs/fuzz/guard-email_seed_corpus/01-basic.eml +5 -0
  168. package/lib/vendor/blamejs/fuzz/guard-envelope.fuzz.js +24 -0
  169. package/lib/vendor/blamejs/fuzz/guard-event-bus-payload.fuzz.js +24 -0
  170. package/lib/vendor/blamejs/fuzz/guard-event-bus-topic.fuzz.js +20 -0
  171. package/lib/vendor/blamejs/fuzz/guard-html.fuzz.js +16 -0
  172. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/01-basic.html +1 -0
  173. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/02-script.html +1 -0
  174. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/03-event.html +1 -0
  175. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/04-jsurl.html +1 -0
  176. package/lib/vendor/blamejs/fuzz/guard-idempotency-key.fuzz.js +20 -0
  177. package/lib/vendor/blamejs/fuzz/guard-imap-command.fuzz.js +35 -0
  178. package/lib/vendor/blamejs/fuzz/guard-jmap.fuzz.js +41 -0
  179. package/lib/vendor/blamejs/fuzz/guard-json.fuzz.js +16 -0
  180. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/01-basic.json +1 -0
  181. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/02-proto.json +1 -0
  182. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/03-dupkey.json +1 -0
  183. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/04-nan.json +1 -0
  184. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/05-bom.json +1 -0
  185. package/lib/vendor/blamejs/fuzz/guard-list-id.fuzz.js +21 -0
  186. package/lib/vendor/blamejs/fuzz/guard-list-unsubscribe.fuzz.js +25 -0
  187. package/lib/vendor/blamejs/fuzz/guard-mail-compose.fuzz.js +22 -0
  188. package/lib/vendor/blamejs/fuzz/guard-mail-move.fuzz.js +22 -0
  189. package/lib/vendor/blamejs/fuzz/guard-mail-query.fuzz.js +27 -0
  190. package/lib/vendor/blamejs/fuzz/guard-mail-reply.fuzz.js +23 -0
  191. package/lib/vendor/blamejs/fuzz/guard-mail-sieve.fuzz.js +36 -0
  192. package/lib/vendor/blamejs/fuzz/guard-managesieve-command.fuzz.js +26 -0
  193. package/lib/vendor/blamejs/fuzz/guard-markdown.fuzz.js +16 -0
  194. package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/01-basic.md +2 -0
  195. package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/02-jsurl.md +1 -0
  196. package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/03-jsimg.md +1 -0
  197. package/lib/vendor/blamejs/fuzz/guard-message-id.fuzz.js +26 -0
  198. package/lib/vendor/blamejs/fuzz/guard-pop3-command.fuzz.js +23 -0
  199. package/lib/vendor/blamejs/fuzz/guard-posture-chain.fuzz.js +22 -0
  200. package/lib/vendor/blamejs/fuzz/guard-saga-config.fuzz.js +32 -0
  201. package/lib/vendor/blamejs/fuzz/guard-smtp-command.fuzz.js +27 -0
  202. package/lib/vendor/blamejs/fuzz/guard-snapshot-envelope.fuzz.js +22 -0
  203. package/lib/vendor/blamejs/fuzz/guard-stream-args.fuzz.js +22 -0
  204. package/lib/vendor/blamejs/fuzz/guard-svg.fuzz.js +16 -0
  205. package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/01-basic.svg +1 -0
  206. package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/02-script.svg +1 -0
  207. package/lib/vendor/blamejs/fuzz/guard-tenant-id.fuzz.js +20 -0
  208. package/lib/vendor/blamejs/fuzz/guard-trace-context.fuzz.js +30 -0
  209. package/lib/vendor/blamejs/fuzz/guard-xml.fuzz.js +16 -0
  210. package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/01-basic.xml +1 -0
  211. package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/02-xxe.xml +1 -0
  212. package/lib/vendor/blamejs/fuzz/guard-yaml.fuzz.js +16 -0
  213. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/01-basic.yaml +2 -0
  214. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/02-anchor.yaml +2 -0
  215. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/03-norway.yaml +1 -0
  216. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/04-multidoc.yaml +4 -0
  217. package/lib/vendor/blamejs/fuzz/parsers__safe-ini.fuzz.js +16 -0
  218. package/lib/vendor/blamejs/fuzz/parsers__safe-ini_seed_corpus/01-basic.ini +2 -0
  219. package/lib/vendor/blamejs/fuzz/parsers__safe-toml.fuzz.js +16 -0
  220. package/lib/vendor/blamejs/fuzz/parsers__safe-toml_seed_corpus/01-basic.toml +4 -0
  221. package/lib/vendor/blamejs/fuzz/parsers__safe-xml.fuzz.js +16 -0
  222. package/lib/vendor/blamejs/fuzz/parsers__safe-xml_seed_corpus/01-basic.xml +1 -0
  223. package/lib/vendor/blamejs/fuzz/parsers__safe-yaml.fuzz.js +16 -0
  224. package/lib/vendor/blamejs/fuzz/parsers__safe-yaml_seed_corpus/01-basic.yaml +4 -0
  225. package/lib/vendor/blamejs/fuzz/safe-decompress.fuzz.js +49 -0
  226. package/lib/vendor/blamejs/fuzz/safe-dns.fuzz.js +29 -0
  227. package/lib/vendor/blamejs/fuzz/safe-ical.fuzz.js +16 -0
  228. package/lib/vendor/blamejs/fuzz/safe-icap.fuzz.js +42 -0
  229. package/lib/vendor/blamejs/fuzz/safe-json.fuzz.js +25 -0
  230. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/01-object.txt +1 -0
  231. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/02-array.txt +1 -0
  232. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/03-string.txt +1 -0
  233. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/04-proto.txt +1 -0
  234. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/05-deep.txt +1 -0
  235. package/lib/vendor/blamejs/fuzz/safe-jsonpath.fuzz.js +16 -0
  236. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/01-basic.txt +1 -0
  237. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/02-filter.txt +1 -0
  238. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/03-deepscan.txt +1 -0
  239. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/04-slice.txt +1 -0
  240. package/lib/vendor/blamejs/fuzz/safe-mime.fuzz.js +27 -0
  241. package/lib/vendor/blamejs/fuzz/safe-mount-info.fuzz.js +33 -0
  242. package/lib/vendor/blamejs/fuzz/safe-sieve.fuzz.js +28 -0
  243. package/lib/vendor/blamejs/fuzz/safe-smtp.fuzz.js +64 -0
  244. package/lib/vendor/blamejs/fuzz/safe-url.fuzz.js +16 -0
  245. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/01-basic.txt +1 -0
  246. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/02-userinfo.txt +1 -0
  247. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/03-dangerous.txt +1 -0
  248. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/04-data.txt +1 -0
  249. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/05-ipv6.txt +1 -0
  250. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/06-idn.txt +1 -0
  251. package/lib/vendor/blamejs/fuzz/safe-vcard.fuzz.js +16 -0
  252. package/lib/vendor/blamejs/index.js +678 -0
  253. package/lib/vendor/blamejs/keys/release-pqc-pub.json +7 -0
  254. package/lib/vendor/blamejs/lib/_test/crypto-fixtures.js +67 -0
  255. package/lib/vendor/blamejs/lib/a2a-tasks.js +598 -0
  256. package/lib/vendor/blamejs/lib/a2a.js +407 -0
  257. package/lib/vendor/blamejs/lib/acme.js +1448 -0
  258. package/lib/vendor/blamejs/lib/agent-audit.js +45 -0
  259. package/lib/vendor/blamejs/lib/agent-event-bus.js +382 -0
  260. package/lib/vendor/blamejs/lib/agent-idempotency.js +497 -0
  261. package/lib/vendor/blamejs/lib/agent-orchestrator.js +717 -0
  262. package/lib/vendor/blamejs/lib/agent-posture-chain.js +366 -0
  263. package/lib/vendor/blamejs/lib/agent-saga.js +321 -0
  264. package/lib/vendor/blamejs/lib/agent-snapshot.js +676 -0
  265. package/lib/vendor/blamejs/lib/agent-stream.js +269 -0
  266. package/lib/vendor/blamejs/lib/agent-tenant.js +632 -0
  267. package/lib/vendor/blamejs/lib/agent-trace.js +281 -0
  268. package/lib/vendor/blamejs/lib/ai-adverse-decision.js +184 -0
  269. package/lib/vendor/blamejs/lib/ai-content-detect.js +268 -0
  270. package/lib/vendor/blamejs/lib/ai-input.js +201 -0
  271. package/lib/vendor/blamejs/lib/ai-model-manifest.js +363 -0
  272. package/lib/vendor/blamejs/lib/ai-pref.js +340 -0
  273. package/lib/vendor/blamejs/lib/api-key.js +721 -0
  274. package/lib/vendor/blamejs/lib/api-snapshot.js +458 -0
  275. package/lib/vendor/blamejs/lib/app-shutdown.js +557 -0
  276. package/lib/vendor/blamejs/lib/app.js +365 -0
  277. package/lib/vendor/blamejs/lib/archive.js +547 -0
  278. package/lib/vendor/blamejs/lib/arg-parser.js +697 -0
  279. package/lib/vendor/blamejs/lib/argon2-builtin.js +173 -0
  280. package/lib/vendor/blamejs/lib/asn1-der.js +424 -0
  281. package/lib/vendor/blamejs/lib/asyncapi-bindings.js +160 -0
  282. package/lib/vendor/blamejs/lib/asyncapi-traits.js +143 -0
  283. package/lib/vendor/blamejs/lib/asyncapi.js +575 -0
  284. package/lib/vendor/blamejs/lib/atomic-file.js +1023 -0
  285. package/lib/vendor/blamejs/lib/audit-chain.js +266 -0
  286. package/lib/vendor/blamejs/lib/audit-daily-review.js +389 -0
  287. package/lib/vendor/blamejs/lib/audit-sign.js +751 -0
  288. package/lib/vendor/blamejs/lib/audit-tools.js +1113 -0
  289. package/lib/vendor/blamejs/lib/audit.js +1671 -0
  290. package/lib/vendor/blamejs/lib/auth/aal.js +169 -0
  291. package/lib/vendor/blamejs/lib/auth/access-lock.js +220 -0
  292. package/lib/vendor/blamejs/lib/auth/acr-vocabulary.js +265 -0
  293. package/lib/vendor/blamejs/lib/auth/ato-kill-switch.js +112 -0
  294. package/lib/vendor/blamejs/lib/auth/auth-time-tracker.js +111 -0
  295. package/lib/vendor/blamejs/lib/auth/bot-challenge.js +573 -0
  296. package/lib/vendor/blamejs/lib/auth/ciba.js +637 -0
  297. package/lib/vendor/blamejs/lib/auth/dpop.js +516 -0
  298. package/lib/vendor/blamejs/lib/auth/elevation-grant.js +306 -0
  299. package/lib/vendor/blamejs/lib/auth/fal.js +229 -0
  300. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +681 -0
  301. package/lib/vendor/blamejs/lib/auth/jwt-external.js +519 -0
  302. package/lib/vendor/blamejs/lib/auth/jwt.js +430 -0
  303. package/lib/vendor/blamejs/lib/auth/lockout.js +449 -0
  304. package/lib/vendor/blamejs/lib/auth/oauth.js +2141 -0
  305. package/lib/vendor/blamejs/lib/auth/oid4vci.js +657 -0
  306. package/lib/vendor/blamejs/lib/auth/oid4vp.js +531 -0
  307. package/lib/vendor/blamejs/lib/auth/openid-federation.js +600 -0
  308. package/lib/vendor/blamejs/lib/auth/passkey.js +676 -0
  309. package/lib/vendor/blamejs/lib/auth/password.js +693 -0
  310. package/lib/vendor/blamejs/lib/auth/saml.js +2109 -0
  311. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-disclosure.js +95 -0
  312. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +225 -0
  313. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +197 -0
  314. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +728 -0
  315. package/lib/vendor/blamejs/lib/auth/status-list.js +272 -0
  316. package/lib/vendor/blamejs/lib/auth/step-up-policy.js +335 -0
  317. package/lib/vendor/blamejs/lib/auth/step-up.js +454 -0
  318. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +505 -0
  319. package/lib/vendor/blamejs/lib/auth-header.js +148 -0
  320. package/lib/vendor/blamejs/lib/backup/bundle.js +265 -0
  321. package/lib/vendor/blamejs/lib/backup/crypto.js +176 -0
  322. package/lib/vendor/blamejs/lib/backup/index.js +1001 -0
  323. package/lib/vendor/blamejs/lib/backup/manifest.js +443 -0
  324. package/lib/vendor/blamejs/lib/boot-gates.js +174 -0
  325. package/lib/vendor/blamejs/lib/breach-deadline.js +272 -0
  326. package/lib/vendor/blamejs/lib/break-glass.js +1753 -0
  327. package/lib/vendor/blamejs/lib/budr.js +205 -0
  328. package/lib/vendor/blamejs/lib/bundler.js +461 -0
  329. package/lib/vendor/blamejs/lib/cache-redis.js +256 -0
  330. package/lib/vendor/blamejs/lib/cache-status.js +288 -0
  331. package/lib/vendor/blamejs/lib/cache.js +1331 -0
  332. package/lib/vendor/blamejs/lib/calendar.js +1240 -0
  333. package/lib/vendor/blamejs/lib/canonical-json.js +143 -0
  334. package/lib/vendor/blamejs/lib/cdn-cache-control.js +473 -0
  335. package/lib/vendor/blamejs/lib/cert.js +763 -0
  336. package/lib/vendor/blamejs/lib/chain-writer.js +259 -0
  337. package/lib/vendor/blamejs/lib/circuit-breaker.js +101 -0
  338. package/lib/vendor/blamejs/lib/cli-helpers.js +237 -0
  339. package/lib/vendor/blamejs/lib/cli.js +2328 -0
  340. package/lib/vendor/blamejs/lib/client-hints.js +318 -0
  341. package/lib/vendor/blamejs/lib/cloud-events.js +277 -0
  342. package/lib/vendor/blamejs/lib/cluster-provider-db.js +317 -0
  343. package/lib/vendor/blamejs/lib/cluster-storage.js +351 -0
  344. package/lib/vendor/blamejs/lib/cluster.js +1017 -0
  345. package/lib/vendor/blamejs/lib/cms-codec.js +826 -0
  346. package/lib/vendor/blamejs/lib/codepoint-class.js +262 -0
  347. package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +190 -0
  348. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +205 -0
  349. package/lib/vendor/blamejs/lib/compliance-ai-act-risk.js +189 -0
  350. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +200 -0
  351. package/lib/vendor/blamejs/lib/compliance-ai-act.js +821 -0
  352. package/lib/vendor/blamejs/lib/compliance-eaa.js +204 -0
  353. package/lib/vendor/blamejs/lib/compliance-sanctions-aliases.js +167 -0
  354. package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +206 -0
  355. package/lib/vendor/blamejs/lib/compliance-sanctions-fuzzy.js +297 -0
  356. package/lib/vendor/blamejs/lib/compliance-sanctions.js +569 -0
  357. package/lib/vendor/blamejs/lib/compliance.js +1558 -0
  358. package/lib/vendor/blamejs/lib/config-drift.js +426 -0
  359. package/lib/vendor/blamejs/lib/config.js +446 -0
  360. package/lib/vendor/blamejs/lib/consent.js +369 -0
  361. package/lib/vendor/blamejs/lib/constants.js +209 -0
  362. package/lib/vendor/blamejs/lib/content-credentials.js +704 -0
  363. package/lib/vendor/blamejs/lib/cookies.js +560 -0
  364. package/lib/vendor/blamejs/lib/cra-report.js +299 -0
  365. package/lib/vendor/blamejs/lib/credential-hash.js +394 -0
  366. package/lib/vendor/blamejs/lib/crypto-field.js +1017 -0
  367. package/lib/vendor/blamejs/lib/crypto-hpke-pq.js +187 -0
  368. package/lib/vendor/blamejs/lib/crypto-hpke.js +256 -0
  369. package/lib/vendor/blamejs/lib/crypto.js +1908 -0
  370. package/lib/vendor/blamejs/lib/csp.js +271 -0
  371. package/lib/vendor/blamejs/lib/csv.js +418 -0
  372. package/lib/vendor/blamejs/lib/daemon.js +481 -0
  373. package/lib/vendor/blamejs/lib/dark-patterns.js +488 -0
  374. package/lib/vendor/blamejs/lib/data-act.js +328 -0
  375. package/lib/vendor/blamejs/lib/db-collection.js +587 -0
  376. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +267 -0
  377. package/lib/vendor/blamejs/lib/db-declare-view.js +420 -0
  378. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +333 -0
  379. package/lib/vendor/blamejs/lib/db-query.js +802 -0
  380. package/lib/vendor/blamejs/lib/db-role-context.js +50 -0
  381. package/lib/vendor/blamejs/lib/db-schema.js +322 -0
  382. package/lib/vendor/blamejs/lib/db.js +3111 -0
  383. package/lib/vendor/blamejs/lib/dbsc.js +299 -0
  384. package/lib/vendor/blamejs/lib/ddl-change-control.js +523 -0
  385. package/lib/vendor/blamejs/lib/deprecate.js +377 -0
  386. package/lib/vendor/blamejs/lib/dev.js +405 -0
  387. package/lib/vendor/blamejs/lib/dora.js +402 -0
  388. package/lib/vendor/blamejs/lib/dr-runbook.js +368 -0
  389. package/lib/vendor/blamejs/lib/dsr.js +1188 -0
  390. package/lib/vendor/blamejs/lib/dual-control.js +526 -0
  391. package/lib/vendor/blamejs/lib/early-hints.js +212 -0
  392. package/lib/vendor/blamejs/lib/error-page.js +420 -0
  393. package/lib/vendor/blamejs/lib/events.js +214 -0
  394. package/lib/vendor/blamejs/lib/external-db-migrate.js +659 -0
  395. package/lib/vendor/blamejs/lib/external-db.js +1877 -0
  396. package/lib/vendor/blamejs/lib/fapi2.js +394 -0
  397. package/lib/vendor/blamejs/lib/fda-21cfr11.js +395 -0
  398. package/lib/vendor/blamejs/lib/fdx.js +370 -0
  399. package/lib/vendor/blamejs/lib/fedcm.js +264 -0
  400. package/lib/vendor/blamejs/lib/file-type.js +360 -0
  401. package/lib/vendor/blamejs/lib/file-upload.js +1256 -0
  402. package/lib/vendor/blamejs/lib/flag-cache.js +136 -0
  403. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +135 -0
  404. package/lib/vendor/blamejs/lib/flag-providers.js +279 -0
  405. package/lib/vendor/blamejs/lib/flag-targeting.js +210 -0
  406. package/lib/vendor/blamejs/lib/flag.js +346 -0
  407. package/lib/vendor/blamejs/lib/forms.js +525 -0
  408. package/lib/vendor/blamejs/lib/framework-error.js +724 -0
  409. package/lib/vendor/blamejs/lib/framework-schema.js +845 -0
  410. package/lib/vendor/blamejs/lib/framework-sha1-hibp.js +34 -0
  411. package/lib/vendor/blamejs/lib/fsm.js +469 -0
  412. package/lib/vendor/blamejs/lib/gate-contract.js +1661 -0
  413. package/lib/vendor/blamejs/lib/gdpr-ropa.js +261 -0
  414. package/lib/vendor/blamejs/lib/graphql-federation.js +234 -0
  415. package/lib/vendor/blamejs/lib/guard-agent-registry.js +179 -0
  416. package/lib/vendor/blamejs/lib/guard-all.js +555 -0
  417. package/lib/vendor/blamejs/lib/guard-archive.js +901 -0
  418. package/lib/vendor/blamejs/lib/guard-auth.js +451 -0
  419. package/lib/vendor/blamejs/lib/guard-cidr.js +676 -0
  420. package/lib/vendor/blamejs/lib/guard-csv.js +1176 -0
  421. package/lib/vendor/blamejs/lib/guard-domain.js +814 -0
  422. package/lib/vendor/blamejs/lib/guard-dsn.js +382 -0
  423. package/lib/vendor/blamejs/lib/guard-email.js +951 -0
  424. package/lib/vendor/blamejs/lib/guard-envelope.js +294 -0
  425. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +217 -0
  426. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +150 -0
  427. package/lib/vendor/blamejs/lib/guard-filename.js +956 -0
  428. package/lib/vendor/blamejs/lib/guard-graphql.js +731 -0
  429. package/lib/vendor/blamejs/lib/guard-html-wcag-aria.js +164 -0
  430. package/lib/vendor/blamejs/lib/guard-html-wcag-forms.js +144 -0
  431. package/lib/vendor/blamejs/lib/guard-html-wcag-tables.js +154 -0
  432. package/lib/vendor/blamejs/lib/guard-html-wcag-tagwalk.js +44 -0
  433. package/lib/vendor/blamejs/lib/guard-html-wcag.js +470 -0
  434. package/lib/vendor/blamejs/lib/guard-html.js +1209 -0
  435. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +151 -0
  436. package/lib/vendor/blamejs/lib/guard-image.js +584 -0
  437. package/lib/vendor/blamejs/lib/guard-imap-command.js +337 -0
  438. package/lib/vendor/blamejs/lib/guard-jmap.js +321 -0
  439. package/lib/vendor/blamejs/lib/guard-json.js +935 -0
  440. package/lib/vendor/blamejs/lib/guard-jsonpath.js +512 -0
  441. package/lib/vendor/blamejs/lib/guard-jwt.js +772 -0
  442. package/lib/vendor/blamejs/lib/guard-list-id.js +318 -0
  443. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +412 -0
  444. package/lib/vendor/blamejs/lib/guard-mail-compose.js +282 -0
  445. package/lib/vendor/blamejs/lib/guard-mail-move.js +202 -0
  446. package/lib/vendor/blamejs/lib/guard-mail-query.js +310 -0
  447. package/lib/vendor/blamejs/lib/guard-mail-reply.js +172 -0
  448. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +207 -0
  449. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +566 -0
  450. package/lib/vendor/blamejs/lib/guard-markdown.js +768 -0
  451. package/lib/vendor/blamejs/lib/guard-message-id.js +267 -0
  452. package/lib/vendor/blamejs/lib/guard-mime.js +609 -0
  453. package/lib/vendor/blamejs/lib/guard-oauth.js +650 -0
  454. package/lib/vendor/blamejs/lib/guard-pdf.js +569 -0
  455. package/lib/vendor/blamejs/lib/guard-pop3-command.js +317 -0
  456. package/lib/vendor/blamejs/lib/guard-posture-chain.js +201 -0
  457. package/lib/vendor/blamejs/lib/guard-regex.js +632 -0
  458. package/lib/vendor/blamejs/lib/guard-saga-config.js +157 -0
  459. package/lib/vendor/blamejs/lib/guard-shell.js +522 -0
  460. package/lib/vendor/blamejs/lib/guard-smtp-command.js +594 -0
  461. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +168 -0
  462. package/lib/vendor/blamejs/lib/guard-stream-args.js +166 -0
  463. package/lib/vendor/blamejs/lib/guard-svg.js +1163 -0
  464. package/lib/vendor/blamejs/lib/guard-template.js +490 -0
  465. package/lib/vendor/blamejs/lib/guard-tenant-id.js +138 -0
  466. package/lib/vendor/blamejs/lib/guard-time.js +586 -0
  467. package/lib/vendor/blamejs/lib/guard-trace-context.js +172 -0
  468. package/lib/vendor/blamejs/lib/guard-uuid.js +548 -0
  469. package/lib/vendor/blamejs/lib/guard-xml.js +666 -0
  470. package/lib/vendor/blamejs/lib/guard-yaml.js +726 -0
  471. package/lib/vendor/blamejs/lib/hal.js +125 -0
  472. package/lib/vendor/blamejs/lib/handlers.js +350 -0
  473. package/lib/vendor/blamejs/lib/honeytoken.js +168 -0
  474. package/lib/vendor/blamejs/lib/html-balance.js +347 -0
  475. package/lib/vendor/blamejs/lib/http-client-cache.js +923 -0
  476. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +519 -0
  477. package/lib/vendor/blamejs/lib/http-client.js +2152 -0
  478. package/lib/vendor/blamejs/lib/http-message-signature.js +589 -0
  479. package/lib/vendor/blamejs/lib/http2-teardown.js +34 -0
  480. package/lib/vendor/blamejs/lib/i18n-messageformat.js +398 -0
  481. package/lib/vendor/blamejs/lib/i18n.js +931 -0
  482. package/lib/vendor/blamejs/lib/iab-mspa.js +257 -0
  483. package/lib/vendor/blamejs/lib/iab-tcf.js +461 -0
  484. package/lib/vendor/blamejs/lib/importmap-integrity.js +90 -0
  485. package/lib/vendor/blamejs/lib/inbox.js +435 -0
  486. package/lib/vendor/blamejs/lib/incident-report.js +314 -0
  487. package/lib/vendor/blamejs/lib/ip-utils.js +102 -0
  488. package/lib/vendor/blamejs/lib/jobs.js +185 -0
  489. package/lib/vendor/blamejs/lib/jose-jwe-experimental.js +228 -0
  490. package/lib/vendor/blamejs/lib/jsonapi.js +230 -0
  491. package/lib/vendor/blamejs/lib/keychain.js +865 -0
  492. package/lib/vendor/blamejs/lib/lazy-require.js +48 -0
  493. package/lib/vendor/blamejs/lib/legal-hold.js +374 -0
  494. package/lib/vendor/blamejs/lib/local-db-thin.js +321 -0
  495. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +369 -0
  496. package/lib/vendor/blamejs/lib/log-stream-local.js +146 -0
  497. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +410 -0
  498. package/lib/vendor/blamejs/lib/log-stream-otlp.js +286 -0
  499. package/lib/vendor/blamejs/lib/log-stream-syslog.js +310 -0
  500. package/lib/vendor/blamejs/lib/log-stream-webhook.js +199 -0
  501. package/lib/vendor/blamejs/lib/log-stream.js +584 -0
  502. package/lib/vendor/blamejs/lib/log.js +625 -0
  503. package/lib/vendor/blamejs/lib/lro.js +200 -0
  504. package/lib/vendor/blamejs/lib/mail-agent.js +786 -0
  505. package/lib/vendor/blamejs/lib/mail-arc-sign.js +417 -0
  506. package/lib/vendor/blamejs/lib/mail-arf.js +343 -0
  507. package/lib/vendor/blamejs/lib/mail-auth.js +2144 -0
  508. package/lib/vendor/blamejs/lib/mail-bimi.js +1047 -0
  509. package/lib/vendor/blamejs/lib/mail-bounce.js +955 -0
  510. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +1286 -0
  511. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +789 -0
  512. package/lib/vendor/blamejs/lib/mail-crypto.js +108 -0
  513. package/lib/vendor/blamejs/lib/mail-dav.js +1224 -0
  514. package/lib/vendor/blamejs/lib/mail-deploy.js +1119 -0
  515. package/lib/vendor/blamejs/lib/mail-dkim.js +1250 -0
  516. package/lib/vendor/blamejs/lib/mail-greylist.js +448 -0
  517. package/lib/vendor/blamejs/lib/mail-helo.js +473 -0
  518. package/lib/vendor/blamejs/lib/mail-journal.js +435 -0
  519. package/lib/vendor/blamejs/lib/mail-mdn.js +424 -0
  520. package/lib/vendor/blamejs/lib/mail-rbl.js +392 -0
  521. package/lib/vendor/blamejs/lib/mail-require-tls.js +198 -0
  522. package/lib/vendor/blamejs/lib/mail-scan.js +502 -0
  523. package/lib/vendor/blamejs/lib/mail-send-deliver.js +629 -0
  524. package/lib/vendor/blamejs/lib/mail-server-imap.js +1858 -0
  525. package/lib/vendor/blamejs/lib/mail-server-jmap.js +1565 -0
  526. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +908 -0
  527. package/lib/vendor/blamejs/lib/mail-server-mx.js +969 -0
  528. package/lib/vendor/blamejs/lib/mail-server-pop3.js +915 -0
  529. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +315 -0
  530. package/lib/vendor/blamejs/lib/mail-server-registry.js +378 -0
  531. package/lib/vendor/blamejs/lib/mail-server-submission.js +1396 -0
  532. package/lib/vendor/blamejs/lib/mail-server-tls.js +445 -0
  533. package/lib/vendor/blamejs/lib/mail-sieve.js +557 -0
  534. package/lib/vendor/blamejs/lib/mail-spam-score.js +284 -0
  535. package/lib/vendor/blamejs/lib/mail-srs.js +248 -0
  536. package/lib/vendor/blamejs/lib/mail-store-fts.js +394 -0
  537. package/lib/vendor/blamejs/lib/mail-store.js +929 -0
  538. package/lib/vendor/blamejs/lib/mail-unsubscribe.js +400 -0
  539. package/lib/vendor/blamejs/lib/mail.js +1971 -0
  540. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +473 -0
  541. package/lib/vendor/blamejs/lib/mcp.js +950 -0
  542. package/lib/vendor/blamejs/lib/metrics.js +1503 -0
  543. package/lib/vendor/blamejs/lib/middleware/age-gate.js +177 -0
  544. package/lib/vendor/blamejs/lib/middleware/ai-act-disclosure.js +203 -0
  545. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +981 -0
  546. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +137 -0
  547. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +171 -0
  548. package/lib/vendor/blamejs/lib/middleware/attach-user.js +220 -0
  549. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +293 -0
  550. package/lib/vendor/blamejs/lib/middleware/body-parser.js +1519 -0
  551. package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +183 -0
  552. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +217 -0
  553. package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +122 -0
  554. package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +355 -0
  555. package/lib/vendor/blamejs/lib/middleware/compression.js +489 -0
  556. package/lib/vendor/blamejs/lib/middleware/cookies.js +130 -0
  557. package/lib/vendor/blamejs/lib/middleware/cors.js +386 -0
  558. package/lib/vendor/blamejs/lib/middleware/csp-nonce.js +388 -0
  559. package/lib/vendor/blamejs/lib/middleware/csp-report.js +167 -0
  560. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +499 -0
  561. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +243 -0
  562. package/lib/vendor/blamejs/lib/middleware/db-role-for.js +304 -0
  563. package/lib/vendor/blamejs/lib/middleware/dpop.js +402 -0
  564. package/lib/vendor/blamejs/lib/middleware/error-handler.js +69 -0
  565. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +168 -0
  566. package/lib/vendor/blamejs/lib/middleware/flag-context.js +110 -0
  567. package/lib/vendor/blamejs/lib/middleware/gpc.js +153 -0
  568. package/lib/vendor/blamejs/lib/middleware/headers.js +242 -0
  569. package/lib/vendor/blamejs/lib/middleware/health.js +438 -0
  570. package/lib/vendor/blamejs/lib/middleware/host-allowlist.js +189 -0
  571. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +964 -0
  572. package/lib/vendor/blamejs/lib/middleware/index.js +183 -0
  573. package/lib/vendor/blamejs/lib/middleware/nel.js +214 -0
  574. package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +237 -0
  575. package/lib/vendor/blamejs/lib/middleware/no-cache.js +106 -0
  576. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +177 -0
  577. package/lib/vendor/blamejs/lib/middleware/protected-resource-metadata.js +277 -0
  578. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +556 -0
  579. package/lib/vendor/blamejs/lib/middleware/request-id.js +79 -0
  580. package/lib/vendor/blamejs/lib/middleware/request-log.js +205 -0
  581. package/lib/vendor/blamejs/lib/middleware/require-aal.js +138 -0
  582. package/lib/vendor/blamejs/lib/middleware/require-auth.js +144 -0
  583. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +290 -0
  584. package/lib/vendor/blamejs/lib/middleware/require-content-type.js +113 -0
  585. package/lib/vendor/blamejs/lib/middleware/require-methods.js +97 -0
  586. package/lib/vendor/blamejs/lib/middleware/require-mtls.js +212 -0
  587. package/lib/vendor/blamejs/lib/middleware/require-step-up.js +226 -0
  588. package/lib/vendor/blamejs/lib/middleware/scim-server.js +375 -0
  589. package/lib/vendor/blamejs/lib/middleware/security-headers.js +285 -0
  590. package/lib/vendor/blamejs/lib/middleware/security-txt.js +170 -0
  591. package/lib/vendor/blamejs/lib/middleware/span-http-server.js +280 -0
  592. package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +323 -0
  593. package/lib/vendor/blamejs/lib/middleware/sse.js +200 -0
  594. package/lib/vendor/blamejs/lib/middleware/trace-log-correlation.js +167 -0
  595. package/lib/vendor/blamejs/lib/middleware/trace-propagate.js +148 -0
  596. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +749 -0
  597. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +164 -0
  598. package/lib/vendor/blamejs/lib/migration-files.js +37 -0
  599. package/lib/vendor/blamejs/lib/migrations.js +385 -0
  600. package/lib/vendor/blamejs/lib/mime-parse.js +198 -0
  601. package/lib/vendor/blamejs/lib/money.js +699 -0
  602. package/lib/vendor/blamejs/lib/mtls-ca.js +572 -0
  603. package/lib/vendor/blamejs/lib/mtls-engine-default.js +501 -0
  604. package/lib/vendor/blamejs/lib/network-byte-quota.js +308 -0
  605. package/lib/vendor/blamejs/lib/network-dns-resolver.js +533 -0
  606. package/lib/vendor/blamejs/lib/network-dns.js +1930 -0
  607. package/lib/vendor/blamejs/lib/network-heartbeat.js +425 -0
  608. package/lib/vendor/blamejs/lib/network-nts.js +574 -0
  609. package/lib/vendor/blamejs/lib/network-proxy.js +265 -0
  610. package/lib/vendor/blamejs/lib/network-smtp-policy.js +836 -0
  611. package/lib/vendor/blamejs/lib/network-tls.js +3126 -0
  612. package/lib/vendor/blamejs/lib/network.js +346 -0
  613. package/lib/vendor/blamejs/lib/nis2-report.js +181 -0
  614. package/lib/vendor/blamejs/lib/nist-crosswalk.js +293 -0
  615. package/lib/vendor/blamejs/lib/nonce-store.js +177 -0
  616. package/lib/vendor/blamejs/lib/notify.js +683 -0
  617. package/lib/vendor/blamejs/lib/ntp-check.js +458 -0
  618. package/lib/vendor/blamejs/lib/numeric-bounds.js +111 -0
  619. package/lib/vendor/blamejs/lib/numeric-checks.js +40 -0
  620. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +349 -0
  621. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +488 -0
  622. package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +351 -0
  623. package/lib/vendor/blamejs/lib/object-store/gcs.js +515 -0
  624. package/lib/vendor/blamejs/lib/object-store/http-put.js +153 -0
  625. package/lib/vendor/blamejs/lib/object-store/http-request.js +38 -0
  626. package/lib/vendor/blamejs/lib/object-store/index.js +197 -0
  627. package/lib/vendor/blamejs/lib/object-store/local.js +163 -0
  628. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +1133 -0
  629. package/lib/vendor/blamejs/lib/object-store/sigv4.js +957 -0
  630. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +420 -0
  631. package/lib/vendor/blamejs/lib/observability-tracer.js +395 -0
  632. package/lib/vendor/blamejs/lib/observability.js +720 -0
  633. package/lib/vendor/blamejs/lib/openapi-paths-builder.js +248 -0
  634. package/lib/vendor/blamejs/lib/openapi-schema-walk.js +192 -0
  635. package/lib/vendor/blamejs/lib/openapi-security.js +169 -0
  636. package/lib/vendor/blamejs/lib/openapi-yaml.js +154 -0
  637. package/lib/vendor/blamejs/lib/openapi.js +489 -0
  638. package/lib/vendor/blamejs/lib/otel-export.js +278 -0
  639. package/lib/vendor/blamejs/lib/outbox.js +547 -0
  640. package/lib/vendor/blamejs/lib/pagination.js +542 -0
  641. package/lib/vendor/blamejs/lib/parsers/index.js +91 -0
  642. package/lib/vendor/blamejs/lib/parsers/safe-env.js +642 -0
  643. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +293 -0
  644. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +784 -0
  645. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +390 -0
  646. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +1015 -0
  647. package/lib/vendor/blamejs/lib/permissions.js +793 -0
  648. package/lib/vendor/blamejs/lib/pick.js +105 -0
  649. package/lib/vendor/blamejs/lib/pqc-agent.js +351 -0
  650. package/lib/vendor/blamejs/lib/pqc-gate.js +279 -0
  651. package/lib/vendor/blamejs/lib/pqc-software.js +271 -0
  652. package/lib/vendor/blamejs/lib/problem-details.js +482 -0
  653. package/lib/vendor/blamejs/lib/process-spawn.js +196 -0
  654. package/lib/vendor/blamejs/lib/promise-pool.js +162 -0
  655. package/lib/vendor/blamejs/lib/protobuf-encoder.js +190 -0
  656. package/lib/vendor/blamejs/lib/protocol-dispatcher.js +161 -0
  657. package/lib/vendor/blamejs/lib/public-suffix.js +403 -0
  658. package/lib/vendor/blamejs/lib/pubsub-cluster.js +154 -0
  659. package/lib/vendor/blamejs/lib/pubsub-redis.js +167 -0
  660. package/lib/vendor/blamejs/lib/pubsub.js +463 -0
  661. package/lib/vendor/blamejs/lib/queue-local.js +476 -0
  662. package/lib/vendor/blamejs/lib/queue-redis.js +745 -0
  663. package/lib/vendor/blamejs/lib/queue-sqs.js +319 -0
  664. package/lib/vendor/blamejs/lib/queue.js +1016 -0
  665. package/lib/vendor/blamejs/lib/redact.js +1007 -0
  666. package/lib/vendor/blamejs/lib/redis-client.js +520 -0
  667. package/lib/vendor/blamejs/lib/render.js +285 -0
  668. package/lib/vendor/blamejs/lib/request-helpers.js +767 -0
  669. package/lib/vendor/blamejs/lib/resource-access-lock.js +116 -0
  670. package/lib/vendor/blamejs/lib/restore-bundle.js +340 -0
  671. package/lib/vendor/blamejs/lib/restore-rollback.js +365 -0
  672. package/lib/vendor/blamejs/lib/restore.js +409 -0
  673. package/lib/vendor/blamejs/lib/retention.js +640 -0
  674. package/lib/vendor/blamejs/lib/retry.js +523 -0
  675. package/lib/vendor/blamejs/lib/router.js +1289 -0
  676. package/lib/vendor/blamejs/lib/safe-async.js +1184 -0
  677. package/lib/vendor/blamejs/lib/safe-buffer.js +562 -0
  678. package/lib/vendor/blamejs/lib/safe-decompress.js +297 -0
  679. package/lib/vendor/blamejs/lib/safe-dns.js +665 -0
  680. package/lib/vendor/blamejs/lib/safe-ical.js +634 -0
  681. package/lib/vendor/blamejs/lib/safe-icap.js +502 -0
  682. package/lib/vendor/blamejs/lib/safe-json.js +946 -0
  683. package/lib/vendor/blamejs/lib/safe-jsonpath.js +285 -0
  684. package/lib/vendor/blamejs/lib/safe-mime.js +831 -0
  685. package/lib/vendor/blamejs/lib/safe-mount-info.js +306 -0
  686. package/lib/vendor/blamejs/lib/safe-path.js +254 -0
  687. package/lib/vendor/blamejs/lib/safe-redirect.js +106 -0
  688. package/lib/vendor/blamejs/lib/safe-schema.js +1810 -0
  689. package/lib/vendor/blamejs/lib/safe-sieve.js +684 -0
  690. package/lib/vendor/blamejs/lib/safe-smtp.js +185 -0
  691. package/lib/vendor/blamejs/lib/safe-sql.js +363 -0
  692. package/lib/vendor/blamejs/lib/safe-url.js +428 -0
  693. package/lib/vendor/blamejs/lib/safe-vcard.js +473 -0
  694. package/lib/vendor/blamejs/lib/sandbox-worker.js +135 -0
  695. package/lib/vendor/blamejs/lib/sandbox.js +358 -0
  696. package/lib/vendor/blamejs/lib/scheduler.js +827 -0
  697. package/lib/vendor/blamejs/lib/sd-notify.js +269 -0
  698. package/lib/vendor/blamejs/lib/sec-cyber.js +214 -0
  699. package/lib/vendor/blamejs/lib/security-assert.js +395 -0
  700. package/lib/vendor/blamejs/lib/seeders.js +620 -0
  701. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +309 -0
  702. package/lib/vendor/blamejs/lib/self-update.js +804 -0
  703. package/lib/vendor/blamejs/lib/server-timing.js +174 -0
  704. package/lib/vendor/blamejs/lib/session-device-binding.js +431 -0
  705. package/lib/vendor/blamejs/lib/session-stores.js +138 -0
  706. package/lib/vendor/blamejs/lib/session.js +1162 -0
  707. package/lib/vendor/blamejs/lib/slug.js +381 -0
  708. package/lib/vendor/blamejs/lib/sse.js +349 -0
  709. package/lib/vendor/blamejs/lib/ssrf-guard.js +792 -0
  710. package/lib/vendor/blamejs/lib/standard-webhooks.js +183 -0
  711. package/lib/vendor/blamejs/lib/static.js +1249 -0
  712. package/lib/vendor/blamejs/lib/storage.js +1272 -0
  713. package/lib/vendor/blamejs/lib/stream-throttle.js +235 -0
  714. package/lib/vendor/blamejs/lib/structured-fields.js +244 -0
  715. package/lib/vendor/blamejs/lib/subject.js +667 -0
  716. package/lib/vendor/blamejs/lib/tcpa-10dlc.js +175 -0
  717. package/lib/vendor/blamejs/lib/template.js +931 -0
  718. package/lib/vendor/blamejs/lib/tenant-quota.js +545 -0
  719. package/lib/vendor/blamejs/lib/test-harness.js +275 -0
  720. package/lib/vendor/blamejs/lib/testing.js +1185 -0
  721. package/lib/vendor/blamejs/lib/time.js +578 -0
  722. package/lib/vendor/blamejs/lib/tls-exporter.js +239 -0
  723. package/lib/vendor/blamejs/lib/totp.js +318 -0
  724. package/lib/vendor/blamejs/lib/tracing.js +546 -0
  725. package/lib/vendor/blamejs/lib/uuid.js +207 -0
  726. package/lib/vendor/blamejs/lib/validate-opts.js +381 -0
  727. package/lib/vendor/blamejs/lib/vault/index.js +638 -0
  728. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +311 -0
  729. package/lib/vendor/blamejs/lib/vault/passphrase-source.js +198 -0
  730. package/lib/vendor/blamejs/lib/vault/rotate.js +803 -0
  731. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +471 -0
  732. package/lib/vendor/blamejs/lib/vault/wrap.js +296 -0
  733. package/lib/vendor/blamejs/lib/vault-aad.js +259 -0
  734. package/lib/vendor/blamejs/lib/vendor/.vendor-data-pubkey +4 -0
  735. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +161 -0
  736. package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.data.js +68 -0
  737. package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.pem +33 -0
  738. package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.data.js +1325 -0
  739. package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.txt +10002 -0
  740. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +9 -0
  741. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +18 -0
  742. package/lib/vendor/blamejs/lib/vendor/pki.cjs +181 -0
  743. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +16382 -0
  744. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5881 -0
  745. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +328 -0
  746. package/lib/vendor/blamejs/lib/vendor/vendor-data-pubkey.js +16 -0
  747. package/lib/vendor/blamejs/lib/vendor-data.js +520 -0
  748. package/lib/vendor/blamejs/lib/vex.js +630 -0
  749. package/lib/vendor/blamejs/lib/watcher.js +608 -0
  750. package/lib/vendor/blamejs/lib/web-push-vapid.js +322 -0
  751. package/lib/vendor/blamejs/lib/webhook.js +977 -0
  752. package/lib/vendor/blamejs/lib/websocket-channels.js +327 -0
  753. package/lib/vendor/blamejs/lib/websocket.js +1561 -0
  754. package/lib/vendor/blamejs/lib/wiki-concepts.js +338 -0
  755. package/lib/vendor/blamejs/lib/worker-pool.js +464 -0
  756. package/lib/vendor/blamejs/lib/ws-client.js +978 -0
  757. package/lib/vendor/blamejs/lib/xml-c14n.js +506 -0
  758. package/lib/vendor/blamejs/memory/specs/node-26-map-getorinsert-migration.md +164 -0
  759. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +19 -0
  760. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/README.md +88 -0
  761. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/build.sh +26 -0
  762. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/project.yaml +28 -0
  763. package/lib/vendor/blamejs/package.json +81 -0
  764. package/lib/vendor/blamejs/release-notes/v0.0.x.json +310 -0
  765. package/lib/vendor/blamejs/release-notes/v0.1.x.json +1798 -0
  766. package/lib/vendor/blamejs/release-notes/v0.10.x.json +1288 -0
  767. package/lib/vendor/blamejs/release-notes/v0.11.x.json +2551 -0
  768. package/lib/vendor/blamejs/release-notes/v0.12.0.json +64 -0
  769. package/lib/vendor/blamejs/release-notes/v0.12.1.json +32 -0
  770. package/lib/vendor/blamejs/release-notes/v0.12.2.json +45 -0
  771. package/lib/vendor/blamejs/release-notes/v0.2.x.json +706 -0
  772. package/lib/vendor/blamejs/release-notes/v0.3.x.json +786 -0
  773. package/lib/vendor/blamejs/release-notes/v0.4.x.json +588 -0
  774. package/lib/vendor/blamejs/release-notes/v0.5.x.json +390 -0
  775. package/lib/vendor/blamejs/release-notes/v0.6.x.json +1947 -0
  776. package/lib/vendor/blamejs/release-notes/v0.7.x.json +3811 -0
  777. package/lib/vendor/blamejs/release-notes/v0.8.x.json +3318 -0
  778. package/lib/vendor/blamejs/release-notes/v0.9.x.json +2257 -0
  779. package/lib/vendor/blamejs/scripts/build-vendored-sbom.js +325 -0
  780. package/lib/vendor/blamejs/scripts/check-api-snapshot.js +62 -0
  781. package/lib/vendor/blamejs/scripts/check-changelog-extract.js +108 -0
  782. package/lib/vendor/blamejs/scripts/check-pack-against-gitignore.js +83 -0
  783. package/lib/vendor/blamejs/scripts/check-services.js +483 -0
  784. package/lib/vendor/blamejs/scripts/check-vendor-currency.js +349 -0
  785. package/lib/vendor/blamejs/scripts/consolidate-release-notes.js +216 -0
  786. package/lib/vendor/blamejs/scripts/gen-migrating.js +275 -0
  787. package/lib/vendor/blamejs/scripts/generate-changelog-entry.js +577 -0
  788. package/lib/vendor/blamejs/scripts/generate-release-signing-key.js +79 -0
  789. package/lib/vendor/blamejs/scripts/publish-dep-confusion-placeholder.sh +101 -0
  790. package/lib/vendor/blamejs/scripts/refresh-api-snapshot.js +31 -0
  791. package/lib/vendor/blamejs/scripts/refresh-vendor-manifest.js +132 -0
  792. package/lib/vendor/blamejs/scripts/release.js +652 -0
  793. package/lib/vendor/blamejs/scripts/sha3-digest.js +62 -0
  794. package/lib/vendor/blamejs/scripts/sign-release-artifact.js +92 -0
  795. package/lib/vendor/blamejs/scripts/test-integration.js +181 -0
  796. package/lib/vendor/blamejs/scripts/test-wiki-integration.js +126 -0
  797. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +77 -0
  798. package/lib/vendor/blamejs/scripts/vendor-data-gen.js +186 -0
  799. package/lib/vendor/blamejs/scripts/vendor-data-keygen.js +101 -0
  800. package/lib/vendor/blamejs/scripts/vendor-update.sh +278 -0
  801. package/lib/vendor/blamejs/test/00-primitives.js +19075 -0
  802. package/lib/vendor/blamejs/test/10-state.js +622 -0
  803. package/lib/vendor/blamejs/test/20-db.js +561 -0
  804. package/lib/vendor/blamejs/test/30-chain.js +2110 -0
  805. package/lib/vendor/blamejs/test/40-consumers.js +2453 -0
  806. package/lib/vendor/blamejs/test/50-integration.js +486 -0
  807. package/lib/vendor/blamejs/test/_helpers.js +10 -0
  808. package/lib/vendor/blamejs/test/_smoke-worker.js +69 -0
  809. package/lib/vendor/blamejs/test/fixtures/exploit-corpus/corpus.json +368 -0
  810. package/lib/vendor/blamejs/test/fixtures/http-client-stream-payload.txt +2 -0
  811. package/lib/vendor/blamejs/test/fixtures/worker-pool/echo.js +52 -0
  812. package/lib/vendor/blamejs/test/helpers/_codebase-shingle-worker.js +24 -0
  813. package/lib/vendor/blamejs/test/helpers/_codebase-shingle.js +203 -0
  814. package/lib/vendor/blamejs/test/helpers/_shape-match.js +513 -0
  815. package/lib/vendor/blamejs/test/helpers/check.js +36 -0
  816. package/lib/vendor/blamejs/test/helpers/cluster.js +70 -0
  817. package/lib/vendor/blamejs/test/helpers/db.js +143 -0
  818. package/lib/vendor/blamejs/test/helpers/drivers.js +207 -0
  819. package/lib/vendor/blamejs/test/helpers/fs-watch.js +101 -0
  820. package/lib/vendor/blamejs/test/helpers/http.js +14 -0
  821. package/lib/vendor/blamejs/test/helpers/index.js +93 -0
  822. package/lib/vendor/blamejs/test/helpers/json-round-trip.js +120 -0
  823. package/lib/vendor/blamejs/test/helpers/mocks.js +20 -0
  824. package/lib/vendor/blamejs/test/helpers/otel.js +13 -0
  825. package/lib/vendor/blamejs/test/helpers/services.js +380 -0
  826. package/lib/vendor/blamejs/test/helpers/wait.js +206 -0
  827. package/lib/vendor/blamejs/test/integration/cache.test.js +235 -0
  828. package/lib/vendor/blamejs/test/integration/cluster-provider-mysql.test.js +174 -0
  829. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +611 -0
  830. package/lib/vendor/blamejs/test/integration/http-client.test.js +129 -0
  831. package/lib/vendor/blamejs/test/integration/log-stream.test.js +219 -0
  832. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +181 -0
  833. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +152 -0
  834. package/lib/vendor/blamejs/test/integration/mail-smtp.test.js +161 -0
  835. package/lib/vendor/blamejs/test/integration/mtls-ca.test.js +289 -0
  836. package/lib/vendor/blamejs/test/integration/network-dns.test.js +123 -0
  837. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +101 -0
  838. package/lib/vendor/blamejs/test/integration/ntp-check.test.js +89 -0
  839. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +403 -0
  840. package/lib/vendor/blamejs/test/integration/pqc-pkcs8-forward-compat.test.js +271 -0
  841. package/lib/vendor/blamejs/test/integration/pubsub.test.js +137 -0
  842. package/lib/vendor/blamejs/test/integration/queue-redis.test.js +352 -0
  843. package/lib/vendor/blamejs/test/integration/redis-client-tls.test.js +96 -0
  844. package/lib/vendor/blamejs/test/integration/ssrf-guard.test.js +98 -0
  845. package/lib/vendor/blamejs/test/integration/websocket-permessage-deflate.test.js +261 -0
  846. package/lib/vendor/blamejs/test/integration/ws-client-roundtrip.test.js +230 -0
  847. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +211 -0
  848. package/lib/vendor/blamejs/test/layer-0-primitives/a2a.test.js +59 -0
  849. package/lib/vendor/blamejs/test/layer-0-primitives/access-lock.test.js +136 -0
  850. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +219 -0
  851. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +69 -0
  852. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +266 -0
  853. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +262 -0
  854. package/lib/vendor/blamejs/test/layer-0-primitives/agent-orchestrator.test.js +390 -0
  855. package/lib/vendor/blamejs/test/layer-0-primitives/agent-posture-chain.test.js +174 -0
  856. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +279 -0
  857. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +322 -0
  858. package/lib/vendor/blamejs/test/layer-0-primitives/agent-stream.test.js +227 -0
  859. package/lib/vendor/blamejs/test/layer-0-primitives/agent-tenant.test.js +302 -0
  860. package/lib/vendor/blamejs/test/layer-0-primitives/agent-trace.test.js +150 -0
  861. package/lib/vendor/blamejs/test/layer-0-primitives/ai-adverse-decision.test.js +44 -0
  862. package/lib/vendor/blamejs/test/layer-0-primitives/ai-content-detect.test.js +150 -0
  863. package/lib/vendor/blamejs/test/layer-0-primitives/ai-input.test.js +50 -0
  864. package/lib/vendor/blamejs/test/layer-0-primitives/ai-model-manifest.test.js +96 -0
  865. package/lib/vendor/blamejs/test/layer-0-primitives/ai-pref.test.js +76 -0
  866. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +1080 -0
  867. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +311 -0
  868. package/lib/vendor/blamejs/test/layer-0-primitives/archive-zip-stream.test.js +291 -0
  869. package/lib/vendor/blamejs/test/layer-0-primitives/archive.test.js +140 -0
  870. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +267 -0
  871. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +108 -0
  872. package/lib/vendor/blamejs/test/layer-0-primitives/asyncapi.test.js +929 -0
  873. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-conflict-path.test.js +80 -0
  874. package/lib/vendor/blamejs/test/layer-0-primitives/audit-cve-defensive.test.js +176 -0
  875. package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +132 -0
  876. package/lib/vendor/blamejs/test/layer-0-primitives/audit-export-cadf.test.js +97 -0
  877. package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +141 -0
  878. package/lib/vendor/blamejs/test/layer-0-primitives/audit-segregation.test.js +115 -0
  879. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-ml-dsa-65.test.js +163 -0
  880. package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +246 -0
  881. package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge-verifier.test.js +485 -0
  882. package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +331 -0
  883. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +352 -0
  884. package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +572 -0
  885. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password-audit.test.js +61 -0
  886. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-bucket-ops.test.js +258 -0
  887. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +105 -0
  888. package/lib/vendor/blamejs/test/layer-0-primitives/backup-worker.test.js +34 -0
  889. package/lib/vendor/blamejs/test/layer-0-primitives/bearer-auth.test.js +107 -0
  890. package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-chunked-malformed.test.js +131 -0
  891. package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-smuggling.test.js +118 -0
  892. package/lib/vendor/blamejs/test/layer-0-primitives/boot-gates.test.js +85 -0
  893. package/lib/vendor/blamejs/test/layer-0-primitives/breach-deadline.test.js +38 -0
  894. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +861 -0
  895. package/lib/vendor/blamejs/test/layer-0-primitives/budr.test.js +55 -0
  896. package/lib/vendor/blamejs/test/layer-0-primitives/bundler-engine.test.js +209 -0
  897. package/lib/vendor/blamejs/test/layer-0-primitives/cache-status.test.js +129 -0
  898. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +871 -0
  899. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +891 -0
  900. package/lib/vendor/blamejs/test/layer-0-primitives/canonical-json-jcs.test.js +43 -0
  901. package/lib/vendor/blamejs/test/layer-0-primitives/cdn-cache-control.test.js +243 -0
  902. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +550 -0
  903. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +107 -0
  904. package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +147 -0
  905. package/lib/vendor/blamejs/test/layer-0-primitives/cli-audit-verify-chain.test.js +104 -0
  906. package/lib/vendor/blamejs/test/layer-0-primitives/cli-backup.test.js +135 -0
  907. package/lib/vendor/blamejs/test/layer-0-primitives/cli-config-drift.test.js +67 -0
  908. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +75 -0
  909. package/lib/vendor/blamejs/test/layer-0-primitives/cli-file-type.test.js +98 -0
  910. package/lib/vendor/blamejs/test/layer-0-primitives/cli-helpers.test.js +145 -0
  911. package/lib/vendor/blamejs/test/layer-0-primitives/cli-mtls.test.js +133 -0
  912. package/lib/vendor/blamejs/test/layer-0-primitives/cli-password.test.js +97 -0
  913. package/lib/vendor/blamejs/test/layer-0-primitives/cli-restore.test.js +160 -0
  914. package/lib/vendor/blamejs/test/layer-0-primitives/cli-retention.test.js +84 -0
  915. package/lib/vendor/blamejs/test/layer-0-primitives/cli-security.test.js +69 -0
  916. package/lib/vendor/blamejs/test/layer-0-primitives/cli-vault.test.js +142 -0
  917. package/lib/vendor/blamejs/test/layer-0-primitives/client-hints.test.js +133 -0
  918. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +237 -0
  919. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +9600 -0
  920. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +575 -0
  921. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-cascade.test.js +89 -0
  922. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-eaa.test.js +36 -0
  923. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +712 -0
  924. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +278 -0
  925. package/lib/vendor/blamejs/test/layer-0-primitives/config-drift.test.js +97 -0
  926. package/lib/vendor/blamejs/test/layer-0-primitives/config.test.js +424 -0
  927. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +94 -0
  928. package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +357 -0
  929. package/lib/vendor/blamejs/test/layer-0-primitives/cra-report.test.js +31 -0
  930. package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +226 -0
  931. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +86 -0
  932. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-envelope.test.js +85 -0
  933. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +193 -0
  934. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +98 -0
  935. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke-pq.test.js +132 -0
  936. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke.test.js +155 -0
  937. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-mlkem768-x25519.test.js +129 -0
  938. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-namespace-hash.test.js +0 -0
  939. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-random-int.test.js +72 -0
  940. package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +96 -0
  941. package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +401 -0
  942. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +34 -0
  943. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +180 -0
  944. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +210 -0
  945. package/lib/vendor/blamejs/test/layer-0-primitives/daily-byte-quota.test.js +153 -0
  946. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +66 -0
  947. package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +74 -0
  948. package/lib/vendor/blamejs/test/layer-0-primitives/db-collection-extensions.test.js +226 -0
  949. package/lib/vendor/blamejs/test/layer-0-primitives/db-collection.test.js +136 -0
  950. package/lib/vendor/blamejs/test/layer-0-primitives/db-init-extensions.test.js +165 -0
  951. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +150 -0
  952. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-extensions.test.js +191 -0
  953. package/lib/vendor/blamejs/test/layer-0-primitives/db-role-for.test.js +228 -0
  954. package/lib/vendor/blamejs/test/layer-0-primitives/db-vacuum.test.js +55 -0
  955. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +89 -0
  956. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +184 -0
  957. package/lib/vendor/blamejs/test/layer-0-primitives/declare-row-policy.test.js +203 -0
  958. package/lib/vendor/blamejs/test/layer-0-primitives/declare-view.test.js +303 -0
  959. package/lib/vendor/blamejs/test/layer-0-primitives/dns-dnssec-algorithm.test.js +163 -0
  960. package/lib/vendor/blamejs/test/layer-0-primitives/dns-null-mx.test.js +39 -0
  961. package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +165 -0
  962. package/lib/vendor/blamejs/test/layer-0-primitives/dr-runbook.test.js +59 -0
  963. package/lib/vendor/blamejs/test/layer-0-primitives/dsr-state-rules.test.js +55 -0
  964. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +786 -0
  965. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +105 -0
  966. package/lib/vendor/blamejs/test/layer-0-primitives/early-hints.test.js +147 -0
  967. package/lib/vendor/blamejs/test/layer-0-primitives/events.test.js +105 -0
  968. package/lib/vendor/blamejs/test/layer-0-primitives/exploit-replay.test.js +243 -0
  969. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +181 -0
  970. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +190 -0
  971. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-routing.test.js +531 -0
  972. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +118 -0
  973. package/lib/vendor/blamejs/test/layer-0-primitives/fapi2.test.js +89 -0
  974. package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +156 -0
  975. package/lib/vendor/blamejs/test/layer-0-primitives/fdx.test.js +79 -0
  976. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +216 -0
  977. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +434 -0
  978. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +432 -0
  979. package/lib/vendor/blamejs/test/layer-0-primitives/file-type.test.js +81 -0
  980. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +887 -0
  981. package/lib/vendor/blamejs/test/layer-0-primitives/forensic-snapshot.test.js +51 -0
  982. package/lib/vendor/blamejs/test/layer-0-primitives/fsm.test.js +375 -0
  983. package/lib/vendor/blamejs/test/layer-0-primitives/gcs-bucket-ops.test.js +321 -0
  984. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +41 -0
  985. package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +32 -0
  986. package/lib/vendor/blamejs/test/layer-0-primitives/guard-agent-registry.test.js +87 -0
  987. package/lib/vendor/blamejs/test/layer-0-primitives/guard-all.test.js +328 -0
  988. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +339 -0
  989. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +694 -0
  990. package/lib/vendor/blamejs/test/layer-0-primitives/guard-dsn.test.js +296 -0
  991. package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +234 -0
  992. package/lib/vendor/blamejs/test/layer-0-primitives/guard-envelope.test.js +192 -0
  993. package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-payload.test.js +89 -0
  994. package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-topic.test.js +71 -0
  995. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +386 -0
  996. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html-wcag.test.js +859 -0
  997. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +357 -0
  998. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +92 -0
  999. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  1000. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +174 -0
  1001. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +317 -0
  1002. package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-id.test.js +199 -0
  1003. package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-unsubscribe.test.js +214 -0
  1004. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-compose.test.js +111 -0
  1005. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-move.test.js +110 -0
  1006. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-query.test.js +112 -0
  1007. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-reply.test.js +86 -0
  1008. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-sieve.test.js +92 -0
  1009. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +301 -0
  1010. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +265 -0
  1011. package/lib/vendor/blamejs/test/layer-0-primitives/guard-message-id.test.js +0 -0
  1012. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +161 -0
  1013. package/lib/vendor/blamejs/test/layer-0-primitives/guard-posture-chain.test.js +100 -0
  1014. package/lib/vendor/blamejs/test/layer-0-primitives/guard-saga-config.test.js +79 -0
  1015. package/lib/vendor/blamejs/test/layer-0-primitives/guard-smtp-command.test.js +269 -0
  1016. package/lib/vendor/blamejs/test/layer-0-primitives/guard-snapshot-envelope.test.js +89 -0
  1017. package/lib/vendor/blamejs/test/layer-0-primitives/guard-stream-args.test.js +78 -0
  1018. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +288 -0
  1019. package/lib/vendor/blamejs/test/layer-0-primitives/guard-tenant-id.test.js +69 -0
  1020. package/lib/vendor/blamejs/test/layer-0-primitives/guard-trace-context.test.js +102 -0
  1021. package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +202 -0
  1022. package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +203 -0
  1023. package/lib/vendor/blamejs/test/layer-0-primitives/hal.test.js +51 -0
  1024. package/lib/vendor/blamejs/test/layer-0-primitives/honeytoken.test.js +50 -0
  1025. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +37 -0
  1026. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +692 -0
  1027. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +280 -0
  1028. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +225 -0
  1029. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +203 -0
  1030. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +991 -0
  1031. package/lib/vendor/blamejs/test/layer-0-primitives/iab-mspa.test.js +63 -0
  1032. package/lib/vendor/blamejs/test/layer-0-primitives/iab-tcf.test.js +73 -0
  1033. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +612 -0
  1034. package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +56 -0
  1035. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +166 -0
  1036. package/lib/vendor/blamejs/test/layer-0-primitives/incident-report.test.js +29 -0
  1037. package/lib/vendor/blamejs/test/layer-0-primitives/jose-jwe-experimental.test.js +121 -0
  1038. package/lib/vendor/blamejs/test/layer-0-primitives/json-api.test.js +58 -0
  1039. package/lib/vendor/blamejs/test/layer-0-primitives/json-round-trip-helper.test.js +110 -0
  1040. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +159 -0
  1041. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  1042. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +118 -0
  1043. package/lib/vendor/blamejs/test/layer-0-primitives/local-db-thin.test.js +150 -0
  1044. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-cloudwatch.test.js +489 -0
  1045. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp-grpc.test.js +207 -0
  1046. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp.test.js +283 -0
  1047. package/lib/vendor/blamejs/test/layer-0-primitives/lro.test.js +65 -0
  1048. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +417 -0
  1049. package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +208 -0
  1050. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +910 -0
  1051. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +502 -0
  1052. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +680 -0
  1053. package/lib/vendor/blamejs/test/layer-0-primitives/mail-canspam.test.js +128 -0
  1054. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +149 -0
  1055. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +323 -0
  1056. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +297 -0
  1057. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +514 -0
  1058. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy-tlsrpt.test.js +369 -0
  1059. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +199 -0
  1060. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +627 -0
  1061. package/lib/vendor/blamejs/test/layer-0-primitives/mail-feedback-id.test.js +56 -0
  1062. package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +217 -0
  1063. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +283 -0
  1064. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +217 -0
  1065. package/lib/vendor/blamejs/test/layer-0-primitives/mail-mdn.test.js +334 -0
  1066. package/lib/vendor/blamejs/test/layer-0-primitives/mail-rbl.test.js +271 -0
  1067. package/lib/vendor/blamejs/test/layer-0-primitives/mail-require-tls.test.js +128 -0
  1068. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +215 -0
  1069. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +336 -0
  1070. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +732 -0
  1071. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +840 -0
  1072. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +130 -0
  1073. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +285 -0
  1074. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +74 -0
  1075. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +112 -0
  1076. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +229 -0
  1077. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +394 -0
  1078. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +147 -0
  1079. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +151 -0
  1080. package/lib/vendor/blamejs/test/layer-0-primitives/mail-spam-score.test.js +204 -0
  1081. package/lib/vendor/blamejs/test/layer-0-primitives/mail-srs.test.js +152 -0
  1082. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +279 -0
  1083. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +323 -0
  1084. package/lib/vendor/blamejs/test/layer-0-primitives/mail-unsubscribe.test.js +165 -0
  1085. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +439 -0
  1086. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-tool-registry.test.js +202 -0
  1087. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +155 -0
  1088. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-shadow-registry.test.js +112 -0
  1089. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +224 -0
  1090. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-compose-pipeline.test.js +278 -0
  1091. package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +376 -0
  1092. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-paths.test.js +89 -0
  1093. package/lib/vendor/blamejs/test/layer-0-primitives/nel.test.js +200 -0
  1094. package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +106 -0
  1095. package/lib/vendor/blamejs/test/layer-0-primitives/network-byte-quota.test.js +133 -0
  1096. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +372 -0
  1097. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +635 -0
  1098. package/lib/vendor/blamejs/test/layer-0-primitives/network-heartbeat-passive.test.js +128 -0
  1099. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-build-options.test.js +130 -0
  1100. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-ct-inclusion.test.js +179 -0
  1101. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +447 -0
  1102. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +369 -0
  1103. package/lib/vendor/blamejs/test/layer-0-primitives/nis2-report.test.js +21 -0
  1104. package/lib/vendor/blamejs/test/layer-0-primitives/nist-crosswalk.test.js +42 -0
  1105. package/lib/vendor/blamejs/test/layer-0-primitives/no-cache.test.js +98 -0
  1106. package/lib/vendor/blamejs/test/layer-0-primitives/notify.test.js +707 -0
  1107. package/lib/vendor/blamejs/test/layer-0-primitives/numeric-bounds.test.js +142 -0
  1108. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +72 -0
  1109. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +597 -0
  1110. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +190 -0
  1111. package/lib/vendor/blamejs/test/layer-0-primitives/openapi.test.js +877 -0
  1112. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +257 -0
  1113. package/lib/vendor/blamejs/test/layer-0-primitives/pagination.test.js +522 -0
  1114. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +216 -0
  1115. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +324 -0
  1116. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +546 -0
  1117. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +153 -0
  1118. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-software.test.js +94 -0
  1119. package/lib/vendor/blamejs/test/layer-0-primitives/problem-details.test.js +195 -0
  1120. package/lib/vendor/blamejs/test/layer-0-primitives/process-spawn.test.js +62 -0
  1121. package/lib/vendor/blamejs/test/layer-0-primitives/promise-pool.test.js +93 -0
  1122. package/lib/vendor/blamejs/test/layer-0-primitives/protected-resource-metadata.test.js +68 -0
  1123. package/lib/vendor/blamejs/test/layer-0-primitives/protobuf-encoder.test.js +138 -0
  1124. package/lib/vendor/blamejs/test/layer-0-primitives/protocol-dispatcher.test.js +174 -0
  1125. package/lib/vendor/blamejs/test/layer-0-primitives/public-suffix.test.js +197 -0
  1126. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +232 -0
  1127. package/lib/vendor/blamejs/test/layer-0-primitives/queue-dlq-extend-lease.test.js +178 -0
  1128. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +322 -0
  1129. package/lib/vendor/blamejs/test/layer-0-primitives/queue-priority-rate-progress.test.js +266 -0
  1130. package/lib/vendor/blamejs/test/layer-0-primitives/queue-sqs.test.js +300 -0
  1131. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-cluster.test.js +338 -0
  1132. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-registry.test.js +75 -0
  1133. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +246 -0
  1134. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +130 -0
  1135. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +335 -0
  1136. package/lib/vendor/blamejs/test/layer-0-primitives/request-log.test.js +170 -0
  1137. package/lib/vendor/blamejs/test/layer-0-primitives/require-auth-cache-control.test.js +93 -0
  1138. package/lib/vendor/blamejs/test/layer-0-primitives/require-mtls.test.js +34 -0
  1139. package/lib/vendor/blamejs/test/layer-0-primitives/resource-access-lock.test.js +52 -0
  1140. package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +67 -0
  1141. package/lib/vendor/blamejs/test/layer-0-primitives/retry.test.js +535 -0
  1142. package/lib/vendor/blamejs/test/layer-0-primitives/router-cross-origin-redirect.test.js +0 -0
  1143. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +128 -0
  1144. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +163 -0
  1145. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-parallel.test.js +170 -0
  1146. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +248 -0
  1147. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +451 -0
  1148. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +289 -0
  1149. package/lib/vendor/blamejs/test/layer-0-primitives/safe-icap.test.js +206 -0
  1150. package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +104 -0
  1151. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +339 -0
  1152. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mount-info.test.js +180 -0
  1153. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +78 -0
  1154. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sieve.test.js +123 -0
  1155. package/lib/vendor/blamejs/test/layer-0-primitives/safe-smtp.test.js +95 -0
  1156. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-idn-homograph.test.js +77 -0
  1157. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +257 -0
  1158. package/lib/vendor/blamejs/test/layer-0-primitives/saml-slo.test.js +249 -0
  1159. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +228 -0
  1160. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-exactly-once.test.js +238 -0
  1161. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +92 -0
  1162. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +700 -0
  1163. package/lib/vendor/blamejs/test/layer-0-primitives/sd-notify.test.js +67 -0
  1164. package/lib/vendor/blamejs/test/layer-0-primitives/sec-cyber.test.js +85 -0
  1165. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +107 -0
  1166. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +175 -0
  1167. package/lib/vendor/blamejs/test/layer-0-primitives/seeders.test.js +816 -0
  1168. package/lib/vendor/blamejs/test/layer-0-primitives/self-update-standalone-verifier.test.js +168 -0
  1169. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +302 -0
  1170. package/lib/vendor/blamejs/test/layer-0-primitives/server-timing.test.js +93 -0
  1171. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +247 -0
  1172. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +295 -0
  1173. package/lib/vendor/blamejs/test/layer-0-primitives/shape-match.test.js +142 -0
  1174. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +952 -0
  1175. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-multipart-sse.test.js +441 -0
  1176. package/lib/vendor/blamejs/test/layer-0-primitives/slug.test.js +330 -0
  1177. package/lib/vendor/blamejs/test/layer-0-primitives/smtp-policy.test.js +233 -0
  1178. package/lib/vendor/blamejs/test/layer-0-primitives/source-comment-blocks.test.js +105 -0
  1179. package/lib/vendor/blamejs/test/layer-0-primitives/speculation-rules.test.js +319 -0
  1180. package/lib/vendor/blamejs/test/layer-0-primitives/sse.test.js +148 -0
  1181. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +283 -0
  1182. package/lib/vendor/blamejs/test/layer-0-primitives/standard-webhooks.test.js +67 -0
  1183. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +266 -0
  1184. package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +487 -0
  1185. package/lib/vendor/blamejs/test/layer-0-primitives/storage-chunk-scratch.test.js +0 -0
  1186. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +773 -0
  1187. package/lib/vendor/blamejs/test/layer-0-primitives/stream-throttle.test.js +173 -0
  1188. package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +180 -0
  1189. package/lib/vendor/blamejs/test/layer-0-primitives/tcpa-10dlc.test.js +66 -0
  1190. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +89 -0
  1191. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +571 -0
  1192. package/lib/vendor/blamejs/test/layer-0-primitives/test-harness.test.js +190 -0
  1193. package/lib/vendor/blamejs/test/layer-0-primitives/testing-request.test.js +119 -0
  1194. package/lib/vendor/blamejs/test/layer-0-primitives/testing.test.js +522 -0
  1195. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +151 -0
  1196. package/lib/vendor/blamejs/test/layer-0-primitives/tls-exporter.test.js +168 -0
  1197. package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-ct.test.js +275 -0
  1198. package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-verify.test.js +105 -0
  1199. package/lib/vendor/blamejs/test/layer-0-primitives/tls-pinset-drift.test.js +35 -0
  1200. package/lib/vendor/blamejs/test/layer-0-primitives/tls-preferred-groups.test.js +81 -0
  1201. package/lib/vendor/blamejs/test/layer-0-primitives/tracing.test.js +280 -0
  1202. package/lib/vendor/blamejs/test/layer-0-primitives/uuid.test.js +93 -0
  1203. package/lib/vendor/blamejs/test/layer-0-primitives/vault-aad.test.js +277 -0
  1204. package/lib/vendor/blamejs/test/layer-0-primitives/vault-seal-pem-file.test.js +252 -0
  1205. package/lib/vendor/blamejs/test/layer-0-primitives/vendor-data.test.js +149 -0
  1206. package/lib/vendor/blamejs/test/layer-0-primitives/vendor-manifest.test.js +92 -0
  1207. package/lib/vendor/blamejs/test/layer-0-primitives/vex.test.js +661 -0
  1208. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +308 -0
  1209. package/lib/vendor/blamejs/test/layer-0-primitives/web-push-vapid.test.js +144 -0
  1210. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +674 -0
  1211. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-channels.test.js +360 -0
  1212. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool.test.js +302 -0
  1213. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +349 -0
  1214. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +717 -0
  1215. package/lib/vendor/blamejs/test/layer-5-integration/bundler-output.test.js +444 -0
  1216. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +597 -0
  1217. package/lib/vendor/blamejs/test/layer-5-integration/security-chaos.test.js +308 -0
  1218. package/lib/vendor/blamejs/test/smoke.js +431 -0
  1219. package/lib/webhooks.js +305 -0
  1220. package/package.json +43 -0
@@ -0,0 +1,2152 @@
1
+ "use strict";
2
+ /**
3
+ * @module b.httpClient
4
+ * @nav HTTP
5
+ * @title Http Client
6
+ *
7
+ * @intro
8
+ * Outbound HTTP client with SSRF gate, retry, circuit breaker,
9
+ * wall-clock + idle timeouts, AbortSignal propagation, connection
10
+ * pooling, streaming, and ALPN-negotiated HTTP/2. Built on node:http,
11
+ * node:https, and node:http2 with zero npm runtime dependency.
12
+ *
13
+ * Every outbound request flows through `b.ssrfGuard` out of the box:
14
+ * hostname → DNS lookup is pinned to vetted IP literals, RFC 1918 /
15
+ * loopback / link-local / IPv6 ULA destinations are refused, and the
16
+ * redirect chain is re-validated at every hop so a 302 to
17
+ * `http://169.254.169.254/` (cloud metadata) can't smuggle past the
18
+ * first-hop gate. The same DNS pinning applies to retries — there's
19
+ * no retry path that bypasses the guard.
20
+ *
21
+ * Protocol selection is automatic. HTTPS origins handshake with
22
+ * ALPN `['h2', 'http/1.1']` and cache the resulting transport per
23
+ * `<protocol>//<hostname>:<port>`. While a transport is mid-negotiate
24
+ * the cache holds the in-flight Promise so concurrent calls to a new
25
+ * origin coalesce onto a single connection. h2 GOAWAY or session
26
+ * error evicts the entry; the next request reconnects.
27
+ *
28
+ * Resiliency defaults: TLS 1.3 minimum, PQC-preferred `ecdhCurve`
29
+ * group order, split wall-clock vs zero-progress idle timeouts,
30
+ * request-body stream errors propagated to the returned Promise,
31
+ * and h2 stream cancellation via NGHTTP2_CANCEL (clean, not
32
+ * `stream.destroy`) when the AbortSignal fires.
33
+ *
34
+ * @card
35
+ * Outbound HTTP client with SSRF gate, retry, circuit breaker, wall-clock + idle timeouts, AbortSignal propagation, connection pooling, streaming, and ALPN-negotiated HTTP/2.
36
+ */
37
+
38
+ var nodeFs = require("node:fs");
39
+ var http = require("node:http");
40
+ var https = require("node:https");
41
+ var http2 = require("node:http2");
42
+ var nodeCrypto = require("node:crypto");
43
+ var nodePath = require("node:path");
44
+ var nodeStream = require("node:stream");
45
+ var streamPromises = require("node:stream/promises");
46
+ var { URL } = require("node:url");
47
+ var atomicFile = require("./atomic-file");
48
+ var C = require("./constants");
49
+ var bCrypto = require("./crypto");
50
+ var pqcAgent = require("./pqc-agent");
51
+ var safeAsync = require("./safe-async");
52
+ var safeBuffer = require("./safe-buffer");
53
+ var safeUrl = require("./safe-url");
54
+ var ssrfGuard = require("./ssrf-guard");
55
+ var networkProxy = require("./network-proxy");
56
+ var validateOpts = require("./validate-opts");
57
+ var { FrameworkError, HttpClientError } = require("./framework-error");
58
+
59
+ // Per-origin transport cache. Entry is either the resolved transport
60
+ // object or a pending Promise that resolves to one. The Promise form
61
+ // lets concurrent calls to a new origin coalesce on the same connect.
62
+ //
63
+ // Transport shapes the cache currently holds:
64
+ //
65
+ // { kind: "h1", lib, agent } — node:http(s) + keepAlive Agent
66
+ // { kind: "h2", session } — node:http2 ClientHttp2Session
67
+ //
68
+ // Reserved for the future (when node:http3 ships stable — currently
69
+ // behind --experimental-quic, no http3 module yet):
70
+ //
71
+ // { kind: "h3", session } — node:http3 ClientHttp3Session
72
+ //
73
+ // Adding the h3 case won't change the caller-facing surface: ALPN
74
+ // negotiation gains "h3" as the highest-preference protocol over QUIC,
75
+ // _getTransport branches on the resolved transport, and a new
76
+ // _requestH3 mirrors _requestH2's stream-based shape. h3's design
77
+ // gives 0-RTT first-class (vs. h1/h2 where 0-RTT is opaque under
78
+ // node's TLS layer — see TLS_SESSION_RESUMPTION_NOTES below).
79
+ var _transports = new Map();
80
+
81
+ // TLS session resumption notes — what's automatic vs. what's not
82
+ // exposed by Node's public API:
83
+ //
84
+ // keepAlive Agent (h1) / long-lived ClientHttp2Session (h2) means
85
+ // the WARM-CONNECTION case is zero-handshake — better than 0-RTT.
86
+ // We pay the TLS handshake once per origin, then amortize.
87
+ //
88
+ // When a pool socket is recycled, node's tls layer caches session
89
+ // tickets and does 1-RTT resumption automatically. We don't
90
+ // expose 0-RTT (early_data) — node's https.Agent has no clean API
91
+ // for it, and 0-RTT is REPLAY-RISKY for non-idempotent requests
92
+ // (server can't distinguish original from replay until the
93
+ // handshake completes). Operators who need 0-RTT for a specific
94
+ // idempotent path can pass their own agent via opts.agent.
95
+ //
96
+ // QUIC/h3 changes this calculus: 0-RTT is a first-class feature
97
+ // built into the protocol, with replay protection at the QUIC
98
+ // layer. The framework's `b.httpClient` is HTTP/1.1 + HTTP/2 only;
99
+ // operators wanting h3 wire their own client.
100
+ //
101
+ // QUIC retry / address-validation (RFC 9000 §8 + RFC 9001 §6) is
102
+ // deferred-with-condition: outbound h3 negotiation re-opens when
103
+ // Node's `--experimental-quic` graduates to stable and ships a
104
+ // `node:http3` module. The escape hatch today is `opts.agent` —
105
+ // operators on internal-mesh deployments that already terminate h3
106
+ // pass their own h3 agent rather than the framework rolling its
107
+ // own implementation under an experimental Node flag. SECURITY.md
108
+ // "Watch list" tracks the re-open trigger.
109
+
110
+ // Pool tuning for the HTTP-client transport cache. Keep-alive is
111
+ // shorter than the standalone pqc-agent default (1s vs 30s) because
112
+ // the cache layer manages its own warm-connection reuse and we want
113
+ // idle sockets reaped quickly between bursts. ecdhCurve / minVersion
114
+ // come from pqc-agent and cannot be set here — the framework's
115
+ // PQC-only TLS posture is one place, in lib/pqc-agent.js.
116
+ //
117
+ // Operators tune at boot via `b.httpClient.configurePool({...})`.
118
+ // Existing transports stay on whichever values were active when they
119
+ // were created — reconfigure runs before any outbound request to take
120
+ // effect on the per-origin cache.
121
+ var DEFAULT_AGENT_OPTS = Object.freeze({
122
+ keepAlive: true,
123
+ keepAliveMsecs: C.TIME.seconds(1),
124
+ maxSockets: C.BYTES.bytes(16),
125
+ maxFreeSockets: C.BYTES.bytes(8),
126
+ scheduling: "lifo",
127
+ });
128
+
129
+ var HTTP_CLIENT_AGENT_OPTS = Object.assign({}, DEFAULT_AGENT_OPTS);
130
+
131
+ /**
132
+ * @primitive b.httpClient.configurePool
133
+ * @signature b.httpClient.configurePool(opts)
134
+ * @since 0.1.0
135
+ * @status stable
136
+ * @related b.httpClient.request
137
+ *
138
+ * Updates the keepAlive Agent options used for new h1 transports and
139
+ * tears down the per-origin transport cache so subsequent requests
140
+ * pick up the fresh values. Existing in-flight responses keep their
141
+ * old transport. Throws on unknown keys, non-positive integers, or a
142
+ * non-boolean `keepAlive`. Use at boot when the default 16/8 socket
143
+ * caps don't match the operator's downstream concurrency budget.
144
+ *
145
+ * @opts
146
+ * keepAlive: true, // boolean — whether to reuse sockets
147
+ * keepAliveMsecs: 1000, // positive integer ms between keep-alive probes
148
+ * maxSockets: 16, // positive integer — concurrent sockets per origin
149
+ * maxFreeSockets: 8, // positive integer — idle sockets retained per origin
150
+ * scheduling: "lifo", // "lifo" | "fifo"
151
+ *
152
+ * @example
153
+ * b.httpClient.configurePool({ maxSockets: 64, maxFreeSockets: 32 });
154
+ * // → undefined (cache cleared; next request builds a 64-socket pool)
155
+ */
156
+ function configurePool(opts) {
157
+ if (!opts || typeof opts !== "object") {
158
+ throw new Error("httpClient.configurePool: opts must be an object");
159
+ }
160
+ var allowed = ["keepAlive", "keepAliveMsecs", "maxSockets", "maxFreeSockets", "scheduling"];
161
+ for (var k in opts) {
162
+ if (!Object.prototype.hasOwnProperty.call(opts, k)) continue;
163
+ if (allowed.indexOf(k) === -1) {
164
+ throw new Error("httpClient.configurePool: unknown option '" + k +
165
+ "'. Allowed: " + allowed.join(", "));
166
+ }
167
+ }
168
+ function _requirePositiveInt(name, value) {
169
+ if (typeof value !== "number" || !isFinite(value) || value <= 0 || Math.floor(value) !== value) {
170
+ throw new Error("httpClient.configurePool: " + name +
171
+ " must be a positive integer, got " + JSON.stringify(value));
172
+ }
173
+ }
174
+ if (opts.maxSockets !== undefined) _requirePositiveInt("maxSockets", opts.maxSockets);
175
+ if (opts.maxFreeSockets !== undefined) _requirePositiveInt("maxFreeSockets", opts.maxFreeSockets);
176
+ if (opts.keepAliveMsecs !== undefined) _requirePositiveInt("keepAliveMsecs", opts.keepAliveMsecs);
177
+ if (opts.keepAlive !== undefined && typeof opts.keepAlive !== "boolean") {
178
+ throw new Error("httpClient.configurePool: keepAlive must be a boolean");
179
+ }
180
+ if (opts.scheduling !== undefined && opts.scheduling !== "lifo" && opts.scheduling !== "fifo") {
181
+ throw new Error("httpClient.configurePool: scheduling must be 'lifo' or 'fifo'");
182
+ }
183
+ Object.assign(HTTP_CLIENT_AGENT_OPTS, opts);
184
+ // Existing transports keep their old values (Agent constructor
185
+ // copies). Drop the per-origin cache + tear down idle sockets so
186
+ // subsequent requests build fresh transports with the new opts.
187
+ _transports.forEach(function (t) {
188
+ if (t && t.kind === "h1" && t.agent && typeof t.agent.destroy === "function") {
189
+ try { t.agent.destroy(); } catch (_e) { /* best-effort agent teardown */ }
190
+ }
191
+ if (t && t.kind === "h2" && t.session) {
192
+ _tearDownH2Session(t.session);
193
+ }
194
+ });
195
+ _transports.clear();
196
+ }
197
+
198
+ // HTTP/2 session teardown — see lib/http2-teardown.js for the full
199
+ // rationale. Centralised so any future sink / pool teardown gets the
200
+ // same close()-then-destroy() discipline.
201
+ var _tearDownH2Session = require("./http2-teardown").tearDownH2Session;
202
+
203
+ // h2 session connect options. Same TLS posture as h1 Agent.
204
+ var DEFAULT_H2_TLS_OPTS = {
205
+ ALPNProtocols: ["h2", "http/1.1"],
206
+ ecdhCurve: C.TLS_GROUP_CURVE_STR,
207
+ minVersion: "TLSv1.3",
208
+ };
209
+
210
+ var DEFAULT_CONTROL_PLANE_CAP = C.BYTES.mib(16);
211
+ var DEFAULT_GET_CAP = C.BYTES.gib(1);
212
+ var DEFAULT_IDLE_TIMEOUT_MS = C.TIME.seconds(30);
213
+
214
+ // h2 session idle close. After this much idle time with no streams,
215
+ // close the session — long-running processes don't pin one TLS
216
+ // connection forever.
217
+ var H2_SESSION_IDLE_TIMEOUT_MS = C.TIME.minutes(5);
218
+
219
+ // IANA-assigned default ports per RFC 9110 §4.2.
220
+ var DEFAULT_HTTPS_PORT = 443;
221
+ var DEFAULT_HTTP_PORT = C.BYTES.bytes(80);
222
+
223
+ function _defaultPortFor(u) {
224
+ return u.protocol === "https:" ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;
225
+ }
226
+
227
+ function _originKey(u) {
228
+ return u.protocol + "//" + u.hostname + ":" + (u.port || _defaultPortFor(u));
229
+ }
230
+
231
+ function _makeH1Transport(u, ips) {
232
+ var lib = u.protocol === "https:" ? https : http;
233
+ // HTTPS path goes through pqcAgent.create so the framework's PQC-only
234
+ // posture is enforced via the single primitive. Cleartext HTTP stays
235
+ // on http.Agent because there's no TLS posture to enforce.
236
+ var agent = u.protocol === "https:"
237
+ ? pqcAgent.create(HTTP_CLIENT_AGENT_OPTS)
238
+ : new lib.Agent(HTTP_CLIENT_AGENT_OPTS);
239
+ return { kind: "h1", lib: lib, agent: agent, lookup: _pinnedLookupFor(ips) };
240
+ }
241
+
242
+ // Build a `lookup` callback that pins outbound connections to IPs the
243
+ // SSRF guard already validated. Closes the TOCTOU window between
244
+ // SSRF resolution and the kernel's connect — without this, a hostile
245
+ // (or compromised) DNS could rotate the answer between guard-check
246
+ // and connect-time and route the request to a private / metadata IP
247
+ // that bypassed the gate. ips comes from `ssrfGuard.checkUrl` — its
248
+ // classification ran on these exact addresses.
249
+ function _pinnedLookupFor(ips) {
250
+ if (!Array.isArray(ips) || ips.length === 0) return undefined;
251
+ var families = ips.map(function (i) { return { address: i.address, family: i.family || 4 }; });
252
+ return function pinnedLookup(hostname, options, callback) {
253
+ if (typeof options === "function") { callback = options; options = {}; }
254
+ options = options || {};
255
+ if (options.all) {
256
+ callback(null, families);
257
+ } else {
258
+ callback(null, families[0].address, families[0].family);
259
+ }
260
+ };
261
+ }
262
+
263
+ // Connect an h2 session to an HTTPS origin via ALPN. If the server picks
264
+ // http/1.1, fall back to an h1 transport for that origin.
265
+ function _connectHttpsWithAlpn(u, ips) {
266
+ return new Promise(function (resolve, reject) {
267
+ var connectOpts = Object.assign({}, DEFAULT_H2_TLS_OPTS);
268
+ var pinned = _pinnedLookupFor(ips);
269
+ if (pinned) connectOpts.lookup = pinned;
270
+ var session = http2.connect(u.protocol + "//" + u.host, connectOpts);
271
+ var settled = false;
272
+ function _done(t) { if (!settled) { settled = true; resolve(t); } }
273
+ function _fail(err) { if (!settled) { settled = true; reject(err); } }
274
+
275
+ session.once("connect", function () {
276
+ var alpn = session.alpnProtocol;
277
+ if (alpn === "h2") {
278
+ _wireH2Session(session, _originKey(u));
279
+ _done({ kind: "h2", session: session });
280
+ return;
281
+ }
282
+ // Server picked http/1.1 — close the h2 session, return h1 transport.
283
+ _tearDownH2Session(session);
284
+ _done(_makeH1Transport(u, ips));
285
+ });
286
+ session.once("error", function (err) {
287
+ _tearDownH2Session(session);
288
+ _fail(err);
289
+ });
290
+ });
291
+ }
292
+
293
+ // Connect an h2c session (cleartext h2). No ALPN, no fallback — caller
294
+ // has attested via preferH2 that the server speaks h2c.
295
+ function _connectH2c(u, ips) {
296
+ return new Promise(function (resolve, reject) {
297
+ var connectOpts = {};
298
+ var pinned = _pinnedLookupFor(ips);
299
+ if (pinned) connectOpts.lookup = pinned;
300
+ var session = http2.connect(u.protocol + "//" + u.host, connectOpts);
301
+ session.once("connect", function () {
302
+ _wireH2Session(session, _originKey(u));
303
+ resolve({ kind: "h2", session: session });
304
+ });
305
+ session.once("error", function (err) {
306
+ _tearDownH2Session(session);
307
+ reject(err);
308
+ });
309
+ });
310
+ }
311
+
312
+ // Common h2 session wiring — idle close + cache eviction on error/close.
313
+ function _wireH2Session(session, key) {
314
+ session.setTimeout(H2_SESSION_IDLE_TIMEOUT_MS, function () {
315
+ _tearDownH2Session(session);
316
+ });
317
+ session.once("close", function () { _transports.delete(key); });
318
+ session.once("error", function () { _transports.delete(key); });
319
+ session.once("goaway", function () {
320
+ // Server signalling 'no new streams' — let in-flight finish, evict cache.
321
+ _transports.delete(key);
322
+ });
323
+ }
324
+
325
+ // Async transport selection. Returns Promise<transport>. `ips` is the
326
+ // validated address list returned by `ssrfGuard.checkUrl`; the transport
327
+ // uses it to pin connections so a hostile DNS rebind can't redirect
328
+ // the actual TCP connect to a private / metadata IP.
329
+ function _getTransport(u, opts, ips) {
330
+ var key = _originKey(u);
331
+ var cached = _transports.get(key);
332
+ if (cached) {
333
+ // Could be a resolved transport OR a pending Promise. Cached
334
+ // transports keep whatever IP pinning was set when they were
335
+ // first created — subsequent SSRF checks still gate the request,
336
+ // and the transport's TCP socket is bound to its original IP.
337
+ return Promise.resolve(cached);
338
+ }
339
+
340
+ var promise;
341
+ if (u.protocol === "https:") {
342
+ promise = _connectHttpsWithAlpn(u, ips);
343
+ } else if (opts && opts.preferH2) {
344
+ promise = _connectH2c(u, ips);
345
+ } else {
346
+ // HTTP without preferH2 → h1 only.
347
+ promise = Promise.resolve(_makeH1Transport(u, ips));
348
+ }
349
+
350
+ // Cache the in-flight Promise immediately so concurrent calls
351
+ // coalesce. On resolve, replace with the transport. On reject, evict.
352
+ _transports.set(key, promise);
353
+ promise.then(
354
+ function (t) { _transports.set(key, t); },
355
+ function (_err) { _transports.delete(key); }
356
+ );
357
+
358
+ return promise;
359
+ }
360
+
361
+ function _makeError(errorClass, code, message, permanent, statusCode) {
362
+ if (!errorClass) return new FrameworkError(message, code);
363
+ return new errorClass(code, message, permanent, statusCode);
364
+ }
365
+
366
+ // RFC 9110 §15.5 4xx codes that are NOT permanent (request-timeout,
367
+ // too-early, too-many-requests — operator should retry).
368
+ var STATUS_REQUEST_TIMEOUT = C.BYTES.bytes(408);
369
+ var STATUS_TOO_EARLY = 425;
370
+ var STATUS_TOO_MANY_REQUESTS = 429;
371
+
372
+ function _isPermanentStatus(statusCode) {
373
+ if (statusCode >= 400 && statusCode < 500) {
374
+ return statusCode !== STATUS_REQUEST_TIMEOUT &&
375
+ statusCode !== STATUS_TOO_EARLY &&
376
+ statusCode !== STATUS_TOO_MANY_REQUESTS;
377
+ }
378
+ return false;
379
+ }
380
+
381
+ // h2 sends headers as lowercased keys plus :method / :path / :scheme /
382
+ // :authority pseudo-headers. Convert from h1-shaped headers.
383
+ function _toH2Headers(method, u, headers) {
384
+ var h2Headers = Object.create(null);
385
+ h2Headers[":method"] = method;
386
+ h2Headers[":path"] = u.pathname + (u.search || "");
387
+ h2Headers[":scheme"] = u.protocol === "https:" ? "https" : "http";
388
+ h2Headers[":authority"] = u.host;
389
+ var sawAcceptEncoding = false;
390
+ for (var k in headers) {
391
+ if (!Object.prototype.hasOwnProperty.call(headers, k)) continue;
392
+ var lk = k.toLowerCase();
393
+ // h2 forbids the connection-specific headers
394
+ if (lk === "connection" || lk === "host" ||
395
+ lk === "keep-alive" || lk === "transfer-encoding" ||
396
+ lk === "upgrade" || lk === "proxy-connection") continue;
397
+ if (lk === "accept-encoding") sawAcceptEncoding = true;
398
+ h2Headers[lk] = headers[k];
399
+ }
400
+ // CVE-2026-22036 mitigation — same identity default as the h1 path.
401
+ // Refuse compressed responses unless the operator explicitly opts in.
402
+ if (!sawAcceptEncoding) h2Headers["accept-encoding"] = "identity";
403
+ return h2Headers;
404
+ }
405
+
406
+ function _fromH2Headers(h2Headers) {
407
+ // Strip pseudo-headers from the response — caller doesn't want them
408
+ // mixed with normal headers.
409
+ var out = {};
410
+ for (var k in h2Headers) {
411
+ if (!Object.prototype.hasOwnProperty.call(h2Headers, k)) continue;
412
+ if (k.charAt(0) === ":") continue;
413
+ out[k] = h2Headers[k];
414
+ }
415
+ return out;
416
+ }
417
+
418
+ // ---- request() ----
419
+
420
+ var REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
421
+
422
+ // http-client-cookie-jar is exposed on b.httpClient.cookieJar via index.js.
423
+ // http-client itself only consumes the jar shape passed by operators via
424
+ // the request opt; no direct require is needed here.
425
+
426
+ // Merge a jar-derived Cookie header with any caller-supplied Cookie
427
+ // header. Operators who override Cookie explicitly always win — the jar
428
+ // supplements rather than replaces.
429
+ function _attachJarCookie(headers, jar, url) {
430
+ if (!jar) return headers;
431
+ var jarHeader = jar.cookieHeaderFor(url);
432
+ if (!jarHeader) return headers;
433
+ var merged = Object.assign({}, headers || {});
434
+ var existing = null;
435
+ var keys = Object.keys(merged);
436
+ for (var i = 0; i < keys.length; i++) {
437
+ if (keys[i].toLowerCase() === "cookie") { existing = keys[i]; break; }
438
+ }
439
+ if (existing) merged[existing] = merged[existing] + "; " + jarHeader;
440
+ else merged.Cookie = jarHeader;
441
+ return merged;
442
+ }
443
+
444
+ // Build a multipart/form-data body from { fields, files } shape.
445
+ // Mirrors the wire format that lib/middleware/body-parser.js's multipart
446
+ // parser accepts so round-trip from one blamejs app's outbound to
447
+ // another's inbound is exact.
448
+ //
449
+ // Two output shapes:
450
+ //
451
+ // - { boundary, body: Buffer, contentLength }
452
+ // When every file entry is a Buffer / string (size known
453
+ // up front) and no operator opted into streaming, the result
454
+ // is a fully-materialized body. Smaller payloads avoid the
455
+ // streaming overhead and let HTTP/1.1 KeepAlive reuse with a
456
+ // known Content-Length.
457
+ //
458
+ // - { boundary, body: Readable, contentLength }
459
+ // When at least one file entry is `{ filePath }` / `{ stream }`
460
+ // OR opts.streaming === true, the result is a Readable that
461
+ // emits boundary headers + content + CRLF in order. Avoids the
462
+ // Buffer.concat() OOM class on large uploads. contentLength is
463
+ // a finite number when every source's size is statically
464
+ // resolvable (Buffer length, nodeFs.statSync().size, opts.size on
465
+ // a stream entry); null otherwise — caller falls back to
466
+ // chunked transfer.
467
+ //
468
+ // File entry shapes (all require `field`):
469
+ //
470
+ // { field, content: Buffer | string } — in-memory (existing)
471
+ // { field, filePath: string } — stream-from-disk
472
+ // { field, stream: Readable, size?: number } — operator-supplied stream
473
+ //
474
+ // `filename` and `contentType` apply to all three shapes; for
475
+ // `filePath` entries, `filename` defaults to path.basename(filePath).
476
+ function _buildMultipartBody(spec) {
477
+ var boundary = "----blamejs-mp-" + bCrypto.generateToken(C.BYTES.bytes(16));
478
+ var CRLF = "\r\n";
479
+ var nodeFs = require("node:fs"); // allow:inline-require — only on multipart paths that touch the filesystem
480
+ var path = require("node:path"); // allow:inline-require — same
481
+ var nodeStream = require("node:stream"); // allow:inline-require — Readable subclass only when streaming
482
+
483
+ // Each entry is { headerBytes, source } where source is one of:
484
+ // { kind: "buffer", buf: Buffer }
485
+ // { kind: "filePath", filePath: string, size: number }
486
+ // { kind: "stream", stream: Readable, size: number | null }
487
+ var entries = [];
488
+ var anyStreaming = false;
489
+ var totalSize = 0;
490
+ var sizeKnown = true;
491
+
492
+ function _entryHeaderBytes(disposition, contentType) {
493
+ var head = "--" + boundary + CRLF + disposition + CRLF;
494
+ if (contentType) head += "Content-Type: " + contentType + CRLF;
495
+ head += CRLF;
496
+ return Buffer.from(head, "utf8");
497
+ }
498
+
499
+ function _addEntry(headerBytes, source) {
500
+ entries.push({ header: headerBytes, source: source });
501
+ totalSize += headerBytes.length;
502
+ if (source.kind === "buffer") {
503
+ totalSize += source.buf.length;
504
+ } else if (typeof source.size === "number" && isFinite(source.size) && source.size >= 0) {
505
+ totalSize += source.size;
506
+ } else {
507
+ sizeKnown = false;
508
+ }
509
+ totalSize += CRLF.length;
510
+ }
511
+
512
+ function _pushField(name, value) {
513
+ if (typeof name !== "string" || name.length === 0) {
514
+ throw new Error("multipart: field name must be a non-empty string");
515
+ }
516
+ var disposition = 'Content-Disposition: form-data; name="' + name + '"';
517
+ var head = _entryHeaderBytes(disposition, null);
518
+ var bodyBuf = Buffer.isBuffer(value) ? value : Buffer.from(String(value), "utf8");
519
+ _addEntry(head, { kind: "buffer", buf: bodyBuf });
520
+ }
521
+
522
+ function _pushFile(file) {
523
+ if (!file || typeof file !== "object") throw new Error("multipart: file entries must be objects");
524
+ if (typeof file.field !== "string" || file.field.length === 0) {
525
+ throw new Error("multipart: file.field must be a non-empty string");
526
+ }
527
+ var hasContent = file.content !== undefined && file.content !== null;
528
+ var hasFilePath = typeof file.filePath === "string" && file.filePath.length > 0;
529
+ var hasStream = file.stream && typeof file.stream.pipe === "function";
530
+ var sourceCount = (hasContent ? 1 : 0) + (hasFilePath ? 1 : 0) + (hasStream ? 1 : 0);
531
+ if (sourceCount === 0) {
532
+ throw new Error("multipart: file entry requires one of { content, filePath, stream }");
533
+ }
534
+ if (sourceCount > 1) {
535
+ throw new Error("multipart: file entry must have exactly one of { content, filePath, stream }");
536
+ }
537
+
538
+ var filename;
539
+ if (typeof file.filename === "string" && file.filename.length > 0) {
540
+ filename = file.filename;
541
+ } else if (hasFilePath) {
542
+ filename = path.basename(file.filePath);
543
+ } else {
544
+ filename = "blob";
545
+ }
546
+ var mimeType = file.contentType || file.mimeType || "application/octet-stream";
547
+ var disposition = 'Content-Disposition: form-data; name="' + file.field + '"' +
548
+ '; filename="' + filename.replace(/"/g, "%22") + '"';
549
+ var head = _entryHeaderBytes(disposition, mimeType);
550
+
551
+ if (hasContent) {
552
+ var content = file.content;
553
+ if (typeof content === "string") content = Buffer.from(content, "utf8");
554
+ if (!Buffer.isBuffer(content)) {
555
+ throw new Error("multipart: file.content must be a Buffer or string");
556
+ }
557
+ _addEntry(head, { kind: "buffer", buf: content });
558
+ } else if (hasFilePath) {
559
+ anyStreaming = true;
560
+ var st;
561
+ try { st = nodeFs.statSync(file.filePath); }
562
+ catch (e) { throw new Error("multipart: file.filePath not readable: " + e.message); }
563
+ if (!st.isFile()) throw new Error("multipart: file.filePath is not a regular file");
564
+ _addEntry(head, { kind: "filePath", filePath: file.filePath, size: st.size });
565
+ } else {
566
+ anyStreaming = true;
567
+ var streamSize = (typeof file.size === "number" && isFinite(file.size) && file.size >= 0)
568
+ ? file.size : null;
569
+ _addEntry(head, { kind: "stream", stream: file.stream, size: streamSize });
570
+ }
571
+ }
572
+
573
+ if (spec && spec.fields && typeof spec.fields === "object") {
574
+ var keys = Object.keys(spec.fields);
575
+ for (var i = 0; i < keys.length; i++) {
576
+ var k = keys[i];
577
+ var v = spec.fields[k];
578
+ if (Array.isArray(v)) {
579
+ for (var j = 0; j < v.length; j++) _pushField(k, v[j]);
580
+ } else {
581
+ _pushField(k, v);
582
+ }
583
+ }
584
+ }
585
+ if (spec && Array.isArray(spec.files)) {
586
+ for (var fi = 0; fi < spec.files.length; fi++) _pushFile(spec.files[fi]);
587
+ }
588
+ var trailer = Buffer.from("--" + boundary + "--" + CRLF, "utf8");
589
+ totalSize += trailer.length;
590
+
591
+ // All-buffer fast path — return a fully-materialized body when no
592
+ // streaming sources are involved AND the operator didn't ask for
593
+ // streaming explicitly. Existing callers that pass small in-memory
594
+ // payloads keep the buffer codepath.
595
+ if (!anyStreaming && !(spec && spec.streaming === true)) {
596
+ var parts = [];
597
+ for (var ei = 0; ei < entries.length; ei++) {
598
+ parts.push(entries[ei].header);
599
+ parts.push(entries[ei].source.buf);
600
+ parts.push(Buffer.from(CRLF, "utf8"));
601
+ }
602
+ parts.push(trailer);
603
+ return { boundary: boundary, body: Buffer.concat(parts), contentLength: totalSize };
604
+ }
605
+
606
+ // Streaming path — produce a Readable from an async iterator that
607
+ // yields the bytes for each entry in order.
608
+ var crlfBuf = Buffer.from(CRLF, "utf8");
609
+ async function* _iter() {
610
+ for (var ix = 0; ix < entries.length; ix++) {
611
+ var entry = entries[ix];
612
+ yield entry.header;
613
+ if (entry.source.kind === "buffer") {
614
+ yield entry.source.buf;
615
+ } else if (entry.source.kind === "filePath") {
616
+ var rs = nodeFs.createReadStream(entry.source.filePath);
617
+ try {
618
+ for await (var chunk of rs) yield chunk;
619
+ } finally {
620
+ try { rs.destroy(); } catch (_e) { /* best-effort cleanup */ }
621
+ }
622
+ } else {
623
+ // operator-supplied stream
624
+ for await (var chunk2 of entry.source.stream) yield chunk2;
625
+ }
626
+ yield crlfBuf;
627
+ }
628
+ yield trailer;
629
+ }
630
+ var body = nodeStream.Readable.from(_iter());
631
+ return {
632
+ boundary: boundary,
633
+ body: body,
634
+ contentLength: sizeKnown ? totalSize : null,
635
+ };
636
+ }
637
+
638
+ // Headers stripped on cross-origin redirect to defend against accidental
639
+ // credential exfiltration. Lower-case for header-map comparison.
640
+ var SENSITIVE_HEADERS_LC = ["authorization", "cookie", "proxy-authorization"];
641
+
642
+ function _stripCrossOriginAuth(headers) {
643
+ var out = {};
644
+ var keys = Object.keys(headers);
645
+ for (var i = 0; i < keys.length; i++) {
646
+ if (SENSITIVE_HEADERS_LC.indexOf(keys[i].toLowerCase()) !== -1) continue;
647
+ out[keys[i]] = headers[keys[i]];
648
+ }
649
+ return out;
650
+ }
651
+
652
+ /**
653
+ * @primitive b.httpClient.request
654
+ * @signature b.httpClient.request(opts)
655
+ * @since 0.1.0
656
+ * @status stable
657
+ * @related b.httpClient.downloadStream, b.httpClient.uploadMultipartStream, b.ssrfGuard
658
+ *
659
+ * Promise-returning, AbortSignal-aware HTTP request. Negotiates h2 /
660
+ * h1 per-origin via ALPN, reuses transports from the cache, runs every
661
+ * destination through `b.ssrfGuard` before connecting, and re-validates
662
+ * each redirect hop. Returns `{ statusCode, headers, body }` for the
663
+ * default `"buffer"` mode; `"stream"` returns a Readable for the body.
664
+ * Sensitive headers (Authorization / Cookie / Proxy-Authorization) are
665
+ * stripped on cross-origin redirect. Body-stream errors propagate to
666
+ * the rejected Promise.
667
+ *
668
+ * @opts
669
+ * method: "GET", // HTTP method
670
+ * url: <required>, // string or URL — destination
671
+ * headers: {}, // request headers
672
+ * body: undefined, // Buffer | string | Readable | undefined
673
+ * timeoutMs: undefined, // wall-clock cap; no default — operator chooses
674
+ * idleTimeoutMs: 30000, // zero-progress cap
675
+ * responseMode: "buffer", // "buffer" | "stream" | "always-resolve"
676
+ * maxResponseBytes: undefined, // 16 MiB control / 1 GiB GET defaults; ignored in "stream"
677
+ * onChunk: undefined, // (chunk: Buffer) => void — fires per response chunk
678
+ * signal: undefined, // AbortSignal — propagated to req / stream
679
+ * errorClass: HttpClientError, // FrameworkError subclass for thrown errors
680
+ * observer: undefined, // (stage, info) => void — lifecycle hook
681
+ * agent: undefined, // override per-origin Agent (h1 only)
682
+ * preferH2: false, // attempt h2c against an HTTP origin (no ALPN)
683
+ * before: undefined, // array of (opts) => opts | Promise — request mutators
684
+ * after: undefined, // array of (response) => response | Promise — response mutators
685
+ * onUploadProgress: undefined, // (bytesSent, totalBytes?) => void
686
+ *
687
+ * @example
688
+ * var res = await b.httpClient.request({
689
+ * method: "GET",
690
+ * url: "https://example.com/health",
691
+ * timeoutMs: 5000,
692
+ * });
693
+ * // → { statusCode: 200, headers: { "content-type": "application/json", ... }, body: <Buffer> }
694
+ */
695
+ function request(opts) {
696
+ if (!opts || !opts.url) {
697
+ return Promise.reject(_makeError(opts && opts.errorClass, "BAD_ARG", "url is required", true));
698
+ }
699
+
700
+ // Validate before/after shapes early — throw at call site if the
701
+ // operator passed something un-callable so the bug surfaces here
702
+ // rather than inside the request loop.
703
+ if (opts.before !== undefined) {
704
+ if (!Array.isArray(opts.before) || !opts.before.every(function (f) { return typeof f === "function"; })) {
705
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
706
+ "before must be an array of functions", true));
707
+ }
708
+ }
709
+ if (opts.after !== undefined) {
710
+ if (!Array.isArray(opts.after) || !opts.after.every(function (f) { return typeof f === "function"; })) {
711
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
712
+ "after must be an array of functions", true));
713
+ }
714
+ }
715
+ if (opts.onUploadProgress !== undefined && typeof opts.onUploadProgress !== "function") {
716
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
717
+ "onUploadProgress must be a function", true));
718
+ }
719
+ if (opts.onDownloadProgress !== undefined && typeof opts.onDownloadProgress !== "function") {
720
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
721
+ "onDownloadProgress must be a function", true));
722
+ }
723
+ if (opts.onChunk !== undefined && typeof opts.onChunk !== "function") {
724
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
725
+ "onChunk must be a function (chunk: Buffer) -> void", true));
726
+ }
727
+ if (opts.jar !== undefined && opts.jar !== null) {
728
+ if (typeof opts.jar !== "object" ||
729
+ typeof opts.jar.cookieHeaderFor !== "function" ||
730
+ typeof opts.jar.setFromResponse !== "function") {
731
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
732
+ "jar must be a b.httpClient.cookieJar.create() instance", true));
733
+ }
734
+ }
735
+ // RFC 9111 outbound HTTP cache. Validate shape at the entry-point;
736
+ // the cache hot path itself is drop-silent (any failure falls back
737
+ // to the network so caching is never a request-failure surface).
738
+ if (opts.cache !== undefined && opts.cache !== null) {
739
+ if (typeof opts.cache !== "object" ||
740
+ typeof opts.cache._lookup !== "function" ||
741
+ typeof opts.cache._evaluateStorage !== "function" ||
742
+ typeof opts.cache._store !== "function") {
743
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
744
+ "cache must be a b.httpClient.cache.create() instance", true));
745
+ }
746
+ }
747
+
748
+ // before interceptors — run in array order. Each may return a modified
749
+ // opts object (or return nothing to leave the running opts as-is).
750
+ // Caller-set defaults / observability / auth header injection lands
751
+ // here. Synchronous to keep the request hot path simple; async
752
+ // pre-flight work (e.g. token refresh) belongs in the route handler
753
+ // before httpClient.request is even called.
754
+ if (Array.isArray(opts.before) && opts.before.length > 0) {
755
+ var working = opts;
756
+ for (var bi = 0; bi < opts.before.length; bi++) {
757
+ var ret;
758
+ try { ret = opts.before[bi](working); }
759
+ catch (e) {
760
+ return Promise.reject(_makeError(opts.errorClass, "BEFORE_THREW",
761
+ "before[" + bi + "] threw: " + ((e && e.message) || String(e)), true));
762
+ }
763
+ if (ret && typeof ret === "object") working = ret;
764
+ }
765
+ opts = working;
766
+ }
767
+
768
+ // Multipart shorthand: { multipart: { fields, files } } expands to
769
+ // body + Content-Type with the boundary parameter. Mutually exclusive
770
+ // with caller-supplied body / Content-Type.
771
+ if (opts.multipart) {
772
+ if (opts.body !== undefined) {
773
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
774
+ "request: pass either { body } or { multipart }, not both", true));
775
+ }
776
+ var built;
777
+ try { built = _buildMultipartBody(opts.multipart); }
778
+ catch (e) {
779
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG", e.message, true));
780
+ }
781
+ var mpHeaders = Object.assign({}, opts.headers || {}, {
782
+ "Content-Type": "multipart/form-data; boundary=" + built.boundary,
783
+ });
784
+ // Content-Length is set when the framework can statically resolve
785
+ // every source's byte size. Otherwise the framework omits the
786
+ // header and Node's HTTP layer falls back to chunked transfer —
787
+ // valid HTTP/1.1, requires no operator opt-in.
788
+ if (typeof built.contentLength === "number" && isFinite(built.contentLength)) {
789
+ mpHeaders["Content-Length"] = String(built.contentLength);
790
+ }
791
+ opts = Object.assign({}, opts, {
792
+ method: opts.method || "POST",
793
+ body: built.body,
794
+ headers: mpHeaders,
795
+ multipart: undefined,
796
+ });
797
+ }
798
+
799
+ // maxRedirects:
800
+ // undefined → today's behavior (no follow). Caller inspects 3xx.
801
+ // null → today's behavior (explicit). Same as undefined.
802
+ // 0 → no follow, but 3xx returned to caller (alias of null).
803
+ // N → follow up to N hops; 3xx with no Location returned as-is.
804
+ var maxRedirects = (opts.maxRedirects === undefined || opts.maxRedirects === null)
805
+ ? null : opts.maxRedirects;
806
+ if (maxRedirects !== null) {
807
+ if (typeof maxRedirects !== "number" || !isFinite(maxRedirects) || maxRedirects < 0 ||
808
+ Math.floor(maxRedirects) !== maxRedirects) {
809
+ return Promise.reject(_makeError(opts.errorClass, "BAD_ARG",
810
+ "maxRedirects must be a non-negative integer or null", true));
811
+ }
812
+ }
813
+ var afterChain = (Array.isArray(opts.after) && opts.after.length > 0) ? opts.after : null;
814
+ function _runAfter(finalOpts, res) {
815
+ if (!afterChain) return res;
816
+ for (var ai = 0; ai < afterChain.length; ai++) {
817
+ try { afterChain[ai](finalOpts, res); }
818
+ catch (_e) { /* after hooks are best-effort — never break the response */ }
819
+ }
820
+ return res;
821
+ }
822
+
823
+ // Cache layer wraps the redirect-aware path. Cache wiring is a no-op
824
+ // for non-GET/HEAD methods (per RFC 9111 §3) and bypassed entirely
825
+ // when the request opts include a body (the request mutates state on
826
+ // the upstream, can't be a cache hit).
827
+ if (opts.cache && _cacheEligibleMethod(opts.method) && opts.body == null) {
828
+ return _runWithCache(opts, maxRedirects, _runAfter);
829
+ }
830
+
831
+ if (maxRedirects === null || maxRedirects === 0) {
832
+ return _requestSingle(opts).then(function (res) { return _runAfter(opts, res); });
833
+ }
834
+
835
+ return _requestWithRedirects(opts, maxRedirects).then(function (boxed) {
836
+ return _runAfter(boxed.finalOpts, boxed.res);
837
+ });
838
+ }
839
+
840
+ // Cache-method gate. RFC 9111 §3 — method must be GET or HEAD for the
841
+ // outbound cache to consider a response. Any other method shortcircuits
842
+ // straight to the network path (and operator code that mistakenly
843
+ // passed a cache instance to a POST sees the same network behaviour as
844
+ // without the cache, no surprise).
845
+ function _cacheEligibleMethod(method) {
846
+ var m = String(method || "GET").toUpperCase();
847
+ return m === "GET" || m === "HEAD";
848
+ }
849
+
850
+ // Wrap an outbound headers object with the framework's cache-decision
851
+ // markers. Mutates a copy; never the original.
852
+ function _withCacheHeaders(res, status, ageSeconds) {
853
+ var headers = Object.assign({}, res.headers || {});
854
+ headers["x-blamejs-cache"] = status;
855
+ if (typeof ageSeconds === "number" && ageSeconds >= 0) {
856
+ headers["age"] = String(Math.floor(ageSeconds));
857
+ }
858
+ return Object.assign({}, res, { headers: headers });
859
+ }
860
+
861
+ function _runWithCache(opts, maxRedirects, runAfter) {
862
+ var cache = opts.cache;
863
+ var method = String(opts.method || "GET").toUpperCase();
864
+ var requestHeaders = opts.headers || {};
865
+ var nowMs = Date.now();
866
+
867
+ // 1. Lookup. Cache lookups themselves are drop-silent; on store
868
+ // failure we treat the call as a miss.
869
+ var got = null;
870
+ try { got = cache._lookup(method, opts.url, requestHeaders); }
871
+ catch (_e) { got = null; }
872
+
873
+ function _doNetwork(extraReqHeaders) {
874
+ var nextOpts = opts;
875
+ if (extraReqHeaders) {
876
+ nextOpts = Object.assign({}, opts, {
877
+ headers: Object.assign({}, opts.headers || {}, extraReqHeaders),
878
+ });
879
+ }
880
+ if (maxRedirects === null || maxRedirects === 0) {
881
+ return _requestSingle(nextOpts).then(function (res) {
882
+ return { finalOpts: nextOpts, res: res };
883
+ });
884
+ }
885
+ return _requestWithRedirects(nextOpts, maxRedirects);
886
+ }
887
+
888
+ // 2. Miss → network → maybe store.
889
+ if (!got) {
890
+ try { cache._emit("httpclient.cache.miss", "allowed", { url: String(opts.url), method: method }); }
891
+ catch (_e) { /* drop-silent */ }
892
+ try { cache._obsEvent("httpclient.cache.miss", 1, { method: method }); }
893
+ catch (_e) { /* drop-silent */ }
894
+ return _doNetwork(null).then(function (boxed) {
895
+ _maybeStore(cache, method, opts.url, requestHeaders, boxed.res);
896
+ return runAfter(boxed.finalOpts, _withCacheHeaders(boxed.res, "MISS"));
897
+ });
898
+ }
899
+
900
+ // 3. Hit. Decide fresh / stale / revalidate.
901
+ var entry = got.entry;
902
+ var evaluation;
903
+ try { evaluation = cache._evaluateStored(entry, nowMs); }
904
+ catch (_e) {
905
+ // Malformed entry — drop it, treat as miss.
906
+ try { cache.invalidate(method, opts.url, requestHeaders); }
907
+ catch (_e2) { /* drop-silent */ }
908
+ return _doNetwork(null).then(function (boxed) {
909
+ _maybeStore(cache, method, opts.url, requestHeaders, boxed.res);
910
+ return runAfter(boxed.finalOpts, _withCacheHeaders(boxed.res, "MISS"));
911
+ });
912
+ }
913
+
914
+ if (evaluation.fresh && !evaluation.mustRevalidate) {
915
+ var age = cache._serveAgeSeconds(entry, nowMs);
916
+ try { cache._emit("httpclient.cache.hit", "allowed", { url: String(opts.url), method: method, ageMs: evaluation.ageMs }); }
917
+ catch (_e) { /* drop-silent */ }
918
+ try { cache._obsEvent("httpclient.cache.hit", 1, { method: method }); }
919
+ catch (_e) { /* drop-silent */ }
920
+ var hitRes = {
921
+ statusCode: entry.statusCode,
922
+ headers: Object.assign({}, entry.headers),
923
+ body: Buffer.isBuffer(entry.body) ? Buffer.from(entry.body) : entry.body,
924
+ cacheStatus: "HIT",
925
+ };
926
+ return Promise.resolve(runAfter(opts, _withCacheHeaders(hitRes, "HIT", age)));
927
+ }
928
+
929
+ // 4. Stale or must-revalidate. Within stale-while-revalidate or
930
+ // defaultMaxStale grace, we serve stale + kick off background
931
+ // revalidation. Otherwise we revalidate inline.
932
+ var ageOverFresh = Math.max(0, evaluation.ageMs - evaluation.freshnessMs);
933
+ var swrApplies = !evaluation.mustRevalidate &&
934
+ ageOverFresh < Math.max(evaluation.swrWindowMs, evaluation.defaultStaleMs);
935
+
936
+ if (swrApplies && cache.revalidateInBackground) {
937
+ // Serve stale immediately, kick off background revalidation. We
938
+ // explicitly DON'T await the background revalidation Promise so
939
+ // the caller gets the stale response immediately. We also catch
940
+ // its error so an unhandled rejection doesn't escape.
941
+ var ageStale = cache._serveAgeSeconds(entry, nowMs);
942
+ try { cache._emit("httpclient.cache.stale", "allowed", { url: String(opts.url), method: method, ageMs: evaluation.ageMs, mode: "swr" }); }
943
+ catch (_e) { /* drop-silent */ }
944
+ try { cache._obsEvent("httpclient.cache.stale", 1, { method: method, mode: "swr" }); }
945
+ catch (_e) { /* drop-silent */ }
946
+ var staleRes = {
947
+ statusCode: entry.statusCode,
948
+ headers: Object.assign({}, entry.headers),
949
+ body: Buffer.isBuffer(entry.body) ? Buffer.from(entry.body) : entry.body,
950
+ cacheStatus: "STALE",
951
+ };
952
+ // Background revalidation — fire-and-forget, errors swallowed (the
953
+ // next caller observes the stale entry until either the upstream
954
+ // recovers or stale-if-error / s-w-r windows expire).
955
+ setImmediate(function () {
956
+ _revalidate(cache, method, opts, entry, requestHeaders).catch(function () {
957
+ /* background revalidation best-effort; swallow */
958
+ });
959
+ });
960
+ return Promise.resolve(runAfter(opts, _withCacheHeaders(staleRes, "STALE", ageStale)));
961
+ }
962
+
963
+ // 5. Inline conditional revalidation. Build If-None-Match /
964
+ // If-Modified-Since from the stored entry, fire the network
965
+ // request, branch on 304 vs anything-else.
966
+ return _revalidate(cache, method, opts, entry, requestHeaders).then(function (rev) {
967
+ if (rev.kind === "not-modified") {
968
+ var ageRev = cache._serveAgeSeconds(rev.refreshed || entry, Date.now());
969
+ var revRes = {
970
+ statusCode: (rev.refreshed || entry).statusCode,
971
+ headers: Object.assign({}, (rev.refreshed || entry).headers),
972
+ body: Buffer.isBuffer((rev.refreshed || entry).body)
973
+ ? Buffer.from((rev.refreshed || entry).body)
974
+ : (rev.refreshed || entry).body,
975
+ cacheStatus: "REVALIDATED",
976
+ };
977
+ return runAfter(opts, _withCacheHeaders(revRes, "REVALIDATED", ageRev));
978
+ }
979
+ if (rev.kind === "fresh-response") {
980
+ _maybeStore(cache, method, opts.url, requestHeaders, rev.res);
981
+ return runAfter(rev.finalOpts || opts, _withCacheHeaders(rev.res, "MISS"));
982
+ }
983
+ // rev.kind === "error" — try stale-if-error.
984
+ var sieMs = (evaluation.sieWindowMs || 0);
985
+ if (sieMs > 0 && ageOverFresh < sieMs) {
986
+ var ageErr = cache._serveAgeSeconds(entry, Date.now());
987
+ try { cache._emit("httpclient.cache.stale", "allowed", { url: String(opts.url), method: method, ageMs: evaluation.ageMs, mode: "sie", error: rev.error && rev.error.message }); }
988
+ catch (_e) { /* drop-silent */ }
989
+ try { cache._obsEvent("httpclient.cache.stale", 1, { method: method, mode: "sie" }); }
990
+ catch (_e) { /* drop-silent */ }
991
+ var sieRes = {
992
+ statusCode: entry.statusCode,
993
+ headers: Object.assign({}, entry.headers),
994
+ body: Buffer.isBuffer(entry.body) ? Buffer.from(entry.body) : entry.body,
995
+ cacheStatus: "STALE",
996
+ };
997
+ return runAfter(opts, _withCacheHeaders(sieRes, "STALE", ageErr));
998
+ }
999
+ return Promise.reject(rev.error);
1000
+ });
1001
+ }
1002
+
1003
+ // Build conditional headers for revalidation per RFC 9110 §13.
1004
+ function _conditionalHeaders(entry) {
1005
+ var out = {};
1006
+ if (entry.etag) out["If-None-Match"] = entry.etag;
1007
+ if (entry.lastModified) out["If-Modified-Since"] = entry.lastModified;
1008
+ return out;
1009
+ }
1010
+
1011
+ // Run a revalidation request. Returns one of:
1012
+ // { kind: "not-modified", refreshed } — upstream returned 304
1013
+ // { kind: "fresh-response", res, finalOpts } — upstream returned 2xx/...
1014
+ // { kind: "error", error } — network or upstream error
1015
+ function _revalidate(cache, method, opts, entry, requestHeaders) {
1016
+ var conditional = _conditionalHeaders(entry);
1017
+ var nextOpts = Object.assign({}, opts, {
1018
+ headers: Object.assign({}, requestHeaders, conditional),
1019
+ // Stream-mode bypass: revalidation always uses buffer mode so the
1020
+ // 304 / fresh-response branches both have buffered body in hand
1021
+ // ready to merge / store.
1022
+ responseMode: "always-resolve",
1023
+ // Ensure we don't recurse into the cache layer on the revalidation
1024
+ // request itself. Pass cache as null/undefined.
1025
+ cache: undefined,
1026
+ });
1027
+ var maxRedirects = (opts.maxRedirects === undefined || opts.maxRedirects === null)
1028
+ ? null : opts.maxRedirects;
1029
+ var p = (maxRedirects === null || maxRedirects === 0)
1030
+ ? _requestSingle(nextOpts).then(function (res) { return { finalOpts: nextOpts, res: res }; })
1031
+ : _requestWithRedirects(nextOpts, maxRedirects);
1032
+
1033
+ return p.then(function (boxed) {
1034
+ var res = boxed.res;
1035
+ if (res.statusCode === 304) { // allow:raw-byte-literal — HTTP 304 Not Modified status code, not bytes
1036
+ // Merge 304 headers into the stored entry.
1037
+ var refreshed;
1038
+ try { refreshed = cache._refreshFrom304(entry, res.headers); }
1039
+ catch (_e) { refreshed = entry; }
1040
+ try { cache._emit("httpclient.cache.revalidated", "allowed", { url: String(opts.url), method: method }); }
1041
+ catch (_e) { /* drop-silent */ }
1042
+ try { cache._obsEvent("httpclient.cache.revalidated", 1, { method: method }); }
1043
+ catch (_e) { /* drop-silent */ }
1044
+ return { kind: "not-modified", refreshed: refreshed };
1045
+ }
1046
+ return { kind: "fresh-response", res: res, finalOpts: boxed.finalOpts };
1047
+ }, function (err) {
1048
+ return { kind: "error", error: err };
1049
+ });
1050
+ }
1051
+
1052
+ // Decide whether to store, then store. Drop-silent on any internal
1053
+ // throw so caching cannot surface as a request failure.
1054
+ function _maybeStore(cache, method, url, requestHeaders, res) {
1055
+ try {
1056
+ var evaluation = cache._evaluateStorage(method, res.statusCode, res.headers || {});
1057
+ if (!evaluation.cacheable) return;
1058
+ cache._store(method, url, requestHeaders, res.statusCode, res.headers || {}, res.body, evaluation);
1059
+ } catch (_e) { /* drop-silent — caching never breaks the request */ }
1060
+ }
1061
+
1062
+ function _requestWithRedirects(opts, hopsLeft) {
1063
+ var originalUrl = opts.url;
1064
+ var originalOrigin = null;
1065
+ try {
1066
+ var u0 = safeUrl.parse(opts.url, { allowedProtocols: safeUrl.ALLOW_HTTP_ALL });
1067
+ originalOrigin = u0.protocol + "//" + u0.host;
1068
+ } catch (_e) { /* request() will reject on next hop's parse */ }
1069
+ // onRedirect: function ({ from, to, hop, headersStripped, statusCode }) — called
1070
+ // BEFORE each follow. Operator can mutate the next-hop URL or abort
1071
+ // the redirect by throwing. Async hooks are awaited.
1072
+ var onRedirect = typeof opts.onRedirect === "function" ? opts.onRedirect : null;
1073
+ var hopCount = 0;
1074
+
1075
+ var current = Object.assign({}, opts, { _resolveOnRedirect: true });
1076
+ function _follow() {
1077
+ return _requestSingle(current).then(function (res) {
1078
+ if (!REDIRECT_STATUSES.has(res.statusCode) || hopsLeft <= 0) {
1079
+ return { finalOpts: current, res: res };
1080
+ }
1081
+ var loc = res.headers && (res.headers.location || res.headers.Location);
1082
+ if (!loc) return { finalOpts: current, res: res }; // 3xx with no Location — operator handles
1083
+ hopsLeft -= 1;
1084
+ hopCount += 1;
1085
+
1086
+ // Resolve relative Location against the just-fetched URL (the URL
1087
+ // of the request that produced the redirect, which may itself be a
1088
+ // post-redirect URL).
1089
+ var nextUrl;
1090
+ try {
1091
+ // Resolve relative Location against current URL using Node's URL
1092
+ // base-URL form. Re-validate the resolved absolute through safeUrl
1093
+ // immediately below.
1094
+ nextUrl = Reflect.construct(URL, [loc, current.url]).toString();
1095
+ }
1096
+ catch (_e) {
1097
+ return Promise.reject(_makeError(opts.errorClass, "BAD_REDIRECT",
1098
+ "Location header invalid URL: " + loc, true));
1099
+ }
1100
+
1101
+ // Cross-origin auth-header strip.
1102
+ var nextHeaders = current.headers || {};
1103
+ var nextOrigin;
1104
+ try {
1105
+ var nu = safeUrl.parse(nextUrl, { allowedProtocols: safeUrl.ALLOW_HTTP_ALL });
1106
+ nextOrigin = nu.protocol + "//" + nu.host;
1107
+ } catch (_e) { /* request() will reject when it tries to parse */ }
1108
+ var headersStripped = false;
1109
+ if (originalOrigin && nextOrigin && nextOrigin !== originalOrigin) {
1110
+ nextHeaders = _stripCrossOriginAuth(nextHeaders);
1111
+ headersStripped = true;
1112
+ }
1113
+
1114
+ // 303 → always GET; body dropped. 301/302 → historical clients
1115
+ // also coerce non-GET bodies (we follow that convention). 307/308
1116
+ // → preserve method + body.
1117
+ var nextMethod = current.method || "GET";
1118
+ var nextBody = current.body;
1119
+ if (res.statusCode === 303 ||
1120
+ ((res.statusCode === 301 || res.statusCode === 302) &&
1121
+ nextMethod !== "GET" && nextMethod !== "HEAD")) {
1122
+ nextMethod = "GET";
1123
+ nextBody = undefined;
1124
+ }
1125
+
1126
+ function _continueFollow() {
1127
+ current = Object.assign({}, current, {
1128
+ url: nextUrl,
1129
+ method: nextMethod,
1130
+ body: nextBody,
1131
+ headers: nextHeaders,
1132
+ _resolveOnRedirect: true,
1133
+ });
1134
+ return _follow();
1135
+ }
1136
+
1137
+ // Caller-supplied redirect hook fires here. The hook can throw
1138
+ // (sync) or reject (async) to abort the follow with a custom
1139
+ // error; otherwise we proceed to the next hop. We pre-bind the
1140
+ // values the hook gets and pass them in a frozen object so a
1141
+ // caller can't mutate the in-flight pipeline by side-effect.
1142
+ if (onRedirect) {
1143
+ var hookEvent = Object.freeze({
1144
+ from: current.url,
1145
+ to: nextUrl,
1146
+ hop: hopCount,
1147
+ statusCode: res.statusCode,
1148
+ headersStripped: headersStripped,
1149
+ method: nextMethod,
1150
+ });
1151
+ try {
1152
+ var hookResult = onRedirect(hookEvent);
1153
+ if (hookResult && typeof hookResult.then === "function") {
1154
+ return hookResult.then(function () { return _continueFollow(); });
1155
+ }
1156
+ } catch (e) {
1157
+ return Promise.reject(_makeError(opts.errorClass, "REDIRECT_ABORTED",
1158
+ "onRedirect hook refused redirect: " + ((e && e.message) || String(e)), true));
1159
+ }
1160
+ }
1161
+ return _continueFollow();
1162
+ });
1163
+ }
1164
+ void originalUrl;
1165
+ return _follow();
1166
+ }
1167
+
1168
+ function _requestSingle(opts) {
1169
+ // Validate scheme + shape via url-safe. Default is HTTPS-only — the
1170
+ // framework refuses to silently drop bytes on the wire as cleartext.
1171
+ // Callers with cleartext endpoints (h2c, internal services, test
1172
+ // fixtures) explicitly opt in via opts.allowedProtocols
1173
+ // (safeUrl.ALLOW_HTTP_ALL accepts both http: and https:).
1174
+ var u;
1175
+ try {
1176
+ u = safeUrl.parse(opts.url, {
1177
+ allowedProtocols: opts.allowedProtocols || safeUrl.ALLOW_HTTP_TLS,
1178
+ errorClass: opts.errorClass,
1179
+ });
1180
+ } catch (e) {
1181
+ return Promise.reject(e);
1182
+ }
1183
+
1184
+ // Optional outbound destination allowlist. When opts.allowedHosts
1185
+ // is set, only URLs whose hostname is on the list are permitted.
1186
+ // Layer above safeUrl (scheme/userinfo gate) and above ssrfGuard
1187
+ // (IP-class gate) — operators with strict egress policies pin the
1188
+ // outbound destinations the app is allowed to talk to so a
1189
+ // compromised process can't reach arbitrary upstreams.
1190
+ //
1191
+ // Entry forms (each entry is a string OR an object):
1192
+ // "api.partner.com" — exact host match
1193
+ // ".partner.com" — suffix match: "api.partner.com" yes,
1194
+ // "evilpartner.com" no
1195
+ // "*.partner.com" — same as ".partner.com" (DNS-glob shape
1196
+ // operators expect from firewall configs)
1197
+ // { host: "api.x.com", methods: ["GET","HEAD"] }
1198
+ // — method-restricted entry; methods omitted
1199
+ // = any method
1200
+ //
1201
+ // A disallowed call rejects with HOST_DISALLOWED AND emits an
1202
+ // audit event when opts.audit is wired (operator gets a structured
1203
+ // signal that the application tried to reach somewhere it shouldn't).
1204
+ if (Array.isArray(opts.allowedHosts) && opts.allowedHosts.length > 0) {
1205
+ var host = u.hostname.toLowerCase();
1206
+ var method = (opts.method || "GET").toUpperCase();
1207
+ var ok = false;
1208
+ for (var ai = 0; ai < opts.allowedHosts.length; ai++) {
1209
+ var entry = opts.allowedHosts[ai];
1210
+ var allow, allowedMethods = null;
1211
+ if (typeof entry === "object" && entry !== null) {
1212
+ allow = String(entry.host || "").toLowerCase();
1213
+ if (Array.isArray(entry.methods) && entry.methods.length > 0) {
1214
+ allowedMethods = entry.methods.map(function (m) { return String(m).toUpperCase(); });
1215
+ }
1216
+ } else {
1217
+ allow = String(entry || "").toLowerCase();
1218
+ }
1219
+ if (allow.length === 0) continue;
1220
+ // Normalise "*.x.com" to ".x.com" for the suffix match path.
1221
+ if (allow.charAt(0) === "*" && allow.charAt(1) === ".") allow = allow.slice(1);
1222
+ var matched = false;
1223
+ if (allow.charAt(0) === ".") {
1224
+ if (host === allow.slice(1) || host.endsWith(allow)) matched = true;
1225
+ } else if (host === allow) {
1226
+ matched = true;
1227
+ }
1228
+ if (!matched) continue;
1229
+ if (allowedMethods !== null && allowedMethods.indexOf(method) === -1) continue;
1230
+ ok = true;
1231
+ break;
1232
+ }
1233
+ if (!ok) {
1234
+ if (opts.audit && typeof opts.audit.safeEmit === "function") {
1235
+ try {
1236
+ opts.audit.safeEmit({
1237
+ action: "system.httpclient.host_denied",
1238
+ outcome: "denied",
1239
+ resource: { kind: "outbound.http", id: host },
1240
+ metadata: { method: method, url: opts.url, allowedHostsCount: opts.allowedHosts.length },
1241
+ });
1242
+ } catch (_e) { /* audit best-effort */ }
1243
+ }
1244
+ return Promise.reject(_makeError(opts.errorClass, "HOST_DISALLOWED",
1245
+ "host '" + host + "' not in allowedHosts (method=" + method + ")", true));
1246
+ }
1247
+ }
1248
+
1249
+ // Attach jar-derived Cookie header BEFORE the request fires; record
1250
+ // Set-Cookie response headers AFTER. Both halves run when opts.jar
1251
+ // is set; redirect-following naturally re-runs both paths per hop
1252
+ // because each hop calls _requestSingle.
1253
+ if (opts.jar) {
1254
+ var headersWithJar = _attachJarCookie(opts.headers, opts.jar, opts.url);
1255
+ if (headersWithJar !== opts.headers) {
1256
+ opts = Object.assign({}, opts, { headers: headersWithJar });
1257
+ }
1258
+ }
1259
+
1260
+ // Proxy detection runs BEFORE the SSRF DNS lookup. When a proxy is
1261
+ // configured AND the operator explicitly opts into `allowInternal:
1262
+ // true`, the SSRF DNS lookup is skipped — the proxy resolves the
1263
+ // target hostname in its own network context (the proxy is the trust
1264
+ // boundary). Without this short-circuit, hostnames that only resolve
1265
+ // inside the proxy's network (e.g. corporate intranets, docker
1266
+ // service names) would fail DNS locally before the proxy ever sees
1267
+ // them.
1268
+ //
1269
+ // The `allowInternal: true` opt is the operator's affirmative waiver
1270
+ // of local SSRF defense; combined with a configured proxy, it
1271
+ // signals "trust the proxy's resolution + classification". When
1272
+ // `allowInternal` is false / array-form, the SSRF check still runs
1273
+ // even with a proxy — the proxy's freedom to reach internal IPs is
1274
+ // not a license for operator code to do so without the explicit opt-in.
1275
+ var proxyAgent = null;
1276
+ try { proxyAgent = networkProxy.agentFor(u); } catch (_e) { proxyAgent = null; }
1277
+
1278
+ var ssrfPromise;
1279
+ if (proxyAgent && opts.allowInternal === true) {
1280
+ // Proxy short-circuit — skip DNS resolution of the destination
1281
+ // hostname (the proxy resolves it in its own network context).
1282
+ // BUT still apply the textual cloud-metadata-IP block: addresses
1283
+ // like 169.254.169.254 (AWS / GCP / Azure / OpenStack / DO IMDS)
1284
+ // leak instance credentials and are NEVER overridable, even with
1285
+ // `allowInternal: true` AND a proxy configured. ssrfGuard's
1286
+ // textual check refuses metadata-IP literals at the hostname-text
1287
+ // layer so the proxy never receives the request.
1288
+ try {
1289
+ ssrfGuard.checkUrlTextual(u, { errorClass: opts.errorClass });
1290
+ } catch (eMeta) {
1291
+ return Promise.reject(eMeta);
1292
+ }
1293
+ ssrfPromise = Promise.resolve({ ips: null });
1294
+ } else {
1295
+ // SSRF gate — refuse private / loopback / link-local / cloud-metadata
1296
+ // / reserved IP destinations by default. The returned `ips` are
1297
+ // threaded into transport creation so the actual TCP connect pins
1298
+ // to those exact addresses, closing the DNS-rebinding TOCTOU window.
1299
+ ssrfPromise = ssrfGuard.checkUrl(u, {
1300
+ allowInternal: opts.allowInternal,
1301
+ errorClass: opts.errorClass,
1302
+ });
1303
+ }
1304
+
1305
+ return ssrfPromise.then(function (ssrfResult) {
1306
+ var ips = ssrfResult && ssrfResult.ips;
1307
+ // Caller-supplied agent bypasses transport cache (h1 only). The
1308
+ // operator owns the agent's connection pool — we still pass the
1309
+ // pinned lookup through per-request so the SSRF check's IPs win.
1310
+ if (opts.agent) {
1311
+ return _requestH1({
1312
+ kind: "h1",
1313
+ lib: u.protocol === "https:" ? https : http,
1314
+ agent: opts.agent,
1315
+ lookup: _pinnedLookupFor(ips),
1316
+ }, u, opts);
1317
+ }
1318
+
1319
+ if (proxyAgent) {
1320
+ return _requestH1({
1321
+ kind: "h1",
1322
+ lib: u.protocol === "https:" ? https : http,
1323
+ agent: proxyAgent,
1324
+ lookup: undefined,
1325
+ }, u, opts);
1326
+ }
1327
+
1328
+ return _getTransport(u, opts, ips).then(function (transport) {
1329
+ if (transport.kind === "h2") return _requestH2(transport, u, opts);
1330
+ return _requestH1(transport, u, opts);
1331
+ });
1332
+ });
1333
+ }
1334
+
1335
+ // ---- _requestH1: existing node:http(s) path ----
1336
+
1337
+ function _requestH1(transport, u, opts) {
1338
+ return new Promise(function (resolve, reject) {
1339
+ var method = (opts.method || "GET").toUpperCase();
1340
+ var headers = Object.assign({}, opts.headers || {});
1341
+ var responseMode = opts.responseMode || "buffer";
1342
+ var maxResponseBytes = opts.maxResponseBytes ||
1343
+ (method === "GET" ? DEFAULT_GET_CAP : DEFAULT_CONTROL_PLANE_CAP);
1344
+ var observer = typeof opts.observer === "function" ? opts.observer : null;
1345
+ var startedAt = Date.now();
1346
+
1347
+ var signal = safeAsync.withTimeoutSignal(opts.signal || null, opts.timeoutMs);
1348
+ if (signal && signal.aborted) {
1349
+ var r0 = signal.reason;
1350
+ var code0 = (r0 && r0.name === "TimeoutError") ? "ETIMEDOUT" : "ABORT";
1351
+ reject(_makeError(opts.errorClass, code0,
1352
+ (r0 && r0.message) || "request aborted before start", false));
1353
+ return;
1354
+ }
1355
+
1356
+ if (Buffer.isBuffer(opts.body)) {
1357
+ headers["Content-Length"] = opts.body.length;
1358
+ }
1359
+ // CVE-2026-22036 mitigation — refuse compressed responses by
1360
+ // default. The framework's http-client returns raw bytes capped
1361
+ // at maxResponseBytes; if a server sends gzip/br/zstd the cap is
1362
+ // on-wire bytes only, and any operator-side decompression is the
1363
+ // operator's responsibility to bound. Identity by default closes
1364
+ // the decompression-bomb amplification class. Operators who DO
1365
+ // want compressed responses opt in by passing an explicit
1366
+ // Accept-Encoding header (lowercase or canonical form).
1367
+ if (!headers["Accept-Encoding"] && !headers["accept-encoding"]) {
1368
+ headers["Accept-Encoding"] = "identity";
1369
+ }
1370
+
1371
+ var reqOpts = {
1372
+ method: method,
1373
+ hostname: u.hostname,
1374
+ port: u.port || _defaultPortFor(u),
1375
+ path: u.pathname + (u.search || ""),
1376
+ headers: headers,
1377
+ agent: transport.agent,
1378
+ timeout: typeof opts.idleTimeoutMs === "number" ? opts.idleTimeoutMs : DEFAULT_IDLE_TIMEOUT_MS,
1379
+ };
1380
+ // Pin DNS to the IPs the SSRF guard validated. Closes the
1381
+ // rebinding TOCTOU between guard-check and actual TCP connect.
1382
+ if (transport.lookup) reqOpts.lookup = transport.lookup;
1383
+
1384
+ if (observer) observer("request:start", { method: method, url: String(opts.url), protocol: "h1" });
1385
+
1386
+ var settled = false;
1387
+ function _resolve(value) { if (!settled) { settled = true; resolve(value); } }
1388
+ function _reject(err) { if (!settled) { settled = true; reject(err); } }
1389
+
1390
+ var onUploadProgress = typeof opts.onUploadProgress === "function" ? opts.onUploadProgress : null;
1391
+ var onDownloadProgress = typeof opts.onDownloadProgress === "function" ? opts.onDownloadProgress : null;
1392
+ var onChunk = typeof opts.onChunk === "function" ? opts.onChunk : null;
1393
+
1394
+ var req = transport.lib.request(reqOpts, function (res) {
1395
+ if (observer) observer("response:headers", { statusCode: res.statusCode, headers: res.headers });
1396
+
1397
+ // Save Set-Cookie into the jar (if wired) BEFORE delivering the
1398
+ // response object — operator inspecting the response can already
1399
+ // count on the jar carrying the new state.
1400
+ if (opts.jar && res.headers && res.headers["set-cookie"]) {
1401
+ try { opts.jar.setFromResponse(opts.url, res.headers["set-cookie"]); }
1402
+ catch (_e) { /* jar is best-effort — never break the response */ }
1403
+ }
1404
+
1405
+ // Download total: Content-Length when present, null otherwise.
1406
+ var dlTotal = null;
1407
+ if (res.headers && typeof res.headers["content-length"] === "string") {
1408
+ var cl = parseInt(res.headers["content-length"], 10);
1409
+ if (!isNaN(cl) && cl >= 0) dlTotal = cl;
1410
+ }
1411
+ var dlLoaded = 0;
1412
+ function _emitDownload(chunkBytes) {
1413
+ if (!onDownloadProgress) return;
1414
+ dlLoaded += chunkBytes;
1415
+ try { onDownloadProgress({ loaded: dlLoaded, total: dlTotal }); }
1416
+ catch (_e) { /* progress hooks are best-effort */ }
1417
+ }
1418
+
1419
+ if (responseMode === "stream") {
1420
+ if (res.statusCode >= 400 && responseMode !== "always-resolve") {
1421
+ res.resume();
1422
+ return _reject(_makeError(opts.errorClass, "HTTP_ERROR",
1423
+ "HTTP " + res.statusCode + " " + (res.statusMessage || ""),
1424
+ _isPermanentStatus(res.statusCode), res.statusCode));
1425
+ }
1426
+ if (onDownloadProgress || onChunk) {
1427
+ // Wrap the stream so chunks emit progress + onChunk to the
1428
+ // operator. The framework's contract is to hand back the
1429
+ // response stream unmodified; fix-up via a passthrough keeps
1430
+ // that contract while observing the chunk sizes. onChunk
1431
+ // gets the buffer itself (for hash-as-you-go); a throw from
1432
+ // it is caught and dropped so a hash-mismatch detector can
1433
+ // raise without breaking the response stream — caller
1434
+ // surfaces the error through their own pipe handler.
1435
+ var passthrough = new nodeStream.PassThrough();
1436
+ res.on("data", function (chunk) {
1437
+ _emitDownload(chunk.length);
1438
+ if (onChunk) {
1439
+ try { onChunk(chunk); }
1440
+ catch (_e) { /* operator-supplied hook — drop-silent */ }
1441
+ }
1442
+ passthrough.write(chunk);
1443
+ });
1444
+ res.on("end", function () { passthrough.end(); });
1445
+ res.on("error", function (e) { passthrough.destroy(e); });
1446
+ return _resolve({ statusCode: res.statusCode, headers: res.headers, body: passthrough });
1447
+ }
1448
+ return _resolve({ statusCode: res.statusCode, headers: res.headers, body: res });
1449
+ }
1450
+
1451
+ var collector = safeBuffer.boundedChunkCollector({ maxBytes: maxResponseBytes });
1452
+ var capExceeded = false;
1453
+
1454
+ res.on("data", function (chunk) {
1455
+ if (capExceeded) return;
1456
+ try { collector.push(chunk); }
1457
+ catch (_e) {
1458
+ capExceeded = true;
1459
+ req.destroy();
1460
+ _reject(_makeError(opts.errorClass, "RESPONSE_TOO_LARGE",
1461
+ "response body exceeds " + maxResponseBytes + " bytes", true));
1462
+ return;
1463
+ }
1464
+ _emitDownload(chunk.length);
1465
+ if (onChunk) {
1466
+ try { onChunk(chunk); }
1467
+ catch (_e) { /* operator-supplied hook — drop-silent */ }
1468
+ }
1469
+ });
1470
+ res.on("end", function () {
1471
+ if (capExceeded) return;
1472
+ var buf = collector.result();
1473
+ if (observer) observer("response:end", {
1474
+ statusCode: res.statusCode,
1475
+ durationMs: Date.now() - startedAt,
1476
+ bytes: buf.length,
1477
+ });
1478
+ if (res.statusCode >= 200 && res.statusCode < 300) {
1479
+ _resolve({ statusCode: res.statusCode, headers: res.headers, body: buf });
1480
+ } else if (opts._resolveOnRedirect && REDIRECT_STATUSES.has(res.statusCode)) {
1481
+ // Redirect-following layer needs the response object intact so
1482
+ // it can inspect Location and re-issue. The caller-facing
1483
+ // request() never sets _resolveOnRedirect — operator code that
1484
+ // didn't ask for redirect-following keeps seeing 3xx as errors.
1485
+ _resolve({ statusCode: res.statusCode, headers: res.headers, body: buf });
1486
+ } else if (responseMode === "always-resolve") {
1487
+ // Operator opted in to "give me the full response object
1488
+ // regardless of status." Caller branches on statusCode in
1489
+ // their own code path — useful for proxies / forwarders /
1490
+ // health-checkers / probe libraries that want to surface
1491
+ // the upstream response structurally instead of via an
1492
+ // error message string.
1493
+ _resolve({ statusCode: res.statusCode, headers: res.headers, body: buf });
1494
+ } else {
1495
+ var msg = "HTTP " + res.statusCode + ": " + buf.toString("utf8").slice(0, 500);
1496
+ _reject(_makeError(opts.errorClass, "HTTP_ERROR", msg,
1497
+ _isPermanentStatus(res.statusCode), res.statusCode));
1498
+ }
1499
+ });
1500
+ res.on("error", function (e) {
1501
+ if (capExceeded) return;
1502
+ if (observer) observer("error", { phase: "response", message: e.message });
1503
+ _reject(_makeError(opts.errorClass, e.code || "RES_ERROR", e.message, false));
1504
+ });
1505
+ });
1506
+
1507
+ req.on("timeout", function () {
1508
+ req.destroy();
1509
+ _reject(_makeError(opts.errorClass, "ETIMEDOUT",
1510
+ "request idle timeout (no data for " + reqOpts.timeout + "ms)", false));
1511
+ });
1512
+
1513
+ req.on("error", function (e) {
1514
+ if (observer) observer("error", { phase: "request", message: e.message });
1515
+ _reject(_makeError(opts.errorClass, e.code || "REQ_ERROR", e.message, false));
1516
+ });
1517
+
1518
+ if (signal) {
1519
+ var onAbort = function () {
1520
+ var r = signal.reason;
1521
+ var code = (r && r.name === "TimeoutError") ? "ETIMEDOUT" : "ABORT";
1522
+ var msg = (r && r.message) || "request aborted";
1523
+ try { req.destroy(r || new Error(msg)); } catch (_e) { /* best-effort req teardown */ }
1524
+ _reject(_makeError(opts.errorClass, code, msg, false));
1525
+ };
1526
+ signal.addEventListener("abort", onAbort, { once: true });
1527
+ }
1528
+
1529
+ // Upload progress: emit { loaded, total } as body bytes go to the
1530
+ // wire. Buffer / string bodies are sliced into chunks ourselves so
1531
+ // operators see incremental progress; Readable bodies emit on each
1532
+ // 'data' event from the source stream.
1533
+ var ulTotal = null;
1534
+ if (Buffer.isBuffer(opts.body)) ulTotal = opts.body.length;
1535
+ else if (typeof opts.body === "string") ulTotal = Buffer.byteLength(opts.body, "utf8");
1536
+ var ulLoaded = 0;
1537
+ function _emitUpload(chunkBytes) {
1538
+ if (!onUploadProgress) return;
1539
+ ulLoaded += chunkBytes;
1540
+ try { onUploadProgress({ loaded: ulLoaded, total: ulTotal }); }
1541
+ catch (_e) { /* progress hooks are best-effort */ }
1542
+ }
1543
+
1544
+ if (opts.body && typeof opts.body.pipe === "function") {
1545
+ if (onUploadProgress) {
1546
+ opts.body.on("data", function (c) { _emitUpload(c.length); });
1547
+ }
1548
+ opts.body.on("error", function (e) {
1549
+ try { req.destroy(); } catch (_) { /* best-effort req teardown */ }
1550
+ _reject(_makeError(opts.errorClass, "REQ_BODY_ERROR",
1551
+ "request body stream error: " + e.message, false));
1552
+ });
1553
+ opts.body.pipe(req);
1554
+ } else if (Buffer.isBuffer(opts.body) || typeof opts.body === "string") {
1555
+ var bodyBuf = Buffer.isBuffer(opts.body) ? opts.body : Buffer.from(opts.body, "utf8");
1556
+ if (onUploadProgress) {
1557
+ // Chunked write so progress reports land before req.end().
1558
+ var CHUNK = C.BYTES.kib(64);
1559
+ var off = 0;
1560
+ while (off < bodyBuf.length) {
1561
+ var slice = bodyBuf.slice(off, Math.min(off + CHUNK, bodyBuf.length));
1562
+ req.write(slice);
1563
+ _emitUpload(slice.length);
1564
+ off += slice.length;
1565
+ }
1566
+ req.end();
1567
+ } else {
1568
+ req.end(bodyBuf);
1569
+ }
1570
+ } else {
1571
+ req.end();
1572
+ }
1573
+ });
1574
+ }
1575
+
1576
+ // ---- _requestH2: node:http2 path ----
1577
+
1578
+ function _requestH2(transport, u, opts) {
1579
+ return new Promise(function (resolve, reject) {
1580
+ var method = (opts.method || "GET").toUpperCase();
1581
+ var responseMode = opts.responseMode || "buffer";
1582
+ var maxResponseBytes = opts.maxResponseBytes ||
1583
+ (method === "GET" ? DEFAULT_GET_CAP : DEFAULT_CONTROL_PLANE_CAP);
1584
+ var observer = typeof opts.observer === "function" ? opts.observer : null;
1585
+ var startedAt = Date.now();
1586
+ var onChunkH2 = typeof opts.onChunk === "function" ? opts.onChunk : null;
1587
+
1588
+ var signal = safeAsync.withTimeoutSignal(opts.signal || null, opts.timeoutMs);
1589
+ if (signal && signal.aborted) {
1590
+ var r0 = signal.reason;
1591
+ var code0 = (r0 && r0.name === "TimeoutError") ? "ETIMEDOUT" : "ABORT";
1592
+ reject(_makeError(opts.errorClass, code0,
1593
+ (r0 && r0.message) || "request aborted before start", false));
1594
+ return;
1595
+ }
1596
+
1597
+ var headers = _toH2Headers(method, u, opts.headers || {});
1598
+ if (Buffer.isBuffer(opts.body)) headers["content-length"] = String(opts.body.length);
1599
+
1600
+ if (observer) observer("request:start", { method: method, url: String(opts.url), protocol: "h2" });
1601
+
1602
+ var stream;
1603
+ try {
1604
+ stream = transport.session.request(headers, {
1605
+ endStream: opts.body == null,
1606
+ });
1607
+ } catch (e) {
1608
+ reject(_makeError(opts.errorClass, e.code || "H2_REQUEST_ERROR", e.message, false));
1609
+ return;
1610
+ }
1611
+
1612
+ var settled = false;
1613
+ function _resolve(v) { if (!settled) { settled = true; resolve(v); } }
1614
+ function _reject(e) { if (!settled) { settled = true; reject(e); } }
1615
+
1616
+ // Idle timeout for the stream itself (zero-progress detector).
1617
+ var idleMs = typeof opts.idleTimeoutMs === "number" ? opts.idleTimeoutMs : DEFAULT_IDLE_TIMEOUT_MS;
1618
+ stream.setTimeout(idleMs, function () {
1619
+ try { stream.close(http2.constants.NGHTTP2_CANCEL); } catch (_e) { /* best-effort h2 stream cancel */ }
1620
+ _reject(_makeError(opts.errorClass, "ETIMEDOUT",
1621
+ "h2 stream idle timeout (no data for " + idleMs + "ms)", false));
1622
+ });
1623
+
1624
+ stream.on("response", function (resHeaders) {
1625
+ var statusCode = resHeaders[":status"];
1626
+ var responseHeaders = _fromH2Headers(resHeaders);
1627
+
1628
+ if (observer) observer("response:headers", { statusCode: statusCode, headers: responseHeaders });
1629
+
1630
+ // Save Set-Cookie to the jar (h2 set-cookie comes through as
1631
+ // either a single string or array, same shape as h1).
1632
+ if (opts.jar && responseHeaders["set-cookie"]) {
1633
+ try { opts.jar.setFromResponse(opts.url, responseHeaders["set-cookie"]); }
1634
+ catch (_e) { /* jar best-effort */ }
1635
+ }
1636
+
1637
+ if (responseMode === "stream") {
1638
+ if (statusCode >= 400 && responseMode !== "always-resolve") {
1639
+ stream.resume();
1640
+ return _reject(_makeError(opts.errorClass, "HTTP_ERROR",
1641
+ "HTTP " + statusCode, _isPermanentStatus(statusCode), statusCode));
1642
+ }
1643
+ if (onChunkH2) {
1644
+ var passthroughH2 = new nodeStream.PassThrough();
1645
+ stream.on("data", function (chunk) {
1646
+ try { onChunkH2(chunk); }
1647
+ catch (_e) { /* operator-supplied hook — drop-silent */ }
1648
+ passthroughH2.write(chunk);
1649
+ });
1650
+ stream.on("end", function () { passthroughH2.end(); });
1651
+ stream.on("error", function (e) { passthroughH2.destroy(e); });
1652
+ return _resolve({ statusCode: statusCode, headers: responseHeaders, body: passthroughH2 });
1653
+ }
1654
+ return _resolve({ statusCode: statusCode, headers: responseHeaders, body: stream });
1655
+ }
1656
+
1657
+ var collector = safeBuffer.boundedChunkCollector({ maxBytes: maxResponseBytes });
1658
+ var capExceeded = false;
1659
+
1660
+ stream.on("data", function (chunk) {
1661
+ if (capExceeded) return;
1662
+ try { collector.push(chunk); }
1663
+ catch (_e) {
1664
+ capExceeded = true;
1665
+ try { stream.close(http2.constants.NGHTTP2_CANCEL); } catch (_e2) { /* best-effort h2 stream cancel */ }
1666
+ _reject(_makeError(opts.errorClass, "RESPONSE_TOO_LARGE",
1667
+ "response body exceeds " + maxResponseBytes + " bytes", true));
1668
+ return;
1669
+ }
1670
+ if (onChunkH2) {
1671
+ try { onChunkH2(chunk); }
1672
+ catch (_e) { /* operator-supplied hook — drop-silent */ }
1673
+ }
1674
+ });
1675
+ stream.on("end", function () {
1676
+ if (capExceeded) return;
1677
+ var buf = collector.result();
1678
+ if (observer) observer("response:end", {
1679
+ statusCode: statusCode,
1680
+ durationMs: Date.now() - startedAt,
1681
+ bytes: buf.length,
1682
+ });
1683
+ if (statusCode >= 200 && statusCode < 300) {
1684
+ _resolve({ statusCode: statusCode, headers: responseHeaders, body: buf });
1685
+ } else if (responseMode === "always-resolve") {
1686
+ _resolve({ statusCode: statusCode, headers: responseHeaders, body: buf });
1687
+ } else {
1688
+ var msg = "HTTP " + statusCode + ": " + buf.toString("utf8").slice(0, 500);
1689
+ _reject(_makeError(opts.errorClass, "HTTP_ERROR", msg,
1690
+ _isPermanentStatus(statusCode), statusCode));
1691
+ }
1692
+ });
1693
+ });
1694
+
1695
+ stream.on("error", function (e) {
1696
+ if (observer) observer("error", { phase: "stream", message: e.message });
1697
+ _reject(_makeError(opts.errorClass, e.code || "H2_STREAM_ERROR", e.message, false));
1698
+ });
1699
+
1700
+ if (signal) {
1701
+ var onAbort = function () {
1702
+ var r = signal.reason;
1703
+ var code = (r && r.name === "TimeoutError") ? "ETIMEDOUT" : "ABORT";
1704
+ var msg = (r && r.message) || "request aborted";
1705
+ // NGHTTP2_CANCEL is the protocol-level "I gave up" signal —
1706
+ // cleaner than destroying the stream.
1707
+ try { stream.close(http2.constants.NGHTTP2_CANCEL); } catch (_e) { /* best-effort h2 stream cancel */ }
1708
+ _reject(_makeError(opts.errorClass, code, msg, false));
1709
+ };
1710
+ signal.addEventListener("abort", onAbort, { once: true });
1711
+ }
1712
+
1713
+ if (opts.body && typeof opts.body.pipe === "function") {
1714
+ opts.body.on("error", function (e) {
1715
+ try { stream.close(http2.constants.NGHTTP2_INTERNAL_ERROR); } catch (_) { /* best-effort h2 stream cancel */ }
1716
+ _reject(_makeError(opts.errorClass, "REQ_BODY_ERROR",
1717
+ "request body stream error: " + e.message, false));
1718
+ });
1719
+ opts.body.pipe(stream);
1720
+ } else if (Buffer.isBuffer(opts.body)) {
1721
+ stream.end(opts.body);
1722
+ } else if (typeof opts.body === "string") {
1723
+ stream.end(Buffer.from(opts.body, "utf8"));
1724
+ }
1725
+ // If body is null/undefined, endStream:true was set in session.request()
1726
+ });
1727
+ }
1728
+
1729
+ // ---- Streaming primitives ----
1730
+ //
1731
+ // downloadStream — pipe a response body to a tmp file, hash-while-piping,
1732
+ // atomic-rename on hash match. Operators receive `{ statusCode,
1733
+ // bytesWritten, hash }`; on hash mismatch the tmp file is deleted and an
1734
+ // HttpClientError with code "httpclient/hash-mismatch" is thrown.
1735
+ //
1736
+ // uploadMultipartStream — POST a file body via multipart/form-data
1737
+ // without buffering. Streams from disk through the request body using
1738
+ // `nodeFs.createReadStream` + `node:stream/promises` pipeline.
1739
+ //
1740
+ // Both compose through `request()` (responseMode: "stream") so safeUrl,
1741
+ // ssrfGuard, allowedHosts, network-proxy, audit-on-host-deny, and the
1742
+ // per-origin transport cache apply unchanged.
1743
+
1744
+ // Algorithms exposed to operators. Defaults to PQC-first sha3-512;
1745
+ // callers needing legacy-peer interop with sha-256 (S3 ETag class) opt
1746
+ // in explicitly.
1747
+ var ALLOWED_DOWNLOAD_HASH_ALGS = ["sha3-512", "sha-256", "sha-512", "shake256"];
1748
+ var DEFAULT_DOWNLOAD_HASH_ALG = "sha3-512";
1749
+ var DEFAULT_DOWNLOAD_FILE_MODE = 0o600;
1750
+
1751
+ function _hcErr(code, message, statusCode) {
1752
+ return new HttpClientError(code, message, true, statusCode);
1753
+ }
1754
+
1755
+ // Throw at config-time if opts shape is malformed — operator catches the
1756
+ // typo here, not inside the request loop.
1757
+ function _validateDownloadOpts(opts) {
1758
+ if (!opts || typeof opts !== "object") {
1759
+ throw _hcErr("httpclient/bad-opts", "downloadStream: opts must be an object");
1760
+ }
1761
+ validateOpts.requireNonEmptyString(opts.url, "downloadStream: url",
1762
+ HttpClientError, "httpclient/bad-opts");
1763
+ validateOpts.requireNonEmptyString(opts.dest, "downloadStream: dest",
1764
+ HttpClientError, "httpclient/bad-opts");
1765
+ validateOpts.optionalNonEmptyString(opts.hash, "downloadStream: hash",
1766
+ HttpClientError, "httpclient/bad-opts");
1767
+ if (opts.hash !== undefined && ALLOWED_DOWNLOAD_HASH_ALGS.indexOf(opts.hash) === -1) {
1768
+ throw _hcErr("httpclient/bad-opts",
1769
+ "downloadStream: hash must be one of " + ALLOWED_DOWNLOAD_HASH_ALGS.join(", ") +
1770
+ "; got " + JSON.stringify(opts.hash));
1771
+ }
1772
+ if (opts.expected !== undefined) {
1773
+ validateOpts.requireNonEmptyString(opts.expected, "downloadStream: expected",
1774
+ HttpClientError, "httpclient/bad-opts");
1775
+ if (!safeBuffer.isHex(opts.expected)) {
1776
+ throw _hcErr("httpclient/bad-opts",
1777
+ "downloadStream: expected must be a non-empty hex digest");
1778
+ }
1779
+ }
1780
+ validateOpts.optionalPositiveFinite(opts.timeoutMs, "downloadStream: timeoutMs",
1781
+ HttpClientError, "httpclient/bad-opts");
1782
+ if (opts.maxBytes !== undefined &&
1783
+ (typeof opts.maxBytes !== "number" || !isFinite(opts.maxBytes) || opts.maxBytes <= 0 ||
1784
+ Math.floor(opts.maxBytes) !== opts.maxBytes)) {
1785
+ throw _hcErr("httpclient/bad-opts",
1786
+ "downloadStream: maxBytes must be a positive finite integer");
1787
+ }
1788
+ }
1789
+
1790
+ function _emitAudit(opts, action, outcome, metadata) {
1791
+ if (!opts || !opts.audit || typeof opts.audit.safeEmit !== "function") return;
1792
+ try {
1793
+ opts.audit.safeEmit({
1794
+ action: action,
1795
+ outcome: outcome,
1796
+ resource: { kind: "outbound.http", id: String(opts.url || "") },
1797
+ metadata: metadata || {},
1798
+ });
1799
+ } catch (_e) { /* audit best-effort */ }
1800
+ }
1801
+
1802
+ /**
1803
+ * @primitive b.httpClient.downloadStream
1804
+ * @signature b.httpClient.downloadStream(opts)
1805
+ * @since 0.1.0
1806
+ * @status stable
1807
+ * @related b.httpClient.request, b.httpClient.uploadMultipartStream, b.atomicFile.ensureDir
1808
+ *
1809
+ * Streams a remote resource to disk while hashing the bytes in flight,
1810
+ * then atomically renames the tmp file to `opts.dest` only after the
1811
+ * hash matches `opts.expected` (when supplied). Hash mismatch deletes
1812
+ * the tmp file and throws `httpclient/hash-mismatch`. Composes through
1813
+ * `request({ responseMode: "stream" })` so the SSRF gate, allowedHosts
1814
+ * filter, network proxy, and per-origin transport cache all apply.
1815
+ *
1816
+ * @opts
1817
+ * url: <required>, // string — source
1818
+ * dest: <required>, // absolute filesystem path — final landing
1819
+ * hash: "sha3-512", // "sha3-512" | "sha-256" | "sha-512" | "shake256"
1820
+ * expected: undefined, // hex digest; when set, verified before rename
1821
+ * timeoutMs: undefined, // wall-clock cap
1822
+ * maxBytes: undefined, // positive integer — abort past this size
1823
+ * audit: undefined, // audit sink with safeEmit({...})
1824
+ *
1825
+ * @example
1826
+ * var result = await b.httpClient.downloadStream({
1827
+ * url: "https://example.com/release.tar.gz",
1828
+ * dest: "/var/lib/blamejs/release.tar.gz",
1829
+ * hash: "sha3-512",
1830
+ * expected: "9f86d081884c7d65...d4e5",
1831
+ * });
1832
+ * // → { statusCode: 200, bytesWritten: 1048576, hash: "9f86d081884c7d65...d4e5" }
1833
+ */
1834
+ async function downloadStream(opts) {
1835
+ _validateDownloadOpts(opts);
1836
+ var alg = opts.hash || DEFAULT_DOWNLOAD_HASH_ALG;
1837
+ var dest = opts.dest;
1838
+ var tmpPath = dest + ".tmp-" + bCrypto.generateToken(C.BYTES.bytes(8));
1839
+ var dir = nodePath.dirname(dest);
1840
+
1841
+ atomicFile.ensureDir(dir);
1842
+
1843
+ // Stream-mode request — body is a Readable that emits the response
1844
+ // chunks. The framework's onChunk path is intentionally NOT used here
1845
+ // because we own the destination tmp file and need precise error
1846
+ // ordering between hash + write-fsync + rename.
1847
+ var res;
1848
+ try {
1849
+ res = await request({
1850
+ method: "GET",
1851
+ url: opts.url,
1852
+ headers: opts.headers || {},
1853
+ responseMode: "stream",
1854
+ timeoutMs: opts.timeoutMs,
1855
+ idleTimeoutMs: opts.idleTimeoutMs,
1856
+ signal: opts.signal,
1857
+ agent: opts.agent,
1858
+ allowedProtocols: opts.allowedProtocols,
1859
+ allowedHosts: opts.allowedHosts,
1860
+ allowInternal: opts.allowInternal,
1861
+ audit: opts.audit,
1862
+ errorClass: HttpClientError,
1863
+ });
1864
+ } catch (e) {
1865
+ _emitAudit(opts, "system.httpclient.download_stream.refused", "denied", {
1866
+ reason: "request-failed", message: e.message, code: e.code,
1867
+ });
1868
+ throw e;
1869
+ }
1870
+
1871
+ if (res.statusCode < 200 || res.statusCode >= 300) {
1872
+ // Stream mode of request() already rejected on >=400 above, so this
1873
+ // branch covers 1xx/3xx surfaces that slipped through. Drain + refuse.
1874
+ if (res.body && typeof res.body.resume === "function") res.body.resume();
1875
+ _emitAudit(opts, "system.httpclient.download_stream.refused", "denied", {
1876
+ reason: "non-2xx", statusCode: res.statusCode,
1877
+ });
1878
+ throw _hcErr("httpclient/http-error",
1879
+ "downloadStream: upstream returned HTTP " + res.statusCode, res.statusCode);
1880
+ }
1881
+
1882
+ var hasher = nodeCrypto.createHash(alg);
1883
+ var counter = new nodeStream.Transform({
1884
+ transform: function (chunk, _enc, cb) {
1885
+ hasher.update(chunk);
1886
+ counter.bytesWritten += chunk.length;
1887
+ if (typeof opts.maxBytes === "number" && counter.bytesWritten > opts.maxBytes) {
1888
+ return cb(_hcErr("httpclient/response-too-large",
1889
+ "downloadStream: response body exceeds maxBytes " + opts.maxBytes, res.statusCode));
1890
+ }
1891
+ cb(null, chunk);
1892
+ },
1893
+ });
1894
+ counter.bytesWritten = 0;
1895
+
1896
+ var fileStream = nodeFs.createWriteStream(tmpPath, { mode: DEFAULT_DOWNLOAD_FILE_MODE, flags: "w" });
1897
+
1898
+ try {
1899
+ await streamPromises.pipeline(res.body, counter, fileStream);
1900
+ } catch (e) {
1901
+ // Pipeline failure → tmp may be partially written. Remove + audit.
1902
+ try { nodeFs.unlinkSync(tmpPath); } catch (_u) { /* best-effort cleanup */ }
1903
+ _emitAudit(opts, "system.httpclient.download_stream.refused", "denied", {
1904
+ reason: "pipeline-failed", message: e.message, code: e.code,
1905
+ });
1906
+ if (e && e.isHttpClientError) throw e;
1907
+ throw _hcErr(e.code || "httpclient/pipeline-failed",
1908
+ "downloadStream: pipeline failed: " + (e.message || String(e)), res.statusCode);
1909
+ }
1910
+
1911
+ // fsync the file's data + close. atomicFile.fsync is best-effort
1912
+ // across platforms but matches the discipline of the rest of the
1913
+ // framework's atomic-write paths.
1914
+ //
1915
+ // CodeQL js/insecure-temporary-file: tmpPath = dest + ".tmp-" +
1916
+ // bCrypto.generateToken(C.BYTES.bytes(8)) (line 1802), where
1917
+ // bCrypto.generateToken produces 16 hex chars of CSPRNG-derived
1918
+ // randomness. The path lives next to operator-supplied `dest`
1919
+ // (downloadStream contract — never under os.tmpdir()), and the
1920
+ // 64-bit unpredictable suffix defeats the symlink-pre-creation
1921
+ // attack the rule flags. The fd is used solely for fsync; the
1922
+ // file's bytes were already written by the upstream pipeline.
1923
+ try {
1924
+ var fd = nodeFs.openSync(tmpPath, "r+");
1925
+ try { atomicFile.fsync(fd); } finally { try { nodeFs.closeSync(fd); } catch (_c) { /* best-effort fd close */ } }
1926
+ } catch (_fe) { /* fsync best-effort */ }
1927
+
1928
+ var actualHex = hasher.digest("hex");
1929
+ if (typeof opts.expected === "string" && opts.expected.length > 0) {
1930
+ var expected = opts.expected.toLowerCase();
1931
+ if (actualHex.toLowerCase() !== expected) {
1932
+ try { nodeFs.unlinkSync(tmpPath); } catch (_u) { /* best-effort cleanup */ }
1933
+ _emitAudit(opts, "system.httpclient.download_stream.refused", "denied", {
1934
+ reason: "hash-mismatch", alg: alg, expected: expected, actual: actualHex,
1935
+ statusCode: res.statusCode, bytesWritten: counter.bytesWritten,
1936
+ });
1937
+ throw _hcErr("httpclient/hash-mismatch",
1938
+ "downloadStream: hash mismatch (alg=" + alg + ", expected=" + expected +
1939
+ ", actual=" + actualHex + ")", res.statusCode);
1940
+ }
1941
+ }
1942
+
1943
+ // Atomic rename + dir fsync.
1944
+ try {
1945
+ nodeFs.renameSync(tmpPath, dest);
1946
+ atomicFile.fsyncDir(dir);
1947
+ } catch (e) {
1948
+ try { nodeFs.unlinkSync(tmpPath); } catch (_u) { /* best-effort cleanup */ }
1949
+ _emitAudit(opts, "system.httpclient.download_stream.refused", "denied", {
1950
+ reason: "rename-failed", message: e.message,
1951
+ });
1952
+ throw _hcErr("httpclient/rename-failed",
1953
+ "downloadStream: rename to " + dest + " failed: " + e.message, res.statusCode);
1954
+ }
1955
+
1956
+ _emitAudit(opts, "system.httpclient.download_stream.completed", "allowed", {
1957
+ statusCode: res.statusCode,
1958
+ bytesWritten: counter.bytesWritten,
1959
+ alg: alg,
1960
+ hashVerified: typeof opts.expected === "string" && opts.expected.length > 0,
1961
+ });
1962
+
1963
+ return {
1964
+ statusCode: res.statusCode,
1965
+ bytesWritten: counter.bytesWritten,
1966
+ hash: actualHex,
1967
+ };
1968
+ }
1969
+
1970
+ // ---- uploadMultipartStream ----
1971
+
1972
+ function _validateUploadOpts(opts) {
1973
+ if (!opts || typeof opts !== "object") {
1974
+ throw _hcErr("httpclient/bad-opts", "uploadMultipartStream: opts must be an object");
1975
+ }
1976
+ validateOpts.requireNonEmptyString(opts.url, "uploadMultipartStream: url",
1977
+ HttpClientError, "httpclient/bad-opts");
1978
+ if (!opts.file || typeof opts.file !== "object") {
1979
+ throw _hcErr("httpclient/bad-opts", "uploadMultipartStream: file must be an object");
1980
+ }
1981
+ validateOpts.requireNonEmptyString(opts.file.path, "uploadMultipartStream: file.path",
1982
+ HttpClientError, "httpclient/bad-opts");
1983
+ validateOpts.requireNonEmptyString(opts.file.fieldName, "uploadMultipartStream: file.fieldName",
1984
+ HttpClientError, "httpclient/bad-opts");
1985
+ if (opts.fields !== undefined && (typeof opts.fields !== "object" || opts.fields === null || Array.isArray(opts.fields))) {
1986
+ throw _hcErr("httpclient/bad-opts", "uploadMultipartStream: fields must be an object");
1987
+ }
1988
+ validateOpts.optionalPositiveFinite(opts.timeoutMs, "uploadMultipartStream: timeoutMs",
1989
+ HttpClientError, "httpclient/bad-opts");
1990
+ if (opts.maxBytes !== undefined &&
1991
+ (typeof opts.maxBytes !== "number" || !isFinite(opts.maxBytes) || opts.maxBytes <= 0 ||
1992
+ Math.floor(opts.maxBytes) !== opts.maxBytes)) {
1993
+ throw _hcErr("httpclient/bad-opts",
1994
+ "uploadMultipartStream: maxBytes must be a positive finite integer");
1995
+ }
1996
+ }
1997
+
1998
+ /**
1999
+ * @primitive b.httpClient.uploadMultipartStream
2000
+ * @signature b.httpClient.uploadMultipartStream(opts)
2001
+ * @since 0.1.0
2002
+ * @status stable
2003
+ * @related b.httpClient.request, b.httpClient.downloadStream
2004
+ *
2005
+ * POSTs a file body via `multipart/form-data` without buffering the
2006
+ * file in memory. Streams from disk through the request body using
2007
+ * `fs.createReadStream` + `node:stream/promises` pipeline. Throws
2008
+ * `httpclient/missing-file` when `opts.file.path` doesn't exist or
2009
+ * isn't a regular file. Composes through `request()` so SSRF gating,
2010
+ * proxy routing, and the per-origin transport cache apply unchanged.
2011
+ *
2012
+ * @opts
2013
+ * url: <required>, // string — destination
2014
+ * file: <required>, // { path, fieldName, filename?, contentType? }
2015
+ * fields: undefined, // object — extra form fields { name: value, ... }
2016
+ * timeoutMs: undefined, // wall-clock cap
2017
+ * maxBytes: undefined, // positive integer — refuse files larger than this
2018
+ * audit: undefined, // audit sink with safeEmit({...})
2019
+ *
2020
+ * @example
2021
+ * var res = await b.httpClient.uploadMultipartStream({
2022
+ * url: "https://example.com/upload",
2023
+ * file: {
2024
+ * path: "/var/lib/blamejs/release.tar.gz",
2025
+ * fieldName: "artifact",
2026
+ * contentType: "application/gzip",
2027
+ * },
2028
+ * fields: { releaseTag: "v1.2.3" },
2029
+ * });
2030
+ * // → { statusCode: 200, headers: { ... }, body: <Buffer> }
2031
+ */
2032
+ async function uploadMultipartStream(opts) {
2033
+ _validateUploadOpts(opts);
2034
+
2035
+ var filePath = opts.file.path;
2036
+ var st;
2037
+ try { st = nodeFs.statSync(filePath); }
2038
+ catch (e) {
2039
+ _emitAudit(opts, "system.httpclient.upload_stream.refused", "denied", {
2040
+ reason: "missing-file", path: filePath, message: e.message,
2041
+ });
2042
+ throw _hcErr("httpclient/missing-file",
2043
+ "uploadMultipartStream: file.path not readable: " + e.message);
2044
+ }
2045
+ if (!st.isFile()) {
2046
+ _emitAudit(opts, "system.httpclient.upload_stream.refused", "denied", {
2047
+ reason: "not-a-regular-file", path: filePath,
2048
+ });
2049
+ throw _hcErr("httpclient/missing-file",
2050
+ "uploadMultipartStream: file.path is not a regular file");
2051
+ }
2052
+
2053
+ var filename = (typeof opts.file.filename === "string" && opts.file.filename.length > 0)
2054
+ ? opts.file.filename
2055
+ : nodePath.basename(filePath);
2056
+ var contentType = (typeof opts.file.contentType === "string" && opts.file.contentType.length > 0)
2057
+ ? opts.file.contentType
2058
+ : "application/octet-stream";
2059
+
2060
+ // Reuse the existing multipart shorthand by passing { filePath } —
2061
+ // it produces a Readable body + sets Content-Length when sizes resolve.
2062
+ // _buildMultipartBody is internal; we route through request()'s
2063
+ // multipart shorthand so the same wire path applies.
2064
+ var fileSpec = {
2065
+ field: opts.file.fieldName,
2066
+ filePath: filePath,
2067
+ filename: filename,
2068
+ contentType: contentType,
2069
+ };
2070
+
2071
+ var res;
2072
+ try {
2073
+ res = await request({
2074
+ method: "POST",
2075
+ url: opts.url,
2076
+ headers: opts.headers || {},
2077
+ multipart: { fields: opts.fields || {}, files: [fileSpec], streaming: true },
2078
+ timeoutMs: opts.timeoutMs,
2079
+ idleTimeoutMs: opts.idleTimeoutMs,
2080
+ signal: opts.signal,
2081
+ agent: opts.agent,
2082
+ allowedProtocols: opts.allowedProtocols,
2083
+ allowedHosts: opts.allowedHosts,
2084
+ allowInternal: opts.allowInternal,
2085
+ maxResponseBytes: opts.maxResponseBytes,
2086
+ audit: opts.audit,
2087
+ errorClass: HttpClientError,
2088
+ });
2089
+ } catch (e) {
2090
+ _emitAudit(opts, "system.httpclient.upload_stream.refused", "denied", {
2091
+ reason: "request-failed", message: e.message, code: e.code,
2092
+ });
2093
+ throw e;
2094
+ }
2095
+
2096
+ _emitAudit(opts, "system.httpclient.upload_stream.completed", "allowed", {
2097
+ statusCode: res.statusCode,
2098
+ fileBytes: st.size,
2099
+ fieldName: opts.file.fieldName,
2100
+ filename: filename,
2101
+ });
2102
+
2103
+ return {
2104
+ statusCode: res.statusCode,
2105
+ response: res,
2106
+ };
2107
+ }
2108
+
2109
+ // ---- Test helpers ----
2110
+
2111
+ function _resetForTest() {
2112
+ _transports.forEach(function (t) {
2113
+ if (t && t.kind === "h1" && t.agent && typeof t.agent.destroy === "function") {
2114
+ try { t.agent.destroy(); } catch (_e) { /* best-effort agent teardown */ }
2115
+ }
2116
+ if (t && t.kind === "h2" && t.session) {
2117
+ _tearDownH2Session(t.session);
2118
+ }
2119
+ });
2120
+ _transports.clear();
2121
+ }
2122
+
2123
+ function _getCachedTransportCount() {
2124
+ return _transports.size;
2125
+ }
2126
+
2127
+ // Diagnostic — returns 'h1' | 'h2' | null for a given URL's cached transport.
2128
+ function _getCachedTransportKind(url) {
2129
+ var u = url instanceof URL ? url : safeUrl.parse(url, { allowedProtocols: safeUrl.ALLOW_HTTP_ALL });
2130
+ var t = _transports.get(_originKey(u));
2131
+ if (!t) return null;
2132
+ if (t.then) return "pending";
2133
+ return t.kind;
2134
+ }
2135
+
2136
+ module.exports = {
2137
+ request: request,
2138
+ downloadStream: downloadStream,
2139
+ uploadMultipartStream: uploadMultipartStream,
2140
+ configurePool: configurePool,
2141
+ DEFAULT_CONTROL_PLANE_CAP: DEFAULT_CONTROL_PLANE_CAP,
2142
+ DEFAULT_GET_CAP: DEFAULT_GET_CAP,
2143
+ DEFAULT_AGENT_OPTS: DEFAULT_AGENT_OPTS,
2144
+ ALLOWED_DOWNLOAD_HASH_ALGS: ALLOWED_DOWNLOAD_HASH_ALGS,
2145
+ _resetForTest: _resetForTest,
2146
+ _getCachedTransportCount: _getCachedTransportCount,
2147
+ _getCachedTransportKind: _getCachedTransportKind,
2148
+ // Test-only — exposes the SSRF-pinned DNS lookup builder so unit
2149
+ // tests can confirm the callback shape matches Node's documented
2150
+ // `lookup(hostname, options, callback)` contract.
2151
+ _pinnedLookupForTest: _pinnedLookupFor,
2152
+ };