@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,2453 @@
1
+ "use strict";
2
+ /**
3
+ * Layer 4 — consumer modules.
4
+ *
5
+ * Layer 4 — consumer modules sit on top of audit + db + chain
6
+ * primitives.
7
+ *
8
+ * session — session lifecycle
9
+ * data-residency — db + storage residency rules
10
+ * storage — local + multi-backend object stores +
11
+ * classification routing + retry/breaker +
12
+ * sigv4 / GCS / Azure adapters
13
+ * queue — local queue lifecycle (consume / retry / lease)
14
+ * log-stream — log fan-out (local, webhook, bidirectional)
15
+ * external-db — dispatcher (basic / pool / transaction /
16
+ * residency / classification)
17
+ * middleware — request-id / security headers / error handler /
18
+ * bot-guard / cors / rate-limit
19
+ * env-load — full lifecycle (consumes env-parse + atomicFile)
20
+ *
21
+ * Layers 0–3 must run first.
22
+ *
23
+ * Usage from smoke.js:
24
+ * var consumersLayer = require("./40-consumers");
25
+ * await consumersLayer.run();
26
+ */
27
+
28
+ var helpers = require("./_helpers");
29
+ var b = helpers.b;
30
+ var fs = helpers.fs;
31
+ var os = helpers.os;
32
+ var path = helpers.path;
33
+ var check = helpers.check;
34
+ var setupTestDb = helpers.setupTestDb;
35
+ var teardownTestDb = helpers.teardownTestDb;
36
+ var setupTestDbForMW = helpers.setupTestDbForMW;
37
+ var teardownMW = helpers.teardownMW;
38
+ var listenOnRandomPort = helpers.listenOnRandomPort;
39
+ var _makeFakeDriver = helpers._makeFakeDriver;
40
+ var _makeSqliteDriver = helpers._makeSqliteDriver;
41
+ var _makeFakeServiceAccount = helpers._makeFakeServiceAccount;
42
+ var _mockReq = helpers._mockReq;
43
+ var _mockRes = helpers._mockRes;
44
+
45
+ async function testSession() {
46
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-session-"));
47
+ try {
48
+ await setupTestDb(tmpDir);
49
+
50
+ // Create + verify
51
+ var s1 = await b.session.create({ userId: "u-1", data: { csrfToken: "abc" } });
52
+ check("create returns sealed token", typeof s1.token === "string" && s1.token.indexOf("vault:") === 0);
53
+ check("create returns expiresAt > now", s1.expiresAt > Date.now());
54
+
55
+ var v1 = await b.session.verify(s1.token);
56
+ check("verify returns the session", v1 && v1.userId === "u-1");
57
+ check("verify decrypts data field", v1 && v1.data && v1.data.csrfToken === "abc");
58
+
59
+ // The plaintext sid should NEVER be in the DB — only its hash
60
+ var rawRows = b.db.prepare("SELECT sidHash FROM _blamejs_sessions").all();
61
+ check("only sidHash stored, never plaintext sid",
62
+ rawRows.every(r => r.sidHash !== s1.token && r.sidHash.length === 128));
63
+
64
+ // verify on garbage token returns null
65
+ check("verify on garbage token returns null", (await b.session.verify("not-a-real-token")) === null);
66
+ check("verify on empty token returns null", (await b.session.verify("")) === null);
67
+
68
+ // touch
69
+ var beforeTouch = await b.session.verify(s1.token);
70
+ var t0 = beforeTouch.lastActivity;
71
+ // Sleep briefly to ensure lastActivity changes
72
+ await new Promise(function (r) { setTimeout(r, 10); });
73
+ var ok = await b.session.touch(s1.token);
74
+ check("touch returns true", ok === true);
75
+ var afterTouch = await b.session.verify(s1.token);
76
+ check("touch updates lastActivity", afterTouch.lastActivity > t0);
77
+
78
+ // touch's extendBy is bounded by the same MAX_TTL_MS as create / rotate
79
+ // (10 years). Repeated touches with arbitrary extendBy values
80
+ // can't push expiresAt past that bound.
81
+ var extendThrew = null;
82
+ try { await b.session.touch(s1.token, { extendBy: 1000 * 60 * 60 * 24 * 365 * 100 }); }
83
+ catch (e) { extendThrew = e; }
84
+ check("touch rejects extendBy beyond MAX_TTL_MS",
85
+ extendThrew && /exceeds maximum/.test(extendThrew.message || ""));
86
+ var negThrew = null;
87
+ try { await b.session.touch(s1.token, { extendBy: -1 }); }
88
+ catch (e) { negThrew = e; }
89
+ check("touch rejects negative extendBy", negThrew !== null);
90
+ var nanThrew = null;
91
+ try { await b.session.touch(s1.token, { extendBy: NaN }); }
92
+ catch (e) { nanThrew = e; }
93
+ check("touch rejects NaN extendBy", nanThrew !== null);
94
+
95
+ // destroyAllForUser
96
+ var s2 = await b.session.create({ userId: "u-1" });
97
+ var s3 = await b.session.create({ userId: "u-2" });
98
+ check("count includes all active sessions", (await b.session.count()) === 3);
99
+ var nDel = await b.session.destroyAllForUser("u-1");
100
+ check("destroyAllForUser returns count", nDel === 2);
101
+ check("u-1's sessions all gone",
102
+ (await b.session.verify(s1.token)) === null && (await b.session.verify(s2.token)) === null);
103
+ check("u-2's session survives", (await b.session.verify(s3.token)) !== null);
104
+
105
+ // destroy single
106
+ check("destroy returns true on success", (await b.session.destroy(s3.token)) === true);
107
+ check("destroy returns false on missing", (await b.session.destroy(s3.token)) === false);
108
+
109
+ // Expired session auto-cleans on verify
110
+ var sExp = await b.session.create({ userId: "u-3", ttlMs: 50 });
111
+ await new Promise(function (r) { setTimeout(r, 100); });
112
+ check("verify on expired session returns null", (await b.session.verify(sExp.token)) === null);
113
+
114
+ // purgeExpired
115
+ var sExp2 = await b.session.create({ userId: "u-4", ttlMs: 50 });
116
+ void sExp2;
117
+ await new Promise(function (r) { setTimeout(r, 100); });
118
+ var purged = await b.session.purgeExpired();
119
+ check("purgeExpired returns count", purged >= 1);
120
+
121
+ // Invalid input — session.create rejects synchronously before
122
+ // returning a Promise, so the throw is observable via try/catch
123
+ // around the awaited call (the rejected Promise raises in await).
124
+ var rejected = false;
125
+ try { await b.session.create({}); } catch (_) { rejected = true; }
126
+ check("session.create requires userId", rejected);
127
+ } finally {
128
+ await teardownTestDb(tmpDir);
129
+ }
130
+ }
131
+
132
+ async function testDataResidency() {
133
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-dr-"));
134
+ try {
135
+ b.vault._resetForTest();
136
+ b.db._resetForTest();
137
+ await b.vault.init({ dataDir: tmpDir, mode: "plaintext" });
138
+ await b.db.init({
139
+ dataDir: tmpDir,
140
+ atRest: "plain",
141
+ auditSigning: { mode: "plaintext" },
142
+ schema: [{ name: "x", columns: { _id: "TEXT PRIMARY KEY" } }],
143
+ dataResidency: { region: "EU", allowedStorageRegions: ["eu-west-1"] },
144
+ });
145
+ var dr = b.db.getDataResidency();
146
+ check("getDataResidency returns config", dr && dr.region === "EU");
147
+ check("dataResidency includes allowedRegions", dr.allowedStorageRegions[0] === "eu-west-1");
148
+ } finally {
149
+ await teardownTestDb(tmpDir);
150
+ }
151
+ }
152
+
153
+ async function testStorage() {
154
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-storage-"));
155
+ try {
156
+ await setupTestDb(tmpDir);
157
+ b.storage.init({ backend: "local", uploadDir: path.join(tmpDir, "uploads") });
158
+
159
+ var content = Buffer.from("hello blamejs storage " + Date.now(), "utf8");
160
+ var saved = await b.storage.saveFile(content, "user-1/welcome.txt");
161
+ check("saveFile returns storedPath", saved.storedPath === "user-1/welcome.txt");
162
+ check("saveFile returns sealed encryptionKey",
163
+ typeof saved.encryptionKey === "string" && saved.encryptionKey.startsWith("vault:"));
164
+
165
+ // The on-disk file must NOT contain the plaintext content
166
+ var onDisk = fs.readFileSync(path.join(tmpDir, "uploads", "user-1/welcome.txt"));
167
+ check("on-disk file is encrypted (not plaintext)", onDisk.indexOf(content) === -1);
168
+ check("on-disk file starts with format byte 0x02", onDisk[0] === b.constants.FORMAT.XCHACHA20_POLY1305);
169
+
170
+ // Round-trip
171
+ var decrypted = await b.storage.getFileBuffer("user-1/welcome.txt", saved.encryptionKey);
172
+ check("getFileBuffer round-trip preserves content", decrypted.equals(content));
173
+
174
+ // Stream form
175
+ var stream = await b.storage.getFileStream("user-1/welcome.txt", saved.encryptionKey);
176
+ var chunks = [];
177
+ for await (var chunk of stream) chunks.push(chunk);
178
+ var streamed = Buffer.concat(chunks);
179
+ check("getFileStream round-trip preserves content", streamed.equals(content));
180
+
181
+ // Wrong key fails
182
+ var wrongRejected = false;
183
+ try { await b.storage.getFileBuffer("user-1/welcome.txt", b.vault.seal("not-the-real-key")); }
184
+ catch (_) { wrongRejected = true; }
185
+ check("getFileBuffer with wrong key throws", wrongRejected);
186
+
187
+ // No key required throws
188
+ var noKeyRejected = false;
189
+ try { await b.storage.getFileBuffer("user-1/welcome.txt", null); }
190
+ catch (_) { noKeyRejected = true; }
191
+ check("getFileBuffer without key throws", noKeyRejected);
192
+
193
+ // exists
194
+ check("exists returns true on present file", (await b.storage.exists("user-1/welcome.txt")) === true);
195
+ check("exists returns false on missing", (await b.storage.exists("does/not/exist.txt")) === false);
196
+
197
+ // saveRaw / getRawBuffer (no encryption)
198
+ var rawContent = Buffer.from("already-encrypted-or-not-sensitive", "utf8");
199
+ await b.storage.saveRaw(rawContent, "raw/blob.bin");
200
+ var rawBack = await b.storage.getRawBuffer("raw/blob.bin");
201
+ check("saveRaw / getRawBuffer round-trip", rawBack.equals(rawContent));
202
+
203
+ // deleteFile
204
+ check("deleteFile returns true on existing", (await b.storage.deleteFile("user-1/welcome.txt")) === true);
205
+ check("deleteFile returns false on missing", (await b.storage.deleteFile("user-1/welcome.txt")) === false);
206
+ check("file no longer exists after delete", (await b.storage.exists("user-1/welcome.txt")) === false);
207
+
208
+ // Path traversal rejected
209
+ var traversalRejected = false;
210
+ try { await b.storage.saveFile(content, "../escape.txt"); }
211
+ catch (_) { traversalRejected = true; }
212
+ check("path traversal via .. rejected", traversalRejected);
213
+
214
+ var absRejected = false;
215
+ try { await b.storage.saveFile(content, "/etc/passwd"); }
216
+ catch (_) { absRejected = true; }
217
+ check("absolute path rejected", absRejected);
218
+
219
+ var nullByteRejected = false;
220
+ try { await b.storage.saveFile(content, "okinjected"); }
221
+ catch (_) { nullByteRejected = true; }
222
+ check("null-byte in path rejected", nullByteRejected);
223
+
224
+ // S3 backend not yet available
225
+ b.storage._resetForTest();
226
+ var s3Rejected = false;
227
+ try { b.storage.init({ backend: "s3", bucket: "x" }); }
228
+ catch (e) { s3Rejected = /sigv4|deferred|not yet/i.test(e.message); }
229
+ check("storage backend 's3' deferred with clear message", s3Rejected);
230
+ } finally {
231
+ await teardownTestDb(tmpDir);
232
+ }
233
+ }
234
+
235
+ async function testMultiBackend() {
236
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-multi-"));
237
+ try {
238
+ await setupTestDb(tmpDir);
239
+ b.storage.init({
240
+ backends: {
241
+ "primary": {
242
+ protocol: "local",
243
+ rootDir: path.join(tmpDir, "primary"),
244
+ classifications: ["personal"],
245
+ residencyTag: "unrestricted",
246
+ },
247
+ "ops": {
248
+ protocol: "local",
249
+ rootDir: path.join(tmpDir, "ops"),
250
+ classifications: ["operational", "public"],
251
+ residencyTag: "unrestricted",
252
+ },
253
+ },
254
+ defaultClassification: "personal",
255
+ refuseUnclassified: true,
256
+ });
257
+
258
+ var listed = b.storage.listBackends();
259
+ check("listBackends returns 2 entries", listed.length === 2);
260
+ check("backend names enumerated", listed.some(b => b.name === "primary") && listed.some(b => b.name === "ops"));
261
+
262
+ // Save personal data → routes to 'primary'
263
+ var content1 = Buffer.from("private medical record", "utf8");
264
+ var saved1 = await b.storage.saveFile(content1, "patient/123.json", { classification: "personal" });
265
+ check("personal data routes to primary", saved1.backend === "primary");
266
+
267
+ // Save operational data → routes to 'ops'
268
+ var content2 = Buffer.from("nginx access log line", "utf8");
269
+ var saved2 = await b.storage.saveFile(content2, "logs/2026-04-25.log", { classification: "operational" });
270
+ check("operational data routes to ops", saved2.backend === "ops");
271
+
272
+ // File lands in the right physical directory
273
+ check("personal file in primary tree", fs.existsSync(path.join(tmpDir, "primary", "patient/123.json")));
274
+ check("operational file in ops tree", fs.existsSync(path.join(tmpDir, "ops", "logs/2026-04-25.log")));
275
+ check("personal NOT in ops tree", !fs.existsSync(path.join(tmpDir, "ops", "patient/123.json")));
276
+
277
+ // Round-trip with explicit backend opt
278
+ var back = await b.storage.getFileBuffer("patient/123.json", saved1.encryptionKey, { backend: "primary" });
279
+ check("explicit-backend round-trip works", back.equals(content1));
280
+
281
+ // Unknown classification → fails
282
+ var unknownClsRejected = false;
283
+ try { await b.storage.saveFile(content1, "test", { classification: "unknown" }); }
284
+ catch (e) { unknownClsRejected = e.code === "NO_BACKEND_FOR_CLASSIFICATION"; }
285
+ check("unknown classification rejected", unknownClsRejected);
286
+
287
+ // refuseUnclassified: missing classification rejected
288
+ var noClsRejected = false;
289
+ try { await b.storage.saveFile(content1, "test"); }
290
+ catch (e) { noClsRejected = e.code === "UNCLASSIFIED"; }
291
+ check("refuseUnclassified rejects missing classification", noClsRejected);
292
+
293
+ // Wrong-backend-for-classification rejected
294
+ var wrongBackendRejected = false;
295
+ try { await b.storage.saveFile(content1, "test", { backend: "ops", classification: "personal" }); }
296
+ catch (e) { wrongBackendRejected = e.code === "CLASSIFICATION_MISMATCH"; }
297
+ check("backend that doesn't serve classification rejected", wrongBackendRejected);
298
+ } finally {
299
+ await teardownTestDb(tmpDir);
300
+ }
301
+ }
302
+
303
+ async function testClassificationRouting() {
304
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-cls-"));
305
+ try {
306
+ await setupTestDb(tmpDir);
307
+ // Wildcard backend serves any classification
308
+ b.storage.init({
309
+ backends: {
310
+ "any": {
311
+ protocol: "local",
312
+ rootDir: path.join(tmpDir, "any"),
313
+ classifications: ["*"],
314
+ residencyTag: "unrestricted",
315
+ },
316
+ },
317
+ });
318
+
319
+ var c1 = Buffer.from("a", "utf8");
320
+ var s1 = await b.storage.saveFile(c1, "x", { classification: "personal" });
321
+ check("wildcard backend accepts personal", s1.backend === "any");
322
+ var s2 = await b.storage.saveFile(c1, "y", { classification: "audit-archive" });
323
+ check("wildcard backend accepts custom class", s2.backend === "any");
324
+ var s3 = await b.storage.saveFile(c1, "z");
325
+ check("wildcard backend accepts no-classification", s3.backend === "any");
326
+ } finally {
327
+ await teardownTestDb(tmpDir);
328
+ }
329
+ }
330
+
331
+ async function testResidencyEnforcement() {
332
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-residency-"));
333
+ try {
334
+ process.env.BLAMEJS_SKIP_NTP_CHECK = "1";
335
+ process.env.BLAMEJS_AUDIT_SIGNING_MODE = "plaintext";
336
+ b.vault._resetForTest();
337
+ b.db._resetForTest();
338
+ await b.vault.init({ dataDir: tmpDir, mode: "plaintext" });
339
+ await b.db.init({
340
+ dataDir: tmpDir,
341
+ atRest: "plain",
342
+ auditSigning: { mode: "plaintext" },
343
+ schema: [],
344
+ dataResidency: { region: "EU", allowedStorageRegions: ["EU"] },
345
+ });
346
+
347
+ // Configuring a personal-data backend tagged US should refuse to init
348
+ var residencyViolation = false;
349
+ try {
350
+ b.storage.init({
351
+ backends: {
352
+ "us-bad": {
353
+ protocol: "local",
354
+ rootDir: path.join(tmpDir, "us"),
355
+ classifications: ["personal"],
356
+ residencyTag: "US", // ← violation
357
+ },
358
+ },
359
+ });
360
+ } catch (e) {
361
+ residencyViolation = e.code === "RESIDENCY_VIOLATION";
362
+ }
363
+ check("personal-data backend outside region refused", residencyViolation);
364
+
365
+ // EU-tagged backend is fine
366
+ b.storage._resetForTest();
367
+ b.storage.init({
368
+ backends: {
369
+ "eu-ok": {
370
+ protocol: "local",
371
+ rootDir: path.join(tmpDir, "eu"),
372
+ classifications: ["personal"],
373
+ residencyTag: "EU",
374
+ },
375
+ },
376
+ });
377
+ var listed = b.storage.listBackends();
378
+ check("EU-tagged backend accepted", listed.length === 1 && listed[0].residencyTag === "EU");
379
+ } finally {
380
+ await teardownTestDb(tmpDir);
381
+ }
382
+ }
383
+
384
+ async function testRetryAndBreaker() {
385
+ // Retry policy unit tests — exercise withRetry directly without backend setup
386
+ var attempts = 0;
387
+ var transientErr = function () {
388
+ attempts += 1;
389
+ var e = new Error("transient");
390
+ e.statusCode = 503;
391
+ e.isObjectStoreError = true;
392
+ e.permanent = false;
393
+ throw e;
394
+ };
395
+
396
+ // Retries 5xx
397
+ var caught = false;
398
+ attempts = 0;
399
+ try {
400
+ await b.retry.withRetry(transientErr, { maxAttempts: 3, baseDelayMs: 1, maxDelayMs: 5 });
401
+ } catch (_) { caught = true; }
402
+ check("retry exhausts maxAttempts on transient", caught && attempts === 3);
403
+
404
+ // Does NOT retry permanent (4xx)
405
+ attempts = 0;
406
+ var permErr = function () {
407
+ attempts += 1;
408
+ var e = new Error("forbidden");
409
+ e.statusCode = 403;
410
+ e.isObjectStoreError = true;
411
+ e.permanent = true;
412
+ throw e;
413
+ };
414
+ var permCaught = false;
415
+ try { await b.retry.withRetry(permErr, { maxAttempts: 5 }); }
416
+ catch (_) { permCaught = true; }
417
+ check("retry does NOT retry permanent errors", permCaught && attempts === 1);
418
+
419
+ // Retryable classification
420
+ check("isRetryable: 503 → true", b.retry.isRetryable({ statusCode: 503 }));
421
+ check("isRetryable: 403 → false", !b.retry.isRetryable({ statusCode: 403 }));
422
+ check("isRetryable: ECONNRESET → true", b.retry.isRetryable({ code: "ECONNRESET" }));
423
+ check("isRetryable: ENOENT → false (not in retry set)", !b.retry.isRetryable({ code: "ENOENT" }));
424
+
425
+ // Circuit breaker
426
+ var breaker = new b.retry.CircuitBreaker("test", { failureThreshold: 3, cooldownMs: 50, successThreshold: 1 });
427
+ check("breaker starts closed", breaker.getState() === "closed");
428
+ // Trip it
429
+ for (var i = 0; i < 3; i++) {
430
+ try { await breaker.wrap(function () { throw Object.assign(new Error("fail"), { code: "ECONNRESET" }); }); }
431
+ catch (_) {}
432
+ }
433
+ check("breaker opens after threshold", breaker.getState() === "open");
434
+
435
+ // Open breaker fails fast (CIRCUIT_OPEN code)
436
+ var fastFail = false;
437
+ try { await breaker.wrap(function () { return Promise.resolve("never-runs"); }); }
438
+ catch (e) { fastFail = e.code === "CIRCUIT_OPEN"; }
439
+ check("open breaker fails fast", fastFail);
440
+
441
+ // Wait for cooldown then half-open + success closes
442
+ await new Promise(function (r) { setTimeout(r, 60); });
443
+ await breaker.wrap(function () { return Promise.resolve("ok"); });
444
+ check("breaker closes after successful probe", breaker.getState() === "closed");
445
+ }
446
+
447
+ function testSigv4Primitives() {
448
+ var sigv4 = require("../lib/object-store/sigv4");
449
+
450
+ // AWS-published test vector for signing-key derivation
451
+ // (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)
452
+ var key = sigv4.deriveSigningKey(
453
+ "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY",
454
+ "20150830",
455
+ "us-east-1",
456
+ "iam"
457
+ );
458
+ var hex = key.toString("hex");
459
+ check("sigv4 deriveSigningKey matches AWS test vector",
460
+ hex === "c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9");
461
+
462
+ // awsUriEncode
463
+ check("awsUriEncode preserves alphanumerics and unreserved",
464
+ sigv4.awsUriEncode("hello-world.txt", true) === "hello-world.txt");
465
+ check("awsUriEncode encodes spaces",
466
+ sigv4.awsUriEncode("a b", true) === "a%20b");
467
+ check("awsUriEncode preserves slashes when encodeSlash=false",
468
+ sigv4.awsUriEncode("foo/bar", false) === "foo/bar");
469
+ check("awsUriEncode encodes slashes when encodeSlash=true",
470
+ sigv4.awsUriEncode("foo/bar", true) === "foo%2Fbar");
471
+
472
+ // canonicalQueryString — sorted, encoded
473
+ var u = new (require("url").URL)("https://x/?b=2&a=1&c=3");
474
+ check("canonicalQueryString sorts keys",
475
+ sigv4.canonicalQueryString(u.searchParams) === "a=1&b=2&c=3");
476
+
477
+ // canonicalHeaders — lowercase keys, sorted, signed list
478
+ var ch = sigv4.canonicalHeaders({ "X-Foo": "bar", host: "example.com", "Z-Last": " trim " });
479
+ check("canonicalHeaders has trailing newline per pair",
480
+ /host:example\.com\n/.test(ch.canonical));
481
+ check("canonicalHeaders lowercases + sorts",
482
+ ch.signed === "host;x-foo;z-last");
483
+ check("canonicalHeaders trims + collapses whitespace",
484
+ /z-last:trim\n/.test(ch.canonical));
485
+
486
+ // signRequest produces an Authorization header with the right shape
487
+ var signed = sigv4.signRequest({
488
+ method: "GET",
489
+ url: "https://test-bucket.s3.us-east-1.amazonaws.com/key1",
490
+ headers: {},
491
+ payloadHash: sigv4.sha256Hex(Buffer.alloc(0)),
492
+ region: "us-east-1",
493
+ accessKeyId: "AKIAIOSFODNN7EXAMPLE",
494
+ secretAccessKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY",
495
+ date: new Date(Date.UTC(2026, 3, 25, 12, 34, 56)), // 2026-04-25T12:34:56Z
496
+ });
497
+ check("signRequest produces AWS4-HMAC-SHA256 Authorization",
498
+ /^AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE\/20260425\/us-east-1\/s3\/aws4_request, SignedHeaders=[a-z0-9;-]+, Signature=[0-9a-f]{64}$/.test(signed.headers["Authorization"]));
499
+ check("signRequest sets host header", signed.headers["host"] === "test-bucket.s3.us-east-1.amazonaws.com");
500
+ check("signRequest sets x-amz-date", signed.headers["x-amz-date"] === "20260425T123456Z");
501
+ check("signRequest sets x-amz-content-sha256",
502
+ signed.headers["x-amz-content-sha256"] === sigv4.sha256Hex(Buffer.alloc(0)));
503
+ check("signRequest signature is deterministic for same inputs",
504
+ signed.signature.length === 64);
505
+
506
+ // Same inputs → same signature
507
+ var signed2 = sigv4.signRequest({
508
+ method: "GET",
509
+ url: "https://test-bucket.s3.us-east-1.amazonaws.com/key1",
510
+ headers: {},
511
+ payloadHash: sigv4.sha256Hex(Buffer.alloc(0)),
512
+ region: "us-east-1",
513
+ accessKeyId: "AKIAIOSFODNN7EXAMPLE",
514
+ secretAccessKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY",
515
+ date: new Date(Date.UTC(2026, 3, 25, 12, 34, 56)),
516
+ });
517
+ check("signRequest deterministic across calls", signed.signature === signed2.signature);
518
+ }
519
+
520
+ async function testSigv4MockServer() {
521
+ var http = require("http");
522
+ var sigv4 = require("../lib/object-store/sigv4");
523
+
524
+ // In-process mock S3 server. Validates request shape (Authorization +
525
+ // x-amz-date + x-amz-content-sha256) and stores PUT bodies in memory
526
+ // so subsequent GET/HEAD/LIST/DELETE can return them.
527
+ var stored = {};
528
+ var server = http.createServer(function (req, res) {
529
+ var auth = req.headers["authorization"] || "";
530
+ if (!/^AWS4-HMAC-SHA256 /.test(auth)) {
531
+ res.writeHead(401); res.end("missing AWS4-HMAC-SHA256"); return;
532
+ }
533
+ if (!req.headers["x-amz-date"]) {
534
+ res.writeHead(400); res.end("missing x-amz-date"); return;
535
+ }
536
+ if (!req.headers["x-amz-content-sha256"]) {
537
+ res.writeHead(400); res.end("missing x-amz-content-sha256"); return;
538
+ }
539
+ // Strip query for routing; URL parse needs Host header
540
+ var pathname = req.url.split("?")[0];
541
+ // Path-style: /bucket/key → key extraction
542
+ var m = pathname.match(/^\/[^/]+\/(.+)$/);
543
+ var key = m ? m[1] : null;
544
+
545
+ if (req.method === "PUT" && key) {
546
+ var bufs = [];
547
+ req.on("data", function (c) { bufs.push(c); });
548
+ req.on("end", function () {
549
+ stored[key] = Buffer.concat(bufs); // lgtm[js/remote-property-injection] test fixture; not a runtime path
550
+ res.writeHead(200, { ETag: '"' + sigv4.sha256Hex(stored[key]).slice(0, 32) + '"' });
551
+ res.end();
552
+ });
553
+ return;
554
+ }
555
+ if (req.method === "GET" && key && stored[key]) {
556
+ res.writeHead(200, { "Content-Length": stored[key].length });
557
+ res.end(stored[key]);
558
+ return;
559
+ }
560
+ if (req.method === "GET" && pathname === "/test-bucket/" || (req.url || "").indexOf("list-type=2") !== -1) {
561
+ // List request
562
+ var xml = "<?xml version=\"1.0\"?><ListBucketResult>";
563
+ Object.keys(stored).forEach(function (k) {
564
+ xml += "<Contents><Key>" + k + "</Key><Size>" + stored[k].length + "</Size>" +
565
+ "<LastModified>2026-04-25T00:00:00.000Z</LastModified></Contents>";
566
+ });
567
+ xml += "<IsTruncated>false</IsTruncated></ListBucketResult>";
568
+ res.writeHead(200, { "Content-Type": "application/xml" });
569
+ res.end(xml);
570
+ return;
571
+ }
572
+ if (req.method === "HEAD" && key && stored[key]) {
573
+ res.writeHead(200, { "Content-Length": stored[key].length });
574
+ res.end();
575
+ return;
576
+ }
577
+ if (req.method === "DELETE" && key) {
578
+ if (stored[key]) {
579
+ delete stored[key]; // lgtm[js/remote-property-injection] test fixture; not a runtime path
580
+ res.writeHead(204); res.end();
581
+ } else {
582
+ res.writeHead(404); res.end();
583
+ }
584
+ return;
585
+ }
586
+ res.writeHead(404); res.end();
587
+ });
588
+
589
+ var port = await listenOnRandomPort(server);
590
+ try {
591
+ var client = sigv4.create({
592
+ endpoint: "http://127.0.0.1:" + port,
593
+ region: "us-east-1",
594
+ bucket: "test-bucket",
595
+ accessKeyId: "AKIAIOSFODNN7EXAMPLE",
596
+ secretAccessKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY",
597
+ pathStyle: true, // 127.0.0.1 doesn't support virtual-hosted
598
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL, // local mock — opt in to cleartext
599
+ allowInternal: true,
600
+ });
601
+
602
+ // PUT
603
+ var content = Buffer.from("sigv4 test payload " + Date.now(), "utf8");
604
+ var putResult = await client.put("dir/object.bin", content);
605
+ check("sigv4 put returns size + etag", putResult.size === content.length && typeof putResult.etag === "string");
606
+
607
+ // GET round-trip
608
+ var got = await client.get("dir/object.bin");
609
+ check("sigv4 get round-trips bytes", got.equals(content));
610
+
611
+ // HEAD
612
+ var meta = await client.head("dir/object.bin");
613
+ check("sigv4 head returns size", meta.size === content.length);
614
+
615
+ // LIST
616
+ var listed = await client.list("");
617
+ check("sigv4 list returns 1 item", listed.items.length === 1);
618
+ check("sigv4 list returns the key", listed.items[0].key === "dir/object.bin");
619
+
620
+ // DELETE
621
+ var del = await client.delete("dir/object.bin");
622
+ check("sigv4 delete returns true", del === true);
623
+ var del2 = await client.delete("dir/object.bin");
624
+ check("sigv4 delete on missing returns false", del2 === false);
625
+ } finally {
626
+ server.close();
627
+ }
628
+ }
629
+
630
+ function testGcsPrimitives() {
631
+ var gcs = require("../lib/object-store/gcs");
632
+
633
+ // base64url encoding (no padding, '+'→'-', '/'→'_')
634
+ var b1 = gcs._base64UrlEncode(Buffer.from("hello"));
635
+ check("gcs base64url encodes basic input", b1 === "aGVsbG8");
636
+ var b2 = gcs._base64UrlEncode(Buffer.from([0xff, 0xff, 0xff]));
637
+ check("gcs base64url has no padding", !/=/.test(b2));
638
+ check("gcs base64url uses '-' and '_'", !/\+|\//.test(b2));
639
+
640
+ // JWT signing with a real keypair
641
+ var sa = _makeFakeServiceAccount();
642
+ var jwt = gcs._signJwt(sa, "test-scope", "https://oauth2.googleapis.com/token");
643
+ var parts = jwt.split(".");
644
+ check("JWT has 3 parts", parts.length === 3);
645
+ // Header is base64url(JSON({ alg, typ }))
646
+ var headerJson = JSON.parse(Buffer.from(parts[0].replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8"));
647
+ check("JWT header alg is RS256", headerJson.alg === "RS256");
648
+ check("JWT header typ is JWT", headerJson.typ === "JWT");
649
+ var claimJson = JSON.parse(Buffer.from(parts[1].replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8"));
650
+ check("JWT iss is service-account email", claimJson.iss === sa.client_email);
651
+ check("JWT scope is honored", claimJson.scope === "test-scope");
652
+ check("JWT aud is token endpoint", claimJson.aud === "https://oauth2.googleapis.com/token");
653
+ check("JWT exp - iat = 3600", claimJson.exp - claimJson.iat === 3600);
654
+ }
655
+
656
+ async function testGcsMockServer() {
657
+ var http = require("http");
658
+ var url = require("url");
659
+ var gcs = require("../lib/object-store/gcs");
660
+ var sa = _makeFakeServiceAccount();
661
+
662
+ var stored = {};
663
+ var tokenIssued = 0;
664
+
665
+ // Mock OAuth2 token endpoint + storage JSON API on the same server,
666
+ // routed by pathname.
667
+ var server = http.createServer(function (req, res) {
668
+ var u = new url.URL(req.url, "http://x");
669
+ var path = u.pathname;
670
+
671
+ // Token exchange
672
+ if (req.method === "POST" && path === "/token") {
673
+ var bufs = [];
674
+ req.on("data", function (c) { bufs.push(c); });
675
+ req.on("end", function () {
676
+ var body = Buffer.concat(bufs).toString("utf8");
677
+ if (!/grant_type=urn/.test(body) || !/assertion=/.test(body)) {
678
+ res.writeHead(400); res.end("bad request"); return;
679
+ }
680
+ tokenIssued += 1;
681
+ res.writeHead(200, { "Content-Type": "application/json" });
682
+ res.end(JSON.stringify({ access_token: "mock-access-token-" + tokenIssued, expires_in: 3600, token_type: "Bearer" }));
683
+ });
684
+ return;
685
+ }
686
+
687
+ // All storage operations require Bearer auth
688
+ if (!/^Bearer mock-access-token-/.test(req.headers["authorization"] || "")) {
689
+ res.writeHead(401); res.end("missing bearer"); return;
690
+ }
691
+
692
+ // PUT object: POST /upload/storage/v1/b/<bucket>/o?uploadType=media&name=<key>
693
+ if (req.method === "POST" && /^\/upload\/storage\/v1\/b\/[^/]+\/o$/.test(path)) {
694
+ var name = u.searchParams.get("name");
695
+ var bufs2 = [];
696
+ req.on("data", function (c) { bufs2.push(c); });
697
+ req.on("end", function () {
698
+ stored[name] = Buffer.concat(bufs2);
699
+ res.writeHead(200, { "Content-Type": "application/json" });
700
+ res.end(JSON.stringify({ name: name, size: String(stored[name].length), etag: "\"" + name + "\"", updated: "2026-04-25T00:00:00.000Z" }));
701
+ });
702
+ return;
703
+ }
704
+
705
+ // GET / HEAD: /storage/v1/b/<bucket>/o/<encoded-key>
706
+ var objectMatch = path.match(/^\/storage\/v1\/b\/[^/]+\/o\/(.+)$/);
707
+ if (objectMatch && req.method === "GET") {
708
+ var key = decodeURIComponent(objectMatch[1]);
709
+ if (u.searchParams.get("alt") === "media") {
710
+ if (stored[key]) {
711
+ res.writeHead(200); res.end(stored[key]);
712
+ } else {
713
+ res.writeHead(404); res.end();
714
+ }
715
+ } else {
716
+ // metadata
717
+ if (stored[key]) {
718
+ res.writeHead(200, { "Content-Type": "application/json" });
719
+ res.end(JSON.stringify({ name: key, size: String(stored[key].length), etag: "\"" + key + "\"", updated: "2026-04-25T00:00:00.000Z" }));
720
+ } else {
721
+ res.writeHead(404); res.end();
722
+ }
723
+ }
724
+ return;
725
+ }
726
+ if (objectMatch && req.method === "DELETE") {
727
+ var dkey = decodeURIComponent(objectMatch[1]);
728
+ if (stored[dkey]) { delete stored[dkey]; res.writeHead(204); res.end(); }
729
+ else { res.writeHead(404); res.end(); }
730
+ return;
731
+ }
732
+
733
+ // LIST: /storage/v1/b/<bucket>/o (no /<key>)
734
+ if (req.method === "GET" && /^\/storage\/v1\/b\/[^/]+\/o$/.test(path)) {
735
+ var prefix = u.searchParams.get("prefix") || "";
736
+ var items = Object.keys(stored).filter(function (k) { return k.indexOf(prefix) === 0; }).map(function (k) {
737
+ return { name: k, size: String(stored[k].length), updated: "2026-04-25T00:00:00.000Z" };
738
+ });
739
+ res.writeHead(200, { "Content-Type": "application/json" });
740
+ res.end(JSON.stringify({ items: items }));
741
+ return;
742
+ }
743
+
744
+ res.writeHead(404); res.end();
745
+ });
746
+
747
+ var port = await listenOnRandomPort(server);
748
+ try {
749
+ var client = gcs.create({
750
+ bucket: "test-bucket",
751
+ serviceAccount: sa,
752
+ endpoint: "http://127.0.0.1:" + port,
753
+ tokenEndpoint: "http://127.0.0.1:" + port + "/token",
754
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
755
+ allowInternal: true,
756
+ });
757
+
758
+ var content = Buffer.from("gcs test payload " + Date.now(), "utf8");
759
+ var putResult = await client.put("dir/object.bin", content);
760
+ check("gcs put returns size", putResult.size === content.length);
761
+
762
+ var got = await client.get("dir/object.bin");
763
+ check("gcs get round-trips bytes", got.equals(content));
764
+
765
+ var meta = await client.head("dir/object.bin");
766
+ check("gcs head returns size", meta.size === content.length);
767
+
768
+ var listed = await client.list("");
769
+ check("gcs list returns 1 item", listed.items.length === 1);
770
+ check("gcs list returns the key", listed.items[0].key === "dir/object.bin");
771
+
772
+ var del = await client.delete("dir/object.bin");
773
+ check("gcs delete returns true", del === true);
774
+
775
+ // Token caching: should have only issued ONE token across all calls
776
+ check("gcs token issued once and cached across calls", tokenIssued === 1);
777
+ } finally {
778
+ server.close();
779
+ }
780
+ }
781
+
782
+ function testAzureBlobPrimitives() {
783
+ var az = require("../lib/object-store/azure-blob");
784
+
785
+ // signRequest produces SharedKey-format Authorization
786
+ var s = az.signRequest({
787
+ method: "PUT",
788
+ url: "https://test.blob.core.windows.net/c/key1",
789
+ headers: { "Content-Type": "application/octet-stream", "Content-Length": "5", "x-ms-blob-type": "BlockBlob" },
790
+ accountName: "test",
791
+ accountKey: Buffer.from("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "utf8").toString("base64"),
792
+ });
793
+ check("azure signRequest produces SharedKey auth", /^SharedKey test:/.test(s.headers["Authorization"]));
794
+ check("azure signRequest sets x-ms-version", !!s.headers["x-ms-version"]);
795
+ check("azure signRequest sets x-ms-date", !!s.headers["x-ms-date"]);
796
+ check("azure signature is base64", /^[A-Za-z0-9+/=]+$/.test(s.signature));
797
+
798
+ // Same inputs at same time produce same signature
799
+ var date = new Date(Date.UTC(2026, 3, 25, 12, 34, 56));
800
+ var dateStr = date.toUTCString();
801
+ var s1 = az.signRequest({
802
+ method: "GET",
803
+ url: "https://test.blob.core.windows.net/c/key2",
804
+ headers: { "x-ms-date": dateStr },
805
+ accountName: "test",
806
+ accountKey: Buffer.from("ZZZZZZZZ", "base64").toString("base64"),
807
+ });
808
+ var s2 = az.signRequest({
809
+ method: "GET",
810
+ url: "https://test.blob.core.windows.net/c/key2",
811
+ headers: { "x-ms-date": dateStr },
812
+ accountName: "test",
813
+ accountKey: Buffer.from("ZZZZZZZZ", "base64").toString("base64"),
814
+ });
815
+ check("azure signature deterministic for same inputs", s1.signature === s2.signature);
816
+ }
817
+
818
+ async function testAzureBlobMockServer() {
819
+ var http = require("http");
820
+ var az = require("../lib/object-store/azure-blob");
821
+
822
+ var stored = {};
823
+ var server = http.createServer(function (req, res) {
824
+ if (!/^SharedKey /.test(req.headers["authorization"] || "")) {
825
+ res.writeHead(401); res.end("missing SharedKey"); return;
826
+ }
827
+ if (!req.headers["x-ms-version"]) { res.writeHead(400); res.end("missing x-ms-version"); return; }
828
+ if (!req.headers["x-ms-date"]) { res.writeHead(400); res.end("missing x-ms-date"); return; }
829
+
830
+ var path = req.url.split("?")[0];
831
+ var keyMatch = path.match(/^\/[^/]+\/(.+)$/);
832
+ var key = keyMatch ? keyMatch[1] : null;
833
+
834
+ if (req.method === "PUT" && key) {
835
+ if (req.headers["x-ms-blob-type"] !== "BlockBlob") { res.writeHead(400); res.end("bad blob type"); return; }
836
+ var bufs = [];
837
+ req.on("data", function (c) { bufs.push(c); });
838
+ req.on("end", function () {
839
+ stored[key] = Buffer.concat(bufs); // lgtm[js/remote-property-injection] test fixture; not a runtime path
840
+ res.writeHead(201, { ETag: "\"" + key + "\"" });
841
+ res.end();
842
+ });
843
+ return;
844
+ }
845
+ if (req.method === "GET" && key && stored[key]) {
846
+ res.writeHead(200, { "Content-Length": stored[key].length });
847
+ res.end(stored[key]);
848
+ return;
849
+ }
850
+ if (req.method === "HEAD" && key && stored[key]) {
851
+ res.writeHead(200, { "Content-Length": stored[key].length });
852
+ res.end();
853
+ return;
854
+ }
855
+ if (req.method === "DELETE" && key) {
856
+ if (stored[key]) { delete stored[key]; res.writeHead(202); res.end(); } // lgtm[js/remote-property-injection] test fixture; not a runtime path
857
+ else { res.writeHead(404); res.end(); }
858
+ return;
859
+ }
860
+ if (req.method === "GET" && (req.url || "").indexOf("comp=list") !== -1) {
861
+ var xml = "<?xml version=\"1.0\"?><EnumerationResults><Blobs>";
862
+ Object.keys(stored).forEach(function (k) {
863
+ xml += "<Blob><Name>" + k + "</Name><Properties><Content-Length>" + stored[k].length + "</Content-Length><Last-Modified>Sat, 25 Apr 2026 00:00:00 GMT</Last-Modified></Properties></Blob>";
864
+ });
865
+ xml += "</Blobs><NextMarker/></EnumerationResults>";
866
+ res.writeHead(200, { "Content-Type": "application/xml" });
867
+ res.end(xml);
868
+ return;
869
+ }
870
+ res.writeHead(404); res.end();
871
+ });
872
+
873
+ var port = await listenOnRandomPort(server);
874
+ try {
875
+ var client = az.create({
876
+ accountName: "test",
877
+ accountKey: Buffer.from("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "utf8").toString("base64"),
878
+ container: "test-container",
879
+ endpoint: "http://127.0.0.1:" + port,
880
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
881
+ allowInternal: true,
882
+ });
883
+
884
+ var content = Buffer.from("azure test payload " + Date.now(), "utf8");
885
+ var putResult = await client.put("dir/blob.bin", content);
886
+ check("azure put returns size", putResult.size === content.length);
887
+
888
+ var got = await client.get("dir/blob.bin");
889
+ check("azure get round-trips bytes", got.equals(content));
890
+
891
+ var meta = await client.head("dir/blob.bin");
892
+ check("azure head returns size", meta.size === content.length);
893
+
894
+ var listed = await client.list("");
895
+ check("azure list returns 1 item", listed.items.length === 1);
896
+ check("azure list returns the key", listed.items[0].key === "dir/blob.bin");
897
+
898
+ var del = await client.delete("dir/blob.bin");
899
+ check("azure delete returns true", del === true);
900
+ } finally {
901
+ server.close();
902
+ }
903
+ }
904
+
905
+ async function testQueueLocal() {
906
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-queue-"));
907
+ try {
908
+ await setupTestDb(tmpDir);
909
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
910
+
911
+ check("queue namespace present", typeof b.queue === "object");
912
+ check("queue.listBackends has 1 entry", b.queue.listBackends().length === 1);
913
+
914
+ // Enqueue
915
+ var result = await b.queue.enqueue("send-welcome", { userId: "u-1", email: "a@b.com" }, {
916
+ classification: "personal",
917
+ traceId: "trace-123",
918
+ });
919
+ check("enqueue returns jobId", typeof result.jobId === "string");
920
+ check("enqueue returns queueName", result.queueName === "send-welcome");
921
+ check("enqueue returns classification", result.classification === "personal");
922
+
923
+ // size reflects pending
924
+ check("size returns 1 after one enqueue", (await b.queue.size("send-welcome")) === 1);
925
+
926
+ // payload sealed on disk
927
+ var rawRow = b.db.prepare("SELECT payload FROM _blamejs_jobs WHERE _id = ?").get(result.jobId);
928
+ check("queue payload sealed in DB", rawRow.payload.startsWith("vault:"));
929
+
930
+ // unrelated queue is independent
931
+ check("size returns 0 for empty queue", (await b.queue.size("other-queue")) === 0);
932
+
933
+ // purge clears
934
+ var purged = await b.queue.purge("send-welcome");
935
+ check("purge returns count of deleted", purged === 1);
936
+ check("size returns 0 after purge", (await b.queue.size("send-welcome")) === 0);
937
+
938
+ // Reserved table name protection still works
939
+ check("_blamejs_jobs is reserved", b.db.RESERVED_TABLE_NAMES.has("_blamejs_jobs"));
940
+ } finally {
941
+ try { await b.queue.shutdown({ timeoutMs: 1000 }); } catch (_e) {}
942
+ await teardownTestDb(tmpDir);
943
+ }
944
+ }
945
+
946
+ async function testQueueConsume() {
947
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-qcons-"));
948
+ try {
949
+ await setupTestDb(tmpDir);
950
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
951
+
952
+ var processed = [];
953
+ var consumer = b.queue.consume("test-job", function (job) {
954
+ processed.push(job.payload);
955
+ return Promise.resolve();
956
+ }, { concurrency: 2, pollIntervalMs: 50, fastPollMs: 20, leaseDurationMs: 5000 });
957
+
958
+ await b.queue.enqueue("test-job", { msg: "hello-1" });
959
+ await b.queue.enqueue("test-job", { msg: "hello-2" });
960
+ await b.queue.enqueue("test-job", { msg: "hello-3" });
961
+
962
+ // Wait for processing (poll up to 3s)
963
+ var deadline = Date.now() + 3000;
964
+ while (processed.length < 3 && Date.now() < deadline) {
965
+ await new Promise(function (r) { setTimeout(r, 50); });
966
+ }
967
+ check("consume processed all 3 jobs", processed.length === 3);
968
+ check("payloads decoded correctly", processed.some(p => p.msg === "hello-1"));
969
+ check("queue size 0 after consume", (await b.queue.size("test-job")) === 0);
970
+
971
+ // All jobs should be in 'done' status
972
+ var doneCount = b.db.prepare("SELECT COUNT(*) AS n FROM _blamejs_jobs WHERE queueName = ? AND status = ?").get("test-job", "done");
973
+ check("all jobs marked done", doneCount.n === 3);
974
+
975
+ // Drain buffered audit emissions before reading audit_log.
976
+ await b.audit.flush();
977
+ // Audit chain has system.queue.enqueue + .consume.start + .consume.success
978
+ var enqRows = await b.audit.query({ action: "system.queue.enqueue" });
979
+ check("audit recorded enqueue events", enqRows.length === 3);
980
+ var sucRows = await b.audit.query({ action: "system.queue.consume.success" });
981
+ check("audit recorded consume.success events", sucRows.length === 3);
982
+
983
+ consumer.cancel();
984
+ } finally {
985
+ try { await b.queue.shutdown({ timeoutMs: 1000 }); } catch (_e) {}
986
+ await teardownTestDb(tmpDir);
987
+ }
988
+ }
989
+
990
+ async function testQueueRetryAndFail() {
991
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-qfail-"));
992
+ try {
993
+ await setupTestDb(tmpDir);
994
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
995
+
996
+ var attempts = 0;
997
+ var consumer = b.queue.consume("fail-job", function (_job) {
998
+ attempts += 1;
999
+ throw new Error("simulated failure attempt " + attempts);
1000
+ }, { concurrency: 1, pollIntervalMs: 50, fastPollMs: 20, leaseDurationMs: 5000 });
1001
+
1002
+ await b.queue.enqueue("fail-job", { x: 1 }, { maxAttempts: 3 });
1003
+
1004
+ // Wait until job is finally failed (3 attempts × ~exponential backoff = up to ~7s)
1005
+ var deadline = Date.now() + 12000;
1006
+ var lastStatus;
1007
+ while (Date.now() < deadline) {
1008
+ var row = b.db.prepare("SELECT status FROM _blamejs_jobs WHERE queueName = ?").get("fail-job");
1009
+ lastStatus = row && row.status;
1010
+ if (lastStatus === "failed") break;
1011
+ await new Promise(function (r) { setTimeout(r, 100); });
1012
+ }
1013
+ check("job ends up in 'failed' status after maxAttempts", lastStatus === "failed");
1014
+ check("handler invoked maxAttempts times", attempts === 3);
1015
+
1016
+ // Drain buffered audit emissions before reading audit_log.
1017
+ await b.audit.flush();
1018
+ // Audit chain has consume.failure events
1019
+ var failRows = await b.audit.query({ action: "system.queue.consume.failure" });
1020
+ check("audit recorded consume.failure events", failRows.length === 3);
1021
+
1022
+ consumer.cancel();
1023
+ } finally {
1024
+ try { await b.queue.shutdown({ timeoutMs: 1000 }); } catch (_e) {}
1025
+ await teardownTestDb(tmpDir);
1026
+ }
1027
+ }
1028
+
1029
+ async function testQueueLeaseExpiry() {
1030
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-qlease-"));
1031
+ try {
1032
+ await setupTestDb(tmpDir);
1033
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
1034
+
1035
+ // Manually call lease via the backend to simulate a crashed handler
1036
+ // (lease the job, never complete or fail it).
1037
+ var localBackend = require("../lib/queue-local").create({});
1038
+ await b.queue.enqueue("orphan-job", { x: 1 });
1039
+ var leased = await localBackend.lease("orphan-job", 100, 1); // 100ms lease
1040
+ check("lease returned the job", leased.length === 1);
1041
+ check("after lease, job status is inflight",
1042
+ b.db.prepare("SELECT status FROM _blamejs_jobs WHERE queueName = ?").get("orphan-job").status === "inflight");
1043
+
1044
+ // Wait for lease to expire, then sweep
1045
+ await new Promise(function (r) { setTimeout(r, 200); });
1046
+ var swept = await localBackend.sweepExpired();
1047
+ check("sweepExpired returned 1 unstuck job", swept === 1);
1048
+ check("unstuck job is back to pending",
1049
+ b.db.prepare("SELECT status FROM _blamejs_jobs WHERE queueName = ?").get("orphan-job").status === "pending");
1050
+ } finally {
1051
+ try { await b.queue.shutdown({ timeoutMs: 1000 }); } catch (_e) {}
1052
+ await teardownTestDb(tmpDir);
1053
+ }
1054
+ }
1055
+
1056
+ async function testQueueShutdown() {
1057
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-qsh-"));
1058
+ try {
1059
+ await setupTestDb(tmpDir);
1060
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
1061
+
1062
+ var processed = 0;
1063
+ var consumer = b.queue.consume("shutdown-job", async function (_job) {
1064
+ // Long-running handler
1065
+ await new Promise(function (r) { setTimeout(r, 200); });
1066
+ processed += 1;
1067
+ }, { concurrency: 2, pollIntervalMs: 30, fastPollMs: 10, leaseDurationMs: 5000 });
1068
+
1069
+ for (var i = 0; i < 3; i++) await b.queue.enqueue("shutdown-job", { i: i });
1070
+ await new Promise(function (r) { setTimeout(r, 100) }); // let some lease
1071
+
1072
+ var t0 = Date.now();
1073
+ await b.queue.shutdown({ timeoutMs: 5000 });
1074
+ var elapsed = Date.now() - t0;
1075
+
1076
+ check("shutdown waits for in-flight handlers", processed >= 1);
1077
+ check("shutdown completes under timeout", elapsed < 5000);
1078
+ void consumer;
1079
+ } finally {
1080
+ await teardownTestDb(tmpDir);
1081
+ }
1082
+ }
1083
+
1084
+ async function testJobsDefineAndEnqueue() {
1085
+ // Surface tests + a single-job round-trip. Uses the framework's
1086
+ // built-in 'local' queue protocol (SQLite via the framework DB).
1087
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-jobs-"));
1088
+ try {
1089
+ await setupTestDb(tmpDir);
1090
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
1091
+ var jobs = b.jobs.create();
1092
+ var processed = [];
1093
+ jobs.define("welcome", async function (job) {
1094
+ processed.push(job.payload.userId);
1095
+ });
1096
+
1097
+ // stats() pre-start
1098
+ var s0 = jobs.stats();
1099
+ check("jobs.stats: defined names listed", s0.defined.length === 1 && s0.defined[0] === "welcome");
1100
+ check("jobs.stats: started=false before start", s0.started === false);
1101
+
1102
+ // enqueue before start is fine — queue persists rows
1103
+ var enq = await jobs.enqueue("welcome", { userId: "u-1" });
1104
+ check("jobs.enqueue returns jobId", typeof enq.jobId === "string");
1105
+
1106
+ await jobs.start();
1107
+ check("jobs.stats: started=true after start", jobs.stats().started === true);
1108
+
1109
+ // Wait for the consumer to drain
1110
+ var t0 = Date.now();
1111
+ while (processed.length === 0 && Date.now() - t0 < 5000) {
1112
+ await new Promise(function (r) { setTimeout(r, 50); });
1113
+ }
1114
+ check("jobs: handler ran for enqueued job", processed.length === 1 && processed[0] === "u-1");
1115
+
1116
+ await jobs.shutdown({ timeoutMs: 2000 });
1117
+ check("jobs.shutdown: started=false after", jobs.stats().started === false);
1118
+ } finally {
1119
+ await teardownTestDb(tmpDir);
1120
+ }
1121
+ }
1122
+
1123
+ async function testJobsValidation() {
1124
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-jobs-"));
1125
+ try {
1126
+ await setupTestDb(tmpDir);
1127
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
1128
+ var jobs = b.jobs.create();
1129
+
1130
+ // Invalid name / handler
1131
+ var threw = null;
1132
+ try { jobs.define("", async function () {}); } catch (e) { threw = e; }
1133
+ check("jobs.define: empty name rejected", threw && threw.code === "INVALID_NAME");
1134
+
1135
+ threw = null;
1136
+ try { jobs.define("x", "not-a-fn"); } catch (e) { threw = e; }
1137
+ check("jobs.define: non-function handler rejected", threw && threw.code === "INVALID_HANDLER");
1138
+
1139
+ // Duplicate
1140
+ jobs.define("dup", async function () {});
1141
+ threw = null;
1142
+ try { jobs.define("dup", async function () {}); } catch (e) { threw = e; }
1143
+ check("jobs.define: duplicate name rejected", threw && threw.code === "DUPLICATE_NAME");
1144
+
1145
+ // enqueue without define
1146
+ threw = null;
1147
+ try { await jobs.enqueue("never-defined", {}); } catch (e) { threw = e; }
1148
+ check("jobs.enqueue: undefined name rejected", threw && threw.code === "UNDEFINED_NAME");
1149
+
1150
+ // allowUnregistered: true bypasses
1151
+ var permissive = b.jobs.create({ allowUnregisteredEnqueue: true });
1152
+ var enqOk = await permissive.enqueue("late-binding", { x: 1 });
1153
+ check("jobs.enqueue: allowUnregistered passes", typeof enqOk.jobId === "string");
1154
+
1155
+ // define after start rejected
1156
+ await jobs.start();
1157
+ threw = null;
1158
+ try { jobs.define("post-start", async function () {}); } catch (e) { threw = e; }
1159
+ check("jobs.define after start rejected", threw && threw.code === "ALREADY_STARTED");
1160
+
1161
+ await jobs.shutdown({ timeoutMs: 2000 });
1162
+ await permissive.shutdown({ timeoutMs: 2000 });
1163
+ } finally {
1164
+ await teardownTestDb(tmpDir);
1165
+ }
1166
+ }
1167
+
1168
+ async function testJobsMultipleHandlers() {
1169
+ // Two handlers, each consuming its own queue, dispatched correctly.
1170
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-jobs-"));
1171
+ try {
1172
+ await setupTestDb(tmpDir);
1173
+ b.queue.init({ backends: { primary: { protocol: "local" } } });
1174
+ var jobs = b.jobs.create({
1175
+ consumerDefaults: { pollIntervalMs: 30, fastPollMs: 10 },
1176
+ });
1177
+ var emails = [];
1178
+ var rebuilds = [];
1179
+ jobs.define("send-email", async function (job) { emails.push(job.payload.to); });
1180
+ jobs.define("rebuild-index", async function (job) { rebuilds.push(job.payload.what); });
1181
+
1182
+ await jobs.start();
1183
+ await jobs.enqueue("send-email", { to: "alice@example.com" });
1184
+ await jobs.enqueue("send-email", { to: "bob@example.com" });
1185
+ await jobs.enqueue("rebuild-index", { what: "users" });
1186
+
1187
+ var t0 = Date.now();
1188
+ while ((emails.length < 2 || rebuilds.length < 1) && Date.now() - t0 < 5000) {
1189
+ await new Promise(function (r) { setTimeout(r, 50); });
1190
+ }
1191
+ check("jobs: both email handlers ran", emails.length === 2);
1192
+ check("jobs: rebuild handler ran", rebuilds.length === 1);
1193
+ // Cross-handler isolation
1194
+ check("jobs: email handler didn't see rebuild payload",
1195
+ emails.indexOf("users") === -1);
1196
+
1197
+ await jobs.shutdown({ timeoutMs: 2000 });
1198
+ } finally {
1199
+ await teardownTestDb(tmpDir);
1200
+ }
1201
+ }
1202
+
1203
+ function testJobsSurface() {
1204
+ check("b.jobs namespace present", typeof b.jobs === "object");
1205
+ check("b.jobs.create is a function", typeof b.jobs.create === "function");
1206
+ }
1207
+
1208
+ async function testLogStreamLocal() {
1209
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-log-"));
1210
+ try {
1211
+ await setupTestDb(tmpDir);
1212
+ b.logStream.init({
1213
+ sinks: { primary: { protocol: "local", dir: path.join(tmpDir, "logs"), maxFileBytes: 1024 } },
1214
+ minLevel: "debug",
1215
+ });
1216
+
1217
+ check("logStream namespace present", typeof b.logStream === "object");
1218
+ check("logStream.LEVELS includes debug/info/warn/error",
1219
+ b.logStream.LEVELS.length === 4);
1220
+
1221
+ b.logStream.info("hello world", { user: "alice" });
1222
+ b.logStream.warn("watch out", { password: "should-be-redacted" });
1223
+ b.logStream.error("kaboom", { jwt: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.aaaa.bbbb" });
1224
+
1225
+ // Allow async writes to complete
1226
+ await new Promise(function (r) { setTimeout(r, 50); });
1227
+ await b.logStream.shutdown();
1228
+
1229
+ var logPath = path.join(tmpDir, "logs", "blamejs.log");
1230
+ check("log file exists", fs.existsSync(logPath));
1231
+ var content = fs.readFileSync(logPath, "utf8");
1232
+ var lines = content.trim().split("\n").filter(Boolean);
1233
+ check("3 events emitted as JSON lines", lines.length === 3);
1234
+
1235
+ var infoRecord = JSON.parse(lines[0]);
1236
+ check("first record has level=info", infoRecord.level === "info");
1237
+ check("first record has message", infoRecord.message === "hello world");
1238
+ check("first record has meta.user", infoRecord.meta.user === "alice");
1239
+
1240
+ var warnRecord = JSON.parse(lines[1]);
1241
+ check("warn record password is redacted", warnRecord.meta.password === "[REDACTED]");
1242
+
1243
+ var errRecord = JSON.parse(lines[2]);
1244
+ check("error record JWT-shaped value redacted", errRecord.meta.jwt === "[REDACTED-JWT]");
1245
+ } finally {
1246
+ await teardownTestDb(tmpDir);
1247
+ }
1248
+ }
1249
+
1250
+ async function testLogStreamWebhook() {
1251
+ var http = require("http");
1252
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-loghook-"));
1253
+ try {
1254
+ await setupTestDb(tmpDir);
1255
+
1256
+ var received = [];
1257
+ var server = http.createServer(function (req, res) {
1258
+ if (req.headers["authorization"] !== "Bearer test-token") {
1259
+ res.writeHead(401); res.end("missing auth"); return;
1260
+ }
1261
+ var bufs = [];
1262
+ req.on("data", function (c) { bufs.push(c); });
1263
+ req.on("end", function () {
1264
+ try {
1265
+ var batch = JSON.parse(Buffer.concat(bufs).toString("utf8"));
1266
+ batch.forEach(function (ev) { received.push(ev); });
1267
+ res.writeHead(200); res.end("ok");
1268
+ } catch (e) { res.writeHead(400); res.end(e.message); }
1269
+ });
1270
+ });
1271
+ var port = await listenOnRandomPort(server);
1272
+
1273
+ try {
1274
+ b.logStream.init({
1275
+ sinks: {
1276
+ siem: {
1277
+ protocol: "webhook",
1278
+ url: "http://127.0.0.1:" + port + "/ingest",
1279
+ auth: "bearer",
1280
+ token: "test-token",
1281
+ batchSize: 2,
1282
+ maxBatchAgeMs: 100,
1283
+ bodyShape: "array",
1284
+ retry: { maxAttempts: 1 },
1285
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1286
+ allowInternal: true,
1287
+ },
1288
+ },
1289
+ });
1290
+
1291
+ b.logStream.info("first", { x: 1 });
1292
+ b.logStream.info("second", { x: 2 });
1293
+ // batchSize=2 should trigger immediate flush
1294
+ await new Promise(function (r) { setTimeout(r, 200); });
1295
+
1296
+ check("webhook received 2 events", received.length === 2);
1297
+ check("first event message", received[0].message === "first");
1298
+ check("second event message", received[1].message === "second");
1299
+
1300
+ // Auth failure path: send another event after server stops accepting
1301
+ b.logStream.info("third", { x: 3 });
1302
+ await new Promise(function (r) { setTimeout(r, 200); });
1303
+ check("third event delivered (under batch size, flushed by age)", received.length >= 3);
1304
+
1305
+ await b.logStream.shutdown();
1306
+ } finally {
1307
+ server.close();
1308
+ }
1309
+ } finally {
1310
+ await teardownTestDb(tmpDir);
1311
+ }
1312
+ }
1313
+
1314
+ async function testLogStreamBidirectional() {
1315
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-logbidi-"));
1316
+ try {
1317
+ await setupTestDb(tmpDir);
1318
+ b.logStream.init({
1319
+ sinks: { primary: { protocol: "local", dir: path.join(tmpDir, "logs") } },
1320
+ });
1321
+
1322
+ var received = [];
1323
+ var unregister = b.logStream.onIncoming(async function (payload, opts) {
1324
+ received.push({ payload: payload, opts: opts });
1325
+ return "ack-" + (received.length);
1326
+ });
1327
+
1328
+ var results = await b.logStream.deliverIncoming({ command: "block-user", userId: "u-123" }, { source: "siem-test" });
1329
+ check("deliverIncoming routes to handler", received.length === 1);
1330
+ check("payload preserved", received[0].payload.command === "block-user");
1331
+ check("opts.source preserved", received[0].opts.source === "siem-test");
1332
+ check("handler return value captured in results", results[0].ok === true && results[0].value === "ack-1");
1333
+
1334
+ // Drain buffered audit emissions before reading audit_log.
1335
+ await b.audit.flush();
1336
+ // Audit: incoming command logged
1337
+ var incRows = await b.audit.query({ action: "system.log.incoming" });
1338
+ check("audit recorded system.log.incoming", incRows.length === 1);
1339
+
1340
+ // Unregister and verify no further dispatch
1341
+ unregister();
1342
+ await b.logStream.deliverIncoming({ command: "second" });
1343
+ check("after unregister, handler no longer called", received.length === 1);
1344
+
1345
+ await b.logStream.shutdown();
1346
+ } finally {
1347
+ await teardownTestDb(tmpDir);
1348
+ }
1349
+ }
1350
+
1351
+ async function testExternalDbBasic() {
1352
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-extdb-"));
1353
+ try {
1354
+ await setupTestDb(tmpDir);
1355
+ var driver = _makeFakeDriver();
1356
+ b.externalDb.init({
1357
+ backends: {
1358
+ "primary": {
1359
+ connect: driver.connect,
1360
+ query: driver.query,
1361
+ close: driver.close,
1362
+ ping: driver.ping,
1363
+ },
1364
+ },
1365
+ });
1366
+
1367
+ check("externalDb namespace present", typeof b.externalDb === "object");
1368
+
1369
+ var listed = b.externalDb.listBackends();
1370
+ check("listBackends returns 1 entry", listed.length === 1);
1371
+
1372
+ var insertResult = await b.externalDb.query(
1373
+ "INSERT INTO kv (id, value) VALUES ($1, $2)", ["k1", "v1"]
1374
+ );
1375
+ check("insert returns rowCount = 1", insertResult.rowCount === 1);
1376
+
1377
+ var selectResult = await b.externalDb.query(
1378
+ "SELECT id, value FROM kv WHERE id = $1", ["k1"]
1379
+ );
1380
+ check("select returns the inserted row", selectResult.rows[0].value === "v1");
1381
+
1382
+ var miss = await b.externalDb.query(
1383
+ "SELECT id, value FROM kv WHERE id = $1", ["missing"]
1384
+ );
1385
+ check("miss returns 0 rows", miss.rowCount === 0);
1386
+
1387
+ // Health check
1388
+ var hc = await b.externalDb.healthCheck();
1389
+ check("healthCheck returns ok for primary", hc.primary && hc.primary.ok === true);
1390
+ check("healthCheck returns breakerState", hc.primary.breakerState === "closed");
1391
+
1392
+ // Drain buffered audit emissions before reading audit_log.
1393
+ await b.audit.flush();
1394
+ // Audit recorded
1395
+ var qRows = await b.audit.query({ action: "system.externaldb.query" });
1396
+ check("audit recorded externaldb.query events", qRows.length >= 3);
1397
+ } finally {
1398
+ try { await b.externalDb.shutdown(); } catch (_e) {}
1399
+ await teardownTestDb(tmpDir);
1400
+ }
1401
+ }
1402
+
1403
+ async function testExternalDbPool() {
1404
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-extdbpool-"));
1405
+ try {
1406
+ await setupTestDb(tmpDir);
1407
+ var driver = _makeFakeDriver();
1408
+ b.externalDb.init({
1409
+ backends: {
1410
+ "primary": {
1411
+ connect: driver.connect, query: driver.query, close: driver.close,
1412
+ pool: { min: 0, max: 3, idleTimeoutMs: 60000 },
1413
+ },
1414
+ },
1415
+ });
1416
+
1417
+ // Sequential queries reuse the same connection
1418
+ await b.externalDb.query("SELECT 1");
1419
+ await b.externalDb.query("SELECT 1");
1420
+ await b.externalDb.query("SELECT 1");
1421
+ var s = driver.getStats();
1422
+ check("pool reuses idle connection", s.connectCount === 1);
1423
+
1424
+ // Concurrent queries open up to max
1425
+ var promises = [];
1426
+ for (var i = 0; i < 5; i++) promises.push(b.externalDb.query("SELECT 1"));
1427
+ await Promise.all(promises);
1428
+ var s2 = driver.getStats();
1429
+ check("concurrent queries open up to pool.max", s2.connectCount <= 3);
1430
+
1431
+ // listBackends shows pool stats
1432
+ var listed = b.externalDb.listBackends();
1433
+ check("listBackends includes pool stats", typeof listed[0].pool === "object");
1434
+ } finally {
1435
+ try { await b.externalDb.shutdown(); } catch (_e) {}
1436
+ await teardownTestDb(tmpDir);
1437
+ }
1438
+ }
1439
+
1440
+ async function testExternalDbTransaction() {
1441
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-extdbtx-"));
1442
+ try {
1443
+ await setupTestDb(tmpDir);
1444
+ var driver = _makeFakeDriver();
1445
+ b.externalDb.init({
1446
+ backends: {
1447
+ "primary": {
1448
+ connect: driver.connect, query: driver.query, close: driver.close,
1449
+ },
1450
+ },
1451
+ });
1452
+
1453
+ // Successful transaction commits
1454
+ var commitResult = await b.externalDb.transaction(async function (tx) {
1455
+ await tx.query("INSERT INTO kv (id, value) VALUES ($1, $2)", ["tx1", "a"]);
1456
+ await tx.query("INSERT INTO kv (id, value) VALUES ($1, $2)", ["tx2", "b"]);
1457
+ return "all-good";
1458
+ });
1459
+ check("transaction returns fn's return value", commitResult === "all-good");
1460
+ var got1 = await b.externalDb.query("SELECT id, value FROM kv WHERE id = $1", ["tx1"]);
1461
+ check("committed rows visible", got1.rows[0].value === "a");
1462
+
1463
+ // Failed transaction (handler throws) — rollback
1464
+ var caught = false;
1465
+ try {
1466
+ await b.externalDb.transaction(async function (tx) {
1467
+ await tx.query("INSERT INTO kv (id, value) VALUES ($1, $2)", ["tx3", "c"]);
1468
+ throw new Error("simulated");
1469
+ });
1470
+ } catch (e) { caught = e.message === "simulated"; }
1471
+ check("transaction error propagates", caught);
1472
+
1473
+ // External-db's audit emissions buffer in the handler; flush
1474
+ // explicitly to make them durable before querying.
1475
+ await b.audit.flush();
1476
+ var txRows = await b.audit.query({ action: "system.externaldb.transaction" });
1477
+ check("transaction events audit-logged", txRows.length >= 2);
1478
+ var failRows = txRows.filter(function (r) { return r.outcome === "failure"; });
1479
+ check("rollback event recorded as failure", failRows.length === 1);
1480
+ } finally {
1481
+ try { await b.externalDb.shutdown(); } catch (_e) {}
1482
+ await teardownTestDb(tmpDir);
1483
+ }
1484
+ }
1485
+
1486
+ async function testExternalDbResidency() {
1487
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-extdbres-"));
1488
+ try {
1489
+ process.env.BLAMEJS_SKIP_NTP_CHECK = "1";
1490
+ process.env.BLAMEJS_AUDIT_SIGNING_MODE = "plaintext";
1491
+ b.vault._resetForTest();
1492
+ b.db._resetForTest();
1493
+ await b.vault.init({ dataDir: tmpDir, mode: "plaintext" });
1494
+ await b.db.init({
1495
+ dataDir: tmpDir,
1496
+ atRest: "plain",
1497
+ auditSigning: { mode: "plaintext" },
1498
+ schema: [],
1499
+ dataResidency: { region: "EU", allowedStorageRegions: ["EU"] },
1500
+ });
1501
+
1502
+ var driver = _makeFakeDriver();
1503
+ var residencyViolation = false;
1504
+ try {
1505
+ b.externalDb.init({
1506
+ backends: {
1507
+ "us-bad": {
1508
+ connect: driver.connect, query: driver.query, close: driver.close,
1509
+ classifications: ["personal"],
1510
+ residencyTag: "US", // ← violation
1511
+ },
1512
+ },
1513
+ });
1514
+ } catch (e) { residencyViolation = e.code === "RESIDENCY_VIOLATION"; }
1515
+ check("external DB residency violation refused", residencyViolation);
1516
+
1517
+ // EU-tagged backend OK
1518
+ b.externalDb._resetForTest();
1519
+ b.externalDb.init({
1520
+ backends: {
1521
+ "eu-ok": {
1522
+ connect: driver.connect, query: driver.query, close: driver.close,
1523
+ classifications: ["personal"],
1524
+ residencyTag: "EU",
1525
+ },
1526
+ },
1527
+ });
1528
+ var listed = b.externalDb.listBackends();
1529
+ check("EU backend accepted", listed.length === 1 && listed[0].residencyTag === "EU");
1530
+ } finally {
1531
+ try { await b.externalDb.shutdown(); } catch (_e) {}
1532
+ await teardownTestDb(tmpDir);
1533
+ }
1534
+ }
1535
+
1536
+ async function testExternalDbClassification() {
1537
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-extdbcls-"));
1538
+ try {
1539
+ await setupTestDb(tmpDir);
1540
+ var personalDriver = _makeFakeDriver();
1541
+ var operationalDriver = _makeFakeDriver();
1542
+ b.externalDb.init({
1543
+ backends: {
1544
+ "personal-db": {
1545
+ connect: personalDriver.connect, query: personalDriver.query, close: personalDriver.close,
1546
+ classifications: ["personal"],
1547
+ },
1548
+ "ops-db": {
1549
+ connect: operationalDriver.connect, query: operationalDriver.query, close: operationalDriver.close,
1550
+ classifications: ["operational"],
1551
+ },
1552
+ },
1553
+ });
1554
+
1555
+ await b.externalDb.query("INSERT INTO kv (id, value) VALUES ($1, $2)", ["x", "y"], { classification: "personal" });
1556
+ await b.externalDb.query("INSERT INTO kv (id, value) VALUES ($1, $2)", ["a", "b"], { classification: "operational" });
1557
+
1558
+ check("personal query routed to personal-db", personalDriver.getStats().queryCount === 1);
1559
+ check("operational query routed to ops-db", operationalDriver.getStats().queryCount === 1);
1560
+
1561
+ // Wrong-classification rejection
1562
+ var rejected = false;
1563
+ try {
1564
+ await b.externalDb.query("SELECT 1", [], { backend: "ops-db", classification: "personal" });
1565
+ } catch (e) { rejected = e.code === "CLASSIFICATION_MISMATCH"; }
1566
+ check("backend that doesn't serve classification rejected", rejected);
1567
+
1568
+ // No backend serves a missing classification
1569
+ var noBackendRejected = false;
1570
+ try { await b.externalDb.query("SELECT 1", [], { classification: "nonexistent" }); }
1571
+ catch (e) { noBackendRejected = e.code === "NO_BACKEND_FOR_CLASSIFICATION"; }
1572
+ check("missing classification rejected", noBackendRejected);
1573
+ } finally {
1574
+ try { await b.externalDb.shutdown(); } catch (_e) {}
1575
+ await teardownTestDb(tmpDir);
1576
+ }
1577
+ }
1578
+
1579
+ async function testMiddlewareRequestId() {
1580
+ await setupTestDbForMW();
1581
+ try {
1582
+ var mw = b.middleware.requestId();
1583
+ var nextCalled = false;
1584
+
1585
+ // Generates fresh ID
1586
+ var req1 = _mockReq();
1587
+ var res1 = _mockRes();
1588
+ mw(req1, res1, function () { nextCalled = true; });
1589
+ check("requestId calls next()", nextCalled);
1590
+ check("requestId sets req.requestId (32 hex chars)", typeof req1.requestId === "string" && req1.requestId.length === 32);
1591
+ check("requestId sets X-Request-Id response header", res1._captured().headers["x-request-id"] === req1.requestId);
1592
+
1593
+ // Propagates upstream value when format matches
1594
+ var req2 = _mockReq({ headers: { "x-request-id": "trace-abc-123_xyz" } });
1595
+ var res2 = _mockRes();
1596
+ mw(req2, res2, function () {});
1597
+ check("requestId propagates valid upstream id", req2.requestId === "trace-abc-123_xyz");
1598
+
1599
+ // Rejects malformed and generates fresh
1600
+ var req3 = _mockReq({ headers: { "x-request-id": "bad id with spaces!@#" } });
1601
+ var res3 = _mockRes();
1602
+ mw(req3, res3, function () {});
1603
+ check("requestId rejects malformed upstream id", req3.requestId !== "bad id with spaces!@#");
1604
+ } finally { teardownMW(); }
1605
+ }
1606
+
1607
+ async function testMiddlewareSecurityHeaders() {
1608
+ await setupTestDbForMW();
1609
+ try {
1610
+ var mw = b.middleware.securityHeaders();
1611
+ // Mark the request socket as TLS so the v0.5.3 HSTS-only-on-HTTPS
1612
+ // gate engages — operators on plain HTTP won't get HSTS, which
1613
+ // matches RFC 6797 §7.2.
1614
+ var req = _mockReq();
1615
+ req.socket = { encrypted: true };
1616
+ var res = _mockRes();
1617
+ mw(req, res, function () {});
1618
+ var h = res._captured().headers;
1619
+ check("security: HSTS set", /max-age=63072000.+includeSubDomains/.test(h["strict-transport-security"]));
1620
+ check("security: X-Content-Type-Options nosniff", h["x-content-type-options"] === "nosniff");
1621
+ check("security: X-Frame-Options DENY", h["x-frame-options"] === "DENY");
1622
+ check("security: Referrer-Policy no-referrer", h["referrer-policy"] === "no-referrer");
1623
+ check("security: Permissions-Policy disables camera", /camera=\(\)/.test(h["permissions-policy"]));
1624
+ check("security: COOP same-origin", h["cross-origin-opener-policy"] === "same-origin");
1625
+ check("security: CORP same-origin", h["cross-origin-resource-policy"] === "same-origin");
1626
+ check("security: Origin-Agent-Cluster ?1", h["origin-agent-cluster"] === "?1");
1627
+ check("security: X-DNS-Prefetch-Control off", h["x-dns-prefetch-control"] === "off");
1628
+ check("security: CSP includes default-src 'self'", /default-src 'self'/.test(h["content-security-policy"]));
1629
+ check("security: CSP no longer ships 'unsafe-inline'",
1630
+ h["content-security-policy"].indexOf("'unsafe-inline'") === -1);
1631
+ check("security: CSP keeps style-src 'self'", /style-src 'self'(?!\s+'unsafe-inline')/.test(h["content-security-policy"]));
1632
+
1633
+ // Override + disable
1634
+ var mw2 = b.middleware.securityHeaders({
1635
+ frameOptions: "SAMEORIGIN",
1636
+ originAgentCluster: false,
1637
+ dnsPrefetchControl: "on",
1638
+ csp: false,
1639
+ });
1640
+ var req2 = _mockReq();
1641
+ var res2 = _mockRes();
1642
+ mw2(req2, res2, function () {});
1643
+ var h2 = res2._captured().headers;
1644
+ check("security: frameOptions override applied", h2["x-frame-options"] === "SAMEORIGIN");
1645
+ check("security: csp disabled when false", h2["content-security-policy"] === undefined);
1646
+ check("security: Origin-Agent-Cluster disabled when false",
1647
+ h2["origin-agent-cluster"] === undefined);
1648
+ check("security: DNS-Prefetch-Control on override", h2["x-dns-prefetch-control"] === "on");
1649
+
1650
+ var threwUnknownOpt = false;
1651
+ try { b.middleware.securityHeaders({ NOT_A_REAL_OPT: true }); }
1652
+ catch (_e) { threwUnknownOpt = true; }
1653
+ check("security: rejects unknown opt", threwUnknownOpt);
1654
+ } finally { teardownMW(); }
1655
+ }
1656
+
1657
+ async function testMiddlewareErrorHandler() {
1658
+ await setupTestDbForMW();
1659
+ try {
1660
+ var mw = b.middleware.errorHandler({ exposeStackInDev: false });
1661
+
1662
+ // Simple error → 500
1663
+ var req = _mockReq({ url: "/x" });
1664
+ var res = _mockRes();
1665
+ mw(new Error("boom"), req, res, function () {});
1666
+ var captured = res._captured();
1667
+ check("errorHandler: default → 500", captured.status === 500);
1668
+ var body = JSON.parse(captured.body);
1669
+ check("errorHandler: generic message on 500", body.error.message === "Internal Server Error");
1670
+ check("errorHandler: error code present", !!body.error.code);
1671
+
1672
+ // statusCode-bearing error → that status
1673
+ var customErr = new Error("not found");
1674
+ customErr.statusCode = 404;
1675
+ customErr.code = "not_found";
1676
+ var req2 = _mockReq();
1677
+ var res2 = _mockRes();
1678
+ mw(customErr, req2, res2, function () {});
1679
+ var c2 = res2._captured();
1680
+ check("errorHandler: respects statusCode on error", c2.status === 404);
1681
+ var b2 = JSON.parse(c2.body);
1682
+ check("errorHandler: 4xx exposes message", b2.error.message === "not found");
1683
+
1684
+ // SafeJsonError → 400 + path
1685
+ var jse = new b.safeJson.SafeJsonError("validation failed", "json/validation", "$.email");
1686
+ var req3 = _mockReq();
1687
+ var res3 = _mockRes();
1688
+ mw(jse, req3, res3, function () {});
1689
+ var c3 = res3._captured();
1690
+ check("errorHandler: SafeJsonError → 400", c3.status === 400);
1691
+ var b3 = JSON.parse(c3.body);
1692
+ check("errorHandler: 400 body includes path", b3.error.path === "$.email");
1693
+
1694
+ // Drain buffered audit emissions before reading audit_log.
1695
+ await b.audit.flush();
1696
+ // Audit recorded
1697
+ var errRows = await b.audit.query({ action: "system.http.error" });
1698
+ check("errorHandler: audit-recorded errors", errRows.length === 3);
1699
+ } finally { teardownMW(); }
1700
+ }
1701
+
1702
+ async function testMiddlewareBotGuard() {
1703
+ await setupTestDbForMW();
1704
+ try {
1705
+ var mw = b.middleware.botGuard();
1706
+
1707
+ // curl UA in 'block' mode → 403
1708
+ var req = _mockReq({ headers: { "user-agent": "curl/8.0.0", "accept-language": "en", "sec-fetch-mode": "navigate" } });
1709
+ var res = _mockRes();
1710
+ var nextCalled = false;
1711
+ mw(req, res, function () { nextCalled = true; });
1712
+ check("botGuard: curl UA blocked", res._captured().status === 403 && !nextCalled);
1713
+
1714
+ // Real-browser-shaped request → pass
1715
+ var req2 = _mockReq({ headers: { "user-agent": "Mozilla/5.0", "accept-language": "en-US", "sec-fetch-mode": "navigate" } });
1716
+ var res2 = _mockRes();
1717
+ var next2 = false;
1718
+ mw(req2, res2, function () { next2 = true; });
1719
+ check("botGuard: browser request passes", next2);
1720
+
1721
+ // Tag mode marks req but doesn't block
1722
+ var mwTag = b.middleware.botGuard({ mode: "tag" });
1723
+ var req3 = _mockReq({ headers: { "user-agent": "curl/8.0.0", "accept-language": "en" } });
1724
+ var res3 = _mockRes();
1725
+ var next3 = false;
1726
+ mwTag(req3, res3, function () { next3 = true; });
1727
+ check("botGuard tag mode: passes through", next3);
1728
+ check("botGuard tag mode: req.suspectedBot set", req3.suspectedBot === "blocked-agent");
1729
+
1730
+ // Skip path
1731
+ var mwSkip = b.middleware.botGuard({ skipPaths: ["/healthz"] });
1732
+ var req4 = _mockReq({ url: "/healthz", pathname: "/healthz", headers: { "user-agent": "curl/8.0.0" } });
1733
+ var res4 = _mockRes();
1734
+ var next4 = false;
1735
+ mwSkip(req4, res4, function () { next4 = true; });
1736
+ check("botGuard: skipPaths bypassed", next4);
1737
+
1738
+ // API path is exempt from missing-Accept-Language by default (onlyForHtml)
1739
+ var req5 = _mockReq({ url: "/api/x", pathname: "/api/x", headers: { "user-agent": "Mozilla" } });
1740
+ var res5 = _mockRes();
1741
+ var next5 = false;
1742
+ mw(req5, res5, function () { next5 = true; });
1743
+ check("botGuard: onlyForHtml exempts /api/*", next5);
1744
+ } finally { teardownMW(); }
1745
+ }
1746
+
1747
+ async function testMiddlewareCors() {
1748
+ await setupTestDbForMW();
1749
+ try {
1750
+ var mw = b.middleware.cors({
1751
+ origins: ["https://app.example.com", /^https:\/\/.+\.staging\.example\.com$/],
1752
+ credentials: true,
1753
+ });
1754
+
1755
+ // Allowed origin → CORS headers set
1756
+ var req = _mockReq({ headers: { origin: "https://app.example.com" } });
1757
+ var res = _mockRes();
1758
+ var nextCalled = false;
1759
+ mw(req, res, function () { nextCalled = true; });
1760
+ check("cors: allowed origin → next called", nextCalled);
1761
+ check("cors: ACAO set", res._captured().headers["access-control-allow-origin"] === "https://app.example.com");
1762
+ check("cors: ACAC set when credentials:true", res._captured().headers["access-control-allow-credentials"] === "true");
1763
+
1764
+ // Regex origin → match
1765
+ var req2 = _mockReq({ headers: { origin: "https://feature-1.staging.example.com" } });
1766
+ var res2 = _mockRes();
1767
+ mw(req2, res2, function () {});
1768
+ check("cors: regex origin matched", res2._captured().headers["access-control-allow-origin"] === "https://feature-1.staging.example.com");
1769
+
1770
+ // Disallowed origin → 403 (refuseUnknown default)
1771
+ var req3 = _mockReq({ headers: { origin: "https://evil.example.com" } });
1772
+ var res3 = _mockRes();
1773
+ var n3 = false;
1774
+ mw(req3, res3, function () { n3 = true; });
1775
+ check("cors: unknown origin blocked", res3._captured().status === 403 && !n3);
1776
+
1777
+ // No Origin header → pass through
1778
+ var req4 = _mockReq();
1779
+ var res4 = _mockRes();
1780
+ var n4 = false;
1781
+ mw(req4, res4, function () { n4 = true; });
1782
+ check("cors: no Origin header → passes through", n4 && !res4._captured().headers["access-control-allow-origin"]);
1783
+
1784
+ // Preflight (OPTIONS + Access-Control-Request-Method) → 204 with allow-headers
1785
+ var req5 = _mockReq({ method: "OPTIONS", headers: { origin: "https://app.example.com", "access-control-request-method": "PUT" } });
1786
+ var res5 = _mockRes();
1787
+ mw(req5, res5, function () {});
1788
+ check("cors preflight: 204", res5._captured().status === 204);
1789
+ check("cors preflight: ACAM set", /PUT/.test(res5._captured().headers["access-control-allow-methods"]));
1790
+ } finally { teardownMW(); }
1791
+ }
1792
+
1793
+ async function testMiddlewareRateLimit() {
1794
+ await setupTestDbForMW();
1795
+ try {
1796
+ var mw = b.middleware.rateLimit({ burst: 3, refillPerSecond: 1 });
1797
+
1798
+ function fire() {
1799
+ var req = _mockReq();
1800
+ var res = _mockRes();
1801
+ var nextCalled = false;
1802
+ mw(req, res, function () { nextCalled = true; });
1803
+ return { passed: nextCalled, status: res._captured().status };
1804
+ }
1805
+
1806
+ // First 3 pass (burst=3)
1807
+ check("rateLimit: 1st request passes", fire().passed);
1808
+ check("rateLimit: 2nd request passes", fire().passed);
1809
+ check("rateLimit: 3rd request passes", fire().passed);
1810
+ var blocked = fire();
1811
+ check("rateLimit: 4th request blocked with 429", !blocked.passed && blocked.status === 429);
1812
+
1813
+ // Different key → independent bucket
1814
+ var mw2 = b.middleware.rateLimit({ burst: 2, refillPerSecond: 0.5, keyFn: function (req) { return req.headers["x-key"] || "default"; } });
1815
+ function fireKey(k) {
1816
+ var req = _mockReq({ headers: { "x-key": k } });
1817
+ var res = _mockRes();
1818
+ var ok = false;
1819
+ mw2(req, res, function () { ok = true; });
1820
+ return ok;
1821
+ }
1822
+ check("rateLimit: keyA 1st passes", fireKey("a"));
1823
+ check("rateLimit: keyA 2nd passes", fireKey("a"));
1824
+ check("rateLimit: keyA 3rd blocked", !fireKey("a"));
1825
+ check("rateLimit: keyB independent — 1st passes", fireKey("b"));
1826
+
1827
+ // Skip path
1828
+ var mwSkip = b.middleware.rateLimit({ burst: 1, refillPerSecond: 0.1, skipPaths: ["/healthz"] });
1829
+ function fireWithPath(p) {
1830
+ var req = _mockReq({ url: p, pathname: p });
1831
+ var res = _mockRes();
1832
+ var ok = false;
1833
+ mwSkip(req, res, function () { ok = true; });
1834
+ return ok;
1835
+ }
1836
+ check("rateLimit: 1st /healthz passes", fireWithPath("/healthz"));
1837
+ check("rateLimit: 2nd /healthz passes (skipped)", fireWithPath("/healthz"));
1838
+ check("rateLimit: 1st /api passes", fireWithPath("/api"));
1839
+ check("rateLimit: 2nd /api blocked", !fireWithPath("/api"));
1840
+ } finally { teardownMW(); }
1841
+ }
1842
+
1843
+ async function testMiddlewareCsrfProtect() {
1844
+ // End-to-end via a real http server. Token is stored in a fake
1845
+ // session under req.expectedCsrfToken so the middleware's tokenLookup
1846
+ // can return it without dragging the real session module into this
1847
+ // test fixture (which is about CSRF gating, not session lifecycle).
1848
+ await setupTestDbForMW();
1849
+ try {
1850
+ var http = require("http");
1851
+
1852
+ var EXPECTED = b.forms.generateCsrfToken();
1853
+
1854
+ function _captureBody(req) {
1855
+ return new Promise(function (resolve) {
1856
+ var chunks = [];
1857
+ req.on("data", function (c) { chunks.push(c); });
1858
+ req.on("end", function () { resolve(Buffer.concat(chunks).toString("utf8")); });
1859
+ });
1860
+ }
1861
+
1862
+ var bodyParser = b.middleware.bodyParser();
1863
+ var protect = b.middleware.csrfProtect({
1864
+ tokenLookup: function (req) { return EXPECTED; },
1865
+ });
1866
+ var server = http.createServer(async function (req, res) {
1867
+ // bodyParser runs first so urlencoded form posts populate req.body
1868
+ // for csrf-protect to read. Header path still works without it.
1869
+ await new Promise(function (resolve) {
1870
+ bodyParser(req, res, function () {
1871
+ protect(req, res, function () {
1872
+ res.writeHead(200, { "Content-Type": "text/plain", "Content-Length": 2 });
1873
+ res.end("ok");
1874
+ resolve();
1875
+ });
1876
+ });
1877
+ });
1878
+ });
1879
+ var port = await listenOnRandomPort(server);
1880
+ try {
1881
+ // 1. Safe method (GET) → middleware passes through, even with no token
1882
+ var safe = await b.httpClient.request({
1883
+ url: "http://127.0.0.1:" + port + "/protected",
1884
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1885
+ allowInternal: true,
1886
+ });
1887
+ check("csrfProtect: GET passes through", safe.statusCode === 200);
1888
+
1889
+ // 2. POST without token → 403
1890
+ var noTok = await b.httpClient.request({
1891
+ method: "POST",
1892
+ url: "http://127.0.0.1:" + port + "/protected",
1893
+ body: Buffer.from(""),
1894
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1895
+ allowInternal: true,
1896
+ errorClass: b.frameworkError.ObjectStoreError,
1897
+ }).catch(function (e) { return e; });
1898
+ check("csrfProtect: POST without token → 403", noTok.statusCode === 403);
1899
+
1900
+ // 3. POST with token in X-CSRF-Token header → 200
1901
+ var hdrOk = await b.httpClient.request({
1902
+ method: "POST",
1903
+ url: "http://127.0.0.1:" + port + "/protected",
1904
+ headers: { "x-csrf-token": EXPECTED, "Content-Type": "application/json" },
1905
+ body: Buffer.from("{}"),
1906
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1907
+ allowInternal: true,
1908
+ });
1909
+ check("csrfProtect: POST with header token → 200", hdrOk.statusCode === 200);
1910
+
1911
+ // 4. POST with token in urlencoded body → 200
1912
+ var bodyOk = await b.httpClient.request({
1913
+ method: "POST",
1914
+ url: "http://127.0.0.1:" + port + "/protected",
1915
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
1916
+ body: Buffer.from("_csrf=" + encodeURIComponent(EXPECTED) + "&name=Alice"),
1917
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1918
+ allowInternal: true,
1919
+ });
1920
+ check("csrfProtect: POST with urlencoded body token → 200", bodyOk.statusCode === 200);
1921
+
1922
+ // 5. POST with WRONG token → 403
1923
+ var wrong = await b.httpClient.request({
1924
+ method: "POST",
1925
+ url: "http://127.0.0.1:" + port + "/protected",
1926
+ headers: { "x-csrf-token": "wrong-token" },
1927
+ body: Buffer.from(""),
1928
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1929
+ allowInternal: true,
1930
+ errorClass: b.frameworkError.ObjectStoreError,
1931
+ }).catch(function (e) { return e; });
1932
+ check("csrfProtect: POST with wrong token → 403", wrong.statusCode === 403);
1933
+ } finally { server.close(); }
1934
+
1935
+ // 6. Custom methods + custom headerName
1936
+ var protectCustom = b.middleware.csrfProtect({
1937
+ tokenLookup: function () { return EXPECTED; },
1938
+ methods: ["DELETE"],
1939
+ headerName: "X-My-CSRF",
1940
+ });
1941
+ var server2 = http.createServer(async function (req, res) {
1942
+ await new Promise(function (resolve) {
1943
+ protectCustom(req, res, function () {
1944
+ res.writeHead(200, { "Content-Type": "text/plain", "Content-Length": 2 });
1945
+ res.end("ok");
1946
+ resolve();
1947
+ });
1948
+ });
1949
+ });
1950
+ var port2 = await listenOnRandomPort(server2);
1951
+ try {
1952
+ // POST is now NOT in the protected methods → passes through
1953
+ var postPass = await b.httpClient.request({
1954
+ method: "POST",
1955
+ url: "http://127.0.0.1:" + port2 + "/x",
1956
+ body: Buffer.from(""),
1957
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1958
+ allowInternal: true,
1959
+ });
1960
+ check("csrfProtect: custom methods exclude POST", postPass.statusCode === 200);
1961
+
1962
+ // DELETE without token → 403
1963
+ var del403 = await b.httpClient.request({
1964
+ method: "DELETE",
1965
+ url: "http://127.0.0.1:" + port2 + "/x",
1966
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1967
+ allowInternal: true,
1968
+ errorClass: b.frameworkError.ObjectStoreError,
1969
+ }).catch(function (e) { return e; });
1970
+ check("csrfProtect: DELETE in custom methods gated", del403.statusCode === 403);
1971
+
1972
+ // DELETE with token in custom header → 200
1973
+ var del200 = await b.httpClient.request({
1974
+ method: "DELETE",
1975
+ url: "http://127.0.0.1:" + port2 + "/x",
1976
+ headers: { "x-my-csrf": EXPECTED },
1977
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
1978
+ allowInternal: true,
1979
+ });
1980
+ check("csrfProtect: custom headerName honored", del200.statusCode === 200);
1981
+ } finally { server2.close(); }
1982
+
1983
+ // 7. tokenLookup returns null → 403 (no expected token to compare)
1984
+ var protectNullLookup = b.middleware.csrfProtect({
1985
+ tokenLookup: function () { return null; },
1986
+ });
1987
+ var server3 = http.createServer(async function (req, res) {
1988
+ await new Promise(function (resolve) {
1989
+ protectNullLookup(req, res, function () {
1990
+ res.writeHead(200); res.end("should not reach"); resolve();
1991
+ });
1992
+ });
1993
+ });
1994
+ var port3 = await listenOnRandomPort(server3);
1995
+ try {
1996
+ var nullLookup = await b.httpClient.request({
1997
+ method: "POST",
1998
+ url: "http://127.0.0.1:" + port3 + "/x",
1999
+ headers: { "x-csrf-token": EXPECTED },
2000
+ body: Buffer.from(""),
2001
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
2002
+ allowInternal: true,
2003
+ errorClass: b.frameworkError.ObjectStoreError,
2004
+ }).catch(function (e) { return e; });
2005
+ check("csrfProtect: tokenLookup null → 403", nullLookup.statusCode === 403);
2006
+ } finally { server3.close(); }
2007
+
2008
+ // 8. Validation: tokenLookup required
2009
+ var threw = null;
2010
+ try { b.middleware.csrfProtect({}); }
2011
+ catch (e) { threw = e; }
2012
+ check("csrfProtect: tokenLookup is required", threw && /tokenLookup is required/.test(threw.message));
2013
+ } finally { teardownMW(); }
2014
+ }
2015
+
2016
+ async function testMiddlewareAttachUser() {
2017
+ // attachUser populates req.user via session.verify + operator-supplied
2018
+ // userLoader. Validates token-source dispatch (cookie + Bearer header),
2019
+ // graceful failure modes (no token / invalid token / userLoader nulls /
2020
+ // userLoader throws), and that the middleware never throws or
2021
+ // short-circuits — gating is downstream's job.
2022
+ await setupTestDbForMW();
2023
+ try {
2024
+ // Create a real session; we'll exercise verify through the middleware.
2025
+ var s = await b.session.create({ userId: "u-1", data: { role: "member" } });
2026
+ var goodToken = s.token;
2027
+
2028
+ var loaderCalls = [];
2029
+ var userLoader = async function (verified) {
2030
+ loaderCalls.push(verified.userId);
2031
+ if (verified.userId === "u-1") return { _id: "u-1", email: "alice@example.com" };
2032
+ if (verified.userId === "u-suspended") return null; // user record exists but loader rejects
2033
+ if (verified.userId === "u-throws") throw new Error("DB blew up");
2034
+ return null;
2035
+ };
2036
+
2037
+ // userLoader is required
2038
+ var threw = null;
2039
+ try { b.middleware.attachUser({}); }
2040
+ catch (e) { threw = e; }
2041
+ check("attachUser: throws when userLoader missing",
2042
+ threw && /userLoader is required/.test(threw.message));
2043
+
2044
+ var mw = b.middleware.attachUser({ userLoader: userLoader });
2045
+
2046
+ // 1. No token in either source → req.user = null, next() called
2047
+ var req1 = _mockReq();
2048
+ var res1 = _mockRes();
2049
+ var n1 = false;
2050
+ await mw(req1, res1, function () { n1 = true; });
2051
+ check("attachUser: no token → next() called", n1 === true);
2052
+ check("attachUser: no token → req.user is null", req1.user === null);
2053
+ check("attachUser: no token → res not written", res1._captured().ended === false);
2054
+
2055
+ // 2. Valid cookie token → req.user populated, req.session set
2056
+ var req2 = _mockReq({ headers: { cookie: "blamejs_session=" + goodToken } });
2057
+ var res2 = _mockRes();
2058
+ var n2 = false;
2059
+ await mw(req2, res2, function () { n2 = true; });
2060
+ check("attachUser: valid cookie → next() called", n2 === true);
2061
+ check("attachUser: valid cookie → req.user set", req2.user && req2.user._id === "u-1");
2062
+ check("attachUser: valid cookie → req.session set", req2.session && req2.session.userId === "u-1");
2063
+
2064
+ // 3. Valid Bearer header → req.user populated
2065
+ var req3 = _mockReq({ headers: { authorization: "Bearer " + goodToken } });
2066
+ var res3 = _mockRes();
2067
+ await mw(req3, res3, function () {});
2068
+ check("attachUser: valid Bearer → req.user set", req3.user && req3.user._id === "u-1");
2069
+
2070
+ // 4. Cookie wins over Bearer when both present (cookie tried first)
2071
+ var anotherSession = await b.session.create({ userId: "u-1" });
2072
+ var req4 = _mockReq({ headers: {
2073
+ cookie: "blamejs_session=" + goodToken + "; foo=bar",
2074
+ authorization: "Bearer " + anotherSession.token,
2075
+ } });
2076
+ var res4 = _mockRes();
2077
+ await mw(req4, res4, function () {});
2078
+ check("attachUser: cookie precedes Bearer when both present",
2079
+ req4.user && req4.user._id === "u-1");
2080
+
2081
+ // 5. Invalid token → req.user = null
2082
+ var req5 = _mockReq({ headers: { authorization: "Bearer not-a-real-token" } });
2083
+ var res5 = _mockRes();
2084
+ var n5 = false;
2085
+ await mw(req5, res5, function () { n5 = true; });
2086
+ check("attachUser: invalid token → next() called", n5 === true);
2087
+ check("attachUser: invalid token → req.user is null", req5.user === null);
2088
+
2089
+ // 6. Valid session but userLoader returns null (deleted/suspended)
2090
+ var sSuspended = await b.session.create({ userId: "u-suspended" });
2091
+ var req6 = _mockReq({ headers: { authorization: "Bearer " + sSuspended.token } });
2092
+ var res6 = _mockRes();
2093
+ await mw(req6, res6, function () {});
2094
+ check("attachUser: userLoader returns null → req.user is null",
2095
+ req6.user === null);
2096
+
2097
+ // 7. userLoader throws → req.user = null, no propagation
2098
+ var sThrows = await b.session.create({ userId: "u-throws" });
2099
+ var req7 = _mockReq({ headers: { authorization: "Bearer " + sThrows.token } });
2100
+ var res7 = _mockRes();
2101
+ var n7 = false;
2102
+ await mw(req7, res7, function () { n7 = true; });
2103
+ check("attachUser: userLoader throw → next() still called", n7 === true);
2104
+ check("attachUser: userLoader throw → req.user is null", req7.user === null);
2105
+
2106
+ // 8. tokenFrom 'cookie' ignores Bearer
2107
+ var mwCookieOnly = b.middleware.attachUser({ userLoader: userLoader, tokenFrom: "cookie" });
2108
+ var req8 = _mockReq({ headers: { authorization: "Bearer " + goodToken } });
2109
+ await mwCookieOnly(req8, _mockRes(), function () {});
2110
+ check("attachUser: tokenFrom='cookie' ignores Bearer header",
2111
+ req8.user === null);
2112
+
2113
+ // 9. tokenFrom 'header' ignores cookie
2114
+ var mwHeaderOnly = b.middleware.attachUser({ userLoader: userLoader, tokenFrom: "header" });
2115
+ var req9 = _mockReq({ headers: { cookie: "blamejs_session=" + goodToken } });
2116
+ await mwHeaderOnly(req9, _mockRes(), function () {});
2117
+ check("attachUser: tokenFrom='header' ignores cookie",
2118
+ req9.user === null);
2119
+ } finally { teardownMW(); }
2120
+ }
2121
+
2122
+ async function testMiddlewareRequireAuth() {
2123
+ // requireAuth gates routes. With req.user populated, next() runs.
2124
+ // Without it: 401 JSON, 401 text, or 302 redirect depending on
2125
+ // request shape + opts.
2126
+ await setupTestDbForMW();
2127
+ try {
2128
+ var mw = b.middleware.requireAuth();
2129
+
2130
+ // 1. Authenticated request → next() called, no response written
2131
+ var req1 = _mockReq();
2132
+ req1.user = { _id: "u-1" };
2133
+ var res1 = _mockRes();
2134
+ var n1 = false;
2135
+ mw(req1, res1, function () { n1 = true; });
2136
+ check("requireAuth: authenticated → next() called", n1 === true);
2137
+ check("requireAuth: authenticated → res not written", res1._captured().ended === false);
2138
+
2139
+ // 2. Unauthenticated JSON-preferring request → 401 JSON
2140
+ var req2 = _mockReq({ headers: { accept: "application/json" } });
2141
+ var res2 = _mockRes();
2142
+ var n2 = false;
2143
+ mw(req2, res2, function () { n2 = true; });
2144
+ var cap2 = res2._captured();
2145
+ check("requireAuth: unauth + JSON → next() NOT called", n2 === false);
2146
+ check("requireAuth: unauth + JSON → 401 status", cap2.status === 401);
2147
+ check("requireAuth: unauth + JSON → Content-Type JSON",
2148
+ cap2.headers["content-type"].indexOf("application/json") === 0);
2149
+ var body2 = JSON.parse(cap2.body);
2150
+ check("requireAuth: unauth + JSON → error body", body2.error === "Authentication required.");
2151
+
2152
+ // 3. Unauthenticated XHR (X-Requested-With) → 401 JSON
2153
+ var req3 = _mockReq({ headers: { "x-requested-with": "XMLHttpRequest" } });
2154
+ var res3 = _mockRes();
2155
+ mw(req3, res3, function () {});
2156
+ check("requireAuth: unauth + XHR → 401 status", res3._captured().status === 401);
2157
+
2158
+ // 4. Unauthenticated browser-y request → 401 text/plain
2159
+ var req4 = _mockReq({ headers: { accept: "text/html" } });
2160
+ var res4 = _mockRes();
2161
+ mw(req4, res4, function () {});
2162
+ var cap4 = res4._captured();
2163
+ check("requireAuth: unauth browser → 401 status", cap4.status === 401);
2164
+ check("requireAuth: unauth browser → text/plain",
2165
+ cap4.headers["content-type"].indexOf("text/plain") === 0);
2166
+
2167
+ // 4b. Content-Type: application/json on the REQUEST body is NOT
2168
+ // a signal — it describes what the client SENT, not what they
2169
+ // want back. Server-to-server POST with no Accept header lands
2170
+ // on the default text/plain branch (or the redirect branch when
2171
+ // opts.redirectTo is set).
2172
+ var req4c = _mockReq({ headers: { "content-type": "application/json" } });
2173
+ var res4c = _mockRes();
2174
+ mw(req4c, res4c, function () {});
2175
+ var cap4c = res4c._captured();
2176
+ check("requireAuth: req Content-Type JSON alone → text/plain (not JSON)",
2177
+ cap4c.status === 401 &&
2178
+ cap4c.headers["content-type"].indexOf("text/plain") === 0);
2179
+
2180
+ // 5. Unauthenticated browser-y request WITH redirectTo → 302
2181
+ var mwRedirect = b.middleware.requireAuth({ redirectTo: "/auth/login" });
2182
+ var req5 = _mockReq({ headers: { accept: "text/html" } });
2183
+ var res5 = _mockRes();
2184
+ mwRedirect(req5, res5, function () {});
2185
+ var cap5 = res5._captured();
2186
+ check("requireAuth: unauth + redirectTo → 302 status", cap5.status === 302);
2187
+ check("requireAuth: unauth + redirectTo → Location set",
2188
+ cap5.headers.location === "/auth/login");
2189
+
2190
+ // 6. JSON-preferring still gets 401 JSON even with redirectTo set
2191
+ var req6 = _mockReq({ headers: { accept: "application/json" } });
2192
+ var res6 = _mockRes();
2193
+ mwRedirect(req6, res6, function () {});
2194
+ check("requireAuth: JSON-prefer + redirectTo → 401 (not redirect)",
2195
+ res6._captured().status === 401);
2196
+
2197
+ // 7. Custom errorMessage propagates
2198
+ var mwCustom = b.middleware.requireAuth({ errorMessage: "Sign in to continue." });
2199
+ var req7 = _mockReq({ headers: { accept: "application/json" } });
2200
+ var res7 = _mockRes();
2201
+ mwCustom(req7, res7, function () {});
2202
+ check("requireAuth: custom errorMessage propagates",
2203
+ JSON.parse(res7._captured().body).error === "Sign in to continue.");
2204
+
2205
+ // 8. Custom prefersJson override
2206
+ var mwForce = b.middleware.requireAuth({ prefersJson: function () { return false; } });
2207
+ var req8 = _mockReq({ headers: { accept: "application/json" } }); // would normally be JSON
2208
+ var res8 = _mockRes();
2209
+ mwForce(req8, res8, function () {});
2210
+ check("requireAuth: prefersJson override forces text/plain",
2211
+ res8._captured().headers["content-type"].indexOf("text/plain") === 0);
2212
+ } finally { teardownMW(); }
2213
+ }
2214
+
2215
+ function testEnvLoadDiffAndAudit() {
2216
+ // Use real file I/O via atomicFile — exercises load() end-to-end.
2217
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-env-"));
2218
+ try {
2219
+ var envPath = path.join(tmpDir, ".env");
2220
+ var snapPath = path.join(tmpDir, "env.snapshot.json");
2221
+
2222
+ fs.writeFileSync(envPath, "DATABASE_URL=postgres://A\nFEATURE_FOO=true\n");
2223
+ var res1 = b.parsers.env.load(envPath, {
2224
+ snapshotPath: snapPath,
2225
+ audit: false, // no framework db wired in this test fixture
2226
+ });
2227
+ check("env.load returns values", res1.values.DATABASE_URL === "postgres://A");
2228
+ check("env.load first call: 2 added", res1.diff.added.length === 2);
2229
+ check("env.load first call: nothing removed", res1.diff.removed.length === 0);
2230
+ check("env.load first call: nothing changed", res1.diff.changed.length === 0);
2231
+
2232
+ // Now change one and add another
2233
+ fs.writeFileSync(envPath, "DATABASE_URL=postgres://B\nFEATURE_FOO=true\nNEW_KEY=hello\n");
2234
+ var res2 = b.parsers.env.load(envPath, { snapshotPath: snapPath, audit: false });
2235
+ check("env.load second call: 1 added", res2.diff.added.length === 1 && res2.diff.added[0] === "NEW_KEY");
2236
+ check("env.load second call: nothing removed", res2.diff.removed.length === 0);
2237
+ check("env.load second call: 1 changed", res2.diff.changed.length === 1);
2238
+ check("env.load second call: changed key", res2.diff.changed[0].key === "DATABASE_URL");
2239
+
2240
+ // Now remove one
2241
+ fs.writeFileSync(envPath, "DATABASE_URL=postgres://B\nNEW_KEY=hello\n");
2242
+ var res3 = b.parsers.env.load(envPath, { snapshotPath: snapPath, audit: false });
2243
+ check("env.load third call: 1 removed", res3.diff.removed.length === 1 && res3.diff.removed[0] === "FEATURE_FOO");
2244
+ } finally {
2245
+ fs.rmSync(tmpDir, { recursive: true, force: true });
2246
+ }
2247
+ }
2248
+
2249
+ function testEnvLoadSchemaAndTypos() {
2250
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-env-"));
2251
+ try {
2252
+ var envPath = path.join(tmpDir, ".env");
2253
+ fs.writeFileSync(envPath,
2254
+ "DATABSE_URL=oops\n" + // typo of DATABASE_URL
2255
+ "feature_flag=true\n"); // case mismatch — wait, this is rejected by keyShape
2256
+ // Actually case-mismatch must use keys that pass shape. Use uppercase
2257
+ // mismatch instead — rewrite.
2258
+ fs.writeFileSync(envPath,
2259
+ "DATABSE_URL=oops\n" + // typo (missing 'A')
2260
+ "FEATURE_FLAG=true\n" + // exact match for registered
2261
+ "TOTALLY_UNKNOWN=other\n");
2262
+ var expected = {
2263
+ DATABASE_URL: { type: "string", sensitivity: "breaking" },
2264
+ FEATURE_FLAG: { type: "boolean", sensitivity: "runtime" },
2265
+ };
2266
+ var res = b.parsers.env.load(envPath, {
2267
+ expected: expected,
2268
+ audit: false,
2269
+ });
2270
+ check("env: schema coerces type when registered", res.values.FEATURE_FLAG === true);
2271
+
2272
+ // Find the typo entry in suspicious
2273
+ var typo = res.diff.suspicious.find(function (s) { return s.key === "DATABSE_URL"; });
2274
+ check("env: typo flagged as suspicious", typo && typo.suggestion === "DATABASE_URL");
2275
+ check("env: typo reason is single-char-typo", typo && typo.reason === "single-char-typo");
2276
+
2277
+ var unknown = res.diff.suspicious.find(function (s) { return s.key === "TOTALLY_UNKNOWN"; });
2278
+ check("env: unrelated unknown flagged", unknown && unknown.reason === "unknown");
2279
+
2280
+ // rejectUnknown mode refuses
2281
+ var threwRejectUnknown = false;
2282
+ try { b.parsers.env.load(envPath, { expected: expected, audit: false, rejectUnknown: true }); }
2283
+ catch (e) { threwRejectUnknown = e.code === "env/unknown-keys"; }
2284
+ check("env: rejectUnknown surfaces error", threwRejectUnknown);
2285
+
2286
+ // Required key missing
2287
+ fs.writeFileSync(envPath, "FEATURE_FLAG=true\n");
2288
+ var threwRequired = false;
2289
+ try {
2290
+ b.parsers.env.load(envPath, {
2291
+ expected: { DATABASE_URL: { type: "string", required: true } },
2292
+ audit: false,
2293
+ });
2294
+ } catch (e) { threwRequired = e.code === "env/missing-required"; }
2295
+ check("env: missing required key rejected", threwRequired);
2296
+
2297
+ // Bad type coercion
2298
+ fs.writeFileSync(envPath, "FEATURE_FLAG=yes\n");
2299
+ var threwBadBool = false;
2300
+ try {
2301
+ b.parsers.env.load(envPath, {
2302
+ expected: { FEATURE_FLAG: { type: "boolean" } },
2303
+ audit: false,
2304
+ });
2305
+ } catch (e) { threwBadBool = e.code === "env/bad-type"; }
2306
+ check("env: 'yes' for boolean rejected (no Norway)", threwBadBool);
2307
+ } finally {
2308
+ fs.rmSync(tmpDir, { recursive: true, force: true });
2309
+ }
2310
+ }
2311
+
2312
+ function testEnvLoadBreakingChange() {
2313
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-env-"));
2314
+ try {
2315
+ var envPath = path.join(tmpDir, ".env");
2316
+ var snapPath = path.join(tmpDir, "env.snapshot.json");
2317
+ var expected = {
2318
+ DATABASE_URL: { type: "string", sensitivity: "breaking" },
2319
+ };
2320
+
2321
+ fs.writeFileSync(envPath, "DATABASE_URL=postgres://A\n");
2322
+ b.parsers.env.load(envPath, { expected: expected, snapshotPath: snapPath, audit: false });
2323
+
2324
+ // Try to change without acknowledgement
2325
+ fs.writeFileSync(envPath, "DATABASE_URL=postgres://B\n");
2326
+ var threwBreaking = false;
2327
+ try {
2328
+ b.parsers.env.load(envPath, { expected: expected, snapshotPath: snapPath, audit: false });
2329
+ } catch (e) { threwBreaking = e.code === "env/breaking-change"; }
2330
+ check("env: breaking-sensitivity change refused", threwBreaking);
2331
+
2332
+ // With explicit allow, succeeds
2333
+ var ok = b.parsers.env.load(envPath, {
2334
+ expected: expected,
2335
+ snapshotPath: snapPath,
2336
+ audit: false,
2337
+ allow: ["DATABASE_URL"],
2338
+ });
2339
+ check("env: { allow: [...] } authorises breaking change",
2340
+ ok.values.DATABASE_URL === "postgres://B");
2341
+ } finally {
2342
+ fs.rmSync(tmpDir, { recursive: true, force: true });
2343
+ }
2344
+ }
2345
+
2346
+ // ---- run() ----
2347
+
2348
+ async function run() {
2349
+ // session
2350
+ await testSession();
2351
+
2352
+ // data residency (db + storage)
2353
+ await testDataResidency();
2354
+
2355
+ // storage + object-store
2356
+ await testStorage();
2357
+ await testMultiBackend();
2358
+ await testClassificationRouting();
2359
+ await testResidencyEnforcement();
2360
+ await testRetryAndBreaker();
2361
+ testSigv4Primitives();
2362
+ await testSigv4MockServer();
2363
+ testGcsPrimitives();
2364
+ await testGcsMockServer();
2365
+ testAzureBlobPrimitives();
2366
+ await testAzureBlobMockServer();
2367
+
2368
+ // queue
2369
+ await testQueueLocal();
2370
+ await testQueueConsume();
2371
+ await testQueueRetryAndFail();
2372
+ await testQueueLeaseExpiry();
2373
+ await testQueueShutdown();
2374
+ testJobsSurface();
2375
+ await testJobsDefineAndEnqueue();
2376
+ await testJobsValidation();
2377
+ await testJobsMultipleHandlers();
2378
+
2379
+ // log-stream
2380
+ await testLogStreamLocal();
2381
+ await testLogStreamWebhook();
2382
+ await testLogStreamBidirectional();
2383
+
2384
+ // external-db
2385
+ await testExternalDbBasic();
2386
+ await testExternalDbPool();
2387
+ await testExternalDbTransaction();
2388
+ await testExternalDbResidency();
2389
+ await testExternalDbClassification();
2390
+
2391
+ // middleware
2392
+ await testMiddlewareRequestId();
2393
+ await testMiddlewareSecurityHeaders();
2394
+ await testMiddlewareErrorHandler();
2395
+ await testMiddlewareBotGuard();
2396
+ await testMiddlewareCors();
2397
+ await testMiddlewareRateLimit();
2398
+ await testMiddlewareAttachUser();
2399
+ await testMiddlewareRequireAuth();
2400
+ await testMiddlewareCsrfProtect();
2401
+
2402
+ // env-safe.load() — full lifecycle (depends on audit chain)
2403
+ await testEnvLoadDiffAndAudit();
2404
+ await testEnvLoadSchemaAndTypos();
2405
+ await testEnvLoadBreakingChange();
2406
+ }
2407
+
2408
+ module.exports = {
2409
+ name: "Layer 4 — consumers (session, storage, queue, log-stream, external-db, middleware, env-load)",
2410
+ run: run,
2411
+ testSession: testSession,
2412
+ testMiddlewareAttachUser: testMiddlewareAttachUser,
2413
+ testMiddlewareRequireAuth: testMiddlewareRequireAuth,
2414
+ testMiddlewareCsrfProtect: testMiddlewareCsrfProtect,
2415
+ testDataResidency: testDataResidency,
2416
+ testStorage: testStorage,
2417
+ testMultiBackend: testMultiBackend,
2418
+ testClassificationRouting: testClassificationRouting,
2419
+ testResidencyEnforcement: testResidencyEnforcement,
2420
+ testRetryAndBreaker: testRetryAndBreaker,
2421
+ testSigv4Primitives: testSigv4Primitives,
2422
+ testSigv4MockServer: testSigv4MockServer,
2423
+ testGcsPrimitives: testGcsPrimitives,
2424
+ testGcsMockServer: testGcsMockServer,
2425
+ testAzureBlobPrimitives: testAzureBlobPrimitives,
2426
+ testAzureBlobMockServer: testAzureBlobMockServer,
2427
+ testQueueLocal: testQueueLocal,
2428
+ testQueueConsume: testQueueConsume,
2429
+ testQueueRetryAndFail: testQueueRetryAndFail,
2430
+ testQueueLeaseExpiry: testQueueLeaseExpiry,
2431
+ testQueueShutdown: testQueueShutdown,
2432
+ testJobsSurface: testJobsSurface,
2433
+ testJobsDefineAndEnqueue: testJobsDefineAndEnqueue,
2434
+ testJobsValidation: testJobsValidation,
2435
+ testJobsMultipleHandlers: testJobsMultipleHandlers,
2436
+ testLogStreamLocal: testLogStreamLocal,
2437
+ testLogStreamWebhook: testLogStreamWebhook,
2438
+ testLogStreamBidirectional: testLogStreamBidirectional,
2439
+ testExternalDbBasic: testExternalDbBasic,
2440
+ testExternalDbPool: testExternalDbPool,
2441
+ testExternalDbTransaction: testExternalDbTransaction,
2442
+ testExternalDbResidency: testExternalDbResidency,
2443
+ testExternalDbClassification: testExternalDbClassification,
2444
+ testMiddlewareRequestId: testMiddlewareRequestId,
2445
+ testMiddlewareSecurityHeaders: testMiddlewareSecurityHeaders,
2446
+ testMiddlewareErrorHandler: testMiddlewareErrorHandler,
2447
+ testMiddlewareBotGuard: testMiddlewareBotGuard,
2448
+ testMiddlewareCors: testMiddlewareCors,
2449
+ testMiddlewareRateLimit: testMiddlewareRateLimit,
2450
+ testEnvLoadDiffAndAudit: testEnvLoadDiffAndAudit,
2451
+ testEnvLoadSchemaAndTypos: testEnvLoadSchemaAndTypos,
2452
+ testEnvLoadBreakingChange: testEnvLoadBreakingChange,
2453
+ };