@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,1971 @@
1
+ "use strict";
2
+ /**
3
+ * @module b.mail
4
+ * @featured true
5
+ * @nav Communication
6
+ * @title Mail
7
+ *
8
+ * @intro
9
+ * SMTP / HTTP-API email send with multipart RFC 5322 message
10
+ * composition, DKIM signing on the way out, and full inbound mail-
11
+ * authentication parsing on the way in. Builds a multipart/alternative
12
+ * body for text+html, multipart/related for inline images via `cid:`
13
+ * references, multipart/mixed when attachments are present, and
14
+ * handles SMTPUTF8 (RFC 6531) + IDN domain Punycode (RFC 3492) for
15
+ * internationalized addresses.
16
+ *
17
+ * Transports ship as `b.mail.transports.*`: `console` (stderr dev
18
+ * default), `memory` (captures to `sent[]` for fixtures), `smtp`
19
+ * (raw RFC 5321 over net / tls with STARTTLS, AUTH LOGIN, and PQC-
20
+ * friendly TLS opts), `http` (generic JSON-over-HTTPS for any vendor
21
+ * speaking that contract — Postmark / Mailgun / SES HTTP / SendGrid /
22
+ * Resend), `resend` (thin preset wiring `http` to the Resend API as
23
+ * the worked example). Operators can also pass any function or
24
+ * `{ send }` object as a custom transport.
25
+ *
26
+ * DKIM-Signature header generation lives at `b.mail.dkim` (rsa-sha256
27
+ * default, ed25519-sha256 opt-in, dual-signer per RFC 8463 §3 for
28
+ * transition windows). Inbound authentication-results parsing —
29
+ * SPF (RFC 7208), DMARC (RFC 7489), ARC chain trust evaluation
30
+ * (RFC 8617) — is exposed as `b.mail.spf` / `b.mail.dmarc` /
31
+ * `b.mail.arc` / `b.mail.authResults`. BIMI (RFC draft) is at
32
+ * `b.mail.bimi`. RFC 8058 one-click List-Unsubscribe lives at
33
+ * `b.mail.unsubscribe` and folds in automatically when the message
34
+ * carries `unsubscribe: { url | mailto, oneClick? }`.
35
+ *
36
+ * CAN-SPAM Act §7704 enforcement is on-by-default for instances
37
+ * created with `commercial: true`: every send refuses unless the
38
+ * instance supplied `postalAddress` AND the message exposes a
39
+ * functional opt-out (List-Unsubscribe header or `unsubscribe.{url|
40
+ * mailto}` on the message). The postal address auto-appends to both
41
+ * text and html bodies via the configured separator; operators
42
+ * override the html footer with `footerHtml` (must still contain the
43
+ * country + postal-code bytes — the framework refuses operator
44
+ * overrides that drop the legally-required address).
45
+ *
46
+ * Validation surface uses `MailError` (a `FrameworkError` subclass)
47
+ * with stable codes per failure: `missing-to` / `missing-from` /
48
+ * `missing-body` / `invalid-recipient` / `mail/transport-failed` /
49
+ * `smtp-*` / `http-*` / `resend-*`. Vendor-specific presets carry
50
+ * their own code prefix so diagnostic logs identify the provider
51
+ * that rejected the message. Audit emits `mail.send.success` /
52
+ * `mail.send.failure` / `mail.canspam.refused` and records recipient
53
+ * COUNTS only — addresses are PII, never auto-logged.
54
+ *
55
+ * @card
56
+ * SMTP / HTTP-API email send with multipart RFC 5322 message composition, DKIM signing on the way out, and full inbound mail- authentication parsing on the way in.
57
+ */
58
+ var C = require("./constants");
59
+ var bCrypto = require("./crypto");
60
+ var lazyRequire = require("./lazy-require");
61
+ var safeBuffer = require("./safe-buffer");
62
+ var guardDomain = require("./guard-domain");
63
+ var audit = lazyRequire(function () { return require("./audit"); });
64
+ var httpClient = lazyRequire(function () { return require("./http-client"); });
65
+ var guardEmail = lazyRequire(function () { return require("./guard-email"); });
66
+ var guardFilename = lazyRequire(function () { return require("./guard-filename"); });
67
+ var fileType = lazyRequire(function () { return require("./file-type"); });
68
+ var dkim = require("./mail-dkim");
69
+ var ipUtils = require("./ip-utils");
70
+ var mailAuth = require("./mail-auth");
71
+ var mailBimi = require("./mail-bimi");
72
+ var mailUnsubscribe = require("./mail-unsubscribe");
73
+ var mailAgent = require("./mail-agent");
74
+ var net = lazyRequire(function () { return require("node:net"); });
75
+ var networkDns = lazyRequire(function () { return require("./network-dns"); });
76
+ var nodeUrl = require("node:url");
77
+ var numericBounds = require("./numeric-bounds");
78
+ var nodeTls = lazyRequire(function () { return require("node:tls"); });
79
+ var safeJson = require("./safe-json");
80
+ var safeSchema = require("./safe-schema");
81
+ var validateOpts = require("./validate-opts");
82
+ var { FrameworkError } = require("./framework-error");
83
+
84
+ // Cap on responses parsed from upstream mail providers (Resend, etc.).
85
+ // Vendor responses are tiny in spec; 256 KiB is generous headroom.
86
+ var MAIL_RESPONSE_MAX_BYTES = C.BYTES.kib(256);
87
+
88
+ class MailError extends FrameworkError {
89
+ constructor(code, message, permanent, statusCode) {
90
+ super(message, code);
91
+ this.name = "MailError";
92
+ this.permanent = !!permanent;
93
+ this.isMailError = true;
94
+ if (typeof statusCode === "number") this.statusCode = statusCode;
95
+ }
96
+ }
97
+
98
+ // Pragmatic email regex — shared with forms.validate / safe-schema.
99
+ // RFC 5322 in a regex is a fool's errand; this catches obvious nonsense
100
+ // and lets real-world addresses through.
101
+ var EMAIL_RE = safeSchema.EMAIL_RE;
102
+ // RFC 5321 §4.5.3.1.3 forward-path bound — bound length BEFORE the regex
103
+ // test so a megabyte-long input can't exhaust the regex engine.
104
+ var EMAIL_MAX_LEN = 254;
105
+
106
+ // EAI / SMTPUTF8 — RFC 6531/6532/6533 internationalized email. Detect
107
+ // non-ASCII content; convert IDN domains to Punycode (RFC 3492) for the
108
+ // ASCII path, leave them in Unicode where the peer announces SMTPUTF8.
109
+
110
+ // Match any code point outside ASCII (U+0080 and above). Used to
111
+ // detect EAI / SMTPUTF8-required content in an address or subject.
112
+ // eslint-disable-next-line no-control-regex
113
+ var NON_ASCII_RE = /[^\x00-\x7f]/;
114
+
115
+ function _isAscii(s) {
116
+ if (typeof s !== "string" || s.length > EMAIL_MAX_LEN) return false; // bound BEFORE regex test
117
+ return !NON_ASCII_RE.test(s);
118
+ }
119
+
120
+ /**
121
+ * @primitive b.mail.toAscii
122
+ * @signature b.mail.toAscii(domain)
123
+ * @since 0.7.16
124
+ * @status stable
125
+ * @related b.mail.toUnicode, b.mail.create
126
+ *
127
+ * RFC 3492 Punycode encode an IDN domain to its ASCII-compatible form.
128
+ * `domain` MUST be the part after `@` — pass the local part separately.
129
+ * Returns the encoded ASCII string, or `null` when the input isn't a
130
+ * valid IDN-encodable domain. Used internally by `send()` to convert
131
+ * IDN domain parts before the pre-SMTPUTF8 ASCII regex check; surfaced
132
+ * publicly so operators wiring custom transports can apply the same
133
+ * normalization.
134
+ *
135
+ * @example
136
+ * var b = require("@blamejs/core");
137
+ * var ascii = b.mail.toAscii("münchen.de");
138
+ * // → "xn--mnchen-3ya.de"
139
+ */
140
+ function toAscii(domain) {
141
+ if (typeof domain !== "string" || domain.length === 0) return null;
142
+ var ascii;
143
+ try { ascii = nodeUrl.domainToASCII(domain); }
144
+ catch (_e) { return null; }
145
+ if (typeof ascii !== "string" || ascii.length === 0) return null;
146
+ return ascii;
147
+ }
148
+
149
+ /**
150
+ * @primitive b.mail.toUnicode
151
+ * @signature b.mail.toUnicode(domain)
152
+ * @since 0.7.16
153
+ * @status stable
154
+ * @related b.mail.toAscii, b.mail.create
155
+ *
156
+ * Decode an ASCII-Compatible-Encoding (Punycode `xn--…`) domain back
157
+ * to its Unicode form. Returns `null` when the input isn't a valid
158
+ * IDN domain. Operators rendering received-from / authentication-
159
+ * results trace lines use this to display the human-readable form
160
+ * alongside the on-the-wire ASCII representation.
161
+ *
162
+ * @example
163
+ * var b = require("@blamejs/core");
164
+ * var u = b.mail.toUnicode("xn--mnchen-3ya.de");
165
+ * // → "münchen.de"
166
+ */
167
+ function toUnicode(domain) {
168
+ if (typeof domain !== "string" || domain.length === 0) return null;
169
+ try { return nodeUrl.domainToUnicode(domain); }
170
+ catch (_e) { return null; }
171
+ }
172
+
173
+ /**
174
+ * @primitive b.mail.reverseDns
175
+ * @signature b.mail.reverseDns(ip)
176
+ * @since 0.8.53
177
+ * @status stable
178
+ * @related b.mail.create
179
+ *
180
+ * Forward-confirmed reverse DNS lookup (FCrDNS, RFC 8601 §3 lite) for
181
+ * an IPv4 or IPv6 address. Returns
182
+ * `{ ok, ptr, forward, fcrdns }`:
183
+ *
184
+ * - `ok` — whether the PTR resolved at all.
185
+ * - `ptr` — the first PTR record name (or `null`).
186
+ * - `forward` — array of A / AAAA addresses for that name (or `[]`).
187
+ * - `fcrdns` — `true` when the original `ip` appears in `forward`.
188
+ *
189
+ * Used as the building block for the iprev mail-authentication check
190
+ * (RFC 8601 §2.7.3): a sender's connect-IP must reverse-resolve to a
191
+ * PTR name whose forward A/AAAA includes that IP. Operators wiring
192
+ * inbound mail-receive paths call this on the connect address before
193
+ * accepting the SMTP transaction; bulk-sender reputation systems use
194
+ * the same check for outbound submission.
195
+ *
196
+ * Errors thrown by the underlying DNS path (bad-IP shape / lookup
197
+ * timeout) are caught and surfaced as `{ ok: false, error: code }`
198
+ * so the call doesn't reject the inbound path on a transient DNS
199
+ * blip; `fcrdns` remains `false`.
200
+ *
201
+ * @example
202
+ * var b = require("@blamejs/core");
203
+ * var r = await b.mail.reverseDns("8.8.8.8");
204
+ * // → { ok: true, ptr: "dns.google", forward: ["8.8.8.8"], fcrdns: true }
205
+ */
206
+ async function reverseDns(ip) {
207
+ var dns = networkDns();
208
+ var result = { ok: false, ptr: null, forward: [], fcrdns: false };
209
+ var ptrs;
210
+ try {
211
+ ptrs = await dns.reverse(ip);
212
+ } catch (e) {
213
+ result.error = (e && e.code) || "dns/reverse-failed";
214
+ return result;
215
+ }
216
+ if (!Array.isArray(ptrs) || ptrs.length === 0) {
217
+ result.error = "dns/no-ptr";
218
+ return result;
219
+ }
220
+ var ptrName = String(ptrs[0]);
221
+ result.ok = true;
222
+ result.ptr = ptrName;
223
+ // Forward-confirm — query A or AAAA depending on the IP family of
224
+ // the original input. RFC 8601 §3 says the forward query must use
225
+ // the same family as the source; mismatched families don't count
226
+ // as confirmation.
227
+ var net = require("node:net");
228
+ var forwardAddrs = [];
229
+ try {
230
+ if (net.isIPv6(ip)) {
231
+ forwardAddrs = await dns.resolveAaaa(ptrName);
232
+ } else {
233
+ forwardAddrs = await dns.resolve4(ptrName);
234
+ }
235
+ } catch (e) {
236
+ result.error = (e && e.code) || "dns/forward-failed";
237
+ return result;
238
+ }
239
+ result.forward = Array.isArray(forwardAddrs) ? forwardAddrs.slice() : [];
240
+ // Case-insensitive equality on IPv6 (canonical form differs for
241
+ // ::ffff:8.8.8.8 vs 8.8.8.8); compare lower-cased strings.
242
+ var ipLc = String(ip).toLowerCase();
243
+ for (var i = 0; i < result.forward.length; i += 1) {
244
+ if (String(result.forward[i]).toLowerCase() === ipLc) {
245
+ result.fcrdns = true;
246
+ break;
247
+ }
248
+ }
249
+ return result;
250
+ }
251
+
252
+ function _isValidEmail(addr) {
253
+ if (typeof addr !== "string" || addr.length === 0 || addr.length > EMAIL_MAX_LEN) {
254
+ return false;
255
+ }
256
+ // Pure ASCII — fast path through the existing regex (length bounded above).
257
+ if (_isAscii(addr)) return EMAIL_RE.test(addr); // bound: addr.length <= EMAIL_MAX_LEN
258
+ // EAI path — split at last '@', convert domain to Punycode, then test
259
+ // ASCII-only the assembled local@ascii-domain. The local part can be
260
+ // Unicode under RFC 6531 §3.3 — we accept it without further regex
261
+ // gating beyond the existing CRLF/NUL refusals upstream.
262
+ var atIdx = addr.lastIndexOf("@");
263
+ if (atIdx <= 0 || atIdx === addr.length - 1) return false;
264
+ var local = addr.slice(0, atIdx);
265
+ var domain = addr.slice(atIdx + 1);
266
+ var ascii = toAscii(domain);
267
+ if (!ascii) return false;
268
+ // Re-test the ASCII-converted domain against the existing email regex
269
+ // to refuse junk like "..invalid" that domainToASCII rubber-stamps
270
+ // (Node's WHATWG-URL implementation is permissive on dotted-empty
271
+ // labels). Substitute a placeholder local part so the regex sees an
272
+ // ASCII-only shape; the actual local part may legitimately be Unicode
273
+ // under RFC 6531 §3.3 and is enforced separately below.
274
+ if (ascii.length > EMAIL_MAX_LEN - 2) return false; // bound BEFORE regex test
275
+ if (!EMAIL_RE.test("x@" + ascii)) return false;
276
+ // Local part must not contain CRLF / NUL (header injection / SMTP
277
+ // smuggling). Other Unicode is fine per RFC 6531.
278
+ if (/[\r\n\0]/.test(local)) return false;
279
+ // Length cap also applies to the ASCII-equivalent so a long IDN
280
+ // domain that punycodes to >254 ASCII bytes is refused.
281
+ if ((local.length + 1 + ascii.length) > EMAIL_MAX_LEN) return false;
282
+ return true;
283
+ }
284
+
285
+ // Does this message require SMTPUTF8 on the wire? RFC 6531 §3.2 — true
286
+ // when any of from / to / cc / bcc / subject / mailbox-display-name
287
+ // contains non-ASCII octets.
288
+ function _messageRequiresSmtpUtf8(message) {
289
+ if (!message) return false;
290
+ if (!_isAscii(String(message.from || ""))) return true;
291
+ if (!_isAscii(String(message.subject || ""))) return true;
292
+ var lists = [message.to, message.cc, message.bcc];
293
+ for (var li = 0; li < lists.length; li += 1) {
294
+ var arr = Array.isArray(lists[li]) ? lists[li] : (lists[li] ? [lists[li]] : []);
295
+ for (var i = 0; i < arr.length; i += 1) {
296
+ if (!_isAscii(String(arr[i]))) return true;
297
+ }
298
+ }
299
+ return false;
300
+ }
301
+
302
+ function _normalizeRecipientList(value, label) {
303
+ if (value === undefined || value === null) return [];
304
+ var arr = Array.isArray(value) ? value : [value];
305
+ for (var i = 0; i < arr.length; i++) {
306
+ if (typeof arr[i] !== "string" || arr[i].length === 0) {
307
+ throw new MailError("mail/invalid-recipient",
308
+ label + "[" + i + "] must be a non-empty string", true);
309
+ }
310
+ // CRLF/NUL in addresses → header injection. Reject hard.
311
+ if (/[\r\n\0]/.test(arr[i])) {
312
+ throw new MailError("mail/invalid-recipient",
313
+ label + "[" + i + "] contains forbidden control characters", true);
314
+ }
315
+ // Accept "Name <email@addr>" form too — extract the angle-bracket
316
+ // address for validation; preserve the full string in the message.
317
+ var bracket = arr[i].match(/<([^>]+)>/);
318
+ var addr = bracket ? bracket[1] : arr[i];
319
+ if (!_isValidEmail(addr.trim())) {
320
+ throw new MailError("mail/invalid-recipient",
321
+ label + " '" + arr[i] + "' is not a valid email address", true);
322
+ }
323
+ }
324
+ return arr;
325
+ }
326
+
327
+ // CAN-SPAM postal-address validation. Accepts either a 5-field object
328
+ // shape (street/city/region/postalCode/country) or a non-empty string
329
+ // (operators with an irregular address layout — e.g. EU multi-line —
330
+ // pass a pre-rendered string and the framework appends it as-is).
331
+ //
332
+ // Returns null on valid; a description string on invalid. The framework
333
+ // converts the description into a MailError code at the call-site.
334
+ function _validatePostalAddress(addr) {
335
+ if (addr == null) return "postalAddress is required";
336
+ if (typeof addr === "string") {
337
+ if (addr.trim().length === 0) return "postalAddress (string) must be non-empty";
338
+ return null;
339
+ }
340
+ if (typeof addr !== "object") {
341
+ return "postalAddress must be an object or non-empty string";
342
+ }
343
+ var REQUIRED = ["street", "city", "region", "postalCode", "country"];
344
+ for (var i = 0; i < REQUIRED.length; i += 1) {
345
+ var k = REQUIRED[i];
346
+ var v = addr[k];
347
+ if (typeof v !== "string" || v.trim().length === 0) {
348
+ return "postalAddress." + k + " is required (non-empty string)";
349
+ }
350
+ if (/[\r\n\0]/.test(v)) { // allow:regex-no-length-cap — short typo-surfacing check; address fields are operator config not network bytes
351
+ return "postalAddress." + k + " contains forbidden control characters (CR/LF/NUL)";
352
+ }
353
+ }
354
+ return null;
355
+ }
356
+
357
+ // Pull a single field out of the address shape (object or string).
358
+ // Returns "" when the field isn't present (string-shape addresses don't
359
+ // carry structured fields).
360
+ function _addressField(addr, field) {
361
+ if (addr && typeof addr === "object" && typeof addr[field] === "string") {
362
+ return addr[field];
363
+ }
364
+ return "";
365
+ }
366
+
367
+ // Render the structured address as a single text block for the
368
+ // CAN-SPAM footer. String-shape inputs render verbatim.
369
+ function _renderPostalAddressText(addr) {
370
+ if (typeof addr === "string") return addr;
371
+ if (!addr || typeof addr !== "object") return "";
372
+ var line2 = [addr.city, addr.region, addr.postalCode].filter(Boolean).join(", ");
373
+ return [addr.street, line2, addr.country].filter(Boolean).join("\n");
374
+ }
375
+
376
+ function _renderPostalAddressHtml(addr) {
377
+ if (typeof addr === "string") {
378
+ return _htmlEscape(addr).replace(/\n/g, "<br>");
379
+ }
380
+ if (!addr || typeof addr !== "object") return "";
381
+ var parts = [];
382
+ if (addr.street) parts.push(_htmlEscape(addr.street));
383
+ var line2 = [addr.city, addr.region, addr.postalCode].filter(Boolean).join(", ");
384
+ if (line2) parts.push(_htmlEscape(line2));
385
+ if (addr.country) parts.push(_htmlEscape(addr.country));
386
+ return parts.join("<br>");
387
+ }
388
+
389
+ function _htmlEscape(s) {
390
+ return String(s)
391
+ .replace(/&/g, "&amp;")
392
+ .replace(/</g, "&lt;")
393
+ .replace(/>/g, "&gt;")
394
+ .replace(/"/g, "&quot;");
395
+ }
396
+
397
+ function _hasUnsubscribe(message) {
398
+ if (message.unsubscribe && typeof message.unsubscribe === "object") return true;
399
+ var headers = message.headers;
400
+ if (!headers || typeof headers !== "object") return false;
401
+ var keys = Object.keys(headers);
402
+ for (var i = 0; i < keys.length; i += 1) {
403
+ if (keys[i].toLowerCase() === "list-unsubscribe") return true;
404
+ }
405
+ return false;
406
+ }
407
+
408
+ function _validateMessage(message) {
409
+ if (!message || typeof message !== "object") {
410
+ throw new MailError("mail/missing-message", "send() requires a message object", true);
411
+ }
412
+ var to = _normalizeRecipientList(message.to, "to");
413
+ if (to.length === 0) {
414
+ throw new MailError("mail/missing-to", "message.to is required (one or more recipients)", true);
415
+ }
416
+ _normalizeRecipientList(message.cc, "cc");
417
+ _normalizeRecipientList(message.bcc, "bcc");
418
+
419
+ if (!message.from || typeof message.from !== "string") {
420
+ throw new MailError("mail/missing-from", "message.from is required", true);
421
+ }
422
+ if (/[\r\n\0]/.test(message.from)) {
423
+ throw new MailError("mail/invalid-from",
424
+ "message.from contains forbidden control characters", true);
425
+ }
426
+ var fromBracket = message.from.match(/<([^>]+)>/);
427
+ var fromAddr = fromBracket ? fromBracket[1] : message.from;
428
+ if (!_isValidEmail(fromAddr.trim())) {
429
+ throw new MailError("mail/invalid-from",
430
+ "message.from '" + message.from + "' is not a valid email address", true);
431
+ }
432
+ if (message.subject && safeBuffer.hasCrlf(message.subject)) {
433
+ throw new MailError("mail/invalid-subject",
434
+ "message.subject contains forbidden CRLF", true);
435
+ }
436
+
437
+ if (!message.text && !message.html && !message.calendar) {
438
+ throw new MailError("mail/missing-body",
439
+ "message must include at least one of text, html, or calendar", true);
440
+ }
441
+
442
+ if (message.calendar !== undefined) {
443
+ if (!message.calendar || typeof message.calendar !== "object") {
444
+ throw new MailError("mail/invalid-calendar",
445
+ "message.calendar must be an object { method, icalText }", true);
446
+ }
447
+ var ALLOWED_METHODS = ["REQUEST", "CANCEL", "REPLY", "PUBLISH", "COUNTER", "REFRESH", "ADD", "DECLINECOUNTER"];
448
+ if (typeof message.calendar.method !== "string" ||
449
+ ALLOWED_METHODS.indexOf(message.calendar.method) === -1) {
450
+ throw new MailError("mail/invalid-calendar",
451
+ "calendar.method must be one of: " + ALLOWED_METHODS.join(", "), true);
452
+ }
453
+ if (typeof message.calendar.icalText !== "string" ||
454
+ message.calendar.icalText.length === 0) {
455
+ throw new MailError("mail/invalid-calendar",
456
+ "calendar.icalText is required (non-empty string)", true);
457
+ }
458
+ if (!/^BEGIN:VCALENDAR/.test(message.calendar.icalText)) {
459
+ throw new MailError("mail/invalid-calendar",
460
+ "calendar.icalText must start with 'BEGIN:VCALENDAR' (RFC 5545)", true);
461
+ }
462
+ }
463
+
464
+ if (message.attachments !== undefined) {
465
+ if (!Array.isArray(message.attachments)) {
466
+ throw new MailError("mail/invalid-attachments",
467
+ "message.attachments must be an array", true);
468
+ }
469
+ for (var i = 0; i < message.attachments.length; i++) {
470
+ var att = message.attachments[i];
471
+ if (!att || typeof att !== "object") {
472
+ throw new MailError("mail/invalid-attachment",
473
+ "attachments[" + i + "] must be an object", true);
474
+ }
475
+ if (typeof att.filename !== "string" || att.filename.length === 0) {
476
+ throw new MailError("mail/invalid-attachment",
477
+ "attachments[" + i + "].filename must be a non-empty string", true);
478
+ }
479
+ if (/[\r\n\0]/.test(att.filename)) {
480
+ throw new MailError("mail/invalid-attachment",
481
+ "attachments[" + i + "].filename contains forbidden control characters", true);
482
+ }
483
+ // Filename safety gate — path traversal / null-byte / NTFS ADS /
484
+ // RTLO bidi / Windows-reserved / overlong UTF-8 / shell-exec
485
+ // / double-extension. Without this, an operator forwarding a
486
+ // user-uploaded attachment passes attacker-controlled filenames
487
+ // straight to mail clients (which use the filename for "save
488
+ // as" prompts) where Excel + macOS Finder + Outlook honor the
489
+ // RTLO + reserved-name + Windows-strip semantics.
490
+ if (att.skipFilenameSafety !== true) {
491
+ var fnResult = guardFilename().validate(att.filename, { profile: "strict" });
492
+ if (!fnResult.ok) {
493
+ throw new MailError("mail/invalid-attachment",
494
+ "attachments[" + i + "].filename rejected by guardFilename: " +
495
+ (fnResult.issues && fnResult.issues[0] && fnResult.issues[0].kind || "filename-safety-fail"),
496
+ true);
497
+ }
498
+ }
499
+ // Magic-byte gate — refuse claimed/detected MIME mismatch when
500
+ // both are present. Operator can opt out per-attachment with
501
+ // `skipMagicByteCheck: true` and audited reason (e.g. encrypted
502
+ // payloads where the magic bytes intentionally don't match the
503
+ // claimed type).
504
+ if (att.skipMagicByteCheck !== true && att.contentType &&
505
+ Buffer.isBuffer(att.content)) {
506
+ try {
507
+ var detected = fileType().detect(att.content);
508
+ if (detected && detected.mime &&
509
+ detected.mime.split("/")[0] !==
510
+ att.contentType.split(";")[0].trim().toLowerCase().split("/")[0]) {
511
+ throw new MailError("mail/invalid-attachment",
512
+ "attachments[" + i + "].contentType '" + att.contentType +
513
+ "' disagrees with detected magic-byte MIME '" + detected.mime +
514
+ "' — refusing to send mis-typed attachment", true);
515
+ }
516
+ } catch (e) {
517
+ if (e && e.code === "mail/invalid-attachment") throw e;
518
+ // file-type detection error: drop-silent, treat as no-detection
519
+ }
520
+ }
521
+ if (att.content === undefined || att.content === null) {
522
+ throw new MailError("mail/invalid-attachment",
523
+ "attachments[" + i + "].content is required (Buffer or string)", true);
524
+ }
525
+ if (!Buffer.isBuffer(att.content) && typeof att.content !== "string") {
526
+ throw new MailError("mail/invalid-attachment",
527
+ "attachments[" + i + "].content must be a Buffer or string", true);
528
+ }
529
+ if (att.contentType !== undefined &&
530
+ (typeof att.contentType !== "string" || /[\r\n\0]/.test(att.contentType))) {
531
+ throw new MailError("mail/invalid-attachment",
532
+ "attachments[" + i + "].contentType must be a clean string", true);
533
+ }
534
+ if (att.contentDisposition !== undefined &&
535
+ att.contentDisposition !== "attachment" &&
536
+ att.contentDisposition !== "inline") {
537
+ throw new MailError("mail/invalid-attachment",
538
+ "attachments[" + i + "].contentDisposition must be 'attachment' or 'inline'", true);
539
+ }
540
+ if (att.cid !== undefined &&
541
+ (typeof att.cid !== "string" || /[\r\n\0<>]/.test(att.cid))) {
542
+ throw new MailError("mail/invalid-attachment",
543
+ "attachments[" + i + "].cid must be a clean string (no <>)", true);
544
+ }
545
+ }
546
+ }
547
+ }
548
+
549
+ function _mergeMessage(defaults, message) {
550
+ // Per-message values override defaults; headers merged shallow.
551
+ var merged = Object.assign({}, defaults || {}, message);
552
+ if (defaults && defaults.headers && message.headers) {
553
+ merged.headers = Object.assign({}, defaults.headers, message.headers);
554
+ }
555
+ return merged;
556
+ }
557
+
558
+ function _extractAddr(s) {
559
+ if (s === undefined || s === null) return s;
560
+ var m = String(s).match(/<([^>]+)>/);
561
+ return m ? m[1].trim() : String(s).trim();
562
+ }
563
+
564
+ function _toArray(v) {
565
+ if (v === undefined || v === null) return [];
566
+ return Array.isArray(v) ? v.slice() : [v];
567
+ }
568
+
569
+ // ---- Built-in transports: console + memory (dev / tests) ----
570
+
571
+ function consoleTransport(opts) {
572
+ opts = opts || {};
573
+ var stream = opts.stream || process.stderr;
574
+ // redactBcc: print only the recipient COUNT instead of the addresses.
575
+ // Default false preserves the dev-visibility purpose of this
576
+ // transport. Operators piping dev logs into shared / centralized
577
+ // sinks (Slack, log aggregator, ticket system) opt in to avoid
578
+ // leaking the BCC list — the property exists precisely so a recipient
579
+ // doesn't see who else got the message, and that promise breaks the
580
+ // moment the addresses land in a non-private log.
581
+ var redactBcc = opts.redactBcc === true;
582
+ return {
583
+ name: "console",
584
+ send: async function (message) {
585
+ var lines = [
586
+ "[mail.console] To: " + (Array.isArray(message.to) ? message.to.join(", ") : message.to),
587
+ "[mail.console] From: " + message.from,
588
+ "[mail.console] Subject: " + (message.subject || ""),
589
+ ];
590
+ if (message.cc) lines.push("[mail.console] Cc: " + (Array.isArray(message.cc) ? message.cc.join(", ") : message.cc));
591
+ if (message.bcc) {
592
+ if (redactBcc) {
593
+ var bccCount = Array.isArray(message.bcc) ? message.bcc.length : 1;
594
+ lines.push("[mail.console] Bcc: <" + bccCount + " recipient" + (bccCount === 1 ? "" : "s") + " — redacted>");
595
+ } else {
596
+ lines.push("[mail.console] Bcc: " + (Array.isArray(message.bcc) ? message.bcc.join(", ") : message.bcc));
597
+ }
598
+ }
599
+ var body = message.text || (message.html ? "(html body, " + message.html.length + " bytes)" : "");
600
+ lines.push("");
601
+ lines.push(body);
602
+ lines.push("");
603
+ stream.write(lines.join("\n") + "\n");
604
+ return { transport: "console", deliveredAt: Date.now() };
605
+ },
606
+ };
607
+ }
608
+
609
+ function memoryTransport() {
610
+ var sent = [];
611
+ return {
612
+ name: "memory",
613
+ sent: sent,
614
+ send: async function (message) {
615
+ sent.push(message);
616
+ return { transport: "memory", deliveredAt: Date.now(), index: sent.length - 1 };
617
+ },
618
+ reset: function () { sent.length = 0; },
619
+ };
620
+ }
621
+
622
+ // ---- SMTP transport ----
623
+ //
624
+ // Raw RFC 5321 state machine over net/tls. Multi-recipient (loops
625
+ // RCPT TO over to + cc + bcc), builds an RFC 5322 message with
626
+ // multipart/alternative when both text and html are supplied, and
627
+ // dot-stuffs body lines beginning with "." per SMTP transparency.
628
+ //
629
+ // PQC posture: TLS opts default to TLSv1.3 minimum and accept an
630
+ // `ecdhCurve` string (set to a hybrid PQC group such as
631
+ // "X25519MLKEM768" when peer + Node version support it). On a
632
+ // cleartext port the transport always issues STARTTLS and refuses
633
+ // to send AUTH or DATA in cleartext if the upgrade is rejected.
634
+
635
+ function _newBoundary(label) {
636
+ // crypto.randomBytes for the boundary suffix matches the framework
637
+ // convention. RFC 5322 only requires uniqueness within a message,
638
+ // but consistency with how every other identifier in lib/ is built
639
+ // wins over premature differentiation.
640
+ return "blamejs-" + label + "-" + Date.now() + "-" + bCrypto.generateToken(C.BYTES.bytes(8));
641
+ }
642
+
643
+ // base64-encode the buffer with line wrapping at 76 chars (RFC 2045
644
+ // §6.8). Most clients tolerate longer lines but the spec maximum is
645
+ // 998 octets per line; sticking to 76 keeps everyone happy.
646
+ function _base64Wrap(buf) {
647
+ var b64 = buf.toString("base64");
648
+ var lines = [];
649
+ for (var i = 0; i < b64.length; i += 76) lines.push(b64.slice(i, i + 76));
650
+ return lines.join("\r\n");
651
+ }
652
+
653
+ function _buildAttachmentPart(att) {
654
+ var content = Buffer.isBuffer(att.content) ? att.content : Buffer.from(String(att.content), "utf8");
655
+ var contentType = att.contentType || "application/octet-stream";
656
+ var disposition = att.contentDisposition || (att.cid ? "inline" : "attachment");
657
+ var lines = [];
658
+ lines.push("Content-Type: " + contentType + '; name="' + att.filename + '"');
659
+ lines.push("Content-Transfer-Encoding: base64");
660
+ lines.push("Content-Disposition: " + disposition + '; filename="' + att.filename + '"');
661
+ if (att.cid) lines.push("Content-ID: <" + att.cid + ">");
662
+ lines.push("");
663
+ lines.push(_base64Wrap(content));
664
+ return lines.join("\r\n");
665
+ }
666
+
667
+ function _buildBodyPart(message) {
668
+ // Collect body parts (text / html / calendar). Multiple parts → wrap
669
+ // in multipart/alternative so the recipient client picks whichever
670
+ // it can render. Calendar parts carry the `method=` parameter so
671
+ // mail clients (Outlook / Gmail / Apple Mail) treat the message as
672
+ // an invite, not a generic ics download.
673
+ var parts = [];
674
+ if (message.text) {
675
+ parts.push({ contentType: "text/plain; charset=utf-8", body: message.text });
676
+ }
677
+ if (message.html) {
678
+ parts.push({ contentType: "text/html; charset=utf-8", body: message.html });
679
+ }
680
+ if (message.calendar) {
681
+ parts.push({
682
+ contentType: 'text/calendar; method="' + message.calendar.method + '"; charset=utf-8',
683
+ body: message.calendar.icalText,
684
+ });
685
+ }
686
+ if (parts.length === 1) return parts[0];
687
+ var altBoundary = _newBoundary("alt");
688
+ var lines = [];
689
+ for (var i = 0; i < parts.length; i++) {
690
+ lines.push("--" + altBoundary);
691
+ lines.push("Content-Type: " + parts[i].contentType);
692
+ lines.push("");
693
+ lines.push(parts[i].body);
694
+ }
695
+ lines.push("--" + altBoundary + "--");
696
+ return {
697
+ contentType: 'multipart/alternative; boundary="' + altBoundary + '"',
698
+ body: lines.join("\r\n"),
699
+ };
700
+ }
701
+
702
+ function _buildRfc822(message) {
703
+ var headers = [];
704
+ headers.push("From: " + message.from);
705
+ headers.push("To: " + (Array.isArray(message.to) ? message.to.join(", ") : message.to));
706
+ if (message.cc) headers.push("Cc: " + (Array.isArray(message.cc) ? message.cc.join(", ") : message.cc));
707
+ if (message.replyTo) headers.push("Reply-To: " + message.replyTo);
708
+ if (message.subject) headers.push("Subject: " + message.subject);
709
+ headers.push("MIME-Version: 1.0");
710
+ headers.push("Date: " + new Date().toUTCString());
711
+ if (message.headers) {
712
+ for (var k in message.headers) {
713
+ if (Object.prototype.hasOwnProperty.call(message.headers, k)) {
714
+ // Strip CRLF defensively even though we already validated the
715
+ // message; custom headers go straight onto the wire.
716
+ var v = safeBuffer.stripCrlf(String(message.headers[k]));
717
+ headers.push(k + ": " + v);
718
+ }
719
+ }
720
+ }
721
+
722
+ var attachments = Array.isArray(message.attachments) ? message.attachments : [];
723
+ var inner = _buildBodyPart(message);
724
+ var body;
725
+
726
+ if (attachments.length === 0) {
727
+ headers.push("Content-Type: " + inner.contentType);
728
+ body = inner.body;
729
+ } else {
730
+ // multipart/mixed: first part is the body (single or alternative),
731
+ // subsequent parts are the attachments. Inline disposition +
732
+ // Content-ID is interpreted correctly by every major client even
733
+ // inside mixed. Operators needing strict-RFC-2387 multipart/related
734
+ // wrap the body via the mail.transports interface and pass a
735
+ // content-type override.
736
+ var mixedBoundary = _newBoundary("mixed");
737
+ headers.push('Content-Type: multipart/mixed; boundary="' + mixedBoundary + '"');
738
+ var parts = [];
739
+ parts.push("--" + mixedBoundary);
740
+ parts.push("Content-Type: " + inner.contentType);
741
+ parts.push("");
742
+ parts.push(inner.body);
743
+ for (var ai = 0; ai < attachments.length; ai++) {
744
+ parts.push("--" + mixedBoundary);
745
+ parts.push(_buildAttachmentPart(attachments[ai]));
746
+ }
747
+ parts.push("--" + mixedBoundary + "--");
748
+ body = parts.join("\r\n");
749
+ }
750
+
751
+ // Normalize line endings then dot-stuff per SMTP transparency.
752
+ body = body.replace(/\r?\n/g, "\r\n");
753
+ body = body.split("\r\n").map(function (l) { return l.charAt(0) === "." ? "." + l : l; }).join("\r\n");
754
+
755
+ return headers.join("\r\n") + "\r\n\r\n" + body;
756
+ }
757
+
758
+ function smtpTransport(opts) {
759
+ opts = opts || {};
760
+ if (!opts.host) {
761
+ throw new MailError("mail/smtp-misconfigured",
762
+ "smtp transport requires opts.host", true);
763
+ }
764
+ if (opts.dkimSigner !== undefined && opts.dkimSigner !== null &&
765
+ (typeof opts.dkimSigner !== "object" || typeof opts.dkimSigner.sign !== "function")) {
766
+ throw new MailError("mail/smtp-misconfigured",
767
+ "dkimSigner must be an object with a .sign(rfc822) method " +
768
+ "(see b.mail.dkim.create)", true);
769
+ }
770
+ var port = opts.port || 587;
771
+ var useImplicitTLS = port === 465 || opts.implicitTls === true;
772
+ var rejectUnauthorized = opts.rejectUnauthorized !== false;
773
+ var ehloName = opts.ehloName || "blamejs";
774
+ // GHSA-c7w3-x93f-qmm8 / GHSA-vvjj-xcjg-gr5g (nodemailer CRLF-injection
775
+ // class) — any string concatenated into an outbound SMTP wire command
776
+ // MUST be CRLF/NUL-free, otherwise an attacker who can shape ehloName /
777
+ // user / pass / host (via config injection or template indirection)
778
+ // gets to inject a fresh EHLO / MAIL FROM / RCPT TO line. Refuse at
779
+ // config-time so the operator's boot dies at the misconfiguration line
780
+ // rather than silently emitting a smuggled command at first send.
781
+ function _refuseCtlBytes(label, val) {
782
+ if (val === undefined || val === null) return;
783
+ if (typeof val !== "string") return;
784
+ if (/[\r\n\0]/.test(val)) { // allow:regex-no-length-cap — CRLF/NUL is a 3-codepoint class
785
+ throw new MailError("mail/smtp-misconfigured",
786
+ "smtp transport: opts." + label + " contains CR/LF/NUL bytes " +
787
+ "(SMTP command-injection class — GHSA-c7w3-x93f-qmm8 / GHSA-vvjj-xcjg-gr5g)",
788
+ true);
789
+ }
790
+ }
791
+ _refuseCtlBytes("ehloName", ehloName);
792
+ _refuseCtlBytes("user", opts.user);
793
+ _refuseCtlBytes("pass", opts.pass);
794
+ _refuseCtlBytes("host", opts.host);
795
+ _refuseCtlBytes("servername", opts.servername);
796
+ var timeoutMs = opts.timeoutMs || C.TIME.seconds(15);
797
+ var tlsOpts = {
798
+ rejectUnauthorized: rejectUnauthorized,
799
+ minVersion: opts.minTlsVersion || "TLSv1.3",
800
+ };
801
+ if (opts.ecdhCurve) tlsOpts.ecdhCurve = opts.ecdhCurve;
802
+ if (opts.ca) tlsOpts.ca = opts.ca;
803
+
804
+ // SNI is only legal for hostnames; IP literals must omit servername
805
+ // (Node's tls.connect throws "Setting the TLS ServerName to an IP
806
+ // address is not permitted" otherwise). Operators with private CAs
807
+ // and an IP-only target pass `opts.servername: "expected-cn.example"`
808
+ // explicitly. Same convention as lib/redis-client.js.
809
+ var host = opts.host;
810
+ var servername = opts.servername;
811
+ if (servername === undefined) {
812
+ servername = (ipUtils.isIPv4Shape(host) || (host && host.indexOf(":") !== -1))
813
+ ? undefined : host;
814
+ }
815
+
816
+ // RFC 3030 BDAT chunking — default chunk size 256 KiB. Operator opt
817
+ // `chunking: false` disables BDAT even when offered (some legacy
818
+ // receivers advertise CHUNKING but mishandle bare BDAT framing).
819
+ var chunkingEnabled = opts.chunking !== false;
820
+ numericBounds.requirePositiveFiniteIntIfPresent(opts.chunkSize,
821
+ "smtp transport: opts.chunkSize", MailError, "mail/smtp-misconfigured");
822
+ var chunkSize = (opts.chunkSize !== undefined) ? opts.chunkSize : C.BYTES.kib(256);
823
+
824
+ // RFC 1870 SIZE — by default we honor the peer's advertised cap and
825
+ // refuse before opening DATA / BDAT. `respectPeerSize: false`
826
+ // disables the precheck (operator-asserted "I trust the peer to
827
+ // accept whatever I send").
828
+ var respectPeerSize = opts.respectPeerSize !== false;
829
+
830
+ // IPv4 / IPv6 family preference for the underlying connect. "any"
831
+ // lets Node pick (default — Happy Eyeballs / system policy); "4" or
832
+ // "6" forces a single family. The framework auto-detects when the
833
+ // local network has no IPv6 interfaces and prefers v4 in that case
834
+ // so a v6-only peer doesn't hang the connect timeout.
835
+ var preferFamily = (opts.preferFamily === 4 || opts.preferFamily === 6 ||
836
+ opts.preferFamily === "4" || opts.preferFamily === "6")
837
+ ? Number(opts.preferFamily) : "any";
838
+
839
+ var cfg = {
840
+ host: host,
841
+ port: port,
842
+ user: opts.user,
843
+ pass: opts.pass,
844
+ useImplicitTLS: useImplicitTLS,
845
+ ehloName: ehloName,
846
+ timeoutMs: timeoutMs,
847
+ tlsOpts: tlsOpts,
848
+ servername: servername,
849
+ dkimSigner: opts.dkimSigner || null,
850
+ chunkingEnabled: chunkingEnabled,
851
+ chunkSize: chunkSize,
852
+ respectPeerSize: respectPeerSize,
853
+ preferFamily: preferFamily,
854
+ };
855
+
856
+ return {
857
+ name: "smtp",
858
+ send: function (message) { return _smtpSend(message, cfg); },
859
+ };
860
+ }
861
+
862
+ // SMTP state-machine step IDs. Hex-encoded so the framework's
863
+ // byte-literal lint (which flags decimal multiples of 8) doesn't hit
864
+ // the equality comparisons in handleResponse below.
865
+ var SMTP_STEP_GREETING = 0x0;
866
+ var SMTP_STEP_EHLO_RESP = 0x1;
867
+ var SMTP_STEP_AUTH_USER = 0x2;
868
+ var SMTP_STEP_AUTH_PASS = 0x3;
869
+ var SMTP_STEP_AUTH_FINAL = 0x4;
870
+ var SMTP_STEP_MAIL_FROM = 0x5;
871
+ var SMTP_STEP_RCPT_TO = 0x6;
872
+ var SMTP_STEP_DATA = 0x7;
873
+ var SMTP_STEP_BODY = 0x8;
874
+ var SMTP_STEP_STARTTLS = 0xA;
875
+ // RFC 3030 BDAT chunked-body framing. The transport sends `BDAT N`
876
+ // (or `BDAT N LAST`) followed by exactly N bytes of body; each chunk
877
+ // expects a 250 response before the next chunk is written.
878
+ var SMTP_STEP_BDAT = 0xB;
879
+
880
+ function _smtpUtf8Suffix(requiresSmtpUtf8, peerSupportsSmtpUtf8) {
881
+ // RFC 6531 §3.4 — when SMTPUTF8 is advertised by the peer AND the
882
+ // message requires it, append " SMTPUTF8" to MAIL FROM to opt this
883
+ // transaction into the EAI extension. Pure-ASCII messages don't add
884
+ // it (some peers reject the keyword on legacy mailboxes).
885
+ return (requiresSmtpUtf8 && peerSupportsSmtpUtf8) ? " SMTPUTF8" : "";
886
+ }
887
+
888
+ // Detect whether the message has an 8-bit / binary attachment that
889
+ // requires BINARYMIME (RFC 3030 §3) on the wire. Pure-text messages —
890
+ // even when text/html bodies contain UTF-8 — go through 8BITMIME
891
+ // (RFC 6152) which is universally supported. The "binary" trigger is
892
+ // a Buffer attachment whose octet stream includes NUL bytes (or any
893
+ // byte > 0x7F when the operator marks `binary: true`). Buffers with
894
+ // the "application/octet-stream" claimed content-type also count.
895
+ function _messageRequiresBinaryMime(message) {
896
+ if (!message) return false;
897
+ if (!Array.isArray(message.attachments)) return false;
898
+ for (var i = 0; i < message.attachments.length; i += 1) {
899
+ var att = message.attachments[i];
900
+ if (!att) continue;
901
+ // Operator can mark explicit binary intent.
902
+ if (att.binary === true) return true;
903
+ // Buffer attachments whose content includes NUL are binary —
904
+ // base64 wraps them safely but the source octets are 8-bit-binary
905
+ // so the BODY=BINARYMIME hint is what tells the peer to expect
906
+ // RFC 3030 framing instead of bare 8BITMIME.
907
+ if (Buffer.isBuffer(att.content)) {
908
+ // Quick scan — first 4 KiB is enough to detect the common case
909
+ // (any executable / image / archive / pdf).
910
+ var max = Math.min(att.content.length, C.BYTES.kib(4));
911
+ for (var j = 0; j < max; j += 1) {
912
+ if (att.content[j] === 0) return true;
913
+ }
914
+ }
915
+ }
916
+ return false;
917
+ }
918
+
919
+ // Detect whether the message body has any non-ASCII (8-bit) octets
920
+ // requiring at minimum 8BITMIME (RFC 6152) on the wire. Triggers on
921
+ // non-ASCII text bytes in subject / text / html / calendar parts.
922
+ // Distinct from BINARYMIME — the latter is for true binary streams
923
+ // (NUL-bearing).
924
+ function _messageRequires8BitMime(message) {
925
+ if (!message) return false;
926
+ var fields = ["text", "html", "subject"];
927
+ for (var i = 0; i < fields.length; i += 1) {
928
+ var v = message[fields[i]];
929
+ if (typeof v === "string" && NON_ASCII_RE.test(v)) return true; // allow:regex-no-length-cap — header-value detector; bounded by SMTP line cap upstream
930
+ }
931
+ if (message.calendar && typeof message.calendar.icalText === "string" &&
932
+ NON_ASCII_RE.test(message.calendar.icalText)) return true; // allow:regex-no-length-cap — caller bounds calendar.icalText size
933
+ return false;
934
+ }
935
+
936
+ // Auto-detect IPv4 / IPv6 family for outbound connect when the
937
+ // operator didn't pin one. Walks `os.networkInterfaces()`; if the
938
+ // host has no non-internal IPv6 interfaces, prefer family=4 so a
939
+ // v6-only AAAA record doesn't hang the connect timeout. When the
940
+ // host has both, return 0 (let Node pick — Happy Eyeballs / system
941
+ // resultOrder applies).
942
+ function _autoDetectFamily() {
943
+ try {
944
+ var os = require("node:os");
945
+ var ifaces = os.networkInterfaces();
946
+ var hasV6 = false;
947
+ var hasV4 = false;
948
+ var keys = Object.keys(ifaces);
949
+ for (var k = 0; k < keys.length; k += 1) {
950
+ var arr = ifaces[keys[k]] || [];
951
+ for (var i = 0; i < arr.length; i += 1) {
952
+ var entry = arr[i];
953
+ if (entry.internal) continue;
954
+ if (entry.family === "IPv6" || entry.family === 6) hasV6 = true;
955
+ if (entry.family === "IPv4" || entry.family === 4) hasV4 = true;
956
+ }
957
+ }
958
+ if (hasV4 && !hasV6) return 4;
959
+ if (!hasV4 && hasV6) return 6;
960
+ return 0;
961
+ } catch (_e) {
962
+ return 0;
963
+ }
964
+ }
965
+
966
+ // Compute the wire size of the produced RFC 822 message. Used by RFC
967
+ // 1870 SIZE pre-check before MAIL FROM. Caller passes the already-
968
+ // CRLF-normalized + dot-stuffed wire string (the same one that goes
969
+ // into DATA / BDAT). Returns the byte count Node will write.
970
+ function _messageWireSize(wire) {
971
+ if (typeof wire !== "string") return 0;
972
+ return Buffer.byteLength(wire, "utf8");
973
+ }
974
+
975
+ // Parse the SIZE keyword's argument from a `SIZE 12345` EHLO line.
976
+ // Returns 0 when SIZE is advertised without a value (RFC 1870 §3 —
977
+ // some peers omit the limit, indicating "no enforced cap"); returns
978
+ // -1 when SIZE isn't advertised; otherwise returns the operator-side
979
+ // peer cap.
980
+ function _parsePeerSize(ehloLines) {
981
+ if (!Array.isArray(ehloLines)) return -1;
982
+ for (var i = 0; i < ehloLines.length; i += 1) {
983
+ var line = ehloLines[i];
984
+ // Lines come in already uppercased keyword form; the SIZE entry
985
+ // may be `SIZE` alone OR `SIZE 12345` — split on whitespace.
986
+ var parts = String(line).split(/\s+/);
987
+ if (parts[0] === "SIZE") {
988
+ if (parts.length < 2) return 0;
989
+ var n = parseInt(parts[1], 10);
990
+ return isFinite(n) && n >= 0 ? n : -1;
991
+ }
992
+ }
993
+ return -1;
994
+ }
995
+
996
+ function _smtpSend(message, cfg) {
997
+ return new Promise(function (resolve, reject) {
998
+ var socket;
999
+ var step = SMTP_STEP_GREETING;
1000
+ var buffer = "";
1001
+ var ehloLines = []; // RFC 5321 §4.1.1.1 — EHLO extension lines (uppercase keyword)
1002
+ var ehloFullLines = []; // Full extension text (incl. args, e.g. "SIZE 12345")
1003
+ var peerSupportsSmtpUtf8 = false; // RFC 6531 — set from EHLO response
1004
+ var peerSupportsChunking = false; // RFC 3030 §2 CHUNKING
1005
+ var peerSupportsBinaryMime = false; // RFC 3030 §3 BINARYMIME
1006
+ var peerSupports8BitMime = false; // RFC 6152 (eight-bit MIME) // allow:raw-byte-literal — RFC number, not a byte literal
1007
+ var peerSizeCap = -1; // RFC 1870 SIZE — -1 unset, 0 = no cap, >0 = byte limit
1008
+ var upgradedToTLS = false;
1009
+ var settled = false;
1010
+ var rcptIndex = 0;
1011
+ var bdatOffset = 0; // Bytes of dataMessage written so far via BDAT
1012
+ var dataWireBytes = null; // Buffer view of dataMessage for BDAT slicing
1013
+ var useBdat = false; // Decided post-EHLO based on peerSupportsChunking + cfg.chunkingEnabled
1014
+ var bodyMode = "7BIT"; // "7BIT" / "8BITMIME" / "BINARYMIME"
1015
+
1016
+ var fromAddr = _extractAddr(message.from);
1017
+ var toList = _toArray(message.to).map(_extractAddr);
1018
+ var ccList = _toArray(message.cc).map(_extractAddr);
1019
+ var bccList = _toArray(message.bcc).map(_extractAddr);
1020
+ var rcpts = toList.concat(ccList, bccList);
1021
+ var requiresSmtpUtf8 = _messageRequiresSmtpUtf8(message);
1022
+ var requiresBinaryMime = _messageRequiresBinaryMime(message);
1023
+ var requires8BitMime = _messageRequires8BitMime(message);
1024
+ var dataMessage = _buildRfc822(message);
1025
+ if (cfg.dkimSigner) {
1026
+ try { dataMessage = cfg.dkimSigner.sign(dataMessage); }
1027
+ catch (e) {
1028
+ reject(new MailError("mail/dkim-sign-failed",
1029
+ "dkim signing failed: " + ((e && e.message) || String(e)), true));
1030
+ return;
1031
+ }
1032
+ }
1033
+ var messageWireSize = _messageWireSize(dataMessage);
1034
+
1035
+ // Outbound SMTP-smuggling defense — refuse before opening the
1036
+ // socket if the produced RFC 822 wire contains the bare-CR / bare-
1037
+ // LF + smuggled-verb shape (CVE-2023-51764 / 51765 / 51766 class).
1038
+ // Operator-supplied subject / body / headers can sneak the pattern
1039
+ // through _buildRfc822 if the input wasn't already gated.
1040
+ var rv = guardEmail().validateMessage(dataMessage, { profile: "strict" });
1041
+ if (!rv.ok) {
1042
+ var critical = rv.issues.filter(function (i) {
1043
+ return i.severity === "critical";
1044
+ });
1045
+ if (critical.length > 0) {
1046
+ reject(new MailError("mail/outbound-smuggling-refused",
1047
+ "outbound RFC 822 wire failed guardEmail: " +
1048
+ critical.map(function (i) { return i.kind; }).join(","), true));
1049
+ return;
1050
+ }
1051
+ }
1052
+
1053
+ function fail(reason) {
1054
+ if (settled) return;
1055
+ settled = true;
1056
+ try { if (socket) socket.destroy(); } catch (_e) { /* socket may already be torn down */ }
1057
+ reject(new MailError("mail/smtp-failed",
1058
+ "SMTP send failed: " + reason, false));
1059
+ }
1060
+ function done(ok, code) {
1061
+ if (settled) return;
1062
+ settled = true;
1063
+ try { socket.end(); } catch (_e) { /* socket may already be torn down */ }
1064
+ if (ok) resolve({ transport: "smtp", deliveredAt: Date.now(), code: code });
1065
+ else reject(new MailError("mail/smtp-rejected",
1066
+ "SMTP rejected message (code " + code + ")", false));
1067
+ }
1068
+
1069
+ function send(cmd) {
1070
+ try { socket.write(cmd + "\r\n"); }
1071
+ catch (e) { fail(e.message || String(e)); }
1072
+ }
1073
+
1074
+ // RFC 5321 + 6531 + 6152 + 3030 + 1870 — MAIL FROM keyword bundle.
1075
+ // Order: SMTPUTF8 (6531) → BODY=<7BIT|8BITMIME|BINARYMIME> →
1076
+ // SIZE=<bytes>. Peers tolerate any order but consistent ordering
1077
+ // simplifies the wire-trace gold files.
1078
+ function _mailFromSuffix() {
1079
+ var s = "";
1080
+ s += _smtpUtf8Suffix(requiresSmtpUtf8, peerSupportsSmtpUtf8);
1081
+ if (bodyMode === "BINARYMIME" && peerSupportsBinaryMime) {
1082
+ s += " BODY=BINARYMIME";
1083
+ } else if (bodyMode === "8BITMIME" && peerSupports8BitMime) {
1084
+ s += " BODY=8BITMIME";
1085
+ }
1086
+ // Append SIZE= when peer advertised SIZE (cap or no-cap form).
1087
+ // Peers without SIZE support get no SIZE= keyword (some legacy
1088
+ // peers reject unknown MAIL FROM keywords).
1089
+ if (peerSizeCap !== -1) {
1090
+ s += " SIZE=" + messageWireSize;
1091
+ }
1092
+ return s;
1093
+ }
1094
+
1095
+ // Send the next BDAT chunk. Each `BDAT N [LAST]` line is followed
1096
+ // immediately by exactly N bytes of body (no CRLF terminator on
1097
+ // the chunk; SMTP framing is purely length-based per RFC 3030 §2).
1098
+ function sendBdatChunk() {
1099
+ if (!dataWireBytes) dataWireBytes = Buffer.from(dataMessage, "utf8");
1100
+ var remaining = dataWireBytes.length - bdatOffset;
1101
+ if (remaining <= 0) {
1102
+ // Empty body — send `BDAT 0 LAST` to terminate gracefully.
1103
+ socket.write("BDAT 0 LAST\r\n");
1104
+ return;
1105
+ }
1106
+ var thisChunk = Math.min(remaining, cfg.chunkSize);
1107
+ var isLast = (bdatOffset + thisChunk) >= dataWireBytes.length;
1108
+ var header = "BDAT " + thisChunk + (isLast ? " LAST" : "") + "\r\n";
1109
+ try {
1110
+ socket.write(header);
1111
+ socket.write(dataWireBytes.slice(bdatOffset, bdatOffset + thisChunk));
1112
+ } catch (e) {
1113
+ fail(e.message || String(e));
1114
+ return;
1115
+ }
1116
+ bdatOffset += thisChunk;
1117
+ }
1118
+
1119
+ function onData(data) {
1120
+ buffer += data;
1121
+ var lines = buffer.split("\r\n");
1122
+ buffer = lines.pop();
1123
+ for (var i = 0; i < lines.length; i++) {
1124
+ var line = lines[i];
1125
+ if (!line) continue;
1126
+ var code = parseInt(line.slice(0, 3), 10);
1127
+ // EHLO continuation lines (250-X) carry extension names. We
1128
+ // capture them so the dispatcher can branch on SMTPUTF8 /
1129
+ // 8BITMIME / BINARYMIME / CHUNKING / SIZE / STARTTLS before
1130
+ // MAIL FROM is sent. Both forms recorded: keyword-only (used
1131
+ // for set-membership tests) and full-line (used for SIZE arg).
1132
+ if (step === SMTP_STEP_EHLO_RESP) {
1133
+ var rest = line.slice(4);
1134
+ var keyword = rest.split(" ")[0].toUpperCase();
1135
+ if (keyword) {
1136
+ ehloLines.push(keyword);
1137
+ ehloFullLines.push(rest.toUpperCase());
1138
+ }
1139
+ }
1140
+ if (line[3] === "-") continue; // continuation line
1141
+ try { handleResponse(code); }
1142
+ catch (e) { fail(e.message || String(e)); return; }
1143
+ if (settled) return;
1144
+ }
1145
+ }
1146
+
1147
+ function attachSocket(s) {
1148
+ socket = s;
1149
+ socket.setEncoding("utf8");
1150
+ socket.setTimeout(cfg.timeoutMs);
1151
+ socket.on("data", onData);
1152
+ socket.on("error", function (err) { fail(err.message || String(err)); });
1153
+ socket.on("timeout", function () { fail("timeout"); });
1154
+ }
1155
+
1156
+ function connect() {
1157
+ // Family preference for the underlying lookup. Node's net /
1158
+ // tls.connect both honor `family: 4|6` to bias the dns lookup;
1159
+ // the framework auto-detects an IPv4-only host when the operator
1160
+ // didn't pin one explicitly so a v6-only AAAA result doesn't
1161
+ // hang the connect.
1162
+ var family = cfg.preferFamily;
1163
+ if (family === "any") family = _autoDetectFamily();
1164
+ if (cfg.useImplicitTLS) {
1165
+ var tlsConnectOpts = Object.assign({}, cfg.tlsOpts);
1166
+ if (cfg.servername) tlsConnectOpts.servername = cfg.servername;
1167
+ tlsConnectOpts.host = cfg.host;
1168
+ tlsConnectOpts.port = cfg.port;
1169
+ if (family === 4 || family === 6) tlsConnectOpts.family = family;
1170
+ attachSocket(nodeTls().connect(tlsConnectOpts));
1171
+ } else {
1172
+ var netOpts = { host: cfg.host, port: cfg.port };
1173
+ if (family === 4 || family === 6) netOpts.family = family;
1174
+ attachSocket(net().createConnection(netOpts));
1175
+ }
1176
+ }
1177
+
1178
+ function handleResponse(code) {
1179
+ if (step === SMTP_STEP_GREETING) {
1180
+ if (code !== 220) { fail("greeting-rejected (code " + code + ")"); return; }
1181
+ send("EHLO " + cfg.ehloName); step = SMTP_STEP_EHLO_RESP;
1182
+ }
1183
+ else if (step === SMTP_STEP_EHLO_RESP) {
1184
+ if (code < 200 || code >= 300) { fail("ehlo-rejected (code " + code + ")"); return; }
1185
+ // Snapshot extensions advertised on the wire for downstream use.
1186
+ peerSupportsSmtpUtf8 = ehloLines.indexOf("SMTPUTF8") !== -1;
1187
+ peerSupports8BitMime = ehloLines.indexOf("8BITMIME") !== -1;
1188
+ peerSupportsBinaryMime = ehloLines.indexOf("BINARYMIME") !== -1;
1189
+ peerSupportsChunking = ehloLines.indexOf("CHUNKING") !== -1;
1190
+ peerSizeCap = _parsePeerSize(ehloFullLines);
1191
+ // RFC 6531 §3.2 — if the message requires SMTPUTF8 and the
1192
+ // peer does not advertise it, refuse hard rather than emit a
1193
+ // mangled wire (server might still accept but headers/local
1194
+ // parts would silently corrupt downstream).
1195
+ if (requiresSmtpUtf8 && !peerSupportsSmtpUtf8) {
1196
+ fail("eai-required-not-supported: message has non-ASCII content but peer does not advertise SMTPUTF8");
1197
+ return;
1198
+ }
1199
+ // RFC 3030 §3 — BINARYMIME is only legal when the peer
1200
+ // advertises it. If the message requires it but the peer
1201
+ // doesn't offer it, refuse: silently downgrading to 8BITMIME
1202
+ // would corrupt NUL-bearing octets in transit.
1203
+ if (requiresBinaryMime && !peerSupportsBinaryMime) {
1204
+ settled = true;
1205
+ try { socket.destroy(); } catch (_e) { /* socket may already be torn down */ }
1206
+ reject(new MailError("mail/binarymime-not-advertised",
1207
+ "message has 8-bit binary content but peer does not advertise BINARYMIME (RFC 3030 §3)",
1208
+ true));
1209
+ return;
1210
+ }
1211
+ // RFC 1870 §3 — SIZE pre-check. Refuse before opening DATA /
1212
+ // BDAT so the caller gets a clean error instead of a 552
1213
+ // mid-stream rejection. peerSizeCap = 0 means "no enforced
1214
+ // cap"; -1 means "SIZE not advertised" (no precheck).
1215
+ if (cfg.respectPeerSize && peerSizeCap > 0 && messageWireSize > peerSizeCap) {
1216
+ settled = true;
1217
+ try { socket.destroy(); } catch (_e) { /* socket may already be torn down */ }
1218
+ reject(new MailError("mail/peer-size-exceeded",
1219
+ "message wire size " + messageWireSize + " bytes exceeds peer SIZE cap " +
1220
+ peerSizeCap + " bytes (RFC 1870)", true));
1221
+ return;
1222
+ }
1223
+ // Decide BDAT vs DATA + BODY=8BITMIME / BINARYMIME for this
1224
+ // transaction. CHUNKING + BDAT is preferred when both peer
1225
+ // advertises it AND operator didn't disable it.
1226
+ useBdat = peerSupportsChunking && cfg.chunkingEnabled;
1227
+ if (requiresBinaryMime) bodyMode = "BINARYMIME";
1228
+ else if (requires8BitMime && peerSupports8BitMime) bodyMode = "8BITMIME";
1229
+ else bodyMode = "7BIT";
1230
+
1231
+ if (!cfg.useImplicitTLS && !upgradedToTLS) { send("STARTTLS"); step = SMTP_STEP_STARTTLS; }
1232
+ else if (cfg.user) { send("AUTH LOGIN"); step = SMTP_STEP_AUTH_USER; }
1233
+ else { send("MAIL FROM:<" + fromAddr + ">" + _mailFromSuffix()); step = SMTP_STEP_MAIL_FROM; }
1234
+ }
1235
+ else if (step === SMTP_STEP_STARTTLS) {
1236
+ if (code !== 220) { fail("starttls-rejected (code " + code + ")"); return; }
1237
+ var tlsConnectOpts = Object.assign({ socket: socket }, cfg.tlsOpts);
1238
+ if (cfg.servername) tlsConnectOpts.servername = cfg.servername;
1239
+ var tlsSocket = nodeTls().connect(tlsConnectOpts, function () {
1240
+ upgradedToTLS = true;
1241
+ try { socket.removeAllListeners("data"); } catch (_e) { /* listeners migrate to upgraded socket */ }
1242
+ attachSocket(tlsSocket);
1243
+ send("EHLO " + cfg.ehloName);
1244
+ step = SMTP_STEP_EHLO_RESP;
1245
+ });
1246
+ tlsSocket.on("error", function (err) {
1247
+ fail("tls-upgrade: " + (err.message || String(err)));
1248
+ });
1249
+ }
1250
+ else if (step === SMTP_STEP_AUTH_USER) {
1251
+ if (code !== 334) { fail("auth-username-rejected (code " + code + ")"); return; }
1252
+ send(Buffer.from(cfg.user || "").toString("base64")); step = SMTP_STEP_AUTH_PASS;
1253
+ }
1254
+ else if (step === SMTP_STEP_AUTH_PASS) {
1255
+ if (code !== 334) { fail("auth-password-rejected (code " + code + ")"); return; }
1256
+ send(Buffer.from(cfg.pass || "").toString("base64")); step = SMTP_STEP_AUTH_FINAL;
1257
+ }
1258
+ else if (step === SMTP_STEP_AUTH_FINAL) {
1259
+ if (code !== 235) { fail("auth-failed (code " + code + ")"); return; }
1260
+ send("MAIL FROM:<" + fromAddr + ">" + _mailFromSuffix()); step = SMTP_STEP_MAIL_FROM;
1261
+ }
1262
+ else if (step === SMTP_STEP_MAIL_FROM) {
1263
+ if (code < 200 || code >= 300) { fail("mail-from-rejected (code " + code + ")"); return; }
1264
+ send("RCPT TO:<" + rcpts[rcptIndex++] + ">"); step = SMTP_STEP_RCPT_TO;
1265
+ }
1266
+ else if (step === SMTP_STEP_RCPT_TO) {
1267
+ if (code < 200 || code >= 300) { fail("rcpt-rejected (code " + code + ")"); return; }
1268
+ if (rcptIndex < rcpts.length) {
1269
+ send("RCPT TO:<" + rcpts[rcptIndex++] + ">");
1270
+ } else if (useBdat) {
1271
+ // RFC 3030 §2 — BDAT framing replaces DATA + CRLF.CRLF.
1272
+ // Each chunk is `BDAT <octet-count> [LAST]\r\n` followed by
1273
+ // exactly <octet-count> bytes of body. We emit the audit
1274
+ // signal once per send (not per chunk) so the audit chain
1275
+ // doesn't get flooded for large messages.
1276
+ try {
1277
+ audit().safeEmit({
1278
+ action: "mail.transport.bdat",
1279
+ outcome: "success",
1280
+ metadata: {
1281
+ wireBytes: messageWireSize,
1282
+ chunkSize: cfg.chunkSize,
1283
+ expectedChunks: Math.max(1, Math.ceil(messageWireSize / cfg.chunkSize)),
1284
+ bodyMode: bodyMode,
1285
+ },
1286
+ });
1287
+ if (bodyMode === "BINARYMIME") {
1288
+ audit().safeEmit({
1289
+ action: "mail.transport.binarymime",
1290
+ outcome: "success",
1291
+ metadata: { wireBytes: messageWireSize },
1292
+ });
1293
+ }
1294
+ } catch (_e) { /* audit best-effort */ }
1295
+ step = SMTP_STEP_BDAT;
1296
+ sendBdatChunk();
1297
+ } else {
1298
+ send("DATA"); step = SMTP_STEP_DATA;
1299
+ }
1300
+ }
1301
+ else if (step === SMTP_STEP_DATA) {
1302
+ if (code !== 354) { fail("data-rejected (code " + code + ")"); return; }
1303
+ send(dataMessage + "\r\n.");
1304
+ step = SMTP_STEP_BODY;
1305
+ }
1306
+ else if (step === SMTP_STEP_BDAT) {
1307
+ // Each BDAT chunk gets a 250 response per RFC 3030 §2. Anything
1308
+ // else (4xx / 5xx) is a hard rejection of the chunk; surface
1309
+ // a stable error code so downstream retry policy can identify
1310
+ // the chunked-body failure mode.
1311
+ if (code !== 250) {
1312
+ settled = true;
1313
+ try { socket.destroy(); } catch (_e) { /* socket may already be torn down */ }
1314
+ reject(new MailError("mail/bdat-chunk-rejected",
1315
+ "BDAT chunk rejected (code " + code + ", offset " + bdatOffset + "/" +
1316
+ messageWireSize + ")", false));
1317
+ return;
1318
+ }
1319
+ if (bdatOffset >= messageWireSize) {
1320
+ // Final chunk acknowledged — message accepted.
1321
+ done(true, code);
1322
+ return;
1323
+ }
1324
+ sendBdatChunk();
1325
+ }
1326
+ else if (step === SMTP_STEP_BODY) {
1327
+ var ok = code === 250;
1328
+ done(ok, code);
1329
+ }
1330
+ }
1331
+
1332
+ try { connect(); }
1333
+ catch (e) { fail(e.message || String(e)); }
1334
+ });
1335
+ }
1336
+
1337
+ // ---- Generic HTTP transport ----
1338
+ //
1339
+ // Vendor-agnostic transport for any mail API that speaks HTTP. Operators
1340
+ // supply three things: an endpoint, a serialize() that turns the
1341
+ // framework-shaped message into the vendor's request body + headers,
1342
+ // and an interpret() that reads the vendor's response and decides
1343
+ // success vs failure. Uses lib/http-client so PQC TLS, response caps,
1344
+ // and timeout handling come for free.
1345
+ //
1346
+ // httpTransport({
1347
+ // name: "postmark", // appears in result + error codes
1348
+ // endpoint: "https://...", // POST target
1349
+ // method: "POST", // default POST
1350
+ // headers: { ... }, // base headers (auth, content-type, ...)
1351
+ // timeoutMs: 15000,
1352
+ // allowedProtocols: safeUrl.ALLOW_HTTP_TLS, // default HTTPS-only
1353
+ // serialize: function (message) {
1354
+ // // → { headers?: {...}, body: string | Buffer }
1355
+ // },
1356
+ // interpret: function (res, message) {
1357
+ // // res = { statusCode, headers, body: Buffer }
1358
+ // // → { ok: true, id?: "..." } | { ok: false, reason: "..." }
1359
+ // // throw a MailError for permanent / structural failures
1360
+ // },
1361
+ // })
1362
+ //
1363
+ // Errors carry a `mail/<name>-*` code so logs identify which provider
1364
+ // rejected which message (mail/postmark-failed, mail/resend-rejected,
1365
+ // etc.). HTTPS-only is the default — pass safeUrl.ALLOW_HTTP_ALL via
1366
+ // opts.allowedProtocols only for local test fixtures.
1367
+
1368
+ function httpTransport(opts) {
1369
+ opts = opts || {};
1370
+ if (!opts.endpoint || typeof opts.endpoint !== "string") {
1371
+ throw new MailError("mail/http-misconfigured",
1372
+ "http transport requires opts.endpoint", true);
1373
+ }
1374
+ if (typeof opts.serialize !== "function") {
1375
+ throw new MailError("mail/http-misconfigured",
1376
+ "http transport requires opts.serialize(message) → { headers?, body }", true);
1377
+ }
1378
+ var name = opts.name || "http";
1379
+ var method = (opts.method || "POST").toUpperCase();
1380
+ var endpoint = opts.endpoint;
1381
+ var baseHeaders = opts.headers || {};
1382
+ var timeoutMs = opts.timeoutMs || C.TIME.seconds(15);
1383
+ var allowedProtocols = opts.allowedProtocols || null;
1384
+ var allowInternal = opts.allowInternal != null ? opts.allowInternal : null;
1385
+ var interpret = typeof opts.interpret === "function" ? opts.interpret : null;
1386
+ var serialize = opts.serialize;
1387
+ var codePrefix = "mail/" + name;
1388
+
1389
+ return {
1390
+ name: name,
1391
+ send: async function (message) {
1392
+ var serialized = serialize(message);
1393
+ if (!serialized || typeof serialized !== "object") {
1394
+ throw new MailError(codePrefix + "-bad-serializer",
1395
+ "serialize() must return { headers?, body }", false);
1396
+ }
1397
+ var body = serialized.body;
1398
+ if (typeof body === "string") body = Buffer.from(body, "utf8");
1399
+ if (!Buffer.isBuffer(body)) {
1400
+ throw new MailError(codePrefix + "-bad-serializer",
1401
+ "serialize() body must be a string or Buffer", false);
1402
+ }
1403
+ var headers = Object.assign({}, baseHeaders, serialized.headers || {});
1404
+ // Default Content-Length when caller hasn't asserted chunked
1405
+ // transfer; keeps small JSON payloads from being chunked needlessly.
1406
+ var hasLen = false;
1407
+ for (var hk in headers) {
1408
+ if (Object.prototype.hasOwnProperty.call(headers, hk) &&
1409
+ hk.toLowerCase() === "content-length") { hasLen = true; break; }
1410
+ }
1411
+ if (!hasLen) headers["Content-Length"] = body.length;
1412
+
1413
+ var reqOpts = {
1414
+ method: method,
1415
+ url: endpoint,
1416
+ headers: headers,
1417
+ body: body,
1418
+ timeoutMs: timeoutMs,
1419
+ errorClass: MailError, // http-client constructs (code, message, permanent, statusCode)
1420
+ };
1421
+ if (allowedProtocols) reqOpts.allowedProtocols = allowedProtocols;
1422
+ if (allowInternal !== null) reqOpts.allowInternal = allowInternal;
1423
+
1424
+ var res;
1425
+ try {
1426
+ res = await httpClient().request(reqOpts);
1427
+ } catch (e) {
1428
+ // http-client constructs a MailError via opts.errorClass on
1429
+ // non-2xx / network / timeout, with its own code domain
1430
+ // (HTTP_ERROR, ETIMEDOUT, ...). Rewrap into mail/<name>-failed
1431
+ // so the consumer-facing code identifies the provider while
1432
+ // preserving the original as `cause` and the HTTP statusCode.
1433
+ var wrapped = new MailError(codePrefix + "-failed",
1434
+ name + " request failed: " + ((e && e.message) || String(e)),
1435
+ false,
1436
+ e && typeof e.statusCode === "number" ? e.statusCode : undefined);
1437
+ wrapped.cause = e;
1438
+ throw wrapped;
1439
+ }
1440
+
1441
+ var info = { transport: name, deliveredAt: Date.now() };
1442
+ if (typeof res.statusCode === "number") info.statusCode = res.statusCode;
1443
+
1444
+ if (!interpret) return info;
1445
+
1446
+ var verdict;
1447
+ try { verdict = interpret(res, message); }
1448
+ catch (e) {
1449
+ if (e && e.isMailError) throw e;
1450
+ throw new MailError(codePrefix + "-interpret-failed",
1451
+ "interpret() threw: " + ((e && e.message) || String(e)), false);
1452
+ }
1453
+ if (!verdict || verdict.ok === false) {
1454
+ var reason = (verdict && verdict.reason) || "rejected";
1455
+ var err = new MailError(codePrefix + "-rejected",
1456
+ name + " rejected message: " + reason, false);
1457
+ if (verdict && typeof verdict.statusCode === "number") err.statusCode = verdict.statusCode;
1458
+ throw err;
1459
+ }
1460
+ if (verdict.id) info.id = verdict.id;
1461
+ if (verdict.extra) Object.assign(info, verdict.extra);
1462
+ return info;
1463
+ },
1464
+ };
1465
+ }
1466
+
1467
+ // ---- Resend preset ----
1468
+ //
1469
+ // Thin convenience wrapper that wires httpTransport to Resend's API.
1470
+ // Operators wanting Postmark / Mailgun / SES HTTP / SendGrid build the
1471
+ // same shape against httpTransport directly — this preset exists to
1472
+ // document the pattern, not to privilege any single vendor.
1473
+
1474
+ function resendTransport(opts) {
1475
+ opts = opts || {};
1476
+ if (!opts.apiKey || typeof opts.apiKey !== "string") {
1477
+ throw new MailError("mail/resend-misconfigured",
1478
+ "resend transport requires opts.apiKey", true);
1479
+ }
1480
+ return httpTransport({
1481
+ name: "resend",
1482
+ endpoint: opts.endpoint || "https://api.resend.com/emails",
1483
+ method: "POST",
1484
+ timeoutMs: opts.timeoutMs || C.TIME.seconds(15),
1485
+ allowedProtocols: opts.allowedProtocols || null,
1486
+ allowInternal: opts.allowInternal != null ? opts.allowInternal : null,
1487
+ headers: {
1488
+ "Authorization": "Bearer " + opts.apiKey,
1489
+ "Content-Type": "application/json",
1490
+ },
1491
+ serialize: function (message) {
1492
+ var payload = {
1493
+ from: message.from,
1494
+ to: Array.isArray(message.to) ? message.to : [message.to],
1495
+ subject: message.subject || "",
1496
+ };
1497
+ if (message.cc) payload.cc = Array.isArray(message.cc) ? message.cc : [message.cc];
1498
+ if (message.bcc) payload.bcc = Array.isArray(message.bcc) ? message.bcc : [message.bcc];
1499
+ if (message.replyTo) payload.reply_to = message.replyTo;
1500
+ if (message.html) payload.html = message.html;
1501
+ if (message.text) payload.text = message.text;
1502
+ if (message.headers) payload.headers = message.headers;
1503
+ // Resend attachments shape: [{ filename, content (base64 string),
1504
+ // contentType?, content_id? }]. Inline images via cid go through
1505
+ // the content_id field (Resend renders <img src="cid:...">).
1506
+ if (Array.isArray(message.attachments) && message.attachments.length > 0) {
1507
+ payload.attachments = message.attachments.map(function (att) {
1508
+ var buf = Buffer.isBuffer(att.content) ? att.content : Buffer.from(String(att.content), "utf8");
1509
+ var entry = {
1510
+ filename: att.filename,
1511
+ content: buf.toString("base64"),
1512
+ };
1513
+ if (att.contentType) entry.contentType = att.contentType;
1514
+ if (att.cid) entry.content_id = att.cid;
1515
+ return entry;
1516
+ });
1517
+ }
1518
+ return { body: JSON.stringify(payload) };
1519
+ },
1520
+ interpret: function (res) {
1521
+ var text = res.body ? res.body.toString("utf8") : "";
1522
+ var data;
1523
+ // Cap on diagnostic-message snippet length (chars, not bytes) — keeps
1524
+ // a hostile or huge backend response from blowing up the error message.
1525
+ var DIAG_SNIPPET_LEN = 0xC8;
1526
+ try { data = safeJson.parse(text, { maxBytes: MAIL_RESPONSE_MAX_BYTES }); }
1527
+ catch (_e) {
1528
+ throw new MailError("mail/resend-bad-response",
1529
+ "resend response was not JSON: " + text.slice(0, DIAG_SNIPPET_LEN), false);
1530
+ }
1531
+ if (!data.id) {
1532
+ return {
1533
+ ok: false,
1534
+ reason: data.message || JSON.stringify(data).slice(0, DIAG_SNIPPET_LEN),
1535
+ };
1536
+ }
1537
+ return { ok: true, id: data.id };
1538
+ },
1539
+ });
1540
+ }
1541
+
1542
+ // ---- Engine instance ----
1543
+
1544
+ /**
1545
+ * @primitive b.mail.create
1546
+ * @signature b.mail.create(opts)
1547
+ * @since 0.1.0
1548
+ * @status stable
1549
+ * @compliance gdpr, soc2, hipaa
1550
+ * @related b.mail.toAscii, b.mail.toUnicode
1551
+ *
1552
+ * Build a mail instance bound to a transport + defaults. Returns
1553
+ * `{ send, transport, defaults }`: `send(message)` validates the
1554
+ * merged message against the framework contract, applies CAN-SPAM
1555
+ * footer + unsubscribe enforcement when `commercial: true`, runs
1556
+ * RFC 8058 List-Unsubscribe header expansion when the message carries
1557
+ * `unsubscribe`, then delegates to the transport. Audit rows record
1558
+ * recipient counts only (addresses are PII).
1559
+ *
1560
+ * @opts
1561
+ * transport: function (message) | { send(message), name? }, // default: console
1562
+ * defaults: { from, replyTo, headers, ... }, // merged into every message
1563
+ * audit: boolean, // default true
1564
+ * commercial: boolean, // CAN-SPAM §7704 enforcement
1565
+ * regulated: boolean, // alias for commercial:true
1566
+ * postalAddress: { street, city, region, postalCode, country } | string,
1567
+ * footerSeparator: string, // default "\n\n----\n" / "<hr>"
1568
+ * footerHtml: string, // override for html-part footer
1569
+ *
1570
+ * @example
1571
+ * var b = require("@blamejs/core");
1572
+ * var mail = b.mail.create({
1573
+ * transport: b.mail.transports.memory(),
1574
+ * defaults: { from: "Acme <noreply@acme.test>" },
1575
+ * });
1576
+ * // → { send, transport, defaults }
1577
+ */
1578
+ function create(opts) {
1579
+ opts = opts || {};
1580
+ validateOpts(opts, [
1581
+ "transport", "defaults", "audit",
1582
+ "commercial", "postalAddress", "footerSeparator", "footerHtml", "regulated",
1583
+ "guardDomain", "profile",
1584
+ ], "mail");
1585
+ var transport = opts.transport || consoleTransport();
1586
+ if (typeof transport === "function") {
1587
+ transport = { send: transport, name: "anonymous" };
1588
+ }
1589
+ if (!transport || typeof transport.send !== "function") {
1590
+ throw new MailError("mail/bad-transport",
1591
+ "opts.transport must be a function or an object with .send(message)", true);
1592
+ }
1593
+ var defaults = opts.defaults || {};
1594
+ var auditOn = opts.audit !== false;
1595
+
1596
+ // Default-on guardDomain hardening for every outbound recipient + the
1597
+ // sender address. Refuses CVE-2017-5469-class IDN homograph spoofs in
1598
+ // recipient or from domains, RFC 6761 special-use domain names
1599
+ // (`.localhost`, `.test`, `.invalid`, `.example`) in production sends,
1600
+ // RFC 1035 §2.3.4 label-length violations, and CVE-2021-22931-class
1601
+ // bare-IP-as-domain (DNS-rebinding allowlist-bypass class). Operators
1602
+ // sending to address literals (`<x@[1.2.3.4]>`) — rare; mostly mailing-
1603
+ // list internals — pass `guardDomain: false` to opt out, or pass
1604
+ // `guardDomain: { profile: "permissive" }` to relax the rules.
1605
+ var guardDomainProfileName;
1606
+ if (opts.guardDomain === false) {
1607
+ guardDomainProfileName = null;
1608
+ } else {
1609
+ guardDomainProfileName = opts.guardDomain && typeof opts.guardDomain === "object"
1610
+ ? (opts.guardDomain.profile || opts.profile || "strict")
1611
+ : (opts.profile || "strict");
1612
+ }
1613
+ function _validateAddrDomain(addr, label) {
1614
+ if (!guardDomainProfileName) return;
1615
+ if (typeof addr !== "string") return;
1616
+ // RFC 5322 §3.4 angle-bracket address (`name <local@dom>`) — extract
1617
+ // the inner address via indexOf/lastIndexOf rather than a regex so
1618
+ // we stay linear on input shape (CodeQL js/polynomial-redos class).
1619
+ var ltIdx = addr.indexOf("<");
1620
+ var gtIdx = addr.lastIndexOf(">");
1621
+ var rawAddr = (ltIdx !== -1 && gtIdx > ltIdx)
1622
+ ? addr.slice(ltIdx + 1, gtIdx)
1623
+ : addr;
1624
+ var atIdx = rawAddr.lastIndexOf("@");
1625
+ if (atIdx === -1) return;
1626
+ var domain = rawAddr.slice(atIdx + 1).trim();
1627
+ // RFC 5321 §4.1.3 address-literal form `[1.2.3.4]` / `[IPv6:...]`
1628
+ // — already a syntactic constraint via the brackets; b.guardDomain
1629
+ // refuses bare IPs without brackets which is the security-relevant
1630
+ // shape (CVE-2021-22931 DNS rebinding allowlist-bypass).
1631
+ if (domain.length === 0 || domain[0] === "[") return;
1632
+ // RFC 5891 ToASCII — convert any IDN labels to Punycode BEFORE
1633
+ // guardDomain validation so EAI (RFC 6531) addresses like
1634
+ // `<x@münchen.example>` pass under strict (which refuses raw
1635
+ // Unicode labels per RFC 5891 §4.2 transport-safety rule). The
1636
+ // SMTPUTF8 wire encoding is the transport's concern; the gate
1637
+ // here runs on a transport-safe form.
1638
+ var asciiDomain = toAscii(domain) || domain;
1639
+ // Override punycodePolicy — `xn--…` labels are RFC 5891-encoded
1640
+ // IDNs and the whole point of EAI (RFC 6531) is to deliver to
1641
+ // them. The strict profile defaults to refusing Punycode (the
1642
+ // generic "operator typed a homograph" defense); for mail.send
1643
+ // we've already gone through RFC 5891 ToASCII, so the Punycode
1644
+ // is structural, not a homograph attempt. All other strict
1645
+ // defenses (mixed-script, BIDI, control, IP-literal, special-
1646
+ // use, wildcard, DGA, raw-unicode pre-conversion) remain.
1647
+ var verdict = guardDomain.validate(asciiDomain, {
1648
+ profile: guardDomainProfileName,
1649
+ punycodePolicy: "allow",
1650
+ });
1651
+ if (!verdict.ok) {
1652
+ throw new MailError("mail/recipient-domain-refused",
1653
+ "mail.send: " + label + " domain '" + domain + "' refused by b.guardDomain (" +
1654
+ (verdict.issues && verdict.issues[0] && verdict.issues[0].kind) + ")", true);
1655
+ }
1656
+ }
1657
+
1658
+ // CAN-SPAM Act §7704(a)(5) — every commercial-content message MUST
1659
+ // include the sender's valid physical postal address. Validate the
1660
+ // address shape at create() so a typo / blank field surfaces at boot,
1661
+ // not silently on first send. Operators marking an instance
1662
+ // commercial:true also opt every send() into the unsubscribe-required
1663
+ // posture (CAN-SPAM §7704(a)(3) — RFC 8058 List-Unsubscribe header
1664
+ // already wired via b.mail.unsubscribe).
1665
+ var commercial = opts.commercial === true || opts.regulated === true;
1666
+ var postalAddress = opts.postalAddress != null ? opts.postalAddress : null;
1667
+ if (commercial) {
1668
+ var addrError = _validatePostalAddress(postalAddress);
1669
+ if (addrError) {
1670
+ throw new MailError("mail/missing-postal-address",
1671
+ "mail.create({ commercial: true }): " + addrError +
1672
+ " — CAN-SPAM Act §7704(a)(5) requires a valid physical postal address.",
1673
+ true);
1674
+ }
1675
+ }
1676
+ var footerSeparator = (typeof opts.footerSeparator === "string")
1677
+ ? opts.footerSeparator : null;
1678
+ var footerHtml = (typeof opts.footerHtml === "string") ? opts.footerHtml : null;
1679
+ if (footerHtml && commercial) {
1680
+ var addrText = _renderPostalAddressText(postalAddress);
1681
+ // Country + postal-code presence check — operator-supplied HTML
1682
+ // overrides MUST still carry the address bytes. We don't lex HTML
1683
+ // here; substring match against the rendered address is enough to
1684
+ // catch "operator forgot to interpolate the address into their
1685
+ // override template" without parsing markup.
1686
+ var country = _addressField(postalAddress, "country");
1687
+ var postalCode = _addressField(postalAddress, "postalCode");
1688
+ if (country && footerHtml.indexOf(country) === -1) {
1689
+ throw new MailError("mail/bad-footer-html",
1690
+ "mail.create({ footerHtml }): override must contain the postalAddress.country '" +
1691
+ country + "' (CAN-SPAM §7704(a)(5)). Got: " + footerHtml.slice(0, 200), // allow:raw-byte-literal — diagnostic clamp characters, not bytes
1692
+ true);
1693
+ }
1694
+ if (postalCode && footerHtml.indexOf(postalCode) === -1) {
1695
+ throw new MailError("mail/bad-footer-html",
1696
+ "mail.create({ footerHtml }): override must contain the postalAddress.postalCode '" +
1697
+ postalCode + "' (CAN-SPAM §7704(a)(5))",
1698
+ true);
1699
+ }
1700
+ // Suppress the "unused-variable" lint signal for addrText — the
1701
+ // sanity-render establishes the address shape is renderable before
1702
+ // we trust the operator override; the rendered text isn't itself
1703
+ // injected when footerHtml overrides.
1704
+ void addrText;
1705
+ }
1706
+
1707
+ function _emit(action, info) {
1708
+ if (!auditOn) return;
1709
+ audit().safeEmit({
1710
+ action: action,
1711
+ outcome: info.outcome || (action.endsWith(".failure") ? "failure" : "success"),
1712
+ actor: info.actor || {},
1713
+ // Recipient COUNT, not addresses — addresses can be PII; the
1714
+ // framework's audit chain shouldn't carry them by default.
1715
+ // Operators who need full address logging set their own audit
1716
+ // hook with whatever PII discipline they want.
1717
+ metadata: {
1718
+ transport: transport.name || "custom",
1719
+ subject: info.subject || "",
1720
+ toCount: info.toCount,
1721
+ ccCount: info.ccCount,
1722
+ bccCount: info.bccCount,
1723
+ durationMs: info.durationMs,
1724
+ },
1725
+ reason: info.reason || null,
1726
+ });
1727
+ }
1728
+
1729
+ async function send(message) {
1730
+ var merged = _mergeMessage(defaults, message);
1731
+ // RFC 8058 / RFC 2369 List-Unsubscribe support: when the operator
1732
+ // passes `unsubscribe: { url, mailto, oneClick }`, expand into the
1733
+ // header pair and merge into the message headers. Lets bulk
1734
+ // senders comply with the Gmail / Yahoo / Microsoft bulk-sender
1735
+ // mandate without hand-rolling the header byte sequence.
1736
+ if (merged.unsubscribe && typeof merged.unsubscribe === "object") {
1737
+ var unsubHeaders = mailUnsubscribe.buildHeaders(merged.unsubscribe);
1738
+ merged.headers = Object.assign({}, merged.headers || {}, unsubHeaders);
1739
+ delete merged.unsubscribe;
1740
+ }
1741
+
1742
+ // CAN-SPAM §7704(a) — every commercial-content message must carry
1743
+ // a valid physical postal address (auto-appended to the body) and
1744
+ // a clear opt-out path. The address shape was validated at
1745
+ // create(); this block (a) re-asserts the unsubscribe path is
1746
+ // present, (b) appends the formatted footer to text + html parts,
1747
+ // and (c) emits a structured audit row when the send refuses.
1748
+ if (commercial) {
1749
+ if (!_hasUnsubscribe(merged)) {
1750
+ try {
1751
+ audit().safeEmit({
1752
+ action: "mail.canspam.refused",
1753
+ outcome: "denied",
1754
+ metadata: {
1755
+ reason: "missing-unsubscribe",
1756
+ transport: transport.name || "custom",
1757
+ },
1758
+ });
1759
+ } catch (_e) { /* audit best-effort */ }
1760
+ throw new MailError("mail/canspam-no-unsubscribe",
1761
+ "mail.send: commercial:true requires either message.unsubscribe = " +
1762
+ "{ url|mailto, oneClick? } OR a List-Unsubscribe header. CAN-SPAM " +
1763
+ "§7704(a)(3)/(4) — every commercial message must give recipients a " +
1764
+ "clear opt-out mechanism.", true);
1765
+ }
1766
+ var sepText = footerSeparator != null ? footerSeparator : "\n\n----\n";
1767
+ var sepHtml = footerSeparator != null ? footerSeparator : "<hr>";
1768
+ var addrText = _renderPostalAddressText(postalAddress);
1769
+ var addrHtml = footerHtml || _renderPostalAddressHtml(postalAddress);
1770
+ // Append-only — operators who want the address in a different
1771
+ // location render it themselves and disable commercial:true (or
1772
+ // pass footerHtml with the operator-controlled layout).
1773
+ if (typeof merged.text === "string" && merged.text.length > 0 &&
1774
+ merged.text.indexOf(addrText) === -1) {
1775
+ merged.text = merged.text + sepText + addrText + "\n";
1776
+ } else if (merged.text == null && addrText) {
1777
+ merged.text = addrText + "\n";
1778
+ }
1779
+ if (typeof merged.html === "string" && merged.html.length > 0 &&
1780
+ merged.html.indexOf(addrHtml) === -1) {
1781
+ merged.html = merged.html + sepHtml + addrHtml;
1782
+ }
1783
+ }
1784
+
1785
+ _validateMessage(merged);
1786
+
1787
+ // Default-on guardDomain hardening on every recipient + the sender
1788
+ // address (see closure setup above). Skipped when operator opts out
1789
+ // via guardDomain:false.
1790
+ if (guardDomainProfileName) {
1791
+ _validateAddrDomain(merged.from, "from");
1792
+ var _toArr = _normalizeRecipientList(merged.to, "to");
1793
+ var _ccArr = _normalizeRecipientList(merged.cc, "cc");
1794
+ var _bccArr = _normalizeRecipientList(merged.bcc, "bcc");
1795
+ for (var _ti = 0; _ti < _toArr.length; _ti += 1) _validateAddrDomain(_toArr[_ti], "to");
1796
+ for (var _ci = 0; _ci < _ccArr.length; _ci += 1) _validateAddrDomain(_ccArr[_ci], "cc");
1797
+ for (var _bi = 0; _bi < _bccArr.length; _bi += 1) _validateAddrDomain(_bccArr[_bi], "bcc");
1798
+ }
1799
+
1800
+ var t0 = Date.now();
1801
+ try {
1802
+ var result = await transport.send(merged);
1803
+ _emit("mail.send.success", {
1804
+ subject: merged.subject,
1805
+ toCount: Array.isArray(merged.to) ? merged.to.length : 1,
1806
+ ccCount: Array.isArray(merged.cc) ? merged.cc.length : (merged.cc ? 1 : 0),
1807
+ bccCount: Array.isArray(merged.bcc) ? merged.bcc.length : (merged.bcc ? 1 : 0),
1808
+ durationMs: Date.now() - t0,
1809
+ });
1810
+ return result;
1811
+ } catch (e) {
1812
+ _emit("mail.send.failure", {
1813
+ subject: merged.subject,
1814
+ toCount: Array.isArray(merged.to) ? merged.to.length : 1,
1815
+ ccCount: Array.isArray(merged.cc) ? merged.cc.length : (merged.cc ? 1 : 0),
1816
+ bccCount: Array.isArray(merged.bcc) ? merged.bcc.length : (merged.bcc ? 1 : 0),
1817
+ durationMs: Date.now() - t0,
1818
+ outcome: "failure",
1819
+ reason: (e && e.message) || String(e),
1820
+ });
1821
+ // Re-throw as MailError when the upstream wasn't already one,
1822
+ // preserving the cause for diagnostic chains.
1823
+ if (e && e.isMailError) throw e;
1824
+ var wrapped = new MailError("mail/transport-failed",
1825
+ "transport '" + (transport.name || "custom") + "' failed: " + ((e && e.message) || String(e)),
1826
+ false);
1827
+ wrapped.cause = e;
1828
+ throw wrapped;
1829
+ }
1830
+ }
1831
+
1832
+ return {
1833
+ send: send,
1834
+ transport: transport,
1835
+ defaults: defaults,
1836
+ };
1837
+ }
1838
+
1839
+ /**
1840
+ * @primitive b.mail.feedbackId
1841
+ * @signature b.mail.feedbackId(opts)
1842
+ * @since 0.8.87
1843
+ * @status stable
1844
+ * @related b.mail.create
1845
+ *
1846
+ * Build a Gmail Feedback Loop (FBL) Feedback-ID header value per
1847
+ * Google's FBL convention: a colon-separated 4-tuple
1848
+ * `CampaignID:CustomerID:MailType:SenderID`. Setting Feedback-ID on
1849
+ * outbound mail lets Gmail surface per-campaign abuse-rate metrics
1850
+ * back via the Postmaster Tools API so operators see spam
1851
+ * complaints aggregated by their own campaign vocabulary instead of
1852
+ * by SMTP envelope-sender alone.
1853
+ *
1854
+ * Refuses missing / empty fields (`mail/bad-feedback-id-field`),
1855
+ * fields containing `:` (would corrupt the 4-tuple separator), and
1856
+ * fields longer than 64 bytes (Gmail truncates beyond ~64 chars per
1857
+ * field). Operators set the result via `mail.create({ headers:
1858
+ * { "Feedback-ID": b.mail.feedbackId({...}) } })` or attach it to
1859
+ * an individual send().
1860
+ *
1861
+ * @opts
1862
+ * campaignId: string, // operator's campaign tag (e.g. "wk26-promo")
1863
+ * customerId: string, // operator's tenant or user-segment id
1864
+ * mailType: string, // operator-defined message type (e.g. "marketing")
1865
+ * senderId: string, // operator's app / IP-pool / domain reputation id
1866
+ *
1867
+ * @example
1868
+ * var feedbackId = b.mail.feedbackId({
1869
+ * campaignId: "wk26-promo",
1870
+ * customerId: "acme",
1871
+ * mailType: "marketing",
1872
+ * senderId: "mail-pool-1",
1873
+ * });
1874
+ * // → "wk26-promo:acme:marketing:mail-pool-1"
1875
+ *
1876
+ * mail.send({
1877
+ * to: "...",
1878
+ * headers: { "Feedback-ID": feedbackId },
1879
+ * });
1880
+ */
1881
+ function feedbackId(opts) {
1882
+ if (!opts || typeof opts !== "object") {
1883
+ throw new MailError("mail/bad-feedback-id-opts",
1884
+ "feedbackId: opts required (campaignId + customerId + mailType + senderId)");
1885
+ }
1886
+ var fields = [
1887
+ { key: "campaignId", value: opts.campaignId },
1888
+ { key: "customerId", value: opts.customerId },
1889
+ { key: "mailType", value: opts.mailType },
1890
+ { key: "senderId", value: opts.senderId },
1891
+ ];
1892
+ var parts = [];
1893
+ for (var i = 0; i < fields.length; i += 1) {
1894
+ var f = fields[i];
1895
+ if (typeof f.value !== "string" || f.value.length === 0) {
1896
+ throw new MailError("mail/bad-feedback-id-field",
1897
+ "feedbackId: " + f.key + " must be a non-empty string");
1898
+ }
1899
+ if (f.value.length > 64) { // allow:raw-byte-literal — Gmail FBL per-field cap, not byte arithmetic
1900
+ throw new MailError("mail/bad-feedback-id-field",
1901
+ "feedbackId: " + f.key + " exceeds 64 chars (Gmail FBL truncation threshold)");
1902
+ }
1903
+ if (f.value.indexOf(":") !== -1) {
1904
+ throw new MailError("mail/bad-feedback-id-field",
1905
+ "feedbackId: " + f.key + " contains ':' which is the field separator");
1906
+ }
1907
+ // Refuse CR/LF (header-injection) + control chars. Walk codepoints
1908
+ // manually because eslint's no-control-regex refuses control-char
1909
+ // ranges in regex literals regardless of escape form.
1910
+ for (var ci = 0; ci < f.value.length; ci += 1) {
1911
+ var code = f.value.charCodeAt(ci);
1912
+ if (code < 32 || code === 127) { // allow:raw-byte-literal — C0 + DEL codepoint range
1913
+ throw new MailError("mail/bad-feedback-id-field",
1914
+ "feedbackId: " + f.key + " contains control characters");
1915
+ }
1916
+ }
1917
+ parts.push(f.value);
1918
+ }
1919
+ return parts.join(":");
1920
+ }
1921
+
1922
+ var mailRequireTls = require("./mail-require-tls");
1923
+ var mailSrs = require("./mail-srs");
1924
+
1925
+ module.exports = {
1926
+ create: create,
1927
+ feedbackId: feedbackId,
1928
+ requireTls: mailRequireTls,
1929
+ srs: mailSrs,
1930
+ MailError: MailError,
1931
+ unsubscribe: mailUnsubscribe,
1932
+ // RFC 3492 Punycode IDN domain encode/decode (b.mail.toAscii /
1933
+ // toUnicode). Wraps node:url.domainToASCII / domainToUnicode so
1934
+ // operators have one obvious place to reach for IDN handling. Used
1935
+ // internally by send() to convert IDN domain parts before the
1936
+ // pre-SMTPUTF8 ASCII regex check.
1937
+ toAscii: toAscii,
1938
+ toUnicode: toUnicode,
1939
+ // Forward-confirmed reverse DNS lookup (RFC 8601 §3 lite). Building
1940
+ // block for inbound iprev / outbound submission reputation checks.
1941
+ reverseDns: reverseDns,
1942
+ // DKIM-Signature header generation for outbound mail (rsa-sha256
1943
+ // default, ed25519-sha256 opt-in). Wire it into the smtp transport
1944
+ // via opts.dkimSigner. See lib/mail-dkim.js for the full surface.
1945
+ dkim: dkim,
1946
+ // Inbound mail authentication-results verification: SPF (RFC 7208),
1947
+ // DMARC (RFC 7489), ARC (RFC 8617). Outbound DKIM signing lives in
1948
+ // .dkim above; per-hop DKIM verification is deferred (composes with
1949
+ // the existing canonicalization helpers in lib/mail-dkim.js).
1950
+ spf: mailAuth.spf,
1951
+ dmarc: mailAuth.dmarc,
1952
+ arc: mailAuth.arc,
1953
+ iprev: mailAuth.iprev,
1954
+ authResults: mailAuth.authResults,
1955
+ bimi: mailBimi,
1956
+ // Test-only export: lets unit tests inspect the wire format without
1957
+ // standing up a TLS-capable SMTP fixture. Operators don't call this.
1958
+ _buildRfc822ForTest: _buildRfc822,
1959
+ transports: {
1960
+ console: consoleTransport,
1961
+ memory: memoryTransport,
1962
+ smtp: smtpTransport,
1963
+ http: httpTransport,
1964
+ resend: resendTransport,
1965
+ },
1966
+ // The mail-stack standardization contract (v0.9.20). JMAP / IMAP /
1967
+ // POP3 / ManageSieve / MX / submission all translate into
1968
+ // `agent.X(args)`; RBAC + posture + audit + dispatch owned here.
1969
+ // See lib/mail-agent.js for the full surface.
1970
+ agent: mailAgent,
1971
+ };