@blamejs/blamejs-shop 0.4.31 → 0.4.33

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 (343) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -1
  3. package/lib/asset-manifest.json +1 -1
  4. package/lib/vendor/MANIFEST.json +400 -282
  5. package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
  6. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
  7. package/lib/vendor/blamejs/.gitignore +6 -0
  8. package/lib/vendor/blamejs/CHANGELOG.md +28 -0
  9. package/lib/vendor/blamejs/MIGRATING.md +55 -0
  10. package/lib/vendor/blamejs/README.md +8 -6
  11. package/lib/vendor/blamejs/SECURITY.md +19 -3
  12. package/lib/vendor/blamejs/api-snapshot.json +2190 -664
  13. package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
  14. package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
  15. package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
  16. package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
  17. package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
  18. package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
  19. package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
  20. package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
  21. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
  22. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
  23. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
  24. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
  25. package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
  26. package/lib/vendor/blamejs/index.js +4 -0
  27. package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
  28. package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
  29. package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
  30. package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
  31. package/lib/vendor/blamejs/lib/api-key.js +158 -77
  32. package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
  33. package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
  34. package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
  35. package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
  36. package/lib/vendor/blamejs/lib/audit.js +259 -123
  37. package/lib/vendor/blamejs/lib/auth/elevation-grant.js +6 -2
  38. package/lib/vendor/blamejs/lib/auth/oauth.js +66 -9
  39. package/lib/vendor/blamejs/lib/auth/openid-federation.js +108 -47
  40. package/lib/vendor/blamejs/lib/auth/saml.js +6 -8
  41. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +36 -7
  42. package/lib/vendor/blamejs/lib/backup/index.js +45 -10
  43. package/lib/vendor/blamejs/lib/break-glass.js +355 -147
  44. package/lib/vendor/blamejs/lib/cache.js +174 -105
  45. package/lib/vendor/blamejs/lib/chain-writer.js +38 -16
  46. package/lib/vendor/blamejs/lib/cli.js +19 -14
  47. package/lib/vendor/blamejs/lib/cluster-provider-db.js +130 -104
  48. package/lib/vendor/blamejs/lib/cluster-storage.js +119 -22
  49. package/lib/vendor/blamejs/lib/cluster.js +119 -71
  50. package/lib/vendor/blamejs/lib/codepoint-class.js +23 -0
  51. package/lib/vendor/blamejs/lib/compliance.js +210 -4
  52. package/lib/vendor/blamejs/lib/consent.js +82 -29
  53. package/lib/vendor/blamejs/lib/constants.js +27 -11
  54. package/lib/vendor/blamejs/lib/credential-hash.js +9 -0
  55. package/lib/vendor/blamejs/lib/crypto-field.js +916 -156
  56. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
  57. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
  58. package/lib/vendor/blamejs/lib/db-query.js +882 -260
  59. package/lib/vendor/blamejs/lib/db-schema.js +228 -44
  60. package/lib/vendor/blamejs/lib/db.js +249 -99
  61. package/lib/vendor/blamejs/lib/dsr.js +385 -55
  62. package/lib/vendor/blamejs/lib/error-page.js +14 -1
  63. package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
  64. package/lib/vendor/blamejs/lib/external-db.js +549 -34
  65. package/lib/vendor/blamejs/lib/file-upload.js +52 -7
  66. package/lib/vendor/blamejs/lib/framework-error.js +20 -1
  67. package/lib/vendor/blamejs/lib/framework-files.js +73 -0
  68. package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
  69. package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
  70. package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
  71. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  72. package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
  73. package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
  74. package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
  75. package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
  76. package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
  77. package/lib/vendor/blamejs/lib/guard-email.js +47 -69
  78. package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
  79. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
  80. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
  81. package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
  82. package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
  83. package/lib/vendor/blamejs/lib/guard-html.js +53 -108
  84. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
  85. package/lib/vendor/blamejs/lib/guard-image.js +46 -103
  86. package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
  87. package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
  88. package/lib/vendor/blamejs/lib/guard-json.js +38 -108
  89. package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
  90. package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
  91. package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
  92. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
  93. package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
  94. package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
  95. package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
  96. package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
  97. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
  98. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
  99. package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
  100. package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
  101. package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
  102. package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
  105. package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
  106. package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
  107. package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
  108. package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
  109. package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
  110. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
  111. package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
  112. package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
  113. package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
  114. package/lib/vendor/blamejs/lib/guard-template.js +35 -172
  115. package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
  116. package/lib/vendor/blamejs/lib/guard-time.js +32 -154
  117. package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
  118. package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
  119. package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
  120. package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
  121. package/lib/vendor/blamejs/lib/http-client.js +37 -9
  122. package/lib/vendor/blamejs/lib/inbox.js +120 -107
  123. package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
  124. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
  125. package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
  126. package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
  128. package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
  129. package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
  130. package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
  131. package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
  132. package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
  133. package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
  134. package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
  136. package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
  137. package/lib/vendor/blamejs/lib/mail-store.js +293 -154
  138. package/lib/vendor/blamejs/lib/mail.js +8 -4
  139. package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
  140. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
  141. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
  142. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
  143. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
  144. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
  145. package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
  146. package/lib/vendor/blamejs/lib/migrations.js +108 -66
  147. package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
  148. package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
  149. package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
  150. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
  151. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
  152. package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
  153. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
  154. package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
  155. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
  156. package/lib/vendor/blamejs/lib/observability.js +124 -0
  157. package/lib/vendor/blamejs/lib/otel-export.js +12 -3
  158. package/lib/vendor/blamejs/lib/outbox.js +184 -83
  159. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
  160. package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
  161. package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
  162. package/lib/vendor/blamejs/lib/queue-local.js +225 -140
  163. package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
  164. package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
  165. package/lib/vendor/blamejs/lib/queue.js +7 -0
  166. package/lib/vendor/blamejs/lib/redact.js +68 -11
  167. package/lib/vendor/blamejs/lib/redis-client.js +160 -31
  168. package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
  169. package/lib/vendor/blamejs/lib/retention.js +117 -42
  170. package/lib/vendor/blamejs/lib/router.js +212 -5
  171. package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
  172. package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
  173. package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
  174. package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
  175. package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
  176. package/lib/vendor/blamejs/lib/safe-url.js +170 -3
  177. package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
  178. package/lib/vendor/blamejs/lib/scheduler.js +47 -12
  179. package/lib/vendor/blamejs/lib/seeders.js +122 -74
  180. package/lib/vendor/blamejs/lib/session-stores.js +42 -14
  181. package/lib/vendor/blamejs/lib/session.js +175 -77
  182. package/lib/vendor/blamejs/lib/sql.js +3842 -0
  183. package/lib/vendor/blamejs/lib/sse.js +26 -0
  184. package/lib/vendor/blamejs/lib/ssrf-guard.js +169 -4
  185. package/lib/vendor/blamejs/lib/static.js +177 -34
  186. package/lib/vendor/blamejs/lib/subject.js +96 -49
  187. package/lib/vendor/blamejs/lib/vault/index.js +3 -2
  188. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
  189. package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
  190. package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
  191. package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
  192. package/lib/vendor/blamejs/lib/websocket.js +35 -5
  193. package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
  194. package/lib/vendor/blamejs/package.json +2 -2
  195. package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
  196. package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
  197. package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
  198. package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
  199. package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
  200. package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
  201. package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
  202. package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
  203. package/lib/vendor/blamejs/release-notes/v0.15.7.json +43 -0
  204. package/lib/vendor/blamejs/scripts/check-services.js +21 -0
  205. package/lib/vendor/blamejs/scripts/gen-migrating.js +67 -0
  206. package/lib/vendor/blamejs/scripts/release.js +398 -38
  207. package/lib/vendor/blamejs/test/00-primitives.js +168 -0
  208. package/lib/vendor/blamejs/test/10-state.js +140 -14
  209. package/lib/vendor/blamejs/test/20-db.js +65 -2
  210. package/lib/vendor/blamejs/test/helpers/db.js +9 -0
  211. package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
  212. package/lib/vendor/blamejs/test/helpers/services.js +21 -0
  213. package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
  214. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
  215. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
  216. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
  217. package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
  218. package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
  219. package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
  220. package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
  221. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
  222. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
  223. package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
  224. package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
  225. package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
  226. package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
  227. package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
  228. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
  229. package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
  230. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
  231. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
  232. package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
  233. package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
  234. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
  235. package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
  236. package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
  237. package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
  238. package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
  239. package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
  240. package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
  241. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
  242. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
  243. package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
  244. package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
  245. package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
  246. package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
  247. package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
  248. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
  249. package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
  250. package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
  251. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
  252. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1196 -14
  253. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
  254. package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +18 -0
  255. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
  256. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
  257. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
  258. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
  259. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
  262. package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
  263. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
  264. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
  267. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
  270. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
  275. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
  276. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
  277. package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
  278. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
  282. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
  283. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
  284. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
  286. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
  287. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
  288. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
  296. package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +59 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
  302. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +362 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-watchdog-stale-settle.test.js +71 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
  309. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
  315. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
  317. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
  318. package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
  319. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
  320. package/lib/vendor/blamejs/test/smoke.js +79 -21
  321. package/package.json +2 -2
  322. package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
  323. package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
  324. package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
  325. package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
  326. package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
  327. package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
  328. package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
  329. package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
  330. package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
  331. package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
  332. package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
  333. package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
  334. package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
  335. package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
  336. package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
  337. package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
  338. package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
  339. package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
  340. package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
  341. package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
  342. package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
  343. package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
@@ -81,6 +81,7 @@
81
81
 
82
82
  var C = require("./constants");
83
83
  var { defineClass } = require("./framework-error");
84
+ var gateContract = require("./gate-contract");
84
85
 
85
86
  var SafeIcalError = defineClass("SafeIcalError", { alwaysPermanent: true });
86
87
 
@@ -116,12 +117,7 @@ var PROFILES = Object.freeze({
116
117
  }),
117
118
  });
118
119
 
119
- var COMPLIANCE_POSTURES = Object.freeze({
120
- hipaa: "strict",
121
- "pci-dss": "strict",
122
- gdpr: "strict",
123
- soc2: "strict",
124
- });
120
+ var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
125
121
 
126
122
  // Property-name allowlist per RFC 5545 §8.7 (Property Registry) +
127
123
  // RFC 5546 §4.3 (iTIP additions) + RFC 7986 §5 (new calendar
@@ -273,24 +269,6 @@ function parse(text, opts) {
273
269
  : { vcalendar: vcalendars[0], vcalendars: vcalendars };
274
270
  }
275
271
 
276
- /**
277
- * @primitive b.safeIcal.compliancePosture
278
- * @signature b.safeIcal.compliancePosture(name)
279
- * @since 0.9.81
280
- * @status stable
281
- * @related b.safeIcal.parse
282
- *
283
- * Map a compliance-posture name to its profile. Returns the profile
284
- * string for a known posture, `null` for unknown names.
285
- *
286
- * @example
287
- * b.safeIcal.compliancePosture("hipaa"); // → "strict"
288
- * b.safeIcal.compliancePosture("loose"); // → null
289
- */
290
- function compliancePosture(name) {
291
- return COMPLIANCE_POSTURES[name] || null;
292
- }
293
-
294
272
  // ---- Profile / opt resolution ----
295
273
 
296
274
  function _resolveCaps(opts) {
@@ -623,12 +601,19 @@ function _preview(s) {
623
601
  return s.length > 64 ? s.slice(0, 64) + "..." : s; // log-preview length cap
624
602
  }
625
603
 
626
- module.exports = {
627
- parse: parse,
628
- compliancePosture: compliancePosture,
629
- PROFILES: PROFILES,
630
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
631
- KNOWN_PROPERTIES: KNOWN_PROPERTIES,
632
- KNOWN_COMPONENTS: KNOWN_COMPONENTS,
633
- SafeIcalError: SafeIcalError,
634
- };
604
+ // compliancePosture is assembled by gateContract.defineParser below; its
605
+ // wiki section renders from the single-sourced @abiTemplate (defineParser)
606
+ // block in gate-contract.js, instantiated for this guard by the page
607
+ // generator.
608
+ module.exports = gateContract.defineParser({
609
+ name: "ical",
610
+ entry: parse,
611
+ entryName: "parse",
612
+ errorClass: SafeIcalError,
613
+ profiles: PROFILES,
614
+ postures: COMPLIANCE_POSTURES,
615
+ extra: {
616
+ KNOWN_PROPERTIES: KNOWN_PROPERTIES,
617
+ KNOWN_COMPONENTS: KNOWN_COMPONENTS,
618
+ },
619
+ });
@@ -77,6 +77,7 @@
77
77
 
78
78
  var C = require("./constants");
79
79
  var { defineClass } = require("./framework-error");
80
+ var gateContract = require("./gate-contract");
80
81
 
81
82
  var SafeIcapError = defineClass("SafeIcapError", { alwaysPermanent: true });
82
83
 
@@ -131,11 +132,15 @@ var PROFILES = Object.freeze({
131
132
  },
132
133
  });
133
134
 
134
- var COMPLIANCE_POSTURES = Object.freeze({
135
- hipaa: "strict",
136
- "pci-dss": "strict",
137
- gdpr: "strict",
138
- soc2: "strict",
135
+ var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
136
+
137
+ var _resolveProfile = gateContract.makeProfileResolver({
138
+ profiles: PROFILES,
139
+ postures: COMPLIANCE_POSTURES,
140
+ defaults: DEFAULT_PROFILE,
141
+ errorClass: SafeIcapError,
142
+ codePrefix: "safe-icap",
143
+ byObject: true,
139
144
  });
140
145
 
141
146
  /**
@@ -257,22 +262,6 @@ function parse(buf, opts) {
257
262
  };
258
263
  }
259
264
 
260
- /**
261
- * @primitive b.safeIcap.compliancePosture
262
- * @signature b.safeIcap.compliancePosture(posture)
263
- * @since 0.9.81
264
- * @status stable
265
- *
266
- * Return the effective profile name for a compliance posture, or
267
- * `null` for unknown posture names.
268
- *
269
- * @example
270
- * b.safeIcap.compliancePosture("hipaa"); // → "strict"
271
- */
272
- function compliancePosture(posture) {
273
- return COMPLIANCE_POSTURES[posture] || null;
274
- }
275
-
276
265
  // ---- internals ----
277
266
 
278
267
  function _findHeaderEnd(buf, maxHeaderBytes) {
@@ -479,25 +468,20 @@ function _detectThreat(statusCode, headers) {
479
468
  return { found: found, name: name };
480
469
  }
481
470
 
482
- function _resolveProfile(opts) {
483
- if (opts.posture && COMPLIANCE_POSTURES[opts.posture]) {
484
- return PROFILES[COMPLIANCE_POSTURES[opts.posture]];
485
- }
486
- var p = opts.profile || DEFAULT_PROFILE;
487
- if (!PROFILES[p]) {
488
- throw new SafeIcapError("safe-icap/bad-profile",
489
- "safeIcap: unknown profile '" + p + "' (valid: strict / balanced / permissive)");
490
- }
491
- return PROFILES[p];
492
- }
493
-
494
- module.exports = {
495
- parse: parse,
496
- compliancePosture: compliancePosture,
497
- PROFILES: PROFILES,
498
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
499
- ALLOWED_STATUS: ALLOWED_STATUS,
500
- SafeIcapError: SafeIcapError,
501
- NAME: "icap",
502
- KIND: "icap-response",
503
- };
471
+ // compliancePosture is assembled by gateContract.defineParser below; its
472
+ // wiki section renders from the single-sourced @abiTemplate (defineParser)
473
+ // block in gate-contract.js, instantiated for this guard by the page
474
+ // generator.
475
+ module.exports = gateContract.defineParser({
476
+ name: "icap",
477
+ entry: parse,
478
+ entryName: "parse",
479
+ errorClass: SafeIcapError,
480
+ profiles: PROFILES,
481
+ postures: COMPLIANCE_POSTURES,
482
+ extra: {
483
+ ALLOWED_STATUS: ALLOWED_STATUS,
484
+ NAME: "icap",
485
+ KIND: "icap-response",
486
+ },
487
+ });
@@ -49,6 +49,7 @@
49
49
  */
50
50
 
51
51
  var { defineClass } = require("./framework-error");
52
+ var gateContract = require("./gate-contract");
52
53
 
53
54
  var SafeSieveError = defineClass("SafeSieveError", { alwaysPermanent: true });
54
55
 
@@ -82,12 +83,7 @@ var PROFILES = Object.freeze({
82
83
  }),
83
84
  });
84
85
 
85
- var COMPLIANCE_POSTURES = Object.freeze({
86
- hipaa: "strict",
87
- "pci-dss": "strict",
88
- gdpr: "strict",
89
- soc2: "strict",
90
- });
86
+ var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
91
87
 
92
88
  // RFC 5228 §1.2 capability identifiers. Each entry lists whether the
93
89
  // framework's v0.9.55 interpreter implements the capability. Unknown
@@ -648,37 +644,22 @@ function validate(script, opts) {
648
644
  }
649
645
  }
650
646
 
651
- /**
652
- * @primitive b.safeSieve.compliancePosture
653
- * @signature b.safeSieve.compliancePosture(name)
654
- * @since 0.9.55
655
- * @status stable
656
- * @related b.safeSieve.parse, b.safeSieve.validate
657
- *
658
- * Look up the recommended profile name for a compliance posture
659
- * (`hipaa` / `pci-dss` / `gdpr` / `soc2`). Returns `"strict"` for any
660
- * known posture, `null` for unknown names. Operator-facing primitives
661
- * that thread `compliancePosture` opt through to safeSieve compose
662
- * this for the explicit-cast pattern when they need the name string
663
- * (rather than relying on `_resolveOpts` to do the lookup).
664
- *
665
- * @example
666
- * b.safeSieve.compliancePosture("hipaa"); // → "strict"
667
- * b.safeSieve.compliancePosture("loose"); // → null
668
- */
669
- function compliancePosture(name) {
670
- return COMPLIANCE_POSTURES[name] || null;
671
- }
672
-
673
- module.exports = {
674
- parse: parse,
675
- validate: validate,
676
- compliancePosture: compliancePosture,
677
- KNOWN_CAPABILITIES: KNOWN_CAPABILITIES,
678
- PROFILES: PROFILES,
679
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
680
- SafeSieveError: SafeSieveError,
681
- // Internal exports for the interpreter at lib/mail-sieve.js.
682
- _tokenize: _tokenize,
683
- _resolveCaps: _resolveCaps,
684
- };
647
+ // compliancePosture is assembled by gateContract.defineParser below; its
648
+ // wiki section renders from the single-sourced @abiTemplate (defineParser)
649
+ // block in gate-contract.js, instantiated for this guard by the page
650
+ // generator.
651
+ module.exports = gateContract.defineParser({
652
+ name: "sieve",
653
+ entry: parse,
654
+ entryName: "parse",
655
+ errorClass: SafeSieveError,
656
+ profiles: PROFILES,
657
+ postures: COMPLIANCE_POSTURES,
658
+ extra: {
659
+ validate: validate,
660
+ KNOWN_CAPABILITIES: KNOWN_CAPABILITIES,
661
+ // Internal exports for the interpreter at lib/mail-sieve.js.
662
+ _tokenize: _tokenize,
663
+ _resolveCaps: _resolveCaps,
664
+ },
665
+ });
@@ -175,7 +175,7 @@ function validateIdentifier(name, opts) {
175
175
 
176
176
  /**
177
177
  * @primitive b.safeSql.quoteIdentifier
178
- * @signature b.safeSql.quoteIdentifier(name, dialect?)
178
+ * @signature b.safeSql.quoteIdentifier(name, dialect?, opts?)
179
179
  * @since 0.1.0
180
180
  * @status stable
181
181
  * @related b.safeSql.validateIdentifier, b.safeSql.quoteQualified
@@ -185,6 +185,17 @@ function validateIdentifier(name, opts) {
185
185
  * MySQL. Default dialect is `"sqlite"`. Throws `SafeSqlError` if the
186
186
  * identifier fails `validateIdentifier`.
187
187
  *
188
+ * `opts` is forwarded to `validateIdentifier` — pass
189
+ * `{ allowReserved: true }` to quote a name that collides with a SQL
190
+ * keyword (a column literally named `from` / `select`). Quoting is
191
+ * exactly what makes a reserved word safe in identifier position, so the
192
+ * query builder (`b.sql`) routes every identifier through here with
193
+ * `allowReserved` on; the default still rejects reserved words so a bare
194
+ * caller catches the likely typo.
195
+ *
196
+ * @opts
197
+ * allowReserved: boolean, // default: false — permit SQL-keyword names (safe once quoted)
198
+ *
188
199
  * @example
189
200
  * var b = require("blamejs");
190
201
  * b.safeSql.quoteIdentifier("users");
@@ -193,11 +204,14 @@ function validateIdentifier(name, opts) {
193
204
  * b.safeSql.quoteIdentifier("Order", "postgres");
194
205
  * // → '"Order"'
195
206
  *
207
+ * b.safeSql.quoteIdentifier("from", "postgres", { allowReserved: true });
208
+ * // → '"from"'
209
+ *
196
210
  * b.safeSql.quoteIdentifier("users", "mysql");
197
211
  * // → "`users`"
198
212
  */
199
- function quoteIdentifier(name, dialect) {
200
- validateIdentifier(name);
213
+ function quoteIdentifier(name, dialect, opts) {
214
+ validateIdentifier(name, opts);
201
215
  dialect = (dialect || "sqlite").toLowerCase();
202
216
  if (dialect === "mysql") return "`" + name + "`";
203
217
  // sqlite + postgres both use double-quote per SQL standard
@@ -258,6 +272,53 @@ function quoteQualified(parts, dialect) {
258
272
  return quoted.join(".");
259
273
  }
260
274
 
275
+ /**
276
+ * @primitive b.safeSql.quoteList
277
+ * @signature b.safeSql.quoteList(names, dialect?, opts?)
278
+ * @since 0.15.0
279
+ * @status stable
280
+ * @related b.safeSql.quoteIdentifier, b.safeSql.quoteQualified, b.sql
281
+ *
282
+ * Quote a list of identifiers into a comma-joined fragment — each name
283
+ * validated + quoted via `quoteIdentifier`. The "many" companion to
284
+ * `quoteIdentifier` (one) and `quoteQualified` (a dotted name): use it for
285
+ * SELECT projections and INSERT column lists so the recurring
286
+ * `cols.map(quoteIdentifier).join(", ")` shape is composed, not hand-rolled.
287
+ *
288
+ * There is deliberately NO value/string-literal quoter in this module:
289
+ * values flow as bound placeholders (`?` / `$N`), never interpolated, which
290
+ * is what makes the injection class structurally impossible. Quoting a
291
+ * literal would reopen it — use the query builder's parameter binding.
292
+ *
293
+ * `opts` is forwarded to each `quoteIdentifier` (e.g.
294
+ * `{ allowReserved: true }` for column lists that may contain SQL-keyword
295
+ * names, as `b.sql` does).
296
+ *
297
+ * Throws `SafeSqlError` (`sql/empty`) on an empty array and (per
298
+ * `quoteIdentifier`) on any invalid identifier.
299
+ *
300
+ * @opts
301
+ * allowReserved: boolean, // default: false — forwarded to quoteIdentifier
302
+ *
303
+ * @example
304
+ * var b = require("blamejs");
305
+ * b.safeSql.quoteList(["id", "createdAt"], "postgres");
306
+ * // → '"id", "createdAt"'
307
+ *
308
+ * b.safeSql.quoteList(["queueName", "status"], "mysql");
309
+ * // → "`queueName`, `status`"
310
+ */
311
+ function quoteList(names, dialect, opts) {
312
+ if (!Array.isArray(names) || names.length === 0) {
313
+ throw new SafeSqlError("quoteList requires a non-empty array of identifiers", "sql/empty");
314
+ }
315
+ var out = [];
316
+ for (var i = 0; i < names.length; i++) {
317
+ out.push(quoteIdentifier(names[i], dialect, opts));
318
+ }
319
+ return out.join(", ");
320
+ }
321
+
261
322
  /**
262
323
  * @primitive b.safeSql.assertOneOf
263
324
  * @signature b.safeSql.assertOneOf(name, allowlist)
@@ -310,6 +371,64 @@ function assertOneOf(name, allowlist) {
310
371
  return name;
311
372
  }
312
373
 
374
+ /**
375
+ * @primitive b.safeSql.countPlaceholders
376
+ * @signature b.safeSql.countPlaceholders(sql)
377
+ * @since 0.14.29
378
+ * @status stable
379
+ * @related b.safeSql.quoteIdentifier, b.safeSql.validateIdentifier
380
+ *
381
+ * Count the bound `?` placeholders in a SQL string, skipping any `?`
382
+ * that appears inside a string literal (`'...'` / `"..."`, doubled-quote
383
+ * escape aware) or inside a line or block comment. The canonical quote-
384
+ * and comment-aware scanner the query builder uses to check placeholder /
385
+ * param parity and the residency write-gate uses to align bound values;
386
+ * both compose this so the skip rules live in one place.
387
+ *
388
+ * @example
389
+ * var b = require("blamejs");
390
+ * b.safeSql.countPlaceholders("a = ? AND b = ?");
391
+ * // → 2
392
+ *
393
+ * b.safeSql.countPlaceholders("note = 'is ? literal' AND id = ?");
394
+ * // → 1
395
+ */
396
+ function countPlaceholders(sql) {
397
+ var count = 0;
398
+ var i = 0;
399
+ var len = sql.length;
400
+ while (i < len) {
401
+ var ch = sql.charAt(i);
402
+ var next = i + 1 < len ? sql.charAt(i + 1) : "";
403
+ if (ch === "'" || ch === '"') {
404
+ var quote = ch;
405
+ i += 1;
406
+ while (i < len) {
407
+ if (sql.charAt(i) === quote) {
408
+ // SQL doubles the quote char to escape it within a literal.
409
+ if (sql.charAt(i + 1) === quote) { i += 2; continue; }
410
+ i += 1; break;
411
+ }
412
+ i += 1;
413
+ }
414
+ continue;
415
+ }
416
+ if (ch === "-" && next === "-") {
417
+ while (i < len && sql.charAt(i) !== "\n") i += 1;
418
+ continue;
419
+ }
420
+ if (ch === "/" && next === "*") {
421
+ i += 2;
422
+ while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) i += 1;
423
+ i += 2;
424
+ continue;
425
+ }
426
+ if (ch === "?") count += 1;
427
+ i += 1;
428
+ }
429
+ return count;
430
+ }
431
+
313
432
  /**
314
433
  * @primitive b.safeSql.DEFAULT_IDENTIFIER_RE
315
434
  * @signature b.safeSql.DEFAULT_IDENTIFIER_RE
@@ -351,11 +470,101 @@ function assertOneOf(name, allowlist) {
351
470
  * // → 63
352
471
  */
353
472
 
473
+ /**
474
+ * @primitive b.safeSql.assertSingleStatement
475
+ * @signature b.safeSql.assertSingleStatement(sql, opts?)
476
+ * @since 0.15.4
477
+ * @status stable
478
+ * @related b.safeSql.quoteIdentifier, b.safeSql.countPlaceholders, b.sql
479
+ *
480
+ * The one quote/comment-aware single-statement gate for any FINISHED SQL
481
+ * string that reaches a driver. Refuses a NUL, a lone surrogate, a
482
+ * top-level ';' (stacked statement), an unterminated quote, and unbalanced
483
+ * parentheses - while CORRECTLY allowing those characters inside a balanced
484
+ * quoted label (e.g. a MySQL ENUM('a;b')). Hand-rolled DDL (schema
485
+ * reconcile, the DSR store, migrations) and the b.sql builder's own output
486
+ * gates route through this single scan so the injection backstop cannot
487
+ * drift between the structured builder and the raw-DDL paths. Returns the
488
+ * input string so a caller can wrap inline:
489
+ * runSql(db, safeSql.assertSingleStatement(ddl, { label: "schema" }));
490
+ *
491
+ * @opts
492
+ * label: string, // message prefix (default: "sql")
493
+ * makeError: function, // (message, codeSuffix) => Error (default: SafeSqlError "sql/<suffix>")
494
+ *
495
+ * @example
496
+ * var ddl = b.safeSql.assertSingleStatement("CREATE TABLE t (id INTEGER)", { label: "schema" });
497
+ * // returns the input string; throws sql/stacked-statement on a stacked DDL
498
+ */
499
+ function assertSingleStatement(sql, opts) {
500
+ opts = opts || {};
501
+ var label = typeof opts.label === "string" ? opts.label : "sql";
502
+ var mkErr = typeof opts.makeError === "function"
503
+ ? opts.makeError
504
+ : function (msg, suffix) { return new SafeSqlError(msg, "sql/" + suffix); };
505
+ // Backtick written via its code point so no NUL byte can reach this source.
506
+ var BACKTICK = String.fromCharCode(96);
507
+ if (typeof sql !== "string" || sql.length === 0) {
508
+ throw mkErr(label + ": SQL must be a non-empty string", "empty-sql");
509
+ }
510
+ if (sql.indexOf(String.fromCharCode(0)) !== -1) {
511
+ throw mkErr(label + ": SQL contains a NUL byte - rejected", "null-byte-sql");
512
+ }
513
+ if (typeof sql.isWellFormed === "function" && !sql.isWellFormed()) {
514
+ throw mkErr(label + ": SQL contains invalid Unicode (lone surrogates) - rejected",
515
+ "invalid-encoding-sql");
516
+ }
517
+ var i = 0;
518
+ var len = sql.length;
519
+ var depth = 0;
520
+ while (i < len) {
521
+ var ch = sql.charAt(i);
522
+ var next = i + 1 < len ? sql.charAt(i + 1) : "";
523
+ if (ch === "'" || ch === '"' || ch === BACKTICK) {
524
+ var qch = ch;
525
+ var closed = false;
526
+ i += 1;
527
+ while (i < len) {
528
+ if (sql.charAt(i) === qch) {
529
+ if (sql.charAt(i + 1) === qch) { i += 2; continue; } // doubled quote = escaped literal
530
+ i += 1; closed = true; break;
531
+ }
532
+ i += 1;
533
+ }
534
+ if (!closed) {
535
+ throw mkErr(label + ": unterminated quote in SQL (quote-jump / breakout risk)",
536
+ "unterminated-quote");
537
+ }
538
+ continue;
539
+ }
540
+ if (ch === "-" && next === "-") { while (i < len && sql.charAt(i) !== "\n") i += 1; continue; }
541
+ if (ch === "/" && next === "*") {
542
+ i += 2;
543
+ while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) i += 1;
544
+ i += 2;
545
+ continue;
546
+ }
547
+ if (ch === "(") { depth += 1; }
548
+ else if (ch === ")") { depth -= 1; }
549
+ else if (ch === ";") {
550
+ throw mkErr(label + ": emitted a top-level ';' - exactly one statement", "stacked-statement");
551
+ }
552
+ i += 1;
553
+ }
554
+ if (depth !== 0) {
555
+ throw mkErr(label + ": unbalanced parentheses in SQL", "unbalanced");
556
+ }
557
+ return sql;
558
+ }
559
+
354
560
  module.exports = {
355
561
  validateIdentifier: validateIdentifier,
562
+ assertSingleStatement: assertSingleStatement,
356
563
  quoteIdentifier: quoteIdentifier,
357
564
  quoteQualified: quoteQualified,
565
+ quoteList: quoteList,
358
566
  assertOneOf: assertOneOf,
567
+ countPlaceholders: countPlaceholders,
359
568
  SafeSqlError: SafeSqlError,
360
569
  // Exposed so consumers can compose their own validators
361
570
  DEFAULT_IDENTIFIER_RE: DEFAULT_IDENTIFIER_RE,