@blamejs/blamejs-shop 0.4.31 → 0.4.32

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 (336) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +392 -278
  4. package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
  5. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
  6. package/lib/vendor/blamejs/.gitignore +6 -0
  7. package/lib/vendor/blamejs/CHANGELOG.md +26 -0
  8. package/lib/vendor/blamejs/MIGRATING.md +43 -0
  9. package/lib/vendor/blamejs/README.md +8 -6
  10. package/lib/vendor/blamejs/SECURITY.md +19 -3
  11. package/lib/vendor/blamejs/api-snapshot.json +2190 -664
  12. package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
  13. package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
  14. package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
  15. package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
  16. package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
  17. package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
  18. package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
  19. package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
  20. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
  21. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
  22. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
  23. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
  24. package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
  25. package/lib/vendor/blamejs/index.js +4 -0
  26. package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
  27. package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
  28. package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
  29. package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
  30. package/lib/vendor/blamejs/lib/api-key.js +158 -77
  31. package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
  32. package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
  33. package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
  34. package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
  35. package/lib/vendor/blamejs/lib/audit.js +259 -123
  36. package/lib/vendor/blamejs/lib/auth/oauth.js +53 -9
  37. package/lib/vendor/blamejs/lib/auth/openid-federation.js +108 -47
  38. package/lib/vendor/blamejs/lib/auth/saml.js +6 -8
  39. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +31 -5
  40. package/lib/vendor/blamejs/lib/backup/index.js +45 -10
  41. package/lib/vendor/blamejs/lib/break-glass.js +355 -147
  42. package/lib/vendor/blamejs/lib/cache.js +174 -105
  43. package/lib/vendor/blamejs/lib/chain-writer.js +38 -16
  44. package/lib/vendor/blamejs/lib/cli.js +19 -14
  45. package/lib/vendor/blamejs/lib/cluster-provider-db.js +130 -104
  46. package/lib/vendor/blamejs/lib/cluster-storage.js +119 -22
  47. package/lib/vendor/blamejs/lib/cluster.js +119 -71
  48. package/lib/vendor/blamejs/lib/codepoint-class.js +23 -0
  49. package/lib/vendor/blamejs/lib/compliance.js +206 -4
  50. package/lib/vendor/blamejs/lib/consent.js +82 -29
  51. package/lib/vendor/blamejs/lib/constants.js +27 -11
  52. package/lib/vendor/blamejs/lib/crypto-field.js +916 -156
  53. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
  54. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
  55. package/lib/vendor/blamejs/lib/db-query.js +882 -260
  56. package/lib/vendor/blamejs/lib/db-schema.js +228 -44
  57. package/lib/vendor/blamejs/lib/db.js +249 -99
  58. package/lib/vendor/blamejs/lib/dsr.js +385 -55
  59. package/lib/vendor/blamejs/lib/error-page.js +14 -1
  60. package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
  61. package/lib/vendor/blamejs/lib/external-db.js +549 -34
  62. package/lib/vendor/blamejs/lib/file-upload.js +52 -7
  63. package/lib/vendor/blamejs/lib/framework-error.js +20 -1
  64. package/lib/vendor/blamejs/lib/framework-files.js +73 -0
  65. package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
  66. package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
  67. package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
  68. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  69. package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
  70. package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
  71. package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
  72. package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
  73. package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
  74. package/lib/vendor/blamejs/lib/guard-email.js +47 -69
  75. package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
  76. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
  77. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
  78. package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
  79. package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
  80. package/lib/vendor/blamejs/lib/guard-html.js +53 -108
  81. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
  82. package/lib/vendor/blamejs/lib/guard-image.js +46 -103
  83. package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
  84. package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
  85. package/lib/vendor/blamejs/lib/guard-json.js +38 -108
  86. package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
  87. package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
  88. package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
  89. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
  90. package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
  91. package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
  92. package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
  93. package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
  94. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
  95. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
  96. package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
  97. package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
  98. package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
  99. package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
  100. package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
  101. package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
  102. package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
  103. package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
  104. package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
  105. package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
  106. package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
  107. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
  108. package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
  109. package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
  110. package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
  111. package/lib/vendor/blamejs/lib/guard-template.js +35 -172
  112. package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
  113. package/lib/vendor/blamejs/lib/guard-time.js +32 -154
  114. package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
  115. package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
  116. package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
  117. package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
  118. package/lib/vendor/blamejs/lib/http-client.js +37 -9
  119. package/lib/vendor/blamejs/lib/inbox.js +120 -107
  120. package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
  121. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
  123. package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
  124. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
  125. package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
  126. package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
  127. package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
  128. package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
  129. package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
  130. package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
  131. package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
  132. package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
  133. package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
  134. package/lib/vendor/blamejs/lib/mail-store.js +293 -154
  135. package/lib/vendor/blamejs/lib/mail.js +8 -4
  136. package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
  137. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
  138. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
  139. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
  140. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
  141. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
  142. package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
  143. package/lib/vendor/blamejs/lib/migrations.js +108 -66
  144. package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
  145. package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
  146. package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
  147. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
  148. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
  149. package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
  150. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
  151. package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
  152. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
  153. package/lib/vendor/blamejs/lib/observability.js +124 -0
  154. package/lib/vendor/blamejs/lib/otel-export.js +12 -3
  155. package/lib/vendor/blamejs/lib/outbox.js +184 -83
  156. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
  157. package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
  158. package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
  159. package/lib/vendor/blamejs/lib/queue-local.js +225 -140
  160. package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
  161. package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
  162. package/lib/vendor/blamejs/lib/queue.js +7 -0
  163. package/lib/vendor/blamejs/lib/redact.js +68 -11
  164. package/lib/vendor/blamejs/lib/redis-client.js +160 -31
  165. package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
  166. package/lib/vendor/blamejs/lib/retention.js +101 -40
  167. package/lib/vendor/blamejs/lib/router.js +212 -5
  168. package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
  169. package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
  170. package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
  171. package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
  172. package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
  173. package/lib/vendor/blamejs/lib/safe-url.js +170 -3
  174. package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
  175. package/lib/vendor/blamejs/lib/scheduler.js +35 -12
  176. package/lib/vendor/blamejs/lib/seeders.js +122 -74
  177. package/lib/vendor/blamejs/lib/session-stores.js +42 -14
  178. package/lib/vendor/blamejs/lib/session.js +175 -77
  179. package/lib/vendor/blamejs/lib/sql.js +3842 -0
  180. package/lib/vendor/blamejs/lib/sse.js +26 -0
  181. package/lib/vendor/blamejs/lib/ssrf-guard.js +151 -4
  182. package/lib/vendor/blamejs/lib/static.js +177 -34
  183. package/lib/vendor/blamejs/lib/subject.js +96 -49
  184. package/lib/vendor/blamejs/lib/vault/index.js +3 -2
  185. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
  186. package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
  187. package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
  188. package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
  189. package/lib/vendor/blamejs/lib/websocket.js +35 -5
  190. package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
  191. package/lib/vendor/blamejs/package.json +2 -2
  192. package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
  193. package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
  194. package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
  195. package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
  196. package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
  197. package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
  198. package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
  199. package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
  200. package/lib/vendor/blamejs/scripts/check-services.js +21 -0
  201. package/lib/vendor/blamejs/scripts/gen-migrating.js +51 -0
  202. package/lib/vendor/blamejs/scripts/release.js +398 -38
  203. package/lib/vendor/blamejs/test/00-primitives.js +117 -0
  204. package/lib/vendor/blamejs/test/10-state.js +140 -14
  205. package/lib/vendor/blamejs/test/20-db.js +65 -2
  206. package/lib/vendor/blamejs/test/helpers/db.js +9 -0
  207. package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
  208. package/lib/vendor/blamejs/test/helpers/services.js +21 -0
  209. package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
  210. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
  211. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
  212. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
  213. package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
  214. package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
  215. package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
  216. package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
  217. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
  218. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
  219. package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
  220. package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
  221. package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
  222. package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
  223. package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
  224. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
  225. package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
  226. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
  227. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
  228. package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
  229. package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
  230. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
  231. package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
  232. package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
  233. package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
  234. package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
  235. package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
  236. package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
  237. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
  238. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
  239. package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
  240. package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
  241. package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
  242. package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
  243. package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
  244. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
  245. package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
  246. package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
  247. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
  248. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1120 -14
  249. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
  250. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
  251. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
  252. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
  253. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
  254. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
  255. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
  256. package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
  257. package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
  258. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
  259. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
  262. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
  271. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
  272. package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
  273. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
  277. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
  278. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
  281. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
  282. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
  283. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
  284. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
  291. package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +309 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
  302. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
  308. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
  310. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
  311. package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
  312. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
  313. package/lib/vendor/blamejs/test/smoke.js +79 -21
  314. package/package.json +1 -1
  315. package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
  316. package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
  317. package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
  318. package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
  319. package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
  320. package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
  321. package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
  322. package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
  323. package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
  324. package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
  325. package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
  326. package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
  327. package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
  328. package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
  329. package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
  330. package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
  331. package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
  332. package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
  333. package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
  334. package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
  335. package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
  336. package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ /**
3
+ * crypto-interop-oracles — prove the framework's "external interop" and
4
+ * "FIPS/NIST" crypto claims against INDEPENDENT oracles, not the
5
+ * framework's own verifier.
6
+ *
7
+ * The advertised surface that this file holds to account:
8
+ *
9
+ * - b.auth.jws.sign — docstring: "exists strictly for interop with
10
+ * external ecosystems" (OAuth/OIDC OPs, FAPI, wallets). Every other
11
+ * test round-trips a token through b.auth.jwt.verifyExternal — the
12
+ * framework's OWN verifier. Here a from-scratch RFC 7515 verifier
13
+ * built on node:crypto (no framework code in the verify path) checks
14
+ * an ES256 and an EdDSA token, proving a third party who never
15
+ * touches blamejs can verify what blamejs signed.
16
+ *
17
+ * - b.pqcSoftware.{ml_kem_1024, ml_dsa_87, slh_dsa_shake_256f} — the
18
+ * module advertises "FIPS-203 / FIPS-204 / FIPS-205" and the
19
+ * "reference-implementation path for interop tests against Node
20
+ * WebCrypto or a hardware HSM". b.crypto.selfTest's PQC legs are
21
+ * pairwise-consistency only (generate a fresh keypair, round-trip it
22
+ * against itself) and b.pqcSoftware.runKnownAnswerTest's own
23
+ * docstring concedes it is "a self-consistency gate, NOT the FIPS 203
24
+ * Appendix A KAT vectors". This file closes that gap two ways:
25
+ *
26
+ * (a) A frozen cross-implementation KNOWN-ANSWER vector. ML-KEM-1024
27
+ * keygen + encapsulate are deterministic from a seed (d||z) and
28
+ * a message (m); the vendored pure-JS @noble/post-quantum bundle
29
+ * and Node's native OpenSSL-backed ML-KEM — two fully
30
+ * independent FIPS-203 implementations — agree on the resulting
31
+ * shared secret. That agreed value is embedded as the expected
32
+ * answer; the noble primitive must reproduce it byte-for-byte.
33
+ *
34
+ * (b) A live cross-implementation oracle on every run. The vendored
35
+ * pure-JS primitive is checked against Node's native OpenSSL
36
+ * implementation in BOTH directions for ML-KEM (encaps↔decaps),
37
+ * and the spec answer for the signature families comes FROM
38
+ * OpenSSL: OpenSSL signs, the framework's noble primitive
39
+ * verifies (ML-DSA-87 and SLH-DSA-SHAKE-256f), then the
40
+ * reverse. A pure-JS lattice/hash-sig implementation agreeing
41
+ * with a C/OpenSSL one is the substance of a KAT — neither
42
+ * shares code with the other.
43
+ *
44
+ * No bypass: real vendored bundle, real node:crypto, no rejectUnauthorized
45
+ * shortcuts, no require-cache mock of anything under test. The native
46
+ * ML-KEM / ML-DSA / SLH-DSA primitives are an independent implementation,
47
+ * not a stand-in for the thing under test (the vendored noble bundle).
48
+ *
49
+ * Native PQC is a Node-26 surface. Where it is unavailable the live
50
+ * cross-impl legs report a coverage finding and the frozen KAT (which
51
+ * needs no native crypto) still runs — so the FIPS conformance claim is
52
+ * always exercised against at least one off-framework anchor.
53
+ */
54
+
55
+ var nodeCrypto = require("node:crypto");
56
+ var b = require("../..");
57
+ var check = require("../helpers/check").check;
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Independent RFC 7515 compact-JWS verifier — node:crypto only, ZERO
61
+ // framework code. This is the "different verifier" the framework's own
62
+ // jws.verify is not.
63
+ // ---------------------------------------------------------------------------
64
+
65
+ function b64uToBuf(s) {
66
+ var t = String(s).replace(/-/g, "+").replace(/_/g, "/");
67
+ while (t.length % 4) t += "=";
68
+ return Buffer.from(t, "base64");
69
+ }
70
+
71
+ // Verify a compact JWS using only node:crypto. Mirrors RFC 7515 §5.2:
72
+ // recompute the signing input (ASCII of "<protected>.<payload>"), pick
73
+ // the verify parameters from the protected header's alg, and run
74
+ // crypto.verify against the operator-supplied public key.
75
+ function rfc7515Verify(token, publicKey) {
76
+ var parts = token.split(".");
77
+ if (parts.length !== 3) throw new Error("not a 3-part compact JWS");
78
+ var header = JSON.parse(b64uToBuf(parts[0]).toString("utf8"));
79
+ var signingInput = Buffer.from(parts[0] + "." + parts[1], "ascii");
80
+ var sig = b64uToBuf(parts[2]);
81
+ var alg = header.alg;
82
+ if (alg === "ES256") {
83
+ return {
84
+ header: header,
85
+ valid: nodeCrypto.verify("sha256", signingInput,
86
+ { key: publicKey, dsaEncoding: "ieee-p1363" }, sig),
87
+ };
88
+ }
89
+ if (alg === "ES384") {
90
+ return {
91
+ header: header,
92
+ valid: nodeCrypto.verify("sha384", signingInput,
93
+ { key: publicKey, dsaEncoding: "ieee-p1363" }, sig),
94
+ };
95
+ }
96
+ if (alg === "EdDSA") {
97
+ return { header: header, valid: nodeCrypto.verify(null, signingInput, publicKey, sig) };
98
+ }
99
+ if (alg === "RS256") {
100
+ return { header: header, valid: nodeCrypto.verify("sha256", signingInput, publicKey, sig) };
101
+ }
102
+ throw new Error("independent verifier does not implement alg " + alg);
103
+ }
104
+
105
+ // ---------------------------------------------------------------------------
106
+ // Frozen cross-implementation ML-KEM-1024 KNOWN-ANSWER VECTOR.
107
+ //
108
+ // Derived deterministically (FIPS 203 is deterministic given the keygen
109
+ // seed d||z and the encapsulation message m) and confirmed identical by
110
+ // BOTH the vendored pure-JS @noble/post-quantum bundle AND Node's native
111
+ // OpenSSL ML-KEM-1024. The shared secret below is the value those two
112
+ // independent implementations agree on; the framework primitive must
113
+ // reproduce it. This anchor needs no native crypto, so it pins the FIPS
114
+ // conformance claim even on runtimes that lack native ML-KEM.
115
+ // ---------------------------------------------------------------------------
116
+
117
+ var MLKEM1024_KAT = {
118
+ // 64-byte keygen seed (d || z), FIPS 203 §7.1.
119
+ seedHex: "000102030405060708090a0b0c0d0e0f" +
120
+ "101112131415161718191a1b1c1d1e1f" +
121
+ "202122232425262728292a2b2c2d2e2f" +
122
+ "303132333435363738393a3b3c3d3e3f",
123
+ // 32-byte encapsulation message m, FIPS 203 §7.2.
124
+ msgHex: "0202020202020202020202020202020202020202020202020202020202020202",
125
+ // Expected 32-byte shared secret K, agreed by noble + OpenSSL.
126
+ sharedSecretHex: "7ca83e2bf9cdbdf7ebe24146efdd9a40a256e83c437d132d2048acf853fbbe46",
127
+ };
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Native-PQC availability probe (Node 26+). Used to gate the live
131
+ // cross-impl legs; the frozen KAT runs regardless.
132
+ // ---------------------------------------------------------------------------
133
+
134
+ // Whether this runtime can import an AKP (post-quantum) private key from a JWK
135
+ // for the given keygen alg — the exact operation each cross-implementation
136
+ // oracle leg performs. The AKP JWK *import* path is Node 26+ for ML-KEM and
137
+ // SLH-DSA; only ML-DSA JWK import is wired on the Node 24.14 floor. Probing the
138
+ // full generate -> export-to-JWK -> import-from-JWK round-trip (rather than just
139
+ // keygen, which exists for every alg on Node 24) lets a leg be SKIPPED — not
140
+ // FAILED — on a runtime that cannot perform the import the oracle relies on.
141
+ function nativeJwkImportWorks(keygenAlg) {
142
+ try {
143
+ var kp = nodeCrypto.generateKeyPairSync(keygenAlg);
144
+ var jwk = kp.privateKey.export({ format: "jwk" });
145
+ nodeCrypto.createPrivateKey({ key: jwk, format: "jwk" });
146
+ return true;
147
+ } catch (_e) { return false; }
148
+ }
149
+ function nativeMlKemAvailable() { return nativeJwkImportWorks("ml-kem-1024"); }
150
+ function nativeMlDsaAvailable() { return nativeJwkImportWorks("ml-dsa-87"); }
151
+ function nativeSlhDsaAvailable() { return nativeJwkImportWorks("slh-dsa-shake-256f"); }
152
+
153
+ function b64u(buf) { return Buffer.from(buf).toString("base64url"); }
154
+
155
+ var coverageFindings = [];
156
+
157
+ function run() {
158
+ var pq = b.pqcSoftware;
159
+ check("vendored PQC bundle is available", pq.isAvailable() === true);
160
+
161
+ // =====================================================================
162
+ // (1) b.auth.jws.sign verified by an INDEPENDENT RFC 7515 verifier.
163
+ // =====================================================================
164
+
165
+ // --- ES256 ---
166
+ var ecKeys = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "prime256v1" });
167
+ var es256Token = b.auth.jws.sign(
168
+ { iss: "blamejs-client", aud: "https://as.example.com", response_type: "code" },
169
+ { privateKey: ecKeys.privateKey, typ: "oauth-authz-req+jwt", kid: "c1" });
170
+ var es256r = rfc7515Verify(es256Token, ecKeys.publicKey);
171
+ check("jws.sign ES256: independent RFC 7515 verifier accepts", es256r.valid === true);
172
+ check("jws.sign ES256: header alg derived from key", es256r.header.alg === "ES256");
173
+ check("jws.sign ES256: typ + kid present in protected header",
174
+ es256r.header.typ === "oauth-authz-req+jwt" && es256r.header.kid === "c1");
175
+
176
+ // A tampered payload must fail the independent verifier — proves the
177
+ // verify path actually checks the signature, not just structure.
178
+ var es256Parts = es256Token.split(".");
179
+ var forgedPayload = b64u(Buffer.from(JSON.stringify(
180
+ { iss: "attacker", aud: "https://as.example.com", response_type: "code" }), "utf8"));
181
+ var es256Forged = es256Parts[0] + "." + forgedPayload + "." + es256Parts[2];
182
+ var es256ForgedR = rfc7515Verify(es256Forged, ecKeys.publicKey);
183
+ check("jws.sign ES256: tampered payload rejected by independent verifier",
184
+ es256ForgedR.valid === false);
185
+
186
+ // Wrong key must fail — proves the signature binds to the signer's key.
187
+ var otherEc = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "prime256v1" });
188
+ check("jws.sign ES256: wrong public key rejected by independent verifier",
189
+ rfc7515Verify(es256Token, otherEc.publicKey).valid === false);
190
+
191
+ // --- EdDSA ---
192
+ var edKeys = nodeCrypto.generateKeyPairSync("ed25519");
193
+ var edToken = b.auth.jws.sign({ sub: "user-42", scope: "openid" }, { privateKey: edKeys.privateKey });
194
+ var edR = rfc7515Verify(edToken, edKeys.publicKey);
195
+ check("jws.sign EdDSA: independent RFC 7515 verifier accepts", edR.valid === true);
196
+ check("jws.sign EdDSA: header alg derived from key", edR.header.alg === "EdDSA");
197
+ check("jws.sign EdDSA: wrong key rejected by independent verifier",
198
+ rfc7515Verify(edToken, nodeCrypto.generateKeyPairSync("ed25519").publicKey).valid === false);
199
+
200
+ // --- RS256 ---
201
+ var rsaKeys = nodeCrypto.generateKeyPairSync("rsa", { modulusLength: 2048 });
202
+ var rsToken = b.auth.jws.sign({ iss: "rp", aud: "op" }, { privateKey: rsaKeys.privateKey });
203
+ var rsR = rfc7515Verify(rsToken, rsaKeys.publicKey);
204
+ check("jws.sign RS256: independent RFC 7515 verifier accepts", rsR.valid === true);
205
+ check("jws.sign RS256: header alg derived from RSA key", rsR.header.alg === "RS256");
206
+
207
+ // =====================================================================
208
+ // (2a) ML-KEM-1024 FROZEN cross-implementation KNOWN-ANSWER vector.
209
+ // The framework primitive must produce the exact spec shared secret
210
+ // that two independent FIPS-203 implementations agree on.
211
+ // =====================================================================
212
+
213
+ var katSeed = Buffer.from(MLKEM1024_KAT.seedHex, "hex");
214
+ var katMsg = Buffer.from(MLKEM1024_KAT.msgHex, "hex");
215
+ var katExpected = Buffer.from(MLKEM1024_KAT.sharedSecretHex, "hex");
216
+
217
+ check("ML-KEM-1024 KAT: seed is 64 bytes (d||z)", katSeed.length === 64);
218
+ check("ML-KEM-1024 KAT: message is 32 bytes (m)", katMsg.length === 32);
219
+
220
+ var katKp = pq.ml_kem_1024.keygen(katSeed);
221
+ check("ML-KEM-1024 KAT: deterministic keygen pk size (FIPS 203 |ek|=1568)",
222
+ katKp.publicKey.length === 1568);
223
+ check("ML-KEM-1024 KAT: deterministic keygen sk size (FIPS 203 |dk|=3168)",
224
+ katKp.secretKey.length === 3168);
225
+
226
+ var katEnc = pq.ml_kem_1024.encapsulate(katKp.publicKey, katMsg);
227
+ check("ML-KEM-1024 KAT: ciphertext size (FIPS 203 |c|=1568)",
228
+ katEnc.cipherText.length === 1568);
229
+ check("ML-KEM-1024 KAT: encapsulated shared secret matches frozen spec answer",
230
+ Buffer.from(katEnc.sharedSecret).equals(katExpected));
231
+
232
+ var katSs = pq.ml_kem_1024.decapsulate(katEnc.cipherText, katKp.secretKey);
233
+ check("ML-KEM-1024 KAT: decapsulated shared secret matches frozen spec answer",
234
+ Buffer.from(katSs).equals(katExpected));
235
+
236
+ // Re-run to assert determinism — a non-deterministic keygen/encaps
237
+ // would make the frozen vector meaningless.
238
+ var katKp2 = pq.ml_kem_1024.keygen(katSeed);
239
+ var katEnc2 = pq.ml_kem_1024.encapsulate(katKp2.publicKey, katMsg);
240
+ check("ML-KEM-1024 KAT: keygen is deterministic from the seed",
241
+ Buffer.from(katKp.publicKey).equals(Buffer.from(katKp2.publicKey)));
242
+ check("ML-KEM-1024 KAT: encapsulate is deterministic from (pk, m)",
243
+ Buffer.from(katEnc.cipherText).equals(Buffer.from(katEnc2.cipherText)));
244
+
245
+ // =====================================================================
246
+ // (2b) Live cross-implementation oracle: vendored pure-JS noble bundle
247
+ // vs Node native OpenSSL. Independent in both directions.
248
+ // =====================================================================
249
+
250
+ if (nativeMlKemAvailable()) {
251
+ // Cross-check the frozen KAT's public key against OpenSSL too:
252
+ // import noble's (seed, pk) and have OpenSSL decapsulate noble's
253
+ // ciphertext — the independent impl must derive the same secret.
254
+ var natPriv = nodeCrypto.createPrivateKey({
255
+ key: { kty: "AKP", alg: "ML-KEM-1024", priv: b64u(katSeed), pub: b64u(katKp.publicKey) },
256
+ format: "jwk",
257
+ });
258
+ var natDecaps = nodeCrypto.decapsulate(natPriv, Buffer.from(katEnc.cipherText));
259
+ check("ML-KEM-1024 live: OpenSSL accepts noble's deterministic key + ciphertext",
260
+ Buffer.from(natDecaps).equals(katExpected));
261
+
262
+ // Fresh random keypair, noble encapsulates -> OpenSSL decapsulates.
263
+ var freshSeed = nodeCrypto.randomBytes(64);
264
+ var freshKp = pq.ml_kem_1024.keygen(freshSeed);
265
+ var freshEnc = pq.ml_kem_1024.encapsulate(freshKp.publicKey);
266
+ var freshPriv = nodeCrypto.createPrivateKey({
267
+ key: { kty: "AKP", alg: "ML-KEM-1024", priv: b64u(freshSeed), pub: b64u(freshKp.publicKey) },
268
+ format: "jwk",
269
+ });
270
+ var ossDecaps = nodeCrypto.decapsulate(freshPriv, Buffer.from(freshEnc.cipherText));
271
+ check("ML-KEM-1024 live: noble encaps -> OpenSSL decaps agree",
272
+ Buffer.from(freshEnc.sharedSecret).equals(Buffer.from(ossDecaps)));
273
+
274
+ // Reverse: OpenSSL encapsulates -> noble decapsulates.
275
+ var ossEnc = nodeCrypto.encapsulate(nodeCrypto.createPublicKey(freshPriv));
276
+ var nobleDecaps = pq.ml_kem_1024.decapsulate(ossEnc.ciphertext, freshKp.secretKey);
277
+ check("ML-KEM-1024 live: OpenSSL encaps -> noble decaps agree",
278
+ Buffer.from(ossEnc.sharedKey).equals(Buffer.from(nobleDecaps)));
279
+
280
+ // A different keypair must NOT recover the secret — proves the KEM
281
+ // binds the secret to the key, not to the ciphertext shape.
282
+ var wrongSeed = nodeCrypto.randomBytes(64);
283
+ var wrongKp = pq.ml_kem_1024.keygen(wrongSeed);
284
+ var wrongDecaps = pq.ml_kem_1024.decapsulate(freshEnc.cipherText, wrongKp.secretKey);
285
+ check("ML-KEM-1024 live: wrong secret key does not recover the shared secret",
286
+ !Buffer.from(wrongDecaps).equals(Buffer.from(freshEnc.sharedSecret)));
287
+ } else {
288
+ coverageFindings.push("ML-KEM-1024 live cross-impl (Node native OpenSSL) " +
289
+ "unavailable on this runtime — frozen cross-impl KAT still ran.");
290
+ }
291
+
292
+ // =====================================================================
293
+ // (3) ML-DSA-87 — spec answer FROM OpenSSL: OpenSSL signs, the
294
+ // framework's noble primitive verifies. Then the reverse.
295
+ // =====================================================================
296
+
297
+ if (nativeMlDsaAvailable()) {
298
+ var dsaSeed = nodeCrypto.randomBytes(32);
299
+ var dsaKp = pq.ml_dsa_87.keygen(dsaSeed);
300
+ check("ML-DSA-87: keygen pk size (FIPS 204 |pk|=2592)", dsaKp.publicKey.length === 2592);
301
+
302
+ var dsaMsg = Buffer.from("cross-impl ML-DSA-87 known-answer message", "utf8");
303
+ // Import noble's (seed, pk) into OpenSSL; OpenSSL is the signer.
304
+ var dsaNatPriv = nodeCrypto.createPrivateKey({
305
+ key: { kty: "AKP", alg: "ML-DSA-87", priv: b64u(dsaSeed), pub: b64u(dsaKp.publicKey) },
306
+ format: "jwk",
307
+ });
308
+ var ossSig = nodeCrypto.sign(null, dsaMsg, dsaNatPriv);
309
+ check("ML-DSA-87: OpenSSL produced a non-empty signature", ossSig.length > 0);
310
+ // The framework's pure-JS verifier accepts an OpenSSL-produced sig.
311
+ check("ML-DSA-87: noble verifies an OpenSSL-signed message (spec answer = accept)",
312
+ pq.ml_dsa_87.verify(Buffer.from(ossSig), dsaMsg, dsaKp.publicKey) === true);
313
+ // Tamper the OpenSSL signature -> noble must reject.
314
+ var ossSigTamp = Buffer.from(ossSig); ossSigTamp[0] ^= 0xff;
315
+ check("ML-DSA-87: noble rejects a tampered OpenSSL signature",
316
+ pq.ml_dsa_87.verify(ossSigTamp, dsaMsg, dsaKp.publicKey) === false);
317
+ // Wrong message -> noble must reject.
318
+ check("ML-DSA-87: noble rejects an OpenSSL sig over a different message",
319
+ pq.ml_dsa_87.verify(Buffer.from(ossSig),
320
+ Buffer.from("different message", "utf8"), dsaKp.publicKey) === false);
321
+
322
+ // Reverse: noble signs -> OpenSSL verifies (spec answer = accept).
323
+ var nobleSig = pq.ml_dsa_87.sign(dsaMsg, dsaKp.secretKey);
324
+ var dsaNatPub = nodeCrypto.createPublicKey(dsaNatPriv);
325
+ check("ML-DSA-87: OpenSSL verifies a noble-signed message",
326
+ nodeCrypto.verify(null, dsaMsg, dsaNatPub, Buffer.from(nobleSig)) === true);
327
+ } else {
328
+ coverageFindings.push("ML-DSA-87 cross-impl (Node native OpenSSL) unavailable " +
329
+ "on this runtime — no off-framework signature oracle exercised for ML-DSA-87.");
330
+ }
331
+
332
+ // =====================================================================
333
+ // (4) SLH-DSA-SHAKE-256f — spec answer FROM OpenSSL, same shape.
334
+ // =====================================================================
335
+
336
+ if (nativeSlhDsaAvailable()) {
337
+ var slh = pq.slh_dsa_shake_256f;
338
+ var slhKp = slh.keygen();
339
+ check("SLH-DSA-SHAKE-256f: keygen pk size (FIPS 205 |pk|=64)", slhKp.publicKey.length === 64);
340
+
341
+ var slhMsg = Buffer.from("cross-impl SLH-DSA-SHAKE-256f known-answer message", "utf8");
342
+ // OpenSSL is the signer. Native SLH-DSA's JWK private field is the
343
+ // full secret key, which matches noble's secretKey byte layout.
344
+ var slhNatPriv = nodeCrypto.createPrivateKey({
345
+ key: { kty: "AKP", alg: "SLH-DSA-SHAKE-256f", priv: b64u(slhKp.secretKey), pub: b64u(slhKp.publicKey) },
346
+ format: "jwk",
347
+ });
348
+ var slhOssSig = nodeCrypto.sign(null, slhMsg, slhNatPriv);
349
+ check("SLH-DSA-SHAKE-256f: OpenSSL produced a non-empty signature", slhOssSig.length > 0);
350
+ check("SLH-DSA-SHAKE-256f: noble verifies an OpenSSL-signed message (spec answer = accept)",
351
+ slh.verify(Buffer.from(slhOssSig), slhMsg, slhKp.publicKey) === true);
352
+ var slhTamp = Buffer.from(slhOssSig); slhTamp[0] ^= 0xff;
353
+ check("SLH-DSA-SHAKE-256f: noble rejects a tampered OpenSSL signature",
354
+ slh.verify(slhTamp, slhMsg, slhKp.publicKey) === false);
355
+
356
+ // Reverse: noble signs -> OpenSSL verifies.
357
+ var slhNobleSig = slh.sign(slhMsg, slhKp.secretKey);
358
+ var slhNatPub = nodeCrypto.createPublicKey(slhNatPriv);
359
+ check("SLH-DSA-SHAKE-256f: OpenSSL verifies a noble-signed message",
360
+ nodeCrypto.verify(null, slhMsg, slhNatPub, Buffer.from(slhNobleSig)) === true);
361
+ } else {
362
+ coverageFindings.push("SLH-DSA-SHAKE-256f cross-impl (Node native OpenSSL) " +
363
+ "unavailable on this runtime — no off-framework signature oracle exercised for SLH-DSA.");
364
+ }
365
+
366
+ // =====================================================================
367
+ // Coverage findings — where no independent oracle was achievable.
368
+ // COSE_Sign1 (b.cose.sign) and PGP (b.mail.crypto.pgp) are NOT proven
369
+ // here against an external verifier; an independent CBOR Sig_structure
370
+ // reconstruction (COSE) and a GnuPG cross-verify (PGP) are the next
371
+ // oracles to build. b.crypto.selfTest's PQC legs remain
372
+ // pairwise-only — this file is the independent KAT coverage they lack.
373
+ // =====================================================================
374
+ coverageFindings.push("COSE_Sign1 (b.cose.sign) NOT verified against an independent " +
375
+ "oracle here — requires a from-scratch CBOR Sig_structure verifier.");
376
+ coverageFindings.push("PGP (b.mail.crypto.pgp) NOT cross-verified against GnuPG here — " +
377
+ "requires gpg in PATH (not assumed in layer-0).");
378
+ coverageFindings.push("b.crypto.selfTest's ML-KEM/ML-DSA/SLH-DSA legs remain " +
379
+ "pairwise-consistency only; this file supplies the independent-oracle / frozen-KAT coverage.");
380
+
381
+ if (coverageFindings.length) {
382
+ console.log("Coverage findings:");
383
+ coverageFindings.forEach(function (f) { console.log(" - " + f); });
384
+ }
385
+
386
+ console.log("OK — crypto-interop-oracles tests");
387
+ }
388
+
389
+ module.exports = { run: run };
390
+ if (require.main === module) {
391
+ try { run(); process.exit(0); } catch (e) { console.error(e); process.exit(1); }
392
+ }
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ /**
3
+ * b.middleware.csrfProtect — cookie-header parsing prototype-pollution
4
+ * defense (CWE-915 / CWE-1321) + double-submit success path.
5
+ *
6
+ * The Cookie request header is attacker-controlled. The internal cookie
7
+ * parser builds its map from [name, value] pairs through
8
+ * Object.fromEntries onto a null-prototype object — never a computed-
9
+ * write (`out[name] = value`) sink. These tests drive the middleware
10
+ * end-to-end (no internal mocks) to verify:
11
+ * - a Cookie header carrying `__proto__` / `constructor` / `prototype`
12
+ * names does NOT pollute Object.prototype;
13
+ * - a legitimate CSRF cookie alongside those hostile names still
14
+ * resolves and the double-submit check passes (header token matches);
15
+ * - first-occurrence-wins is preserved for duplicate cookie names.
16
+ *
17
+ * Run standalone: `node test/layer-0-primitives/csrf-protect.test.js`
18
+ * Or via smoke: `node test/smoke.js`
19
+ */
20
+
21
+ var helpers = require("../helpers");
22
+ var b = helpers.b;
23
+ var check = helpers.check;
24
+ var _mockReq = helpers._mockReq;
25
+ var _mockRes = helpers._mockRes;
26
+
27
+ // Drive one request through the csrf middleware; resolve to an outcome
28
+ // object describing whether next() was called or the request was denied.
29
+ function _runCsrf(mwOpts, req) {
30
+ var res = _mockRes();
31
+ return new Promise(function (resolve) {
32
+ var calledNext = false;
33
+ var mw = b.middleware.csrfProtect(mwOpts);
34
+ // denyResponse writes to res + ends it; next() is the success signal.
35
+ // mockRes captures the status via writeHead → res._captured().status.
36
+ var origEnd = res.end;
37
+ res.end = function () {
38
+ var r = origEnd.apply(res, arguments);
39
+ var cap = res._captured();
40
+ resolve({ outcome: "denied", status: cap.status, body: cap.body, req: req, res: res, calledNext: calledNext });
41
+ return r;
42
+ };
43
+ mw(req, res, function () {
44
+ calledNext = true;
45
+ resolve({ outcome: "next", req: req, res: res, calledNext: true });
46
+ });
47
+ });
48
+ }
49
+
50
+ async function testSuccessPathDoubleSubmit() {
51
+ // Valid 64-hex cookie + matching X-CSRF-Token header on a POST → next().
52
+ var token = b.forms.generateCsrfToken();
53
+ var req = _mockReq({
54
+ method: "POST",
55
+ url: "/submit",
56
+ headers: {
57
+ host: "example.com",
58
+ cookie: "csrf=" + token,
59
+ "x-csrf-token": token,
60
+ },
61
+ });
62
+ var r = await _runCsrf({ cookie: true }, req);
63
+ check("csrf: valid double-submit passes (next called)", r.outcome === "next");
64
+ }
65
+
66
+ async function testMismatchDenied() {
67
+ var token = b.forms.generateCsrfToken();
68
+ var req = _mockReq({
69
+ method: "POST",
70
+ url: "/submit",
71
+ headers: {
72
+ host: "example.com",
73
+ cookie: "csrf=" + token,
74
+ "x-csrf-token": b.forms.generateCsrfToken(), // different token
75
+ },
76
+ });
77
+ var r = await _runCsrf({ cookie: true }, req);
78
+ check("csrf: token mismatch denied (403)", r.outcome === "denied" && r.status === 403);
79
+ }
80
+
81
+ async function testPoisonedCookieNamesDoNotPollute() {
82
+ // A Cookie header carrying __proto__ / constructor / prototype names
83
+ // alongside the real csrf cookie must not pollute Object.prototype, and
84
+ // the legitimate cookie must still resolve so the double-submit passes.
85
+ var token = b.forms.generateCsrfToken();
86
+ var req = _mockReq({
87
+ method: "POST",
88
+ url: "/submit",
89
+ headers: {
90
+ host: "example.com",
91
+ cookie: "__proto__=polluted; constructor=evil; prototype=evil2; csrf=" + token + "; other=ok",
92
+ "x-csrf-token": token,
93
+ },
94
+ });
95
+ var r = await _runCsrf({ cookie: true }, req);
96
+ check("csrf: hostile cookie names did not pollute Object.prototype",
97
+ ({}).polluted === undefined &&
98
+ Object.prototype.polluted === undefined &&
99
+ ({}).evil === undefined &&
100
+ ({}).evil2 === undefined);
101
+ check("csrf: legitimate cookie still resolved (double-submit passed)",
102
+ r.outcome === "next");
103
+ }
104
+
105
+ async function testFirstOccurrenceWinsForDuplicateCookie() {
106
+ // RFC 6265 §5.2 — duplicate cookie names resolve to the FIRST occurrence
107
+ // (most-specific path). A later forged `csrf=` must not override the
108
+ // first; the double-submit must validate against the first value.
109
+ var first = b.forms.generateCsrfToken();
110
+ var second = b.forms.generateCsrfToken();
111
+ var req = _mockReq({
112
+ method: "POST",
113
+ url: "/submit",
114
+ headers: {
115
+ host: "example.com",
116
+ cookie: "csrf=" + first + "; csrf=" + second,
117
+ "x-csrf-token": first, // matches FIRST occurrence
118
+ },
119
+ });
120
+ var r = await _runCsrf({ cookie: true }, req);
121
+ check("csrf: duplicate cookie resolves to first occurrence (next on first-token submit)",
122
+ r.outcome === "next");
123
+
124
+ // Submitting the SECOND value must be rejected — proves first-wins, not
125
+ // last-wins.
126
+ var req2 = _mockReq({
127
+ method: "POST",
128
+ url: "/submit",
129
+ headers: {
130
+ host: "example.com",
131
+ cookie: "csrf=" + first + "; csrf=" + second,
132
+ "x-csrf-token": second,
133
+ },
134
+ });
135
+ var r2 = await _runCsrf({ cookie: true }, req2);
136
+ check("csrf: submitting the second (shadowed) cookie value is denied",
137
+ r2.outcome === "denied" && r2.status === 403);
138
+ }
139
+
140
+ async function run() {
141
+ await testSuccessPathDoubleSubmit();
142
+ await testMismatchDenied();
143
+ await testPoisonedCookieNamesDoNotPollute();
144
+ await testFirstOccurrenceWinsForDuplicateCookie();
145
+ }
146
+
147
+ module.exports = { run: run };
148
+
149
+ if (require.main === module) {
150
+ run().then(
151
+ function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
152
+ // Re-throw rather than logging e.message: the failure message can
153
+ // echo request-derived cookie names/values fed into the middleware,
154
+ // and writing that to the log unescaped would be log injection
155
+ // (CWE-117). The non-zero exit + thrown stack still surface the
156
+ // failure to the runner.
157
+ function (e) { process.exitCode = 1; throw e; }
158
+ );
159
+ }