@blamejs/blamejs-shop 0.4.30 → 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 (338) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/checkout.js +8 -0
  4. package/lib/order.js +71 -11
  5. package/lib/vendor/MANIFEST.json +392 -278
  6. package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
  7. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
  8. package/lib/vendor/blamejs/.gitignore +6 -0
  9. package/lib/vendor/blamejs/CHANGELOG.md +26 -0
  10. package/lib/vendor/blamejs/MIGRATING.md +43 -0
  11. package/lib/vendor/blamejs/README.md +8 -6
  12. package/lib/vendor/blamejs/SECURITY.md +19 -3
  13. package/lib/vendor/blamejs/api-snapshot.json +2190 -664
  14. package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
  15. package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
  16. package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
  17. package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
  18. package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
  19. package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
  20. package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
  21. package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
  22. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
  23. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
  24. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
  25. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
  26. package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
  27. package/lib/vendor/blamejs/index.js +4 -0
  28. package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
  29. package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
  30. package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
  31. package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
  32. package/lib/vendor/blamejs/lib/api-key.js +158 -77
  33. package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
  34. package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
  35. package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
  36. package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
  37. package/lib/vendor/blamejs/lib/audit.js +259 -123
  38. package/lib/vendor/blamejs/lib/auth/oauth.js +53 -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 +31 -5
  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 +206 -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/crypto-field.js +916 -156
  55. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
  56. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
  57. package/lib/vendor/blamejs/lib/db-query.js +882 -260
  58. package/lib/vendor/blamejs/lib/db-schema.js +228 -44
  59. package/lib/vendor/blamejs/lib/db.js +249 -99
  60. package/lib/vendor/blamejs/lib/dsr.js +385 -55
  61. package/lib/vendor/blamejs/lib/error-page.js +14 -1
  62. package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
  63. package/lib/vendor/blamejs/lib/external-db.js +549 -34
  64. package/lib/vendor/blamejs/lib/file-upload.js +52 -7
  65. package/lib/vendor/blamejs/lib/framework-error.js +20 -1
  66. package/lib/vendor/blamejs/lib/framework-files.js +73 -0
  67. package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
  68. package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
  69. package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
  70. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  71. package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
  72. package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
  73. package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
  74. package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
  75. package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
  76. package/lib/vendor/blamejs/lib/guard-email.js +47 -69
  77. package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
  78. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
  79. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
  80. package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
  81. package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
  82. package/lib/vendor/blamejs/lib/guard-html.js +53 -108
  83. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
  84. package/lib/vendor/blamejs/lib/guard-image.js +46 -103
  85. package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
  86. package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
  87. package/lib/vendor/blamejs/lib/guard-json.js +38 -108
  88. package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
  89. package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
  90. package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
  91. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
  92. package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
  93. package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
  94. package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
  95. package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
  96. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
  97. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
  98. package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
  99. package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
  100. package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
  101. package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
  102. package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
  103. package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
  104. package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
  105. package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
  106. package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
  107. package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
  108. package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
  109. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
  110. package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
  111. package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
  112. package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
  113. package/lib/vendor/blamejs/lib/guard-template.js +35 -172
  114. package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
  115. package/lib/vendor/blamejs/lib/guard-time.js +32 -154
  116. package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
  117. package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
  118. package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
  119. package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
  120. package/lib/vendor/blamejs/lib/http-client.js +37 -9
  121. package/lib/vendor/blamejs/lib/inbox.js +120 -107
  122. package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
  123. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
  124. package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
  125. package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
  126. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
  127. package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
  128. package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
  129. package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
  130. package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
  131. package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
  132. package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
  133. package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
  134. package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
  135. package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
  136. package/lib/vendor/blamejs/lib/mail-store.js +293 -154
  137. package/lib/vendor/blamejs/lib/mail.js +8 -4
  138. package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
  139. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
  140. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
  141. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
  142. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
  143. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
  144. package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
  145. package/lib/vendor/blamejs/lib/migrations.js +108 -66
  146. package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
  147. package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
  148. package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
  149. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
  150. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
  151. package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
  152. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
  153. package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
  154. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
  155. package/lib/vendor/blamejs/lib/observability.js +124 -0
  156. package/lib/vendor/blamejs/lib/otel-export.js +12 -3
  157. package/lib/vendor/blamejs/lib/outbox.js +184 -83
  158. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
  159. package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
  160. package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
  161. package/lib/vendor/blamejs/lib/queue-local.js +225 -140
  162. package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
  163. package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
  164. package/lib/vendor/blamejs/lib/queue.js +7 -0
  165. package/lib/vendor/blamejs/lib/redact.js +68 -11
  166. package/lib/vendor/blamejs/lib/redis-client.js +160 -31
  167. package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
  168. package/lib/vendor/blamejs/lib/retention.js +101 -40
  169. package/lib/vendor/blamejs/lib/router.js +212 -5
  170. package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
  171. package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
  172. package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
  173. package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
  174. package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
  175. package/lib/vendor/blamejs/lib/safe-url.js +170 -3
  176. package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
  177. package/lib/vendor/blamejs/lib/scheduler.js +35 -12
  178. package/lib/vendor/blamejs/lib/seeders.js +122 -74
  179. package/lib/vendor/blamejs/lib/session-stores.js +42 -14
  180. package/lib/vendor/blamejs/lib/session.js +175 -77
  181. package/lib/vendor/blamejs/lib/sql.js +3842 -0
  182. package/lib/vendor/blamejs/lib/sse.js +26 -0
  183. package/lib/vendor/blamejs/lib/ssrf-guard.js +151 -4
  184. package/lib/vendor/blamejs/lib/static.js +177 -34
  185. package/lib/vendor/blamejs/lib/subject.js +96 -49
  186. package/lib/vendor/blamejs/lib/vault/index.js +3 -2
  187. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
  188. package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
  189. package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
  190. package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
  191. package/lib/vendor/blamejs/lib/websocket.js +35 -5
  192. package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
  193. package/lib/vendor/blamejs/package.json +2 -2
  194. package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
  195. package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
  196. package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
  197. package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
  198. package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
  199. package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
  200. package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
  201. package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
  202. package/lib/vendor/blamejs/scripts/check-services.js +21 -0
  203. package/lib/vendor/blamejs/scripts/gen-migrating.js +51 -0
  204. package/lib/vendor/blamejs/scripts/release.js +398 -38
  205. package/lib/vendor/blamejs/test/00-primitives.js +117 -0
  206. package/lib/vendor/blamejs/test/10-state.js +140 -14
  207. package/lib/vendor/blamejs/test/20-db.js +65 -2
  208. package/lib/vendor/blamejs/test/helpers/db.js +9 -0
  209. package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
  210. package/lib/vendor/blamejs/test/helpers/services.js +21 -0
  211. package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
  212. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
  213. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
  214. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
  215. package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
  216. package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
  217. package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
  218. package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
  219. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
  220. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
  221. package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
  222. package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
  223. package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
  224. package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
  225. package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
  226. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
  227. package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
  228. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
  229. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
  230. package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
  231. package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
  232. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
  233. package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
  234. package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
  235. package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
  236. package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
  237. package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
  238. package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
  239. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
  240. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
  241. package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
  242. package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
  243. package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
  244. package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
  245. package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
  246. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
  247. package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
  248. package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
  249. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
  250. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1120 -14
  251. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
  252. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
  253. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
  254. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
  255. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
  256. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
  257. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
  258. package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
  259. package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
  260. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
  261. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
  262. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
  264. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
  270. package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
  272. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
  273. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
  274. package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
  275. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
  279. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
  280. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
  283. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
  284. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
  285. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
  293. package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +309 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
  302. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
  304. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
  310. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
  312. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
  313. package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
  314. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
  315. package/lib/vendor/blamejs/test/smoke.js +79 -21
  316. package/package.json +1 -1
  317. package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
  318. package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
  319. package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
  320. package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
  321. package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
  322. package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
  323. package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
  324. package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
  325. package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
  326. package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
  327. package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
  328. package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
  329. package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
  330. package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
  331. package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
  332. package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
  333. package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
  334. package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
  335. package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
  336. package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
  337. package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
  338. package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
@@ -11,7 +11,8 @@
11
11
  * node scripts/release.js regen # re-regen CHANGELOG + api-snapshot (after release-notes edits)
12
12
  * node scripts/release.js smoke # SMOKE_PARALLEL=64 + (optional) wiki e2e
13
13
  * node scripts/release.js commit # release branch + signed commit
14
- * node scripts/release.js push # gitleaks + push + open PR
14
+ * node scripts/release.js live-integration # touched-backend live tests
15
+ * node scripts/release.js push # live-integration + gitleaks + push + open PR
15
16
  * node scripts/release.js watch # gh pr checks --watch + flag Codex threads
16
17
  * node scripts/release.js merge # squash-merge if CLEAN + zero unresolved threads
17
18
  * node scripts/release.js tag # signed tag + push tag + verify
@@ -30,6 +31,13 @@
30
31
  * - Git signing config (SSH + allowed_signers + commit/tag.gpgsign)
31
32
  * must be in place. See CLAUDE.md "Release workflow" — one-time
32
33
  * signing setup.
34
+ * - Docker must be running for `push` when the release touches a
35
+ * backend-protocol lib file (S3/SigV4, MySQL, Postgres, Redis,
36
+ * MinIO, SMTP, NTP, DoT, federation/Keycloak, OTel). `push` brings
37
+ * up docker-compose.test.yml and runs the matching live integration
38
+ * tests; an unavailable stack or a failing test refuses the push.
39
+ * This is non-skippable except via an explicit, audited override
40
+ * (--skip-live-integration --live-skip-reason="<why>").
33
41
  *
34
42
  * The judgment-requiring parts stay manual:
35
43
  * - Writing `release-notes/v<next>.json` content.
@@ -249,6 +257,275 @@ function _verifyCommitSignature(label) {
249
257
  _ok(label + " commit signature verified");
250
258
  }
251
259
 
260
+ // ---- Touched-backend live integration ------------------------------------
261
+ //
262
+ // A release that changes the lib code behind a network backend MUST prove
263
+ // itself against a real instance of that backend before it reaches a PR.
264
+ // The class this catches: a change validated only on the host smoke gate
265
+ // (which runs against sqlite + in-memory fakes) that breaks against the
266
+ // live protocol — e.g. a DDL/migration refactor that self-validates on
267
+ // sqlite but emits casing the Postgres wire rejects. Host smoke is green;
268
+ // the regression ships. The fix is to make the matching live test
269
+ // non-skippable on the release path, not advisory.
270
+ //
271
+ // Each backend entry declares:
272
+ // match — lib path substrings (matched against the forward-slashed
273
+ // repo-relative path of every changed file) that mean this
274
+ // backend's protocol surface was touched. A file under
275
+ // lib/object-store/ touches the S3 / Azure / GCS backends;
276
+ // a change to lib/external-db*.js or lib/db-query.js touches
277
+ // the Postgres + MySQL backends; etc.
278
+ // services — the docker-compose.test.yml service names this backend's
279
+ // tests require (informational + used to scope the readiness
280
+ // check; the compose `up --wait` brings up the whole stack).
281
+ // tests — the test/integration/*.test.js file(s) (basename) that
282
+ // exercise this backend live. `test-integration.js` accepts
283
+ // either the bare name or the `.test.js` form.
284
+ //
285
+ // Conservative by construction: when a changed file matches more than one
286
+ // backend, every matching test runs. A shared file (lib/http-client.js,
287
+ // lib/safe-url.js, lib/crypto.js) is referenced by multiple backends on
288
+ // purpose — touching the SigV4 signer or the HTTP client is exactly the
289
+ // kind of cross-cutting change a single-backend smoke can hide.
290
+ var BACKEND_LIVE_MAP = [
291
+ {
292
+ backend: "postgres",
293
+ match: ["lib/external-db", "lib/db-query", "lib/db-schema.js",
294
+ "lib/db-declare", "lib/db-role-context", "lib/cluster-provider-db",
295
+ "lib/cluster-storage", "lib/safe-sql", "lib/db-collection.js"],
296
+ services: ["postgres", "postgres-replica"],
297
+ tests: ["external-db-postgres", "audit-chain-external-db",
298
+ "audit-actor-binding-pg", "distributed-scheduler-fencing-pg"],
299
+ },
300
+ {
301
+ backend: "mysql",
302
+ match: ["lib/external-db", "lib/cluster-provider-db", "lib/cluster-storage",
303
+ "lib/safe-sql"],
304
+ services: ["mysql"],
305
+ tests: ["cluster-provider-mysql"],
306
+ },
307
+ {
308
+ backend: "redis",
309
+ match: ["lib/redis-client", "lib/queue-redis", "lib/pubsub-redis",
310
+ "lib/cache-redis", "lib/queue.js", "lib/cache.js", "lib/pubsub.js",
311
+ "lib/crypto-field"],
312
+ services: ["redis", "redis-tls"],
313
+ tests: ["redis-client-tls", "cache", "queue-redis", "pubsub",
314
+ "redis-reconnect-toxiproxy"],
315
+ },
316
+ {
317
+ backend: "object-store-s3",
318
+ match: ["lib/object-store/sigv4", "lib/object-store/http",
319
+ "lib/object-store/local", "lib/object-store/index.js",
320
+ "lib/queue-sqs", "lib/log-stream-cloudwatch", "lib/backup",
321
+ "lib/restore"],
322
+ services: ["minio", "minio-tls", "localstack", "localstack-tls"],
323
+ tests: ["object-store-sigv4", "object-store-worm-lock",
324
+ "backup-restore-objectstore", "queue-sqs",
325
+ "log-stream-cloudwatch"],
326
+ },
327
+ {
328
+ backend: "object-store-azure",
329
+ match: ["lib/object-store/azure-blob", "lib/object-store/http",
330
+ "lib/object-store/index.js"],
331
+ services: ["azurite"],
332
+ tests: ["object-store-azure"],
333
+ },
334
+ {
335
+ backend: "object-store-gcs",
336
+ match: ["lib/object-store/gcs", "lib/object-store/http",
337
+ "lib/object-store/index.js"],
338
+ services: ["fake-gcs"],
339
+ tests: ["object-store-gcs"],
340
+ },
341
+ {
342
+ backend: "smtp-mail",
343
+ match: ["lib/mail-send", "lib/mail-smtp", "lib/mail-require-tls",
344
+ "lib/mail-server", "lib/network-smtp-policy", "lib/mail-dkim",
345
+ "lib/mail-crypto", "lib/mail-deploy", "lib/mail-auth",
346
+ "lib/mail.js"],
347
+ services: ["mailpit"],
348
+ tests: ["mail-smtp", "mail-dkim", "mail-crypto-smime"],
349
+ },
350
+ {
351
+ backend: "ntp",
352
+ match: ["lib/ntp-check", "lib/network-nts", "lib/network-ntp"],
353
+ services: ["ntp"],
354
+ tests: ["ntp-check"],
355
+ },
356
+ {
357
+ backend: "dns-dot",
358
+ match: ["lib/network-dns", "lib/network-dane", "lib/network-dnssec",
359
+ "lib/network-tsig"],
360
+ services: ["coredns"],
361
+ tests: ["network-dns"],
362
+ },
363
+ {
364
+ backend: "http-tls-outbound",
365
+ match: ["lib/http-client", "lib/network-tls", "lib/network-heartbeat",
366
+ "lib/network-proxy", "lib/tls-exporter", "lib/safe-url"],
367
+ services: ["caddy", "haproxy", "squid"],
368
+ tests: ["http-client", "tls-classical-downgrade-audit",
369
+ "network-heartbeat", "ssrf-guard"],
370
+ },
371
+ {
372
+ backend: "federation-keycloak",
373
+ match: ["lib/oauth", "lib/saml", "lib/openid", "lib/auth.js",
374
+ "lib/auth-header", "lib/ciba", "lib/oid4v", "lib/jar",
375
+ "lib/jarm", "lib/par", "lib/dcr", "lib/scim"],
376
+ services: ["keycloak"],
377
+ tests: ["federation-auth"],
378
+ },
379
+ {
380
+ backend: "log-stream-tls",
381
+ match: ["lib/log-stream"],
382
+ services: ["syslog", "syslog-tls"],
383
+ tests: ["log-stream"],
384
+ },
385
+ {
386
+ backend: "otel-telemetry",
387
+ match: ["lib/log-stream-otlp", "lib/observability"],
388
+ services: ["otel-collector"],
389
+ tests: ["log-stream-cloudwatch"],
390
+ },
391
+ ];
392
+
393
+ // The whole set of changed files relevant to backend detection: both what
394
+ // the release branch already committed on top of main AND the uncommitted
395
+ // working tree. The feature+release cut (CLAUDE.md "Release workflow")
396
+ // stages the fix in the working tree and lets `commit`'s `git add -A`
397
+ // capture it — so by the time `push` runs the change may be EITHER
398
+ // committed (bump-only cut) or still uncommitted (feature+release cut). We
399
+ // union both so the gate can't be slipped by running before the commit.
400
+ function _changedFilesForBackendDetection() {
401
+ var seen = {};
402
+ function add(list) {
403
+ list.forEach(function (p) {
404
+ p = (p || "").replace(/\\/g, "/").trim();
405
+ if (p) seen[p] = true;
406
+ });
407
+ }
408
+ // Committed delta vs main. `origin/main` is the merge target; fall back
409
+ // to local `main` if the remote ref isn't fetched.
410
+ var base = "origin/main";
411
+ if (_capture("git", ["rev-parse", "--verify", "--quiet", base]).status !== 0) {
412
+ base = "main";
413
+ }
414
+ add(_capture("git", ["diff", "--name-only", base + "...HEAD"]).stdout.split(/\r?\n/));
415
+ // Uncommitted working-tree delta (staged + unstaged + untracked).
416
+ add(_capture("git", ["diff", "--name-only"]).stdout.split(/\r?\n/));
417
+ add(_capture("git", ["diff", "--name-only", "--cached"]).stdout.split(/\r?\n/));
418
+ add(_capture("git", ["ls-files", "--others", "--exclude-standard"]).stdout.split(/\r?\n/));
419
+ return Object.keys(seen);
420
+ }
421
+
422
+ // Map the changed-file set onto the backends whose protocol surface was
423
+ // touched. Returns a de-duplicated, deterministic list of
424
+ // { backend, services, tests, matchedBy } entries.
425
+ function _detectTouchedBackends(changedFiles) {
426
+ var hits = [];
427
+ BACKEND_LIVE_MAP.forEach(function (entry) {
428
+ var matchedBy = changedFiles.filter(function (f) {
429
+ return entry.match.some(function (m) { return f.indexOf(m) !== -1; });
430
+ });
431
+ if (matchedBy.length > 0) {
432
+ hits.push({
433
+ backend: entry.backend,
434
+ services: entry.services,
435
+ tests: entry.tests,
436
+ matchedBy: matchedBy,
437
+ });
438
+ }
439
+ });
440
+ return hits;
441
+ }
442
+
443
+ // Bring the docker-compose.test.yml stack up and block until every
444
+ // service reports healthy. Docker being unavailable, or the stack failing
445
+ // to converge, is a HARD STOP — never a skip. A release that touches a
446
+ // backend it cannot prove against does not ship.
447
+ function _bringUpDockerStack() {
448
+ var probe = _capture("docker", ["version", "--format", "{{.Server.Version}}"]);
449
+ if (probe.status !== 0) {
450
+ throw new Error(
451
+ "release: live integration requires Docker, but `docker version` failed.\n" +
452
+ (probe.stderr || probe.stdout || "(no docker daemon reachable)") + "\n" +
453
+ "Start Docker Desktop / the docker daemon and re-run. This is a hard stop, " +
454
+ "not a skip — a backend change that can't be proven live does not ship.");
455
+ }
456
+ console.log("docker server: " + (probe.stdout || "(version unknown)"));
457
+ // `up -d --wait` returns non-zero if any service's healthcheck doesn't
458
+ // reach healthy within its compose-declared timeout. _run throws on
459
+ // non-zero (allowFail defaults off), so a stack that won't converge
460
+ // stops the release here.
461
+ _run("docker", ["compose", "-f", "docker-compose.test.yml", "up", "-d", "--wait"]);
462
+ _ok("docker-compose.test.yml stack up + healthy");
463
+ }
464
+
465
+ function cmdLiveIntegration(opts) {
466
+ opts = opts || {};
467
+ _section("live integration");
468
+
469
+ var changed = _changedFilesForBackendDetection();
470
+ var touched = _detectTouchedBackends(changed);
471
+
472
+ if (touched.length === 0) {
473
+ _ok("no backend-protocol lib files changed — no live integration required");
474
+ return;
475
+ }
476
+
477
+ // Aggregate the matching test files across every touched backend.
478
+ var testSet = {};
479
+ touched.forEach(function (t) {
480
+ t.tests.forEach(function (name) { testSet[name] = true; });
481
+ });
482
+ var testFiles = Object.keys(testSet).sort();
483
+
484
+ console.log("touched backends (" + touched.length + "):");
485
+ touched.forEach(function (t) {
486
+ console.log(" - " + t.backend + " [" + t.tests.join(", ") + "]");
487
+ t.matchedBy.slice(0, 6).forEach(function (f) { console.log(" via " + f); });
488
+ if (t.matchedBy.length > 6) {
489
+ console.log(" via (+" + (t.matchedBy.length - 6) + " more)");
490
+ }
491
+ });
492
+ console.log("live test files to run (" + testFiles.length + "): " + testFiles.join(", "));
493
+
494
+ // The skip path is deliberately heavy: an explicit flag AND a non-empty
495
+ // audited reason, both printed loudly so the bypass is never silent and
496
+ // is captured in the release-flow transcript. A flag with no reason is
497
+ // refused — "I'll explain later" is not an answer here.
498
+ if (opts.skip) {
499
+ if (!opts.skipReason) {
500
+ throw new Error(
501
+ "release: --skip-live-integration requires --live-skip-reason=\"<why>\".\n" +
502
+ "The live gate proves a touched backend against a real instance; skipping " +
503
+ "it needs an explicit, audited reason printed to the operator — not a silent " +
504
+ "bypass. Provide --live-skip-reason or run the live tests.");
505
+ }
506
+ console.log("");
507
+ console.log("!! LIVE INTEGRATION SKIPPED — operator override");
508
+ console.log("!! reason: " + opts.skipReason);
509
+ console.log("!! touched backends NOT proven live: " +
510
+ touched.map(function (t) { return t.backend; }).join(", "));
511
+ console.log("!! tests NOT run: " + testFiles.join(", "));
512
+ console.log("!! This override is recorded in the release-flow output above.");
513
+ return;
514
+ }
515
+
516
+ _bringUpDockerStack();
517
+
518
+ // `--skip-service-check` is intentionally NOT passed: the readiness gate
519
+ // inside test-integration.js is a second proof that the stack the tests
520
+ // need is actually reachable (the `up --wait` healthchecks and the
521
+ // framework's own TCP/TLS probes can disagree). We want both.
522
+ _section("run live integration tests");
523
+ _run("node", ["scripts/test-integration.js"].concat(testFiles));
524
+ _ok("live integration green for: " + touched.map(function (t) {
525
+ return t.backend;
526
+ }).join(", "));
527
+ }
528
+
252
529
  // ---- Subcommands ---------------------------------------------------------
253
530
 
254
531
  function cmdPrepare(opts) {
@@ -405,13 +682,21 @@ function cmdCommit() {
405
682
  console.log("\nnext: node scripts/release.js push");
406
683
  }
407
684
 
408
- function cmdPush() {
685
+ function cmdPush(opts) {
686
+ opts = opts || {};
409
687
  _section("push");
410
688
  if (!_gitOnRelease()) {
411
689
  throw new Error("release: push must run on a release/vX.Y.Z branch");
412
690
  }
413
691
  var next = _readPackageVersion();
414
692
 
693
+ // Touched-backend live integration runs BEFORE gitleaks + the PR opens.
694
+ // A backend change that only passed host smoke (sqlite + in-memory
695
+ // fakes) must prove itself against the real protocol here; a failure is
696
+ // a hard stop that refuses the push. Non-skippable except via an
697
+ // explicit, audited override (see cmdLiveIntegration).
698
+ cmdLiveIntegration({ skip: opts.skipLiveIntegration, skipReason: opts.liveSkipReason });
699
+
415
700
  _section("gitleaks");
416
701
  // Docker bind-mount path: Windows host paths look like
417
702
  // `C:\Users\Robert\Dropbox (Personal)\...`; Docker Desktop accepts
@@ -457,6 +742,56 @@ function cmdPush() {
457
742
  console.log("\nnext: node scripts/release.js watch");
458
743
  }
459
744
 
745
+ // Fetch every UNRESOLVED review thread on the PR with enough context to act on
746
+ // it: the file:line, the reviewer that raised it (CodeQL = github-advanced-
747
+ // security, Codex = chatgpt-codex-connector, lint = github-code-quality), the
748
+ // first line of the finding, the thread id, and the resolve mutation. Bot
749
+ // reviews post ASYNCHRONOUSLY — often a minute or two AFTER the status checks
750
+ // finish — so this is the authoritative check at merge time, not just watch.
751
+ function _unresolvedThreads(prNum) {
752
+ var rv = _capture("gh", ["api", "graphql",
753
+ "-f", "query=query { repository(owner:\"blamejs\",name:\"blamejs\") { pullRequest(number:" + prNum +
754
+ ") { reviewThreads(first:100) { nodes { id isResolved path line " +
755
+ "comments(first:1) { nodes { author{login} body } } } } } } }",
756
+ "--jq", ".data.repository.pullRequest.reviewThreads.nodes"]);
757
+ var nodes;
758
+ try { nodes = JSON.parse(rv.stdout || "[]"); } catch (_e) { nodes = []; }
759
+ return (nodes || []).filter(function (t) { return t && t.isResolved === false; })
760
+ .map(function (t) {
761
+ var c = t.comments && t.comments.nodes && t.comments.nodes[0];
762
+ return {
763
+ id: t.id,
764
+ path: t.path || "(pr-level)",
765
+ line: t.line,
766
+ author: (c && c.author && c.author.login) || "(unknown)",
767
+ body: (c && c.body) || "",
768
+ };
769
+ });
770
+ }
771
+
772
+ // Surface each unresolved thread with the exact finding it raises + how to
773
+ // clear it, so a BLOCKED merge names its cause instead of "state=BLOCKED".
774
+ function _printUnresolvedThreads(unresolved) {
775
+ console.log("\n" + unresolved.length + " unresolved review thread(s) block the merge " +
776
+ "(main-protection requires every thread resolved):\n");
777
+ unresolved.forEach(function (t, i) {
778
+ var lines = (t.body || "").split("\n");
779
+ var firstLine = "(no text)";
780
+ for (var li = 0; li < lines.length; li++) {
781
+ if (lines[li].trim().length > 0) { firstLine = lines[li]; break; }
782
+ }
783
+ // Strip markdown badge images / formatting noise from Codex P1/P2 headers.
784
+ firstLine = firstLine.replace(/!\[[^\]]*\]\([^)]*\)/g, "").replace(/[*_`#>]/g, "").trim();
785
+ console.log(" " + (i + 1) + ". [" + t.author + "] " + t.path +
786
+ (t.line != null ? ":" + t.line : ""));
787
+ console.log(" " + firstLine.slice(0, 160));
788
+ console.log(" resolve: gh api graphql -f query='mutation { resolveReviewThread(" +
789
+ "input:{threadId:\"" + t.id + "\"}){ thread { isResolved } } }'");
790
+ });
791
+ console.log("\nFix each finding in a NEW commit on the branch (never dismiss), then run the");
792
+ console.log("resolve command above for its thread. Re-run: node scripts/release.js merge");
793
+ }
794
+
460
795
  function cmdWatch() {
461
796
  _section("watch");
462
797
  var prNum = _capture("gh", ["pr", "list",
@@ -472,24 +807,16 @@ function cmdWatch() {
472
807
 
473
808
  _run("gh", ["pr", "checks", prNum, "--watch"], { allowFail: true });
474
809
 
475
- var threadRv = _capture("gh", ["api", "graphql",
476
- "-f", "query=query { repository(owner:\"blamejs\",name:\"blamejs\") { pullRequest(number:" + prNum +
477
- ") { reviewThreads(first:50) { nodes { isResolved comments(first:1) { nodes { author{login} body } } } } } } }",
478
- "--jq", ".data.repository.pullRequest.reviewThreads.nodes | map(select(.isResolved==false))"]);
479
- var unresolved = JSON.parse(threadRv.stdout || "[]");
810
+ var unresolved = _unresolvedThreads(prNum);
480
811
  if (unresolved.length > 0) {
481
- console.log("\nunresolved review threads (" + unresolved.length + "):");
482
- unresolved.forEach(function (t) {
483
- var c = t.comments && t.comments.nodes && t.comments.nodes[0];
484
- if (c) {
485
- console.log(" - by " + c.author.login + ": " + c.body.split("\n")[0]);
486
- }
487
- });
488
- console.log("");
489
- console.log("Resolve threads + push fixes, then re-run: node scripts/release.js watch");
812
+ _printUnresolvedThreads(unresolved);
490
813
  process.exit(3);
491
814
  }
492
- _ok("zero unresolved threads");
815
+ // Zero here is NOT conclusive: bot reviews (CodeQL / Codex / code-quality)
816
+ // can post a minute or two after the checks finish. `merge` re-pulls and is
817
+ // the authoritative gate; treat a clean watch as "checks done", not "no
818
+ // findings".
819
+ _ok("zero unresolved threads at watch time (merge re-checks — bot reviews may still be posting)");
493
820
 
494
821
  console.log("\nnext: node scripts/release.js merge");
495
822
  }
@@ -505,27 +832,29 @@ function cmdMerge() {
505
832
  }
506
833
  var state = JSON.parse(_capture("gh", ["pr", "view", prNum,
507
834
  "--json", "mergeStateStatus,mergeable"]).stdout || "{}");
835
+ // Pull unresolved review threads FIRST, at merge time. A BLOCKED state is
836
+ // most often unresolved threads — the bot reviews (CodeQL = github-advanced-
837
+ // security, Codex = chatgpt-codex-connector, lint = github-code-quality) post
838
+ // asynchronously, AFTER the status checks finish, so `watch` can have seen
839
+ // zero while they were still landing. Surface exactly which findings block
840
+ // the merge instead of an opaque "state=BLOCKED", so the operator knows what
841
+ // to fix + resolve. (main-protection's require_review_thread_resolution makes
842
+ // any open thread BLOCK; this is the recovery path.)
843
+ var unresolved = _unresolvedThreads(prNum);
508
844
  if (state.mergeStateStatus !== "CLEAN" || state.mergeable !== "MERGEABLE") {
845
+ if (unresolved.length > 0) _printUnresolvedThreads(unresolved);
509
846
  throw new Error("release: PR #" + prNum + " not mergeable (state=" +
510
- state.mergeStateStatus + " mergeable=" + state.mergeable + ")");
511
- }
512
- // Re-check unresolved review threads RIGHT BEFORE the merge call.
513
- // `watch` enforces zero unresolved at watch time, but a reviewer
514
- // can open a new thread between watch + merge, or main-protection
515
- // may not enforce `require_review_thread_resolution` on every repo
516
- // the merge gate stays robust either way.
517
- var threadRv = _capture("gh", ["api", "graphql",
518
- "-f", "query=query { repository(owner:\"blamejs\",name:\"blamejs\") { pullRequest(number:" + prNum +
519
- ") { reviewThreads(first:50) { nodes { isResolved comments(first:1) { nodes { author{login} body } } } } } } }",
520
- "--jq", ".data.repository.pullRequest.reviewThreads.nodes | map(select(.isResolved==false))"]);
521
- var unresolved = JSON.parse(threadRv.stdout || "[]");
847
+ state.mergeStateStatus + " mergeable=" + state.mergeable + ")" +
848
+ (unresolved.length > 0
849
+ ? " — " + unresolved.length + " unresolved review thread(s); see above"
850
+ : " no unresolved threads; check required status checks / signatures"));
851
+ }
852
+ // Belt-and-suspenders: even if the API reports CLEAN, refuse on any open
853
+ // thread (a thread can open in the window between the state read and merge).
522
854
  if (unresolved.length > 0) {
523
- console.log("\nunresolved review threads opened since watch (" + unresolved.length + "):");
524
- unresolved.forEach(function (t) {
525
- var c = t.comments && t.comments.nodes && t.comments.nodes[0];
526
- if (c) console.log(" - by " + c.author.login + ": " + c.body.split("\n")[0]);
527
- });
528
- throw new Error("release: refusing to merge PR #" + prNum + " — unresolved review threads");
855
+ _printUnresolvedThreads(unresolved);
856
+ throw new Error("release: refusing to merge PR #" + prNum + " — " +
857
+ unresolved.length + " unresolved review thread(s)");
529
858
  }
530
859
  _run("gh", ["pr", "merge", prNum, "--squash", "--delete-branch"]);
531
860
  _ok("PR #" + prNum + " squash-merged");
@@ -609,7 +938,7 @@ function cmdAll(opts) {
609
938
  cmdPrepare(opts);
610
939
  cmdSmoke();
611
940
  cmdCommit();
612
- cmdPush();
941
+ cmdPush(opts);
613
942
  cmdWatch();
614
943
  cmdMerge();
615
944
  cmdTag();
@@ -643,7 +972,8 @@ function cmdHelp() {
643
972
  console.log(" node scripts/release.js regen # re-regen artifacts after release-notes edits");
644
973
  console.log(" node scripts/release.js smoke # framework + wiki e2e if needed");
645
974
  console.log(" node scripts/release.js commit # release branch + signed commit");
646
- console.log(" node scripts/release.js push # gitleaks + push + open PR");
975
+ console.log(" node scripts/release.js live-integration # touched-backend live tests (docker stack)");
976
+ console.log(" node scripts/release.js push # live-integration + gitleaks + push + open PR");
647
977
  console.log(" node scripts/release.js watch # CI watch + flag Codex threads");
648
978
  console.log(" node scripts/release.js merge # squash-merge if CLEAN");
649
979
  console.log(" node scripts/release.js tag # signed tag + push tag");
@@ -651,14 +981,39 @@ function cmdHelp() {
651
981
  console.log(" node scripts/release.js all [--minor] # all eight in sequence");
652
982
  console.log(" node scripts/release.js status # current branch + version state");
653
983
  console.log(" node scripts/release.js help # this banner");
984
+ console.log("");
985
+ console.log("Live-integration gate (runs inside push):");
986
+ console.log(" Detects which backends the release touched (diffing changed lib");
987
+ console.log(" files against a backend->files map), brings up docker-compose.test.yml,");
988
+ console.log(" and runs the matching test/integration tests live. A failing test or an");
989
+ console.log(" unavailable docker stack is a HARD STOP — the push is refused. To override");
990
+ console.log(" (audited, never silent): --skip-live-integration --live-skip-reason=\"<why>\".");
654
991
  }
655
992
 
656
993
  // ---- Dispatch ------------------------------------------------------------
657
994
 
658
995
  var sub = process.argv[2] || "help";
659
996
  var args = process.argv.slice(3);
997
+
998
+ // Parse a `--flag=value` form into its value; returns undefined if absent
999
+ // or if the flag was passed without an `=value` (bare `--flag`).
1000
+ function _flagValue(name) {
1001
+ var prefix = name + "=";
1002
+ for (var i = 0; i < args.length; i++) {
1003
+ if (args[i].indexOf(prefix) === 0) return args[i].slice(prefix.length);
1004
+ }
1005
+ return undefined;
1006
+ }
1007
+
660
1008
  var opts = {
661
1009
  minor: args.indexOf("--minor") !== -1,
1010
+ // The live-integration gate is on by default. `--skip-live-integration`
1011
+ // opts out, but ONLY together with `--live-skip-reason="<why>"`; the
1012
+ // reason is printed loudly and recorded in the release-flow transcript.
1013
+ // A flag with no reason is refused inside cmdLiveIntegration — the gate
1014
+ // is never silently skippable.
1015
+ skipLiveIntegration: args.indexOf("--skip-live-integration") !== -1,
1016
+ liveSkipReason: _flagValue("--live-skip-reason"),
662
1017
  };
663
1018
 
664
1019
  try {
@@ -667,7 +1022,12 @@ try {
667
1022
  case "regen": cmdRegen(); break;
668
1023
  case "smoke": cmdSmoke(); break;
669
1024
  case "commit": cmdCommit(); break;
670
- case "push": cmdPush(); break;
1025
+ case "live-integration":
1026
+ case "live": cmdLiveIntegration({
1027
+ skip: opts.skipLiveIntegration,
1028
+ skipReason: opts.liveSkipReason,
1029
+ }); break;
1030
+ case "push": cmdPush(opts); break;
671
1031
  case "watch": cmdWatch(); break;
672
1032
  case "merge": cmdMerge(); break;
673
1033
  case "tag": cmdTag(); break;