@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
@@ -353,6 +353,31 @@ async function testDkimVerifyHappyPath() {
353
353
  check("verify: warnings array on pass", Array.isArray(rv[0].warnings));
354
354
  }
355
355
 
356
+ async function testDkimVerifyBareLfMessage() {
357
+ // A message signed on the CRLF wire but read back from a Unix file /
358
+ // mbox (CRs stripped) arrives bare-LF. The public verifier must
359
+ // normalize it to canonical CRLF and verify — not throw an uncaught
360
+ // dkim/missing-body-separator out of the header/body split. RED before
361
+ // the _splitHeadersBody LF->CRLF normalization: verify() threw.
362
+ // Reset the process-local DKIM key cache: a prior test cached a different
363
+ // key under the same example.com/s1 selector, which would otherwise shadow
364
+ // this message's key (the cache is consulted before the injected dnsLookup).
365
+ b.mail.dkim._resetDkimKeyCacheForTest();
366
+ var kp = _rsaKeypair();
367
+ var signed = await _signedMessage(kp);
368
+ var bareLf = signed.replace(/\r\n/g, "\n");
369
+ var b64 = _spkiPemToB64(kp.publicKey);
370
+ var dnsLookup = async function () { return [["v=DKIM1; k=rsa; p=" + b64]]; };
371
+ var threw = null;
372
+ var rv = null;
373
+ try { rv = await b.mail.dkim.verify(bareLf, { dnsLookup: dnsLookup }); }
374
+ catch (e) { threw = e; }
375
+ check("verify: bare-LF message does not throw", threw === null);
376
+ check("verify: bare-LF message returns a verdict array", Array.isArray(rv));
377
+ check("verify: CRLF-signed message transported bare-LF verifies pass",
378
+ rv && rv[0] && rv[0].result === "pass");
379
+ }
380
+
356
381
  async function testDkimVerifyKeyCacheHit() {
357
382
  // Same selector/domain twice → second fetch must hit cache.
358
383
  b.mail.dkim._resetDkimKeyCacheForTest();
@@ -798,6 +823,773 @@ async function testArcAmsLTagAppendRefused() {
798
823
  rv[0] && rv[0].result === "fail");
799
824
  }
800
825
 
826
+ // ---- Coverage: uncovered error / adversarial / defensive / option-default
827
+ // branches (sign + verify). Each drives the REAL b.mail.dkim consumer
828
+ // path with an injected DNS stub — never real DNS. ----
829
+
830
+ // Body-hash (relaxed) helper mirroring lib _bodyHashB64 with the default
831
+ // (no l=) path, so an adversarial signature can carry a body-correct bh=
832
+ // and reach the header / key / algorithm guards past the body-hash gate.
833
+ function _relaxedBodyHash(body) {
834
+ var canon = b.mail.dkim._canonBodyRelaxedForTest(body);
835
+ return nodeCrypto.createHash("sha256").update(Buffer.from(canon, "utf8")).digest("base64");
836
+ }
837
+
838
+ // Build a message with an arbitrary DKIM-Signature tag list. Used for the
839
+ // adversarial-verify cases whose verdict is decided BEFORE cryptographic
840
+ // verification (v=, x=/t=, missing d/s, missing bh/b, h= without from) — so
841
+ // the b= value need not be a valid signature.
842
+ function _messageWithSig(tags, body) {
843
+ return "From: alice@example.com\r\n" +
844
+ "DKIM-Signature: " + tags.join("; ") + "\r\n" +
845
+ "\r\n" + (body === undefined ? "Hi\r\n" : body);
846
+ }
847
+
848
+ // Build a FULLY-VALID relaxed/relaxed single-signature message (h=from)
849
+ // with optional extra tags (t=, x=, l=) folded into the signed content, so
850
+ // the signature verifies and the run reaches _verifySingleSignature's
851
+ // pass path. Mirrors the manual construction the l= tests already use.
852
+ function _buildRelaxedSigned(kp, domain, selector, extraTags, body) {
853
+ var dkim = b.mail.dkim;
854
+ body = body === undefined ? "Hello world.\r\n" : body;
855
+ var bh = _relaxedBodyHash(body);
856
+ var fromValue = " Alice <alice@" + domain + ">";
857
+ var tags = ["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
858
+ "d=" + domain, "s=" + selector, "h=from", "bh=" + bh];
859
+ if (extraTags) tags = tags.concat(extraTags);
860
+ tags.push("b=");
861
+ var unsigned = tags.join("; ");
862
+ var canonHeaders =
863
+ dkim._canonHeaderRelaxedForTest("From", fromValue) +
864
+ dkim._canonHeaderRelaxedForTest("DKIM-Signature", unsigned).replace(/\r\n$/, "");
865
+ var sig = nodeCrypto.createSign("RSA-SHA256").update(canonHeaders)
866
+ .sign(kp.privateKey).toString("base64");
867
+ var finalSig = unsigned.replace(/b=$/, "b=" + sig);
868
+ return "From:" + fromValue + "\r\n" +
869
+ "DKIM-Signature: " + finalSig + "\r\n" +
870
+ "\r\n" + body;
871
+ }
872
+
873
+ // ---- create() input-shape branches ----
874
+
875
+ function testDkimCreateInputBranches() {
876
+ var kp = _rsaKeypair();
877
+
878
+ // headersToSign element that isn't a non-empty string → bad-headers.
879
+ var threw = null;
880
+ try {
881
+ b.mail.dkim.create({ domain: "example.com", selector: "s1",
882
+ privateKey: kp.privateKey, headersToSign: ["from", 123] });
883
+ } catch (e) { threw = e; }
884
+ check("create: non-string headersToSign element → bad-headers",
885
+ threw && /dkim\/bad-headers/.test(threw.code || ""));
886
+
887
+ // privateKey of a non-string / non-object type → missing-private-key.
888
+ threw = null;
889
+ try {
890
+ b.mail.dkim.create({ domain: "example.com", selector: "s1", privateKey: 123 });
891
+ } catch (e) { threw = e; }
892
+ check("create: numeric privateKey → missing-private-key",
893
+ threw && /dkim\/missing-private-key/.test(threw.code || ""));
894
+
895
+ // privateKey as a Buffer (Buffer.isBuffer branch) → parses + signs.
896
+ var bufSigner = b.mail.dkim.create({ domain: "example.com", selector: "s1",
897
+ privateKey: Buffer.from(kp.privateKey, "utf8") });
898
+ check("create: accepts a Buffer PEM privateKey",
899
+ typeof bufSigner.sign === "function");
900
+
901
+ // privateKey as a pre-built crypto.KeyObject (the non-string, non-Buffer
902
+ // object branch — used directly without re-parsing).
903
+ var keyObj = nodeCrypto.createPrivateKey({ key: kp.privateKey, format: "pem" });
904
+ var koSigner = b.mail.dkim.create({ domain: "example.com", selector: "s1",
905
+ privateKey: keyObj });
906
+ var koSigned = koSigner.sign(
907
+ "From: a@example.com\r\nSubject: t\r\n\r\nbody\r\n");
908
+ check("create: accepts a crypto.KeyObject privateKey and signs",
909
+ /^DKIM-Signature: /.test(koSigned));
910
+
911
+ // create() with no argument object at all → opts defaults to {} then the
912
+ // domain guard throws (the opts || {} default branch).
913
+ threw = null;
914
+ try { b.mail.dkim.create(); } catch (e) { threw = e; }
915
+ check("create: no argument → bad-domain",
916
+ threw && /dkim\/bad-domain/.test(threw.code || ""));
917
+ }
918
+
919
+ function testDkimSignerAuditDisabled() {
920
+ // audit:false suppresses the sign-success + missing-header audit emits
921
+ // (the auditOn === false option-default branch), and signing still works.
922
+ var kp = _rsaKeypair();
923
+ var signer = b.mail.dkim.create({
924
+ domain: "noaudit.example", selector: "na",
925
+ privateKey: kp.privateKey, audit: false,
926
+ headersToSign: ["from", "subject", "x-absent-header"],
927
+ });
928
+ var signed = signer.sign(
929
+ "From: a@noaudit.example\r\nSubject: t\r\nDate: Mon, 5 May 2026 12:00:00 +0000\r\n" +
930
+ "Message-ID: <n@noaudit.example>\r\n\r\nbody\r\n");
931
+ check("create audit:false → signs with audit emits suppressed",
932
+ /^DKIM-Signature: /.test(signed));
933
+ }
934
+
935
+ async function testDkimEd25519VerifyRoundTrip() {
936
+ // The ed25519-sha256 VERIFY path (RFC 8463): sign then verify against the
937
+ // published k=ed25519 key. Exercises the ed25519 nodeAlgo=null verify
938
+ // branch that the RSA round-trips never reach.
939
+ var kp = _ed25519Keypair();
940
+ b.mail.dkim._resetDkimKeyCacheForTest();
941
+ var signer = b.mail.dkim.create({
942
+ domain: "ed.example", selector: "e1",
943
+ privateKey: kp.privateKey, algorithm: "ed25519-sha256",
944
+ });
945
+ var msg =
946
+ "From: alice@ed.example\r\nTo: bob@example.org\r\nSubject: Ed\r\n" +
947
+ "Date: Mon, 5 May 2026 12:00:00 +0000\r\nMessage-ID: <ed@example.com>\r\n\r\nBody\r\n";
948
+ var signed = signer.sign(msg);
949
+ var b64 = _spkiPemToB64(kp.publicKey);
950
+ var rv = await b.mail.dkim.verify(signed,
951
+ { dnsLookup: async function () { return [["v=DKIM1; k=ed25519; p=" + b64]]; } });
952
+ check("ed25519 verify: round-trip passes (RFC 8463)",
953
+ rv[0] && rv[0].result === "pass");
954
+ }
955
+
956
+ // ---- simple/* canonicalization sign + verify round-trips ----
957
+
958
+ function testDkimSimpleCanonDirect() {
959
+ var sb = b.mail.dkim._canonBodySimpleForTest;
960
+ var rb = b.mail.dkim._canonBodyRelaxedForTest;
961
+ // simple body: strips trailing empty lines (the while-loop branch).
962
+ check("simple body: strips trailing empty lines",
963
+ sb("hi\r\n\r\n\r\n") === "hi\r\n");
964
+ // simple body: a body with no trailing CRLF gains one.
965
+ check("simple body: appends missing trailing CRLF",
966
+ sb("hi") === "hi\r\n");
967
+ // relaxed body: an all-empty-line body collapses to a bare CRLF.
968
+ check("relaxed body: all-empty-line body → bare CRLF",
969
+ rb("\r\n\r\n") === "\r\n");
970
+ }
971
+
972
+ async function testDkimSimpleCanonRoundTrips() {
973
+ // relaxed/simple exercises SIMPLE BODY canonicalization on both the sign
974
+ // and verify sides; the header canon stays relaxed (which unfolds the
975
+ // folded DKIM-Signature header) so the round-trip is RFC-correct and
976
+ // passes. This is the legitimate simple-body coverage path.
977
+ var kpB = _rsaKeypair();
978
+ b.mail.dkim._resetDkimKeyCacheForTest();
979
+ var signerB = b.mail.dkim.create({
980
+ domain: "sbody.example", selector: "sb",
981
+ privateKey: kpB.privateKey, canonicalization: "relaxed/simple",
982
+ });
983
+ var msgB =
984
+ "From: alice@sbody.example\r\nTo: bob@example.org\r\n" +
985
+ "Subject: Simple body\r\nDate: Mon, 5 May 2026 12:00:00 +0000\r\n" +
986
+ "Message-ID: <sb@example.com>\r\n\r\nLine one\r\nLine two\r\n\r\n";
987
+ var signedB = signerB.sign(msgB);
988
+ check("relaxed/simple sign: emits c=relaxed/simple",
989
+ signedB.indexOf("c=relaxed/simple") !== -1);
990
+ var b64B = _spkiPemToB64(kpB.publicKey);
991
+ var rvB = await b.mail.dkim.verify(signedB,
992
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p=" + b64B]]; } });
993
+ check("relaxed/simple verify: simple-body round-trip passes",
994
+ rvB[0] && rvB[0].result === "pass");
995
+
996
+ // simple HEADER canonicalization (simple/simple, simple/relaxed) drives
997
+ // the _canonHeaderSimple sign + verify branches. NOTE: the framework
998
+ // signer signs the UNFOLDED DKIM-Signature tag string, but the wire
999
+ // header is folded (CRLF+WSP) and simple header canonicalization does not
1000
+ // unfold — so the verifier canonicalizes different bytes than were signed
1001
+ // and the self-verify does NOT pass. This documents current behavior; see
1002
+ // the reported simple-header-canon signature-computation bug.
1003
+ var simpleHeaderCanons = ["simple/simple", "simple/relaxed"];
1004
+ for (var si = 0; si < simpleHeaderCanons.length; si += 1) {
1005
+ var canon = simpleHeaderCanons[si];
1006
+ var kp = _rsaKeypair();
1007
+ b.mail.dkim._resetDkimKeyCacheForTest();
1008
+ var signer = b.mail.dkim.create({
1009
+ domain: "shdr" + si + ".example", selector: "sh" + si,
1010
+ privateKey: kp.privateKey, canonicalization: canon,
1011
+ });
1012
+ var msg =
1013
+ "From: alice@shdr" + si + ".example\r\nTo: bob@example.org\r\n" +
1014
+ "Subject: Simple header\r\nDate: Mon, 5 May 2026 12:00:00 +0000\r\n" +
1015
+ "Message-ID: <sh" + si + "@example.com>\r\n\r\nLine one\r\n";
1016
+ var signed = signer.sign(msg);
1017
+ check("simple-header sign: emits c=" + canon,
1018
+ signed.indexOf("c=" + canon) !== -1);
1019
+ var b64 = _spkiPemToB64(kp.publicKey);
1020
+ var dnsLookup = async function () { return [["v=DKIM1; k=rsa; p=" + b64]]; };
1021
+ var rv = await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup });
1022
+ // Simple header canonicalization signs and verifies the DKIM-Signature
1023
+ // header verbatim (folded, one space after the colon) per RFC 6376 §3.4.1,
1024
+ // so a folded simple-header signature now round-trips.
1025
+ check("simple-header verify: folded " + canon + " self-verify passes",
1026
+ rv[0] && rv[0].result === "pass");
1027
+ }
1028
+ }
1029
+
1030
+ async function testDkimSimpleCanonHonorsWireFieldName() {
1031
+ // Simple header canon is verbatim, INCLUDING the DKIM-Signature field-name
1032
+ // casing exactly as it appears on the wire — the verifier must canonicalize
1033
+ // with the parsed field name, not a hardcoded "DKIM-Signature". So a peer that
1034
+ // signs and sends `dkim-signature:` (lowercase) verifies, and a message whose
1035
+ // field name was altered after signing no longer matches. Proven here by
1036
+ // altering the on-wire casing after signing: the signature was computed over
1037
+ // "DKIM-Signature", so the lowercased wire must NOT verify. (Before the fix
1038
+ // the verifier ignored the on-wire name and this passed spuriously.)
1039
+ var kp = _rsaKeypair();
1040
+ b.mail.dkim._resetDkimKeyCacheForTest();
1041
+ var signer = b.mail.dkim.create({
1042
+ domain: "wirename.example", selector: "wn",
1043
+ privateKey: kp.privateKey, canonicalization: "simple/simple",
1044
+ });
1045
+ var msg =
1046
+ "From: alice@wirename.example\r\nTo: bob@example.org\r\n" +
1047
+ "Subject: Wire name\r\nDate: Mon, 5 May 2026 12:00:00 +0000\r\n" +
1048
+ "Message-ID: <wn@example.com>\r\n\r\nBody.\r\n";
1049
+ var signed = signer.sign(msg);
1050
+ var b64 = _spkiPemToB64(kp.publicKey);
1051
+ var dnsLookup = async function () { return [["v=DKIM1; k=rsa; p=" + b64]]; };
1052
+ var rvUpper = await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup });
1053
+ check("simple-canon verify: canonical DKIM-Signature casing verifies",
1054
+ rvUpper[0] && rvUpper[0].result === "pass");
1055
+ // Alter ONLY the field-name casing on the wire (the signed bytes used
1056
+ // "DKIM-Signature"), leaving everything else intact.
1057
+ var loweredWire = signed.replace(/^DKIM-Signature:/, "dkim-signature:");
1058
+ var rvLower = await b.mail.dkim.verify(loweredWire, { dnsLookup: dnsLookup });
1059
+ check("simple-canon verify: honors the on-wire field-name casing (altered name does not verify)",
1060
+ rvLower[0] && rvLower[0].result === "fail");
1061
+ }
1062
+
1063
+ // ---- Cross-implementation conformance: openssl-signed simple/simple vector ----
1064
+ //
1065
+ // The signature bytes below were produced by an INDEPENDENT implementation:
1066
+ // OpenSSL (`openssl dgst -sha256 -sign` — RSASSA-PKCS1-v1_5) over
1067
+ // hand-constructed RFC 6376 simple/simple canonicalization. bh= is the
1068
+ // SHA-256 of the verbatim CRLF body (section 3.4.3); b= signs the four h=
1069
+ // headers verbatim (each with its CRLF) followed by the DKIM-Signature
1070
+ // header with an empty b= value and no trailing CRLF (sections 3.4.1 and
1071
+ // 3.7). No framework code participated in producing the fixture, so a pass
1072
+ // here proves cross-implementation ACCEPTANCE of simple canonicalization —
1073
+ // a self-round-trip alone stays green when sign and verify share the same
1074
+ // canonicalization bug. The tampered-body / tampered-header controls prove
1075
+ // the pass is cryptographic, not vacuous.
1076
+ async function testDkimOpensslSimpleCanonInteropVector() {
1077
+ var BH = "AD876huuF731JvLItVmRCvApI83P8LTA8/xaXm2Hu8Y=";
1078
+ var SIG =
1079
+ "i62Ti4k531wo/A2u2rk8G5J8JpgM0+MBj6vJbmwzz6MiMYEwS6XfO1GAOL0rUtM3TSNeWjKg" +
1080
+ "ul2XjS4C5bVMjRQma1W+TzcJh3aHL8UXTc8K64DQ8isZ61BsN8v/iaIf/z5/6MZIOxlnaAbn" +
1081
+ "CVWm/1OU3qvhKxyFOU9aCl+EaHuHGlvF1EM/bBpPpu9jmjRzSvj6Nyojw1tFl/g4HfOaCvpv" +
1082
+ "wVmOBo49O1voWHC3CHDHK5rbURzf/dVC37aviTkjTgbh5I8QTcRVllBAMOs5LYl5zHAr1Jop" +
1083
+ "h+8omZwednKI/Inj//S0EsyZeM6iKkuNX1nP3c460DH65jexsLj49Q==";
1084
+ var PUB_B64 =
1085
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0VM3DGY3FSvXw58NTv2nMzJ149kB" +
1086
+ "Q6KuTQBaRjjQfrYxRAbLhCSgatNz55GbZlBR0Uj7sYmGzte18sef5AqCWY4lXrD/+97S0GjH" +
1087
+ "jUMHzQhp9Tk1m4yVnfqJp2MgXyMi31yrRvRkmNM7XD/EC07HuugHcKGnPRsHQV6kyGUkeuHt" +
1088
+ "lQYRx058jTOWja6mcc0/nVQa08GM4703QYl6j3ZgSiu90fFnw77uswcuaKgwPIw3V66uPNPS" +
1089
+ "VhqxGLyuXF4fw1DvYtRyJ/3liMNhqClEqDSwKfSEK6Z8nE/4M8Nv3BZA0OOzitDmqzyXkcdY" +
1090
+ "At3XbaUHc0Gpbs5MYV7k2YXKWQIDAQAB";
1091
+
1092
+ var message =
1093
+ "DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; " +
1094
+ "d=openssl-interop.example; s=oss1; h=from:to:subject:date; " +
1095
+ "bh=" + BH + "; b=" + SIG + "\r\n" +
1096
+ "From: interop@openssl-interop.example\r\n" +
1097
+ "To: rcpt@blamejs.example\r\n" +
1098
+ "Subject: DKIM simple canonicalization interop\r\n" +
1099
+ "Date: Thu, 01 Jan 2026 00:00:00 +0000\r\n" +
1100
+ "\r\n" +
1101
+ "Interop body line one.\r\nInterop body line two.\r\n";
1102
+
1103
+ var dnsLookup = async function () { return [["v=DKIM1; k=rsa; p=" + PUB_B64]]; };
1104
+
1105
+ b.mail.dkim._resetDkimKeyCacheForTest();
1106
+ var rv = await b.mail.dkim.verify(message, { dnsLookup: dnsLookup });
1107
+ check("openssl interop: independently-signed simple/simple vector passes",
1108
+ Array.isArray(rv) && rv.length === 1 && rv[0].result === "pass");
1109
+ check("openssl interop: pass verdict carries zero errors",
1110
+ rv[0] && Array.isArray(rv[0].errors) && rv[0].errors.length === 0);
1111
+ check("openssl interop: verdict identifies the signing domain and selector",
1112
+ rv[0] && rv[0].d === "openssl-interop.example" && rv[0].s === "oss1");
1113
+
1114
+ // Control 1: one flipped body byte breaks the simple body hash.
1115
+ var bodyTampered = message.replace("Interop body line two.", "Interop body line 2wo.");
1116
+ var rvBody = await b.mail.dkim.verify(bodyTampered, { dnsLookup: dnsLookup });
1117
+ check("openssl interop: tampered body fails (body hash mismatch)",
1118
+ rvBody[0] && rvBody[0].result === "fail" &&
1119
+ /body hash mismatch/.test((rvBody[0].errors || []).join(",")));
1120
+
1121
+ // Control 2: one flipped byte in a signed header breaks the signature.
1122
+ var hdrTampered = message.replace("Subject: DKIM simple", "Subject: DKIM Simple");
1123
+ var rvHdr = await b.mail.dkim.verify(hdrTampered, { dnsLookup: dnsLookup });
1124
+ check("openssl interop: tampered signed header fails signature verification",
1125
+ rvHdr[0] && rvHdr[0].result === "fail" &&
1126
+ /signature verification failed/.test((rvHdr[0].errors || []).join(",")));
1127
+ }
1128
+
1129
+ // ---- verify(): input + option-default guards ----
1130
+
1131
+ async function testDkimVerifyBadInputAndOptions() {
1132
+ var kp = _rsaKeypair();
1133
+ var signed = await _signedMessage(kp);
1134
+ var b64 = _spkiPemToB64(kp.publicKey);
1135
+ var dnsLookup = async function () { return [["v=DKIM1; k=rsa; p=" + b64]]; };
1136
+
1137
+ // Empty / non-string rfc822 → bad-input throw.
1138
+ var threw = null;
1139
+ try { await b.mail.dkim.verify(""); } catch (e) { threw = e; }
1140
+ check("verify: empty rfc822 → bad-input", threw && /dkim\/bad-input/.test(threw.code || ""));
1141
+ threw = null;
1142
+ try { await b.mail.dkim.verify(12345); } catch (e) { threw = e; }
1143
+ check("verify: non-string rfc822 → bad-input", threw && /dkim\/bad-input/.test(threw.code || ""));
1144
+
1145
+ // A well-formed valid clockSkewMs (the accepted numeric branch).
1146
+ b.mail.dkim._resetDkimKeyCacheForTest();
1147
+ var rvSkew = await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup, clockSkewMs: 60000 });
1148
+ check("verify: accepts a valid clockSkewMs (finite, < ceiling)",
1149
+ rvSkew[0] && rvSkew[0].result === "pass");
1150
+
1151
+ // maxSignatures range-check: below 1 and above the ceiling throw.
1152
+ threw = null;
1153
+ try { await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup, maxSignatures: 0 }); }
1154
+ catch (e) { threw = e; }
1155
+ check("verify: maxSignatures < 1 → bad-max-signatures",
1156
+ threw && /dkim\/bad-max-signatures/.test(threw.code || ""));
1157
+ threw = null;
1158
+ try { await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup, maxSignatures: 99 }); }
1159
+ catch (e) { threw = e; }
1160
+ check("verify: maxSignatures > ceiling → bad-max-signatures",
1161
+ threw && /dkim\/bad-max-signatures/.test(threw.code || ""));
1162
+
1163
+ // A valid in-range maxSignatures (the accepted numeric branch).
1164
+ b.mail.dkim._resetDkimKeyCacheForTest();
1165
+ var rvMax = await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup, maxSignatures: 4 });
1166
+ check("verify: accepts an in-range maxSignatures",
1167
+ rvMax[0] && rvMax[0].result === "pass");
1168
+ }
1169
+
1170
+ async function testDkimVerifyNoSignatureHeaders() {
1171
+ // A message with no DKIM-Signature header → single "none" result.
1172
+ var msg = "From: a@example.com\r\nSubject: unsigned\r\n\r\nbody\r\n";
1173
+ var rv = await b.mail.dkim.verify(msg, { dnsLookup: async function () { return [[""]]; } });
1174
+ check("verify: unsigned message → [{ result: 'none' }]",
1175
+ Array.isArray(rv) && rv[0] && rv[0].result === "none" &&
1176
+ /no DKIM-Signature/.test((rv[0].errors || []).join(",")));
1177
+ }
1178
+
1179
+ // ---- verify(): v= / x= / t= NumericDate guards (decided pre-crypto) ----
1180
+
1181
+ async function testDkimVerifyBadVersion() {
1182
+ var rv = await b.mail.dkim.verify(
1183
+ _messageWithSig(["v=2", "a=rsa-sha256", "c=relaxed/relaxed",
1184
+ "d=v.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1185
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p=AAA"]]; } });
1186
+ check("verify: v=2 → permerror (only v=1 supported)",
1187
+ rv[0] && rv[0].result === "permerror" && /only v=1/.test((rv[0].errors || []).join(",")));
1188
+ }
1189
+
1190
+ async function testDkimVerifyExpiredAndUnparseableDates() {
1191
+ var nowSec = Math.floor(Date.now() / 1000);
1192
+ var stub = { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p=AAA"]]; } };
1193
+
1194
+ // x= in the past (beyond the default 5-min skew) → expired permerror.
1195
+ var rvExp = await b.mail.dkim.verify(
1196
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1197
+ "d=x.example", "s=s", "h=from", "bh=AAA", "x=" + (nowSec - 3600), "b=AAA"]), stub);
1198
+ check("verify: expired x= → permerror",
1199
+ rvExp[0] && rvExp[0].result === "permerror" && /has expired/.test((rvExp[0].errors || []).join(",")));
1200
+
1201
+ // x= present but not digits-only → fail-closed permerror.
1202
+ var rvXbad = await b.mail.dkim.verify(
1203
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1204
+ "d=x.example", "s=s", "h=from", "bh=AAA", "x=12abc", "b=AAA"]), stub);
1205
+ check("verify: unparseable x= → permerror (NumericDate required)",
1206
+ rvXbad[0] && rvXbad[0].result === "permerror" &&
1207
+ /x= present but unparseable/.test((rvXbad[0].errors || []).join(",")));
1208
+
1209
+ // t= present but not digits-only → fail-closed permerror.
1210
+ var rvTbad = await b.mail.dkim.verify(
1211
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1212
+ "d=t.example", "s=s", "h=from", "bh=AAA", "t=notanum", "b=AAA"]), stub);
1213
+ check("verify: unparseable t= → permerror (NumericDate required)",
1214
+ rvTbad[0] && rvTbad[0].result === "permerror" &&
1215
+ /t= present but unparseable/.test((rvTbad[0].errors || []).join(",")));
1216
+
1217
+ // t= more than 24h in the future → sanity permerror.
1218
+ var rvFuture = await b.mail.dkim.verify(
1219
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1220
+ "d=t.example", "s=s", "h=from", "bh=AAA", "t=" + (nowSec + 48 * 3600), "b=AAA"]), stub);
1221
+ check("verify: t= >24h in the future → permerror",
1222
+ rvFuture[0] && rvFuture[0].result === "permerror" &&
1223
+ /more than 24h in the future/.test((rvFuture[0].errors || []).join(",")));
1224
+
1225
+ // x= before t= (expiry earlier than signing time) → ordering permerror.
1226
+ var rvOrder = await b.mail.dkim.verify(
1227
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1228
+ "d=t.example", "s=s", "h=from", "bh=AAA",
1229
+ "t=" + (nowSec + 100), "x=" + (nowSec + 50), "b=AAA"]), stub);
1230
+ check("verify: x= before t= → permerror (x must be after t)",
1231
+ rvOrder[0] && rvOrder[0].result === "permerror" &&
1232
+ /x= must be after t=/.test((rvOrder[0].errors || []).join(",")));
1233
+ }
1234
+
1235
+ async function testDkimVerifyValidDatesPassThrough() {
1236
+ // A fully-valid signature carrying non-expired t= + x= reaches the pass
1237
+ // path (exercises the accepted t=/x= branches, not the reject branches).
1238
+ var kp = _rsaKeypair();
1239
+ b.mail.dkim._resetDkimKeyCacheForTest();
1240
+ var nowSec = Math.floor(Date.now() / 1000);
1241
+ var signed = _buildRelaxedSigned(kp, "dates.example", "sd",
1242
+ ["t=" + (nowSec - 60), "x=" + (nowSec + 3600)]);
1243
+ var b64 = _spkiPemToB64(kp.publicKey);
1244
+ var rv = await b.mail.dkim.verify(signed,
1245
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p=" + b64]]; } });
1246
+ check("verify: valid non-expired t= + x= passes through to verification",
1247
+ rv[0] && rv[0].result === "pass");
1248
+ }
1249
+
1250
+ async function testDkimVerifyMissingDomainSelector() {
1251
+ // Signature with neither d= nor s= → permerror (missing d= or s=).
1252
+ var rv = await b.mail.dkim.verify(
1253
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1254
+ "h=from", "bh=AAA", "b=AAA"]),
1255
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p=AAA"]]; } });
1256
+ check("verify: missing d=/s= → permerror",
1257
+ rv[0] && rv[0].result === "permerror" &&
1258
+ /missing d= or s=/.test((rv[0].errors || []).join(",")));
1259
+ }
1260
+
1261
+ // ---- verify(): key-resolution error paths ----
1262
+
1263
+ async function testDkimVerifyKeyLookupErrors() {
1264
+ // ENOTFOUND from the resolver → permerror key-not-found.
1265
+ var rvNx = await b.mail.dkim.verify(
1266
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1267
+ "d=nx.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1268
+ { dnsLookup: async function () { var e = new Error("nx"); e.code = "ENOTFOUND"; throw e; } });
1269
+ check("verify: ENOTFOUND key lookup → permerror (no TXT record)",
1270
+ rvNx[0] && rvNx[0].result === "permerror" &&
1271
+ /no DKIM TXT record/.test((rvNx[0].errors || []).join(",")));
1272
+
1273
+ // A generic resolver failure (no ENOTFOUND/ENODATA code) → temperror.
1274
+ var rvTemp = await b.mail.dkim.verify(
1275
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1276
+ "d=temp.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1277
+ { dnsLookup: async function () { throw new Error("connection reset"); } });
1278
+ check("verify: generic key-lookup failure → temperror",
1279
+ rvTemp[0] && rvTemp[0].result === "temperror" &&
1280
+ /lookup for .* failed/.test((rvTemp[0].errors || []).join(",")));
1281
+ }
1282
+
1283
+ async function testDkimVerifyKeyRecordShapes() {
1284
+ var kp = _rsaKeypair();
1285
+ var b64 = _spkiPemToB64(kp.publicKey);
1286
+
1287
+ // A bare-string TXT record (not the [[chunk]] shape) still parses.
1288
+ b.mail.dkim._resetDkimKeyCacheForTest();
1289
+ var signed = await _signedMessage(kp);
1290
+ var rvStr = await b.mail.dkim.verify(signed,
1291
+ { dnsLookup: async function () { return "v=DKIM1; k=rsa; p=" + b64; } });
1292
+ check("verify: accepts a bare-string TXT record shape",
1293
+ rvStr[0] && rvStr[0].result === "pass");
1294
+
1295
+ // An empty TXT record → key-not-found (empty) → permerror.
1296
+ var rvEmpty = await b.mail.dkim.verify(
1297
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1298
+ "d=e.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1299
+ { dnsLookup: async function () { return ""; } });
1300
+ check("verify: empty TXT record → permerror (key record is empty)",
1301
+ rvEmpty[0] && rvEmpty[0].result === "permerror" &&
1302
+ /empty/.test((rvEmpty[0].errors || []).join(",")));
1303
+
1304
+ // A record present but missing p= → permerror (missing p=).
1305
+ var rvNoP = await b.mail.dkim.verify(
1306
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1307
+ "d=nop.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1308
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa"]]; } });
1309
+ check("verify: key record without p= → permerror (missing p=)",
1310
+ rvNoP[0] && rvNoP[0].result === "permerror" &&
1311
+ /missing p=/.test((rvNoP[0].errors || []).join(",")));
1312
+
1313
+ // An explicitly-revoked key (empty p=) → fail (well-formed, withdrawn).
1314
+ var rvRevoked = await b.mail.dkim.verify(
1315
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1316
+ "d=rev.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1317
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p="]]; } });
1318
+ check("verify: revoked key (empty p=) → fail",
1319
+ rvRevoked[0] && rvRevoked[0].result === "fail" &&
1320
+ /revoked/.test((rvRevoked[0].errors || []).join(",")));
1321
+
1322
+ // Key k= family disagrees with the signature a= family → permerror.
1323
+ var rvKMismatch = await b.mail.dkim.verify(
1324
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1325
+ "d=km.example", "s=s", "h=from", "bh=AAA", "b=AAA"]),
1326
+ { dnsLookup: async function () { return [["v=DKIM1; k=ed25519; p=AAA"]]; } });
1327
+ check("verify: key k= family != signature a= family → permerror",
1328
+ rvKMismatch[0] && rvKMismatch[0].result === "permerror" &&
1329
+ /does not match signature a=/.test((rvKMismatch[0].errors || []).join(",")));
1330
+ }
1331
+
1332
+ // ---- verify(): _verifySingleSignature body-hash / header / key guards ----
1333
+
1334
+ async function testDkimVerifySingleSignatureGuards() {
1335
+ var kp = _rsaKeypair();
1336
+ var b64 = _spkiPemToB64(kp.publicKey);
1337
+ var goodKey = async function () { return [["v=DKIM1; k=rsa; p=" + b64]]; };
1338
+ var bhBody = "guarded body\r\n";
1339
+ var bh = _relaxedBodyHash(bhBody);
1340
+
1341
+ // Signature with no bh= tag → permerror (missing bh=).
1342
+ var rvNoBh = await b.mail.dkim.verify(
1343
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1344
+ "d=nobh.example", "s=s", "h=from", "b=AAA"], bhBody),
1345
+ { dnsLookup: goodKey });
1346
+ check("verify: signature missing bh= → permerror",
1347
+ rvNoBh[0] && rvNoBh[0].result === "permerror" &&
1348
+ /missing bh=/.test((rvNoBh[0].errors || []).join(",")));
1349
+
1350
+ // A tampered body (correct-length but different content) → body-hash fail.
1351
+ var rvBhMismatch = await b.mail.dkim.verify(
1352
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1353
+ "d=bhmm.example", "s=s", "h=from", "bh=" + bh, "b=AAA"], "TAMPERED body\r\n"),
1354
+ { dnsLookup: goodKey });
1355
+ check("verify: body-hash mismatch → fail",
1356
+ rvBhMismatch[0] && rvBhMismatch[0].result === "fail" &&
1357
+ /body hash mismatch/.test((rvBhMismatch[0].errors || []).join(",")));
1358
+
1359
+ // Correct bh but h= omits 'from' → permerror (from not covered).
1360
+ var rvNoFrom = await b.mail.dkim.verify(
1361
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1362
+ "d=nofrom.example", "s=s", "h=to", "bh=" + bh, "b=AAA"], bhBody),
1363
+ { dnsLookup: goodKey });
1364
+ check("verify: h= without 'from' → permerror",
1365
+ rvNoFrom[0] && rvNoFrom[0].result === "permerror" &&
1366
+ /does not include 'from'/.test((rvNoFrom[0].errors || []).join(",")));
1367
+
1368
+ // Correct bh + h=from but no b= tag → permerror (missing b=).
1369
+ var rvNoB = await b.mail.dkim.verify(
1370
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1371
+ "d=nob.example", "s=s", "h=from", "bh=" + bh], bhBody),
1372
+ { dnsLookup: goodKey });
1373
+ check("verify: signature missing b= → permerror",
1374
+ rvNoB[0] && rvNoB[0].result === "permerror" &&
1375
+ /missing b=/.test((rvNoB[0].errors || []).join(",")));
1376
+
1377
+ // l= present but not digits-only → fail-closed permerror.
1378
+ var rvLbad = await b.mail.dkim.verify(
1379
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1380
+ "d=lbad.example", "s=s", "h=from", "bh=" + bh, "l=12x", "b=AAA"], bhBody),
1381
+ { dnsLookup: goodKey });
1382
+ check("verify: unparseable l= → permerror (unsigned integer required)",
1383
+ rvLbad[0] && rvLbad[0].result === "permerror" &&
1384
+ /l= present but unparseable/.test((rvLbad[0].errors || []).join(",")));
1385
+
1386
+ // Correct bh + h=from + b= present, but the published key p= is garbage
1387
+ // that node:crypto cannot parse → permerror (key parse failed).
1388
+ var rvKeyParse = await b.mail.dkim.verify(
1389
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1390
+ "d=keyparse.example", "s=s", "h=from", "bh=" + bh, "b=AAAA"], bhBody),
1391
+ { dnsLookup: async function () { return [["v=DKIM1; k=rsa; p=@@not-base64-der@@"]]; } });
1392
+ check("verify: unparseable key material → permerror (key parse failed)",
1393
+ rvKeyParse[0] && rvKeyParse[0].result === "permerror" &&
1394
+ /key parse failed/.test((rvKeyParse[0].errors || []).join(",")));
1395
+
1396
+ // a= names a supported family (rsa) but an unsupported full algorithm
1397
+ // (rsa-sha1) → permerror (unsupported DKIM algorithm). Take a valid
1398
+ // rsa-sha256 signature and re-label its a= so bh stays valid and the
1399
+ // run reaches the algorithm check before any crypto verify.
1400
+ b.mail.dkim._resetDkimKeyCacheForTest();
1401
+ var validSigned = _buildRelaxedSigned(kp, "alg.example", "sa");
1402
+ var relabeled = validSigned.replace("a=rsa-sha256", "a=rsa-sha1");
1403
+ var rvUnsupported = await b.mail.dkim.verify(relabeled, { dnsLookup: goodKey });
1404
+ check("verify: unsupported a= algorithm (rsa-sha1) → permerror",
1405
+ rvUnsupported[0] && rvUnsupported[0].result === "permerror" &&
1406
+ /unsupported DKIM algorithm/.test((rvUnsupported[0].errors || []).join(",")));
1407
+ }
1408
+
1409
+ async function testDkimVerifyCryptoThrowsPath() {
1410
+ // a=rsa-sha256 (digest sha256) but the published key is an Ed25519 key
1411
+ // with no k= tag, so the k= guard is skipped and node:crypto.verify is
1412
+ // invoked with a digest the key type rejects → it THROWS, and the
1413
+ // verifier maps the throw to a permerror rather than crashing.
1414
+ var edKp = _ed25519Keypair();
1415
+ var edB64 = _spkiPemToB64(edKp.publicKey);
1416
+ var body = "throws body\r\n";
1417
+ var bh = _relaxedBodyHash(body);
1418
+ b.mail.dkim._resetDkimKeyCacheForTest();
1419
+ var rv = await b.mail.dkim.verify(
1420
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1421
+ "d=throws.example", "s=s", "h=from", "bh=" + bh, "b=AAAA"], body),
1422
+ { dnsLookup: async function () { return [["v=DKIM1; p=" + edB64]]; } });
1423
+ check("verify: node:crypto.verify throw is caught → permerror",
1424
+ rv[0] && rv[0].result === "permerror" &&
1425
+ /verify threw/.test((rv[0].errors || []).join(",")));
1426
+ }
1427
+
1428
+ // ---- verify(): key cache expiry + eviction ----
1429
+
1430
+ async function testDkimKeyCacheExpiry() {
1431
+ // A cached key entry past its TTL is dropped and re-fetched. Advance the
1432
+ // clock via a scoped Date.now override (deterministic; no wall-clock wait).
1433
+ b.mail.dkim._resetDkimKeyCacheForTest();
1434
+ var kp = _rsaKeypair();
1435
+ var b64 = _spkiPemToB64(kp.publicKey);
1436
+ var signed = await _signedMessage(kp);
1437
+ var calls = 0;
1438
+ var dnsLookup = async function () { calls += 1; return [["v=DKIM1; k=rsa; p=" + b64]]; };
1439
+ var realNow = Date.now;
1440
+ try {
1441
+ await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup }); // fetch + cache
1442
+ var base = realNow();
1443
+ Date.now = function () { return base + 6 * 60 * 1000; }; // TTL is 5 min
1444
+ await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup }); // expired → re-fetch
1445
+ check("verify: key cache entry past TTL is evicted and re-fetched",
1446
+ calls === 2);
1447
+ } finally {
1448
+ Date.now = realNow;
1449
+ }
1450
+ }
1451
+
1452
+ async function testDkimKeyCacheEvictionBound() {
1453
+ // Fill the key cache past its max-entries bound so the oldest entry is
1454
+ // evicted (the DoS-bounding eviction path). Each verify pins a distinct
1455
+ // domain; a k=-family mismatch short-circuits before any crypto verify,
1456
+ // so the fill is cheap. The first-inserted selector must be re-fetched
1457
+ // after the eviction wave, proving the oldest entry was dropped.
1458
+ b.mail.dkim._resetDkimKeyCacheForTest();
1459
+ var MAX = 1024; // lib DKIM_KEY_CACHE_MAX_ENTRIES (module-private)
1460
+ var fetches = Object.create(null);
1461
+ var dnsLookup = async function (qname) {
1462
+ fetches[qname] = (fetches[qname] || 0) + 1;
1463
+ return [["v=DKIM1; k=ed25519; p=AAA"]]; // mismatch vs a=rsa-sha256 → permerror pre-crypto
1464
+ };
1465
+ async function verifyDomain(dom) {
1466
+ return b.mail.dkim.verify(
1467
+ _messageWithSig(["v=1", "a=rsa-sha256", "c=relaxed/relaxed",
1468
+ "d=" + dom, "s=s", "h=from", "bh=AAA", "b=AAA"]),
1469
+ { dnsLookup: dnsLookup });
1470
+ }
1471
+ var firstDomain = "g0.evict.example";
1472
+ await verifyDomain(firstDomain); // insert oldest
1473
+ for (var i = 1; i <= MAX; i += 1) { // MAX more → oldest evicted
1474
+ await verifyDomain("g" + i + ".evict.example");
1475
+ }
1476
+ var firstQname = "s._domainkey." + firstDomain;
1477
+ var before = fetches[firstQname];
1478
+ await verifyDomain(firstDomain); // must miss → re-fetch
1479
+ check("verify: oldest key-cache entry evicted past the max-entries bound",
1480
+ fetches[firstQname] === before + 1);
1481
+ }
1482
+
1483
+ // ---- dualSigner() + bootstrap() validation branches ----
1484
+
1485
+ function testDualSignerValidation() {
1486
+ var kp = _rsaKeypair();
1487
+ function shouldThrow(label, opts, codeRe) {
1488
+ var threw = null;
1489
+ try { b.mail.dkim.dualSigner(opts); } catch (e) { threw = e; }
1490
+ check("dualSigner: " + label, threw && codeRe.test(threw.code || ""));
1491
+ }
1492
+ shouldThrow("missing rsa/eddsa → dual-signer-missing",
1493
+ { domain: "example.com" }, /dkim\/dual-signer-missing/);
1494
+ shouldThrow("missing eddsa → dual-signer-missing",
1495
+ { domain: "example.com", rsa: { selector: "r", privateKey: kp.privateKey } },
1496
+ /dkim\/dual-signer-missing/);
1497
+ shouldThrow("missing domain → dual-signer-missing-domain",
1498
+ { rsa: { selector: "r", privateKey: kp.privateKey },
1499
+ eddsa: { selector: "e", privateKey: _ed25519Keypair().privateKey } },
1500
+ /dkim\/dual-signer-missing-domain/);
1501
+ }
1502
+
1503
+ function testBootstrapMoreValidation() {
1504
+ function shouldThrow(label, opts, codeRe) {
1505
+ var threw = null;
1506
+ try { b.mail.dkim.bootstrap(opts); } catch (e) { threw = e; }
1507
+ check("bootstrap: " + label, threw && codeRe.test(threw.code || ""));
1508
+ }
1509
+ // Domain that fails the DNS-hostname shape (leading hyphen).
1510
+ shouldThrow("rejects malformed domain shape",
1511
+ { domain: "-bad-.example", selector: "s1" }, /dkim\/bad-domain/);
1512
+ // Dual with a malformed explicit rsaSelector.
1513
+ shouldThrow("dual rejects malformed rsaSelector",
1514
+ { domain: "example.com", selector: "s1", algorithm: "dual", rsaSelector: "bad/sel" },
1515
+ /dkim\/bad-selector/);
1516
+ // Dual with sub-floor rsaBits.
1517
+ shouldThrow("dual rejects sub-floor rsaBits",
1518
+ { domain: "example.com", selector: "s1", algorithm: "dual", rsaBits: 512 },
1519
+ /dkim\/bad-rsa-bits/);
1520
+ }
1521
+
1522
+ // RFC 8463 §3-4 — an ed25519 DKIM key is published as the RAW 32-byte key,
1523
+ // base64'd (44 chars), the form every conformant sender uses. The verifier must
1524
+ // accept it; it previously SPKI-wrapped the raw bytes so createPublicKey threw
1525
+ // and a valid ed25519 signature returned permerror.
1526
+ async function testDkimVerifyEd25519RawKeyRfc8463() {
1527
+ var kp = _ed25519Keypair();
1528
+ var signer = b.mail.dkim.create({
1529
+ domain: "example.com",
1530
+ selector: "ed1",
1531
+ privateKey: kp.privateKey,
1532
+ algorithm: "ed25519-sha256",
1533
+ });
1534
+ var rfc822 =
1535
+ "From: alice@example.com\r\n" +
1536
+ "To: bob@example.org\r\n" +
1537
+ "Subject: Test ed raw\r\n" +
1538
+ "Date: Mon, 5 May 2026 12:00:00 +0000\r\n" +
1539
+ "Message-ID: <ed-raw@example.com>\r\n" +
1540
+ "\r\n" +
1541
+ "Hello raw ed25519.\r\n";
1542
+ var signed = signer.sign(rfc822);
1543
+ var rawB64 = nodeCrypto.createPublicKey(kp.publicKey)
1544
+ .export({ type: "spki", format: "der" }).subarray(-32).toString("base64");
1545
+ check("ed25519 raw key is the 44-char RFC 8463 form (not 60-char SPKI)", rawB64.length === 44);
1546
+ var dnsLookup = async function () { return [["v=DKIM1; k=ed25519; p=" + rawB64]]; };
1547
+ var rv = await b.mail.dkim.verify(signed, { dnsLookup: dnsLookup });
1548
+ check("ed25519 raw-key (RFC 8463) DKIM signature verifies pass",
1549
+ Array.isArray(rv) && rv[0] && rv[0].result === "pass");
1550
+ }
1551
+
1552
+ // A record `p=<raw-32-byte-key>` with NO k= is an RSA record (RFC 6376 §3.6.1
1553
+ // default). It must NOT verify an a=ed25519-sha256 signature just because the
1554
+ // key is 32 bytes long — a key-family confusion the record never authorized.
1555
+ async function testDkimEd25519KFamilyConfusionRefused() {
1556
+ var kp = _ed25519Keypair();
1557
+ var rawB64 = nodeCrypto.createPublicKey(kp.publicKey)
1558
+ .export({ type: "spki", format: "der" }).subarray(-32).toString("base64");
1559
+ // Distinct selectors so the per-qname key cache does not carry one record's
1560
+ // key into the other's lookup.
1561
+ function signWith(sel) {
1562
+ return b.mail.dkim.create({
1563
+ domain: "example.com", selector: sel, privateKey: kp.privateKey, algorithm: "ed25519-sha256",
1564
+ }).sign("From: a@example.com\r\nTo: b@example.org\r\nSubject: x\r\n\r\nbody\r\n");
1565
+ }
1566
+ // (negative) record omits k= (defaults rsa) → the ed25519 signature is refused.
1567
+ var rvNo = await b.mail.dkim.verify(signWith("edkconfno"),
1568
+ { dnsLookup: async function () { return [["v=DKIM1; p=" + rawB64]]; } });
1569
+ check("ed25519 sig against a k=-absent (RSA-default) raw-key record is refused",
1570
+ Array.isArray(rvNo) && rvNo[0] && rvNo[0].result === "permerror");
1571
+ // (positive control) with k=ed25519 it verifies.
1572
+ var rvOk = await b.mail.dkim.verify(signWith("edkconfok"),
1573
+ { dnsLookup: async function () { return [["v=DKIM1; k=ed25519; p=" + rawB64]]; } });
1574
+ check("ed25519 sig against a k=ed25519 raw-key record verifies pass",
1575
+ Array.isArray(rvOk) && rvOk[0] && rvOk[0].result === "pass");
1576
+ }
1577
+
1578
+ // bootstrap must PUBLISH the raw 32-byte ed25519 key (44 base64 chars), not
1579
+ // SPKI DER (60 chars) — the SPKI form does not verify at a conformant receiver,
1580
+ // so the framework's own default-algorithm signatures would be undeliverable.
1581
+ function testDkimBootstrapEd25519PublishesRawKey() {
1582
+ var bs = b.mail.dkim.bootstrap({ domain: "example.com", selector: "ed1", algorithm: "ed25519-sha256" });
1583
+ var m = /p=([A-Za-z0-9+/=]+)/.exec(bs.dnsTxtValue);
1584
+ check("bootstrap ed25519: p= present", m !== null);
1585
+ check("bootstrap ed25519: p= is the 44-char raw key (RFC 8463), not 60-char SPKI",
1586
+ m !== null && m[1].length === 44);
1587
+ // And the published raw key round-trips: a signature from bootstrap's signer
1588
+ // verifies against the published p=.
1589
+ var rawB64 = m ? m[1] : "";
1590
+ check("bootstrap ed25519: published p= is a 32-byte key", Buffer.from(rawB64, "base64").length === 32);
1591
+ }
1592
+
801
1593
  async function run() {
802
1594
  testDkimSurfaceAndValidation();
803
1595
  testDkimCanonicalization();
@@ -807,6 +1599,10 @@ async function run() {
807
1599
  testDkimSignerRejectsBadInput();
808
1600
  testDkimRejectsLTagBodyLength();
809
1601
  await testDkimVerifyHappyPath();
1602
+ await testDkimVerifyEd25519RawKeyRfc8463();
1603
+ await testDkimEd25519KFamilyConfusionRefused();
1604
+ testDkimBootstrapEd25519PublishesRawKey();
1605
+ await testDkimVerifyBareLfMessage();
810
1606
  await testDkimVerifyKeyCacheHit();
811
1607
  await testDkimVerifySmallKeyRejected();
812
1608
  await testCalendarValidation();
@@ -827,6 +1623,28 @@ async function run() {
827
1623
  await testDkimVerifyLTagCountsCanonicalizedOctets();
828
1624
  await testDkimVerifyLTagAppendAfterSignatureRefused();
829
1625
  await testArcAmsLTagAppendRefused();
1626
+ // Uncovered error / adversarial / defensive / option-default branches
1627
+ testDkimCreateInputBranches();
1628
+ testDkimSignerAuditDisabled();
1629
+ await testDkimEd25519VerifyRoundTrip();
1630
+ testDkimSimpleCanonDirect();
1631
+ await testDkimSimpleCanonRoundTrips();
1632
+ await testDkimSimpleCanonHonorsWireFieldName();
1633
+ await testDkimOpensslSimpleCanonInteropVector();
1634
+ await testDkimVerifyBadInputAndOptions();
1635
+ await testDkimVerifyNoSignatureHeaders();
1636
+ await testDkimVerifyBadVersion();
1637
+ await testDkimVerifyExpiredAndUnparseableDates();
1638
+ await testDkimVerifyValidDatesPassThrough();
1639
+ await testDkimVerifyMissingDomainSelector();
1640
+ await testDkimVerifyKeyLookupErrors();
1641
+ await testDkimVerifyKeyRecordShapes();
1642
+ await testDkimVerifySingleSignatureGuards();
1643
+ await testDkimVerifyCryptoThrowsPath();
1644
+ await testDkimKeyCacheExpiry();
1645
+ await testDkimKeyCacheEvictionBound();
1646
+ testDualSignerValidation();
1647
+ testBootstrapMoreValidation();
830
1648
  }
831
1649
 
832
1650
  module.exports = { run: run };