@blamejs/blamejs-shop 0.4.56 → 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 (397) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +426 -366
  4. package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
  5. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  6. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
  7. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
  8. package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
  9. package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
  10. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
  11. package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
  12. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
  13. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  14. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  15. package/lib/vendor/blamejs/api-snapshot.json +1381 -4
  16. package/lib/vendor/blamejs/eslint.config.mjs +1 -0
  17. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
  18. package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
  19. package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
  20. package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
  21. package/lib/vendor/blamejs/index.js +2 -0
  22. package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
  23. package/lib/vendor/blamejs/lib/acme.js +6 -5
  24. package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
  25. package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
  26. package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
  27. package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
  28. package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
  29. package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
  30. package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
  31. package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
  32. package/lib/vendor/blamejs/lib/ai-input.js +2 -2
  33. package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
  34. package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
  35. package/lib/vendor/blamejs/lib/api-key.js +37 -28
  36. package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
  37. package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
  38. package/lib/vendor/blamejs/lib/archive-read.js +5 -17
  39. package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
  40. package/lib/vendor/blamejs/lib/archive.js +2 -10
  41. package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
  42. package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
  43. package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
  44. package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
  45. package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
  46. package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
  47. package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
  48. package/lib/vendor/blamejs/lib/audit.js +84 -0
  49. package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
  50. package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
  51. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
  52. package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
  53. package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
  54. package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
  55. package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
  56. package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
  57. package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
  58. package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
  59. package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
  60. package/lib/vendor/blamejs/lib/auth/password.js +7 -1
  61. package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
  62. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
  63. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
  64. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
  65. package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
  66. package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
  67. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
  68. package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
  69. package/lib/vendor/blamejs/lib/backup/index.js +14 -47
  70. package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
  71. package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
  72. package/lib/vendor/blamejs/lib/cache.js +7 -18
  73. package/lib/vendor/blamejs/lib/cbor.js +2 -1
  74. package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
  75. package/lib/vendor/blamejs/lib/cert.js +3 -10
  76. package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
  77. package/lib/vendor/blamejs/lib/cli.js +5 -1
  78. package/lib/vendor/blamejs/lib/client-hints.js +7 -9
  79. package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
  80. package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
  81. package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
  82. package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
  83. package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
  84. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
  85. package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
  86. package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
  87. package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
  88. package/lib/vendor/blamejs/lib/compliance.js +2 -9
  89. package/lib/vendor/blamejs/lib/config-drift.js +2 -12
  90. package/lib/vendor/blamejs/lib/content-digest.js +10 -8
  91. package/lib/vendor/blamejs/lib/cookies.js +5 -11
  92. package/lib/vendor/blamejs/lib/cose.js +19 -11
  93. package/lib/vendor/blamejs/lib/cra-report.js +1 -11
  94. package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
  95. package/lib/vendor/blamejs/lib/crypto.js +120 -3
  96. package/lib/vendor/blamejs/lib/csp.js +235 -3
  97. package/lib/vendor/blamejs/lib/daemon.js +42 -41
  98. package/lib/vendor/blamejs/lib/data-act.js +19 -9
  99. package/lib/vendor/blamejs/lib/db-query.js +6 -40
  100. package/lib/vendor/blamejs/lib/db.js +34 -12
  101. package/lib/vendor/blamejs/lib/dbsc.js +5 -6
  102. package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
  103. package/lib/vendor/blamejs/lib/deprecate.js +4 -5
  104. package/lib/vendor/blamejs/lib/did.js +6 -2
  105. package/lib/vendor/blamejs/lib/dsr.js +8 -12
  106. package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
  107. package/lib/vendor/blamejs/lib/external-db.js +14 -26
  108. package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
  109. package/lib/vendor/blamejs/lib/fdx.js +22 -18
  110. package/lib/vendor/blamejs/lib/file-upload.js +80 -66
  111. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
  112. package/lib/vendor/blamejs/lib/framework-error.js +12 -0
  113. package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
  114. package/lib/vendor/blamejs/lib/fsm.js +7 -12
  115. package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
  116. package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
  117. package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
  118. package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
  119. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  120. package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
  121. package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
  122. package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
  123. package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
  124. package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
  125. package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
  126. package/lib/vendor/blamejs/lib/guard-email.js +46 -53
  127. package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
  128. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
  129. package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
  130. package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
  131. package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
  132. package/lib/vendor/blamejs/lib/guard-html.js +65 -117
  133. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
  134. package/lib/vendor/blamejs/lib/guard-image.js +280 -77
  135. package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
  136. package/lib/vendor/blamejs/lib/guard-json.js +87 -103
  137. package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
  138. package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
  139. package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
  140. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
  141. package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
  142. package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
  143. package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
  144. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
  145. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
  146. package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
  147. package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
  148. package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
  149. package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
  150. package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
  151. package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
  152. package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
  153. package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
  154. package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
  155. package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
  156. package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
  157. package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
  158. package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
  159. package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
  160. package/lib/vendor/blamejs/lib/guard-template.js +23 -80
  161. package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
  162. package/lib/vendor/blamejs/lib/guard-text.js +592 -0
  163. package/lib/vendor/blamejs/lib/guard-time.js +27 -95
  164. package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
  165. package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
  166. package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
  167. package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
  168. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
  169. package/lib/vendor/blamejs/lib/http-client.js +8 -21
  170. package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
  171. package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
  172. package/lib/vendor/blamejs/lib/i18n.js +83 -26
  173. package/lib/vendor/blamejs/lib/inbox.js +8 -8
  174. package/lib/vendor/blamejs/lib/incident-report.js +3 -21
  175. package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
  176. package/lib/vendor/blamejs/lib/jobs.js +3 -2
  177. package/lib/vendor/blamejs/lib/keychain.js +6 -18
  178. package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
  179. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
  180. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
  181. package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
  182. package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
  183. package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
  184. package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
  185. package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
  186. package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
  187. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
  188. package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
  189. package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
  190. package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
  191. package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
  192. package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
  193. package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
  194. package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
  195. package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
  196. package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
  197. package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
  198. package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
  199. package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
  200. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
  201. package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
  202. package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
  203. package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
  204. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
  205. package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
  206. package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
  207. package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
  208. package/lib/vendor/blamejs/lib/mail-store.js +3 -2
  209. package/lib/vendor/blamejs/lib/mail.js +6 -11
  210. package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
  211. package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
  212. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
  213. package/lib/vendor/blamejs/lib/mcp.js +1 -1
  214. package/lib/vendor/blamejs/lib/mdoc.js +11 -12
  215. package/lib/vendor/blamejs/lib/metrics.js +32 -30
  216. package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
  217. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
  218. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
  219. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
  220. package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
  221. package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
  222. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
  223. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
  224. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
  225. package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
  226. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
  227. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
  228. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
  229. package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
  230. package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
  231. package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
  232. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
  233. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
  234. package/lib/vendor/blamejs/lib/migrations.js +4 -13
  235. package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
  236. package/lib/vendor/blamejs/lib/module-loader.js +44 -0
  237. package/lib/vendor/blamejs/lib/money.js +105 -0
  238. package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
  239. package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
  240. package/lib/vendor/blamejs/lib/network-dane.js +8 -6
  241. package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
  242. package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
  243. package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
  244. package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
  245. package/lib/vendor/blamejs/lib/network-tls.js +40 -42
  246. package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
  247. package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
  248. package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
  249. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
  250. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
  251. package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
  252. package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
  253. package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
  254. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
  255. package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
  256. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
  257. package/lib/vendor/blamejs/lib/observability.js +95 -0
  258. package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
  259. package/lib/vendor/blamejs/lib/otel-export.js +7 -10
  260. package/lib/vendor/blamejs/lib/outbox.js +43 -37
  261. package/lib/vendor/blamejs/lib/pagination.js +11 -15
  262. package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
  263. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
  264. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
  265. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
  266. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
  267. package/lib/vendor/blamejs/lib/pick.js +63 -5
  268. package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
  269. package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
  270. package/lib/vendor/blamejs/lib/problem-details.js +2 -5
  271. package/lib/vendor/blamejs/lib/pubsub.js +4 -8
  272. package/lib/vendor/blamejs/lib/redact.js +2 -1
  273. package/lib/vendor/blamejs/lib/render.js +4 -2
  274. package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
  275. package/lib/vendor/blamejs/lib/restore.js +5 -22
  276. package/lib/vendor/blamejs/lib/retention.js +3 -5
  277. package/lib/vendor/blamejs/lib/safe-async.js +457 -0
  278. package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
  279. package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
  280. package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
  281. package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
  282. package/lib/vendor/blamejs/lib/safe-json.js +7 -8
  283. package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
  284. package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
  285. package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
  286. package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
  287. package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
  288. package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
  289. package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
  290. package/lib/vendor/blamejs/lib/sandbox.js +3 -2
  291. package/lib/vendor/blamejs/lib/scheduler.js +5 -12
  292. package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
  293. package/lib/vendor/blamejs/lib/seeders.js +4 -11
  294. package/lib/vendor/blamejs/lib/self-update.js +92 -69
  295. package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
  296. package/lib/vendor/blamejs/lib/session.js +194 -6
  297. package/lib/vendor/blamejs/lib/sql.js +225 -78
  298. package/lib/vendor/blamejs/lib/sse.js +6 -10
  299. package/lib/vendor/blamejs/lib/static.js +136 -98
  300. package/lib/vendor/blamejs/lib/storage.js +4 -2
  301. package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
  302. package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
  303. package/lib/vendor/blamejs/lib/tsa.js +11 -15
  304. package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
  305. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
  306. package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
  307. package/lib/vendor/blamejs/lib/vc.js +2 -7
  308. package/lib/vendor/blamejs/lib/vex.js +35 -13
  309. package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
  310. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
  311. package/lib/vendor/blamejs/lib/webhook.js +43 -18
  312. package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
  313. package/lib/vendor/blamejs/lib/websocket.js +7 -3
  314. package/lib/vendor/blamejs/lib/worm.js +2 -3
  315. package/lib/vendor/blamejs/lib/ws-client.js +8 -10
  316. package/lib/vendor/blamejs/package.json +1 -1
  317. package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
  318. package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
  319. package/lib/vendor/blamejs/test/00-primitives.js +136 -7
  320. package/lib/vendor/blamejs/test/10-state.js +9 -3
  321. package/lib/vendor/blamejs/test/30-chain.js +40 -0
  322. package/lib/vendor/blamejs/test/helpers/check.js +18 -0
  323. package/lib/vendor/blamejs/test/helpers/db.js +4 -0
  324. package/lib/vendor/blamejs/test/helpers/index.js +1 -0
  325. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
  326. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
  327. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
  328. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
  329. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
  330. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
  334. package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
  335. package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
  336. package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
  337. package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
  341. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
  344. package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
  346. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
  347. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
  348. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
  376. package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
  387. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
  388. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
  389. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
  391. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
  392. package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
  395. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
  396. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
  397. package/package.json +1 -1
@@ -48,6 +48,7 @@
48
48
  */
49
49
  var audit = require("./audit");
50
50
  var canonicalJson = require("./canonical-json");
51
+ var validateOpts = require("./validate-opts");
51
52
  var cluster = require("./cluster");
52
53
  var clusterStorage = require("./cluster-storage");
53
54
  var C = require("./constants");
@@ -149,6 +150,38 @@ function _sessionSqlTable() { return frameworkSchema.tableName(SESSION_TABLE); }
149
150
  // dispatch; this controls only the builder-side quoting + idiom selection.
150
151
  function _sessionSqlOpts() { return { dialect: clusterStorage.dialect() }; }
151
152
 
153
+ // Per-subject valid-from boundary table. A monotonic epoch (ms) the issuer
154
+ // bumps to invalidate every STATELESS self-validating token (sealed cookie
155
+ // with no DB row, JWT) minted before the bump: log-out-everywhere, a
156
+ // right-to-erasure cutoff, a forced re-auth after a credential change. Token
157
+ // readers compare the token's iat against this boundary via check(). Same
158
+ // dual-storage shape as _blamejs_sessions — registered in both db.js's
159
+ // FRAMEWORK_SCHEMA (single-node SQLite) and framework-schema.js (cluster
160
+ // external-db); clusterStorage.execute routes by cluster mode. The subject id
161
+ // is hashed before it becomes the PRIMARY KEY, so the plaintext id never lands
162
+ // in the table (the same sidHash / userIdHash discipline the sessions table
163
+ // follows).
164
+ var VALID_FROM_TABLE = "_blamejs_session_valid_from"; // allow:hand-rolled-sql — canonical logical table-name + reserved schema name
165
+ var VALID_FROM_SUBJECT_NAMESPACE = "bj-session-valid-from-subject:";
166
+ function _validFromSqlTable() { return frameworkSchema.tableName(VALID_FROM_TABLE); }
167
+ function _hashSubjectId(subjectId) { return sha3Hash(VALID_FROM_SUBJECT_NAMESPACE + subjectId); }
168
+
169
+ // Dialect-aware conflict-row references for the monotonic-max upsert in
170
+ // bump(). Mirrors rate-limit.js's pattern: the proposed row is EXCLUDED
171
+ // (Postgres/SQLite) / VALUES() (MySQL); the existing row is a self-reference.
172
+ function _validFromConflictRefs(dialect, table) {
173
+ if (dialect === "mysql") {
174
+ return {
175
+ proposed: function (col) { return "VALUES(`" + col + "`)"; },
176
+ existing: function (col) { return "`" + table + "`.`" + col + "`"; },
177
+ };
178
+ }
179
+ return {
180
+ proposed: function (col) { return "EXCLUDED.\"" + col + "\""; },
181
+ existing: function (col) { return "\"" + table + "\".\"" + col + "\""; },
182
+ };
183
+ }
184
+
152
185
  // Column order used for INSERT — kept as a constant so the placeholders
153
186
  // list and the values list stay in sync. Must match the session table's
154
187
  // schema in db.js (single-node) and framework-schema.js (cluster mode).
@@ -825,6 +858,10 @@ async function destroyAllForUser(userId) {
825
858
  .whereIn("userIdHash", userHashes)
826
859
  .toSql();
827
860
  var result = await _currentStore().execute(built.sql, built.params);
861
+ // Also raise the stateless valid-from boundary so a "logout everywhere"
862
+ // revokes the operator's stateless tokens (sealed cookies / JWTs checked via
863
+ // b.session.check) too, not only the store-backed rows just deleted.
864
+ await bump(userId);
828
865
  return result.rowCount || 0;
829
866
  }
830
867
 
@@ -1272,12 +1309,8 @@ function useStore(store) {
1272
1309
  _store = null;
1273
1310
  return;
1274
1311
  }
1275
- if (typeof store !== "object" ||
1276
- typeof store.execute !== "function" ||
1277
- typeof store.executeOne !== "function") {
1278
- throw _err("INVALID_ARG",
1279
- "session.useStore: store must expose execute(sql,params) and executeOne(sql,params)", true);
1280
- }
1312
+ validateOpts.requireMethods(store, ["execute", "executeOne"],
1313
+ "session.useStore: store", SessionError, "INVALID_ARG", true);
1281
1314
  _store = store;
1282
1315
  }
1283
1316
 
@@ -1304,6 +1337,158 @@ function isAnonymous(userId) {
1304
1337
  return _isAnonymousUserId(userId);
1305
1338
  }
1306
1339
 
1340
+ /**
1341
+ * @primitive b.session.bump
1342
+ * @signature b.session.bump(subjectId, opts?)
1343
+ * @since 0.15.13
1344
+ * @status stable
1345
+ * @related b.session.check, b.session.validFrom, b.session.destroyAllForUser
1346
+ *
1347
+ * Revoke every STATELESS self-validating token (sealed cookie carrying no DB
1348
+ * row, JWT) for a subject by raising a durable per-subject valid-from boundary
1349
+ * to now. Any token whose issued-at (`iat`) predates the boundary fails
1350
+ * `b.session.check`. Unlike `destroyAllForUser` — which deletes server-side
1351
+ * session rows — this revokes tokens the framework never stored a row for:
1352
+ * log-out-everywhere, a right-to-erasure cutoff, a forced re-auth after a
1353
+ * password / key change. `destroyAllForUser` calls this for you, so a single
1354
+ * "logout everywhere" covers both store-backed and stateless tokens.
1355
+ *
1356
+ * The boundary is MONOTONIC: it only ever moves forward. A bump to an
1357
+ * `epochMs` at or below the stored value is a no-op — a replayed or
1358
+ * clock-skewed lower value can never widen a revoked window back open. Returns
1359
+ * the boundary in effect after the call. Leader-only. The subject id is stored
1360
+ * hashed; the plaintext id never lands in the table.
1361
+ *
1362
+ * @opts
1363
+ * epochMs: number, // boundary to set; default Date.now(). Tokens with iat < this are revoked.
1364
+ *
1365
+ * @example
1366
+ * // Force re-auth everywhere for a subject after a password change:
1367
+ * var boundary = await b.session.bump("user-42");
1368
+ * // Cut off at a specific instant (right-to-erasure effective time):
1369
+ * await b.session.bump("user-42", { epochMs: erasureEffectiveMs });
1370
+ */
1371
+ async function bump(subjectId, opts) {
1372
+ cluster.requireLeader();
1373
+ if (typeof subjectId !== "string" || subjectId.length === 0) {
1374
+ throw _err("INVALID_ARG", "session.bump requires a non-empty subjectId", true);
1375
+ }
1376
+ opts = opts || {};
1377
+ var epochMs = opts.epochMs === undefined ? Date.now() : opts.epochMs;
1378
+ if (typeof epochMs !== "number" || !isFinite(epochMs) || epochMs < 0) {
1379
+ throw _err("INVALID_ARG",
1380
+ "session.bump: epochMs must be a non-negative finite number, got " + JSON.stringify(epochMs), true);
1381
+ }
1382
+ var subjectHash = _hashSubjectId(subjectId);
1383
+ var t = _validFromSqlTable();
1384
+ var dialect = clusterStorage.dialect();
1385
+ var refs = _validFromConflictRefs(dialect, t);
1386
+
1387
+ // Monotonic-max conflict action: keep the LATER of the proposed and the
1388
+ // stored boundary, so a lower (replayed / clock-skewed) epoch can never move
1389
+ // the boundary backwards and re-open a revoked window.
1390
+ var validFromExpr = "CASE WHEN " + refs.proposed("validFromEpoch") + " > " +
1391
+ refs.existing("validFromEpoch") + " THEN " + refs.proposed("validFromEpoch") +
1392
+ " ELSE " + refs.existing("validFromEpoch") + " END";
1393
+ var built = sql.upsert(t, _sessionSqlOpts())
1394
+ .columns(["subjectHash", "validFromEpoch", "updatedAt"])
1395
+ .values({ subjectHash: subjectHash, validFromEpoch: epochMs, updatedAt: Date.now() })
1396
+ .onConflict(["subjectHash"])
1397
+ .doUpdate({ validFromEpoch: validFromExpr, updatedAt: "?" }, [Date.now()])
1398
+ .returning(["validFromEpoch"])
1399
+ .toSql();
1400
+ // The valid-from boundary is a FRAMEWORK table (FRAMEWORK_SCHEMA / cluster
1401
+ // DDL), NOT session data — it must execute against clusterStorage (the
1402
+ // framework db), never _currentStore(): a pluggable session-data store
1403
+ // (b.session.useStore / localDbThin) does not provision this table, so
1404
+ // routing the bump through it throws "no such table".
1405
+ var row;
1406
+ if (built.readbackSql) {
1407
+ // MySQL: ON DUPLICATE KEY UPDATE has no RETURNING — run the upsert, then
1408
+ // the readback SELECT b.sql emits (keyed on subjectHash).
1409
+ await clusterStorage.execute(built.sql, built.params);
1410
+ var readback = await clusterStorage.execute(built.readbackSql.sql, built.readbackSql.params);
1411
+ row = readback.rows && readback.rows[0];
1412
+ } else {
1413
+ var result = await clusterStorage.execute(built.sql, built.params);
1414
+ row = result.rows && result.rows[0];
1415
+ }
1416
+ var effective = row ? Number(row.validFromEpoch) : epochMs;
1417
+
1418
+ // Best-effort audit — matches the file's emit convention (safeEmit is
1419
+ // already drop-silent internally).
1420
+ try {
1421
+ audit.safeEmit({
1422
+ action: "auth.session.valid_from_bump",
1423
+ outcome: "success",
1424
+ metadata: { validFromEpoch: effective },
1425
+ });
1426
+ } catch (_ignored) { /* audit best-effort */ }
1427
+
1428
+ return effective;
1429
+ }
1430
+
1431
+ /**
1432
+ * @primitive b.session.validFrom
1433
+ * @signature b.session.validFrom(subjectId)
1434
+ * @since 0.15.13
1435
+ * @status stable
1436
+ * @related b.session.bump, b.session.check
1437
+ *
1438
+ * Read the current valid-from boundary (epoch ms) for a subject. Returns `0`
1439
+ * when the subject has never been bumped — no token is revoked by boundary, so
1440
+ * any non-negative token `iat` passes `b.session.check`. Runs anywhere (leader
1441
+ * or follower) — it only reads. The subject id is hashed before lookup; the
1442
+ * plaintext id never lands in the table.
1443
+ *
1444
+ * @example
1445
+ * var boundary = await b.session.validFrom("user-42");
1446
+ * // → 1735689600000 (last bump) or 0 (never bumped)
1447
+ */
1448
+ async function validFrom(subjectId) {
1449
+ if (typeof subjectId !== "string" || subjectId.length === 0) return 0;
1450
+ var built = sql.select(_validFromSqlTable(), _sessionSqlOpts())
1451
+ .columns(["validFromEpoch"])
1452
+ .where("subjectHash", _hashSubjectId(subjectId))
1453
+ .toSql();
1454
+ // Framework valid-from table — read from clusterStorage (the framework db),
1455
+ // not _currentStore(), so a pluggable session-data store cannot divert it (it
1456
+ // does not provision this table). See bump() for the full rationale.
1457
+ var row = await clusterStorage.executeOne(built.sql, built.params);
1458
+ return row ? Number(row.validFromEpoch) : 0;
1459
+ }
1460
+
1461
+ /**
1462
+ * @primitive b.session.check
1463
+ * @signature b.session.check(subjectId, tokenIatMs)
1464
+ * @since 0.15.13
1465
+ * @status stable
1466
+ * @related b.session.bump, b.session.validFrom
1467
+ *
1468
+ * Decide whether a stateless self-validating token is still valid against the
1469
+ * subject's valid-from boundary. Returns `true` when the token's issued-at
1470
+ * (`tokenIatMs`, epoch ms) is at or after the boundary; `false` when the token
1471
+ * was issued before the last `bump` (revoked). A subject that was never bumped
1472
+ * has boundary `0`, so any non-negative `iat` is valid. Runs anywhere.
1473
+ *
1474
+ * Fails CLOSED: a non-finite / negative / non-number `tokenIatMs` returns
1475
+ * `false` (treat an unparseable token as revoked rather than admit it). Call
1476
+ * this AFTER the token's own signature + expiry checks pass — it is the
1477
+ * server-side revocation layer those stateless checks otherwise lack.
1478
+ *
1479
+ * @example
1480
+ * // jwt already signature- and exp-verified; iat is in seconds → ms:
1481
+ * var ok = await b.session.check(claims.sub, claims.iat * 1000);
1482
+ * if (!ok) { res.statusCode = 401; res.end("session revoked"); return; }
1483
+ */
1484
+ async function check(subjectId, tokenIatMs) {
1485
+ if (typeof tokenIatMs !== "number" || !isFinite(tokenIatMs) || tokenIatMs < 0) {
1486
+ return false;
1487
+ }
1488
+ var boundary = await validFrom(subjectId);
1489
+ return tokenIatMs >= boundary;
1490
+ }
1491
+
1307
1492
  module.exports = {
1308
1493
  create: create,
1309
1494
  verify: verify,
@@ -1315,6 +1500,9 @@ module.exports = {
1315
1500
  updateData: updateData,
1316
1501
  purgeExpired: purgeExpired,
1317
1502
  count: count,
1503
+ bump: bump,
1504
+ validFrom: validFrom,
1505
+ check: check,
1318
1506
  useStore: useStore,
1319
1507
  isAnonymous: isAnonymous,
1320
1508
  stores: require("./session-stores"), // allow:inline-require — session-stores depends on local-db-thin which requires audit lazily; eager require is fine here
@@ -1107,39 +1107,11 @@ function _checkRawFragment(sql, params, opts, where) {
1107
1107
  // comments are skipped. Single linear pass, no backtracking regex. Same
1108
1108
  // shape as db-query.js's scanner.
1109
1109
  function _assertRawNoStringLiteral(sql, where) {
1110
- var i = 0;
1111
- var len = sql.length;
1112
- while (i < len) {
1113
- var ch = sql.charAt(i);
1114
- var next = i + 1 < len ? sql.charAt(i + 1) : "";
1115
- if (ch === '"') {
1116
- i += 1;
1117
- while (i < len) {
1118
- if (sql.charAt(i) === '"') {
1119
- if (sql.charAt(i + 1) === '"') { i += 2; continue; }
1120
- i += 1; break;
1121
- }
1122
- i += 1;
1123
- }
1124
- continue;
1125
- }
1126
- if (ch === "-" && next === "-") {
1127
- while (i < len && sql.charAt(i) !== "\n") i += 1;
1128
- continue;
1129
- }
1130
- if (ch === "/" && next === "*") {
1131
- i += 2;
1132
- while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) i += 1;
1133
- i += 2;
1134
- continue;
1135
- }
1136
- if (ch === "'") {
1137
- throw _err(where + ": raw SQL must not contain a string literal ('...') - bind " +
1138
- "every value with a ? placeholder, or pass { allowLiterals: true } when the " +
1139
- "literal is static and operator-controlled", "sql-builder/raw-literal");
1140
- }
1141
- i += 1;
1142
- }
1110
+ safeSql.assertNoRawStringLiteral(sql, where, function (w) {
1111
+ return _err(w + ": raw SQL must not contain a string literal ('...') - bind " +
1112
+ "every value with a ? placeholder, or pass { allowLiterals: true } when the " +
1113
+ "literal is static and operator-controlled", "sql-builder/raw-literal");
1114
+ });
1143
1115
  }
1144
1116
 
1145
1117
  // Refuse the two-char Postgres JSONB key-existence tokens (?| / ?&) in a raw
@@ -1188,51 +1160,10 @@ function _assertNoRawJsonbKeyOp(sql, where) {
1188
1160
  var _countPlaceholders = safeSql.countPlaceholders;
1189
1161
 
1190
1162
  // Translate the builder's `?` placeholders to a dialect's positional form
1191
- // (Postgres `$1..$N`; SQLite / MySQL keep `?`). Quote / comment-aware single
1192
- // pass - a `?` inside a string literal, a quoted identifier, or a comment is
1193
- // NOT a placeholder and is left untouched. This is the toExternalSql terminal
1194
- // for code that hands the SQL to an operator-supplied driver directly (no
1195
- // clusterStorage in the path to do the rewrite). The translator lives here -
1196
- // the builder owns its driver-final output rendering - rather than reaching
1197
- // into clusterStorage (which transitively requires this module).
1198
- function _toPositional(sql, dialect) {
1199
- if (dialect !== "postgres") return sql;
1200
- var out = "";
1201
- var n = 0;
1202
- var i = 0;
1203
- var len = sql.length;
1204
- while (i < len) {
1205
- var c = sql.charAt(i);
1206
- var nx = i + 1 < len ? sql.charAt(i + 1) : "";
1207
- if (c === "'" || c === '"' || c === "`") {
1208
- out += c;
1209
- i += 1;
1210
- while (i < len) {
1211
- var q = sql.charAt(i);
1212
- if (q === c) {
1213
- if (sql.charAt(i + 1) === c) { out += c + c; i += 2; continue; }
1214
- out += c; i += 1; break;
1215
- }
1216
- out += q; i += 1;
1217
- }
1218
- continue;
1219
- }
1220
- if (c === "-" && nx === "-") {
1221
- while (i < len && sql.charAt(i) !== "\n") { out += sql.charAt(i); i += 1; }
1222
- continue;
1223
- }
1224
- if (c === "/" && nx === "*") {
1225
- out += "/*"; i += 2;
1226
- while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) { out += sql.charAt(i); i += 1; }
1227
- if (i < len) { out += "*/"; i += 2; }
1228
- continue;
1229
- }
1230
- if (c === "?") { n += 1; out += "$" + n; i += 1; continue; }
1231
- out += c;
1232
- i += 1;
1233
- }
1234
- return out;
1235
- }
1163
+ // (Postgres `$1..$N`; SQLite / MySQL keep `?`); composed from safe-sql so the
1164
+ // quote / comment / backtick skip rules live in one place. The toExternalSql
1165
+ // terminal for code that hands the SQL to an operator-supplied driver directly.
1166
+ var _toPositional = safeSql.toPositional;
1236
1167
 
1237
1168
  /**
1238
1169
  * @primitive b.sql.toExternalSql
@@ -1922,6 +1853,163 @@ class InsertBuilder extends Builder {
1922
1853
  }
1923
1854
  }
1924
1855
 
1856
+ // ---- INSERT ... SELECT ... WHERE (conditional / append-only) --------
1857
+ //
1858
+ // A conditional INSERT that materialises its row from a value-less SELECT
1859
+ // guarded by a WHERE - INSERT INTO t (cols) SELECT <cells> WHERE <guard>.
1860
+ // The append-only-ledger debit idiom: the new row is written ONLY when a
1861
+ // guard derived from the table itself holds (a store-credit / gift-card /
1862
+ // points / metered-quota balance that lives on the latest row, with no
1863
+ // mutable counter row to increment()). The SELECT has no FROM - it is a
1864
+ // single computed row that the WHERE either admits (one row inserted) or
1865
+ // rejects (zero rows), evaluated atomically inside the INSERT against the
1866
+ // table the guard's correlated subquery / EXISTS references, so two racing
1867
+ // debits cannot both pass the balance check.
1868
+ //
1869
+ // Standard-SQL across sqlite / Postgres / MySQL - the only dialect-divergent
1870
+ // clause is RETURNING (Postgres / SQLite; refused on MySQL by the shared
1871
+ // _renderReturning, which the MySQL caller replaces with an explicit read).
1872
+ // Every SELECT cell routes through the SAME _renderValueCell choke-point
1873
+ // INSERT VALUES uses (so a cell is a bound ?, a b.sql.cast(...) ?::type, or a
1874
+ // b.sql.fn(...) allowlisted server function - no param), and the guard is a
1875
+ // full Predicate (the whole where-family: whereExists / whereSub / whereOp /
1876
+ // whereRaw / whereGroup compose, which is how a balance fence is expressed).
1877
+ //
1878
+ // Safety default: an INSERT...SELECT with no WHERE is just an INSERT...VALUES
1879
+ // and shipping it un-guarded is almost always a bug, so the verb THROWS
1880
+ // without a where() unless allowNoWhere() opts in - the same discipline
1881
+ // update / delete apply.
1882
+ class InsertSelectWhereBuilder extends Builder {
1883
+ constructor(tableNameOrRef, opts) {
1884
+ super("insert-select-where", tableNameOrRef, opts);
1885
+ this._columns = null;
1886
+ this._values = null; // single row, aligned to _columns
1887
+ this._where = new Predicate(this, "AND");
1888
+ this._returning = null;
1889
+ this._allowNoWhere = false;
1890
+ }
1891
+
1892
+ // Declare the target column list (validated + gated). values() infers it
1893
+ // from a row object's keys when omitted, exactly like INSERT.
1894
+ columns(cols) {
1895
+ if (!Array.isArray(cols) || cols.length === 0) {
1896
+ throw _err("columns() expects a non-empty array", "sql-builder/bad-columns");
1897
+ }
1898
+ var self = this;
1899
+ cols.forEach(function (c) { self._assertColumnMember(c, "insertSelectWhere"); _validateColumn(c); });
1900
+ this._columns = cols.slice();
1901
+ return this;
1902
+ }
1903
+
1904
+ // values(obj) - one row from a column->value map (sets _columns from the
1905
+ // keys when not already declared). values(array) - one positional row
1906
+ // aligned to a prior columns() call. A single row only: the SELECT
1907
+ // materialises exactly one candidate row gated by the WHERE.
1908
+ values(rowOrArray) {
1909
+ if (Array.isArray(rowOrArray)) {
1910
+ if (this._columns === null) {
1911
+ throw _err("values(array) requires a prior columns([...]) call", "sql-builder/no-columns");
1912
+ }
1913
+ if (rowOrArray.length !== this._columns.length) {
1914
+ throw _err("values(array): " + rowOrArray.length + " values but " +
1915
+ this._columns.length + " columns", "sql-builder/value-count");
1916
+ }
1917
+ this._values = rowOrArray.slice();
1918
+ return this;
1919
+ }
1920
+ if (rowOrArray && typeof rowOrArray === "object") {
1921
+ var keys = Object.keys(rowOrArray);
1922
+ if (keys.length === 0) throw _err("insertSelectWhere row object is empty", "sql-builder/empty-values");
1923
+ if (this._columns === null) this.columns(keys);
1924
+ var self = this;
1925
+ this._values = this._columns.map(function (c) {
1926
+ if (!Object.prototype.hasOwnProperty.call(rowOrArray, c)) {
1927
+ throw _err("insertSelectWhere row is missing column '" + c + "'", "sql-builder/missing-column");
1928
+ }
1929
+ return rowOrArray[c];
1930
+ });
1931
+ keys.forEach(function (k) {
1932
+ if (self._columns.indexOf(k) === -1) {
1933
+ throw _err("insertSelectWhere row has column '" + k + "' not in the column set",
1934
+ "sql-builder/extra-column");
1935
+ }
1936
+ });
1937
+ return this;
1938
+ }
1939
+ throw _err("insertSelectWhere values() requires a row object or a value array aligned to columns()",
1940
+ "sql-builder/bad-values");
1941
+ }
1942
+
1943
+ // A deliberate un-guarded conditional insert opts in here - same shape as
1944
+ // update / delete. Without it the verb refuses an empty WHERE.
1945
+ allowNoWhere() { this._allowNoWhere = true; return this; }
1946
+
1947
+ where() { this._where.where.apply(this._where, arguments); return this; }
1948
+ andWhere() { this._where.andWhere.apply(this._where, arguments); return this; }
1949
+ orWhere() { this._where.orWhere.apply(this._where, arguments); return this; }
1950
+ whereOp(col, op, value) { this._where.whereOp(col, op, value); return this; }
1951
+ orWhereOp(col, op, value) { this._where.orWhereOp(col, op, value); return this; }
1952
+ whereIn(col, values) { this._where.whereIn(col, values); return this; }
1953
+ whereNotIn(col, values) { this._where.whereNotIn(col, values); return this; }
1954
+ orWhereIn(col, values) { this._where.orWhereIn(col, values); return this; }
1955
+ whereInArray(col, values) { this._where.whereInArray(col, values); return this; }
1956
+ orWhereInArray(col, values) { this._where.orWhereInArray(col, values); return this; }
1957
+ whereInJsonEach(col, jsonArrayString) { this._where.whereInJsonEach(col, jsonArrayString); return this; }
1958
+ whereMatch(target, expr) { this._where.whereMatch(target, expr); return this; }
1959
+ whereNull(col) { this._where.whereNull(col); return this; }
1960
+ whereNotNull(col) { this._where.whereNotNull(col); return this; }
1961
+ orWhereNull(col) { this._where.orWhereNull(col); return this; }
1962
+ whereLike(col, term, mode) { this._where.whereLike(col, term, mode); return this; }
1963
+ orWhereLike(col, term, mode) { this._where.orWhereLike(col, term, mode); return this; }
1964
+ whereBetween(col, low, high) { this._where.whereBetween(col, low, high); return this; }
1965
+ whereSub(col, op, sub) { this._where.whereSub(col, op, sub); return this; }
1966
+ whereExists(sub) { this._where.whereExists(sub); return this; }
1967
+ whereNotExists(sub) { this._where.whereNotExists(sub); return this; }
1968
+ orWhereExists(sub) { this._where.orWhereExists(sub); return this; }
1969
+ whereGroup(closure) { this._where.whereGroup(closure); return this; }
1970
+ orWhereGroup(closure) { this._where.orWhereGroup(closure); return this; }
1971
+ whereRaw(sql, params, opts) { this._where.whereRaw(sql, params, opts); return this; }
1972
+ orWhereRaw(sql, params, opts) { this._where.orWhereRaw(sql, params, opts); return this; }
1973
+
1974
+ returning(cols) { this._returning = _normReturning(cols); return this; }
1975
+
1976
+ _render() {
1977
+ if (this._columns === null || this._values === null) {
1978
+ throw _err("insertSelectWhere requires columns + a values() row", "sql-builder/empty-values");
1979
+ }
1980
+ if (this._where.length === 0 && !this._allowNoWhere) {
1981
+ throw _err("refusing unconditional insertSelectWhere - call where(...) first or " +
1982
+ "allowNoWhere() (an un-guarded INSERT...SELECT is just INSERT...VALUES)",
1983
+ "sql-builder/no-where");
1984
+ }
1985
+ var dialect = this._dialect;
1986
+ var params = [];
1987
+ var quotedCols = this._columns.map(function (c) { return _quoteId(c, dialect); }).join(", ");
1988
+
1989
+ // Each SELECT cell renders through the same choke-point INSERT VALUES
1990
+ // uses: `?` (bound), `?::type` (cast), or an allowlisted server-function
1991
+ // token (NOW() / CURRENT_TIMESTAMP - no param).
1992
+ var cells = [];
1993
+ for (var v = 0; v < this._values.length; v += 1) {
1994
+ var rendered = _renderValueCell(this._values[v], dialect);
1995
+ cells.push(rendered.sql);
1996
+ for (var rp = 0; rp < rendered.params.length; rp += 1) params.push(rendered.params[rp]);
1997
+ }
1998
+
1999
+ var sql = "INSERT INTO " + this._table.ref(dialect) + " (" + quotedCols + ") SELECT " +
2000
+ cells.join(", ");
2001
+
2002
+ var w = this._where.build();
2003
+ if (w.sql) {
2004
+ sql += " WHERE " + w.sql;
2005
+ for (var wi = 0; wi < w.params.length; wi += 1) params.push(w.params[wi]);
2006
+ }
2007
+
2008
+ sql += _renderReturning(this._returning, dialect);
2009
+ return _emit(sql, params);
2010
+ }
2011
+ }
2012
+
1925
2013
  // ---- UPDATE ---------------------------------------------------------
1926
2014
 
1927
2015
  class UpdateBuilder extends Builder {
@@ -3699,6 +3787,64 @@ function select(tableNameOrRef, opts) { return new SelectBuilder(tableNameOrRef,
3699
3787
  */
3700
3788
  function insert(tableNameOrRef, opts) { return new InsertBuilder(tableNameOrRef, opts); }
3701
3789
 
3790
+ /**
3791
+ * @primitive b.sql.insertSelectWhere
3792
+ * @signature b.sql.insertSelectWhere(table, opts?)
3793
+ * @since 0.15.13
3794
+ * @status stable
3795
+ * @related b.sql.insert, b.sql.upsert, b.sql.update
3796
+ *
3797
+ * Start a conditional `INSERT ... SELECT ... WHERE` builder - a row written
3798
+ * ONLY when a guard derived from the table itself holds. Emits
3799
+ * `INSERT INTO t (cols) SELECT <cells> WHERE <guard>`: the value-less SELECT
3800
+ * is a single computed candidate row the WHERE either admits (one row
3801
+ * inserted) or rejects (zero rows). It is the race-free append-only-ledger
3802
+ * debit - a store-credit / gift-card / wallet / points / metered-quota /
3803
+ * seat-counter balance that lives only on the latest row, with no mutable
3804
+ * counter row to `increment()`. The guard's correlated subquery / `EXISTS`
3805
+ * is evaluated atomically inside the INSERT, so two concurrent debits cannot
3806
+ * both pass the same balance check.
3807
+ *
3808
+ * Supply the row via `columns([...])` + `values([...])` (positional),
3809
+ * `values({ ... })` (one row object, inferring the column list from its
3810
+ * keys), then the guard via the full `where` family (`whereExists` /
3811
+ * `whereSub` / `whereOp` / `whereGroup` / `whereRaw` all compose - the
3812
+ * balance fence is typically an `EXISTS` against the same table). Each SELECT
3813
+ * cell routes through the same choke-point INSERT `values()` uses, so a cell
3814
+ * may be a bound `?`, a `b.sql.cast(...)` (`?::type`), or a `b.sql.fn(...)`
3815
+ * allowlisted server function (`NOW()`, no param). Standard SQL across sqlite
3816
+ * / Postgres / MySQL; only `RETURNING` diverges (Postgres / SQLite - refused
3817
+ * on MySQL, run an explicit read).
3818
+ *
3819
+ * Safety default: an INSERT...SELECT with no WHERE is just an
3820
+ * INSERT...VALUES, so the verb THROWS without a `where()` unless
3821
+ * `allowNoWhere()` opts in - the same discipline `update` / `delete` apply.
3822
+ *
3823
+ * @opts
3824
+ * dialect: string, // postgres | sqlite | mysql (default sqlite)
3825
+ * schema: string, // schema qualifier
3826
+ * prefix: string, // operator app-table namespace prefix
3827
+ * allowedColumns: array, // column-membership gate set
3828
+ *
3829
+ * @example
3830
+ * // Append a -25 debit ONLY if the wallet's balance row still covers it -
3831
+ * // a race-free conditional insert with no read-modify-write. The guard is
3832
+ * // an EXISTS over a same-dialect sub-builder (no raw statement verb).
3833
+ * var covered = b.sql.select("wallet", { dialect: "postgres" })
3834
+ * .selectRaw("1")
3835
+ * .whereRaw('"id" = ? AND "balance" >= ?', ["w-1", 25]);
3836
+ * b.sql.insertSelectWhere("wallet_ledger", { dialect: "postgres" })
3837
+ * .values({ wallet_id: "w-1", amount: -25, at: b.sql.fn("NOW") })
3838
+ * .whereExists(covered)
3839
+ * .returning(["id"])
3840
+ * .toSql();
3841
+ * // -> { sql: 'INSERT INTO wallet_ledger ("wallet_id", "amount", "at") ' +
3842
+ * // 'SELECT ?, ?, NOW() WHERE EXISTS (SELECT 1 FROM wallet ' +
3843
+ * // 'WHERE ("id" = ? AND "balance" >= ?)) RETURNING "id"',
3844
+ * // params: ["w-1", -25, "w-1", 25] }
3845
+ */
3846
+ function insertSelectWhere(tableNameOrRef, opts) { return new InsertSelectWhereBuilder(tableNameOrRef, opts); }
3847
+
3702
3848
  /**
3703
3849
  * @primitive b.sql.update
3704
3850
  * @signature b.sql.update(table, opts?)
@@ -3806,6 +3952,7 @@ module.exports = {
3806
3952
  // Verbs
3807
3953
  select: select,
3808
3954
  insert: insert,
3955
+ insertSelectWhere: insertSelectWhere,
3809
3956
  update: update,
3810
3957
  delete: del,
3811
3958
  upsert: upsert,
@@ -76,6 +76,8 @@
76
76
 
77
77
  var C = require("./constants");
78
78
  var audit = require("./audit");
79
+ var validateOpts = require("./validate-opts");
80
+ var numericBounds = require("./numeric-bounds");
79
81
  var { SseError } = require("./framework-error");
80
82
 
81
83
  // Per W3C SSE — the wire format uses LF as terminator. A single LF
@@ -228,10 +230,8 @@ function _readLastEventId(req) {
228
230
  function create(req, res, opts) {
229
231
  opts = opts || {};
230
232
  var errorClass = opts.errorClass || SseError;
231
- if (!res || typeof res.write !== "function" || typeof res.end !== "function") {
232
- throw errorClass.factory("sse/bad-res",
233
- "sse.create: res must be a writable response stream");
234
- }
233
+ validateOpts.requireMethods(res, ["write", "end"],
234
+ "sse.create: res (writable response stream)", errorClass, "sse/bad-res");
235
235
  var heartbeatMs = opts.heartbeatMs;
236
236
  if (heartbeatMs === undefined) heartbeatMs = C.TIME.seconds(15);
237
237
  if (typeof heartbeatMs !== "number" || !isFinite(heartbeatMs) ||
@@ -255,12 +255,8 @@ function create(req, res, opts) {
255
255
  // never affected. Config-time input → throw on a bad value.
256
256
  var maxBufferedBytes = opts.maxBufferedBytes;
257
257
  if (maxBufferedBytes === undefined) maxBufferedBytes = C.BYTES.mib(1);
258
- if (typeof maxBufferedBytes !== "number" || !isFinite(maxBufferedBytes) ||
259
- maxBufferedBytes <= 0 || Math.floor(maxBufferedBytes) !== maxBufferedBytes) {
260
- throw errorClass.factory("sse/bad-opts",
261
- "sse.create: maxBufferedBytes must be a positive integer byte count (got " +
262
- JSON.stringify(maxBufferedBytes) + ")");
263
- }
258
+ numericBounds.requirePositiveFiniteInt(maxBufferedBytes,
259
+ "sse.create: maxBufferedBytes", errorClass, "sse/bad-opts");
264
260
 
265
261
  var lastEventId = _readLastEventId(req);
266
262