@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
@@ -5,10 +5,11 @@
5
5
  * (minio-tls:9443) so the framework's sigv4 signer + S3 client are
6
6
  * exercised end-to-end against real AWS-compatible servers.
7
7
  *
8
- * No security bypass: the TLS leg pins the test CA via opts.ca on
9
- * the request layer (rejectUnauthorized stays on by default).
8
+ * No security bypass: the TLS leg trusts the test CA via the runner's
9
+ * NODE_EXTRA_CA_CERTS (scripts/test-integration.js), so the framework's
10
+ * own TLS verification stays fully on with no rejectUnauthorized override
11
+ * and no per-request CA threading.
10
12
  */
11
- var fs = require("node:fs");
12
13
  var helpers = require("../helpers");
13
14
  var check = helpers.check;
14
15
  var services = require("../helpers/services");
@@ -86,6 +87,29 @@ function _runOnEndpoint(label, endpoint, extraConfig) {
86
87
  check("[" + label + "] list after delete: object gone",
87
88
  !afterDelete.items.some(function (it) { return it.key === key; }));
88
89
 
90
+ // ---- special-character key round-trip (the v0.15.2 SigV4 single-encode
91
+ // fix). A key with a space / + / & / () previously double-encoded the
92
+ // canonical path → the signature was computed over a path the wire never
93
+ // carried → SignatureDoesNotMatch (403). Every prior test used ASCII keys,
94
+ // so the bug shipped green; this drives a real special-char key end-to-end.
95
+ // put() throws on a non-2xx, so reaching the asserts proves no 403. ----
96
+ // Includes a non-BMP code point (emoji) so the round-trip also proves the
97
+ // encoder iterates by code point — a UTF-16-unit split would throw URIError
98
+ // before signing.
99
+ var specialKey = "obj report (v2)+final & draft \u{1F600}-" + Math.floor(Math.random() * 1e6) + ".txt";
100
+ var specialPayload = Buffer.from("special-char-key payload", "utf8");
101
+ await backend.put(specialKey, specialPayload, { contentType: "text/plain" });
102
+ check("[" + label + "] special-char key put: signed + accepted (no 403)", true);
103
+ var specialGot = await backend.get(specialKey);
104
+ var specialBuf = Buffer.isBuffer(specialGot) ? specialGot : (specialGot && specialGot.body);
105
+ check("[" + label + "] special-char key get: bytes round-trip exactly",
106
+ Buffer.isBuffer(specialBuf) && Buffer.compare(specialBuf, specialPayload) === 0);
107
+ var specialListing = await backend.list("obj report");
108
+ check("[" + label + "] special-char key list: surfaces the object",
109
+ specialListing.items.some(function (it) { return it.key === specialKey; }));
110
+ await backend.delete(specialKey);
111
+ check("[" + label + "] special-char key delete: returned (no throw)", true);
112
+
89
113
  // ---- multipart upload + round-trip (covers the v0.6.50 ?uploads
90
114
  // wire-form fix; until now multipart had only mock-server coverage). ----
91
115
  var bigBackendCfg = Object.assign({}, beCfg, {
@@ -359,20 +383,17 @@ async function run() {
359
383
  var svcTls = await services.requireService("minioTls");
360
384
  if (!svcTls.ok) throw new Error("minio-tls unreachable: " + svcTls.reason);
361
385
 
362
- var caPath = await services.exportCaCert();
363
- var caPem = fs.readFileSync(caPath, "utf8");
364
-
365
386
  // ---- plain HTTP variant ----
366
387
  await _runOnEndpoint("http", "http://127.0.0.1:9000", {
367
388
  allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
368
389
  });
369
390
 
370
- // ---- TLS variant — strict CA pinning, no rejectUnauthorized override ----
391
+ // ---- TLS variant — full verification, no rejectUnauthorized override ----
392
+ // Trust for the test CA comes from the runner's NODE_EXTRA_CA_CERTS.
371
393
  // Endpoint uses "localhost" so SNI works (cert SAN covers localhost +
372
- // 127.0.0.1; node:tls forbids IP literals as servername).
373
- await _runOnEndpoint("tls", "https://localhost:9443", {
374
- ca: caPem,
375
- });
394
+ // 127.0.0.1; node:tls forbids IP literals as servername). https is in
395
+ // the default allowedProtocols so no extra config is needed.
396
+ await _runOnEndpoint("tls", "https://localhost:9443", {});
376
397
 
377
398
  // ---- Object Lock variant (HTTP only — no benefit from doing it twice
378
399
  // and the WORM cleanup adds 2s of sleep which we don't want
@@ -383,14 +404,12 @@ async function run() {
383
404
  });
384
405
 
385
406
  // ---- Presigned response-header overrides (v0.8.53). HTTP first;
386
- // TLS second to confirm signing math + Object.assign(ca) on
387
- // the framework's httpClient request path. ----
407
+ // TLS second to confirm the signing math + the live presigned GET
408
+ // stay valid over a fully-verified TLS handshake. ----
388
409
  await _runPresignResponseHeadersOnEndpoint("http", "http://127.0.0.1:9000", {
389
410
  allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
390
411
  });
391
- await _runPresignResponseHeadersOnEndpoint("tls", "https://localhost:9443", {
392
- ca: caPem,
393
- });
412
+ await _runPresignResponseHeadersOnEndpoint("tls", "https://localhost:9443", {});
394
413
  }
395
414
 
396
415
  module.exports = { run: run };
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+ /**
3
+ * S3 Object Lock WORM enforcement — does COMPLIANCE-mode retention
4
+ * actually REFUSE a delete on real MinIO (which enforces Object Lock)?
5
+ *
6
+ * The existing object-store-sigv4 test only round-trips the retention /
7
+ * legal-hold CONFIG (set → get echoes the value back). It explicitly
8
+ * does NOT assert that a delete is blocked, with the rationale that
9
+ * Object-Lock buckets are versioned and an unversioned DELETE just
10
+ * writes a delete-marker. That leaves the headline WORM guarantee
11
+ * ("a record cannot be deleted before its retainUntil by anyone") never
12
+ * proven against a backend that enforces it.
13
+ *
14
+ * This test proves enforcement directly: it puts an object into an
15
+ * Object-Lock-enabled bucket, applies a COMPLIANCE retention with
16
+ * retainUntil in the future, then attempts to delete the PROTECTED
17
+ * VERSION and asserts MinIO refuses. A control object with no retention
18
+ * has its version deleted successfully, proving the refusal is the lock
19
+ * and not a blanket failure.
20
+ *
21
+ * Why the versioned delete matters — and what it exposes about the
22
+ * framework: WORM protects a specific object VERSION. An unversioned
23
+ * `DELETE /key` on a versioned bucket always succeeds (it writes a
24
+ * delete-marker; the protected version survives untouched). The
25
+ * framework's object-store delete (`backend.delete(key)` /
26
+ * `bucketOps.delete`) issues ONLY the unversioned form — there is no
27
+ * versionId surface anywhere in lib/object-store. So:
28
+ *
29
+ * (a) the framework's own delete() on a retained object SUCCEEDS and
30
+ * returns a clean result, masking the fact that the data version
31
+ * is still there — the framework delete path is not WORM-aware;
32
+ * (b) the operation WORM actually blocks (delete the protected version)
33
+ * can only be issued by hand-signing `DELETE /key?versionId=<v>`.
34
+ *
35
+ * This test hand-signs that versioned delete with the framework's OWN
36
+ * SigV4 signer (lib/object-store/sigv4.signRequest) so the proof is that
37
+ * MinIO enforces the lock under a request the framework signed correctly
38
+ * — no security bypass, real handshake, real signature.
39
+ *
40
+ * Observed MinIO behaviour (ground truth, captured live): the versioned
41
+ * delete of a COMPLIANCE-retained version is refused with HTTP 400
42
+ * InvalidRequest, body "Object is WORM protected and cannot be
43
+ * overwritten" — both with and without x-amz-bypass-governance-retention
44
+ * (COMPLIANCE cannot be bypassed by anyone). A no-retention version
45
+ * deletes with HTTP 204. AWS S3 uses 403 AccessDenied for the same
46
+ * refusal; the assertion accepts any 4xx refusal carrying the WORM
47
+ * signal so it holds on both backends.
48
+ *
49
+ * MinIO note: an Object-Lock bucket MUST be created with the
50
+ * x-amz-bucket-object-lock-enabled:true header at create time (object
51
+ * lock cannot be added later). bucketOps.create({ objectLockEnabled:true })
52
+ * sends that header. MinIO genuinely ENFORCES COMPLIANCE retention; it is
53
+ * the right backend for this proof. LocalStack's community S3 does not
54
+ * verify SigV4 and its Object-Lock enforcement is not authoritative — we
55
+ * target MinIO only.
56
+ */
57
+ var helpers = require("../helpers");
58
+ var check = helpers.check;
59
+ var services = require("../helpers/services");
60
+ var b = require("../../");
61
+ var sigv4 = require("../../lib/object-store/sigv4");
62
+
63
+ var REGION = "us-east-1";
64
+ var ACCESS = "blamejs";
65
+ var SECRET = "blamejs_test_password";
66
+
67
+ // Hand-sign a raw S3 request with the framework's signer and send it via
68
+ // the framework's httpClient in always-resolve mode, so EVERY HTTP
69
+ // response — including a 4xx WORM refusal — comes back as
70
+ // { statusCode, headers, body } rather than a thrown error. Only a
71
+ // transport-level failure rejects. extraHeaders lets a caller add e.g.
72
+ // x-amz-bypass-governance-retention into the signed set.
73
+ function _rawSigned(method, urlStr, bodyBuf, extraHeaders) {
74
+ var payloadHash = sigv4.sha256Hex(bodyBuf || Buffer.alloc(0));
75
+ var extra = Object.assign({}, extraHeaders || {});
76
+ if (bodyBuf && bodyBuf.length > 0) {
77
+ extra["Content-Length"] = String(bodyBuf.length);
78
+ if (!extra["Content-Type"]) extra["Content-Type"] = "application/octet-stream";
79
+ }
80
+ var signed = sigv4.signRequest({
81
+ method: method,
82
+ url: urlStr,
83
+ headers: extra,
84
+ payloadHash: payloadHash,
85
+ region: REGION,
86
+ accessKeyId: ACCESS,
87
+ secretAccessKey: SECRET,
88
+ allowedProtocols: ["http:", "https:"],
89
+ });
90
+ return b.httpClient.request({
91
+ method: method,
92
+ url: urlStr,
93
+ headers: signed.headers,
94
+ body: bodyBuf && bodyBuf.length > 0 ? bodyBuf : null,
95
+ allowedProtocols: ["http:", "https:"],
96
+ allowInternal: true,
97
+ responseMode: "always-resolve",
98
+ });
99
+ }
100
+
101
+ function _objUrl(endpoint, bucket, key, versionId) {
102
+ var u = endpoint + "/" + bucket + "/" + encodeURIComponent(key);
103
+ if (versionId) u += "?versionId=" + encodeURIComponent(versionId);
104
+ return u;
105
+ }
106
+
107
+ function _bodyText(res) {
108
+ return res && res.body ? Buffer.from(res.body).toString("utf8") : "";
109
+ }
110
+
111
+ // A genuine WORM refusal: a 4xx whose body carries the lock signal.
112
+ // MinIO → 400 InvalidRequest "Object is WORM protected"; AWS S3 → 403
113
+ // AccessDenied. Accept either, but require the WORM/retention signal so a
114
+ // generic 400 (bad request shape) can't masquerade as enforcement.
115
+ function _isWormRefusal(res) {
116
+ if (!res || (res.statusCode !== 400 && res.statusCode !== 403)) return false;
117
+ var t = _bodyText(res);
118
+ return /WORM|retention|object lock|AccessDenied|cannot be overwritten|protected/i.test(t);
119
+ }
120
+
121
+ async function _runWormOnEndpoint(label, endpoint, extraConfig) {
122
+ var bucket = "blamejs-worm-" + label + "-" + Date.now();
123
+ var opsCfg = Object.assign({
124
+ protocol: "sigv4",
125
+ endpoint: endpoint,
126
+ region: REGION,
127
+ accessKeyId: ACCESS,
128
+ secretAccessKey: SECRET,
129
+ allowInternal: true,
130
+ forcePathStyle: true,
131
+ }, extraConfig);
132
+ var ops = b.objectStore.bucketOps.create(opsCfg);
133
+
134
+ // ---- 1. Object-Lock-enabled bucket (header at create time) ----
135
+ await ops.create(bucket, { objectLockEnabled: true });
136
+ var lockCfg = await ops.getObjectLockConfiguration(bucket);
137
+ check("[" + label + "] bucket reports object-lock enabled", lockCfg.enabled === true);
138
+
139
+ var backend = b.objectStore.buildBackend(Object.assign({
140
+ name: "minio-worm-" + label,
141
+ protocol: "sigv4",
142
+ endpoint: endpoint,
143
+ region: REGION,
144
+ bucket: bucket,
145
+ accessKeyId: ACCESS,
146
+ secretAccessKey: SECRET,
147
+ allowInternal: true,
148
+ forcePathStyle: true,
149
+ classifications: ["operational"],
150
+ residencyTag: "unrestricted",
151
+ }, extraConfig));
152
+
153
+ // ============================================================
154
+ // PROTECTED OBJECT — COMPLIANCE retention in the future
155
+ // ============================================================
156
+ var key = "worm-doc-" + Math.floor(Math.random() * 1e6) + ".txt";
157
+ var payload = Buffer.from("immutable filing " + new Date().toISOString(), "utf8");
158
+
159
+ // Capture the versionId from a hand-signed PUT (backend.put discards
160
+ // x-amz-version-id; we need the version to target the protected delete).
161
+ var putRes = await _rawSigned("PUT", _objUrl(endpoint, bucket, key), payload);
162
+ check("[" + label + "] protected object PUT succeeds", putRes.statusCode === 200);
163
+ var versionId = putRes.headers && putRes.headers["x-amz-version-id"];
164
+ check("[" + label + "] PUT returned a versionId (bucket is versioned)",
165
+ typeof versionId === "string" && versionId.length > 0);
166
+
167
+ // Apply COMPLIANCE retention 1 hour into the future — long enough that
168
+ // it cannot lapse during the test. COMPLIANCE = nobody can delete the
169
+ // version before retainUntil, not even with bypassGovernance.
170
+ var retainUntil = new Date(Date.now() + b.constants.TIME.hours(1));
171
+ var setRet = await ops.setObjectRetention(bucket, key, {
172
+ mode: "COMPLIANCE",
173
+ retainUntil: retainUntil,
174
+ });
175
+ check("[" + label + "] setObjectRetention COMPLIANCE applied", setRet.applied === true);
176
+
177
+ var gotRet = await ops.getObjectRetention(bucket, key);
178
+ check("[" + label + "] retention reads back COMPLIANCE", gotRet.mode === "COMPLIANCE");
179
+ check("[" + label + "] retainUntil reads back in the future",
180
+ gotRet.retainUntil instanceof Date && gotRet.retainUntil.getTime() > Date.now());
181
+
182
+ // ---- 2. The framework's own delete() is NOT WORM-aware ----
183
+ // backend.delete(key) issues an unversioned DELETE → MinIO writes a
184
+ // delete-marker and returns success. The protected DATA version is
185
+ // untouched, but the framework caller is told the delete "worked".
186
+ // This documents that the framework delete path cannot enforce — and
187
+ // cannot even attempt — the WORM-blocked operation.
188
+ var fwDeleteResult = await backend.delete(key);
189
+ check("[" + label + "] framework backend.delete() returns success on a retained object " +
190
+ "(unversioned DELETE writes a delete-marker; data version survives)",
191
+ fwDeleteResult === true);
192
+ // Prove the data version actually survived the framework delete: a
193
+ // versioned GET of the protected version still returns the bytes.
194
+ var stillThere = await _rawSigned("GET", _objUrl(endpoint, bucket, key, versionId), null);
195
+ check("[" + label + "] protected DATA version still readable after framework delete() " +
196
+ "(framework delete only wrote a delete-marker)",
197
+ stillThere.statusCode === 200 &&
198
+ Buffer.compare(Buffer.from(stillThere.body || []), payload) === 0);
199
+
200
+ // ---- 3. THE WORM PROOF: deleting the protected VERSION is REFUSED ----
201
+ // This is the operation WORM exists to block. Hand-sign
202
+ // DELETE /key?versionId=<v> with the framework's signer. MinIO must
203
+ // refuse because the version is under COMPLIANCE retention.
204
+ var wormDel = await _rawSigned("DELETE", _objUrl(endpoint, bucket, key, versionId), null);
205
+ check("[" + label + "] WORM ENFORCED: delete of the COMPLIANCE-retained version is REFUSED " +
206
+ "(got " + wormDel.statusCode + " " + _bodyText(wormDel).replace(/\s+/g, " ").slice(0, 80) + ")",
207
+ _isWormRefusal(wormDel));
208
+
209
+ // ---- 3b. bypassGovernance does NOT defeat COMPLIANCE ----
210
+ // x-amz-bypass-governance-retention can shorten/delete GOVERNANCE
211
+ // retention with the right permission, but COMPLIANCE is immutable to
212
+ // everyone. Assert the version delete is STILL refused even with the
213
+ // bypass header signed in.
214
+ var wormDelBypass = await _rawSigned("DELETE", _objUrl(endpoint, bucket, key, versionId), null, {
215
+ "x-amz-bypass-governance-retention": "true",
216
+ });
217
+ check("[" + label + "] COMPLIANCE cannot be bypassed: versioned delete with " +
218
+ "x-amz-bypass-governance-retention is STILL refused (got " + wormDelBypass.statusCode + ")",
219
+ _isWormRefusal(wormDelBypass));
220
+
221
+ // And the version is verifiably still present after both refused deletes.
222
+ var afterRefuse = await _rawSigned("GET", _objUrl(endpoint, bucket, key, versionId), null);
223
+ check("[" + label + "] retained version still present after the refused deletes",
224
+ afterRefuse.statusCode === 200 &&
225
+ Buffer.compare(Buffer.from(afterRefuse.body || []), payload) === 0);
226
+
227
+ // ============================================================
228
+ // CONTROL — no retention: the version deletes fine
229
+ // ============================================================
230
+ var ctlKey = "control-" + Math.floor(Math.random() * 1e6) + ".txt";
231
+ var ctlPayload = Buffer.from("disposable", "utf8");
232
+ var ctlPut = await _rawSigned("PUT", _objUrl(endpoint, bucket, ctlKey), ctlPayload);
233
+ check("[" + label + "] control object PUT succeeds", ctlPut.statusCode === 200);
234
+ var ctlVersion = ctlPut.headers && ctlPut.headers["x-amz-version-id"];
235
+ check("[" + label + "] control PUT returned a versionId",
236
+ typeof ctlVersion === "string" && ctlVersion.length > 0);
237
+
238
+ var ctlDel = await _rawSigned("DELETE", _objUrl(endpoint, bucket, ctlKey, ctlVersion), null);
239
+ check("[" + label + "] CONTROL: no-retention version deletes fine (2xx) — the refusal above " +
240
+ "is the lock, not a blanket failure (got " + ctlDel.statusCode + ")",
241
+ ctlDel.statusCode === 204 || ctlDel.statusCode === 200);
242
+ var ctlGone = await _rawSigned("GET", _objUrl(endpoint, bucket, ctlKey, ctlVersion), null);
243
+ check("[" + label + "] control version is gone after delete (404)",
244
+ ctlGone.statusCode === 404);
245
+
246
+ // ---- Cleanup is impossible while COMPLIANCE retention holds: the
247
+ // protected version cannot be removed before retainUntil by anyone,
248
+ // and bucketOps.delete refuses a non-empty bucket. That is the WORM
249
+ // guarantee working as designed. Confirm the bucket delete refuses,
250
+ // then leave the bucket; the name carries Date.now() so re-runs don't
251
+ // collide and the MinIO container reset sweeps it. ----
252
+ var bucketDropped = true;
253
+ try {
254
+ await ops.delete(bucket);
255
+ } catch (_e) {
256
+ bucketDropped = false;
257
+ }
258
+ check("[" + label + "] bucket with a COMPLIANCE-retained version cannot be dropped " +
259
+ "(WORM holds the bytes)",
260
+ bucketDropped === false);
261
+ }
262
+
263
+ async function run() {
264
+ var svc = await services.requireService("minio");
265
+ var svcTls = await services.requireService("minioTls");
266
+ if (!svc.ok && !svcTls.ok) {
267
+ throw new Error("minio unreachable (need plain or TLS): " +
268
+ (svc.reason || "") + " / " + (svcTls.reason || ""));
269
+ }
270
+
271
+ // MinIO over the plain HTTP listener — it enforces Object Lock + verifies
272
+ // SigV4 (unlike LocalStack). We use the plain endpoint for the WORM proof
273
+ // since the enforcement, not the transport, is the subject; the runner's
274
+ // NODE_EXTRA_CA_CERTS covers the TLS leg if only that one is up.
275
+ if (svc.ok) {
276
+ await _runWormOnEndpoint("http", "http://127.0.0.1:9000", {
277
+ allowedProtocols: b.safeUrl.ALLOW_HTTP_ALL,
278
+ });
279
+ } else {
280
+ await _runWormOnEndpoint("tls", "https://localhost:9443", {});
281
+ }
282
+ }
283
+
284
+ module.exports = { run: run };
285
+
286
+ if (require.main === module) {
287
+ run().then(
288
+ function () { console.log("OK — " + helpers.getChecks() + " checks passed"); process.exit(0); },
289
+ function (e) { console.error("FAIL:", e.stack || e); process.exit(1); }
290
+ );
291
+ }
@@ -112,6 +112,20 @@ async function run() {
112
112
  check("cA has u:1", await cA.has("u:1"));
113
113
  check("cB has u:1", await cB.has("u:1"));
114
114
 
115
+ // cache.create() issues cB's SUBSCRIBE on ips2 fire-and-forget; the
116
+ // remote SUBSCRIBE drains asynchronously. Redis PUB/SUB has no
117
+ // buffering for not-yet-subscribed channels — a single invalidateTag
118
+ // published before cB's subscription is active on the server is lost
119
+ // forever. Probe a no-subscriber channel on ips2's connection until
120
+ // Redis answers PUBLISH; that ack means ips2's queued SUBSCRIBE has
121
+ // drained and cB is registered for the invalidation channel. (Real
122
+ // deploys subscribe at boot, long before invalidations flow; this
123
+ // reproduces that steady state.)
124
+ await helpers.waitUntil(async function () {
125
+ var probe = await ips2.publish("cache:fanout:probe:" + Date.now(), {});
126
+ return probe && typeof probe.remote === "number";
127
+ }, { label: "cache fan-out: ips2 SUBSCRIBE drained (cB registered)" });
128
+
115
129
  await cA.invalidateTag("t-user");
116
130
  // The publish goes through redis; ips2 subscribes to the channel,
117
131
  // forwards to cB. Poll until cB has observed the eviction.