@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,1947 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-consolidated-schema.json",
3
+ "minor": "0.6",
4
+ "releases": [
5
+ {
6
+ "version": "0.6.70",
7
+ "date": "2026-05-03",
8
+ "headline": "`numeric-bounds` extended to three more call sites the prior sweep missed",
9
+ "sections": [
10
+ {
11
+ "heading": "Fixed",
12
+ "items": [
13
+ {
14
+ "title": "`lib/middleware/csp-nonce.js` `nonceBytes`",
15
+ "body": "Pre-fix the `typeof === \"number\"` check accepted `Infinity` and `NaN` (both bypass `< MIN_NONCE_BYTES` because every comparison with `NaN` or `Infinity` is false), then crashed per-request inside `crypto.generateBytes(Infinity)` with `ERR_OUT_OF_RANGE`. The DoS-shape: an operator typo at boot took down every CSP-protected route at request time. Now rejects at `create()` with `csp-nonce/bad-nonce-bytes`."
16
+ },
17
+ {
18
+ "title": "`lib/migrations.js` and `lib/external-db-migrate.js` `staleAfterMs`",
19
+ "body": "Both used the `> 0` guard which silently accepted `Infinity`. `(Date.now() - lockedAt) > Infinity` is always false, so `staleAfterMs: Infinity` was identical to the `0` default (never replace) but obscured the typo. Operators wanting `never expire` now pass `0` explicitly; everything else (`Infinity` / `NaN` / fractional / negative / non-number) rejects with a clear message."
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ },
25
+ {
26
+ "version": "0.6.69",
27
+ "date": "2026-05-03",
28
+ "headline": "`lib/numeric-bounds.js` applied across every numeric-opt site that previously accepted `Infinity` / `NaN`",
29
+ "sections": [
30
+ {
31
+ "heading": "Fixed",
32
+ "items": [
33
+ {
34
+ "title": "Shared numeric-bounds validator applied across consumers",
35
+ "body": "The recurring pattern `typeof opts.X === \"number\" && opts.X > 0` was vulnerable everywhere it shipped: `Infinity > Infinity` is false, `byteLength > NaN` is false, `Number.isFinite()` was missing. Operators with env-var coercions (`Number(process.env.MAX_X || \"\")` produces `NaN` for missing values, `Infinity` for typo'd ones) silently lost their cap. New `lib/numeric-bounds.js` exposes `isPositiveFiniteInt(value)` and `shape(value)` (the latter formats `\"number Infinity\"` / `\"number NaN\"` / `\"string \\\"100\\\"\"` so the actual coercion is visible — `JSON.stringify` collapses Infinity/NaN to `\"null\"` and hides the typo)."
36
+ },
37
+ {
38
+ "title": "Sites swept",
39
+ "body": "`lib/safe-buffer.js` (`boundedChunkCollector`, `toBuffer`, `normalizeText`), `lib/atomic-file.js` (refactored from the previous release's inline check), `lib/csv.js` (parse `maxBytes` was operator-overridable to `Infinity` -> multi-megabyte CSV bodies through unbounded), `lib/safe-url.js` (`maxUrlLength` opt was the v0.6.62 escape hatch — now also bounded), `lib/mail-bounce.js` (`maxBytes` for inbound webhook body — DoS-shape on bounce intake)."
40
+ }
41
+ ]
42
+ }
43
+ ]
44
+ },
45
+ {
46
+ "version": "0.6.68",
47
+ "date": "2026-05-03",
48
+ "headline": "`b.atomicFile.read` / `readSync` enforce strict `maxBytes` validation",
49
+ "sections": [
50
+ {
51
+ "heading": "Fixed",
52
+ "items": [
53
+ {
54
+ "title": "Reject `Infinity` / `NaN` `maxBytes` before the size check",
55
+ "body": "The previous size check was `if (stat.size > opts.maxBytes)`, which silently accepted `Infinity` (`stat.size > Infinity` is always false -> reads any file regardless of size, defeating the OOM cap). Operators with `Number(env.MAX_READ_BYTES || \"\")` coercion bugs got `NaN` on missing values and unbounded reads on Infinity-typo'd values. New `_validateMaxBytes` runs before the size check and rejects `Infinity` / `NaN` / non-integer / negative / zero / non-number with `atomic-file/bad-opt`. Real-world consumers (`vault.initPlaintext`, `audit-sign`, `db.loadOrCreateDbKey`, etc.) all pass real positive integers via `C.BYTES.*` helpers and are unaffected."
56
+ }
57
+ ]
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "version": "0.6.67",
63
+ "date": "2026-05-03",
64
+ "headline": "Canonical-JSON walker extracted to `lib/canonical-json.js` and applied across audit / drift / pagination",
65
+ "sections": [
66
+ {
67
+ "heading": "Changed",
68
+ "items": [
69
+ {
70
+ "title": "Unified canonical-JSON serializer",
71
+ "body": "`audit-tools._canonicalize` (used for backup-bundle JSONL serialisation, requires byte-equivalence with audit-chain) and `config-drift._stableStringify` (used to hash framework config for post-boot tamper detection) carried the same silent-data-loss walk as the audit-chain bug just fixed. New `lib/canonical-json.js` exposes `stringify(value, opts?)` with `opts.bufferAs = \"hex\" | \"reject\"` (default `hex` for crypto / config / audit, `reject` for pagination's strict-cursor policy). All four call sites — audit-chain, audit-tools, config-drift, pagination — now route through it; the four near-identical inline walkers collapse to one. Existing audit rows and pre-existing backup bundles round-trip correctly because byte output for plain types is unchanged."
72
+ }
73
+ ]
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "version": "0.6.66",
79
+ "date": "2026-05-03",
80
+ "headline": "`b.auditChain.canonicalize` deep-walks values and rejects non-plain types",
81
+ "sections": [
82
+ {
83
+ "heading": "Fixed",
84
+ "items": [
85
+ {
86
+ "title": "Canonical-JSON walker hardened",
87
+ "body": "The pre-fix walker did `Object.keys(row).map(...)` and `JSON.stringify`'d whatever fell through, which silently encoded `Map` / `Set` / `RegExp` as `{}`, `Symbol` / function as missing keys, `BigInt` as a thrown `Do not know how to serialize` mid-emit (DoS-shape on any operator routing bigint IDs into audit metadata), and circular references as the unwrapped `JSON.stringify` error message. The post-fix walker maps `BigInt -> decimal string`, `Date -> ISO string`, rejects `Map` / `Set` / `RegExp` / `Symbol` / function with a clear constructor-name message, and detects circular references via `WeakSet`. Recursive so nested structures like `{ a: [BigInt(1), BigInt(2)] }` and `{ a: { b: Uint8Array(...) } }` all serialise correctly. Stored-row compatibility is preserved because existing audit rows verify identically — their stored `metadata` columns are already JSON strings."
88
+ }
89
+ ]
90
+ }
91
+ ]
92
+ },
93
+ {
94
+ "version": "0.6.65",
95
+ "date": "2026-05-03",
96
+ "headline": "`b.scheduler.parseCron` rejects step values exceeding the field's range",
97
+ "sections": [
98
+ {
99
+ "heading": "Fixed",
100
+ "items": [
101
+ {
102
+ "title": "Out-of-range cron step rejected",
103
+ "body": "Previously `*/99999 * * * *` was silently accepted and degenerated to `minute 0 of every hour` (because the for-loop adding values stopped at the first iteration when `step > range`); an operator typing the typo got a once-per-hour schedule when they probably meant once per N minutes. `_parseCronField` now rejects with `scheduler/invalid-cron` when `step > (range.max - range.min + 1)`. The bound is inclusive so `*/60 * * * *` (= minute 0 of every hour written with a redundant explicit step) still accepts."
104
+ }
105
+ ]
106
+ }
107
+ ]
108
+ },
109
+ {
110
+ "version": "0.6.64",
111
+ "date": "2026-05-03",
112
+ "headline": "`b.credentialHash.verify` enforces the same 16-byte minimum payload as `hash`",
113
+ "sections": [
114
+ {
115
+ "heading": "Fixed",
116
+ "items": [
117
+ {
118
+ "title": "Symmetric minimum-length on verify",
119
+ "body": "Previously `hash()` refused to create a hash shorter than 16 bytes but `verify()` silently accepted any payload length, including 1-byte payloads where the collision space is 256 — a hand-crafted envelope `{ magic, algoId, SHAKE256(targetPassword, 1)[0] }` would verify against the target password in microseconds. A storage bug or attacker tampering that truncated the stored envelope produced a verifiable but catastrophically weak hash; an attacker with DB write access who couldn't replace the hash outright could truncate it to a nearly-cleartext-equivalent value. Both ends now refuse short payloads symmetrically via the new `SHAKE256_MIN_LENGTH = 16` constant; verify returns false (with `payload-too-short` observability label) when the envelope's payload is under 16 bytes."
120
+ }
121
+ ]
122
+ }
123
+ ]
124
+ },
125
+ {
126
+ "version": "0.6.63",
127
+ "date": "2026-05-03",
128
+ "headline": "`b.parsers.toml.parse` enforces `maxDepth` on dotted-key paths",
129
+ "sections": [
130
+ {
131
+ "heading": "Fixed",
132
+ "items": [
133
+ {
134
+ "title": "Dotted-key path depth cap",
135
+ "body": "Previously the parser walked arbitrarily deep table headers (`[a.b.c.d.e...]`) without applying the existing `maxDepth` (which only ran inside `_parseValue` for inline tables and arrays); a 10,000-segment path built a tree deep enough to stack-overflow the recursive `_normalize` walker after parse. An attacker submitting a malicious TOML config to `b.config` would crash the framework at boot or whenever the file was reloaded. `_parseDottedKey` now rejects a path with more than `maxDepth` segments via the same `toml/too-deep` error code already used for value-side depth."
136
+ }
137
+ ]
138
+ }
139
+ ]
140
+ },
141
+ {
142
+ "version": "0.6.62",
143
+ "date": "2026-05-03",
144
+ "headline": "URL-length DoS-shape gap closed in `safeSchema().url()` and `safeUrl.parse`",
145
+ "summary": "Both surfaces previously accepted arbitrarily long URL strings before validation; an 8 KB cap referencing RFC 7230 §3.1.1 now applies before downstream processing.",
146
+ "sections": [
147
+ {
148
+ "heading": "Fixed",
149
+ "items": [
150
+ {
151
+ "title": "`b.safeSchema.string().url()` length cap",
152
+ "body": "Was regex-only with no length cap, accepting arbitrarily long matching strings — same DoS class as the previous release's `.email()` gap. An operator chaining `.url()` on a request body would feed multi-megabyte URLs into downstream HTTP clients, SSRF gates, and log lines. Now rejects with `string/url-too-long` at 8193+ characters."
153
+ },
154
+ {
155
+ "title": "`b.safeUrl.parse` length cap",
156
+ "body": "Same gap at the framework's primary URL-validation surface (used by httpClient, ssrfGuard, and every operator-supplied URL). The 8 KB cap now applies BEFORE handing the string to Node's `new URL()` parser, so operator-supplied URLs feeding `b.httpClient.request({ url })` from request bodies and webhook configs are bounded. Operators with legitimate non-standard use override via `opts.maxUrlLength`."
157
+ }
158
+ ]
159
+ }
160
+ ],
161
+ "references": [
162
+ {
163
+ "label": "RFC 7230 §3.1.1 — HTTP/1.1 Message Syntax",
164
+ "url": "https://www.rfc-editor.org/rfc/rfc7230.html"
165
+ }
166
+ ]
167
+ },
168
+ {
169
+ "version": "0.6.61",
170
+ "date": "2026-05-03",
171
+ "headline": "`b.safeSchema.string().email()` enforces RFC 5321 §4.5.3.1.3's 254-character cap",
172
+ "summary": "The previous regex-only validator accepted arbitrarily long matching strings — a 50 KB \"email\" passed validation and flowed into downstream DB writes / log lines unbounded. The 254-character cap now refuses oversized addresses before the regex runs.",
173
+ "sections": [
174
+ {
175
+ "heading": "Fixed",
176
+ "items": [
177
+ {
178
+ "title": "Email length cap closes a DoS-shape gap in operator request validation",
179
+ "body": "Pre-fix the validator was the regex-only `/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/`, which accepts arbitrarily long matching strings — an operator chaining `.email()` on a request body was open to a DoS shape (50 KB email passes validation, downstream DB writes / log lines unbounded). The validator now rejects with `string/email-too-long` at 255+ chars before the regex even runs, with a message naming the RFC. Operators with a legitimate non-RFC reason for longer addresses skip `.email()` and chain `.regex(custom)` directly."
180
+ }
181
+ ]
182
+ }
183
+ ],
184
+ "references": [
185
+ {
186
+ "label": "RFC 5321 §4.5.3.1.3 — Path length limits",
187
+ "url": "https://www.rfc-editor.org/rfc/rfc5321#section-4.5.3.1.3"
188
+ }
189
+ ]
190
+ },
191
+ {
192
+ "version": "0.6.60",
193
+ "date": "2026-05-03",
194
+ "headline": "`b.pagination.encodeCursor` rejects non-plain types instead of silently losing data",
195
+ "summary": "The cursor `_canonicalize` walker silently encoded `Date` as `{}`, `Buffer`/`Uint8Array` as `{\"0\":97,…}`, and stack-overflowed on circular references. After encode → decode the operator's data was either gone or unrecognisable. The walker now preserves `Date` as ISO string and refuses the other classes with a clear `pagination/bad-state` error.",
196
+ "sections": [
197
+ {
198
+ "heading": "Fixed",
199
+ "items": [
200
+ {
201
+ "title": "Date round-trips as ISO string; Buffer / Map / Set / RegExp / circular reject cleanly",
202
+ "body": "Pre-fix the `_canonicalize` walker did `if (typeof === \"object\") Object.keys(...)`, which silently lost data on three classes of input: `Date` silently encoded as `{}` (Date instances have no own enumerable keys); `Buffer` / `Uint8Array` silently encoded as `{\"0\":97,\"1\":98,…}` (indexed-key serialisation); circular references stack-overflowed instead of throwing a clean error. After encode → decode the operator's data was either gone or unrecognisable. The fix: `Date` now serialises to its ISO string (matches stdlib `JSON.stringify` semantics — round-trips through encode/decode as the ISO string operators expect); `Buffer` / `Uint8Array` / `Map` / `Set` / `RegExp` throw `pagination/bad-state` with a message naming the offending constructor and pointing operators at the right conversion (`\"convert to a plain primitive (string / number / iso-string) first\"`); circular references throw `pagination/bad-state` cleanly via WeakSet cycle detection."
203
+ }
204
+ ]
205
+ }
206
+ ]
207
+ },
208
+ {
209
+ "version": "0.6.59",
210
+ "date": "2026-05-03",
211
+ "headline": "HTTP/2 session teardown extracted to `lib/http2-teardown.js` + applied across http-client",
212
+ "summary": "The v0.6.58 inline `session.close()` + `session.destroy()` block was the right fix for the OTLP-gRPC sink hang, but the same bug class lived in `lib/http-client.js`'s h2 transport pool. A new shared helper consolidates the teardown routine across both consumers.",
213
+ "sections": [
214
+ {
215
+ "heading": "Fixed",
216
+ "items": [
217
+ {
218
+ "title": "`lib/http2-teardown.js` consolidates the close()-then-destroy() routine",
219
+ "body": "The h2 transport pool in `lib/http-client.js` had five call sites running the bare `session.close()` (`_resetTransports`, the ALPN-fallback path, the h2 connect-error path, the h2c connect-error path, the idle-timeout handler, `_resetForTest`) all of which leak the underlying TCP socket on idle / error / fallback paths in exactly the same way as the v0.6.58 OTLP-gRPC sink. New `lib/http2-teardown.js` exports `tearDownH2Session(session)` which performs the close()-then-destroy() routine; `lib/http-client.js` and `lib/log-stream-otlp-grpc.js` both import it. The v0.6.58 inline block in the OTLP-gRPC sink is removed in favour of the shared helper."
220
+ }
221
+ ]
222
+ }
223
+ ]
224
+ },
225
+ {
226
+ "version": "0.6.58",
227
+ "date": "2026-05-03",
228
+ "headline": "`b.logStream` OTLP-gRPC sink no longer leaks its TCP socket on close",
229
+ "summary": "The sink's `close()` was calling HTTP/2 `session.close()` (graceful) but never `session.destroy()`, leaving the underlying TCP socket connected — which blocked `server.close()` indefinitely on Linux CI runners and silently broke the npm-publish gate from v0.6.38 through v0.6.57.",
230
+ "sections": [
231
+ {
232
+ "heading": "Fixed",
233
+ "items": [
234
+ {
235
+ "title": "OTLP-gRPC sink `close()` follows graceful close with `session.destroy()`",
236
+ "body": "Pre-fix the sink's `close()` was calling `session.close()` (HTTP/2 graceful close — waits for in-flight streams before freeing the socket) but never `session.destroy()`. The graceful close completed but the underlying TCP socket stayed connected, blocking the test fixture's `server.close()` indefinitely on Linux CI runners. Same bug also added ~120 seconds of lingering latency to every local smoke run on Windows (smoke 196s → 76s after fix). The fix calls `session.close()` then `session.destroy()`; by the time we reach close(), all buffered records have been flushed via the awaited `inflightPromise` + final `_doExport`, so destroy() is structurally safe."
237
+ },
238
+ {
239
+ "title": "Unblocks npm-publish stuck since v0.6.37",
240
+ "body": "The npm registry had been stuck at v0.6.37 since 2026-05-02; every tag from v0.6.38 through v0.6.57 timed out at the publish workflow's smoke step because of the lingering HTTP/2 socket. With this fix the publish reaches `npm publish`."
241
+ }
242
+ ]
243
+ }
244
+ ]
245
+ },
246
+ {
247
+ "version": "0.6.57",
248
+ "date": "2026-05-03",
249
+ "headline": "`b.safeBuffer.boundedChunkCollector` enforces positive-finite-integer `maxBytes`",
250
+ "summary": "The OOM-cap validator previously accepted `Infinity` (defeating its purpose) and fractional floats like `3.5` (confusing downstream arithmetic). It now requires a positive finite integer and throws `buffer/bad-arg` at boot on anything else, catching operator typos and broken env-var coercions.",
251
+ "sections": [
252
+ {
253
+ "heading": "Fixed",
254
+ "items": [
255
+ {
256
+ "title": "`maxBytes` validator no longer silently accepts `Infinity` / `NaN` / fractional floats",
257
+ "body": "Pre-fix the validator was `typeof opts.maxBytes === \"number\" && opts.maxBytes > 0` which silently accepted `Infinity` (defeating the OOM-cap purpose entirely — a hostile 10-GB upstream would accumulate fully) and non-integer floats like `3.5` (which set a fractional cap that confused downstream `total + chunk.length > maxBytes` arithmetic). The validator now requires positive finite integer; everything else throws `buffer/bad-arg` at boot with the offending value in the message. Real-world consumers (`b.httpClient` request cap, `b.atomicFile.read`, `b.parsers.*`, multipart body parser) are unaffected because they pass real positive integers via `C.BYTES.*` helpers; the fix catches operator typos / misconfigured env-var coercions where `Number(env.MAX_BYTES)` produces NaN or Infinity."
258
+ }
259
+ ]
260
+ }
261
+ ]
262
+ },
263
+ {
264
+ "version": "0.6.56",
265
+ "date": "2026-05-03",
266
+ "headline": "`b.auth.totp.verify` strips whitespace + separators from pasted codes",
267
+ "summary": "TOTP verification now normalises common paste / authenticator-UI artefacts (whitespace, `-`, `.`, `_`) before the timing-safe comparison, so codes like `\"123 456\"` or `\"123-456\"` from Google Authenticator, Authy, Duo, and 1Password verify instead of being rejected as typos.",
268
+ "sections": [
269
+ {
270
+ "heading": "Changed",
271
+ "items": [
272
+ {
273
+ "title": "TOTP code normalisation before timing-safe compare",
274
+ "body": "`b.auth.totp.verify` strips whitespace + common separators (`\\s`, `-`, `.`, `_`) from the user-supplied code before the timing-safe comparison. Authenticator UIs (Google Authenticator, Authy, Duo, 1Password, etc.) and clipboard paste typically introduce these — `\"123 456\"`, `\"123-456\"`, `\"123.456\"`, `\" 123456\\t\"` — and the framework was rejecting all of them as if they were real typos. RFC 6238 / NIST 800-63B don't mandate normalisation, but every consumer-facing TOTP implementation strips these because the alternative is a silent operator footgun. Letters and other non-numeric characters are NOT stripped — those are real input errors, not paste artefacts. Comparison stays timing-safe via the framework's `crypto.timingSafeEqual` wrapper."
275
+ }
276
+ ]
277
+ }
278
+ ],
279
+ "references": [
280
+ {
281
+ "label": "RFC 6238 — TOTP",
282
+ "url": "https://www.rfc-editor.org/rfc/rfc6238"
283
+ },
284
+ {
285
+ "label": "NIST SP 800-63B",
286
+ "url": "https://pages.nist.gov/800-63-3/sp800-63b.html"
287
+ }
288
+ ]
289
+ },
290
+ {
291
+ "version": "0.6.55",
292
+ "date": "2026-05-03",
293
+ "headline": "SMTP SNI suppression on IP literals + shellcheck fix unblocks publish",
294
+ "summary": "Two bug fixes: the `b.mail` SMTP transport no longer sets a TLS ServerName when the host is an IP literal (Node refuses), and the MongoDB TLS init shell script's broken short-circuit is rewritten to a real `if` so shellcheck stops blocking the npm-publish gate.",
295
+ "sections": [
296
+ {
297
+ "heading": "Fixed",
298
+ "items": [
299
+ {
300
+ "title": "`b.mail` SMTP TLS handshake refuses IP literals as SNI",
301
+ "body": "The TLS handshake (implicit on port 465 + STARTTLS upgrade) was unconditionally setting `servername: cfg.host`, which Node's `tls.connect` rejects when host is an IP literal with `Setting the TLS ServerName to an IP address is not permitted`. Operators with `host: \"127.0.0.1\"` (or any IPv4/IPv6 literal) hit the error before a real cert-verification or auth issue could surface. SNI is now auto-suppressed on IP literals (matching `lib/redis-client.js`'s v0.6.28 convention); operators with private CAs and an IP-only target pass `opts.servername: \"expected-cn.example\"` explicitly."
302
+ },
303
+ {
304
+ "title": "`docker/mongo/init-tls.sh` rewritten as `if … then … fi`",
305
+ "body": "SC2015 — `id mongodb >/dev/null && chown mongodb:mongodb ... || true` is not if-then-else; the `|| true` would fire if `chown` failed (treating it as if `id` had failed), masking real failures. The script is rewritten as a plain `if id mongodb …; then chown …; fi`. The shellcheck failure was blocking the v0.6.54 npm-publish gate."
306
+ }
307
+ ]
308
+ }
309
+ ]
310
+ },
311
+ {
312
+ "version": "0.6.54",
313
+ "date": "2026-05-03",
314
+ "headline": "`npm-publish` workflow cap raised + shellcheck gate on tracked shell scripts",
315
+ "summary": "Releases from v0.6.38 through v0.6.53 stalled at the npm registry because the publish workflow timed out at 15 minutes before reaching `npm publish`. The cap is now 30 minutes (matching `release-container.yml`), and every tracked `.sh` file now runs through `ludeeus/action-shellcheck` so shell-script regressions fail the publish gate before the tarball ships.",
316
+ "sections": [
317
+ {
318
+ "heading": "Changed",
319
+ "items": [
320
+ {
321
+ "title": "`npm-publish` workflow timeout raised from 15 to 30 minutes",
322
+ "body": "Smoke alone runs ~3 minutes locally and 6-8 minutes on CI; combined with eslint cold-pull, wiki e2e, and SBOM generation the full pipeline exceeded the previous 15-minute cap and got cancelled before reaching `npm publish`. The cap now matches `release-container.yml` at 30 minutes so tagged releases actually publish."
323
+ },
324
+ {
325
+ "title": "Shellcheck enforced on every tracked `.sh` file in the publish gate",
326
+ "body": "`vendor-update.sh` and the docker init scripts ship in the npm tarball, so a shell-script regression must fail the publish workflow. The gate runs `ludeeus/action-shellcheck@master` against every tracked `.sh` file. Hadolint stays in `release-container.yml` only because the Dockerfile is container-only and is not part of the npm artifact."
327
+ }
328
+ ]
329
+ }
330
+ ]
331
+ },
332
+ {
333
+ "version": "0.6.53",
334
+ "date": "2026-05-03",
335
+ "headline": "Audit + observability emissions across `b.objectStore.bucketOps` SigV4 state-changing surface",
336
+ "summary": "Object Lock, retention, and legal-hold landed in v0.6.47 positioned as SEC 17a-4 / FINRA / HIPAA-grade primitives but shipped without an audit trail — an auditor asking \"who set the retention on this object, and when?\" got nothing. Every state-changing call on the SigV4 backend now emits an audit event and an observability counter, with `bypassGovernance: true` surfaced as alertable metadata.",
337
+ "sections": [
338
+ {
339
+ "heading": "Added",
340
+ "items": [
341
+ {
342
+ "title": "`audit` + `observability` opts on `bucketOps.create`",
343
+ "body": "`bucketOps.create({ audit, observability, auditSuccess, auditFailures })` wires the operator's `b.audit` and `b.observability` instances into every state-changing call. `auditSuccess` and `auditFailures` default to true; operators at extreme volume opt out of success-path auditing while keeping failure auditing on."
344
+ },
345
+ {
346
+ "title": "Audit events for every state-changing object-store op",
347
+ "body": "Emissions cover `objectstore.bucket.create`, `objectstore.bucket.delete`, `objectstore.bucket.setLifecycle`, `objectstore.bucket.setCorsRules`, `objectstore.bucket.setObjectLockConfiguration`, `objectstore.object.setRetention`, and `objectstore.object.setLegalHold`. Each accepts `{ req }` so the audit chain populates `actorIp`, `actorUserAgent`, `actorSessionId`, `requestId`, `method`, and `route` via `requestHelpers.resolveActorWithOverride`."
348
+ },
349
+ {
350
+ "title": "Observability counters on reads + writes",
351
+ "body": "Every op increments an observability counter, including read paths (`getObjectLockConfiguration`, `getRetention`, `getLegalHold`). Operators get visibility into retention-introspection traffic alongside the state-changing surface."
352
+ },
353
+ {
354
+ "title": "`objectstore` namespace registered in `audit.FRAMEWORK_NAMESPACES`",
355
+ "body": "The new event family registers as a first-class framework namespace so operator-side audit consumers route it like any other built-in primitive."
356
+ }
357
+ ]
358
+ },
359
+ {
360
+ "heading": "Security",
361
+ "items": [
362
+ {
363
+ "title": "`bypassGovernance` flagged in retention audit metadata",
364
+ "body": "`setObjectRetention` audit metadata sets `bypassGovernance: true` when the operator used the bypass-shorten path. Operators wire alerting on this field to satisfy compliance postures that require human review of every governance-mode override."
365
+ }
366
+ ]
367
+ }
368
+ ]
369
+ },
370
+ {
371
+ "version": "0.6.52",
372
+ "date": "2026-05-03",
373
+ "headline": "`b.mtlsCa` serial-number normaliser rejects gibberish instead of silently mangling it",
374
+ "summary": "Before this release `_normalizeSerial(\"xyz-not-hex\")` ran `.replace(/[^0-9a-fA-F]/g, \"\")` which kept just the single `e` and silently registered a phantom `revoke(\"e\")` row. A typo from `openssl x509 -noout -serial` — or any non-serial paste — would have landed in the next CRL the operator published. The normaliser now strips only documented operator-paste shapes (leading `0x`, `:` / `-` / whitespace separators) and asserts the remainder is all-hex; anything else throws `mtls-ca/bad-serial`.",
375
+ "sections": [
376
+ {
377
+ "heading": "Fixed",
378
+ "items": [
379
+ {
380
+ "title": "Serial-number normaliser refuses non-hex input",
381
+ "body": "Real shapes still accepted (`\"0xABC123\"`, `\"AB:C1:23\"`, `\"AB-C1-23\"`, `\"abc 123\"`, `\"abc123\"` all normalise to `abc123`). Gibberish input (`\"xyz-not-hex\"`, `\" \"`, `\"nope\"`) throws `mtls-ca/bad-serial` at the call site so the typo never reaches the revocation registry or a published CRL."
382
+ }
383
+ ]
384
+ },
385
+ {
386
+ "heading": "Added",
387
+ "items": [
388
+ {
389
+ "title": "Three live-CA integration assertions on top of the existing 41",
390
+ "body": "`test/integration/mtls-ca.test.js` now covers the bad-input refusal paths end-to-end against the real CA engine (44 checks total)."
391
+ }
392
+ ]
393
+ }
394
+ ]
395
+ },
396
+ {
397
+ "version": "0.6.51",
398
+ "date": "2026-05-03",
399
+ "headline": "`b.objectStore.bucketOps` Object Lock readers return clean defaults instead of raw 4xx errors",
400
+ "summary": "Live MinIO probing surfaced a UX regression: `getObjectLockConfiguration` on a bucket created without `objectLockEnabled` threw HTTP 404 `ObjectLockConfigurationNotFoundError`, forcing a try/catch on the operationally-trivial \"is this bucket lock-enabled?\" question. `getObjectRetention` and `getObjectLegalHold` had the same shape. All three now return semantically-correct defaults for never-configured state while real errors still throw.",
401
+ "sections": [
402
+ {
403
+ "heading": "Fixed",
404
+ "items": [
405
+ {
406
+ "title": "Object Lock readers return defaults for never-configured state",
407
+ "body": "A new `_isLockNotConfigured` helper recognises both the AWS and MinIO error shapes. `getObjectLockConfiguration` now returns `{ enabled: false, mode: null, days: null, years: null }`, `getObjectRetention` returns `{ mode: null, retainUntil: null }`, and `getObjectLegalHold` returns `{ status: \"OFF\" }` (operationally identical to \"no hold ever applied\"). Auth failures, network errors, and bucket-not-found still throw as before."
408
+ }
409
+ ]
410
+ },
411
+ {
412
+ "heading": "Added",
413
+ "items": [
414
+ {
415
+ "title": "Layer-0 + live MinIO coverage for the not-configured paths",
416
+ "body": "7 new mock-server assertions cover the not-configured branches; 8 new live MinIO assertions in `_runObjectLockOnEndpoint` and a new no-lock-bucket variant in `_runOnEndpoint` exercise the round-trip end-to-end (object-store-sigv4 39 to 47 checks)."
417
+ }
418
+ ]
419
+ }
420
+ ]
421
+ },
422
+ {
423
+ "version": "0.6.50",
424
+ "date": "2026-05-03",
425
+ "headline": "SigV4 multipart subresource consistency + live coverage",
426
+ "sections": [
427
+ {
428
+ "heading": "Changed",
429
+ "items": [
430
+ {
431
+ "title": "`?uploads` bare on the wire",
432
+ "body": "`lib/object-store/sigv4.js` was the only remaining `URLSearchParams.set(k, \"\")` empty-value site — `initiateUrl.searchParams.set(\"uploads\", \"\")` produced `?uploads=` for InitiateMultipartUpload. AWS S3 and MinIO both accept `?uploads=` today, so this wasn't broken in the real world, but the convention drift would mask future regressions and a stricter S3 implementation could route differently. `?uploads` is now bare on the wire, matching the prior subresource fix; SigV4 canonicalization is unchanged (still presents `uploads=` to the signer per AWS spec)."
433
+ }
434
+ ]
435
+ },
436
+ {
437
+ "heading": "Added",
438
+ "items": [
439
+ {
440
+ "title": "Live multipart-upload integration",
441
+ "body": "`test/integration/object-store-sigv4.test.js` `_runOnEndpoint` gains a multipart-upload + get round-trip pass (forces multipart with `multipartThresholdBytes: 1`, `partSizeBytes: 5 MiB`, payload 6 MiB -> 2-part flow). The live MinIO assertion locks in `?uploads`, `?partNumber=N&uploadId=...`, and `?uploadId=...` (CompleteMultipartUpload) wire flow."
442
+ }
443
+ ]
444
+ }
445
+ ]
446
+ },
447
+ {
448
+ "version": "0.6.49",
449
+ "date": "2026-05-03",
450
+ "headline": "SigV4 subresource-query wire form (no trailing `=`)",
451
+ "sections": [
452
+ {
453
+ "heading": "Fixed",
454
+ "items": [
455
+ {
456
+ "title": "Bare `?subresource` for empty-value query keys",
457
+ "body": "The previous Object Lock implementation built URLs via `URLSearchParams.set(\"retention\", \"\")`, producing `?retention=` on the wire. Strict S3 implementations (MinIO in particular) interpret the trailing `=` as a body PUT with a query parameter and route the request to the put-object handler, which then rejects with `InvalidRequest: Object is WORM protected and cannot be overwritten`. `_bucketUrl` and `_objectUrl` now build the URL string manually with `?subresource` (no `=`) for empty-value query keys; `URL` preserves the bare token in `url.search` while `url.searchParams` still presents it as `subresource=` to the SigV4 canonicalizer (AWS spec REQUIRES `key=` in the canonical query string for signature computation)."
458
+ },
459
+ {
460
+ "title": "Live integration coverage for Object Lock",
461
+ "body": "`test/integration/object-store-sigv4.test.js` gains a third endpoint variant (`_runObjectLockOnEndpoint`) that creates a bucket with `objectLockEnabled: true` against live MinIO and exercises per-object retention set + get, per-object legal hold ON/OFF round-trip, bucket-level `setObjectLockConfiguration` + `getObjectLockConfiguration` round-trip, `bypassGovernance` retention shortening, and cleanup."
462
+ }
463
+ ]
464
+ },
465
+ {
466
+ "heading": "Detectors",
467
+ "items": [
468
+ {
469
+ "title": "Subresource bare-token wire-form regression check",
470
+ "body": "`test/layer-0-primitives/sigv4-bucket-ops.test.js` gains three wire-form assertions on `?retention`, `?legal-hold`, and `?object-lock` (`bare subresource, no '=' suffix`) to catch this class of regression before it reaches operators."
471
+ }
472
+ ]
473
+ }
474
+ ]
475
+ },
476
+ {
477
+ "version": "0.6.48",
478
+ "date": "2026-05-03",
479
+ "headline": "Doc catch-up for the v0.6.47 Object Lock surface",
480
+ "sections": [
481
+ {
482
+ "heading": "Changed",
483
+ "items": [
484
+ {
485
+ "title": "README + SECURITY weave-ins for Object Lock",
486
+ "body": "The README `What ships in the box` object-store bullet now mentions S3 Object Lock + per-object retention + legal hold for write-once-read-many compliance workloads. SECURITY application checklist gains a sibling line to `b.retention` covering the operator's hardening checklist for WORM archives (SEC 17a-4, FINRA, HIPAA-shaped retention) — `objectLockEnabled: true` at create time only, `COMPLIANCE` mode irrevocable by anyone (including root), `bypassGovernance` requires `s3:BypassGovernanceRetention`. No code changes."
487
+ }
488
+ ]
489
+ }
490
+ ]
491
+ },
492
+ {
493
+ "version": "0.6.47",
494
+ "date": "2026-05-03",
495
+ "headline": "S3 Object Lock, retention, and legal-hold for `b.objectStore.bucketOps`",
496
+ "summary": "Adds the write-once-read-many compliance surface (SEC 17a-4, FINRA, HIPAA retention) to the SigV4 protocol; Azure and GCS handle WORM out-of-band.",
497
+ "sections": [
498
+ {
499
+ "heading": "Added",
500
+ "items": [
501
+ {
502
+ "title": "Object Lock + retention + legal-hold",
503
+ "body": "`create(name, { objectLockEnabled: true })` flips the underlying versioning and WORM at create time (the only point S3 allows it). `setObjectLockConfiguration(name, { mode, days|years })` / `getObjectLockConfiguration(name)` apply and read bucket-level default retention. `setObjectRetention(name, key, { mode, retainUntil, bypassGovernance? })` / `getObjectRetention(name, key)` apply and read per-object retention dates. `setObjectLegalHold(name, key, \"ON\"|\"OFF\")` / `getObjectLegalHold(name, key)` apply and read per-object legal holds."
504
+ },
505
+ {
506
+ "title": "Up-front validation",
507
+ "body": "Bad inputs are rejected at the call site before any request is signed: unknown mode, `days` + `years` together, fractional or negative durations, non-Date or past-dated `retainUntil`, statuses outside `ON` / `OFF` — all throw `INVALID_OBJECT_LOCK` / `INVALID_RETENTION` / `INVALID_LEGAL_HOLD` (or `INVALID_KEY`) before TCP. `bypassGovernance: true` adds the `x-amz-bypass-governance-retention: true` header for accounts with the `s3:BypassGovernanceRetention` permission; `COMPLIANCE` mode cannot be shortened or bypassed by anyone, including root."
508
+ }
509
+ ]
510
+ }
511
+ ]
512
+ },
513
+ {
514
+ "version": "0.6.46",
515
+ "date": "2026-05-02",
516
+ "headline": "`b.i18n.messageFormat` ICU MessageFormat parser + evaluator",
517
+ "sections": [
518
+ {
519
+ "heading": "Added",
520
+ "items": [
521
+ {
522
+ "title": "ICU MessageFormat support",
523
+ "body": "`lib/i18n-messageformat.js` ships a minimal-but-correct ICU MessageFormat parser and evaluator (~330 LOC, zero npm dep). Supports `{argName}` replacement; `{argName, plural, =N {...} category {...} other {...}}` with optional `offset:N` and `#` placeholder for the plural arg minus offset; `{argName, selectordinal, ...}` (CLDR ordinal categories via `Intl.PluralRules({ type: \"ordinal\" })`); `{argName, select, caseA {...} other {...}}`; nested arguments inside any case body; and ICU-spec apostrophe escaping. CLDR cardinal + ordinal categories via `Intl.PluralRules` per locale (cached). Inline `number` / `date` / `time` formatters, choice-format, and custom argument types are out of scope — operators use `formatNumber` / `formatDate` from `b.i18n` separately and inline the result."
524
+ },
525
+ {
526
+ "title": "Auto-detect via `b.i18n.t`",
527
+ "body": "`b.i18n.t(key, vars, opts)` auto-detects MessageFormat-shaped entries via `messageFormat.looksLikeMessageFormat(template)` (matches `{name, plural / select / selectordinal, ...}`); operators force the path with `opts.messageFormat = true`. Plain `{var}` interpolation and existing CLDR plural-shaped JSON entries continue to work unchanged on the legacy interpolator."
528
+ }
529
+ ]
530
+ }
531
+ ]
532
+ },
533
+ {
534
+ "version": "0.6.45",
535
+ "date": "2026-05-02",
536
+ "headline": "`b.mtlsCa` revocation registry + signed CRL generation",
537
+ "sections": [
538
+ {
539
+ "heading": "Added",
540
+ "items": [
541
+ {
542
+ "title": "`ca.revoke(serialNumber, opts?)`",
543
+ "body": "Records a revocation in `dataDir/revocations.json` with serial / reason / `revokedAt` timestamp. Serials are normalized (strips `0x`, removes non-hex chars, lowercases) so operators can paste any of `\"0xABC123\"` / `\"AB:C1:23\"` / `\"abc123\"` and hit the same row. Reason names map to RFC 5280 numeric codes (full set: `unspecified / keyCompromise / caCompromise / affiliationChanged / superseded / cessationOfOperation / certificateHold / removeFromCRL / privilegeWithdrawn / aACompromise`). Idempotent — repeated revoke of the same serial preserves the original `revokedAt`."
544
+ },
545
+ {
546
+ "title": "`ca.isRevoked` / `ca.getRevocations`",
547
+ "body": "Registry queries, also serial-format-agnostic so callers can pass whichever shape their upstream emits."
548
+ },
549
+ {
550
+ "title": "`ca.generateCrl(opts?)`",
551
+ "body": "Builds an RFC 5280 X.509 CRL signed with the CA private key via `engine.generateCrl({ caCertPem, caKeyPem, revocations, thisUpdate, nextUpdate })`. Default `nextUpdate` is 7 days after `thisUpdate`; operators publishing at a different cadence pass explicit dates. CRL persists to `dataDir/ca.crl` by default; `{ persist: false }` returns the bytes without writing. Operators serve `ca.crl` at the CRL distribution point referenced from issued certs."
552
+ }
553
+ ]
554
+ }
555
+ ],
556
+ "references": [
557
+ {
558
+ "label": "RFC 5280 — X.509 Public Key Infrastructure",
559
+ "url": "https://www.rfc-editor.org/rfc/rfc5280.html"
560
+ }
561
+ ]
562
+ },
563
+ {
564
+ "version": "0.6.44",
565
+ "date": "2026-05-02",
566
+ "headline": "`b.bundler` engine surface for ESM module-graph bundling",
567
+ "sections": [
568
+ {
569
+ "heading": "Added",
570
+ "items": [
571
+ {
572
+ "title": "Pluggable engine layer",
573
+ "body": "`b.bundler.create({ engine })` accepts any object implementing `{ name, transform(entryPath, contentBuf) -> { content, sourceMap?, imports? } }` between the file read and the cache-bust hash. `b.bundler.engine.passthrough` is the default and preserves the prior byte-verbatim behavior — no breaking change."
574
+ },
575
+ {
576
+ "title": "`b.bundler.engine.fromEsbuild(esbuild, opts?)`",
577
+ "body": "Wraps an operator-supplied esbuild module into the engine contract. Routes through `esbuild.build({ entryPoints, write: false, ...opts })`, picks the JS output and `.map` sibling out of `outputFiles`, returns `{ content, sourceMap }` for the framework to hash and write atomically. Source maps land as `<hashed-filename>.map` siblings; the bundler's `outputs[i].sourceMapPath` reports the on-disk path. The framework does not vendor `esbuild-wasm` — at ~10 MB it would 3-5x the npm tarball for a build-time tool most operators only need at deploy time. The integration seam is the framework's; the heavy machinery stays operator-supplied."
578
+ }
579
+ ]
580
+ }
581
+ ]
582
+ },
583
+ {
584
+ "version": "0.6.43",
585
+ "date": "2026-05-02",
586
+ "headline": "AWS SQS queue backend",
587
+ "sections": [
588
+ {
589
+ "heading": "Added",
590
+ "items": [
591
+ {
592
+ "title": "`b.queue` SQS protocol",
593
+ "body": "`protocol: \"sqs\"` for operators on AWS who want a fully-managed queue without standing up a Redis cluster. Wire is AWSJsonProtocol_1.0 over HTTPS (Content-Type `application/x-amz-json-1.0`, `X-Amz-Target: AmazonSQS.<Action>`), SigV4-signed via the framework's service-agnostic `lib/object-store/sigv4.js`. Action mapping: `enqueue -> SendMessage`, `lease -> ReceiveMessage` (long-poll up to `WaitTimeSeconds`), `extendLease -> ChangeMessageVisibility`, `complete -> DeleteMessage`, `fail -> ChangeMessageVisibility(VisibilityTimeout=0)`, `size -> GetQueueAttributes`, `purge -> PurgeQueue`. Queue-name -> URL by default `https://sqs.{region}.amazonaws.com/{accountId}/{queueName}`; operators with cross-account / FIFO / VPCE endpoints pass an explicit `queueUrlByName(name) -> url` resolver. STS session tokens propagate as `x-amz-security-token`. Payloads pass through `cryptoField.sealRow(\"_blamejs_jobs\", row)` before SendMessage so SQS only ever sees the sealed envelope."
594
+ },
595
+ {
596
+ "title": "SQS hard-cap clamps",
597
+ "body": "`DelaySeconds` is clamped to the 900-second SQS hard cap; `MaxNumberOfMessages` is clamped to 10 (SQS's per-call ceiling)."
598
+ }
599
+ ]
600
+ },
601
+ {
602
+ "heading": "Removed",
603
+ "items": [
604
+ {
605
+ "title": "`sqs` removed from `DEFERRED_PROTOCOLS`",
606
+ "body": "The SQS queue backend is first-class and no longer listed as a deferred protocol. DLQ inspection (`dlqList` / `dlqRetry` / `dlqSize`), flow / cron / parent-child dependencies, and `sweepExpired` stay on `local` / `redis` — SQS handles those server-side or via separate-queue DLQs operators wire as a second backend."
607
+ }
608
+ ]
609
+ }
610
+ ]
611
+ },
612
+ {
613
+ "version": "0.6.42",
614
+ "date": "2026-05-02",
615
+ "headline": "Wiki primitive sections for testing / format-helpers / backup-restore",
616
+ "sections": [
617
+ {
618
+ "heading": "Added",
619
+ "items": [
620
+ {
621
+ "title": "`testing` page primitive sections",
622
+ "body": "`b.testing.mockReq(opts?)` / `.mockRes()`, `b.testing.fakeClock(initialMs?)`, `b.testing.captureAudit()` (corrected surface: `.byAction` / `.captured`), `b.testing.captureObservability()` (corrected surface: `.byName` / `.captured`), `b.testing.fakeHttpClient(handler)`, `b.testing.runMiddleware(fn, req, res)`, `b.testing.waitFor(predicate, opts?)`, `b.testing.tempDir(name?)`."
623
+ },
624
+ {
625
+ "title": "`format-helpers` page primitive sections",
626
+ "body": "`b.csv.parse(input, opts?)` / `.stringify(rows, opts?)`, `b.uuid.v4 / .v7 / .parse / .isValid`, `b.slug(input, opts?)` / `.unique(input, exists, opts?)`, `b.time.toParts / .format / .addDays / .addMonths / .startOfDay / .endOfDay / .diffDays / .parseISO / .tzOffsetMs`, `b.archive.zip()`, `b.pagination.cursor(query, opts)` (corrected from non-existent `b.pagination.create({...})`), `b.forms.render(spec, opts?)` / `.validate(spec, body)` / `.generateCsrfToken / .verifyCsrfToken`."
627
+ },
628
+ {
629
+ "title": "`backup-restore` page primitive sections",
630
+ "body": "`b.backup.create(opts)` and `b.restore.create(opts)`. The wiki primitive-runtime gate is up from 147 to 186 clean exec runs."
631
+ }
632
+ ]
633
+ }
634
+ ]
635
+ },
636
+ {
637
+ "version": "0.6.41",
638
+ "date": "2026-05-02",
639
+ "headline": "Wiki primitive sections for welcome / crypto-vault / network-crypto / safe-parsers",
640
+ "sections": [
641
+ {
642
+ "heading": "Added",
643
+ "items": [
644
+ {
645
+ "title": "`welcome` page primitive sections",
646
+ "body": "`b.createApp(opts)` documented as the operator entry point that wires the dependency-ordered boot."
647
+ },
648
+ {
649
+ "title": "`crypto-vault` page primitive sections",
650
+ "body": "`b.vault.seal(plaintext) / .unseal(sealed)` and `b.cryptoField.registerTable(name, opts)` (sealedFields + derivedHashes registry the db-query layer reads on every read/write). The API-drift `b.webhook.signer.create({...})` / `b.webhook.verifier.create({...})` examples are removed — actual API is `b.webhook.signer({...})` and `b.webhook.verifier({...})` documented at outbound-http; crypto-vault now cross-links instead of restating."
651
+ },
652
+ {
653
+ "title": "`network-crypto` page primitive sections",
654
+ "body": "`b.mtlsCa.create(opts)` (lib allow-list reflects `dataDir / vault / paths / caKeySealedMode / generation / engine`), `b.pqcGate.create(opts)` (corrected to `internalPort / internalHost / bypass / clientHelloTimeoutMs / maxClientHelloBytes / log`), `b.pqcAgent.create(opts?)` (with the `b.pqcAgent.agent` and `.enforced` shared-singleton handles documented)."
655
+ },
656
+ {
657
+ "title": "`safe-parsers` page primitive sections",
658
+ "body": "`b.safeJson.parse(text, opts?)`, `b.safeBuffer.normalizeText(input, opts?)` / `.boundedChunkCollector(opts)` / `.secureZero(buf)` (corrected to `bytesCollected()`), `b.safeSql.validateIdentifier(value, opts?)` (corrected from `b.safeSql.identifier` which doesn't exist), and the `b.safeSchema` builder factories (`object / string / number / boolean / array / literal / union` with refinements). The wiki primitive-runtime gate is up from 130 to 147 clean exec runs."
659
+ }
660
+ ]
661
+ }
662
+ ]
663
+ },
664
+ {
665
+ "version": "0.6.40",
666
+ "date": "2026-05-02",
667
+ "headline": "Wiki harness upgrade + compound-primitive coverage for routing / middleware / outbound-http",
668
+ "sections": [
669
+ {
670
+ "heading": "Added",
671
+ "items": [
672
+ {
673
+ "title": "Harness extension for operator-side identifiers",
674
+ "body": "`examples/wiki/test/run-example.js` adds stub bindings for `app` (Express-shape stub with the full HTTP-verb surface), `users` (db-model stub), `template`, `metrics`, `currentToken`, `largeBuffer`, `body`, `loginUrl`, `meUrl`, `authMiddleware`, and `loginHandler`. Compound-primitive examples can now round-trip cleanly through the runtime gate."
675
+ },
676
+ {
677
+ "title": "`routing` page primitive sections",
678
+ "body": "`new b.router.Router(opts?)`, `router.METHOD(path, spec?, ...handlers)`, `router.openapi(opts)`, `b.render.htmlString / .json / .text / .redirect`, `b.htmlBalance.check`, `b.staticServe.create(opts)` (corrected to opts-only with required `root`), `b.errorPage.create(opts)`, `b.requestHelpers.extractActorContext / .parseQualityList / .parseListHeader`."
679
+ },
680
+ {
681
+ "title": "`middleware` page primitive sections",
682
+ "body": "`b.middleware.rateLimit / .csrfProtect / .cspNonce / .bodyParser / .bodyParser.raw / .sse(handler, opts?) / .requestLog / .networkAllowlist`, `b.cookies.create(opts?)` / `.parse(headerValue)`, `b.validateOpts`. Real API drifts corrected: `rateLimit` uses `refillPerSecond`, `csrfProtect` uses `tokenLookup / fieldName`, `requestLog` uses `logger`, `cookies.create` accepts `vault` for sealing values, `sse(handler, opts?)` takes the handler positionally."
683
+ },
684
+ {
685
+ "title": "`outbound-http` page primitive sections",
686
+ "body": "`b.httpClient.request(opts)` with subsections for `maxRedirects`, `multipart`, `before / after` interceptors; `b.httpClient.cookieJar.create`; `b.ssrfGuard.checkUrl / .classify`; `b.safeUrl.parse`; `b.webhook.signer / .verifier`. The wiki primitive-runtime gate is up from 87 to 130 clean exec runs."
687
+ }
688
+ ]
689
+ }
690
+ ]
691
+ },
692
+ {
693
+ "version": "0.6.39",
694
+ "date": "2026-05-02",
695
+ "headline": "Wiki primitive sections for self-contained pure-function helpers",
696
+ "summary": "The wiki harness exec-runs every example with only `b` in scope; this release converts the self-contained primitives whose examples fit in two or three pure-function lines. Compound primitives that need operator stubs (`app`, `req`, `res`) land in a follow-up patch alongside the harness upgrade.",
697
+ "sections": [
698
+ {
699
+ "heading": "Added",
700
+ "items": [
701
+ {
702
+ "title": "Primitive sections for pure-function helpers",
703
+ "body": "`b.requestHelpers.parseQualityList(value, opts?)` (RFC 9110 §12.5 Accept-* parser), `b.requestHelpers.parseListHeader(value, opts?)` (comma-separated parser with trim / lowercase / unique opts), `b.htmlBalance.check(html)` (structural HTML check returning `null` when balanced or `{code, message, line, column}` when not), `b.ssrfGuard.classify(ip)` (offline IP classifier), and `b.safeUrl.parse(input, opts?)` each gain a four-piece primitive section (heading + opts model + description + example). The wiki primitive-runtime gate is up from 75 to 87 clean exec runs."
704
+ }
705
+ ]
706
+ }
707
+ ]
708
+ },
709
+ {
710
+ "version": "0.6.38",
711
+ "date": "2026-05-02",
712
+ "headline": "OTLP gRPC + protobuf transport for `b.logStream`",
713
+ "sections": [
714
+ {
715
+ "heading": "Added",
716
+ "items": [
717
+ {
718
+ "title": "`otlp-grpc` log sink",
719
+ "body": "First-class `protocol: \"otlp-grpc\"` companion to the existing OTLP/JSON sink: same OTel Logs Data Model, transported over HTTP/2 + gRPC framing for the higher-throughput path operators reach for when pushing past 100K logs per second straight to a collector. Single HTTP/2 session per sink, kept alive across many Export calls; recreated on disconnect. Reads `grpc-status` + `grpc-message` from response trailers; non-zero gRPC status surfaces as `HTTP_ERROR` with the gRPC error code and message preserved. Same back-pressure semantics as the JSON sink."
720
+ },
721
+ {
722
+ "title": "`lib/protobuf-encoder.js`",
723
+ "body": "Minimal proto3 wire-format encoder (write-only — no decoder ships). Implements varint, 64-bit fixed, length-delimited, and 32-bit fixed wire types with helpers for `uint32` / `uint64` / `bool` / `fixed64` / `double` / `string` / `bytes` / `embeddedMessage` / `repeatedMessage`. Operators reach for it when constructing protobuf bodies for any external service that accepts proto over HTTP — gRPC, AWS SigV4-protobuf, GCP protobuf APIs. Zero vendored protobuf parser; the encoder is the framework's own."
724
+ },
725
+ {
726
+ "title": "`lib/log-stream-otlp-grpc.js`",
727
+ "body": "Encodes `ExportLogsServiceRequest` per the OTel `logs.proto` schema (Resource -> ScopeLogs -> LogRecord -> AnyValue / KeyValue), wraps in gRPC framing (1-byte compression flag + 4-byte big-endian length + protobuf body), POSTs over `node:http2` to `/opentelemetry.proto.collector.logs.v1.LogsService/Export` with `content-type: application/grpc+proto` plus `te: trailers`. Severity mapping debug=5 / info=9 / warn=13 / error=17."
728
+ }
729
+ ]
730
+ }
731
+ ]
732
+ },
733
+ {
734
+ "version": "0.6.37",
735
+ "date": "2026-05-02",
736
+ "headline": "Azure + GCS bucket-ops parity for `b.objectStore.bucketOps`",
737
+ "sections": [
738
+ {
739
+ "heading": "Added",
740
+ "items": [
741
+ {
742
+ "title": "Protocol-dispatching `bucketOps` factory",
743
+ "body": "`b.objectStore.bucketOps` now accepts `{ protocol: 'sigv4' | 'azure-blob' | 'gcs', ... }` and returns a service-scoped client for the matching cloud. Previously SigV4 only."
744
+ },
745
+ {
746
+ "title": "Azure Blob bucket-ops",
747
+ "body": "`lib/object-store/azure-blob-bucket-ops.js` provides container lifecycle via Shared Key auth: `create(name, {publicAccess?})` (PUT `/{container}?restype=container`), `delete(name)` (DELETE), `list({prefix?, maxResults?})` (GET `/?comp=list` with XML response parsed into `[{ name, lastModified, etag, leaseStatus, leaseState, publicAccess }]`), `setCorsRules(rules)` (account-level — Azure CORS is not per-container). `setLifecycle` throws `NOT_SUPPORTED` because Azure lifecycle lives on Azure Resource Manager with Azure AD bearer auth; the error message points at Terraform / Bicep / az CLI."
748
+ },
749
+ {
750
+ "title": "GCS bucket-ops",
751
+ "body": "`lib/object-store/gcs-bucket-ops.js` provides bucket lifecycle via service-account JWT exchanged for an OAuth2 access token (admin-scoped `devstorage.full_control`): `create(name, {location?, storageClass?, iamConfiguration?})`, `delete(name)`, `list({prefix?, maxResults?, pageToken?})`, `setLifecycle(name, rules)` (PATCH bucket with `lifecycle: { rule: [{ action, condition }] }` — supports `Delete` / `SetStorageClass` / `AbortIncompleteMultipartUpload`), `setCorsRules(name, rules)`."
752
+ },
753
+ {
754
+ "title": "Per-cloud bucket-name validation",
755
+ "body": "Azure containers (3-63 lowercase alphanumeric + hyphens, no consecutive hyphens, start/end alphanumeric); GCS buckets (3-63 lowercase + digits + hyphens + underscores + dots, no consecutive dots, no `goog` prefix). Bad names rejected at the call site before the request leaves the process. Both modules treat 404 on delete as already-gone and 409 on create as `BUCKET_ALREADY_OWNED`."
756
+ }
757
+ ]
758
+ }
759
+ ]
760
+ },
761
+ {
762
+ "version": "0.6.36",
763
+ "date": "2026-05-02",
764
+ "headline": "`b.db.from(\"schema.table\")` cross-schema chain",
765
+ "sections": [
766
+ {
767
+ "heading": "Added",
768
+ "items": [
769
+ {
770
+ "title": "Two-part `schema.table` identifiers",
771
+ "body": "`b.db.from(\"audit.events\")` now accepts a two-part identifier. Both halves validated separately as SQL identifiers (rejects three-part names, empty parts, embedded quotes / SQL keywords); both halves wrapped in `\"...\"` when interpolated so generated SQL is `SELECT * FROM \"audit\".\"events\" WHERE ...`. The bare `b.db.from(\"users\")` form still works unchanged. Sealed-field registry lookup tries the qualified name (`audit.users`) first when schema is set, falls back to the bare table. Use cases: cross-schema joins on Postgres external-db, SQLite `ATTACH DATABASE` per-classification audit / archive databases."
772
+ }
773
+ ]
774
+ }
775
+ ]
776
+ },
777
+ {
778
+ "version": "0.6.35",
779
+ "date": "2026-05-02",
780
+ "headline": "`cluster-provider-db` gains MySQL dialect",
781
+ "sections": [
782
+ {
783
+ "heading": "Added",
784
+ "items": [
785
+ {
786
+ "title": "MySQL dialect for the default leader-election provider",
787
+ "body": "`b.cluster.create({ provider: clusterProviderDb.create({ dialect: \"mysql\", ... }) })` lets operators on MySQL use the framework's default DB-row leader-election provider; it now speaks all three of postgres / sqlite / mysql. MySQL acquireLease uses `INSERT INTO _blamejs_leader (...) VALUES (...) ON DUPLICATE KEY UPDATE col = IF(expiresAt < ?, VALUES(col), col), ..., expiresAt = IF(expiresAt < ?, VALUES(expiresAt), expiresAt)` so a still-valid lease is preserved untouched and an expired one is overwritten atomically, followed by a `SELECT` to read who holds. Renew uses `UPDATE ... SET expiresAt=?, endpoint=? WHERE scope='leader' AND nodeId=? AND leaseId=?` followed by a check-SELECT to surface takeover races as `LEASE_LOST`. Schema generation switches to `BIGINT` / `VARCHAR(64)` / `VARCHAR(255)` per MySQL's primary-key length rules, drops the `CHECK` constraint that some MariaDB / MySQL 5.x versions silently strip, and flips placeholder style to `?`."
788
+ }
789
+ ]
790
+ }
791
+ ]
792
+ },
793
+ {
794
+ "version": "0.6.34",
795
+ "date": "2026-05-02",
796
+ "headline": "`b.pubsub` distributed pub/sub primitive",
797
+ "summary": "Single API for cross-node fan-out with three backends — `local`, `cluster` (shared DB table polled), and `redis` (SUBSCRIBE/PSUBSCRIBE).",
798
+ "sections": [
799
+ {
800
+ "heading": "Added",
801
+ "items": [
802
+ {
803
+ "title": "`b.pubsub` with local / cluster / redis backends",
804
+ "body": "Operator API: `ps.subscribe(channel, handler) -> token`, `ps.subscribePattern(pattern, handler) -> token` (glob-style on local + cluster, native PSUBSCRIBE on redis), `ps.unsubscribe(token)`, `await ps.publish(channel, payload) -> { local, remote }`, `await ps.close()`. `topicPrefix` opt scopes channel names so independent pubsub instances sharing a backend don't collide. Handler errors are caught and logged via the framework's boot logger; they never abort dispatch to other handlers on the same channel."
805
+ },
806
+ {
807
+ "title": "Redis push-message demultiplexing",
808
+ "body": "`lib/redis-client.js` adds push-message demultiplexing: server-pushed `[\"message\", channel, payload]` and `[\"pmessage\", pattern, channel, payload]` arrays route through `setOnPushMessage` instead of consuming a pending request slot, while SUBSCRIBE / UNSUBSCRIBE acks still flow through the normal command pipeline. Per-instance nonce stamped on outgoing redis payloads so the SUBSCRIBE socket recognizes its own publishes and skips the loopback."
809
+ },
810
+ {
811
+ "title": "`lib/websocket-channels.js` reroutes through `b.pubsub`",
812
+ "body": "Replaces the inline cluster-poll-and-fan-out logic with `b.pubsub` consumption. The hub owns one pubsub instance per primitive; cross-node delivery is `pubsub.subscribe` per channel the hub joins, with the hub's `_localDispatch` as the handler. Per-channel pubsub subscription is refcounted by local conn count. The `_blamejs_ws_messages` table is renamed to `_blamejs_pubsub_messages` (column `channel` -> `topic`); pre-1.0, no compat shim — operators upgrading wipe the previous table."
813
+ },
814
+ {
815
+ "title": "`b.cache.create({ invalidationPubsub })`",
816
+ "body": "Passing a `b.pubsub.create()` instance auto-publishes on every successful `del` / `clear` / `invalidateTag`, and subscribes for the same events so other cache instances on other nodes (or processes sharing the pubsub backend) react locally. Re-entrancy guard prevents inbound invalidation events from re-publishing."
817
+ }
818
+ ]
819
+ }
820
+ ]
821
+ },
822
+ {
823
+ "version": "0.6.33",
824
+ "date": "2026-05-02",
825
+ "headline": "`b.logStream` syslog sink (RFC 5424) + CloudWatch `autoCreate`",
826
+ "sections": [
827
+ {
828
+ "heading": "Added",
829
+ "items": [
830
+ {
831
+ "title": "Syslog sink (RFC 5424)",
832
+ "body": "`protocol: \"syslog\"` for `b.logStream.init`; new module `lib/log-stream-syslog.js`. URL-driven transport selection: `udp://host:514`, `tcp://host:514`, `tls://host:6514`. UDP is best-effort one-datagram-per-record; TCP / TLS use RFC 6587 octet-counting framing. TLS is TLS 1.3 minimum; operators with private CAs pass `ca` for trust pinning, `servername` for SNI override (auto-suppressed on IP literals). Records formatted with PRI = `(facility << 3) | severity` (default facility `local0`), severity mapped from the framework's level field (debug=7 / info=6 / warn=4 / error=3); operators override via `facility`, `appName` (default `blamejs`), `procId` (default `process.pid`), `hostname` (default `os.hostname()`), `structuredData` (default `-`). TCP / TLS reconnect with exponential backoff; records buffer during the down window with `bufferLimit`-bounded oldest-drop, replay on reconnect. `close()` waits up to 3s for an in-flight (re)connect to drain the buffer before tearing down. Operator-supplied `onDrop({reason, batch, error})` surfaces every drop class."
833
+ },
834
+ {
835
+ "title": "CloudWatch sink `autoCreate`",
836
+ "body": "Pass `{ autoCreate: true }` to have the framework issue `CreateLogGroup` + `CreateLogStream` on first emit. Idempotent: AWS's `ResourceAlreadyExistsException` is treated as success on both calls. Hard failures drop the batch with `onDrop` reason `autocreate-failed`. Default remains `autoCreate: false`."
837
+ }
838
+ ]
839
+ },
840
+ {
841
+ "heading": "Fixed",
842
+ "items": [
843
+ {
844
+ "title": "`docker/init/generate-certs.sh` preserves existing CA",
845
+ "body": "Was overwriting an existing CA when re-run with `.complete` removed, invalidating every previously-issued leaf cert. Now reuses an existing `(ca.crt, ca.key)` pair across `.complete`-only resets and only generates a fresh CA when neither file is present."
846
+ }
847
+ ]
848
+ }
849
+ ],
850
+ "references": [
851
+ {
852
+ "label": "RFC 5424 — The Syslog Protocol",
853
+ "url": "https://www.rfc-editor.org/rfc/rfc5424.html"
854
+ },
855
+ {
856
+ "label": "RFC 6587 — Transmission of Syslog Messages over TCP",
857
+ "url": "https://www.rfc-editor.org/rfc/rfc6587.html"
858
+ }
859
+ ]
860
+ },
861
+ {
862
+ "version": "0.6.32",
863
+ "date": "2026-05-02",
864
+ "headline": "`b.cache` Redis backend",
865
+ "sections": [
866
+ {
867
+ "heading": "Added",
868
+ "items": [
869
+ {
870
+ "title": "First-class `backend: \"redis\"` for `b.cache.create`",
871
+ "body": "New module `lib/cache-redis.js` consumes `lib/redis-client.js` directly with no operator-supplied glue. Storage layout: `<namespace>:e:<key>` STRING (JSON-encoded value, PEXPIREAT-bounded), `<namespace>:t:<tag>` SET (cacheKeys carrying that tag — powers `invalidateTag` fan-out), `<namespace>:k:<key>:tags` SET (tags this key carries — powers per-key tag cleanup on `del` / `set`-overwrite, expires alongside the entry). TTL is enforced by Redis itself (PEXPIREAT) so the framework's sweeper is a no-op for this backend; sliding TTL bumps the entry's expiry on every read when `slidingTtl: true` AND `ttlMs` is finite."
872
+ },
873
+ {
874
+ "title": "Redis cache opts",
875
+ "body": "New opts on `cache.create`: `redisUrl` (required when `backend: \"redis\"`), `redisPassword`, `redisUsername`, `redisTls`, `redisCa` (private-CA trust pinning), `redisServername`, `redisConnectTimeoutMs`, `redisCommandTimeoutMs`, `redisMaxReconnectAttempts`. Lazy connect — `cache.create({backend:\"redis\"})` stays sync-safe and the first op opens the socket. `invalidateTag` filters out ghost entries (key already PEXPIRE'd from the keyspace but lingering in a tag SET) by EXISTS-checking before del."
876
+ }
877
+ ]
878
+ }
879
+ ]
880
+ },
881
+ {
882
+ "version": "0.6.31",
883
+ "date": "2026-05-02",
884
+ "headline": "Redis queue priority + flow `dependsOn`; WebSocket per-message-deflate",
885
+ "sections": [
886
+ {
887
+ "heading": "Added",
888
+ "items": [
889
+ {
890
+ "title": "Redis queue priority ordering",
891
+ "body": "`b.queue.enqueue({ priority })` on the Redis backend now matches `queue-local`'s `ORDER BY priority DESC, availableAt ASC, enqueuedAt ASC` semantics. The Redis ZSET stays scored by availableAt only, but `LEASE_LUA` over-fetches `maxRows*5` candidates by score, HMGETs priority + availableAt + enqueuedAt for each, sorts server-side in Lua by the same triple, and leases the top `maxRows`."
892
+ },
893
+ {
894
+ "title": "Redis queue flow `dependsOn` cascade",
895
+ "body": "`b.queue.enqueue({ flowId, flowChildName, dependsOn })` on the Redis backend now releases dependent jobs when their parents complete, mirroring `_maybeReleaseFlowChildren` in `queue-local`. A per-flow `<prefix>:flow:<flowId>` Redis SET tracks every job in the flow; `complete()` walks the set, looks up siblings whose `dependsOn` matches the just-completed job (by id or `flowChildName`) AND every other dep is satisfied, and HSET-bumps their `availableAt` to now and ZADDs them into the ready zset."
896
+ },
897
+ {
898
+ "title": "WebSocket per-message-deflate (RFC 7692)",
899
+ "body": "`b.websocket.handleUpgrade` negotiates the `permessage-deflate` extension when the client offers it, accepting `client_max_window_bits` / `server_max_window_bits` (8-15, default 15) and always asserting `client_no_context_takeover` + `server_no_context_takeover` so every message uses fresh zlib state. Send path compresses TEXT/BINARY frames via `zlib.deflateRawSync`, strips the 4-byte `0x00 0x00 0xff 0xff` trailer per RFC 7692 §7.2.1, and sets RSV1 on the first frame. Receive path appends the trailer back and inflates via `zlib.inflateRawSync`. RSV1 on a continuation frame, RSV1 without negotiated extension, RSV2/RSV3 set, and decompressed payload exceeding `maxMessageBytes` all close with the appropriate RFC 6455 status. Operator opt-out: pass `permessageDeflate: false`."
900
+ }
901
+ ]
902
+ }
903
+ ],
904
+ "references": [
905
+ {
906
+ "label": "RFC 7692 — Compression Extensions for WebSocket",
907
+ "url": "https://www.rfc-editor.org/rfc/rfc7692.html"
908
+ }
909
+ ]
910
+ },
911
+ {
912
+ "version": "0.6.30",
913
+ "date": "2026-05-02",
914
+ "headline": "Wiki-app integration gate + framework follow-ups",
915
+ "sections": [
916
+ {
917
+ "heading": "Added",
918
+ "items": [
919
+ {
920
+ "title": "`scripts/test-wiki-integration.js`",
921
+ "body": "Boots `examples/wiki` against the docker-compose fixture stack (real Redis, MinIO, Mailpit, CoreDNS, NTP, mtls-ca) and drives every backend through the wiki's HTTP surface AND the underlying framework primitives — validates that each primitive routes through the configured backend (cache -> custom backend, queue -> Redis Streams, mail -> Mailpit SMTP, object-store -> MinIO SigV4, log-stream -> webhook receiver)."
922
+ },
923
+ {
924
+ "title": "Wiki test-only routes under `/test/*`",
925
+ "body": "Gated by `WIKI_INTEGRATION_TEST=1`, mounted before CSRF / staticServe so test POSTs don't have to round-trip a token cookie. Covers cache get/set/del, queue enqueue/size, mail send, object-store put/get, http-client fetch, log-stream emit, mtls-ca issue, ntp query, dns lookup, ssrf classify+check, plus `/test/diagnostic` exposing the active backend posture."
926
+ },
927
+ {
928
+ "title": "External-integration two-gate rule",
929
+ "body": "When a release diff touches a primitive that talks to an external service, operators run BOTH `scripts/test-integration.js` (per-primitive) AND `scripts/test-wiki-integration.js` (wiki app exercising the same backends end to end) before pushing. Documented in CONTRIBUTING.md and the release workflow. The smoke and wiki-e2e gates stay pure (no docker dependency)."
930
+ }
931
+ ]
932
+ },
933
+ {
934
+ "heading": "Fixed",
935
+ "items": [
936
+ {
937
+ "title": "`b.mtlsCa.create` auto-creates `dataDir`",
938
+ "body": "Now creates `opts.dataDir` with `mode: 0o700` if it doesn't exist (matches `b.logStream`'s local sink, `b.backup`, `b.restoreBundle`). Without it the first `initCA()` call hit `ENOENT` writing `ca.key.tmp`."
939
+ },
940
+ {
941
+ "title": "`b.logStream` webhook-sink close-order, revisited",
942
+ "body": "`close()` now waits for the in-flight `_flush()` before draining the buffer. The previous drain fix only tracked emit-time wrapper promises, not the actual HTTP POST in flight; a record arriving mid-flush would buffer, the emit-time `_flush` early-returned on `if (inFlight) return`, and shutdown would then strand it."
943
+ },
944
+ {
945
+ "title": "`b.queue.bootFromEnv()` wired in the wiki app",
946
+ "body": "The wiki app's `build-app.js` now calls `bootFromEnv()` unconditionally so the wiki picks up `BLAMEJS_QUEUE_PROTOCOL=redis` from env without code changes."
947
+ }
948
+ ]
949
+ }
950
+ ]
951
+ },
952
+ {
953
+ "version": "0.6.29",
954
+ "date": "2026-05-02",
955
+ "headline": "Shellcheck gate green and eslint pin alignment",
956
+ "sections": [
957
+ {
958
+ "heading": "Fixed",
959
+ "items": [
960
+ {
961
+ "title": "`docker/init/generate-certs.sh` line count",
962
+ "body": "The footer line counted output via `ls \"$CERT_DIR\" | wc -l` (SC2012, fragile on filenames with newlines or quoting metacharacters); replaced with `find \"$CERT_DIR\" -maxdepth 1 -mindepth 1 | wc -l`. Same semantics, robust to any cert filename pki-init might end up writing."
963
+ },
964
+ {
965
+ "title": "shellcheck added to the documented pre-push gate list",
966
+ "body": "CONTRIBUTING.md now lists shellcheck alongside smoke / wiki e2e / eslint / api-snapshot / primitive-section validators. CI's `Lint summary` job has always run it, but the local-dev recipe didn't, so contributors hit it after push instead of catching it locally."
967
+ },
968
+ {
969
+ "title": "eslint pin alignment",
970
+ "body": "`.github/PULL_REQUEST_TEMPLATE.md` and CONTRIBUTING.md still pinned `eslint@10` while CI runners had already swapped to `eslint@latest`; both are bumped to `@latest` to match the forward-track posture of every other CI tool."
971
+ }
972
+ ]
973
+ }
974
+ ]
975
+ },
976
+ {
977
+ "version": "0.6.28",
978
+ "date": "2026-05-02",
979
+ "headline": "Live integration test suite + framework bugs caught by it",
980
+ "sections": [
981
+ {
982
+ "heading": "Added",
983
+ "items": [
984
+ {
985
+ "title": "`test/integration/` suite + docker-compose stack",
986
+ "body": "13 live test files covering Redis (plain + TLS), `b.queue` on Redis, `b.mail` SMTP / STARTTLS / multi-rcpt / dot-stuffing, `b.mail.dkim` rsa-sha256 + ed25519-sha256 + bad-algorithm reject, `b.ntpCheck` v4 + v6 + bootCheck, `b.network.dns` plain + DoT + DoH with strict CA pinning + bad-servername + cache, `b.network.heartbeat` http + tcp + state-change callbacks, `b.objectStore` SigV4 on plain HTTP + TLS, `b.cache` memory + Redis-backed cluster, `b.httpClient` direct + Squid forward proxy + TLS pin, `b.ssrfGuard` classify + checkUrl + cloud-metadata block, `b.logStream` local + webhook + deferred-syslog error path, and `b.mtlsCa` CA bootstrap + clientAuth + serverAuth + dual-EKU. Companion `docker-compose.test.yml` stands up redis (plain + TLS), postgres, mysql, mongo, minio (HTTP + HTTPS), rabbitmq (plain + TLS), nats, syslog, ntp, mailpit, coredns (plain + DoT + DoH), haproxy, caddy, mitmproxy, squid, and pki-init. Host port bindings dual-stack on `127.0.0.1` AND `[::1]`. `scripts/test-integration.js` exports the test CA via `docker cp` and sets `NODE_EXTRA_CA_CERTS` per-test child process; no `rejectUnauthorized: false` bypass anywhere."
987
+ }
988
+ ]
989
+ },
990
+ {
991
+ "heading": "Fixed",
992
+ "items": [
993
+ {
994
+ "title": "`b.ssrfGuard.checkUrl` cloud-metadata hard-deny",
995
+ "body": "`allowInternal: true` no longer permits 169.254.169.254 (AWS / GCP / Azure metadata). Loopback / private / link-local / reserved stay overridable per existing semantics; cloud-metadata is unconditional because a blanket override would let any compromised request exfiltrate instance credentials."
996
+ },
997
+ {
998
+ "title": "`b.mtlsCa` issues server certs and dual-EKU certs",
999
+ "body": "`generateClientCert({ usage: \"client\" | \"server\" | \"both\", sans: [...] })`: `usage` controls EKU (`client` = clientAuth, `server` = serverAuth, `both` = both); `sans` accepts `DNS:` / `IP:` / bare-DNS entries; serverAuth without an explicit SAN auto-adds the CN. Operators wiring inbound mTLS reverse-proxy fronts no longer hit `unsuitable certificate purpose` on the handshake."
1000
+ },
1001
+ {
1002
+ "title": "`b.mtlsCa` algorithm auto-detect",
1003
+ "body": "Probes webcrypto plus the vendored x509 library at first cert issuance and picks the highest-PQC option that round-trips: SLH-DSA-SHAKE-256f -> SLH-DSA-SHAKE-128f -> ML-DSA-87 -> ML-DSA-65 -> ECDSA-P384-SHA384. When the bridge condition lifts the same `b.mtlsCa.create(...)` call self-upgrades; `b.mtlsCa.status().cert.label` and `.posture` surface the chosen algorithm."
1004
+ },
1005
+ {
1006
+ "title": "`b.redisClient.create({ ca, servername })`",
1007
+ "body": "Managed-Redis and on-prem-cluster operators connecting over `rediss://` against a private CA can pin trust roots. `servername` auto-suppresses for IP literals so `rediss://127.0.0.1:6380` no longer trips Node's IP-as-SNI rule."
1008
+ },
1009
+ {
1010
+ "title": "DoT / DoH accept a `ca` opt",
1011
+ "body": "`b.network.dns.useDnsOverTls` and `useDnsOverHttps` accept a `ca` opt for the same trust-pinning surface against self-signed / private-PKI endpoints."
1012
+ },
1013
+ {
1014
+ "title": "DoT handshake errors and socket lifecycle",
1015
+ "body": "DoT TLS handshake errors now route as `DnsError` on the lookup promise rather than leaking as `unhandledRejection`. The DoT socket is now ref'd while a query is in flight and unref'd when idle, so Node doesn't exit during an in-flight lookup."
1016
+ },
1017
+ {
1018
+ "title": "`b.ntpCheck.querySingle` honors IPv6 servers",
1019
+ "body": "Previously hardcoded to `dgram.createSocket(\"udp4\")` — `::1` and `fd00::...` queries failed with `EINVAL`. Family is now auto-detected from the server string."
1020
+ },
1021
+ {
1022
+ "title": "`b.logStream.shutdown` drains in-flight emits",
1023
+ "body": "`shutdown` now drains in-flight emit microtasks before closing sink fds; fire-and-forget emits queued just before shutdown were previously dropped."
1024
+ },
1025
+ {
1026
+ "title": "`b.logStream` webhook-sink close-order",
1027
+ "body": "`close()` flushes before setting `closed = true` — `_flush`'s while loop bailed on `!closed`, leaving any records buffered just before shutdown stranded."
1028
+ }
1029
+ ]
1030
+ }
1031
+ ]
1032
+ },
1033
+ {
1034
+ "version": "0.6.27",
1035
+ "date": "2026-05-02",
1036
+ "headline": "Redis backend for `b.queue`",
1037
+ "summary": "Multi-replica apps can share a single queue without each needing to be cluster leader.",
1038
+ "sections": [
1039
+ {
1040
+ "heading": "Added",
1041
+ "items": [
1042
+ {
1043
+ "title": "Bespoke RESP2 client",
1044
+ "body": "`lib/redis-client.js` is zero-npm-dep: TCP via `node:net` and TLS via `node:tls` (`rediss://` auto-detected), legacy single-arg AUTH plus ACL `AUTH user pass`, `SELECT db`, pipelining, exponential-backoff reconnect, and an EVAL helper."
1045
+ },
1046
+ {
1047
+ "title": "`b.queue` Redis protocol",
1048
+ "body": "`lib/queue-redis.js` ships full `enqueue` / `lease` / `extendLease` / `complete` / `fail` / `sweepExpired` / `size` / `purge` / `dlqList` / `dlqRetry` / `dlqSize` parity with the local backend. Atomicity comes from server-side Lua scripts so concurrent consumers can't double-lease and a sweep can't race a complete. Storage: per-job HASH (sealed payload and `lastError` via `cryptoField.sealRow`), per-queue ready ZSET scored by `availableAt`, per-queue inflight ZSET scored by `leaseExpiresAt`, per-queue dlq ZSET scored by `finishedAt`, plus a queues SET so `sweepExpired` walks every known queue without a global secondary index. Cron-repeat handled in `complete()` JS — re-enqueues the next firing as a fresh `jobId` with `availableAt` set to the next cron fire."
1049
+ },
1050
+ {
1051
+ "title": "`b.queue.bootFromEnv({ env })`",
1052
+ "body": "Env-driven init mirroring `b.network.bootFromEnv` and `b.logStream.bootFromEnv`. Reads `BLAMEJS_QUEUE_PROTOCOL` (`local` or `redis`), `BLAMEJS_QUEUE_REDIS_URL`, `BLAMEJS_QUEUE_REDIS_PASSWORD`, `BLAMEJS_QUEUE_REDIS_USERNAME`, `BLAMEJS_QUEUE_REDIS_TLS`, and `BLAMEJS_QUEUE_REDIS_KEY_PREFIX`. Operators flip from local to Redis without a code change; both wiki docker-compose configs declare the new env knobs."
1053
+ }
1054
+ ]
1055
+ },
1056
+ {
1057
+ "heading": "Removed",
1058
+ "items": [
1059
+ {
1060
+ "title": "`redis` removed from `DEFERRED_PROTOCOLS`",
1061
+ "body": "The Redis queue backend is first-class and no longer listed as a deferred protocol."
1062
+ }
1063
+ ]
1064
+ }
1065
+ ]
1066
+ },
1067
+ {
1068
+ "version": "0.6.26",
1069
+ "date": "2026-05-02",
1070
+ "headline": "CLI subcommands for restore and audit chain verification",
1071
+ "sections": [
1072
+ {
1073
+ "heading": "Added",
1074
+ "items": [
1075
+ {
1076
+ "title": "`blamejs restore`",
1077
+ "body": "`list` enumerates bundles in storage, `inspect` reads the manifest summary without touching live data, `apply` runs an in-place restore preserving rollback, `rollback` reverts to the most-recent or named restore point, and `list-rollbacks` enumerates preserved rollback points. Operators identify a bundle via `--bundle <dir>` (matching what `blamejs backup extract` produces) or `--storage-root <root> --bundle-id <id>`. `apply` honors `--max-pulled-bytes` / `--max-pulled-files` (defaults 4 GiB / 100K), `--rollback-root` (default `<data-dir>.rollbacks`), `--no-audit`, and `BLAMEJS_BACKUP_PASSPHRASE`."
1078
+ },
1079
+ {
1080
+ "title": "`blamejs audit verify-chain`",
1081
+ "body": "Walks the live audit chain end to end, reports tampering with `breakAt` / `breakRowId` / expected-versus-actual `prevHash`, and honors `--max-rows` for bounded walks. Default table is `audit_log`."
1082
+ },
1083
+ {
1084
+ "title": "Wiki CLI snapshot validates subcommand pairs",
1085
+ "body": "The wiki CLI snapshot test now walks every wiki and README invocation of the form `blamejs <cmd> <sub>` and verifies `<sub>` exists in the perCommand[<cmd>].subcommands list parsed from `lib/cli.js`. Surfaced drift on first run: `backup-restore.js` referenced `blamejs audit verify-signing` which never existed (only `verify-bundle`); the wiki now references the newly shipped `verify-chain`. README CLI table updated with the `restore` row and the two new audit subcommands."
1086
+ }
1087
+ ]
1088
+ }
1089
+ ]
1090
+ },
1091
+ {
1092
+ "version": "0.6.25",
1093
+ "date": "2026-05-02",
1094
+ "headline": "`b.logStream` CloudWatch Logs sink + framework-level env wiring",
1095
+ "sections": [
1096
+ {
1097
+ "heading": "Added",
1098
+ "items": [
1099
+ {
1100
+ "title": "CloudWatch Logs sink",
1101
+ "body": "`protocol: \"cloudwatch\"` POSTs `PutLogEvents` over HTTPS with SigV4 signing (service `logs`). Operator pre-creates the log group and log stream (the framework does not auto-create here). Honors IAM role and STS session-token credentials. Respects all three CloudWatch caps automatically (10,000 events, 1 MiB total payload, 256 KiB per event); per-event oversize is dropped at `emit()` with `onDrop` fired carrying the truncated message; per-batch oversize splits mid-flush. Permanent AWS errors (`ResourceNotFoundException` / `AccessDeniedException` / `InvalidParameterException` / `UnrecognizedClientException` / `SerializationException`) skip the retry budget. `InvalidSequenceTokenException` (legacy CW accounts) extracts the expected token from the error message and retries with it once."
1102
+ },
1103
+ {
1104
+ "title": "`b.logStream.bootFromEnv({ env })`",
1105
+ "body": "Framework-level env-driven init mirroring `b.network.bootFromEnv`. Reads `BLAMEJS_LOG_STREAM_PROTOCOL` (`local` / `webhook` / `otlp` / `cloudwatch`), `BLAMEJS_LOG_STREAM_URL`, `BLAMEJS_LOG_STREAM_TOKEN`, `BLAMEJS_LOG_STREAM_SERVICE_NAME`, `BLAMEJS_LOG_STREAM_SERVICE_VERSION`, `BLAMEJS_LOG_STREAM_CLOUDWATCH_LOG_GROUP`, `BLAMEJS_LOG_STREAM_CLOUDWATCH_LOG_STREAM`, `BLAMEJS_LOG_STREAM_PATH`, plus standard `AWS_*` knobs. Operators get a working sink without writing build-app code; the wiki app's `build-app.js` replaces its inline env-reading with one call."
1106
+ },
1107
+ {
1108
+ "title": "Wiki env-snapshot test",
1109
+ "body": "Parallel to `api-snapshot.json` — walks `process.env.X` / `env.X` / `safeEnv.readVar(\"X\")` reads in the wiki app and framework `lib/`, walks docker-compose env declarations, and captures the union as `examples/wiki/env-snapshot.json`. Fails the e2e gate when env vars are added or removed without updating the snapshot, or when source-only / compose-only gaps appear. Surfaced 13 real gaps in the wiki app on first run; all 13 fixed. Update workflow: `BLAMEJS_UPDATE_ENV_SNAPSHOT=1 node examples/wiki/test/validate-env-snapshot.js`."
1110
+ }
1111
+ ]
1112
+ },
1113
+ {
1114
+ "heading": "Changed",
1115
+ "items": [
1116
+ {
1117
+ "title": "`object-store/sigv4.js` `signRequest` is service-agnostic",
1118
+ "body": "Accepts `opts.service` (default still `\"s3\"` for back-compat) so the CloudWatch sink and any future SigV4-protobuf service can share the signer."
1119
+ }
1120
+ ]
1121
+ }
1122
+ ]
1123
+ },
1124
+ {
1125
+ "version": "0.6.24",
1126
+ "date": "2026-05-02",
1127
+ "headline": "`b.logStream` OTLP/HTTP-JSON sink",
1128
+ "sections": [
1129
+ {
1130
+ "heading": "Added",
1131
+ "items": [
1132
+ {
1133
+ "title": "OTLP/HTTP-JSON log sink",
1134
+ "body": "`protocol: \"otlp\"` forwards log records to any OpenTelemetry collector via the OTel Logs Data Model — `resourceLogs` -> `scopeLogs` -> `logRecords` envelope with `severityNumber` (debug=5 / info=9 / warn=13 / error=17), `severityText`, `timeUnixNano` (string-encoded for JSON-safe 64-bit), `body.stringValue`, and OTel-typed attributes. Operator opts: `{ url, serviceName, serviceVersion, resourceAttributes, auth, headers, batchSize, retry, onDrop, ... }`. Same back-pressure semantics as the webhook sink (per-sink ring buffer, batched flush on size or `maxBatchAgeMs`, exponential-backoff retry, drop-on-overflow with operator-supplied `onDrop`). URL convention: `/v1/logs` is auto-appended when the operator passes the collector root. JSON not protobuf — operators benchmarking past 100K logs per second ship the OTel Collector locally so the framework hands JSON to a sidecar that forwards via gRPC."
1135
+ }
1136
+ ]
1137
+ },
1138
+ {
1139
+ "heading": "Removed",
1140
+ "items": [
1141
+ {
1142
+ "title": "`otlp` removed from `DEFERRED_PROTOCOLS`",
1143
+ "body": "The OTLP sink is now first-class and no longer listed as a deferred protocol."
1144
+ }
1145
+ ]
1146
+ }
1147
+ ]
1148
+ },
1149
+ {
1150
+ "version": "0.6.23",
1151
+ "date": "2026-05-02",
1152
+ "headline": "Cron-repeat call site cleaned up; `enqueue` scheduling precedence documented",
1153
+ "sections": [
1154
+ {
1155
+ "heading": "Changed",
1156
+ "items": [
1157
+ {
1158
+ "title": "Cron-repeat passes `availableAt` alone",
1159
+ "body": "The cron-repeat call site in `queue-local.js` was passing both `availableAt` and a redundant `delaySeconds = Math.floor((nextMs - nowMs) / 1000)` that only existed to work around the bug fixed in the previous release. The redundant arg is removed; cron repeat now passes `availableAt` alone, matching the queue's documented precedence rule."
1160
+ },
1161
+ {
1162
+ "title": "Scheduling-precedence docstring",
1163
+ "body": "`enqueue()` gains a 20-line scheduling-precedence header documenting that `opts.availableAt` wins over `opts.delaySeconds` when both are passed, why the framework chose that direction, and which callers should use which form."
1164
+ }
1165
+ ]
1166
+ },
1167
+ {
1168
+ "heading": "Added",
1169
+ "items": [
1170
+ {
1171
+ "title": "Round-trip preservation regression test",
1172
+ "body": "`testEnqueueRoundTripsAvailableAt` covers three precise targets, the delaySeconds-only path, and the both-opts-set case so any future attempt to rederive `availableAt` from floored seconds fails the gate."
1173
+ }
1174
+ ]
1175
+ }
1176
+ ]
1177
+ },
1178
+ {
1179
+ "version": "0.6.22",
1180
+ "date": "2026-05-02",
1181
+ "headline": "`b.queue.enqueue({ availableAt })` honored on the local backend",
1182
+ "sections": [
1183
+ {
1184
+ "heading": "Fixed",
1185
+ "items": [
1186
+ {
1187
+ "title": "Local enqueue honors `opts.availableAt`",
1188
+ "body": "Previously the local-protocol enqueue ignored `opts.availableAt` and recomputed availableAt from `Date.now() + delaySeconds * 1000`. The cron-repeat path passes both fields (the exact next-fire ms in `availableAt`, the floored seconds in `delaySeconds`); the enqueue's recomputation lost sub-second precision and drifted on the internal clock-versus-caller delta. Symptoms: cron-scheduled jobs landed up to 999ms off the intended boundary, and the queue-flow-repeat smoke test was intermittently flaky on slow CI runners. Enqueue now honors `opts.availableAt` directly when finite and falls back to delaySeconds-based shorthand otherwise."
1189
+ }
1190
+ ]
1191
+ }
1192
+ ]
1193
+ },
1194
+ {
1195
+ "version": "0.6.21",
1196
+ "date": "2026-05-02",
1197
+ "headline": "Cluster-cache `invalidateTag`, multi-column cursor pagination, DoH POST, DoT pooling, INI parser, persistent cookie jar",
1198
+ "sections": [
1199
+ {
1200
+ "heading": "Added",
1201
+ "items": [
1202
+ {
1203
+ "title": "Cluster-cache `invalidateTag` and `getTags`",
1204
+ "body": "The cluster cache backend gains a `_blamejs_cache_tags` junction table (`(cacheKey, tag)` primary key, index on `tag`) and tag-aware `set` / `del` / `clear` / `_sweep` plus `getTags(key)`. Multi-tag rotation, mid-flight tag replacement on update, and namespace-scoped sweeps are all covered. The previous `NOT_SUPPORTED` path on cluster is gone."
1205
+ },
1206
+ {
1207
+ "title": "Multi-column cursor pagination",
1208
+ "body": "`b.pagination.cursor({ orderBy: [{column, direction}, ...] })` accepts a string, an array of strings, or an array of `{column, direction}` objects. The keyset `WHERE` expands to the standard OR cascade so successive pages can't skip or repeat rows when ties on the leading columns are broken by trailing ones. `_id` is appended as a tiebreaker when not in the chain. Chained `orderBy(col, dir)` calls on the Query class extend a multi-column `ORDER BY` in the SQL. The cursor format is bumped to encode `{ orderKey, vals, forward }` — pre-1.0 break with no compat shim."
1209
+ },
1210
+ {
1211
+ "title": "DoH POST mode",
1212
+ "body": "`b.network.dns.useDnsOverHttps({ method })` accepts `\"GET\" | \"POST\" | undefined` (auto). Auto switches to POST when the GET URL would exceed 2048 bytes, covering long DNS names per RFC 8484 §4.1."
1213
+ },
1214
+ {
1215
+ "title": "DoT connection pooling",
1216
+ "body": "Per-`(host:port)` cached TLS socket with a 2-minute idle timeout, serialized in-flight queries per socket. Eliminates the per-query TLS handshake."
1217
+ },
1218
+ {
1219
+ "title": "`b.parsers.ini`",
1220
+ "body": "Covers Windows `.ini`, `.gitconfig`, systemd-unit, `php.ini`, and `tox.ini` shapes: sections (including `[parent.child]` and `[parent \"child\"]` nesting), `;` and `#` comments (inline and leading), single and double quoting with `\\n` / `\\t` / `\\\\` / `\\\"` / `\\'` escapes, boolean coercion, and decimal / hex / float numerics. Prototype-pollution defense (`__proto__` / `constructor` / `prototype` rejected). Duplicate-key policy throws by default; `onDuplicate: \"first\" | \"last\"` opts in to silent shadowing. Section, per-section key, and value-bytes caps are configurable."
1221
+ },
1222
+ {
1223
+ "title": "Cookie-jar file persistence",
1224
+ "body": "`b.httpClient.cookieJar.create({ persist: \"file\", file: \"/abs/path\", vault: b.vault })` loads at construct, debounce-flushes on every set / clear, plus `flush()` and `close()` for explicit lifecycle. With `vault`, on-disk bytes are sealed; without, plaintext JSON (operator chooses)."
1225
+ }
1226
+ ]
1227
+ },
1228
+ {
1229
+ "heading": "Changed",
1230
+ "items": [
1231
+ {
1232
+ "title": "Internal-narrative cleanup in operator-facing source",
1233
+ "body": "Comments in `vault/index.js`, `mail.js`, `bundler.js`, `archive.js`, `framework-schema.js`, and `http-client.js` are rewritten to describe what's actually shipped, dropping internal-process narrative."
1234
+ },
1235
+ {
1236
+ "title": "README CLI section refreshed",
1237
+ "body": "The CLI section is updated to reflect the additions from the four previous releases (security, config-drift, file-type, password, erase, retention) which were missing six subcommands."
1238
+ }
1239
+ ]
1240
+ }
1241
+ ],
1242
+ "references": [
1243
+ {
1244
+ "label": "RFC 8484 — DNS over HTTPS",
1245
+ "url": "https://www.rfc-editor.org/rfc/rfc8484.html"
1246
+ }
1247
+ ]
1248
+ },
1249
+ {
1250
+ "version": "0.6.20",
1251
+ "date": "2026-05-02",
1252
+ "headline": "SBOM bundled into npm tarball; release-attach step made non-fatal",
1253
+ "summary": "The npm-publish workflow's `gh release upload` step started failing with HTTP 422 against an already-published immutable release; the SBOM is now the canonical npm-tarball artifact and the GitHub release attachment is supplementary.",
1254
+ "sections": [
1255
+ {
1256
+ "heading": "Changed",
1257
+ "items": [
1258
+ {
1259
+ "title": "`sbom.cyclonedx.json` bundled into the npm tarball",
1260
+ "body": "`sbom.cyclonedx.json` is now declared in `package.json` `files`, so `npm install @blamejs/core && cat node_modules/@blamejs/core/sbom.cyclonedx.json` is the canonical SBOM access path. The prepack guard's known-allowed list covers the just-in-time generation."
1261
+ },
1262
+ {
1263
+ "title": "Release-asset attach step made non-fatal",
1264
+ "body": "The workflow's GitHub-release attach step tries to upload, logs a warning if the release is immutable, and lets the publish proceed regardless. The npm tarball is the load-bearing artifact; the GitHub release attachment was only ever supplementary."
1265
+ },
1266
+ {
1267
+ "title": "`.gitignore` adds `sbom.cyclonedx.json`",
1268
+ "body": "A stray local `npm sbom` no longer pollutes the working tree."
1269
+ }
1270
+ ]
1271
+ }
1272
+ ]
1273
+ },
1274
+ {
1275
+ "version": "0.6.19",
1276
+ "date": "2026-05-02",
1277
+ "headline": "NTS reply verification, common-password bundle, TLS trust rotation, and DNS protocol fidelity",
1278
+ "sections": [
1279
+ {
1280
+ "heading": "Fixed",
1281
+ "items": [
1282
+ {
1283
+ "title": "`b.network.ntp.nts.querySingle` now verifies the server reply",
1284
+ "body": "Extracts the AUTHENTICATOR_AND_ENC extension, AEAD-decrypts with AAD equal to the bytes before the authenticator, and fails closed (`nts/auth-failed` / `nts/no-authenticator`) when verification fails. Server-supplied new cookies in the encrypted plaintext are appended to the cookie pool and the consumed cookie popped (real RFC 8915 cookie rotation). Previously the function returned `authenticated: true` while only checking the unique-identifier echo — any MITM that mirrored the request's 32-byte unique field could spoof timestamps."
1285
+ },
1286
+ {
1287
+ "title": "`azure-blob.presignedUploadPolicy` no longer silently misroutes",
1288
+ "body": "Now throws `PRESIGN_NOT_SUPPORTED` instead of returning a SAS PUT URL when operators asked for POST policy semantics — Azure SAS has no body-size cap and the previous shape was a misleading mismatch. The error message points at `presignedUploadUrl` plus a post-upload HEAD as the alternative."
1289
+ },
1290
+ {
1291
+ "title": "DoT handshake errors route as `DnsError`",
1292
+ "body": "The secureConnect / error event-listener race had let cert-verification failures escape the per-query Promise wrapping and surface as `unhandledRejection`. Now every lookup-level error routes back through the per-query promise."
1293
+ },
1294
+ {
1295
+ "title": "DoT socket lifecycle",
1296
+ "body": "Previously the DoT socket was unconditionally `sock.unref()`'d after construct, causing node to exit during in-flight lookups when no other I/O kept the loop alive. It is now ref'd while a query is in flight and unref'd when idle."
1297
+ },
1298
+ {
1299
+ "title": "`b.network.dns` resolver methods use real DNS queries",
1300
+ "body": "`resolve4` / `resolve6` / `resolveAaaa` were aliasing `lookup()`; they now use `dns.promises.resolve4` / `_dohLookup` / `_dotLookup` so semantics match Node's standard library (skips `/etc/hosts`, mDNS)."
1301
+ },
1302
+ {
1303
+ "title": "`b.network.dns.setResultOrder` covers DoH and DoT",
1304
+ "body": "Previously the order setting only sorted OS-resolver results; it now flips the order on the DoH / DoT dual-stack fallback paths as well."
1305
+ },
1306
+ {
1307
+ "title": "Network error-construction argument order corrected",
1308
+ "body": "Every `new XxxError(...)` call across `lib/network*.js` was passing args in the wrong order (message-then-code instead of code-then-message), making `e.code` return human messages and `e.message` return slash-codes. Operators relying on `e.code` for error handling got the wrong field. All affected throws across `lib/network.js`, `network-dns.js`, `network-proxy.js`, `network-tls.js`, `network-heartbeat.js`, and `network-nts.js` are corrected."
1309
+ }
1310
+ ]
1311
+ },
1312
+ {
1313
+ "heading": "Added",
1314
+ "items": [
1315
+ {
1316
+ "title": "`b.auth.password.policy` bundled common-password list",
1317
+ "body": "The SecLists top-10000 common-password list is bundled (CC-BY-3.0, `lib/vendor/common-passwords-top-10000.txt`) and loaded lazily on first `policy.check()`. Passwords like `password`, `dragon`, and `qwerty` now reject with `policy/forbidden-common`. `useBundledCommon: false` per-policy bypasses if operator ships their own list."
1318
+ },
1319
+ {
1320
+ "title": "`b.network.tls` CA-rotation surface",
1321
+ "body": "`removeCa(fingerprint256)`, `removeCaByLabel(label)`, `clearAll()`, `purgeExpired()`, and `expiringSoon(windowMs)` let operators rotate corporate DPI CAs without process restart. Every removal audits with subject + fingerprint + reason."
1322
+ }
1323
+ ]
1324
+ },
1325
+ {
1326
+ "heading": "Removed",
1327
+ "items": [
1328
+ {
1329
+ "title": "`b.network.socket.setDefaultLinger` removed",
1330
+ "body": "Previously a silent no-op; now throws `socket/linger-not-supported` with operator guidance to use `socket.destroy()` (abort) versus `socket.end()` (graceful) since Node's public `net.Socket` has no `setLinger()`."
1331
+ }
1332
+ ]
1333
+ },
1334
+ {
1335
+ "heading": "Security",
1336
+ "items": [
1337
+ {
1338
+ "title": "`.gitleaks.toml` smoke + workflow alignment",
1339
+ "body": "`.gitleaks.toml` adds `test/smoke.js` to the path allowlist and pins the historical commit + fingerprint that tripped the jwt rule on a `REDACTED` placeholder. `npm-publish.yml` job permissions bumped from `contents: read` to `contents: write` so `gh release upload sbom.cyclonedx.json` no longer 403s."
1340
+ }
1341
+ ]
1342
+ }
1343
+ ]
1344
+ },
1345
+ {
1346
+ "version": "0.6.18",
1347
+ "date": "2026-05-02",
1348
+ "headline": "`b.network` namespace covering NTP / DNS / proxy / TLS trust / heartbeat / socket / env boot",
1349
+ "summary": "A single namespace covering every runtime-configurable network behaviour the framework owns: authenticated time, operator-pinned DNS resolvers, HTTP/HTTPS proxy honoring, runtime-overridable trust store for DPI-fronted deploys, application-level heartbeats, socket-default tuning, and env-driven boot.",
1350
+ "sections": [
1351
+ {
1352
+ "heading": "Added",
1353
+ "items": [
1354
+ {
1355
+ "title": "`b.network.ntp` with NTS-KE authenticated time",
1356
+ "body": "Tunable warn / fatal drift thresholds with env-var bindings (`BLAMEJS_NTP_SERVERS`, `BLAMEJS_NTP_TIMEOUT_MS`, `BLAMEJS_NTP_DRIFT_WARN_MS`, `BLAMEJS_NTP_DRIFT_FATAL_MS`). `b.network.ntp.nts.query(opts)` performs an NTS-KE handshake (RFC 8915) over TLS 1.3 with the framework's PQC-hybrid group preference, extracts C2S / S2C keys via the standard TLS exporter, and authenticates NTPv4 packets with AES-SIV-CMAC-256 or AEAD-CHACHA20-POLY1305 — no extra vendored deps."
1357
+ },
1358
+ {
1359
+ "title": "`b.network.dns` operator-pinned resolvers, family + ordering, DoH / DoT",
1360
+ "body": "Exposes operator-pinned resolvers, IPv4 / IPv6 / dual-stack family selection, `ipv4first` / `verbatim` / `ipv6first` ordering, DNS lookup timeout (Node's native `dns.lookup` has none), in-memory positive and negative cache, and DoH / DoT (cloudflare / google / quad9 / custom URL). `b.ssrfGuard` and `b.httpClient` route through it when configured."
1361
+ },
1362
+ {
1363
+ "title": "`b.network.proxy` honors the standard env knobs",
1364
+ "body": "Honors `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` / `ALL_PROXY` (lower- and upper-case) with CIDR + suffix + wildcard `NO_PROXY` matching, basic-auth via `BLAMEJS_PROXY_AUTH`, and CONNECT tunnels for HTTPS through HTTP proxies; `b.httpClient` picks up the agent automatically."
1365
+ },
1366
+ {
1367
+ "title": "`b.network.tls` runtime-overridable trust store",
1368
+ "body": "`addCa(pemOrPath)` / `addCaBundle(path)` / `useSystemTrust()` / `getTrustStore()` for deep-packet-inspection deploys behind Zscaler / Netskope / corporate Squid with custom CA. Node's `NODE_EXTRA_CA_CERTS` only works at boot; this primitive accepts adds at any time and `b.pqcAgent` picks them up immediately. Every `addCa` audits with subject + issuer + fingerprint256 + validity + isSelfSigned. `b.security.assertProduction({ allowDpiTrust })` refuses to boot in production with installed CAs unless explicitly allowed."
1369
+ },
1370
+ {
1371
+ "title": "`b.network.heartbeat` application-level liveness probes",
1372
+ "body": "HTTP / TCP / NTP probe types, a healthy -> degraded -> down state machine with consecutive-failure threshold, audit on state change, and observability counters per probe."
1373
+ },
1374
+ {
1375
+ "title": "`b.network.socket` defaults",
1376
+ "body": "Operator-tunable defaults for `TCP_NODELAY`, `SO_KEEPALIVE`, and `SO_LINGER`."
1377
+ },
1378
+ {
1379
+ "title": "`b.network.bootFromEnv()`",
1380
+ "body": "Reads every supported env var at startup and applies in the right order so configuration takes effect before the first outbound socket. The wiki app's docker-compose configs ship every knob with a default-empty value; the production overlay tightens DNS lookup timeout, cache TTL, `NTP_STRICT=1`, and `SOCKET_NO_DELAY=1`."
1381
+ }
1382
+ ]
1383
+ },
1384
+ {
1385
+ "heading": "Fixed",
1386
+ "items": [
1387
+ {
1388
+ "title": "`.gitleaks.toml` allowlisted in dotfile policy",
1389
+ "body": "Previously gitignored by the deny-all-dotfiles allowlist, so CI's secret-scan job failed loading the framework's allowlist with `.gitleaks.toml: no such file or directory`. The file is now explicitly allowlisted."
1390
+ }
1391
+ ]
1392
+ }
1393
+ ],
1394
+ "references": [
1395
+ {
1396
+ "label": "RFC 8915 — NTS for NTP",
1397
+ "url": "https://www.rfc-editor.org/rfc/rfc8915.html"
1398
+ }
1399
+ ]
1400
+ },
1401
+ {
1402
+ "version": "0.6.17",
1403
+ "date": "2026-05-02",
1404
+ "headline": "Six new CLI subcommands wrapping the v0.6.14 primitives",
1405
+ "summary": "Operators can now drive the v0.6.14 security / config-drift / file-type / password / erase / retention primitives from runbooks, cron, and one-off ops without writing app code.",
1406
+ "sections": [
1407
+ {
1408
+ "heading": "Added",
1409
+ "items": [
1410
+ {
1411
+ "title": "`blamejs security assert`",
1412
+ "body": "Boots the framework and runs `b.security.assertProduction()` against the live posture, aggregating every failure with its code. Exits 1 on any failure."
1413
+ },
1414
+ {
1415
+ "title": "`blamejs config-drift inspect/verify`",
1416
+ "body": "Reads the signed sidecar without rebooting. `verify` exits 1 on tamper or missing sidecar so it composes into supervisord/cron health gates."
1417
+ },
1418
+ {
1419
+ "title": "`blamejs file-type detect <file>`",
1420
+ "body": "Magic-byte content classification with `--allowlist` for upload debugging — pure utility, no framework boot needed."
1421
+ },
1422
+ {
1423
+ "title": "`blamejs password check --plaintext \"...\"`",
1424
+ "body": "Tests `b.auth.password.policy` with `--profile pci-4.0` / `nist-aal2` / `hipaa-aal2`, `--breach-check` for HIBP, and `--email` / `--username` context. Pure utility."
1425
+ },
1426
+ {
1427
+ "title": "`blamejs erase --table X --row-id Y --confirm`",
1428
+ "body": "One-off cryptographic erasure for GDPR Art. 17 — replaces sealed columns and derived hashes with NULL and audits via `system.erase`."
1429
+ },
1430
+ {
1431
+ "title": "`blamejs retention preview/run`",
1432
+ "body": "Ad-hoc rule from CLI flags: `--table` + `--age-field` + `--ttl-ms` + `--action`, with `preview` for dry-run reporting."
1433
+ }
1434
+ ]
1435
+ },
1436
+ {
1437
+ "heading": "Fixed",
1438
+ "items": [
1439
+ {
1440
+ "title": "Per-subcommand `--help` now reaches each handler's USAGE block",
1441
+ "body": "The previous `main()` dispatch short-circuited every `<sub> --help` to the top-level help text. The fix applies to all existing subcommands too (`api-key --help`, `vault --help`, etc.)."
1442
+ }
1443
+ ]
1444
+ },
1445
+ {
1446
+ "heading": "Changed",
1447
+ "items": [
1448
+ {
1449
+ "title": "`b.dualControl` intentionally NOT exposed in the CLI",
1450
+ "body": "Its grants live in an operator-supplied `b.cache` instance the CLI can't bind to without operator wiring; admins approve / revoke from the operator's app instead."
1451
+ },
1452
+ {
1453
+ "title": "Hadolint action pin",
1454
+ "body": "Pinned to `@master` because the published `@v3` floating tag doesn't exist; the maintainer ships only patch tags plus master."
1455
+ }
1456
+ ]
1457
+ }
1458
+ ]
1459
+ },
1460
+ {
1461
+ "version": "0.6.16",
1462
+ "date": "2026-05-02",
1463
+ "headline": "CI secret-scan + action pin forward-track posture",
1464
+ "summary": "The CI secret-scan job switches off `gitleaks/gitleaks-action` (which began requiring a paid license for organization repositories) and installs the OSS gitleaks binary directly. Other CI tooling pins move to floating refs so security improvements ship automatically.",
1465
+ "sections": [
1466
+ {
1467
+ "heading": "Changed",
1468
+ "items": [
1469
+ {
1470
+ "title": "Secret-scan job uses the OSS gitleaks binary",
1471
+ "body": "Replaces `gitleaks/gitleaks-action` (paid `GITLEAKS_LICENSE` requirement for org repos, which had broken the v0.6.14 publish workflow) with a direct install of the Apache-2.0 OSS binary. The job resolves the latest release at job time so new ruleset improvements ship automatically."
1472
+ },
1473
+ {
1474
+ "title": "CI tool pins moved to floating refs",
1475
+ "body": "`aquasecurity/trivy-action` swaps from `@v0.36.0` to `@master`; `hadolint/hadolint-action` from `@v3.3.0` to the `@v3` major tag; `ludeeus/action-shellcheck` from `@2.0.0` to `@master`; the ESLint runner moves from `eslint@10` to `eslint@latest` in both `ci.yml` and `npm-publish.yml`. The pinning posture matches every other security-aware CI tool — silent pinning lets security improvements be missed."
1476
+ }
1477
+ ]
1478
+ },
1479
+ {
1480
+ "heading": "Security",
1481
+ "items": [
1482
+ {
1483
+ "title": "Vendored crypto libraries verified against upstream",
1484
+ "body": "`@noble/ciphers`, `@simplewebauthn/server`, `argon2`, and `peculiar-pki` checked against upstream latest — no bundle refresh needed. The npm-publish workflow is unblocked for v0.6.14, v0.6.15, and this release."
1485
+ }
1486
+ ]
1487
+ }
1488
+ ]
1489
+ },
1490
+ {
1491
+ "version": "0.6.15",
1492
+ "date": "2026-05-02",
1493
+ "headline": "Wiki sidebar collapsible nav + three new wiki env knobs",
1494
+ "summary": "The wiki sidebar's concern groups become collapsible `<details>` sections that auto-open on the active page, and the wiki app exposes three new env knobs in its docker-compose configs covering trusted-proxy detection, admin-path CIDR fencing, and production-posture boot assertion.",
1495
+ "sections": [
1496
+ {
1497
+ "heading": "Added",
1498
+ "items": [
1499
+ {
1500
+ "title": "Collapsible sidebar concern groups",
1501
+ "body": "Every concern group in the wiki sidebar nav is now a `<details>` element starting collapsed; the section containing the current page is rendered with `open` server-side so the operator's current location is always visible. A custom CSS-only disclosure glyph (`>` rotates to `v`) works under the wiki's strict CSP without inline JS."
1502
+ },
1503
+ {
1504
+ "title": "`WIKI_TRUST_PROXY` env knob shipped in docker-compose",
1505
+ "body": "Cookie `Secure`-flag detection through a TLS terminator was already wired in v0.6.12 library code; the env knob now ships in the wiki app's docker-compose configs with documentation so operators fronting the wiki with Caddy / nginx don't have to hand-roll the override."
1506
+ },
1507
+ {
1508
+ "title": "`WIKI_ADMIN_ALLOWED_CIDRS` / `WIKI_ADMIN_DENIED_CIDRS`",
1509
+ "body": "In-process CIDR fence on `/admin` paths via `b.middleware.networkAllowlist`. The production docker-compose overlay defaults the allowlist on; the dev overlay leaves it off."
1510
+ },
1511
+ {
1512
+ "title": "`WIKI_REQUIRE_PROD_ASSERTS` boot gate",
1513
+ "body": "Boot-time `b.security.assertProduction()` gate that refuses to boot when production posture is incomplete. Defaults on in the production overlay (so a misconfigured prod deploy fails fast) and off in the dev overlay."
1514
+ }
1515
+ ]
1516
+ }
1517
+ ]
1518
+ },
1519
+ {
1520
+ "version": "0.6.14",
1521
+ "date": "2026-05-02",
1522
+ "headline": "Production-posture primitives — boot assertions, ABAC, MFA, password policy, dual control, retention, drift, file-type, network allowlist",
1523
+ "summary": "Ships a broad set of operator-facing primitives covering production-posture assertions, attribute-based authorization, MFA-gated sessions, NIST/PCI/HIPAA password policy, two-person-rule dual control, multi-stage retention with legal hold, signed config-drift baselines, magic-byte file-type detection, CIDR-fenced network middleware, host-allowlisted HTTP client, and cryptographic row-level erasure. CI additionally gains a gitleaks secret scan and a CycloneDX SBOM via `npm sbom`. Every new opt is opt-in; existing callers are unaffected.",
1524
+ "sections": [
1525
+ {
1526
+ "heading": "Added",
1527
+ "items": [
1528
+ {
1529
+ "title": "`b.security.assertProduction(opts)` boot-time policy engine",
1530
+ "body": "Refuses boot when production posture is violated: vault / DB-at-rest / audit-signing posture, NTP strict, Node minimum major, TLS minimum version, required + forbidden env vars, NODE_ENV pinning, dataDir POSIX-mode check, CORS-allow-all detection, plus operator-supplied extra asserts. Each assertion throws with the failing predicate named so operators see the misconfiguration directly."
1531
+ },
1532
+ {
1533
+ "title": "`b.permissions.policy(scope, predicate)` ABAC layer",
1534
+ "body": "Per-scope predicates evaluated after RBAC passes, supporting single / requireAll / requireAny composition modes. Lets operators attach attribute-based gates (tenant match, ownership, time-of-day, IP-bound) on top of the existing role check without weaving a parallel auth path."
1535
+ },
1536
+ {
1537
+ "title": "`b.permissions` role-spec `requireMfa` / `mfaWindowMs` + per-route MFA enforcement",
1538
+ "body": "Roles can mandate a recent MFA challenge with a configurable freshness window. The middleware refuses requests from sessions outside the window and emits an audit event so operators can wire step-up flows without rolling their own MFA-recency check."
1539
+ },
1540
+ {
1541
+ "title": "`b.session` IP/UA fingerprint capture + drift detection",
1542
+ "body": "Sessions capture an IP + user-agent fingerprint at create time. An operator-supplied scorer feeds anomaly detection; strict modes `requireFingerprintMatch` and `maxAnomalyScore` refuse the request when the live fingerprint diverges. Defaults stay permissive so existing deployments aren't broken by a NAT roam."
1543
+ },
1544
+ {
1545
+ "title": "`b.auth.password.policy(opts)` with NIST 800-63B / PCI-DSS 4.0 / HIPAA-AAL2 profiles",
1546
+ "body": "Named profiles plus length, common-password, context, dictionary, and complexity rules (categories + min-run + min-sequence). Includes an HIBP k-anonymity breach check (SHA-1 lives in `lib/internal-sha1-hibp.js` and is intentionally NOT exported on `b.crypto`). Rotation (`shouldRotate`) and history-reuse (`reuseProhibited`) are first-class. Aligned with NIST SP 800-63B-4 (March 2024) and PCI-DSS 4.0 (8.3.x)."
1547
+ },
1548
+ {
1549
+ "title": "`b.dualControl.create(opts)` two-person rule",
1550
+ "body": "m-of-n quorum, cooling-off lock between approval and consume, approver-role gate, requester cancellation, minimum reason length, notification hook on each transition. Designed for break-glass admin actions, large-value transfers, and any op that should require a second authorized human in the loop."
1551
+ },
1552
+ {
1553
+ "title": "`b.retention.create(opts)` multi-stage retention",
1554
+ "body": "Warn → archive → erase staged rules, legal-hold per-row exemption, dry-run `preview()`, soft-delete vs hard-delete vs erase, cross-table cascade, per-rule concurrency lock. Operators encode GDPR Art. 17 / CCPA-deletion / sectoral-retention floors as data instead of imperative jobs."
1555
+ },
1556
+ {
1557
+ "title": "`b.configDrift.create(opts)` signed-baseline drift detection",
1558
+ "body": "Multi-baseline support, critical-keys severity classification, ignore-keys allowlist, signed sidecar via SLH-DSA, and diff against the previous snapshot. The detector runs on a schedule and surfaces drift before the next deployment instead of at incident-response time."
1559
+ },
1560
+ {
1561
+ "title": "`b.fileType.detect` / `b.fileType.assertOneOf` magic-byte classification",
1562
+ "body": "Identifies content (image / document / archive / executable / etc.) from the byte stream's magic. Composes with `b.guardArchive` / `b.guardImage` / `b.fileUpload` so the operator gets one classifier surface instead of N ad-hoc sniffers."
1563
+ },
1564
+ {
1565
+ "title": "`b.middleware.networkAllowlist({ paths, allowedCidrs, deniedCidrs })`",
1566
+ "body": "Deny-then-allow CIDR fence per-path. Lets operators ring-fence admin paths to corporate ranges without standing up a reverse-proxy ACL. Emits an audit event on every refused request."
1567
+ },
1568
+ {
1569
+ "title": "`b.httpClient.request({ allowedHosts })` host allowlist + audit",
1570
+ "body": "Exact / suffix / wildcard / per-method entries; the client refuses any outbound request to an unlisted host and emits an audit event with the violating destination. Closes a class of SSRF / data-egress risk on outbound integrations."
1571
+ },
1572
+ {
1573
+ "title": "`b.cryptoField.eraseRow(table, row)` cryptographic erasure",
1574
+ "body": "Helper for sealed columns + derived hashes — destroys per-row key material so the ciphertext becomes irrecoverable without bulk deletes. Aligned with GDPR Art. 17 right-to-erasure on tenants that share a table."
1575
+ }
1576
+ ]
1577
+ },
1578
+ {
1579
+ "heading": "Changed",
1580
+ "items": [
1581
+ {
1582
+ "title": "CI gains gitleaks secret scan + CycloneDX SBOM via `npm sbom`",
1583
+ "body": "Both run on every PR without vendoring additional tooling — gitleaks via the official action pinned to a SHA, SBOM via `npm sbom --sbom-format=cyclonedx` shipped to the artifact bucket. Operators have a verifiable component inventory per release without a separate generation step."
1584
+ },
1585
+ {
1586
+ "title": "README + SECURITY operator-checklist updated end to end",
1587
+ "body": "Every new primitive lands in the README's `What ships` matrix and in the SECURITY hardening checklist. The wiki gains an alerting-rule reference table that maps each framework-emitted audit event to a suggested detection rule."
1588
+ }
1589
+ ]
1590
+ }
1591
+ ],
1592
+ "references": [
1593
+ {
1594
+ "label": "NIST SP 800-63B-4 (Digital Identity Guidelines)",
1595
+ "url": "https://pages.nist.gov/800-63-4/sp800-63b.html"
1596
+ },
1597
+ {
1598
+ "label": "PCI-DSS 4.0",
1599
+ "url": "https://www.pcisecuritystandards.org/document_library/"
1600
+ },
1601
+ {
1602
+ "label": "HIPAA Security Rule (45 CFR Part 164)",
1603
+ "url": "https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-C/part-164"
1604
+ },
1605
+ {
1606
+ "label": "GDPR Article 17 — Right to erasure",
1607
+ "url": "https://gdpr-info.eu/art-17-gdpr/"
1608
+ },
1609
+ {
1610
+ "label": "CycloneDX 1.6",
1611
+ "url": "https://cyclonedx.org/specification/overview/"
1612
+ },
1613
+ {
1614
+ "label": "Have I Been Pwned k-anonymity range API",
1615
+ "url": "https://haveibeenpwned.com/API/v3#PwnedPasswords"
1616
+ }
1617
+ ]
1618
+ },
1619
+ {
1620
+ "version": "0.6.13",
1621
+ "date": "2026-05-02",
1622
+ "headline": "Wiki primitive-section docs catch up to the v0.6.12 surface and `numeric-checks` consolidation",
1623
+ "sections": [
1624
+ {
1625
+ "heading": "Changed",
1626
+ "items": [
1627
+ {
1628
+ "title": "Wiki primitive-section docs reconciled with v0.6.12",
1629
+ "body": "Documentation for `safeUrl.parse` `allowUserinfo`, `session.touch` `extendBy` ceiling, `queue.consume` `rateLimit` validation, `mail.transports.console` `redactBcc`, the `logStream` webhook sink `onDrop`, `backup.create` `requireFlush`, and `restore.create` `maxPulledBytes` / `maxPulledFiles` is now in sync with the lib surface. The restore default cap is stated as `C.BYTES.gib(4)` rather than a raw byte literal."
1630
+ },
1631
+ {
1632
+ "title": "Numeric-check predicates consolidated",
1633
+ "body": "`isPositiveInt`, `isFiniteNonNegative`, and `isPositiveFinite` were duplicated across `api-key`, `cache`, `notify`, `queue`, `restore`, `retry`, `slug`, `testing`, and `webhook`; the helpers are now consolidated into `lib/numeric-checks.js` and every consumer routes through it."
1634
+ },
1635
+ {
1636
+ "title": "API snapshot refreshed",
1637
+ "body": "`api-snapshot.json` is refreshed to capture the new public surface introduced by the previous release."
1638
+ }
1639
+ ]
1640
+ }
1641
+ ]
1642
+ },
1643
+ {
1644
+ "version": "0.6.12",
1645
+ "date": "2026-05-01",
1646
+ "headline": "Hardening sweep across `safeUrl`, `session`, `queue`, middleware, backup/restore, mail, and log-stream",
1647
+ "sections": [
1648
+ {
1649
+ "heading": "Changed",
1650
+ "items": [
1651
+ {
1652
+ "title": "`b.safeUrl.parse` rejects `user:pass@` userinfo by default",
1653
+ "body": "Operators wanting userinfo opt in per-call via `allowUserinfo: true`. The default refuses the shape that most often appears in URL-confusion phishing payloads."
1654
+ },
1655
+ {
1656
+ "title": "`b.session.touch({ extendBy })` enforces the `MAX_TTL_MS` ceiling",
1657
+ "body": "`touch` now applies the same `MAX_TTL_MS` ceiling as `create` and `rotate` so a long-lived session can't be extended past the configured maximum."
1658
+ },
1659
+ {
1660
+ "title": "`b.queue.consume({ rateLimit })` validates `max`",
1661
+ "body": "Negative, zero, `NaN`, `Infinity`, and fractional `max` values are rejected at queue creation instead of silently bypassing the rate limit at consume time."
1662
+ },
1663
+ {
1664
+ "title": "`b.middleware.requireAuth` JSON detection narrowed",
1665
+ "body": "Request `Content-Type: application/json` is no longer treated as a JSON-preference signal; only `Accept` and `X-Requested-With` count so an attacker can't downgrade the response shape by tampering with the request body's content type."
1666
+ }
1667
+ ]
1668
+ },
1669
+ {
1670
+ "heading": "Added",
1671
+ "items": [
1672
+ {
1673
+ "title": "`b.backup.create({ requireFlush: true })` opt-in",
1674
+ "body": "When set, the backup fails if the pre-flush step fails instead of producing a stale snapshot."
1675
+ },
1676
+ {
1677
+ "title": "`b.restore.create` preflight bounds",
1678
+ "body": "`maxPulledBytes` and `maxPulledFiles` preflight bounds bound bundle footprint before and after pull. Defaults are 4 GiB and 100K files."
1679
+ },
1680
+ {
1681
+ "title": "`b.mail.transports.console({ redactBcc: true })`",
1682
+ "body": "When set, the console mail transport prints a recipient count instead of address strings so dev logs don't leak BCC lists."
1683
+ },
1684
+ {
1685
+ "title": "`b.logStream.transports.webhook({ onDrop })`",
1686
+ "body": "Callback fires on overflow and retry-exhausted batch drops so operators see every drop class instead of silent loss."
1687
+ }
1688
+ ]
1689
+ },
1690
+ {
1691
+ "heading": "Security",
1692
+ "items": [
1693
+ {
1694
+ "title": "Wiki admin login wired through `b.auth.lockout`",
1695
+ "body": "Admin login now applies exponential backoff after bad-credential attempts instead of accepting unlimited retries."
1696
+ },
1697
+ {
1698
+ "title": "Cookie `Secure` flag routes through `requestProtocol`",
1699
+ "body": "The wiki app's cookie `Secure` flag now routes through `b.requestHelpers.requestProtocol` with `WIKI_TRUST_PROXY` opt-in instead of trusting `x-forwarded-proto` raw. The wiki README documents the trust model for editable page bodies and the sanitization pattern operators should adopt before expanding the editor surface."
1700
+ }
1701
+ ]
1702
+ }
1703
+ ]
1704
+ },
1705
+ {
1706
+ "version": "0.6.11",
1707
+ "date": "2026-05-01",
1708
+ "headline": "Wiki example-execution validator: fixture init no longer reaches across module realms",
1709
+ "summary": "Unblocks the npm-publish workflow's wiki-e2e gate, where `npm install --install-links` copies the framework into the wiki's `node_modules` and produces two distinct framework singletons.",
1710
+ "sections": [
1711
+ {
1712
+ "heading": "Fixed",
1713
+ "items": [
1714
+ {
1715
+ "title": "Fixture init no longer reaches across module realms",
1716
+ "body": "The wiki example-execution validator constructed its fixture by reaching into framework internals across module realms; with `npm install --install-links` (used by the npm-publish workflow) the wiki's `node_modules` carries a separate framework copy, producing two singletons. The fixture is reworked so initialisation runs entirely inside the wiki's realm and the workflow's wiki-e2e gate unblocks."
1717
+ }
1718
+ ]
1719
+ }
1720
+ ]
1721
+ },
1722
+ {
1723
+ "version": "0.6.10",
1724
+ "date": "2026-05-01",
1725
+ "headline": "Doc accuracy sweep across README / SECURITY / CONTRIBUTING / wiki",
1726
+ "sections": [
1727
+ {
1728
+ "heading": "Fixed",
1729
+ "items": [
1730
+ {
1731
+ "title": "Stale version stamps removed",
1732
+ "body": "Several README and SECURITY sections carried version stamps that drifted across releases; they are removed in favor of pointing at the live manifest."
1733
+ },
1734
+ {
1735
+ "title": "Vendored-dep list points at the live manifest",
1736
+ "body": "SECURITY now points at `lib/vendor/MANIFEST.json` as the authoritative vendored-dependency list instead of an out-of-date prose enumeration. The supported-versions table no longer pins to a specific minor line."
1737
+ },
1738
+ {
1739
+ "title": "Archive example renamed digest variable",
1740
+ "body": "The wiki archive example named the digest variable `sha256` even though `b.archive.zip().digest()` now returns SHA3-512 hex; the variable is renamed so the example reads correctly."
1741
+ }
1742
+ ]
1743
+ }
1744
+ ]
1745
+ },
1746
+ {
1747
+ "version": "0.6.9",
1748
+ "date": "2026-05-01",
1749
+ "headline": "`b.archive.zip().digest()` returns SHA3-512 hex (was SHA-256)",
1750
+ "summary": "Operators reconciling archive digests against an external SHA-256 must now hash the bytes themselves.",
1751
+ "sections": [
1752
+ {
1753
+ "heading": "Changed",
1754
+ "items": [
1755
+ {
1756
+ "title": "Archive digest output switched to SHA3-512",
1757
+ "body": "`b.archive.zip().digest()` now returns a SHA3-512 hex string, matching the framework's PQC-first hash posture. Operators reconciling against an external SHA-256 must hash the produced bytes themselves with `sha256` to recover the prior value."
1758
+ }
1759
+ ]
1760
+ }
1761
+ ]
1762
+ },
1763
+ {
1764
+ "version": "0.6.8",
1765
+ "date": "2026-05-01",
1766
+ "headline": "Wiki primitive-section validator covering presence, opts diff, and example execution",
1767
+ "sections": [
1768
+ {
1769
+ "heading": "Added",
1770
+ "items": [
1771
+ {
1772
+ "title": "Primitive-section validator for wiki pages",
1773
+ "body": "Wiki pages documenting a primitive now run through a validator that asserts presence of the documented surface, diffs documented opts against the lib allow-list, and executes every example against a canonical fixture so drift is caught at the gate."
1774
+ }
1775
+ ]
1776
+ }
1777
+ ]
1778
+ },
1779
+ {
1780
+ "version": "0.6.7",
1781
+ "date": "2026-05-01",
1782
+ "headline": "`db.role.switched` audit, per-role metrics, and an API snapshot baseline",
1783
+ "sections": [
1784
+ {
1785
+ "heading": "Added",
1786
+ "items": [
1787
+ {
1788
+ "title": "`db.role.switched` audit event",
1789
+ "body": "Every request-time role switch on the db pool emits an audit event so operators can correlate role-bound queries with the requests that triggered them."
1790
+ },
1791
+ {
1792
+ "title": "Per-role observability counters",
1793
+ "body": "Observability counters now break down query / acquire / commit / rollback metrics per active DB role."
1794
+ },
1795
+ {
1796
+ "title": "API snapshot baseline",
1797
+ "body": "An `api-snapshot.json` baseline is checked in and validated by CI so accidental surface drift between releases is refused at the gate."
1798
+ }
1799
+ ]
1800
+ }
1801
+ ]
1802
+ },
1803
+ {
1804
+ "version": "0.6.6",
1805
+ "date": "2026-05-01",
1806
+ "headline": "Request-time DB role binding and Postgres RLS migrations",
1807
+ "sections": [
1808
+ {
1809
+ "heading": "Added",
1810
+ "items": [
1811
+ {
1812
+ "title": "Request-time DB role binding",
1813
+ "body": "The db primitive binds a request-scoped role per acquire so Postgres RLS policies and least-privilege roles compose naturally with the request lifecycle."
1814
+ },
1815
+ {
1816
+ "title": "Postgres RLS migration helpers",
1817
+ "body": "Migration helpers emit the `CREATE POLICY` / `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` boilerplate Postgres needs for row-level-security rollout."
1818
+ }
1819
+ ]
1820
+ }
1821
+ ]
1822
+ },
1823
+ {
1824
+ "version": "0.6.5",
1825
+ "date": "2026-05-01",
1826
+ "headline": "`b.db.declareView` and `b.externalDb.migrate`",
1827
+ "sections": [
1828
+ {
1829
+ "heading": "Added",
1830
+ "items": [
1831
+ {
1832
+ "title": "`b.db.declareView`",
1833
+ "body": "Operators declare a named view at boot and the framework manages its creation, replacement, and audit alongside table schemas."
1834
+ },
1835
+ {
1836
+ "title": "`b.externalDb.migrate`",
1837
+ "body": "Schema migrations against an external database now run through the same advisory-lock + version-table workflow the local db primitive uses."
1838
+ }
1839
+ ]
1840
+ }
1841
+ ]
1842
+ },
1843
+ {
1844
+ "version": "0.6.4",
1845
+ "date": "2026-05-01",
1846
+ "headline": "Wiki schema docs realigned with the actual lib API",
1847
+ "sections": [
1848
+ {
1849
+ "heading": "Fixed",
1850
+ "items": [
1851
+ {
1852
+ "title": "Wiki schema docs realigned with the actual lib API",
1853
+ "body": "Several wiki pages documented opts and method shapes that had drifted from the underlying lib surface; every documented signature is now reconciled against the validator and exec-runtime gates."
1854
+ }
1855
+ ]
1856
+ }
1857
+ ]
1858
+ },
1859
+ {
1860
+ "version": "0.6.3",
1861
+ "date": "2026-05-01",
1862
+ "headline": "`externalDb` pool tuning, role-aware connect, and read-replica routing",
1863
+ "sections": [
1864
+ {
1865
+ "heading": "Added",
1866
+ "items": [
1867
+ {
1868
+ "title": "Pool tuning opts for `b.externalDb`",
1869
+ "body": "Operators can now tune the underlying connection pool from primitive opts instead of passing a pre-built driver."
1870
+ },
1871
+ {
1872
+ "title": "Role-aware connect",
1873
+ "body": "Connections can now bind to a request-scoped role on acquire, giving Postgres RLS and least-privilege deploys a clean wiring point."
1874
+ },
1875
+ {
1876
+ "title": "Read-replica routing",
1877
+ "body": "Read-only queries route to a replica pool when configured, with the writer-pool fallback used for any statement that mutates state."
1878
+ }
1879
+ ]
1880
+ }
1881
+ ]
1882
+ },
1883
+ {
1884
+ "version": "0.6.2",
1885
+ "date": "2026-05-01",
1886
+ "headline": "Input validation tightening and identifier-quoting consistency",
1887
+ "sections": [
1888
+ {
1889
+ "heading": "Changed",
1890
+ "items": [
1891
+ {
1892
+ "title": "Input validation tightened across primitives",
1893
+ "body": "Validation paths refuse a broader class of malformed input at the entry boundary, surfacing typos at boot or at the request edge instead of mid-flight."
1894
+ },
1895
+ {
1896
+ "title": "SQL identifier quoting normalised",
1897
+ "body": "Identifier quoting in generated SQL is normalised across the db primitives so cross-dialect output stays consistent."
1898
+ }
1899
+ ]
1900
+ }
1901
+ ]
1902
+ },
1903
+ {
1904
+ "version": "0.6.1",
1905
+ "date": "2026-05-01",
1906
+ "headline": "Security tightenings and operator-facing jargon sweep",
1907
+ "summary": "Several security defaults are tightened and operator-facing prose across the wiki and README is rewritten to remove internal vocabulary.",
1908
+ "sections": [
1909
+ {
1910
+ "heading": "Changed",
1911
+ "items": [
1912
+ {
1913
+ "title": "Operator-facing jargon sweep",
1914
+ "body": "Wiki and README prose is rewritten to remove internal vocabulary so operators read primitive descriptions in their own terms."
1915
+ }
1916
+ ]
1917
+ },
1918
+ {
1919
+ "heading": "Security",
1920
+ "items": [
1921
+ {
1922
+ "title": "Default tightenings across the request lifecycle",
1923
+ "body": "Several security defaults across the request lifecycle are tightened so operators inherit stricter posture without extra opt-in."
1924
+ }
1925
+ ]
1926
+ }
1927
+ ]
1928
+ },
1929
+ {
1930
+ "version": "0.6.0",
1931
+ "date": "2026-05-01",
1932
+ "headline": "Wiki restructured into 22 focused pages with missing-primitive coverage",
1933
+ "summary": "The wiki is reorganized into 22 concern-scoped pages so operators land on the primitive surface for their task instead of scrolling a monolithic index, and every previously missing primitive gains its own page.",
1934
+ "sections": [
1935
+ {
1936
+ "heading": "Changed",
1937
+ "items": [
1938
+ {
1939
+ "title": "Wiki reorganized into 22 concern-scoped pages",
1940
+ "body": "Operators land on the primitive page for the concern they are working in rather than scrolling a single index. The new layout closes coverage gaps where previously missing primitives now ship their own pages."
1941
+ }
1942
+ ]
1943
+ }
1944
+ ]
1945
+ }
1946
+ ]
1947
+ }