@blamejs/blamejs-shop 0.4.55 → 0.4.57

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 (399) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/admin.js +385 -2
  3. package/lib/asset-manifest.json +1 -1
  4. package/lib/vendor/MANIFEST.json +426 -366
  5. package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
  6. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  7. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
  8. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
  9. package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
  10. package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
  11. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
  12. package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
  13. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
  14. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  15. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  16. package/lib/vendor/blamejs/api-snapshot.json +1381 -4
  17. package/lib/vendor/blamejs/eslint.config.mjs +1 -0
  18. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
  19. package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
  20. package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
  21. package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
  22. package/lib/vendor/blamejs/index.js +2 -0
  23. package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
  24. package/lib/vendor/blamejs/lib/acme.js +6 -5
  25. package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
  26. package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
  27. package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
  28. package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
  29. package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
  30. package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
  31. package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
  32. package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
  33. package/lib/vendor/blamejs/lib/ai-input.js +2 -2
  34. package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
  35. package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
  36. package/lib/vendor/blamejs/lib/api-key.js +37 -28
  37. package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
  38. package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
  39. package/lib/vendor/blamejs/lib/archive-read.js +5 -17
  40. package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
  41. package/lib/vendor/blamejs/lib/archive.js +2 -10
  42. package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
  43. package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
  44. package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
  45. package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
  46. package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
  47. package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
  48. package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
  49. package/lib/vendor/blamejs/lib/audit.js +84 -0
  50. package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
  51. package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
  52. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
  53. package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
  54. package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
  55. package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
  56. package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
  57. package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
  58. package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
  59. package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
  60. package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
  61. package/lib/vendor/blamejs/lib/auth/password.js +7 -1
  62. package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
  63. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
  64. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
  65. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
  66. package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
  67. package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
  68. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
  69. package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
  70. package/lib/vendor/blamejs/lib/backup/index.js +14 -47
  71. package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
  72. package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
  73. package/lib/vendor/blamejs/lib/cache.js +7 -18
  74. package/lib/vendor/blamejs/lib/cbor.js +2 -1
  75. package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
  76. package/lib/vendor/blamejs/lib/cert.js +3 -10
  77. package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
  78. package/lib/vendor/blamejs/lib/cli.js +5 -1
  79. package/lib/vendor/blamejs/lib/client-hints.js +7 -9
  80. package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
  81. package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
  82. package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
  83. package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
  84. package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
  85. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
  86. package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
  87. package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
  88. package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
  89. package/lib/vendor/blamejs/lib/compliance.js +2 -9
  90. package/lib/vendor/blamejs/lib/config-drift.js +2 -12
  91. package/lib/vendor/blamejs/lib/content-digest.js +10 -8
  92. package/lib/vendor/blamejs/lib/cookies.js +5 -11
  93. package/lib/vendor/blamejs/lib/cose.js +19 -11
  94. package/lib/vendor/blamejs/lib/cra-report.js +1 -11
  95. package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
  96. package/lib/vendor/blamejs/lib/crypto.js +120 -3
  97. package/lib/vendor/blamejs/lib/csp.js +235 -3
  98. package/lib/vendor/blamejs/lib/daemon.js +42 -41
  99. package/lib/vendor/blamejs/lib/data-act.js +19 -9
  100. package/lib/vendor/blamejs/lib/db-query.js +6 -40
  101. package/lib/vendor/blamejs/lib/db.js +34 -12
  102. package/lib/vendor/blamejs/lib/dbsc.js +5 -6
  103. package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
  104. package/lib/vendor/blamejs/lib/deprecate.js +4 -5
  105. package/lib/vendor/blamejs/lib/did.js +6 -2
  106. package/lib/vendor/blamejs/lib/dsr.js +8 -12
  107. package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
  108. package/lib/vendor/blamejs/lib/external-db.js +14 -26
  109. package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
  110. package/lib/vendor/blamejs/lib/fdx.js +22 -18
  111. package/lib/vendor/blamejs/lib/file-upload.js +80 -66
  112. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
  113. package/lib/vendor/blamejs/lib/framework-error.js +12 -0
  114. package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
  115. package/lib/vendor/blamejs/lib/fsm.js +7 -12
  116. package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
  117. package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
  118. package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
  119. package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
  120. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  121. package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
  122. package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
  123. package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
  124. package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
  125. package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
  126. package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
  127. package/lib/vendor/blamejs/lib/guard-email.js +46 -53
  128. package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
  129. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
  130. package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
  131. package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
  132. package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
  133. package/lib/vendor/blamejs/lib/guard-html.js +65 -117
  134. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
  135. package/lib/vendor/blamejs/lib/guard-image.js +280 -77
  136. package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
  137. package/lib/vendor/blamejs/lib/guard-json.js +87 -103
  138. package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
  139. package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
  140. package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
  141. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
  142. package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
  143. package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
  144. package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
  145. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
  146. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
  147. package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
  148. package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
  149. package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
  150. package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
  151. package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
  152. package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
  153. package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
  154. package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
  155. package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
  156. package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
  157. package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
  158. package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
  159. package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
  160. package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
  161. package/lib/vendor/blamejs/lib/guard-template.js +23 -80
  162. package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
  163. package/lib/vendor/blamejs/lib/guard-text.js +592 -0
  164. package/lib/vendor/blamejs/lib/guard-time.js +27 -95
  165. package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
  166. package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
  167. package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
  168. package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
  169. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
  170. package/lib/vendor/blamejs/lib/http-client.js +8 -21
  171. package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
  172. package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
  173. package/lib/vendor/blamejs/lib/i18n.js +83 -26
  174. package/lib/vendor/blamejs/lib/inbox.js +8 -8
  175. package/lib/vendor/blamejs/lib/incident-report.js +3 -21
  176. package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
  177. package/lib/vendor/blamejs/lib/jobs.js +3 -2
  178. package/lib/vendor/blamejs/lib/keychain.js +6 -18
  179. package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
  180. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
  181. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
  182. package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
  183. package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
  184. package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
  185. package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
  186. package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
  187. package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
  188. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
  189. package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
  190. package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
  191. package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
  192. package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
  193. package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
  194. package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
  195. package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
  196. package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
  197. package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
  198. package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
  199. package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
  200. package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
  201. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
  202. package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
  203. package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
  204. package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
  205. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
  206. package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
  207. package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
  208. package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
  209. package/lib/vendor/blamejs/lib/mail-store.js +3 -2
  210. package/lib/vendor/blamejs/lib/mail.js +6 -11
  211. package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
  212. package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
  213. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
  214. package/lib/vendor/blamejs/lib/mcp.js +1 -1
  215. package/lib/vendor/blamejs/lib/mdoc.js +11 -12
  216. package/lib/vendor/blamejs/lib/metrics.js +32 -30
  217. package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
  218. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
  219. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
  220. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
  221. package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
  222. package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
  223. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
  224. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
  225. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
  226. package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
  227. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
  228. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
  229. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
  230. package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
  231. package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
  232. package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
  233. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
  234. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
  235. package/lib/vendor/blamejs/lib/migrations.js +4 -13
  236. package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
  237. package/lib/vendor/blamejs/lib/module-loader.js +44 -0
  238. package/lib/vendor/blamejs/lib/money.js +105 -0
  239. package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
  240. package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
  241. package/lib/vendor/blamejs/lib/network-dane.js +8 -6
  242. package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
  243. package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
  244. package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
  245. package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
  246. package/lib/vendor/blamejs/lib/network-tls.js +40 -42
  247. package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
  248. package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
  249. package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
  250. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
  251. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
  252. package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
  253. package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
  254. package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
  255. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
  256. package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
  257. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
  258. package/lib/vendor/blamejs/lib/observability.js +95 -0
  259. package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
  260. package/lib/vendor/blamejs/lib/otel-export.js +7 -10
  261. package/lib/vendor/blamejs/lib/outbox.js +43 -37
  262. package/lib/vendor/blamejs/lib/pagination.js +11 -15
  263. package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
  264. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
  265. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
  266. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
  267. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
  268. package/lib/vendor/blamejs/lib/pick.js +63 -5
  269. package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
  270. package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
  271. package/lib/vendor/blamejs/lib/problem-details.js +2 -5
  272. package/lib/vendor/blamejs/lib/pubsub.js +4 -8
  273. package/lib/vendor/blamejs/lib/redact.js +2 -1
  274. package/lib/vendor/blamejs/lib/render.js +4 -2
  275. package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
  276. package/lib/vendor/blamejs/lib/restore.js +5 -22
  277. package/lib/vendor/blamejs/lib/retention.js +3 -5
  278. package/lib/vendor/blamejs/lib/safe-async.js +457 -0
  279. package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
  280. package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
  281. package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
  282. package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
  283. package/lib/vendor/blamejs/lib/safe-json.js +7 -8
  284. package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
  285. package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
  286. package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
  287. package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
  288. package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
  289. package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
  290. package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
  291. package/lib/vendor/blamejs/lib/sandbox.js +3 -2
  292. package/lib/vendor/blamejs/lib/scheduler.js +5 -12
  293. package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
  294. package/lib/vendor/blamejs/lib/seeders.js +4 -11
  295. package/lib/vendor/blamejs/lib/self-update.js +92 -69
  296. package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
  297. package/lib/vendor/blamejs/lib/session.js +194 -6
  298. package/lib/vendor/blamejs/lib/sql.js +225 -78
  299. package/lib/vendor/blamejs/lib/sse.js +6 -10
  300. package/lib/vendor/blamejs/lib/static.js +136 -98
  301. package/lib/vendor/blamejs/lib/storage.js +4 -2
  302. package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
  303. package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
  304. package/lib/vendor/blamejs/lib/tsa.js +11 -15
  305. package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
  306. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
  307. package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
  308. package/lib/vendor/blamejs/lib/vc.js +2 -7
  309. package/lib/vendor/blamejs/lib/vex.js +35 -13
  310. package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
  311. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
  312. package/lib/vendor/blamejs/lib/webhook.js +43 -18
  313. package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
  314. package/lib/vendor/blamejs/lib/websocket.js +7 -3
  315. package/lib/vendor/blamejs/lib/worm.js +2 -3
  316. package/lib/vendor/blamejs/lib/ws-client.js +8 -10
  317. package/lib/vendor/blamejs/package.json +1 -1
  318. package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
  319. package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
  320. package/lib/vendor/blamejs/test/00-primitives.js +136 -7
  321. package/lib/vendor/blamejs/test/10-state.js +9 -3
  322. package/lib/vendor/blamejs/test/30-chain.js +40 -0
  323. package/lib/vendor/blamejs/test/helpers/check.js +18 -0
  324. package/lib/vendor/blamejs/test/helpers/db.js +4 -0
  325. package/lib/vendor/blamejs/test/helpers/index.js +1 -0
  326. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
  327. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
  328. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
  329. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
  330. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
  331. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
  334. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
  335. package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
  336. package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
  337. package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
  338. package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
  342. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
  345. package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
  347. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
  348. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
  376. package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
  388. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
  389. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
  390. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
  391. package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
  392. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
  395. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
  396. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
  397. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
  398. package/lib/winback-campaigns.js +202 -42
  399. package/package.json +1 -1
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * b.session.bump / validFrom / check — per-subject valid-from boundary for
4
+ * STATELESS self-validating tokens (sealed cookies with no DB row, JWTs) that
5
+ * destroy()/destroyAllForUser() can't revoke by deleting a row (#331).
6
+ *
7
+ * Drives the real consumer path through the public b.session surface against a
8
+ * real test DB (setupTestDb provisions the framework _blamejs_session_valid_from
9
+ * table). RED on the current tree: b.session.bump is undefined.
10
+ */
11
+
12
+ var helpers = require("../helpers");
13
+ var b = helpers.b;
14
+ var check = helpers.check;
15
+ var setupTestDb = helpers.setupTestDb;
16
+ var teardownTestDb = helpers.teardownTestDb;
17
+ var fs = require("fs");
18
+ var os = require("os");
19
+ var path = require("path");
20
+
21
+ async function run() {
22
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-svf-"));
23
+ try {
24
+ await setupTestDb(tmpDir);
25
+ var s = b.session;
26
+
27
+ check("bump / validFrom / check are exported on b.session",
28
+ typeof s.bump === "function" && typeof s.validFrom === "function" && typeof s.check === "function");
29
+
30
+ // A never-bumped subject has boundary 0 — every non-negative iat is valid.
31
+ check("validFrom is 0 for a never-bumped subject", (await s.validFrom("user-1")) === 0);
32
+ var t0 = Date.now() - 10000;
33
+ check("a token issued before any bump is valid", (await s.check("user-1", t0)) === true);
34
+
35
+ // bump raises the boundary to now; tokens issued before it are revoked.
36
+ var boundary = await s.bump("user-1");
37
+ check("bump returns the effective boundary (>= the pre-bump iat)",
38
+ typeof boundary === "number" && boundary >= t0);
39
+ check("validFrom now reflects the bump", (await s.validFrom("user-1")) === boundary);
40
+ check("a token issued BEFORE the bump is now revoked", (await s.check("user-1", t0)) === false);
41
+ check("a token issued AFTER the bump is still valid", (await s.check("user-1", boundary + 1000)) === true);
42
+
43
+ // Monotonic: a lower (replayed / clock-skewed) epoch can't move it back.
44
+ var lower = await s.bump("user-1", { epochMs: boundary - 5000 });
45
+ check("a bump to a LOWER epoch is a monotonic no-op", lower === boundary);
46
+ var higher = await s.bump("user-1", { epochMs: boundary + 5000 });
47
+ check("a bump to a HIGHER epoch advances the boundary", higher === boundary + 5000);
48
+
49
+ // check fails CLOSED on a malformed iat (treat an unparseable token as revoked).
50
+ check("check fails closed on NaN iat", (await s.check("user-1", NaN)) === false);
51
+ check("check fails closed on a negative iat", (await s.check("user-1", -1)) === false);
52
+ check("check fails closed on a non-number iat", (await s.check("user-1", "123")) === false);
53
+
54
+ // bump validates its inputs (config-time throw tier).
55
+ var threwSubject = false;
56
+ try { await s.bump(""); } catch (e) { threwSubject = /INVALID_ARG/.test(e.code || ""); }
57
+ check("bump rejects an empty subjectId", threwSubject);
58
+ var threwEpoch = false;
59
+ try { await s.bump("user-1", { epochMs: -1 }); } catch (e) { threwEpoch = /INVALID_ARG/.test(e.code || ""); }
60
+ check("bump rejects a negative epochMs", threwEpoch);
61
+
62
+ // #17 integration: a "logout everywhere" via destroyAllForUser also raises
63
+ // the stateless boundary, so the operator's stateless tokens are revoked
64
+ // too — not only the store-backed rows.
65
+ check("a fresh subject starts un-bumped", (await s.validFrom("user-2")) === 0);
66
+ await s.destroyAllForUser("user-2");
67
+ check("destroyAllForUser raises the stateless valid-from boundary", (await s.validFrom("user-2")) > 0);
68
+ } finally {
69
+ try { await teardownTestDb(tmpDir); } catch (_e) { /* best-effort */ }
70
+ }
71
+ }
72
+
73
+ module.exports = { run: run };
@@ -31,6 +31,7 @@ async function run() {
31
31
  check("b.sql.update", typeof b.sql.update === "function");
32
32
  check("b.sql.delete", typeof b.sql.delete === "function");
33
33
  check("b.sql.upsert", typeof b.sql.upsert === "function");
34
+ check("b.sql.insertSelectWhere", typeof b.sql.insertSelectWhere === "function");
34
35
  check("b.sql.table", typeof b.sql.table === "function");
35
36
  check("b.sql.createTable", typeof b.sql.createTable === "function");
36
37
  check("b.sql.createIndex", typeof b.sql.createIndex === "function");
@@ -590,6 +591,105 @@ async function run() {
590
591
  check("upsert readback renders a cast conflict key (CAST) binding the inner value, not the wrapper",
591
592
  rbCast.readbackSql && rbCast.readbackSql.sql.indexOf("CAST(") !== -1 &&
592
593
  rbCast.readbackSql.params.length === 1 && rbCast.readbackSql.params[0] === "42");
594
+
595
+ // ==== insertSelectWhere (conditional INSERT...SELECT...WHERE, #335) ====
596
+ // The append-only-ledger debit: a row written ONLY when a guard derived
597
+ // from the table itself holds, with no mutable counter row to increment().
598
+ // Standard SQL across all three dialects; the SELECT is value-less and the
599
+ // WHERE admits one row or zero.
600
+
601
+ // Object-form values infer the column list; the guard is an EXISTS over a
602
+ // same-dialect sub-builder (the balance fence). The cells route through the
603
+ // value-cell choke-point (fn(NOW) emits a token, no param).
604
+ var ledgerBalance = sql.select("wallet_ledger", { dialect: "postgres" }).selectRaw("1")
605
+ .whereRaw('"wallet_id" = ?', ["w-1"]);
606
+ var debit = sql.insertSelectWhere("wallet_ledger", { dialect: "postgres" })
607
+ .values({ wallet_id: "w-1", amount: -25, at: sql.fn("NOW") })
608
+ .whereExists(ledgerBalance)
609
+ .returning(["id"]).toSql();
610
+ check("insertSelectWhere emits INSERT...SELECT cells...WHERE EXISTS...RETURNING",
611
+ debit.sql === 'INSERT INTO wallet_ledger ("wallet_id", "amount", "at") ' +
612
+ 'SELECT ?, ?, NOW() WHERE EXISTS (SELECT 1 FROM wallet_ledger WHERE ("wallet_id" = ?)) ' +
613
+ 'RETURNING "id"');
614
+ check("insertSelectWhere binds value cells then the guard params in order, fn emits no param",
615
+ debit.params.length === 3 && debit.params[0] === "w-1" &&
616
+ debit.params[1] === -25 && debit.params[2] === "w-1");
617
+
618
+ // Positional values() aligned to a prior columns() call, sqlite dialect,
619
+ // a scalar guard (whereOp). No RETURNING -> none emitted.
620
+ var lit = sql.insertSelectWhere("seats", { dialect: "sqlite" })
621
+ .columns(["event_id", "seat_no"]).values(["e-9", 12])
622
+ .whereOp("event_id", "=", "e-9").toSql();
623
+ check("insertSelectWhere positional values + sqlite quoting + scalar guard",
624
+ lit.sql === 'INSERT INTO seats ("event_id", "seat_no") SELECT ?, ? WHERE "event_id" = ?' &&
625
+ lit.params.length === 3 && lit.params[2] === "e-9");
626
+
627
+ // cast cell binds value + casts the placeholder (Postgres ?::jsonb).
628
+ var castSel = sql.insertSelectWhere("docs", { dialect: "postgres" })
629
+ .values({ id: 1, meta: sql.cast('{"a":1}', "jsonb") })
630
+ .whereOp("id", "=", 1).toSql();
631
+ check("insertSelectWhere renders a cast SELECT cell (?::jsonb) binding the inner value",
632
+ /SELECT \?, \?::jsonb WHERE "id" = \?/.test(castSel.sql) &&
633
+ castSel.params.length === 3 && castSel.params[1] === '{"a":1}');
634
+
635
+ // MySQL: standard form, backtick quoting; RETURNING refused (run an explicit read).
636
+ var my = sql.insertSelectWhere("ledger", { dialect: "mysql" })
637
+ .values({ k: "a", n: 1 }).whereOp("k", "=", "a").toSql();
638
+ check("insertSelectWhere mysql backtick quoting",
639
+ my.sql === "INSERT INTO ledger (`k`, `n`) SELECT ?, ? WHERE `k` = ?");
640
+ rejects("insertSelectWhere RETURNING refused on mysql", function () {
641
+ return sql.insertSelectWhere("ledger", { dialect: "mysql" })
642
+ .values({ k: "a" }).whereOp("k", "=", "a").returning(["k"]).toSql();
643
+ }, "sql-builder/returning-unsupported");
644
+
645
+ // Safety default: an un-guarded conditional insert THROWS (like update/delete);
646
+ // allowNoWhere() opts in deliberately.
647
+ rejects("insertSelectWhere without where throws (no-where default)", function () {
648
+ return sql.insertSelectWhere("ledger").values({ k: "a", n: 1 }).toSql();
649
+ }, "sql-builder/no-where");
650
+ var noWhere = sql.insertSelectWhere("ledger").values({ k: "a", n: 1 }).allowNoWhere().toSql();
651
+ check("insertSelectWhere allowNoWhere() emits a guard-less SELECT",
652
+ noWhere.sql === 'INSERT INTO ledger ("k", "n") SELECT ?, ?' && noWhere.params.length === 2);
653
+
654
+ // No values() -> empty-values; values() missing a declared column -> missing-column;
655
+ // an extra key not in the declared column set -> extra-column (no silent data drop).
656
+ rejects("insertSelectWhere without values throws", function () {
657
+ return sql.insertSelectWhere("ledger").columns(["k"]).whereOp("k", "=", "a").toSql();
658
+ }, "sql-builder/empty-values");
659
+ rejects("insertSelectWhere positional value-count mismatch", function () {
660
+ return sql.insertSelectWhere("ledger").columns(["k", "n"]).values(["only-one"]);
661
+ }, "sql-builder/value-count");
662
+ rejects("insertSelectWhere row missing a declared column", function () {
663
+ return sql.insertSelectWhere("ledger").columns(["k", "n"]).values({ k: "a" });
664
+ }, "sql-builder/missing-column");
665
+ // extra-column only fires against an EXPLICIT column set (an inferred set
666
+ // can't have an extra key) — declare ["k","n"] first, then the ghost key.
667
+ rejects("insertSelectWhere row with an extra column", function () {
668
+ return sql.insertSelectWhere("ledger").columns(["k", "n"]).values({ k: "a", n: 1, ghost: 2 })
669
+ .whereOp("k", "=", "a").toSql();
670
+ }, "sql-builder/extra-column");
671
+
672
+ // The output gate still fires: a NUL byte in a bound cell value is refused
673
+ // by _assertEmittable, same as every other verb.
674
+ rejects("insertSelectWhere NUL in a cell value refused by the output gate", function () {
675
+ return sql.insertSelectWhere("ledger").values({ k: "x" + NUL + "y", n: 1 })
676
+ .whereOp("n", "=", 1).toSql();
677
+ }, "sql-builder/null-byte-param");
678
+
679
+ // Sub-builder dialect-mismatch is refused (a mysql guard sub spliced into a
680
+ // default-sqlite parent has baked the wrong quote char).
681
+ rejects("insertSelectWhere guard sub dialect-mismatch refused", function () {
682
+ return sql.insertSelectWhere("ledger")
683
+ .values({ k: "a", n: 1 })
684
+ .whereExists(sql.select("other", { dialect: "mysql" }).columns(["id"])).toSql();
685
+ }, "sql-builder/dialect-mismatch");
686
+
687
+ // toExternalSql translates ? -> $N on postgres at the boundary (direct-driver path).
688
+ var ext = sql.insertSelectWhere("ledger", { dialect: "postgres" })
689
+ .values({ k: "a", n: 1 }).whereOp("k", "=", "a").toExternalSql("postgres");
690
+ check("insertSelectWhere toExternalSql postgres $N",
691
+ ext.sql.indexOf("$1") !== -1 && ext.sql.indexOf("$2") !== -1 &&
692
+ ext.sql.indexOf("$3") !== -1 && ext.sql.indexOf("?") === -1);
593
693
  }
594
694
 
595
695
  module.exports = { run: run };
@@ -50,6 +50,42 @@ function testSplitTopLevelSemi() {
50
50
  threw instanceof TypeError);
51
51
  }
52
52
 
53
+ function testParseTagList() {
54
+ var ptl = b.structuredFields.parseTagList;
55
+ // Default: `;` sep, `=` kv, lower-cased keys, raw values.
56
+ check("parseTagList: simple ;/= list, keys lower-cased",
57
+ JSON.stringify(ptl("v=DKIM1; K=rsa; p=ABC")) ===
58
+ JSON.stringify([["v", "DKIM1"], ["k", "rsa"], ["p", "ABC"]]));
59
+ // Empty entries + entries without a kv separator are skipped.
60
+ check("parseTagList: empty + no-kv entries skipped",
61
+ JSON.stringify(ptl("a=1; ; novalue ;b=2")) ===
62
+ JSON.stringify([["a", "1"], ["b", "2"]]));
63
+ // Repeated keys are PRESERVED as pairs (no last-wins collapse) —
64
+ // MTA-STS relies on this for repeated mx: lines.
65
+ check("parseTagList: repeated keys preserved as pairs",
66
+ JSON.stringify(ptl("mx=a; mx=b; mx=c")) ===
67
+ JSON.stringify([["mx", "a"], ["mx", "b"], ["mx", "c"]]));
68
+ // unfold collapses CRLF+WSP folds to a space before splitting (DKIM FWS).
69
+ check("parseTagList: unfold collapses folded value",
70
+ JSON.stringify(ptl("p=ABC\r\n DEF", { unfold: true, stripValueWs: true })) ===
71
+ JSON.stringify([["p", "ABCDEF"]]));
72
+ // stripValueWs removes all whitespace inside a value (DKIM/ARC FWS).
73
+ check("parseTagList: stripValueWs removes internal whitespace",
74
+ JSON.stringify(ptl("p=A B\tC", { stripValueWs: true })) ===
75
+ JSON.stringify([["p", "ABC"]]));
76
+ // Regex sep + colon kv (MTA-STS shape), value whitespace kept.
77
+ check("parseTagList: regex sep + colon kv",
78
+ JSON.stringify(ptl("version: STSv1\r\nmode: enforce\nmx: a", { sep: /\r?\n/, kvSep: ":" })) ===
79
+ JSON.stringify([["version", "STSv1"], ["mode", "enforce"], ["mx", "a"]]));
80
+ // lowerKey:false keeps original key case; first `=` wins (value may hold `=`).
81
+ check("parseTagList: lowerKey:false preserves case, first kvSep wins",
82
+ JSON.stringify(ptl("Key=a=b=c", { lowerKey: false })) ===
83
+ JSON.stringify([["Key", "a=b=c"]]));
84
+ // Non-string input is coerced (String()) — empty/garbage yields [].
85
+ check("parseTagList: empty string → []",
86
+ JSON.stringify(ptl("")) === JSON.stringify([]));
87
+ }
88
+
53
89
  function testRefuseControlBytes() {
54
90
  var SfError = b.structuredFields.refuseControlBytes;
55
91
  // Generate a generic framework-error-shaped class for the test.
@@ -178,12 +214,56 @@ function testUnquoteSfString() {
178
214
  b.structuredFields.unquoteSfString(null) === null);
179
215
  }
180
216
 
217
+ function testForEachKeyValue() {
218
+ // Bare entries (no kvSep → null value) are skipped; surviving values trimmed;
219
+ // index reflects the kvps position (so the skipped bare entry leaves a gap).
220
+ var kvps = b.structuredFields.parseKeyValuePieces("a = 1 ; b ; c=3".split(";"));
221
+ var seen = [];
222
+ b.structuredFields.forEachKeyValue(kvps, function (key, value, i) {
223
+ seen.push([key, value, i]);
224
+ });
225
+ check("forEachKeyValue: skips bare (null-value) entries", seen.length === 2);
226
+ check("forEachKeyValue: trims surviving values + passes key",
227
+ seen[0][0] === "a" && seen[0][1] === "1" &&
228
+ seen[1][0] === "c" && seen[1][1] === "3");
229
+ check("forEachKeyValue: index reflects kvps position (bare skipped)",
230
+ seen[0][2] === 0 && seen[1][2] === 2);
231
+
232
+ // A handler `return` skips the current entry — `continue` semantics.
233
+ var kept = [];
234
+ b.structuredFields.forEachKeyValue(
235
+ b.structuredFields.parseKeyValuePieces("x=1; y=2; z=3".split(";")),
236
+ function (key) { if (key === "y") return; kept.push(key); });
237
+ check("forEachKeyValue: handler return skips like continue", kept.join(",") === "x,z");
238
+
239
+ // Non-function handler throws at the wiring (config-time tier).
240
+ var threw = null;
241
+ try { b.structuredFields.forEachKeyValue([], "nope"); } catch (e) { threw = e; }
242
+ check("forEachKeyValue: non-function handler throws TypeError", threw instanceof TypeError);
243
+ }
244
+
245
+ function testUnfoldHeaderContinuations() {
246
+ // RFC 5322 header unfolding: a CRLF (or bare LF) followed by WSP is
247
+ // folding whitespace — unfold collapses each run to a single space so a
248
+ // wrapped header value (DKIM/DMARC/Authentication-Results, etc.) parses
249
+ // as one logical line.
250
+ check("unfoldHeaderContinuations collapses CRLF+WSP to a single space",
251
+ b.structuredFields.unfoldHeaderContinuations("v=DKIM1;\r\n k=rsa") === "v=DKIM1; k=rsa");
252
+ check("unfoldHeaderContinuations handles bare LF + tab",
253
+ b.structuredFields.unfoldHeaderContinuations("a=1;\n\tb=2") === "a=1; b=2");
254
+ check("unfoldHeaderContinuations leaves an unfolded value unchanged",
255
+ b.structuredFields.unfoldHeaderContinuations("a=1; b=2") === "a=1; b=2");
256
+ }
257
+
181
258
  async function run() {
182
259
  testSplitTopLevelComma();
183
260
  testSplitTopLevelSemi();
261
+ testParseTagList();
262
+ testForEachKeyValue();
184
263
  testRefuseControlBytes();
185
264
  testContainsControlBytes();
186
265
  testUnquoteSfString();
266
+ testUnfoldHeaderContinuations();
187
267
  }
188
268
 
189
269
  module.exports = { run: run };
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ /**
3
+ * validateOpts.shape — declarative opts validator that collapses the
4
+ * per-factory `requireObject + requireNonEmptyString + optionalPositiveFinite
5
+ * + ...` preamble into one schema-driven call.
6
+ *
7
+ * Covers: top-level object requirement; each rule token dispatching to the
8
+ * right underlying check (required/optional string, string-array, boolean,
9
+ * positive-int/finite, non-negative, function, plain-object); the
10
+ * dependency-with-methods rule (required + optional); unknown-rule-throws; that
11
+ * a valid opts object passes and is returned.
12
+ *
13
+ * Run standalone: node test/layer-0-primitives/validate-opts-shape.test.js
14
+ */
15
+ var helpers = require("../helpers");
16
+ var check = helpers.check;
17
+ var validateOpts = require("../../lib/validate-opts");
18
+ var { WebhookDispatcherError, defineClass } = require("../../lib/framework-error");
19
+
20
+ var E = WebhookDispatcherError;
21
+ var CODE = "test/bad-opt";
22
+
23
+ function _throws(fn, re) {
24
+ try { fn(); return false; }
25
+ catch (e) { return re ? re.test(e.message || "") : true; }
26
+ }
27
+
28
+ function run() {
29
+ // top-level: opts must be an object.
30
+ check("non-object opts throws", _throws(function () {
31
+ validateOpts.shape(null, { a: "required-string" }, "t", E, CODE);
32
+ }, /must be an object/));
33
+
34
+ // required-string
35
+ check("required-string missing throws", _throws(function () {
36
+ validateOpts.shape({}, { a: "required-string" }, "t", E, CODE);
37
+ }, /non-empty string/));
38
+ check("required-string present passes",
39
+ validateOpts.shape({ a: "x" }, { a: "required-string" }, "t", E, CODE).a === "x");
40
+
41
+ // optional-* absent is fine
42
+ check("optional-string absent ok", (function () {
43
+ validateOpts.shape({}, { a: "optional-string" }, "t", E, CODE); return true;
44
+ })());
45
+ check("optional-positive-finite bad throws", _throws(function () {
46
+ validateOpts.shape({ n: -1 }, { n: "optional-positive-finite" }, "t", E, CODE);
47
+ }));
48
+ check("optional-positive-int bad throws", _throws(function () {
49
+ validateOpts.shape({ n: 1.5 }, { n: "optional-positive-int" }, "t", E, CODE);
50
+ }));
51
+ check("optional-boolean bad throws", _throws(function () {
52
+ validateOpts.shape({ b: "yes" }, { b: "optional-boolean" }, "t", E, CODE);
53
+ }));
54
+ check("optional-function bad throws", _throws(function () {
55
+ validateOpts.shape({ f: 42 }, { f: "optional-function" }, "t", E, CODE);
56
+ }));
57
+ check("optional-non-negative bad throws", _throws(function () {
58
+ validateOpts.shape({ n: -5 }, { n: "optional-non-negative" }, "t", E, CODE);
59
+ }));
60
+
61
+ // optional-date: present-but-invalid throws; absent ok; valid passes.
62
+ check("optional-date non-Date throws", _throws(function () {
63
+ validateOpts.shape({ at: "2020-01-01" }, { at: "optional-date" }, "t", E, CODE);
64
+ }, /valid Date/));
65
+ check("optional-date Invalid Date throws", _throws(function () {
66
+ validateOpts.shape({ at: new Date("nope") }, { at: "optional-date" }, "t", E, CODE);
67
+ }, /valid Date/));
68
+ check("optional-date absent ok", (function () {
69
+ validateOpts.shape({}, { at: "optional-date" }, "t", E, CODE); return true;
70
+ })());
71
+ check("optional-date valid Date passes",
72
+ validateOpts.shape({ at: new Date(0) }, { at: "optional-date" }, "t", E, CODE).at instanceof Date);
73
+ // direct optionalDate: returns the value when absent / valid; throws the
74
+ // `<label> must be a valid Date` message (byte-identical to the old hand-rolls).
75
+ check("optionalDate(undefined) returns undefined",
76
+ validateOpts.optionalDate(undefined, "x.at", E, CODE) === undefined);
77
+ check("optionalDate(validDate) returns it", (function () {
78
+ var d = new Date(0); return validateOpts.optionalDate(d, "x.at", E, CODE) === d;
79
+ })());
80
+ check("optionalDate(InvalidDate) throws '<label> must be a valid Date'", _throws(function () {
81
+ validateOpts.optionalDate(new Date("nope"), "x.verify: opts.at", E, CODE);
82
+ }, /^x\.verify: opts\.at must be a valid Date$/));
83
+
84
+ // string-array: per-element validation
85
+ check("optional-string-array bad element throws", _throws(function () {
86
+ validateOpts.shape({ a: ["ok", 3] }, { a: "optional-string-array" }, "t", E, CODE);
87
+ }));
88
+ check("optional-string-array valid passes", (function () {
89
+ validateOpts.shape({ a: ["x", "y"] }, { a: "optional-string-array" }, "t", E, CODE); return true;
90
+ })());
91
+
92
+ // required-object field
93
+ check("required-object missing throws", _throws(function () {
94
+ validateOpts.shape({}, { cfg: "required-object" }, "t", E, CODE);
95
+ }));
96
+
97
+ // dependency with methods
98
+ check("methods dep non-object throws", _throws(function () {
99
+ validateOpts.shape({ db: 5 }, { db: { methods: ["query"] } }, "t", E, CODE);
100
+ }));
101
+ check("methods dep missing method throws", _throws(function () {
102
+ validateOpts.shape({ db: {} }, { db: { methods: ["query", "transaction"] } }, "t", E, CODE);
103
+ }, /query/));
104
+ check("methods dep complete passes", (function () {
105
+ validateOpts.shape({ db: { query: function () {}, transaction: function () {} } },
106
+ { db: { methods: ["query", "transaction"] } }, "t", E, CODE); return true;
107
+ })());
108
+ check("optional methods dep absent ok", (function () {
109
+ validateOpts.shape({}, { db: { methods: ["query"], optional: true } }, "t", E, CODE); return true;
110
+ })());
111
+
112
+ // requireMethods permanent flag — a config-time dependency check whose
113
+ // failure is non-retryable forwards `permanent` to the framework error's
114
+ // third constructor argument. Uses a GENERIC error class (arg3 = permanent)
115
+ // so the flag is observable (alwaysPermanent classes set it unconditionally).
116
+ var PermTestError = defineClass("ValidateOptsPermTestError");
117
+ check("requireMethods without permanent → permanent falsy", (function () {
118
+ try { validateOpts.requireMethods({}, ["query"], "x.db", PermTestError, "C"); return false; }
119
+ catch (e) { return e.permanent === false; }
120
+ })());
121
+ check("requireMethods permanent=true → error.permanent true", (function () {
122
+ try { validateOpts.requireMethods({}, ["query"], "x.db", PermTestError, "C", true); return false; }
123
+ catch (e) { return e.permanent === true; }
124
+ })());
125
+ check("requireMethods permanent=true on missing method → permanent true", (function () {
126
+ try { validateOpts.requireMethods({ query: function () {} }, ["query", "tx"], "x.db", PermTestError, "C", true); return false; }
127
+ catch (e) { return e.permanent === true && e.code === "C"; }
128
+ })());
129
+ check("shape methods rule permanent → error.permanent true", (function () {
130
+ try { validateOpts.shape({ db: 5 }, { db: { methods: ["query"], permanent: true } }, "t", PermTestError, "C"); return false; }
131
+ catch (e) { return e.permanent === true; }
132
+ })());
133
+
134
+ // per-field code override preserves a distinct code per field
135
+ check("per-field code override preserved", (function () {
136
+ try {
137
+ validateOpts.shape({ a: "ok" }, {
138
+ a: { rule: "required-string", code: "BAD_A" },
139
+ b: { rule: "required-string", code: "BAD_B" },
140
+ }, "t", E, CODE);
141
+ return false;
142
+ } catch (e) { return e.code === "BAD_B"; } // b is missing → its own code
143
+ })());
144
+ check("per-field label override preserved", (function () {
145
+ try {
146
+ validateOpts.shape({}, { a: { rule: "required-string", label: "custom.path" } }, "t", E, CODE);
147
+ return false;
148
+ } catch (e) { return /custom\.path/.test(e.message); }
149
+ })());
150
+
151
+ // arbitrary validator function — the universal hatch
152
+ check("function rule runs + can throw", _throws(function () {
153
+ validateOpts.shape({ a: 5 }, {
154
+ a: function (v, l, e, c) { if (v > 3) throw e.factory(c, l + " too big"); },
155
+ }, "t", E, CODE);
156
+ }, /too big/));
157
+ check("function rule receives label/errorClass/code", (function () {
158
+ var seen = null;
159
+ validateOpts.shape({ a: 1 }, {
160
+ a: function (v, l, e, c) { seen = { l: l, hasFactory: typeof e.factory === "function", c: c }; },
161
+ }, "t", E, CODE);
162
+ return seen && seen.l === "t: a" && seen.hasFactory && seen.c === CODE;
163
+ })());
164
+
165
+ // nested sub-object shape
166
+ check("nested shape validates sub-object field", _throws(function () {
167
+ validateOpts.shape({ srv: { issuer: "x" } }, {
168
+ srv: { shape: { issuer: "required-string", jwksUri: "required-string" } },
169
+ }, "t", E, CODE); // jwksUri missing
170
+ }, /jwksUri|non-empty string/));
171
+ check("nested shape passes when complete", (function () {
172
+ validateOpts.shape({ srv: { issuer: "x", jwksUri: "y" } }, {
173
+ srv: { shape: { issuer: "required-string", jwksUri: "required-string" } },
174
+ }, "t", E, CODE);
175
+ return true;
176
+ })());
177
+ check("optional nested shape absent ok", (function () {
178
+ validateOpts.shape({}, { srv: { shape: { issuer: "required-string" }, optional: true } }, "t", E, CODE);
179
+ return true;
180
+ })());
181
+
182
+ // mandatory exhaustive: an undeclared opt is always rejected
183
+ check("undeclared opt rejected (mandatory exhaustive)", _throws(function () {
184
+ validateOpts.shape({ known: "x", typo: 1 }, { known: "required-string" }, "t", E, CODE);
185
+ }, /unknown opt "typo"/));
186
+ check("options.allow permits a pass-through key", (function () {
187
+ validateOpts.shape({ known: "x", fwd: 1 }, { known: "required-string" },
188
+ "t", E, CODE, { allow: ["fwd"] });
189
+ return true;
190
+ })());
191
+ check("exhaustive has no opt-out (only allow)", _throws(function () {
192
+ // even passing a (now-ignored) exhaustive:false cannot disable the contract
193
+ validateOpts.shape({ known: "x", extra: 1 }, { known: "required-string" },
194
+ "t", E, CODE, { exhaustive: false });
195
+ }, /unknown opt "extra"/));
196
+
197
+ // numeric-bounds int tokens (finite — reject Infinity, unlike optional-positive-int)
198
+ check("optional-positive-finite-int rejects Infinity", _throws(function () {
199
+ validateOpts.shape({ n: Infinity }, { n: "optional-positive-finite-int" }, "t", E, CODE);
200
+ }));
201
+ check("optional-positive-finite-int rejects 0", _throws(function () {
202
+ validateOpts.shape({ n: 0 }, { n: "optional-positive-finite-int" }, "t", E, CODE);
203
+ }));
204
+ check("optional-positive-finite-int accepts a positive int", (function () {
205
+ validateOpts.shape({ n: 1024 }, { n: "optional-positive-finite-int" }, "t", E, CODE);
206
+ return true;
207
+ })());
208
+ check("optional-non-negative-finite-int accepts 0", (function () {
209
+ validateOpts.shape({ n: 0 }, { n: "optional-non-negative-finite-int" }, "t", E, CODE);
210
+ return true;
211
+ })());
212
+
213
+ // unknown rule is the author's bug — throws loudly
214
+ check("unknown rule token throws", _throws(function () {
215
+ validateOpts.shape({}, { a: "bogus-rule" }, "t", E, CODE);
216
+ }, /unknown shape rule/));
217
+
218
+ // a full mixed schema passes and returns opts
219
+ var opts = { externalDb: { query: function () {}, transaction: function () {} },
220
+ name: "svc", maxAttempts: 8, dryRun: false, hook: function () {} };
221
+ check("mixed valid schema returns opts", validateOpts.shape(opts, {
222
+ externalDb: { methods: ["query", "transaction"] },
223
+ name: "required-string",
224
+ maxAttempts: "optional-positive-finite",
225
+ dryRun: "optional-boolean",
226
+ hook: "optional-function",
227
+ }, "svc", E, CODE) === opts);
228
+ }
229
+
230
+ module.exports = { run: run };
231
+
232
+ if (require.main === module) {
233
+ try { run(); console.log("[validate-opts-shape] OK — " + helpers.getChecks() + " checks passed"); }
234
+ catch (e) { console.error("FAIL:", e && e.stack || e); process.exit(1); }
235
+ }