@blamejs/blamejs-shop 0.5.12 → 0.5.13

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 (521) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +632 -416
  4. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  5. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  6. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  7. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  8. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  9. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  10. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  11. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  12. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  13. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  14. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  15. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  16. package/lib/vendor/blamejs/.gitignore +2 -0
  17. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  18. package/lib/vendor/blamejs/NOTICE +26 -1
  19. package/lib/vendor/blamejs/SECURITY.md +1 -1
  20. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  21. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  22. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  23. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  24. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  25. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  26. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  27. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  28. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  29. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  30. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  31. package/lib/vendor/blamejs/index.js +6 -0
  32. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  33. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  34. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  35. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  36. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  37. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  38. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  39. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  40. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  41. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  42. package/lib/vendor/blamejs/lib/audit.js +71 -8
  43. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  44. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  45. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  46. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  47. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  48. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  49. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  50. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  51. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  52. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  53. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  54. package/lib/vendor/blamejs/lib/base32.js +21 -0
  55. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  56. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  57. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  58. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  59. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  60. package/lib/vendor/blamejs/lib/cert.js +29 -11
  61. package/lib/vendor/blamejs/lib/cli.js +94 -24
  62. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  63. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  65. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  66. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  67. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  68. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  69. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  70. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  71. package/lib/vendor/blamejs/lib/cose.js +31 -16
  72. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  73. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  74. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  75. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  76. package/lib/vendor/blamejs/lib/csp.js +11 -3
  77. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  78. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  79. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  80. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  81. package/lib/vendor/blamejs/lib/db.js +18 -6
  82. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  83. package/lib/vendor/blamejs/lib/dev.js +21 -2
  84. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  85. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  86. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  87. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  88. package/lib/vendor/blamejs/lib/forms.js +113 -27
  89. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  90. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  91. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  92. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  93. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  94. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  95. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  96. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  97. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  98. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  99. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  100. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  101. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  102. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  105. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  106. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  107. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  108. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  109. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  110. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  111. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  112. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  113. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  114. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  115. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  116. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  117. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  118. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  119. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  120. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  121. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  123. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  124. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  125. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  126. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  128. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  129. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  130. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  131. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  132. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  133. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  134. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  136. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  137. package/lib/vendor/blamejs/lib/mail.js +15 -5
  138. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  139. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  140. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  141. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  142. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  143. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  144. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  145. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  146. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  147. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  148. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  149. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  150. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  151. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  153. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  154. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  155. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  156. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  157. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  158. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  159. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  160. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  161. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  162. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  163. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  164. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  165. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  166. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  167. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  168. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  169. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  170. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  171. package/lib/vendor/blamejs/lib/redact.js +54 -0
  172. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  173. package/lib/vendor/blamejs/lib/restore.js +19 -0
  174. package/lib/vendor/blamejs/lib/retention.js +12 -4
  175. package/lib/vendor/blamejs/lib/router.js +60 -6
  176. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  177. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  178. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  179. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  180. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  181. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  182. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  183. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  184. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  185. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  186. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  187. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  188. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  189. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  190. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  191. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  192. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  193. package/lib/vendor/blamejs/lib/session.js +34 -12
  194. package/lib/vendor/blamejs/lib/sql.js +15 -1
  195. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  196. package/lib/vendor/blamejs/lib/static.js +55 -13
  197. package/lib/vendor/blamejs/lib/storage.js +8 -2
  198. package/lib/vendor/blamejs/lib/subject.js +6 -1
  199. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  200. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  201. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  202. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  203. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  204. package/lib/vendor/blamejs/lib/vc.js +44 -5
  205. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  206. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  207. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  208. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  209. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  210. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  212. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  213. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  214. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  215. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  216. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  217. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  218. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  219. package/lib/vendor/blamejs/package-lock.json +2 -2
  220. package/lib/vendor/blamejs/package.json +1 -1
  221. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  222. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  223. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  224. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  245. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  246. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  247. package/lib/vendor/blamejs/socket.yml +94 -0
  248. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  249. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  250. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  251. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  252. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  253. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  254. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  255. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  256. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  257. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  258. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  259. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  262. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  268. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  284. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  293. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  302. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  307. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  321. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  322. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  324. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  326. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  327. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  330. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  334. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  335. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  336. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  337. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  348. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  376. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  388. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  413. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  414. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  415. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  416. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  428. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  432. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  434. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  442. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  443. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  445. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  477. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  478. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  480. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  490. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  491. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  492. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  493. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  495. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  502. package/lib/vendor/blamejs/test/smoke.js +2 -0
  503. package/package.json +1 -1
  504. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  505. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  506. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  507. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  508. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  509. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  510. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  511. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  512. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  513. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  514. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  515. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  516. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  517. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  518. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  519. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  520. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  521. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.0",
4
+ "date": "2026-07-17",
5
+ "headline": "Algorithm and key-type lookups across the crypto verifiers reject a prototype-member name instead of accepting it, the ZIP reader honors the operator's decompression-ratio policy, and signed S3/GCS query parameters transmit the space encoding they were signed with",
6
+ "summary": "A family of verifiers resolved an algorithm, hash, or key-type name against a plain-object lookup table with a truthiness or `in`-operator guard, so a name that is an inherited Object.prototype member (constructor, __proto__, toString, valueOf) slipped the guard and resolved to the inherited member: b.jwk thumbprinted an attacker-crafted key to a predictable digest, b.vc and b.contentCredentials emitted a real signature under a bogus algorithm, and b.sdJwtVc accepted an attacker-controlled hash name from an unsigned issuer payload. All of them now reject a name that is not an own property of the table. Separately, b.archive's ZIP reader silently capped the decompression ratio at its composed default and ignored the operator's configured bomb policy, refusing legitimate highly-compressible entries; and b.storage's SigV4 (and the GCS V4 presigner) signed a query space as %20 but transmitted it as +, so a signed parameter carrying a space was rejected as a signature mismatch.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "Crypto algorithm and key-type lookups reject a prototype-member name",
13
+ "body": "Several verifiers resolved a caller- or attacker-supplied algorithm / hash / key-type name against a plain-object lookup table using a truthiness check (`var v = TABLE[name]; if (!v) reject`) or the prototype-chain-aware `in` operator. A name that names an inherited Object.prototype member -- constructor, __proto__, toString, valueOf, toLocaleString -- is truthy (or present via the prototype chain), so it slipped the guard and resolved to the inherited member. The observed consequences: b.jwk.thumbprint / canonicalize accepted an unsupported kty and thumbprinted the key to a single predictable digest; b.vc.issue (JOSE) and b.contentCredentials.signCose emitted a real signature under a bogus algorithm id; and b.sdJwtVc.present accepted an attacker-controlled _sd_alg read from the unsigned issuer payload. b.tsa and the SD-JWT hash-disclosure path returned a raw runtime error rather than a typed rejection. Every one of these table lookups now checks Object.prototype.hasOwnProperty before indexing, so a name that is not an own member of the table is rejected with the primitive's typed error. Supported algorithm and key-type names are unaffected."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "heading": "Fixed",
19
+ "items": [
20
+ {
21
+ "title": "ZIP extraction honors the operator's decompression-ratio policy",
22
+ "body": "b.archive's random-access ZIP reader composed b.safeDecompress for each DEFLATE entry without forwarding the reader's own expansion-ratio cap, so the decompression inherited safeDecompress's stricter default ratio and silently overrode the operator's configured bomb policy. A ZIP entry that legitimately compressed better than the default ratio (logs, JSON, telemetry, zero-padded or sparse binaries) was refused even when the operator's policy permitted it. The reader now forwards its configured maximum expansion ratio into the decode, so the actual-bytes ratio re-check uses the same cap the declared-size gate already enforced."
23
+ },
24
+ {
25
+ "title": "Signed S3 and GCS query parameters transmit the space encoding they were signed with",
26
+ "body": "b.storage's SigV4 request signing (S3, R2, MinIO, and the S3-compatible backends) and the GCS V4 presigner sign the canonical query string, which encodes a space as %20 per the AWS/GCS specification, but transmitted the request via the WHATWG URL serializer, which encodes a space as +. A signed query parameter carrying a literal space -- a response-content-disposition filename or a list prefix -- was therefore signed over %20 but sent as +, so the storage server re-canonicalized to different bytes and rejected the request with a signature mismatch. The signer now aligns the wire query to the signed canonical encoding (rewriting a bare + back to %20) at each signing sink, so the transmitted query is byte-identical to what the signature commits to."
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.1",
4
+ "date": "2026-07-17",
5
+ "headline": "Profile, posture, and capability name lookups across the content-safety and mail-protocol guards reject a prototype-member name instead of running under it, the mTLS CA can generate a CRL after a fingerprint-only revocation, and a hostile MIME filename no longer crashes attachment extraction",
6
+ "summary": "A second family of guards resolved a profile, posture, or capability name against a plain-object lookup table with a truthiness or in-operator guard, so a name that is an inherited Object.prototype member (constructor, __proto__, toString) slipped the guard and the gate ran under the inherited member instead of refusing the unknown name. The shared profile resolver (b.gateContract.makeProfileResolver, which the guard family composes), the iCal and vCard content guards, the dark-patterns posture check, the JMAP capability allowlist, and the IMAP/POP3/ManageSieve command guards now all resolve names through an own-property check. Separately, b.mtlsCa.generateCrl crashed with a null-serial error once any certificate had been revoked by fingerprint (the mode the require-mTLS gate pins on), dropping every serial-keyed revocation from the published CRL; and b.safeMime.extractAttachments threw an uncaught URIError on a hostile Content-Disposition filename with a malformed percent-escape, crashing the caller.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "Guard profile, posture, and capability lookups reject a prototype-member name",
13
+ "body": "A group of content-safety and mail-protocol guards resolved a caller- or request-supplied profile / posture / capability name against a plain-object lookup table using a truthiness check (var caps = TABLE[name]; if (!caps)) or the prototype-chain-aware in operator. A name that names an inherited Object.prototype member -- constructor, __proto__, toString -- is truthy (or present via the prototype chain), so it slipped the guard and the gate ran under the inherited member instead of refusing the unknown name. The shared resolver b.gateContract.makeProfileResolver (composed by the idempotency-key, mail-compose, message-id and other guards) now guards both its posture and profile lookups with hasOwnProperty; b.safeIcal, b.safeVcard, b.darkPatterns, b.guardJmap (capability allowlist and profile/posture), and the b.guardImapCommand / b.guardPop3Command / b.guardManageSieveCommand command guards do the same. An unknown or prototype-member name is now rejected with the guard's typed error; supported names are unaffected. This extends the same own-property hardening applied to the crypto algorithm-table lookups in 0.17.0 to the guard-family profile resolvers."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "heading": "Fixed",
19
+ "items": [
20
+ {
21
+ "title": "mTLS CA generates a CRL after a fingerprint-only revocation",
22
+ "body": "b.mtlsCa.revoke accepts a certificate fingerprint (the value the require-mTLS gate pins on and generateClientCert surfaces for exactly this use), which is stored without a serial number. b.mtlsCa.generateCrl then mapped the whole revocation registry into CRL entries and handed the null serial to the CRL encoder, which threw -- aborting CRL generation entirely. Because one fingerprint-only revocation broke every subsequent CRL build, all serial-keyed revocations were silently dropped from the published CRL and it could never be regenerated, going stale for external CRL-based revocation checking. generateCrl now projects out fingerprint-only entries (which a standard X.509 CRL cannot represent) before encoding and reports how many were omitted; fingerprint-only revocations remain enforced through the mTLS gate, and the CRL publishes every serial-keyed revocation."
23
+ },
24
+ {
25
+ "title": "A hostile MIME filename no longer crashes attachment extraction",
26
+ "body": "b.safeMime.extractAttachments decoded an RFC 2231 / RFC 5987 extended filename parameter (filename*=charset''percent-encoded) with an unguarded percent-decode, so a malformed escape -- a truncated %, a non-hex %ZZ, or a sequence that decodes to invalid UTF-8 -- threw an uncaught URIError that escaped the parser's typed-error contract and crashed the caller (for example a mail store extracting attachments). A one-line hostile Content-Disposition header was a trivial denial of service. The decode now degrades to the still-encoded filename on failure, matching the framework's handling of every other percent-decode site, so a hostile filename yields a best-effort name that downstream filename guards still vet rather than a crash."
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.10",
4
+ "date": "2026-07-17",
5
+ "headline": "A CIDR-scoped SMTP relay allowlist is now actually enforced instead of relaying for the whole internet, EU AI-Act social scoring is flagged prohibited for any actor rather than only public authorities, and the X-Wing hybrid KEM stays uniform implicit-rejection on a low-order X25519 point",
6
+ "summary": "The mail server's relay authorization discarded its arguments and returned allowed for every connecting peer whenever an operator configured any relayAllowedFor entry, so a per-CIDR relay allowlist -- intended to scope relay to registered sources -- turned the server into an open relay for the entire internet. The EU AI-Act prohibited-practice classifier gated social scoring on the deployer being a public authority, a limitation that was in the 2021 Commission proposal but dropped from the adopted Regulation (EU) 2024/1689, so a private-actor social-scoring system was under-classified as not-prohibited. The GDPR record-of-processing updater validated a legal-basis change with a truthiness guard, so a falsy-but-invalid value skipped the enum check and could corrupt a required Article 30 field. And the X-Wing hybrid post-quantum KEM threw a raw derivation error on a low-order X25519 point instead of the uniform implicit-rejection its contract and the draft specification require, exposing a decapsulation-oracle distinguisher and a crash for any consumer following the documented no-try/catch advice.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "SMTP relay allowlist enforces its per-entry CIDR instead of relaying for everyone",
13
+ "body": "b.mail.server.mx accepts a relayAllowedFor allowlist of { cidr, scope } entries, documented as scoping relay to registered source ranges over the default MX-only, no-relay posture. The relay-authorization check discarded both the peer address and recipient and simply returned allowed whenever the allowlist was non-empty, so an operator restricting relay to, for example, 10.0.0.0/8 actually granted relay to every peer on the internet -- an open relay, directly contradicting the module's advertised open-relay defense. The check now admits relay only when the connecting peer's source address falls inside one of the allowlisted ranges (using the same range arithmetic the HTTP network-allowlist fence uses); a peer outside every range is refused. Each relayAllowedFor entry's cidr is now validated at startup -- a mask is required so a bare IP cannot silently disable an entry, private and reserved ranges are allowed since relay allowlists legitimately name them, and a malformed entry throws at boot rather than mis-scoping relay."
14
+ },
15
+ {
16
+ "title": "AI-Act classifier flags social scoring by any actor as prohibited",
17
+ "body": "b.compliance.aiAct's prohibited-practice classifier implements EU AI-Act Article 5. Its social-scoring gate (Art. 5(1)(c)) required both the purpose to be social scoring and the deployer to be a public authority before flagging the practice as prohibited. The \"by public authorities or on their behalf\" limitation existed in the 2021 Commission proposal but was removed from the adopted Regulation (EU) 2024/1689, which prohibits social scoring by any actor. A private-actor social-scoring system was therefore under-classified as not-prohibited. The classifier now flags social scoring on the purpose alone, matching the adopted text; the other Article 5 gates (predictive policing based solely on profiling, untargeted facial-recognition scraping, emotion inference in the workplace/education outside medical/safety uses) correctly retain the conjuncts that are part of their statutory definitions rather than over-broad limitations."
18
+ },
19
+ {
20
+ "title": "GDPR record-of-processing rejects a falsy-but-invalid legal basis on update",
21
+ "body": "b.gdpr.ropa records the Article 30 register of processing activities, whose legalBasis field is constrained to the six Article 6(1) bases. register validates the basis against the allowlist, but update validated a legal-basis change with a truthiness guard, so a falsy-but-invalid value (an empty string, and similar) short-circuited past the enum check and was written into the record -- silently corrupting a required Article 30 field. The updater now validates whenever the patch touches legalBasis, keyed on the field being present rather than truthy, so an invalid value is rejected with the same rigor register applies and a genuine change to a valid basis still succeeds."
22
+ },
23
+ {
24
+ "title": "X-Wing hybrid KEM stays uniform implicit-rejection on a low-order X25519 point",
25
+ "body": "b.crypto.xwing implements the X-Wing hybrid post-quantum KEM (ML-KEM-768 combined with X25519), whose contract and the draft-connolly-cfrg-xwing-kem specification require decapsulation to be uniform implicit-rejection: a tampered ciphertext yields a different secret, never an error, so a consumer must not branch on success. But a hostile low-order X25519 point in the ciphertext (or in the recipient's X25519 public half) drove the X25519 derivation to an all-zero shared secret, which the underlying library aborts with a raw derivation error rather than returning the value RFC 7748 X25519 (without the optional abort) yields. That exposed a decapsulation-oracle distinguisher (a low-order point throws while every other ciphertext returns a secret) and a crash for any caller following the documented advice not to wrap decapsulation in a try/catch. The shared X25519 step now translates that abort back into the all-zero shared secret, restoring uniform implicit-rejection; the combiner still binds the X25519 ciphertext and public key and the ML-KEM-768 leg still protects the result, so the hybrid's secure-if-either-holds guarantee is unchanged."
26
+ }
27
+ ]
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.11",
4
+ "date": "2026-07-17",
5
+ "headline": "The DER decoder rejects a non-minimal length encoding, and the OAuth client-attestation verifier pins the JWT type so a JWT minted for another purpose can't be replayed into the attestation slot",
6
+ "summary": "The shared ASN.1 DER decoder accepted a non-minimal long-form length encoding (a long form used for a value that fits the short form, or a length carrying a leading-zero octet), a BER/DER parser-differential an attacker could use to smuggle an alternate encoding of a certificate, CMS structure, or OCSP response past the strict decoder. And the OAuth client-attestation verifier did not pin the JOSE type header of the attestation and proof-of-possession JWTs, so a JWT minted for another purpose but signed by the same key could be replayed into the attestation slot.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "DER decoder rejects a non-minimal length encoding",
13
+ "body": "b.asn1Der is the shared DER reader every certificate, CMS, and OCSP parse in the framework routes through. X.690 §10.1 requires the minimum number of length octets: the long form may be used only for lengths of 128 or more, and must carry no leading-zero octet. The decoder accepted both non-minimal forms -- a long-form length for a value that fits the short form, and a long-form length with a leading zero -- which is a BER/DER parser-differential an attacker can use to encode the same structure two ways and slip an alternate encoding past a strict verifier that canonicalizes differently. The decoder already refused every other BER-ism it encounters (indefinite-length, non-minimal OID sub-identifiers, non-minimal high-tag-number tags); it now also refuses a non-minimal length, closing the remaining differential."
14
+ },
15
+ {
16
+ "title": "OAuth client-attestation verifier pins the JWT type",
17
+ "body": "b.auth.oauth's attestation-based client authentication (draft-ietf-oauth-attestation-based-client-auth) verifies two JWTs -- the client-attestation JWT and its proof-of-possession JWT -- each of which carries a REQUIRED, distinct JOSE type header (oauth-client-attestation+jwt and oauth-client-attestation-pop+jwt). The verifier checked the signature and claims but not the type header, so a JWT minted for a different purpose but signed by the same key -- a private_key_jwt client assertion, or the other proof-of-possession JWT -- could be replayed into the attestation or PoP slot (the cross-JWT confused-deputy class RFC 8725 §3.11 explicit typing defends against). The verifier now pins the expected type for each slot, and the builders emit the same literals so a produced and a checked type can never drift; the framework's DPoP and back-channel-logout JWT verifiers already pin their type, and the attestation verifier now matches."
18
+ }
19
+ ]
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.12",
4
+ "date": "2026-07-22",
5
+ "headline": "The vendored Public Suffix List is refreshed to the current upstream snapshot",
6
+ "summary": "The vendored Mozilla Public Suffix List is updated to the current upstream build, so organizational-domain derivation for DMARC identifier alignment, BIMI issuer scoping, cookie-scope confinement, and same-site policy reflects the current registry delegations. The data module is regenerated and re-signed across all four integrity layers, the manifest hashes are refreshed, and the NOTICE attribution date is updated.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "Public Suffix List refreshed to the current upstream snapshot",
13
+ "body": "The vendored Mozilla Public Suffix List is updated to the current upstream snapshot, so organizational-domain derivation reflects the current registry delegations everywhere the framework draws a registrable-domain boundary -- DMARC identifier alignment, BIMI issuer scoping, cookie-scope confinement, and same-site policy. The precise upstream commit and version are recorded in the signed data file and the vendor manifest. The .data.js carrier is regenerated and re-signed across all four integrity layers (SHA-256 + SHA3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary), the manifest hashes are refreshed, and the NOTICE attribution date is updated."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.13",
4
+ "date": "2026-07-23",
5
+ "headline": "A cross-surface hardening sweep: the log pipeline redacts secrets embedded in a message string, the SSRF guard gains a hostname-aware loopback classifier, crypto gains an RFC 7469 SPKI pin, and a batch of cross-platform lifecycle bugs across the watcher, self-update, daemon, and WebSocket-client primitives are fixed",
6
+ "summary": "The structured-log pipeline redacted metadata but shipped the free-text message verbatim, so a secret interpolated into a log message reached file and remote sinks unscrubbed; a new in-place free-text redactor closes that at the emit chokepoint and every sink. The SSRF guard grows a hostname-aware loopback classifier so consumers stop re-deriving the localhost/127.0.0.1/::1 triad, crypto grows an RFC 7469 SubjectPublicKeyInfo pin plus a pin-verifying checkServerIdentity builder, and the self-update verifier now accepts the same SHA3-512 / IEEE-P1363 ECDSA signatures its standalone counterpart does. Alongside: cross-platform lifecycle fixes in the recursive watcher (long-path stat, lost-root signalling, dead-handle classification, case-folded ignore matching), the self-updater (Windows in-use-binary replacement, asset-to-signature pairing, post-install probation), the daemon (detached-spawn failure reporting, a Windows cooperative-stop channel, a read-only status probe, a pid-lock adopt window), and the WebSocket client (a close during a slow initial dial no longer opens an orphan socket).",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "The log pipeline redacts secrets embedded in a message string",
13
+ "body": "b.logStream.emit ran the redactor over structured `meta` but wrote the free-text `message` verbatim, so a credential interpolated into a log line -- a JWT, an AWS access key, a URL-embedded password -- reached file, webhook, syslog, CloudWatch, and OTLP sinks unscrubbed. And the built-in value detectors are whole-value anchored, so even redacting the message with the structured redactor would miss a token embedded mid-sentence. A new `b.redact.redactText` scrubs credentials in place with word-boundary matching (PEM blocks, JWTs, AWS keys, URL-userinfo passwords, bearer tokens, key=secret assignments, SSN/EIN, Luhn-valid PANs) while keeping the surrounding message, deliberately excluding the high-entropy shape detector that would eat ordinary identifiers in prose. It is applied at the emit chokepoint (covering every sink) and at the OTLP encoders' direct path, and is drop-safe on the hot path."
14
+ },
15
+ {
16
+ "title": "The SSRF guard gains a hostname-aware loopback classifier",
17
+ "body": "b.ssrfGuard.classify recognized only IP literals, so `localhost`, `*.localhost`, and bracketed IPv6 forms were not classified as loopback and every consumer re-derived the strip-brackets / strip-trailing-dot / special-case triad by hand. `b.ssrfGuard.isLoopbackHost` composes canonicalization plus classification plus the RFC 6761 reserved names (`localhost` and `*.localhost`); a companion `b.ssrfGuard.isExactLoopbackName` omits the subdomain reservation for the OAuth loopback-redirect exception, which must accept only the exact `localhost` name and never widen to a `*.localhost` an attacker could register. Neither resolves DNS."
18
+ },
19
+ {
20
+ "title": "Crypto gains an RFC 7469 SPKI pin and a pin-verifying identity check",
21
+ "body": "There was no primitive producing the HPKP / RFC 7469 pin -- the base64 SHA-256 over a certificate's SubjectPublicKeyInfo -- so consumers hand-derived it at both the verify and the report site, where drift mints a never-matching pin. `b.crypto.spkiPin` returns that pin (composing the certificate's SPKI export), and `b.crypto.spkiPinVerifier` returns a checkServerIdentity-compatible function that runs the RFC 9525 hostname check first, then constant-time-compares the peer's SPKI pin against a supplied set (requiring the RFC 7469 backup pin). The pin binds the certificate's long-term key, not the ephemeral post-quantum key-exchange group."
22
+ },
23
+ {
24
+ "title": "The self-update verifier accepts the release-signing ECDSA form",
25
+ "body": "b.selfUpdate.verify delegated to an algorithm-agnostic verify that, for an EC P-384 key, pinned neither the SHA3-512 digest nor the raw IEEE-P1363 signature encoding the release pipeline emits -- so a sidecar signed the way the standalone verifier and install script expect only verified through that standalone path, even inside a fully-installed framework. verify now routes through the same streaming SHA3-512 / DER-or-P1363 verifier, collapsing the two into one acceptance set and dropping the whole-asset in-memory buffer."
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ "heading": "Fixed",
31
+ "items": [
32
+ {
33
+ "title": "Recursive watcher: long paths, lost roots, dead handles, case-folded ignores",
34
+ "body": "b.watcher no longer misreads a change on a Windows path over MAX_PATH as a delete (the post-event stat is long-path-aware); a poll walk that can no longer read the ROOT surfaces a distinct fatal `watcher/root-lost` signal and keeps its prior snapshot instead of diffing an empty tree as a delete of every tracked entry; a native-handle error whose code leaves change detection permanently off is classified fatal (`watcher/handle-dead`) so a wrapper can recreate rather than treat it as transient; and an opt-in `ignoreCaseFold` folds the walk-prune to match a case-insensitive filesystem so an on-disk `Node_Modules` is pruned by a `node_modules/**` ignore."
35
+ },
36
+ {
37
+ "title": "Self-update: Windows in-use-binary replacement and asset-to-signature pairing",
38
+ "body": "swap/rollback install by moving the existing target aside and placing the new bytes at the freed path, so a self-updating Windows daemon can replace its own running image (which the OS locks against an overwrite-in-place); the backup and rollback share the same relocation. And poll now pairs the returned signature to the returned asset by the detached-signature name relationship rather than two independent first-matches, failing closed when the pairing is ambiguous, so a release with several sidecars per binary can no longer hand a foreign signature to the verifier."
39
+ },
40
+ {
41
+ "title": "Daemon: detached-spawn failure is reported, pid-lock adopts without a gap",
42
+ "body": "b.daemon.start's detached mode validated the child pid before writing the pidfile and now subscribes the child's async error so a failed spawn (a bad command) throws instead of returning success and writing an `undefined` pid. And appShutdown's pid-lock adopts an existing pidfile that already records the current process id (the detached parent-handoff) instead of unlinking and recreating it -- closing a window in which the pidfile briefly did not exist and a concurrent stop misread a running daemon as not-running."
43
+ },
44
+ {
45
+ "title": "WebSocket client: a close during a slow initial dial opens no orphan socket",
46
+ "body": "b.wsClient.connect ran its post-SSRF-resolve dial continuation even when close() was called during the (asynchronous, over-a-second) SSRF re-resolve, opening a socket and heartbeat nobody owned. The reconnect path already re-checked the closed flag after its await; the initial dial now does too (guarded at the shared dial funnel), and a close() while still connecting retires immediately rather than leaving the flag unset across the graceful-close window."
47
+ },
48
+ {
49
+ "title": "crypto hash error preserves its errno; PQC agent mirrors the curve into TLS groups",
50
+ "body": "b.crypto.hashFilesParallel now preserves the underlying fs error's `code` / `errno` / `path` on the pre-open stat failure (and gives the symlink-refusal, non-regular-file, and size-cap rejections stable codes) so a caller can tell a benign save-then-delete race from a real read failure without string-matching a message. And b.pqcAgent.create mirrors a caller's `ecdhCurve` into the TLS `groups` option, so narrowing or reordering the curve preference is actually advertised on builds that honor `groups`."
51
+ },
52
+ {
53
+ "title": "Reserved-word identifier parity for operator-supplied table and column names",
54
+ "body": "Several sites that quote an operator- or schema-supplied identifier -- CSV export, the outbox and webhook table-name guards, the DSR ticket store, the Postgres row-level-security emitter, and the view declarator -- rejected a schema-valid name that collides with a SQL keyword, stricter than b.db.from() which permits it. Those sites now match db.from()'s parity (still failing closed on shape, length, null bytes, and the reserved table prefix)."
55
+ }
56
+ ]
57
+ },
58
+ {
59
+ "heading": "Added",
60
+ "items": [
61
+ {
62
+ "title": "New primitives across the watcher, self-update, daemon, crypto, SSRF, redaction, and object surfaces",
63
+ "body": "b.watcher exports its ignore-pattern length and wildcard caps so a consumer pre-filter aligns with what create() enforces. b.selfUpdate gains a post-install probation lifecycle (beginProbation / confirmHealthy / evaluateOnBoot) that distinguishes a clean stop from a crash and decides a next-boot rollback. b.daemon gains a read-only status() PID-probe and, on Windows, a cooperative stop-request channel so stop() can drain the graceful-shutdown orchestration instead of a hard terminate. b.crypto adds spkiPin / spkiPinVerifier (above). b.ssrfGuard adds isLoopbackHost / isExactLoopbackName (above). b.redact adds redactText (above). And b.safeObject.ownProp / ownSet provide one prototype-pollution-safe own-property get/set that the framework's interpolators compose instead of re-rolling a guarded read."
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ "heading": "Changed",
69
+ "items": [
70
+ {
71
+ "title": "Public Suffix List refreshed to the current upstream snapshot",
72
+ "body": "The vendored Mozilla Public Suffix List is updated to the current upstream snapshot, so organizational-domain derivation reflects the latest registry delegations wherever the framework draws a registrable-domain boundary -- DMARC identifier alignment, BIMI issuer scoping, cookie-scope confinement, and same-site policy. The .data.js carrier is regenerated and re-signed across all four integrity layers."
73
+ }
74
+ ]
75
+ }
76
+ ]
77
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.14",
4
+ "date": "2026-07-23",
5
+ "headline": "The framework's file watchers are hardened against an uncatchable process abort on Windows 8.3 short-name paths",
6
+ "summary": "fs.watch aborts the whole Node process -- an uncatchable libuv assertion in the directory-change backend -- when the watched path is reached through a Windows 8.3 short-name component (the shape of a path under C:\\Users\\SOMEUS~1\\... or a short-named temp directory). The recursive file watcher already expanded the short name before watching; this closes the same gap everywhere else the framework watches a path: the feature-flag file watcher now stat-polls its config file instead of directory-watching it, and the dev-server and bundler watchers expand the short name before watching. Three structural detectors lock the invariant in so it cannot regress in a way a behavioral test cannot reach (the abort only fires on a real short-name path, which a host with 8.3 generation disabled cannot reproduce).",
7
+ "sections": [
8
+ {
9
+ "heading": "Fixed",
10
+ "items": [
11
+ {
12
+ "title": "The feature-flag file watcher no longer aborts on a Windows short-name config path",
13
+ "body": "b.flags localFile provider with watch enabled directory-watched the config file via fs.watch, which aborts the process (uncatchable) when the config path resolves through a Windows 8.3 short-name component -- its surrounding try/catch cannot recover from a libuv abort(). It now stat-polls the file (StatWatcher opens no directory-change handle, so it is immune to the path form) and reloads on change with sub-second latency."
14
+ },
15
+ {
16
+ "title": "The dev-server and bundler watchers expand a short-name path before watching",
17
+ "body": "b.dev and b.bundler watch a source directory or file via fs.watch; on Windows a path reached through an 8.3 short-name component aborts libuv. Both now resolve the real long-form path (realpathSync.native) before the watch, matching the guard the recursive b.watcher already applied."
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "heading": "Changed",
23
+ "items": [
24
+ {
25
+ "title": "Public Suffix List refreshed to the current upstream snapshot",
26
+ "body": "The vendored Mozilla Public Suffix List is updated to the current upstream snapshot, so organizational-domain derivation reflects the latest registry delegations wherever the framework draws a registrable-domain boundary -- DMARC identifier alignment, BIMI issuer scoping, cookie-scope confinement, and same-site policy. The .data.js carrier is regenerated and re-signed across all four integrity layers."
27
+ }
28
+ ]
29
+ },
30
+ {
31
+ "heading": "Detectors",
32
+ "items": [
33
+ {
34
+ "title": "Filesystem-watch short-name safety and pid-liveness composition are enforced structurally",
35
+ "body": "Three codebase-patterns detectors close invariants a behavioral test cannot assert (the underlying abort is environment-specific to a real 8.3 short-name path): any lib fs.watch must expand the short name via realpathSync.native in the same file (or use the StatWatcher path instead); the daemon's Windows cooperative-stop sentinel must poll a synchronous existsSync rather than watch the filesystem; and a signal-0 process-liveness probe must compose the shared pid-probe classifier rather than re-roll process.kill(pid, 0) with its own EPERM/ESRCH interpretation."
36
+ }
37
+ ]
38
+ }
39
+ ]
40
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.15",
4
+ "date": "2026-07-23",
5
+ "headline": "The standalone multipart parser honors storage: memory and every other documented upload knob",
6
+ "summary": "b.parsers.multipart(req, opts) is documented as a thin wrapper over the same engine b.middleware.bodyParser drives, but its option resolver carried a hand-maintained passthrough list that had drifted: storage (\"disk\" | \"memory\") and filenameCharsets were silently dropped, so a serverless / read-only-filesystem handler passing storage: \"memory\" got disk mode instead and threw when the parser tried to open a temp file. The passthrough is now derived from the parser's own defaults, so every documented knob reaches the standalone path and a future knob cannot silently vanish, and an invalid storage value throws at the call the same way the middleware does instead of falling through to disk.",
7
+ "sections": [
8
+ {
9
+ "heading": "Fixed",
10
+ "items": [
11
+ {
12
+ "title": "b.parsers.multipart honors storage: memory and filenameCharsets",
13
+ "body": "The standalone multipart parser's option resolver passed through a hand-maintained subset of the multipart knobs, omitting storage and filenameCharsets: b.parsers.multipart(req, { storage: \"memory\" }) silently used disk mode and then threw on a read-only / serverless filesystem, and a filename*=ISO-8859-1'' part could not be opted in via filenameCharsets. The passthrough is now derived from the parser's DEFAULTS so every documented knob reaches the standalone path (only the maxBytes/maxFiles aliases and the dispatch-only contentTypes are excluded), and an invalid storage value throws a TypeError at the call rather than falling back to disk -- matching b.middleware.bodyParser."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.16",
4
+ "date": "2026-07-23",
5
+ "headline": "A shared path-containment primitive backs both the strict resolver and static file serving",
6
+ "summary": "b.safePath.resolve and b.staticServe each hand-rolled the same lexical traversal-containment check -- resolve a request path against a base and confirm it stays strictly inside. That core is now one primitive, b.safePath.confineToBase, which both compose: resolve layers its user-input strictness (reserved names, NTFS ADS markers, bidi, control chars) on top, while static serving composes only the bare containment and keeps its own separate basename gate. Static serving keeps that separation deliberately -- its containment barrier and its per-file guardFilename validation are distinct concerns -- and inherits the resolver's cross-platform-aware containment, which the runtime path module missed for a backslash traversal on a POSIX host. Static serving's basename policy is unchanged.",
7
+ "sections": [
8
+ {
9
+ "heading": "Added",
10
+ "items": [
11
+ {
12
+ "title": "b.safePath.confineToBase -- the lexical traversal-containment core",
13
+ "body": "b.safePath.confineToBase(base, rel, opts?) resolves rel against base using the target platform's path semantics and returns the confined absolute path, or null if it escapes. It is the containment barrier b.safePath.resolve layers its user-input strictness on top of, exposed for a consumer that wants ONLY traversal containment and applies its own, differently-calibrated filename validation -- so it does not reject a reserved name, NTFS ADS marker, or trailing dot the way resolve does for untrusted input. opts.platform forces windows path semantics on any host."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "heading": "Changed",
19
+ "items": [
20
+ {
21
+ "title": "Static file serving composes the shared containment primitive",
22
+ "body": "b.staticServe's path-traversal barrier now composes b.safePath.confineToBase for its final lexical containment instead of a hand-rolled join + base-prefix check, so both the strict resolver and static serving route through one implementation. Static serving gains the cross-platform-aware containment (the runtime path module treats the other platform's separator as an ordinary filename character and missed a backslash traversal on a POSIX host). Serve behavior is unchanged: containment and the separate per-file guardFilename basename gate remain distinct steps, and static composes only the containment core rather than resolve so it does not fuse resolve's all-segment user-input strictness into the barrier (which would reject a legitimate colon-named intermediate directory that the basename gate permits). The basename policy itself is untouched."
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.17",
4
+ "date": "2026-07-23",
5
+ "headline": "Three verifier hardening fixes: timestamp trust anchors are required by default, OIDC id_token verification requires a configured issuer, and ed25519 DKIM uses the RFC 8463 raw-key format",
6
+ "summary": "An audit of the signature-verifier surface found three verifiers that accepted or rejected the wrong thing. b.tsa.verifyToken authenticated a timestamp against a certificate embedded in the token itself and only ran the trust-anchor chain when the caller supplied one, so a self-signed token carrying the timestamping EKU was accepted as a valid timestamp; trust anchors are now required by default. b.auth.oauth's verifyIdToken skipped the CVE-2026-23552 cross-realm iss check entirely when the client was created without an issuer, so any OIDC id_token verified regardless of its issuer; an OIDC client must now be configured with an issuer to verify id_tokens. And the ed25519 DKIM verifier could not read the RFC 8463 raw 32-byte key format that every conformant sender publishes -- while the framework's own bootstrap published the non-standard SPKI form -- so ed25519, the default DKIM algorithm, was non-interoperable in both directions.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "Timestamp verification requires a trust anchor by default",
13
+ "body": "b.tsa.verifyToken verified an RFC 3161 timestamp against the signer certificate embedded in the token -- which is attacker-controlled -- and ran the certificate-chain / trust-anchor check only when the caller passed trustAnchorsPem. With it omitted, a token whose self-signed leaf carried a critical, sole id-kp-timeStamping EKU was accepted as a valid timestamp: a forged proof that data existed at an arbitrary time (RFC 3161 §2.4.2 requires a trusted TSA). trustAnchorsPem is now required by default; an operator who deliberately wants trust-anchor-free verification sets allowUntrustedIssuer:true and the result carries issuerTrusted:false so the unauthenticated posture is visible (mirrors b.mdoc.verifyIssuerSigned)."
14
+ },
15
+ {
16
+ "title": "OIDC id_token verification requires a configured issuer",
17
+ "body": "b.auth.oauth.verifyIdToken wrapped the expected-issuer comparison -- the CVE-2026-23552 cross-realm / cross-issuer defense -- in a check that ran only when the client was configured with an issuer. An OIDC client (the default) created without an issuer therefore accepted an id_token with any iss, or none, as long as the signature, aud, and exp were valid: exactly the cross-realm acceptance the verifier exists to close, dangerous against a shared-signing-key multi-tenant OP. verifyIdToken now refuses to verify an OIDC id_token when no expected issuer is configured (OIDC Core §3.1.3.7); pass issuer to b.auth.oauth.create()."
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "heading": "Fixed",
23
+ "items": [
24
+ {
25
+ "title": "ed25519 DKIM uses the RFC 8463 raw-key format on both sign and verify",
26
+ "body": "RFC 8463 §3-4 publishes an ed25519 DKIM public key as the raw 32-byte key, base64'd -- the form every conformant sender uses -- but the verifier wrapped that raw key in SubjectPublicKeyInfo PEM markers, which is not valid SPKI, so createPublicKey threw and a valid ed25519 signature returned permerror. Compounding it, b.mail.dkim.bootstrap published the key as SPKI DER (60 base64 chars) instead of the raw form (44 chars), so the framework's own default-algorithm signatures would not verify at a conformant receiver. The verifier now accepts a raw 32-byte key (wrapping it in the ed25519 SPKI header) and bootstrap publishes the raw key; RSA is unchanged. The same raw-key handling is applied on the ARC (b.mail.arc.verify) message-signature path."
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.18",
4
+ "date": "2026-07-24",
5
+ "headline": "`b.i18n` validates every inline translation tree at boot, closing a path where t() could return undefined",
6
+ "summary": "b.i18n.create validated the translation trees only for the locales listed in the configured locales array. A locale present in the inline translations map but absent from locales is still reachable through an explicit t(key, vars, { locale }) override, and its tree escaped validation: a plural entry there missing the mandatory CLDR 'other' category made t() with a count return undefined instead of the key -- a contract violation that could render the literal string 'undefined' into server-rendered HTML or crash a downstream length/escape. Every inline translation tree is now validated at create, so a malformed one fails closed at boot rather than at the first request that reaches it.",
7
+ "sections": [
8
+ {
9
+ "heading": "Fixed",
10
+ "items": [
11
+ {
12
+ "title": "Every inline translation tree is validated at create, not only the configured locales",
13
+ "body": "b.i18n.create walked only opts.locales when validating translation trees up front, so a locale that appears in opts.translations but not in opts.locales was never checked even though it is reachable via an explicit locale override on t()/has(). A plural entry in such a tree that omits the mandatory 'other' category caused t(key, { count }) to select 'other', find nothing, and return undefined -- violating the documented contract that t() returns a string (the key on a miss) and never a non-string. create now validates every key of opts.translations, so a malformed tree is rejected at boot regardless of whether its locale is in opts.locales."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.19",
4
+ "date": "2026-07-24",
5
+ "headline": "The error and adversarial paths of the sanctions-screening, JSON Schema, and HTTP client primitives are now under test",
6
+ "summary": "This release adds no behaviour change. The fail-closed error paths, boundary conditions, and adversarial-input handling of b.complianceSanctions, b.jsonSchema, and b.httpClient -- previously exercised only on their happy paths -- are now asserted, verifying that each rejects malformed input, unresolvable references, and edge cases the documented contract already promised. No defects were found; the primitives behaved as specified. Genuinely-unreachable defensive fallbacks are documented rather than contorted into coverage.",
7
+ "sections": [
8
+ {
9
+ "heading": "Changed",
10
+ "items": [
11
+ {
12
+ "title": "Verified error-path behaviour for sanctions screening, JSON Schema, and the HTTP client",
13
+ "body": "The sanctions-screening list parsers (OFAC SDN/alias, EU CSL, UN 1267), the fuzzy/exact match strategy toggle, and the entry normalizer; the JSON Schema $ref/$dynamicRef resolution, JSON-pointer traversal, format assertions, and unevaluated-properties/items handling; and the HTTP client's error, redirect, and stream branches now have explicit tests for their failure and boundary behaviour. Behaviour is unchanged -- these assert guarantees the primitives already met -- so no migration is needed; the value is regression protection for the fail-closed paths of security-relevant primitives."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.2",
4
+ "date": "2026-07-17",
5
+ "headline": "Recurrence expansion refuses to spin or crash on an out-of-range interval, the CIDR guard rejects the whole of the ULA and link-local IPv6 ranges, and a device-bound session assertion no longer accepts a far-future issued-at",
6
+ "summary": "b.calendar.expandRecurrence accepted an unbounded, unvalidated recurrence interval; a large interval drove its date arithmetic past the representable range, which either spun the expansion loop forever at full CPU (a denial of service reachable from any JSCalendar event in a request body) or threw an uncaught error that crashed the caller. The expander now stops as soon as the date arithmetic overflows. b.guardCidr tested IPv6 reserved-range membership on whole hex nibbles, so it missed the parts of the ULA (fc00::/7) and link-local (fe80::/10) ranges that do not fall on a nibble boundary -- accepting fd00::/8 and several fe80::/10 sub-ranges as clean under the strict profile that is supposed to refuse them. And b.dbsc.verifyBindingAssertion bounded the assertion's issued-at only from below, so a far-future issued-at was accepted and never aged out of the replay window.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "Recurrence expansion refuses an out-of-range interval instead of hanging or crashing",
13
+ "body": "b.calendar.expandRecurrence validated a recurrence rule's frequency but not its interval, so a caller-supplied interval was used unbounded. A large interval drives the expander's date arithmetic past the representable ECMAScript date range and yields a non-finite date, with two consequences from the one root: with a by-set-position rule the outer loop computed a non-finite period whose inner day-enumeration ran zero times, so the shared step budget never decremented and the not-after break comparisons (which compare against a non-finite value) never fired -- an infinite loop pinning a CPU at 100%; without by-set-position, the loop advanced to a non-finite date and threw an uncaught error when serializing it. Because the rule passed validation, any attacker supplying a JSCalendar event (a JMAP request body, an imported calendar) could trigger it. The expander now stops stepping as soon as the date arithmetic overflows the representable range -- no further instances can exist -- so a hostile interval yields the finite instances that fit and returns, rather than hanging or crashing."
14
+ },
15
+ {
16
+ "title": "CIDR guard rejects the full ULA and link-local IPv6 ranges under the strict profile",
17
+ "body": "b.guardCidr tested whether an IPv6 address falls in a reserved range by comparing hex-nibble prefixes with a string prefix match. Reserved membership is a bit-prefix relation, and the unique-local (fc00::/7, 7 bits) and link-local (fe80::/10, 10 bits) ranges end mid-nibble, so the nibble comparison covered only fc00-fcff and fe80-fe8f -- it missed fd00::/8 (the half of the ULA block that real deployments actually assign) and the fe90::/16 through febf::/16 sub-ranges of link-local. Under the strict profile, which refuses reserved ranges, those CIDRs were accepted as clean and sanitize normalized them into place instead of refusing them. The reserved-range check now compares the whole nibbles and then the remaining prefix bits of the boundary nibble under a mask -- the same bit-prefix relation the IPv4 path and the SSRF guard already use -- so the entire reserved range is caught; nibble-aligned ranges (documentation, multicast, loopback) are unaffected."
18
+ },
19
+ {
20
+ "title": "Device-bound session assertions reject a far-future issued-at",
21
+ "body": "b.dbsc.verifyBindingAssertion enforced the assertion's issued-at only as a lower bound (refusing one older than the configured max age), with no upper bound. A forward-dated issued-at makes the age check compare a negative interval, which never trips, so an assertion carrying an issued-at far in the future was accepted and could not age out of the replay window on the default 300-second path. verifyBindingAssertion now also refuses an issued-at more than a small clock-skew allowance in the future, matching the future-issued-at bound the JWT, DPoP, and client-attestation verifiers already enforce."
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.20",
4
+ "date": "2026-07-24",
5
+ "headline": "`b.forms.validate` enforces required checkboxes server-side and rejects malformed field bounds, closing two validation gaps",
6
+ "summary": "b.forms.validate previously let an unchecked required checkbox pass: the renderer emits the HTML `required` attribute for it, but the server-side validator skipped the check, so a client that omitted the box -- or any non-browser caller -- bypassed a constraint the form advertised. It now rejects an unchecked required checkbox, keeping backend validation in lock-step with what the form displays. Separately, a field whose numeric bound (min/max/minlength/maxlength) was not a finite number went silently unenforced -- a NaN comparison is always false -- so the bound became a no-op; validate now throws on such a spec at the entry point, the same way it already rejects a non-precompiled regex pattern. Two smaller fixes: a field rendered without an explicit type now emits type=\"text\" (matching the widget it dispatches to) rather than an empty type attribute, and b.externalDb reports EXPLAIN statements as row-returning so a query plan's rows are not dropped by the local-execution row/no-row chooser.",
7
+ "sections": [
8
+ {
9
+ "heading": "Fixed",
10
+ "items": [
11
+ {
12
+ "title": "Required checkboxes are enforced server-side in b.forms.validate",
13
+ "body": "A checkbox marked required is rendered with the HTML `required` attribute, but validate() treated an unchecked box (which coerces to false) as satisfying the field, so an unchecked required checkbox passed. Any caller that skipped the box -- a scripted client, or a browser with the constraint stripped -- bypassed a documented requirement. validate() now returns an error for an unchecked required checkbox (honouring the field's errorMessages.required), so the backend enforces the same constraint the frontend shows. A form that relied on the previous pass-through for an unchecked required checkbox will now surface a validation error, which is the intended behaviour."
14
+ },
15
+ {
16
+ "title": "A malformed numeric field bound is rejected instead of silently ignored",
17
+ "body": "When a field's min, max, minlength, or maxlength was not a finite number (a non-numeric string, NaN, or Infinity), its comparison could never fire -- a NaN comparison is always false -- so the bound was quietly unenforced while appearing to constrain the field. validate() now throws at the entry point when a defined bound is non-finite, matching how it already requires pattern to be a pre-compiled RegExp. Numeric-string bounds (e.g. min: \"1\") remain accepted."
18
+ },
19
+ {
20
+ "title": "A typeless field renders type=\"text\" instead of an empty type attribute",
21
+ "body": "b.forms.render dispatches a field with no explicit type to a text input, but the emitted markup carried type=\"\" rather than type=\"text\". The rendered type attribute now matches the widget dispatched, so the markup is self-consistent."
22
+ },
23
+ {
24
+ "title": "b.externalDb reports EXPLAIN statements as row-returning",
25
+ "body": "statementReturnsRows classified a plain EXPLAIN (and an EXPLAIN ANALYZE wrapping a write) as producing no row set, so the local-execution path could route it to a no-row call and drop the query plan. EXPLAIN always returns plan rows to the caller; it is now reported as row-returning whenever its prefix resolves, while an unparseable EXPLAIN prefix stays fail-closed. This is distinct from the cross-border residency read/write classification, which is unchanged."
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ "heading": "Changed",
31
+ "items": [
32
+ {
33
+ "title": "b.forms.validate option reference corrected",
34
+ "body": "The validate() reference described length bounds as minLength/maxLength, but the option keys are the HTML-attribute spellings minlength/maxlength (the same keys the renderer reads); the reference and its example are corrected, and the example now uses a numeric min bound on its number field."
35
+ },
36
+ {
37
+ "title": "Vendored Public Suffix List refreshed to the current snapshot",
38
+ "body": "The bundled Public Suffix List that backs domain classification (registrable-domain and public-suffix checks in URL, cookie, and SSRF handling) is updated to the latest upstream publicsuffix.org snapshot, so newly delegated public suffixes and private-domain entries are recognized."
39
+ }
40
+ ]
41
+ }
42
+ ]
43
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.21",
4
+ "date": "2026-07-25",
5
+ "headline": "`blamejs erase` treats only `--confirm true` as confirmation, so `--confirm false` no longer triggers the irreversible erase",
6
+ "summary": "Three fixes to the blamejs command line. The `erase` subcommand (a cryptographic single-row erase) gated its irreversible action on a bare-truthiness check, so `--confirm false` -- a string -- counted as confirmation and the erase proceeded; the gate now accepts only `true` / \"true\", matching `audit purge`, and refuses anything else. A stray `-v` / `--version` token alongside a subcommand no longer short-circuits to the version print: `blamejs migrate up --db x -v` previously returned 0 after printing the version without running the migration, handing automation a false pass; the version flag is now honored only when it is the whole invocation. And `blamejs dev` now survives a crash of the watched child -- it stays up to hot-restart on the next file change instead of draining the event loop and exiting 0 -- and awaits the child's full termination on SIGINT/SIGTERM so a shutdown cannot orphan it.",
7
+ "sections": [
8
+ {
9
+ "heading": "Fixed",
10
+ "items": [
11
+ {
12
+ "title": "blamejs erase refuses --confirm false instead of performing the irreversible erase",
13
+ "body": "The erase subcommand confirmed its irreversible action with a bare-truthiness check, so the string `--confirm false` was treated as confirmation and the erase ran. Confirmation is now satisfied only by `--confirm true` (or the bare `--confirm`), matching the check `audit purge` already used; any other value -- including `false` -- is refused with a non-zero exit and no erase. A shared confirmation helper backs every destructive subcommand so the acknowledgement contract cannot drift between them."
14
+ },
15
+ {
16
+ "title": "A stray -v / --version no longer turns a subcommand into a silent no-op",
17
+ "body": "The top-level version flag was evaluated before subcommand dispatch and returned 0 whenever `-v` / `--version` appeared anywhere in the arguments, so a consequential command such as `migrate up`, `seed run`, or `erase` alongside a stray `-v` printed the version and exited 0 without doing anything -- a false success for any script checking the exit code. The version flag is now honored only when the invocation carries no subcommand; otherwise the subcommand runs (or fails) as written."
18
+ },
19
+ {
20
+ "title": "blamejs dev survives a watched-child crash and shuts the child down cleanly",
21
+ "body": "The dev supervisor held the event loop open with an unref'd timer, so when the watched child process crashed the supervisor drained the loop and exited 0 -- defeating crash-resilience (it should stay up and hot-restart on the next file change) and reporting success even though the app had crashed. It now holds a referenced heartbeat so a child crash leaves the supervisor running, and on SIGINT/SIGTERM it awaits the child's full termination (graceful signal, then escalation) before exiting, so a shutdown can no longer race ahead and orphan the child."
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.22",
4
+ "date": "2026-07-25",
5
+ "headline": "`b.network.tls.checkServerIdentity9525` parses subjectAltName quote-aware, closing a hostname-verification bypass",
6
+ "summary": "The strict RFC 9525 identity verifier parsed Node's subjectAltName string with a naive comma split, ignoring the JSON-quoted encoding Node emits for a SAN value that itself contains separators (the CVE-2021-44531/44532 remediation). A certificate whose single dNSName is a quoted blob such as `DNS:\"x, DNS:victim.com, y\"` was broken into pieces by the split, smuggling a clean `victim.com` token the certificate never asserts -- so checkServerIdentity9525 ACCEPTED a host that Node's own tls.checkServerIdentity REJECTS (ERR_TLS_CERT_ALTNAME_INVALID). The verifier now splits SAN entries on commas outside quotes and JSON-decodes quoted spans, matching Node's splitEscapedAltNames, so it asserts only the certificate's actual dNSName / IP values and is at least as strict as the function it advertises replacing. This path gates peer identity in b.crypto.spkiPinVerifier.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "checkServerIdentity9525 no longer accepts a hostname smuggled through a quoted subjectAltName",
13
+ "body": "Node renders a subjectAltName value that contains commas or control characters as a JSON-quoted string, so a single dNSName whose value is `x, DNS:victim.com, y` appears in cert.subjectaltname as `DNS:\"x, DNS:victim.com, y\"`. The verifier's SAN parser split that raw string on every comma, turning one entry into several and extracting a `DNS:victim.com` token the certificate does not actually present -- a hostname-verification bypass, since a strict RFC 9525 drop-in must be no weaker than the Node function it replaces (which rejects this cert). The parser now mirrors Node's splitEscapedAltNames: it splits only on commas outside quotes and JSON-decodes quoted spans, so each parsed dNSName is exactly one GeneralName and a smuggled name can no longer match. Malformed SAN quoting fails closed (asserts no identifiers). Operators using b.network.tls.checkServerIdentity9525 (directly or via b.crypto.spkiPinVerifier) should upgrade."
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.17.3",
4
+ "date": "2026-07-17",
5
+ "headline": "A family of security guards that compared a token case-sensitively where the browser or HTTP stack matches it case-insensitively now normalize first, closing a CSP unsafe-keyword bypass and a cookie-prefix bypass and fixing several over-strict refusals of spec-compliant input",
6
+ "summary": "Browsers, HTTP stacks, and URL parsers match a whole family of security-relevant tokens ASCII case-insensitively -- CSP source keywords and scheme sources, the __Secure-/__Host- cookie name prefixes, HTTP auth schemes, media types, and URL schemes. Several framework guards compared those tokens case-sensitively, so a mixed-case variant behaved differently in the guard than it does downstream. In the bypass direction this let a case-variant unsafe CSP keyword reach a header the browser still honors, and let a prefix-violating cookie past the invariant that keeps the browser from silently dropping it. In the over-strict direction it wrongly refused spec-compliant input (a lowercase auth scheme, a mixed-case media type, an uppercase URL scheme, a mixed-case operator allowlist entry). Every case now normalizes the token to ASCII lowercase before the membership, equality, or prefix test. Separately, two crypto algorithm-name lookups and a CBOR integer-boundary round-trip are corrected.",
7
+ "sections": [
8
+ {
9
+ "heading": "Security",
10
+ "items": [
11
+ {
12
+ "title": "CSP builder refuses unsafe keywords and catch-all schemes in any case",
13
+ "body": "b.csp.build screened its source tokens ('unsafe-inline', 'unsafe-eval', 'unsafe-hashes', the catch-all '*'/'https:', and 'data:' in img/media/font) against its guard sets with a case-sensitive comparison. A User-Agent matches CSP keywords and scheme sources ASCII case-insensitively (CSP3 §2.3/§6.7.2), so a case-variant such as 'Unsafe-Inline', 'HTTPS:', or 'DATA:' slipped the guard and was emitted verbatim into a Content-Security-Policy header the browser still enforces -- reintroducing the exact XSS-defense hole the guard exists to refuse, without the required acknowledgement opt-in. The builder now lowercases each token before the membership test; the original case is still emitted for real hosts and paths, only the guard comparison is normalized. mergeDirectives routes added sources through the same guard, so a case-variant in a merged policy is refused too."
14
+ },
15
+ {
16
+ "title": "Cookie name-prefix invariants hold for any case of __Secure-/__Host-",
17
+ "body": "Browsers apply the __Secure-/__Host- cookie name-prefix requirements (RFC 6265bis §4.1.3) case-insensitively -- they lowercase the cookie name before the prefix test. b.cookies.serialize and the CSRF middleware's cookie-name safety check compared the prefix case-sensitively, so a case-variant name like __host- or __SECURE- dodged the framework's Secure/Path=//no-Domain invariant while still being subject to the browser's enforcement -- the cookie would then be silently rejected by the browser (never set), defeating the middleware or session it belonged to. Both now compare a lowercased copy of the name, so a prefix-violating cookie is refused at the source for every case. The CSRF middleware, which builds its own Set-Cookie header rather than routing through serialize, additionally gained the __Secure- branch it was missing entirely."
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "heading": "Fixed",
23
+ "items": [
24
+ {
25
+ "title": "Auth scheme, media type, and URL scheme comparisons accept spec-compliant case variants",
26
+ "body": "Three guards refused input that a case-insensitive downstream would accept. The CIBA notification endpoint (b.auth.ciba) matched the Authorization Bearer scheme case-sensitively, rejecting a spec-compliant 'bearer <token>' sender (RFC 7235 auth-schemes are case-insensitive); it now matches the scheme case-insensitively while comparing the token itself verbatim. The tus upload middleware's creation-with-upload path compared the application/offset+octet-stream media type as an exact string, so a compliant 'Application/Offset+Octet-Stream' (or a variant carrying a parameter) created the upload but silently dropped the body; it now compares the lowercased media type with parameters stripped (RFC 7231 §3.1.1.1). The NEL middleware required its collector URL to begin with a lowercase 'https://', rejecting an equivalent 'HTTPS://'; it now compares the scheme case-insensitively (RFC 3986)."
27
+ },
28
+ {
29
+ "title": "Redirect allowlist matches a mixed-case operator origin or host",
30
+ "body": "b.safeRedirect.resolve compared the parser-canonicalized (lowercased) origin and host of a candidate URL against the operator's allowedOrigins/allowedHosts entries verbatim. A mixed-case operator entry such as 'Example.COM' or 'HTTPS://Example.com' therefore silently never matched, and a legitimate redirect fell through to the fallback. The operator entries are now canonicalized to lowercase before the comparison. This only makes the operator's intended allowlist work; because the attacker-controlled target is already normalized by the parser, it never widens the allowlist."
31
+ },
32
+ {
33
+ "title": "Streaming-hash and OPRF suite selection reject an unknown algorithm name cleanly",
34
+ "body": "b.crypto.hashStream (and b.crypto.hashFile, which composes it) and b.crypto.oprf.suite resolved a caller-supplied algorithm/suite name against a plain-object lookup table with a truthiness check. A name colliding with an inherited Object.prototype member -- 'constructor' or '__proto__' -- read back a truthy inherited value and slipped the guard: hashStream then threw a synchronous TypeError from a function documented to return a rejected Promise (an unhandled exception for a caller wired only to .catch()), and oprf.suite returned a malformed suite object instead of throwing its documented bad-suite error. Both now resolve the name through an own-property check, matching the guarding used for the SRI algorithm table, so any unknown name is refused with the documented error."
35
+ },
36
+ {
37
+ "title": "Deterministic CBOR re-encodes a negative integer at the -2^53 boundary as an integer",
38
+ "body": "The CBOR decoder returned the negative integer at the -2^53 boundary as a plain Number, but that value is one below the safe-integer range, so the deterministic encoder's integer branch re-emitted it as a float -- breaking round-trip and falsely tripping the requireDeterministic check on a value that is canonically an integer. The decoder now promotes a negative integer that is not a safe integer to a BigInt, so the encoder re-emits the integer head (RFC 8949 §3)."
39
+ }
40
+ ]
41
+ }
42
+ ]
43
+ }