@blamejs/blamejs-shop 0.4.31 → 0.4.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +392 -278
  4. package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
  5. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
  6. package/lib/vendor/blamejs/.gitignore +6 -0
  7. package/lib/vendor/blamejs/CHANGELOG.md +26 -0
  8. package/lib/vendor/blamejs/MIGRATING.md +43 -0
  9. package/lib/vendor/blamejs/README.md +8 -6
  10. package/lib/vendor/blamejs/SECURITY.md +19 -3
  11. package/lib/vendor/blamejs/api-snapshot.json +2190 -664
  12. package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
  13. package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
  14. package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
  15. package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
  16. package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
  17. package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
  18. package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
  19. package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
  20. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
  21. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
  22. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
  23. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
  24. package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
  25. package/lib/vendor/blamejs/index.js +4 -0
  26. package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
  27. package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
  28. package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
  29. package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
  30. package/lib/vendor/blamejs/lib/api-key.js +158 -77
  31. package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
  32. package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
  33. package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
  34. package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
  35. package/lib/vendor/blamejs/lib/audit.js +259 -123
  36. package/lib/vendor/blamejs/lib/auth/oauth.js +53 -9
  37. package/lib/vendor/blamejs/lib/auth/openid-federation.js +108 -47
  38. package/lib/vendor/blamejs/lib/auth/saml.js +6 -8
  39. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +31 -5
  40. package/lib/vendor/blamejs/lib/backup/index.js +45 -10
  41. package/lib/vendor/blamejs/lib/break-glass.js +355 -147
  42. package/lib/vendor/blamejs/lib/cache.js +174 -105
  43. package/lib/vendor/blamejs/lib/chain-writer.js +38 -16
  44. package/lib/vendor/blamejs/lib/cli.js +19 -14
  45. package/lib/vendor/blamejs/lib/cluster-provider-db.js +130 -104
  46. package/lib/vendor/blamejs/lib/cluster-storage.js +119 -22
  47. package/lib/vendor/blamejs/lib/cluster.js +119 -71
  48. package/lib/vendor/blamejs/lib/codepoint-class.js +23 -0
  49. package/lib/vendor/blamejs/lib/compliance.js +206 -4
  50. package/lib/vendor/blamejs/lib/consent.js +82 -29
  51. package/lib/vendor/blamejs/lib/constants.js +27 -11
  52. package/lib/vendor/blamejs/lib/crypto-field.js +916 -156
  53. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
  54. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
  55. package/lib/vendor/blamejs/lib/db-query.js +882 -260
  56. package/lib/vendor/blamejs/lib/db-schema.js +228 -44
  57. package/lib/vendor/blamejs/lib/db.js +249 -99
  58. package/lib/vendor/blamejs/lib/dsr.js +385 -55
  59. package/lib/vendor/blamejs/lib/error-page.js +14 -1
  60. package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
  61. package/lib/vendor/blamejs/lib/external-db.js +549 -34
  62. package/lib/vendor/blamejs/lib/file-upload.js +52 -7
  63. package/lib/vendor/blamejs/lib/framework-error.js +20 -1
  64. package/lib/vendor/blamejs/lib/framework-files.js +73 -0
  65. package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
  66. package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
  67. package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
  68. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  69. package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
  70. package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
  71. package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
  72. package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
  73. package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
  74. package/lib/vendor/blamejs/lib/guard-email.js +47 -69
  75. package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
  76. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
  77. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
  78. package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
  79. package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
  80. package/lib/vendor/blamejs/lib/guard-html.js +53 -108
  81. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
  82. package/lib/vendor/blamejs/lib/guard-image.js +46 -103
  83. package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
  84. package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
  85. package/lib/vendor/blamejs/lib/guard-json.js +38 -108
  86. package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
  87. package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
  88. package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
  89. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
  90. package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
  91. package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
  92. package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
  93. package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
  94. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
  95. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
  96. package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
  97. package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
  98. package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
  99. package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
  100. package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
  101. package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
  102. package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
  103. package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
  104. package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
  105. package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
  106. package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
  107. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
  108. package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
  109. package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
  110. package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
  111. package/lib/vendor/blamejs/lib/guard-template.js +35 -172
  112. package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
  113. package/lib/vendor/blamejs/lib/guard-time.js +32 -154
  114. package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
  115. package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
  116. package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
  117. package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
  118. package/lib/vendor/blamejs/lib/http-client.js +37 -9
  119. package/lib/vendor/blamejs/lib/inbox.js +120 -107
  120. package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
  121. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
  123. package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
  124. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
  125. package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
  126. package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
  127. package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
  128. package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
  129. package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
  130. package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
  131. package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
  132. package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
  133. package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
  134. package/lib/vendor/blamejs/lib/mail-store.js +293 -154
  135. package/lib/vendor/blamejs/lib/mail.js +8 -4
  136. package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
  137. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
  138. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
  139. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
  140. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
  141. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
  142. package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
  143. package/lib/vendor/blamejs/lib/migrations.js +108 -66
  144. package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
  145. package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
  146. package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
  147. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
  148. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
  149. package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
  150. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
  151. package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
  152. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
  153. package/lib/vendor/blamejs/lib/observability.js +124 -0
  154. package/lib/vendor/blamejs/lib/otel-export.js +12 -3
  155. package/lib/vendor/blamejs/lib/outbox.js +184 -83
  156. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
  157. package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
  158. package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
  159. package/lib/vendor/blamejs/lib/queue-local.js +225 -140
  160. package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
  161. package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
  162. package/lib/vendor/blamejs/lib/queue.js +7 -0
  163. package/lib/vendor/blamejs/lib/redact.js +68 -11
  164. package/lib/vendor/blamejs/lib/redis-client.js +160 -31
  165. package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
  166. package/lib/vendor/blamejs/lib/retention.js +101 -40
  167. package/lib/vendor/blamejs/lib/router.js +212 -5
  168. package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
  169. package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
  170. package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
  171. package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
  172. package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
  173. package/lib/vendor/blamejs/lib/safe-url.js +170 -3
  174. package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
  175. package/lib/vendor/blamejs/lib/scheduler.js +35 -12
  176. package/lib/vendor/blamejs/lib/seeders.js +122 -74
  177. package/lib/vendor/blamejs/lib/session-stores.js +42 -14
  178. package/lib/vendor/blamejs/lib/session.js +175 -77
  179. package/lib/vendor/blamejs/lib/sql.js +3842 -0
  180. package/lib/vendor/blamejs/lib/sse.js +26 -0
  181. package/lib/vendor/blamejs/lib/ssrf-guard.js +151 -4
  182. package/lib/vendor/blamejs/lib/static.js +177 -34
  183. package/lib/vendor/blamejs/lib/subject.js +96 -49
  184. package/lib/vendor/blamejs/lib/vault/index.js +3 -2
  185. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
  186. package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
  187. package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
  188. package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
  189. package/lib/vendor/blamejs/lib/websocket.js +35 -5
  190. package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
  191. package/lib/vendor/blamejs/package.json +2 -2
  192. package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
  193. package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
  194. package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
  195. package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
  196. package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
  197. package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
  198. package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
  199. package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
  200. package/lib/vendor/blamejs/scripts/check-services.js +21 -0
  201. package/lib/vendor/blamejs/scripts/gen-migrating.js +51 -0
  202. package/lib/vendor/blamejs/scripts/release.js +398 -38
  203. package/lib/vendor/blamejs/test/00-primitives.js +117 -0
  204. package/lib/vendor/blamejs/test/10-state.js +140 -14
  205. package/lib/vendor/blamejs/test/20-db.js +65 -2
  206. package/lib/vendor/blamejs/test/helpers/db.js +9 -0
  207. package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
  208. package/lib/vendor/blamejs/test/helpers/services.js +21 -0
  209. package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
  210. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
  211. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
  212. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
  213. package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
  214. package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
  215. package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
  216. package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
  217. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
  218. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
  219. package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
  220. package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
  221. package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
  222. package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
  223. package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
  224. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
  225. package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
  226. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
  227. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
  228. package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
  229. package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
  230. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
  231. package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
  232. package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
  233. package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
  234. package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
  235. package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
  236. package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
  237. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
  238. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
  239. package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
  240. package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
  241. package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
  242. package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
  243. package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
  244. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
  245. package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
  246. package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
  247. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
  248. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1120 -14
  249. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
  250. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
  251. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
  252. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
  253. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
  254. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
  255. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
  256. package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
  257. package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
  258. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
  259. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
  262. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
  271. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
  272. package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
  273. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
  277. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
  278. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
  281. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
  282. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
  283. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
  284. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
  291. package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +309 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
  302. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
  308. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
  310. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
  311. package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
  312. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
  313. package/lib/vendor/blamejs/test/smoke.js +79 -21
  314. package/package.json +1 -1
  315. package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
  316. package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
  317. package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
  318. package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
  319. package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
  320. package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
  321. package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
  322. package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
  323. package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
  324. package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
  325. package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
  326. package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
  327. package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
  328. package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
  329. package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
  330. package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
  331. package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
  332. package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
  333. package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
  334. package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
  335. package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
  336. package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
@@ -57,13 +57,63 @@
57
57
  * Audit: every limit hit emits system.ratelimit.block with the key + path.
58
58
  */
59
59
  var C = require("../constants");
60
+ var frameworkSchema = require("../framework-schema");
60
61
  var lazyRequire = require("../lazy-require");
61
62
  var requestHelpers = require("../request-helpers");
62
63
  var safeAsync = require("../safe-async");
64
+ var sql = require("../sql");
63
65
  var validateOpts = require("../validate-opts");
64
66
  var clusterStorage = require("../cluster-storage");
65
67
  var denyResponse = require("./deny-response").denyResponse;
66
68
 
69
+ // Cluster-backend table — resolved through frameworkSchema.tableName so a
70
+ // configured table prefix (b.frameworkSchema.setTablePrefix) is honored.
71
+ // The name is identity-mapped in LOCAL_TO_EXTERNAL, so clusterStorage's
72
+ // resolveTables leaves it untouched at dispatch and the resolved name is
73
+ // what reaches the backend on both single-node + cluster sides.
74
+ var RATE_LIMIT_TABLE = "_blamejs_rate_limit_counters"; // allow:hand-rolled-sql — canonical logical table-name declaration
75
+ function _rateLimitSqlTable() { return frameworkSchema.tableName(RATE_LIMIT_TABLE); }
76
+
77
+ // b.sql opts for every cluster-backend statement: thread the ACTIVE backend
78
+ // dialect (clusterStorage.dialect() — "sqlite" single-node, "postgres" |
79
+ // "mysql" in cluster mode) so the emitted identifier quoting and dialect
80
+ // idioms (ON CONFLICT ... DO UPDATE vs ON DUPLICATE KEY UPDATE) match the
81
+ // backend the SQL dispatches to. b.sql defaults to "sqlite", which works on
82
+ // Postgres only by accident (both double-quote identifiers) and emits the
83
+ // wrong quoting + ON CONFLICT (which MySQL rejects) on MySQL.
84
+ // clusterStorage.execute still rewrites table names + translates `?`
85
+ // placeholders at dispatch; this controls only the builder-side quoting +
86
+ // idiom selection.
87
+ function _rateLimitSqlOpts() { return { dialect: clusterStorage.dialect() }; }
88
+
89
+ // Dialect-aware references for the conflict-action CASE expressions in
90
+ // take(). The fixed-window counter's update is per-column conditional (a new
91
+ // window resets count to 1; the same window increments), so it can't reduce
92
+ // to doUpdateFromExcluded — it needs a CASE that reads BOTH the proposed row
93
+ // and the existing row. Those two references are spelled differently per
94
+ // dialect and b.sql passes a doUpdate({col: rawExpr}) expression through
95
+ // verbatim (it is NOT EXCLUDED->VALUES translated on MySQL), so the caller
96
+ // must emit the dialect-correct tokens itself:
97
+ // - proposed-row column: EXCLUDED."<col>" (Postgres/SQLite) vs
98
+ // VALUES(`<col>`) (MySQL ON DUPLICATE KEY UPDATE)
99
+ // - existing-row column: "<table>"."<col>" (Postgres/SQLite) vs
100
+ // `<table>`.`<col>` (MySQL)
101
+ // Identifiers here are framework-controlled constants (the table name + the
102
+ // three counter columns), never operator input, so the inline quoting is
103
+ // closed over a fixed set of names.
104
+ function _conflictRefs(dialect, table) {
105
+ if (dialect === "mysql") {
106
+ return {
107
+ proposed: function (col) { return "VALUES(`" + col + "`)"; },
108
+ existing: function (col) { return "`" + table + "`.`" + col + "`"; },
109
+ };
110
+ }
111
+ return {
112
+ proposed: function (col) { return "EXCLUDED.\"" + col + "\""; },
113
+ existing: function (col) { return "\"" + table + "\".\"" + col + "\""; },
114
+ };
115
+ }
116
+
67
117
  var audit = lazyRequire(function () { return require("../audit"); });
68
118
  var logger = lazyRequire(function () { return require("../log").boot("rate-limit"); });
69
119
 
@@ -260,10 +310,10 @@ function _clusterBackend(opts) {
260
310
  if (now - lastPruneAt < pruneIntervalMs) return;
261
311
  lastPruneAt = now;
262
312
  var cutoff = now - windowMs;
263
- clusterStorage.execute(
264
- "DELETE FROM _blamejs_rate_limit_counters WHERE windowStart < ?",
265
- [cutoff]
266
- ).catch(function (e) {
313
+ var built = sql.delete(_rateLimitSqlTable(), _rateLimitSqlOpts())
314
+ .where("windowStart", "<", cutoff)
315
+ .toSql();
316
+ clusterStorage.execute(built.sql, built.params).catch(function (e) {
267
317
  try {
268
318
  logger().warn("rate-limit prune failed: " + ((e && e.message) || String(e)));
269
319
  } catch (_e) { /* logger best-effort */ }
@@ -274,29 +324,49 @@ function _clusterBackend(opts) {
274
324
  var now = Date.now();
275
325
  var windowStart = Math.floor(now / windowMs) * windowMs;
276
326
 
277
- // Atomic increment: a fresh window resets count to 1; an existing
278
- // row in the same window gets count + 1. Postgres + SQLite both
279
- // support ON CONFLICT...DO UPDATE...RETURNING.
280
- var result = await clusterStorage.execute(
281
- "INSERT INTO _blamejs_rate_limit_counters (key, windowStart, count) " +
282
- "VALUES (?, ?, 1) " +
283
- "ON CONFLICT (key) DO UPDATE SET " +
284
- " count = CASE " +
285
- " WHEN excluded.windowStart > _blamejs_rate_limit_counters.windowStart " +
286
- " THEN 1 " +
287
- " ELSE _blamejs_rate_limit_counters.count + 1 " +
288
- " END, " +
289
- " windowStart = CASE " +
290
- " WHEN excluded.windowStart > _blamejs_rate_limit_counters.windowStart " +
291
- " THEN excluded.windowStart " +
292
- " ELSE _blamejs_rate_limit_counters.windowStart " +
293
- " END " +
294
- "RETURNING count, windowStart",
295
- [key, windowStart]
296
- );
297
- var row = result.rows && result.rows[0];
298
- var count = row ? row.count : 1;
299
- var rowWindow = row ? row.windowStart : windowStart;
327
+ // Atomic increment: a fresh window resets count to 1; an existing row in
328
+ // the same window gets count + 1. The per-column conflict action is a
329
+ // CASE that reads the proposed row AND the existing row, so it goes
330
+ // through the STRUCTURED upsert().doUpdate({...}) form with the dialect
331
+ // threaded b.sql then renders ON CONFLICT...DO UPDATE...RETURNING
332
+ // (Postgres/SQLite) or ON DUPLICATE KEY UPDATE + a readback SELECT
333
+ // (MySQL). The CASE bodies spell the proposed-row (EXCLUDED / VALUES())
334
+ // and existing-row (table self-reference) tokens per dialect via
335
+ // _conflictRefs so the same logic compiles on every backend. No `?` in
336
+ // the CASE bodies; the count seed of 1 binds as the third inserted value.
337
+ var t = _rateLimitSqlTable();
338
+ var dialect = clusterStorage.dialect();
339
+ var refs = _conflictRefs(dialect, t);
340
+ var newerWindow = refs.proposed("windowStart") + " > " + refs.existing("windowStart");
341
+ var countExpr = "CASE WHEN " + newerWindow + " THEN 1 ELSE " +
342
+ refs.existing("count") + " + 1 END";
343
+ var windowExpr = "CASE WHEN " + newerWindow + " THEN " + refs.proposed("windowStart") +
344
+ " ELSE " + refs.existing("windowStart") + " END";
345
+ var built = sql.upsert(t, _rateLimitSqlOpts())
346
+ .columns(["key", "windowStart", "count"])
347
+ .values({ key: key, windowStart: windowStart, count: 1 })
348
+ .onConflict(["key"])
349
+ .doUpdate({ count: countExpr, windowStart: windowExpr })
350
+ .returning(["count", "windowStart"])
351
+ .toSql();
352
+ var row;
353
+ if (built.readbackSql) {
354
+ // MySQL: ON DUPLICATE KEY UPDATE has no RETURNING. Run the upsert,
355
+ // then the readback SELECT b.sql emits (keyed on the conflict key) to
356
+ // learn the post-upsert count/windowStart. clusterStorage.execute
357
+ // coerces the framework int columns (count/windowStart) back to JS
358
+ // numbers on both reads.
359
+ await clusterStorage.execute(built.sql, built.params);
360
+ var readback = await clusterStorage.execute(built.readbackSql.sql, built.readbackSql.params);
361
+ row = readback.rows && readback.rows[0];
362
+ } else {
363
+ var result = await clusterStorage.execute(built.sql, built.params);
364
+ row = result.rows && result.rows[0];
365
+ }
366
+ // count/windowStart are framework int columns coerced to JS numbers by
367
+ // clusterStorage; the absent-row fall-back keeps the verdict math finite.
368
+ var count = row ? Number(row.count) : 1;
369
+ var rowWindow = row ? Number(row.windowStart) : windowStart;
300
370
 
301
371
  _maybePrune();
302
372
 
@@ -318,10 +388,10 @@ function _clusterBackend(opts) {
318
388
  }
319
389
 
320
390
  async function reset(key) {
321
- await clusterStorage.execute(
322
- "DELETE FROM _blamejs_rate_limit_counters WHERE key = ?",
323
- [key]
324
- );
391
+ var built = sql.delete(_rateLimitSqlTable(), _rateLimitSqlOpts())
392
+ .where("key", key)
393
+ .toSql();
394
+ await clusterStorage.execute(built.sql, built.params);
325
395
  }
326
396
 
327
397
  function close() { /* no resources to release */ }
@@ -417,7 +487,7 @@ function create(opts) {
417
487
  // pass "RateLimit-", or a gateway's own prefix. Kept as a matched pair.
418
488
  var headerPrefix = (typeof opts.headerPrefix === "string" && opts.headerPrefix.length > 0)
419
489
  ? opts.headerPrefix : "X-RateLimit-";
420
- var limitHeader = headerPrefix + "Limit";
490
+ var limitHeader = headerPrefix + "Limit"; // allow:hand-rolled-sql — HTTP response-header name (X-RateLimit-Limit), not a SQL LIMIT clause
421
491
  var remainingHeader = headerPrefix + "Remaining";
422
492
  var skipPaths = opts.skipPaths || [];
423
493
  // Throw at create(): each entry must be a string prefix or a RegExp.
@@ -10,8 +10,12 @@
10
10
  * Referrer-Policy: no-referrer — don't leak full URL to outbound links
11
11
  * Permissions-Policy — disable common-attack APIs (camera, geolocation, payment, etc.)
12
12
  * Cross-Origin-Opener-Policy: same-origin
13
- * Cross-Origin-Embedder-Policy: require-corp / credentialless (off by default — breaks images from CDNs; credentialless is the
14
- * CR 2024-12 relaxed mode that lets cross-origin no-cors requests load without CORP markers as long as they don't carry credentials)
13
+ * Cross-Origin-Embedder-Policy: credentialless (default-onwith COOP
14
+ * same-origin this yields cross-origin isolation; credentialless is the
15
+ * relaxed enforcing mode that lets cross-origin no-cors requests load
16
+ * without CORP markers as long as they don't carry credentials, so CDN
17
+ * images/fonts keep working. Pass coep: "require-corp" to tighten, or
18
+ * coep: false to disable.)
15
19
  * Cross-Origin-Resource-Policy: same-origin
16
20
  * Origin-Agent-Cluster: ?1 — origin-keyed agent cluster; extra process isolation
17
21
  * X-DNS-Prefetch-Control: off — don't pre-resolve DNS for off-page links
@@ -173,8 +177,9 @@ function _validatePermissionsPolicy(value) {
173
177
  * nosniff, X-Frame-Options DENY, Referrer-Policy no-referrer, an
174
178
  * extensive Permissions-Policy denylist (camera / geolocation /
175
179
  * payment / Privacy-Sandbox attribution-reporting / bluetooth /
176
- * etc.), COOP same-origin, CORP same-origin, Origin-Agent-Cluster
177
- * `?1`, and a strict default CSP with `require-trusted-types-for
180
+ * etc.), COOP same-origin, COEP credentialless (cross-origin isolation
181
+ * on by default; pass `coep: false` to disable), CORP same-origin,
182
+ * Origin-Agent-Cluster `?1`, and a strict default CSP with `require-trusted-types-for
178
183
  * 'script'`. Each header can be softened by passing the option
179
184
  * value or disabled by passing `false`. Mount FIRST (after
180
185
  * `requestId`) so headers are set before any response could be
@@ -233,7 +238,18 @@ function create(opts) {
233
238
  var refPolicy = opts.referrerPolicy === undefined ? "no-referrer" : opts.referrerPolicy;
234
239
  var permPolicy = opts.permissionsPolicy === undefined ? DEFAULT_PERMISSIONS.join(", ") : opts.permissionsPolicy;
235
240
  var coop = opts.coop === undefined ? "same-origin" : opts.coop;
236
- var coep = opts.coep === undefined ? false : opts.coep;
241
+ // COEP default-on (v0.15.0): emit Cross-Origin-Embedder-Policy:
242
+ // credentialless. With COOP same-origin this completes cross-origin
243
+ // isolation (crossOriginIsolated === true), re-enabling SharedArrayBuffer
244
+ // / high-resolution timers while closing the Spectre-class cross-origin
245
+ // read surface. `credentialless` (HTML spec, shipped Chrome 110+) is the
246
+ // least-breaking enforcing mode: cross-origin no-cors subresources (CDN
247
+ // images, fonts) still load — they're fetched WITHOUT credentials rather
248
+ // than requiring an explicit CORP/CORS opt-in, so existing pages keep
249
+ // working where `require-corp` would have broken them. Operators serving
250
+ // credentialed cross-origin subresources pass coep: "require-corp" (and
251
+ // add CORP/CORS headers), or coep: false to opt out of COEP entirely.
252
+ var coep = opts.coep === undefined ? "credentialless" : opts.coep;
237
253
  var corp = opts.corp === undefined ? "same-origin" : opts.corp;
238
254
  var oac = opts.originAgentCluster === undefined ? "?1" : opts.originAgentCluster;
239
255
  var dpc = opts.dnsPrefetchControl === undefined ? "off" : opts.dnsPrefetchControl;
@@ -41,10 +41,13 @@
41
41
  var nodePath = require("node:path");
42
42
  var atomicFile = require("./atomic-file");
43
43
  var dbSchema = require("./db-schema");
44
+ var frameworkSchema = require("./framework-schema");
44
45
  var lazyRequire = require("./lazy-require");
45
46
  var { boot } = require("./log");
46
47
  var migrationFiles = require("./migration-files");
47
48
  var numericBounds = require("./numeric-bounds");
49
+ var safeSql = require("./safe-sql");
50
+ var sql = require("./sql");
48
51
  var db = lazyRequire(function () { return require("./db"); });
49
52
  var validateOpts = require("./validate-opts");
50
53
  var { FrameworkError } = require("./framework-error");
@@ -60,11 +63,29 @@ class MigrationError extends FrameworkError {
60
63
  }
61
64
  }
62
65
 
63
- var MIGRATIONS_TABLE = "_blamejs_migrations";
64
- // Always interpolate identifiers wrapped in `"..."` so a reserved-word
65
- // or whitespace-bearing name resolves correctly (defense-in-depth even
66
- // though our constant is bare-identifier-shaped).
67
- var Q_MIGRATIONS_TABLE = '"' + MIGRATIONS_TABLE + '"';
66
+ // Logical names; the physical names resolve through
67
+ // frameworkSchema.tableName so a configured table prefix flows here too.
68
+ // SQL is composed with b.sql (quoteName: true) so the resolved name is
69
+ // quoted by construction a reserved-word / whitespace-bearing name
70
+ // still emits a valid `"..."` identifier.
71
+ var MIGRATIONS_TABLE = "_blamejs_migrations"; // allow:hand-rolled-sql — logical name declaration; physical name + prefix resolve via frameworkSchema.tableName below
72
+ function _migrationsTable() { return frameworkSchema.tableName(MIGRATIONS_TABLE); }
73
+ // b.sql opts for the migration bookkeeping statements. db.prepare /
74
+ // runSqlOnHandle run these directly against the handle (never
75
+ // clusterStorage), so the dialect must match the handle: db.from()'s local
76
+ // node:sqlite default, or an operator's own Postgres / MySQL handle (which
77
+ // declares `handle.dialect`). The handle-dialect / opts / key-text-type
78
+ // resolution is shared with db-schema's reconciler + seeders.js, so it is
79
+ // composed from db-schema rather than re-derived here. The historical
80
+ // default (sqlite) is byte-identical for every existing local-handle caller.
81
+ var _handleDialect = dbSchema.handleDialect;
82
+ var _sqlOpts = dbSchema.sqlOpts;
83
+ var _keyTextType = dbSchema.keyTextType;
84
+ // A ms-epoch column type. Date.now() exceeds a 32-bit INTEGER, so the
85
+ // lock timestamp needs a 64-bit type on Postgres + MySQL (BIGINT) — b.sql's
86
+ // logical "int" resolves to BIGINT on both and INTEGER on SQLite, so passing
87
+ // the logical name through the handle dialect is enough.
88
+ var _MS_EPOCH_TYPE = "int";
68
89
  // Filename grammar: leading numeric prefix (any width), then '-', then a
69
90
  // non-empty body, then '.js'. Numeric prefix orders execution. Letters
70
91
  // in the body include hyphens, underscores, and alphanumerics; anything
@@ -87,31 +108,36 @@ function _isMigrationFile(name) {
87
108
  var _runSql = dbSchema.runSqlOnHandle;
88
109
 
89
110
  function _ensureTable(db) {
90
- _runSql(db,
91
- "CREATE TABLE IF NOT EXISTS " + Q_MIGRATIONS_TABLE + " (" +
92
- " name TEXT PRIMARY KEY," +
93
- " description TEXT," +
94
- " appliedAt TEXT NOT NULL" +
95
- ")"
96
- );
111
+ _runSql(db, sql.createTable(_migrationsTable(), [
112
+ { name: "name", type: _keyTextType(db), primaryKey: true },
113
+ { name: "description", type: "text" },
114
+ { name: "appliedAt", type: "text", notNull: true },
115
+ ], _sqlOpts(db)).sql);
97
116
  }
98
117
 
99
118
  // Single-row advisory-lock table. Two processes running `migrate up`
100
119
  // concurrently against the same DB race on this table: the winner of
101
120
  // the INSERT acquires the lock; the loser sees a UNIQUE violation and
102
121
  // the operator gets a clear "lock held by other process" error.
103
- var LOCK_TABLE = "_blamejs_migrations_lock";
104
- var Q_LOCK_TABLE = '"' + LOCK_TABLE + '"';
122
+ var LOCK_TABLE = "_blamejs_migrations_lock"; // allow:hand-rolled-sql — logical name declaration; physical name + prefix resolve via frameworkSchema.tableName below
123
+ function _lockTable() { return frameworkSchema.tableName(LOCK_TABLE); }
105
124
 
106
125
  function _ensureLockTable(db) {
107
- _runSql(db,
108
- "CREATE TABLE IF NOT EXISTS " + Q_LOCK_TABLE + " (" +
109
- " scope TEXT PRIMARY KEY," +
110
- " lockedAt INTEGER NOT NULL," +
111
- " lockedBy TEXT NOT NULL," +
112
- " CHECK (scope = 'lock')" +
113
- ")"
114
- );
126
+ // The single-row invariant (CHECK scope = 'lock') is a static,
127
+ // framework-controlled column constraint b.sql guards the verbatim
128
+ // fragment (allowLiterals) and quotes the column by construction. The
129
+ // CHECK references `scope` with the handle's identifier quoting (backtick
130
+ // on mysql) so the constraint parses on every dialect. lockedAt is an
131
+ // ms-epoch value (`int` BIGINT on Postgres/MySQL, INTEGER on SQLite);
132
+ // a 32-bit INTEGER would overflow Date.now() and make the lock
133
+ // unacquirable on Postgres.
134
+ var dialect = _handleDialect(db);
135
+ var scopeCheck = "CHECK (" + safeSql.quoteIdentifier("scope", dialect, { allowReserved: true }) + " = 'lock')";
136
+ _runSql(db, sql.createTable(_lockTable(), [
137
+ { name: "scope", type: _keyTextType(db), primaryKey: true, constraints: scopeCheck },
138
+ { name: "lockedAt", type: _MS_EPOCH_TYPE, notNull: true },
139
+ { name: "lockedBy", type: "text", notNull: true },
140
+ ], _sqlOpts(db)).sql);
115
141
  }
116
142
 
117
143
  function _lockHolderId() {
@@ -139,23 +165,24 @@ function _acquireLock(db, opts) {
139
165
  } else {
140
166
  staleAfterMs = opts.staleAfterMs;
141
167
  }
168
+ var insertLock = sql.insert(_lockTable(), _sqlOpts(db))
169
+ .values({ scope: "lock", lockedAt: nowMs, lockedBy: holder }).toSql();
142
170
  // Try to insert; if there's a stale lock, optionally force-replace it.
143
171
  try {
144
- db.prepare(
145
- "INSERT INTO " + Q_LOCK_TABLE + " (scope, lockedAt, lockedBy) VALUES ('lock', ?, ?)"
146
- ).run(nowMs, holder);
172
+ var insStmt = db.prepare(insertLock.sql);
173
+ insStmt.run.apply(insStmt, insertLock.params);
147
174
  return holder;
148
175
  } catch {
149
176
  // PRIMARY KEY conflict → existing lock. Inspect it.
150
- var existing = db.prepare(
151
- "SELECT lockedAt, lockedBy FROM " + Q_LOCK_TABLE + " WHERE scope = 'lock'"
152
- ).get();
177
+ var selExisting = sql.select(_lockTable(), _sqlOpts(db))
178
+ .columns(["lockedAt", "lockedBy"]).where("scope", "lock").toSql();
179
+ var selStmt = db.prepare(selExisting.sql);
180
+ var existing = selStmt.get.apply(selStmt, selExisting.params);
153
181
  if (!existing) {
154
182
  // Race window between INSERT failure and SELECT — try once more.
155
183
  try {
156
- db.prepare(
157
- "INSERT INTO " + Q_LOCK_TABLE + " (scope, lockedAt, lockedBy) VALUES ('lock', ?, ?)"
158
- ).run(nowMs, holder);
184
+ var retryStmt = db.prepare(insertLock.sql);
185
+ retryStmt.run.apply(retryStmt, insertLock.params);
159
186
  return holder;
160
187
  } catch (e2) {
161
188
  throw new MigrationError("migrations/lock-busy",
@@ -165,25 +192,32 @@ function _acquireLock(db, opts) {
165
192
  }
166
193
  var ageMs = nowMs - Number(existing.lockedAt);
167
194
  if (staleAfterMs > 0 && ageMs > staleAfterMs) {
168
- // Force-replace the stale lock. Requires DELETE + INSERT in a
169
- // single transaction so the next process can't slip in between.
170
- _runSql(db, "BEGIN IMMEDIATE");
195
+ // Force-replace the stale lock. The DELETE + INSERT run in a single
196
+ // transaction so the next process can't slip in between. The
197
+ // transaction boundary is dialect-aware: only SQLite has the
198
+ // `BEGIN IMMEDIATE` write-lock-up-front form — Postgres + MySQL
199
+ // reject the `IMMEDIATE` keyword, so the shared runInTransaction
200
+ // helper emits a plain portable `BEGIN`/`COMMIT`/`ROLLBACK` there.
201
+ var lockMode = _handleDialect(db) === "sqlite" ? "IMMEDIATE" : null;
171
202
  try {
172
- db.prepare("DELETE FROM " + Q_LOCK_TABLE + " WHERE scope = 'lock' AND lockedAt = ?")
173
- .run(existing.lockedAt);
174
- db.prepare(
175
- "INSERT INTO " + Q_LOCK_TABLE + " (scope, lockedAt, lockedBy) VALUES ('lock', ?, ?)"
176
- ).run(nowMs, holder);
177
- _runSql(db, "COMMIT");
178
- return holder;
203
+ return dbSchema.runInTransaction(db, function () {
204
+ var delStale = sql.delete(_lockTable(), _sqlOpts(db))
205
+ .where("scope", "lock").where("lockedAt", existing.lockedAt).toSql();
206
+ var delStaleStmt = db.prepare(delStale.sql);
207
+ delStaleStmt.run.apply(delStaleStmt, delStale.params);
208
+ var replStmt = db.prepare(insertLock.sql);
209
+ replStmt.run.apply(replStmt, insertLock.params);
210
+ return holder;
211
+ }, {
212
+ lockMode: lockMode,
213
+ onRollbackFail: function (rollbackErr) {
214
+ log.debug("rollback-failed", {
215
+ op: "lock-stale-replace",
216
+ error: rollbackErr && rollbackErr.message,
217
+ });
218
+ },
219
+ });
179
220
  } catch (forceErr) {
180
- try { _runSql(db, "ROLLBACK"); }
181
- catch (rollbackErr) {
182
- log.debug("rollback-failed", {
183
- op: "lock-stale-replace",
184
- error: rollbackErr && rollbackErr.message,
185
- });
186
- }
187
221
  throw new MigrationError("migrations/lock-stale-replace-failed",
188
222
  "could not replace stale lock: " + ((forceErr && forceErr.message) || String(forceErr)),
189
223
  true);
@@ -202,9 +236,10 @@ function _releaseLock(db, holder) {
202
236
  // shouldn't have its lock cleared by an unrelated next deploy unless
203
237
  // the operator explicitly used the staleAfterMs nodePath.
204
238
  try {
205
- db.prepare(
206
- "DELETE FROM " + Q_LOCK_TABLE + " WHERE scope = 'lock' AND lockedBy = ?"
207
- ).run(holder);
239
+ var rel = sql.delete(_lockTable(), _sqlOpts(db))
240
+ .where("scope", "lock").where("lockedBy", holder).toSql();
241
+ var relStmt = db.prepare(rel.sql);
242
+ relStmt.run.apply(relStmt, rel.params);
208
243
  } catch (_e) { /* best-effort release; operator can DELETE manually */ }
209
244
  }
210
245
 
@@ -271,10 +306,11 @@ function create(opts) {
271
306
  function _appliedRows() {
272
307
  var db = _resolveDb(opts);
273
308
  _ensureTable(db);
274
- return db.prepare(
275
- "SELECT name, description, appliedAt FROM " + Q_MIGRATIONS_TABLE +
276
- " ORDER BY appliedAt ASC, name ASC"
277
- ).all();
309
+ var q = sql.select(_migrationsTable(), _sqlOpts(db))
310
+ .columns(["name", "description", "appliedAt"])
311
+ .orderBy("appliedAt", "asc").orderBy("name", "asc").toSql();
312
+ var stmt = db.prepare(q.sql);
313
+ return stmt.all.apply(stmt, q.params);
278
314
  }
279
315
 
280
316
  function status() {
@@ -293,8 +329,10 @@ function create(opts) {
293
329
  var db = _resolveDb(opts);
294
330
  _ensureTable(db);
295
331
  return _withLock(db, opts, function () {
332
+ var namesQ = sql.select(_migrationsTable(), _sqlOpts(db)).columns(["name"]).toSql();
333
+ var namesStmt = db.prepare(namesQ.sql);
296
334
  var appliedSet = new Set(
297
- db.prepare("SELECT name FROM " + Q_MIGRATIONS_TABLE).all()
335
+ namesStmt.all.apply(namesStmt, namesQ.params)
298
336
  .map(function (r) { return r.name; })
299
337
  );
300
338
  var files = _list(dir);
@@ -307,10 +345,11 @@ function create(opts) {
307
345
  try {
308
346
  _txn(db, function () {
309
347
  mod.up(db);
310
- db.prepare(
311
- "INSERT INTO " + Q_MIGRATIONS_TABLE +
312
- " (name, description, appliedAt) VALUES (?, ?, ?)"
313
- ).run(file, mod.description || "", new Date().toISOString());
348
+ var insQ = sql.insert(_migrationsTable(), _sqlOpts(db))
349
+ .values({ name: file, description: mod.description || "",
350
+ appliedAt: new Date().toISOString() }).toSql();
351
+ var insStmt = db.prepare(insQ.sql);
352
+ insStmt.run.apply(insStmt, insQ.params);
314
353
  });
315
354
  } catch (e) {
316
355
  throw new MigrationError("migrations/up-failed",
@@ -336,11 +375,12 @@ function create(opts) {
336
375
  return _withLock(db, opts, function () {
337
376
  // Most-recent applied first (reverse chronological by appliedAt
338
377
  // then by name as a stable tiebreaker for fixtures with identical
339
- // timestamps).
340
- var rows = db.prepare(
341
- "SELECT name FROM " + Q_MIGRATIONS_TABLE +
342
- " ORDER BY appliedAt DESC, name DESC LIMIT ?"
343
- ).all(steps);
378
+ // timestamps). steps is a validated positive integer, so b.sql
379
+ // inlines the LIMIT.
380
+ var downQ = sql.select(_migrationsTable(), _sqlOpts(db)).columns(["name"])
381
+ .orderBy("appliedAt", "desc").orderBy("name", "desc").limit(steps).toSql();
382
+ var downStmt = db.prepare(downQ.sql);
383
+ var rows = downStmt.all.apply(downStmt, downQ.params);
344
384
 
345
385
  var reverted = [];
346
386
  for (var i = 0; i < rows.length; i++) {
@@ -355,7 +395,9 @@ function create(opts) {
355
395
  try {
356
396
  _txn(db, function () {
357
397
  mod.down(db);
358
- db.prepare("DELETE FROM " + Q_MIGRATIONS_TABLE + " WHERE name = ?").run(file);
398
+ var delQ = sql.delete(_migrationsTable(), _sqlOpts(db)).where("name", file).toSql();
399
+ var delStmt = db.prepare(delQ.sql);
400
+ delStmt.run.apply(delStmt, delQ.params);
359
401
  });
360
402
  } catch (e) {
361
403
  throw new MigrationError("migrations/down-failed",
@@ -72,6 +72,13 @@ function _probeHttp(target, timeoutMs) {
72
72
  url: target.url,
73
73
  method: target.method || "GET",
74
74
  timeoutMs: timeoutMs,
75
+ // Forward the target's protocol/host allowlists so an operator who
76
+ // opts a cleartext http:// heartbeat in (allowedProtocols:
77
+ // b.safeUrl.ALLOW_HTTP_ALL) is honoured. Left undefined, httpClient
78
+ // applies its https-only default (ALLOW_HTTP_TLS) — so an http://
79
+ // target with no opt-in is still rejected, not silently probed.
80
+ allowedProtocols: target.allowedProtocols,
81
+ allowedHosts: target.allowedHosts,
75
82
  allowInternal: target.allowInternal === true ? true : target.allowInternal,
76
83
  });
77
84
  p.then(function (res) {
@@ -20,6 +20,11 @@ var DEFAULT_HTTPS_PORT = 443; // RFC 9110 §4.2.2
20
20
  var DEFAULT_HTTP_PORT = C.BYTES.bytes(80); // RFC 9110 §4.2.1
21
21
 
22
22
  var observability = lazyRequire(function () { return require("./observability"); });
23
+ // Lazy so pqc-agent's TLS/audit graph isn't pulled into every process that
24
+ // imports network-proxy but never proxies an https upstream. Used only to audit
25
+ // a classical-group fallback on a proxy-tunneled TLS handshake (the direct path
26
+ // audits in pqc-agent.create()).
27
+ var pqcAgent = lazyRequire(function () { return require("./pqc-agent"); });
23
28
 
24
29
  var STATE = {
25
30
  http: null,
@@ -167,6 +172,13 @@ function _connectThroughTunnel(proxyUrl, targetHost, targetPort, callback) {
167
172
  function done(err, sock) { if (settled) return; settled = true; callback(err, sock); }
168
173
  proxySocket.on("error", function (e) { done(e); });
169
174
  proxySocket.on(proxyUrl.protocol === "https:" ? "secureConnect" : "connect", function () {
175
+ if (proxyUrl.protocol === "https:") {
176
+ // The CONNECT-tunnel leg to an https proxy is itself a TLS handshake;
177
+ // audit a classical fallback to the proxy too, not only to the upstream.
178
+ pqcAgent()._auditClassicalDowngrade(proxySocket, {
179
+ host: proxyUrl.hostname, port: proxyPort,
180
+ });
181
+ }
170
182
  var lines = [
171
183
  "CONNECT " + targetHost + ":" + targetPort + " HTTP/1.1",
172
184
  "Host: " + targetHost + ":" + targetPort,
@@ -218,7 +230,18 @@ function agentFor(targetUrl) {
218
230
  minVersion: "TLSv1.3",
219
231
  ecdhCurve: C.TLS_GROUP_CURVE_STR,
220
232
  ALPNProtocols: options.ALPNProtocols,
221
- }, function () { cb(null, secure); });
233
+ }, function () {
234
+ // Audit a classical-group fallback on the upstream (target) handshake
235
+ // reached through the proxy tunnel, so the "every outbound TLS path
236
+ // emits tls.classical_downgrade" guarantee holds for proxied requests
237
+ // too (the direct path audits in pqc-agent.create). Drop-silent; the
238
+ // handshake itself is unchanged (still hybrid-preferred TLSv1.3).
239
+ pqcAgent()._auditClassicalDowngrade(secure, {
240
+ host: options.servername || options.host,
241
+ port: options.port,
242
+ });
243
+ cb(null, secure);
244
+ });
222
245
  secure.on("error", function (e) { cb(e); });
223
246
  });
224
247
  };
@@ -43,10 +43,30 @@
43
43
 
44
44
  var clusterStorage = require("./cluster-storage");
45
45
  var C = require("./constants");
46
+ var frameworkSchema = require("./framework-schema");
46
47
  var safeAsync = require("./safe-async");
48
+ var sql = require("./sql");
47
49
  var { defineClass } = require("./framework-error");
48
50
  var { boundedMap } = require("./bounded-map");
49
51
 
52
+ // Cluster-backend table — resolved through frameworkSchema.tableName so a
53
+ // configured table prefix (b.frameworkSchema.setTablePrefix) is honored.
54
+ // The name is identity-mapped in LOCAL_TO_EXTERNAL, so clusterStorage's
55
+ // resolveTables leaves it untouched at dispatch and the resolved name is
56
+ // what reaches the backend on both sides.
57
+ var NONCE_TABLE = "_blamejs_api_encrypt_nonces"; // allow:hand-rolled-sql — canonical logical table-name declaration
58
+
59
+ // b.sql opts for every cluster-backend statement: thread the ACTIVE backend
60
+ // dialect (clusterStorage.dialect() — "sqlite" single-node, "postgres" |
61
+ // "mysql" in cluster mode) so the emitted identifier quoting and dialect
62
+ // idioms (ON CONFLICT vs ON DUPLICATE KEY) match the backend the SQL
63
+ // dispatches to. Defaulting to "sqlite" works on Postgres only by accident
64
+ // (both double-quote identifiers) and emits invalid quoting + ON CONFLICT on
65
+ // MySQL. clusterStorage.execute still rewrites table names + translates `?`
66
+ // placeholders at dispatch; this controls only the builder-side quoting +
67
+ // idiom selection.
68
+ function _nonceSqlOpts() { return { dialect: clusterStorage.dialect() }; }
69
+
50
70
  var NonceStoreError = defineClass("NonceStoreError");
51
71
 
52
72
  var DEFAULT_SWEEP_INTERVAL_MS = C.TIME.minutes(5);
@@ -148,19 +168,21 @@ function _clusterBackend(_opts) {
148
168
  // (someone else already inserted the same nonce, i.e. replay).
149
169
  // The middleware hashes the raw nonce before passing it here so
150
170
  // the table only ever sees hashes, not the originals.
151
- var result = await clusterStorage.execute(
152
- "INSERT INTO _blamejs_api_encrypt_nonces (nonceHash, expireAt) " +
153
- "VALUES (?, ?) ON CONFLICT (nonceHash) DO NOTHING",
154
- [nonce, expireAt]
155
- );
171
+ var built = sql.upsert(frameworkSchema.tableName(NONCE_TABLE), _nonceSqlOpts())
172
+ .columns(["nonceHash", "expireAt"])
173
+ .values({ nonceHash: nonce, expireAt: expireAt })
174
+ .onConflict(["nonceHash"])
175
+ .doNothing()
176
+ .toSql();
177
+ var result = await clusterStorage.execute(built.sql, built.params);
156
178
  return (result && result.rowCount > 0);
157
179
  }
158
180
 
159
181
  async function purgeExpired() {
160
- var result = await clusterStorage.execute(
161
- "DELETE FROM _blamejs_api_encrypt_nonces WHERE expireAt <= ?",
162
- [Date.now()]
163
- );
182
+ var built = sql.delete(frameworkSchema.tableName(NONCE_TABLE), _nonceSqlOpts())
183
+ .where("expireAt", "<=", Date.now())
184
+ .toSql();
185
+ var result = await clusterStorage.execute(built.sql, built.params);
164
186
  return (result && result.rowCount) || 0;
165
187
  }
166
188