@blamejs/blamejs-shop 0.5.12 → 0.5.13

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 (521) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +632 -416
  4. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  5. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  6. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  7. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  8. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  9. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  10. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  11. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  12. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  13. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  14. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  15. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  16. package/lib/vendor/blamejs/.gitignore +2 -0
  17. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  18. package/lib/vendor/blamejs/NOTICE +26 -1
  19. package/lib/vendor/blamejs/SECURITY.md +1 -1
  20. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  21. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  22. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  23. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  24. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  25. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  26. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  27. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  28. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  29. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  30. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  31. package/lib/vendor/blamejs/index.js +6 -0
  32. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  33. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  34. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  35. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  36. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  37. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  38. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  39. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  40. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  41. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  42. package/lib/vendor/blamejs/lib/audit.js +71 -8
  43. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  44. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  45. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  46. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  47. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  48. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  49. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  50. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  51. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  52. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  53. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  54. package/lib/vendor/blamejs/lib/base32.js +21 -0
  55. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  56. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  57. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  58. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  59. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  60. package/lib/vendor/blamejs/lib/cert.js +29 -11
  61. package/lib/vendor/blamejs/lib/cli.js +94 -24
  62. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  63. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  65. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  66. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  67. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  68. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  69. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  70. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  71. package/lib/vendor/blamejs/lib/cose.js +31 -16
  72. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  73. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  74. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  75. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  76. package/lib/vendor/blamejs/lib/csp.js +11 -3
  77. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  78. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  79. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  80. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  81. package/lib/vendor/blamejs/lib/db.js +18 -6
  82. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  83. package/lib/vendor/blamejs/lib/dev.js +21 -2
  84. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  85. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  86. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  87. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  88. package/lib/vendor/blamejs/lib/forms.js +113 -27
  89. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  90. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  91. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  92. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  93. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  94. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  95. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  96. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  97. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  98. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  99. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  100. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  101. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  102. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  105. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  106. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  107. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  108. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  109. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  110. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  111. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  112. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  113. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  114. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  115. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  116. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  117. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  118. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  119. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  120. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  121. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  123. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  124. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  125. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  126. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  128. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  129. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  130. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  131. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  132. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  133. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  134. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  136. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  137. package/lib/vendor/blamejs/lib/mail.js +15 -5
  138. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  139. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  140. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  141. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  142. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  143. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  144. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  145. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  146. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  147. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  148. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  149. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  150. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  151. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  153. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  154. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  155. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  156. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  157. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  158. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  159. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  160. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  161. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  162. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  163. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  164. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  165. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  166. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  167. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  168. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  169. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  170. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  171. package/lib/vendor/blamejs/lib/redact.js +54 -0
  172. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  173. package/lib/vendor/blamejs/lib/restore.js +19 -0
  174. package/lib/vendor/blamejs/lib/retention.js +12 -4
  175. package/lib/vendor/blamejs/lib/router.js +60 -6
  176. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  177. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  178. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  179. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  180. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  181. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  182. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  183. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  184. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  185. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  186. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  187. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  188. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  189. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  190. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  191. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  192. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  193. package/lib/vendor/blamejs/lib/session.js +34 -12
  194. package/lib/vendor/blamejs/lib/sql.js +15 -1
  195. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  196. package/lib/vendor/blamejs/lib/static.js +55 -13
  197. package/lib/vendor/blamejs/lib/storage.js +8 -2
  198. package/lib/vendor/blamejs/lib/subject.js +6 -1
  199. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  200. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  201. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  202. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  203. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  204. package/lib/vendor/blamejs/lib/vc.js +44 -5
  205. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  206. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  207. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  208. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  209. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  210. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  212. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  213. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  214. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  215. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  216. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  217. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  218. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  219. package/lib/vendor/blamejs/package-lock.json +2 -2
  220. package/lib/vendor/blamejs/package.json +1 -1
  221. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  222. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  223. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  224. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  245. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  246. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  247. package/lib/vendor/blamejs/socket.yml +94 -0
  248. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  249. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  250. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  251. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  252. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  253. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  254. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  255. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  256. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  257. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  258. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  259. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  262. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  268. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  284. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  293. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  302. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  307. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  321. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  322. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  324. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  326. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  327. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  330. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  334. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  335. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  336. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  337. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  348. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  376. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  388. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  413. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  414. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  415. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  416. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  428. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  432. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  434. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  442. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  443. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  445. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  477. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  478. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  480. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  490. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  491. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  492. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  493. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  495. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  502. package/lib/vendor/blamejs/test/smoke.js +2 -0
  503. package/package.json +1 -1
  504. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  505. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  506. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  507. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  508. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  509. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  510. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  511. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  512. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  513. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  514. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  515. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  516. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  517. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  518. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  519. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  520. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  521. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -0,0 +1,600 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) blamejs contributors
3
+ "use strict";
4
+ /**
5
+ * b.retention — canonical per-primitive coverage.
6
+ *
7
+ * Drives the retention controller through its real consumer path
8
+ * (b.retention.create → declare → run / runAll / preview / list) plus
9
+ * the standalone posture helpers (complianceFloor / applyPosture /
10
+ * activePosture). Focuses on the error / adversarial / defensive /
11
+ * option-default branches: rule-shape rejection, the identifier SQLi
12
+ * gate, legal-hold skip (per-row field + subject registry), multi-stage
13
+ * routing, soft-delete-without-field, custom-action errors, cascade
14
+ * fan-out, the keyset-pagination cursor, the __erasedAt fallback query,
15
+ * sweep failure, and the per-rule concurrency lock.
16
+ */
17
+
18
+ var fs = require("fs");
19
+ var path = require("path");
20
+ var os = require("os");
21
+ var helpers = require("../helpers");
22
+ var dbHelper = require("../helpers/db");
23
+ var b = helpers.b;
24
+ var check = helpers.check;
25
+
26
+ var DAYS90 = b.constants.TIME.days(90);
27
+ var LONG_AGO = function () { return Date.now() - b.constants.TIME.days(400); };
28
+
29
+ // Create an operator app table (unique name per test) with the columns the
30
+ // candidate query expects. __erasedAt present unless withoutErasedAt.
31
+ function _seedTable(table, n, opts) {
32
+ opts = opts || {};
33
+ var cols = ["\"_id\" TEXT PRIMARY KEY", "\"createdAt\" INTEGER", "\"payload\" TEXT"];
34
+ if (!opts.withoutErasedAt) cols.push("\"__erasedAt\" INTEGER");
35
+ if (opts.holdCol) cols.push("\"" + opts.holdCol + "\" INTEGER");
36
+ if (opts.subjectCol) cols.push("\"" + opts.subjectCol + "\" TEXT");
37
+ if (opts.softCol) cols.push("\"" + opts.softCol + "\" INTEGER");
38
+ b.db.prepare("CREATE TABLE \"" + table + "\" (" + cols.join(", ") + ")").run();
39
+ var colNames = ["\"_id\"", "\"createdAt\"", "\"payload\""];
40
+ if (opts.holdCol) colNames.push("\"" + opts.holdCol + "\"");
41
+ if (opts.subjectCol) colNames.push("\"" + opts.subjectCol + "\"");
42
+ var qs = colNames.map(function () { return "?"; }).join(", ");
43
+ for (var i = 0; i < n; i++) {
44
+ var vals = ["r-" + i, LONG_AGO(), "secret-" + i];
45
+ if (opts.holdCol) vals.push(opts.hold ? 1 : null);
46
+ if (opts.subjectCol) vals.push(opts.subject || ("subj-" + i));
47
+ b.db.prepare("INSERT INTO \"" + table + "\" (" + colNames.join(", ") + ") VALUES (" + qs + ")").run.apply(null, vals);
48
+ }
49
+ }
50
+
51
+ function _expectThrow(label, fn, matcher) {
52
+ var threw = null;
53
+ try { fn(); } catch (e) { threw = e; }
54
+ // Match against BOTH the framework-error code and the message text so a
55
+ // matcher can pin either surface.
56
+ var msg = threw ? ((threw.code || "") + " " + (threw.message || String(threw))) : "";
57
+ check(label, threw !== null && (!matcher || matcher.test(msg)));
58
+ }
59
+
60
+ // ---------------------------------------------------------------------------
61
+ // Happy path — establishes the real consumer path works end-to-end.
62
+ // ---------------------------------------------------------------------------
63
+ async function testHappyEraseSweep() {
64
+ b.cryptoField.registerTable("ret_happy", { sealedFields: ["payload"], rowIdField: "_id" });
65
+ _seedTable("ret_happy", 3);
66
+ var ret = b.retention.create({ db: b.db, audit: false });
67
+ ret.declare({ name: "happy", table: "ret_happy", ageField: "createdAt", ttlMs: DAYS90, action: "erase" });
68
+ var summary = await ret.run("happy");
69
+ check("happy erase scanned 3", summary.scanned === 3);
70
+ check("happy erase processed 3", summary.processed === 3);
71
+ check("happy erase action label", summary.action === "erase");
72
+ var nulled = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_happy\" WHERE \"payload\" IS NULL").get();
73
+ check("happy erase NULLed the sealed payload", nulled.n === 3);
74
+ var listed = ret.list();
75
+ check("list() surfaces the declared rule", listed.length === 1 && listed[0].name === "happy");
76
+ check("list() reports default batchSize 500", listed[0].batchSize === 500);
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Audit-on path — exercises _emit + the auditInstance branch of create().
81
+ // ---------------------------------------------------------------------------
82
+ async function testAuditOnEmits() {
83
+ b.cryptoField.registerTable("ret_audit", { sealedFields: ["payload"], rowIdField: "_id" });
84
+ _seedTable("ret_audit", 1);
85
+ // audit: an instance → auditInstance = the passed object (not the lazy singleton).
86
+ var ret = b.retention.create({ db: b.db, audit: b.audit });
87
+ ret.declare({ name: "audit-on", table: "ret_audit", ageField: "createdAt", ttlMs: DAYS90, action: "erase" });
88
+ var summary = await ret.run("audit-on");
89
+ check("audit-on sweep still processes the row", summary.processed === 1);
90
+ // audit: true → auditOn true but auditInstance null (lazy audit() sink).
91
+ var ret2 = b.retention.create({ db: b.db, audit: true });
92
+ ret2.declare({ name: "audit-true", table: "ret_audit", ageField: "createdAt", ttlMs: DAYS90, action: "erase" });
93
+ var s2 = await ret2.run("audit-true");
94
+ check("audit:true controller runs without throwing", !!s2);
95
+ }
96
+
97
+ // ---------------------------------------------------------------------------
98
+ // delete action + keyset-pagination cursor across multiple batches.
99
+ // ---------------------------------------------------------------------------
100
+ async function testDeleteActionMultiBatch() {
101
+ _seedTable("ret_del", 5); // not registered for sealing — plain delete
102
+ var ret = b.retention.create({ db: b.db, audit: false });
103
+ ret.declare({ name: "del", table: "ret_del", ageField: "createdAt", ttlMs: DAYS90, action: "delete", batchSize: 2 });
104
+ var summary = await ret.run("del");
105
+ check("delete multi-batch scanned every row once", summary.scanned === 5);
106
+ check("delete multi-batch processed every row", summary.processed === 5);
107
+ var left = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_del\"").get();
108
+ check("delete removed every past-TTL row", left.n === 0);
109
+ }
110
+
111
+ // ---------------------------------------------------------------------------
112
+ // soft-delete action — writes softDeleteField; candidate query whereNull it.
113
+ // ---------------------------------------------------------------------------
114
+ async function testSoftDeleteAction() {
115
+ _seedTable("ret_soft", 3, { softCol: "deletedAt" });
116
+ var ret = b.retention.create({ db: b.db, audit: false });
117
+ ret.declare({ name: "soft", table: "ret_soft", ageField: "createdAt", ttlMs: DAYS90,
118
+ action: "soft-delete", softDeleteField: "deletedAt" });
119
+ // dry-run first: would-soft-delete without stamping the column.
120
+ var pv = await ret.run("soft", { dryRun: true });
121
+ check("soft-delete dry-run would-process without stamping", pv.processed === 3);
122
+ var unstamped = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_soft\" WHERE \"deletedAt\" IS NULL").get();
123
+ check("soft-delete dry-run stamped nothing", unstamped.n === 3);
124
+ var summary = await ret.run("soft");
125
+ check("soft-delete processed every row", summary.processed === 3);
126
+ var stamped = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_soft\" WHERE \"deletedAt\" IS NOT NULL").get();
127
+ check("soft-delete stamped the timestamp column", stamped.n === 3);
128
+ // A second sweep skips the already-soft-deleted rows (whereNull excludes them).
129
+ var again = await ret.run("soft");
130
+ check("second soft-delete sweep scans nothing (already stamped)", again.scanned === 0);
131
+ }
132
+
133
+ // soft-delete action declared WITHOUT softDeleteField → per-row throw, captured
134
+ // into summary.errors (the run loop's defensive per-row catch + warning outcome).
135
+ async function testSoftDeleteMissingField() {
136
+ _seedTable("ret_soft_bad", 2);
137
+ var ret = b.retention.create({ db: b.db, audit: false });
138
+ ret.declare({ name: "soft-bad", table: "ret_soft_bad", ageField: "createdAt", ttlMs: DAYS90,
139
+ action: "soft-delete" }); // no softDeleteField
140
+ var summary = await ret.run("soft-bad");
141
+ check("soft-delete-without-field records a per-row error", summary.errors.length === 2);
142
+ check("soft-delete-without-field processed nothing", summary.processed === 0);
143
+ check("soft-delete-without-field error names the missing field",
144
+ /softDeleteField/.test(summary.errors[0].reason || ""));
145
+ }
146
+
147
+ // ---------------------------------------------------------------------------
148
+ // custom function action — real path, dry-run path, error path, list label.
149
+ // ---------------------------------------------------------------------------
150
+ async function testCustomActionFn() {
151
+ _seedTable("ret_custom", 2);
152
+ var seen = [];
153
+ var ret = b.retention.create({ db: b.db, audit: false });
154
+ ret.declare({ name: "custom", table: "ret_custom", ageField: "createdAt", ttlMs: DAYS90,
155
+ action: function (row) { seen.push(row._id); return { customAction: 1, id: row._id }; } });
156
+ var summary = await ret.run("custom");
157
+ check("custom action processed every row", summary.processed === 2);
158
+ check("custom action invoked once per row", seen.length === 2);
159
+ check("custom rule reports action 'custom'", summary.action === "custom");
160
+ check("list() reports <custom> for a function action",
161
+ ret.list()[0].action === "<custom>");
162
+ // dry-run: the function must NOT be invoked (wouldCustomAction shape).
163
+ seen.length = 0;
164
+ var preview = await ret.run("custom", { dryRun: true });
165
+ check("custom dry-run would-process without invoking the fn",
166
+ preview.processed === 2 && seen.length === 0);
167
+
168
+ // A custom action returning nothing → the { customAction: 1 } default shape.
169
+ _seedTable("ret_custom_void", 1);
170
+ var ret0 = b.retention.create({ db: b.db, audit: false });
171
+ ret0.declare({ name: "custom-void", table: "ret_custom_void", ageField: "createdAt", ttlMs: DAYS90,
172
+ action: function () { /* returns undefined */ } });
173
+ var s0 = await ret0.run("custom-void");
174
+ check("custom action returning nothing still counts as processed", s0.processed === 1);
175
+
176
+ // A throwing custom action lands in summary.errors, not an unhandled reject.
177
+ _seedTable("ret_custom_err", 2);
178
+ var ret2 = b.retention.create({ db: b.db, audit: false });
179
+ ret2.declare({ name: "custom-err", table: "ret_custom_err", ageField: "createdAt", ttlMs: DAYS90,
180
+ action: function () { throw new Error("boom-in-custom"); } });
181
+ var s2 = await ret2.run("custom-err");
182
+ check("throwing custom action captured per-row (not fatal)", s2.errors.length === 2);
183
+ check("throwing custom action surfaces the reason", /boom-in-custom/.test(s2.errors[0].reason || ""));
184
+
185
+ // An error carrying an empty message → the per-row reason falls back to
186
+ // String(e) rather than storing "".
187
+ _seedTable("ret_custom_empty", 1);
188
+ var ret3 = b.retention.create({ db: b.db, audit: false });
189
+ ret3.declare({ name: "custom-empty", table: "ret_custom_empty", ageField: "createdAt", ttlMs: DAYS90,
190
+ action: function () { throw new Error(""); } });
191
+ var s3 = await ret3.run("custom-empty");
192
+ check("empty-message error still records a non-empty per-row reason",
193
+ s3.errors.length === 1 && typeof s3.errors[0].reason === "string" && s3.errors[0].reason.length > 0);
194
+ }
195
+
196
+ // ---------------------------------------------------------------------------
197
+ // cascade fan-out — real DELETE + dry-run COUNT of child rows.
198
+ // ---------------------------------------------------------------------------
199
+ async function testCascade() {
200
+ _seedTable("ret_parent", 2);
201
+ b.db.prepare("CREATE TABLE \"ret_child\" (\"_id\" TEXT PRIMARY KEY, \"parentId\" TEXT)").run();
202
+ b.db.prepare("INSERT INTO \"ret_child\" (\"_id\", \"parentId\") VALUES ('c-0','r-0')").run();
203
+ b.db.prepare("INSERT INTO \"ret_child\" (\"_id\", \"parentId\") VALUES ('c-1','r-0')").run();
204
+ b.db.prepare("INSERT INTO \"ret_child\" (\"_id\", \"parentId\") VALUES ('c-2','r-1')").run();
205
+ var ret = b.retention.create({ db: b.db, audit: false });
206
+ ret.declare({ name: "casc", table: "ret_parent", ageField: "createdAt", ttlMs: DAYS90,
207
+ action: "delete", cascade: [{ table: "ret_child", foreignKey: "parentId" }] });
208
+
209
+ // dry-run first: counts children, deletes nothing.
210
+ var preview = await ret.run("casc", { dryRun: true });
211
+ check("cascade dry-run scanned the parents", preview.scanned === 2);
212
+ var childPre = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_child\"").get();
213
+ check("cascade dry-run left every child row intact", childPre.n === 3);
214
+
215
+ // real run: deletes parents + cascades to children.
216
+ var summary = await ret.run("casc");
217
+ check("cascade real run processed the parents", summary.processed === 2);
218
+ var childPost = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_child\"").get();
219
+ check("cascade real run fanned the delete into children", childPost.n === 0);
220
+
221
+ // erase action + cascade — the erase path also fans the FK edge out.
222
+ b.cryptoField.registerTable("ret_ec_parent", { sealedFields: ["payload"], rowIdField: "_id" });
223
+ _seedTable("ret_ec_parent", 2);
224
+ b.db.prepare("CREATE TABLE \"ret_ec_child\" (\"_id\" TEXT PRIMARY KEY, \"pid\" TEXT)").run();
225
+ b.db.prepare("INSERT INTO \"ret_ec_child\" (\"_id\", \"pid\") VALUES ('ec-0','r-0')").run();
226
+ b.db.prepare("INSERT INTO \"ret_ec_child\" (\"_id\", \"pid\") VALUES ('ec-1','r-1')").run();
227
+ var retE = b.retention.create({ db: b.db, audit: false });
228
+ retE.declare({ name: "ec", table: "ret_ec_parent", ageField: "createdAt", ttlMs: DAYS90,
229
+ action: "erase", cascade: [{ table: "ret_ec_child", foreignKey: "pid" }] });
230
+ var eSummary = await retE.run("ec");
231
+ check("erase+cascade processed the parents", eSummary.processed === 2);
232
+ var ecChild = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_ec_child\"").get();
233
+ check("erase+cascade fanned the delete into children", ecChild.n === 0);
234
+ var ecParent = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_ec_parent\" WHERE \"payload\" IS NULL").get();
235
+ check("erase+cascade NULLed the parent sealed column", ecParent.n === 2);
236
+ }
237
+
238
+ // ---------------------------------------------------------------------------
239
+ // erase with derived-hash columns — NULLs the sealed field AND its hash sibling.
240
+ // ---------------------------------------------------------------------------
241
+ async function testEraseWithDerivedHash() {
242
+ b.cryptoField.registerTable("ret_dh", {
243
+ sealedFields: ["email"],
244
+ rowIdField: "_id",
245
+ derivedHashes: { emailHash: { from: "email", normalize: function (v) { return String(v).toLowerCase(); } } },
246
+ });
247
+ b.db.prepare("CREATE TABLE \"ret_dh\" (\"_id\" TEXT PRIMARY KEY, \"createdAt\" INTEGER, " +
248
+ "\"email\" TEXT, \"emailHash\" TEXT, \"__erasedAt\" INTEGER)").run();
249
+ var longAgo = LONG_AGO();
250
+ for (var i = 0; i < 2; i++) {
251
+ b.db.prepare("INSERT INTO \"ret_dh\" (\"_id\",\"createdAt\",\"email\",\"emailHash\",\"__erasedAt\") VALUES (?,?,?,?,NULL)")
252
+ .run("d-" + i, longAgo, "user" + i + "@x.test", "hash-" + i);
253
+ }
254
+ var ret = b.retention.create({ db: b.db, audit: false });
255
+ ret.declare({ name: "dh", table: "ret_dh", ageField: "createdAt", ttlMs: DAYS90, action: "erase" });
256
+ var summary = await ret.run("dh");
257
+ check("derived-hash erase processed every row", summary.processed === 2);
258
+ var nulled = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_dh\" WHERE \"email\" IS NULL AND \"emailHash\" IS NULL").get();
259
+ check("derived-hash erase NULLed both the sealed field and its hash sibling", nulled.n === 2);
260
+ }
261
+
262
+ // ---------------------------------------------------------------------------
263
+ // multi-stage routing — earliest-cutoff selection + warn stage + stageBreakdown.
264
+ // ---------------------------------------------------------------------------
265
+ async function testMultiStage() {
266
+ // Rows aged ~400d. Stages: warn at 90d, delete at 300d. Both crossed → the
267
+ // most-aggressive due stage (delete) wins.
268
+ _seedTable("ret_stage", 2);
269
+ var ret = b.retention.create({ db: b.db, audit: false });
270
+ // ttlMs deliberately larger than the smallest stage atMs so the run() cutoff
271
+ // computation walks the stages and picks the earliest stage threshold.
272
+ ret.declare({ name: "stage", table: "ret_stage", ageField: "createdAt", ttlMs: b.constants.TIME.days(400),
273
+ action: "delete",
274
+ stages: [ { atMs: b.constants.TIME.days(90), action: "warn" },
275
+ { atMs: b.constants.TIME.days(300), action: "delete" } ] });
276
+ var summary = await ret.run("stage");
277
+ check("multi-stage scanned the candidate rows", summary.scanned === 2);
278
+ check("multi-stage routed to the most-aggressive due stage (delete)",
279
+ summary.stageBreakdown.delete === 2);
280
+ var left = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_stage\"").get();
281
+ check("multi-stage delete removed the rows", left.n === 0);
282
+
283
+ // warn-only: a young row that crossed only the warn stage → warned, no write.
284
+ b.db.prepare("CREATE TABLE \"ret_warn\" (\"_id\" TEXT PRIMARY KEY, \"createdAt\" INTEGER, \"payload\" TEXT, \"__erasedAt\" INTEGER)").run();
285
+ var midAge = Date.now() - b.constants.TIME.days(120); // past warn(90) but before delete(300)
286
+ b.db.prepare("INSERT INTO \"ret_warn\" (\"_id\",\"createdAt\",\"payload\",\"__erasedAt\") VALUES ('w-0',?, 'p', NULL)").run(midAge);
287
+ var ret2 = b.retention.create({ db: b.db, audit: false });
288
+ ret2.declare({ name: "warn", table: "ret_warn", ageField: "createdAt", ttlMs: DAYS90,
289
+ action: "delete",
290
+ stages: [ { atMs: b.constants.TIME.days(90), action: "warn" },
291
+ { atMs: b.constants.TIME.days(300), action: "delete" } ] });
292
+ var s2 = await ret2.run("warn");
293
+ check("warn stage marks the row warned (no delete)", s2.stageBreakdown.warn === 1);
294
+ var stillHere = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_warn\"").get();
295
+ check("warn stage left the row in place", stillHere.n === 1);
296
+ }
297
+
298
+ // ---------------------------------------------------------------------------
299
+ // legal-hold — per-row field skip.
300
+ // ---------------------------------------------------------------------------
301
+ async function testLegalHoldPerRowField() {
302
+ _seedTable("ret_hold", 3, { holdCol: "onHold", hold: true });
303
+ var ret = b.retention.create({ db: b.db, audit: false });
304
+ ret.declare({ name: "hold", table: "ret_hold", ageField: "createdAt", ttlMs: DAYS90,
305
+ action: "delete", legalHoldField: "onHold" });
306
+ var summary = await ret.run("hold");
307
+ check("per-row legal hold honoured on every row", summary.legalHoldsHonored === 3);
308
+ check("per-row legal hold processed nothing", summary.processed === 0);
309
+ var intact = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_hold\"").get();
310
+ check("per-row legal hold left every row intact", intact.n === 3);
311
+ }
312
+
313
+ // legal-hold — subject-level registry consult (b.legalHold singleton).
314
+ async function testLegalHoldSubjectRegistry() {
315
+ _seedTable("ret_subj", 2, { subjectCol: "userId", subject: "held-user" });
316
+ var holds = b.legalHold.create({ db: b.db, audit: false });
317
+ try {
318
+ var placed = holds.place("held-user", { reason: "SEC subpoena 24-cv-01933", citation: "SEC-Rule-17a-4" });
319
+ check("legal-hold placed on the subject", placed && placed.placed === true);
320
+ check("registry reports the subject held", holds.isHeld("held-user") === true);
321
+ var ret = b.retention.create({ db: b.db, audit: false });
322
+ ret.declare({ name: "subj", table: "ret_subj", ageField: "createdAt", ttlMs: DAYS90,
323
+ action: "delete", subjectField: "userId" });
324
+ var summary = await ret.run("subj");
325
+ check("subject-registry hold honoured on every row", summary.legalHoldsHonored === 2);
326
+ check("subject-registry hold processed nothing", summary.processed === 0);
327
+ var intact = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_subj\"").get();
328
+ check("subject-registry hold left every row intact", intact.n === 2);
329
+ } finally {
330
+ // Don't leak the process-global singleton into sibling suite files.
331
+ if (b.legalHold && typeof b.legalHold._resetForTest === "function") b.legalHold._resetForTest();
332
+ }
333
+ }
334
+
335
+ // ---------------------------------------------------------------------------
336
+ // erase on a table with no sealed columns → falls back to hard delete.
337
+ // ---------------------------------------------------------------------------
338
+ async function testEraseFallbackToDelete() {
339
+ _seedTable("ret_nosealed", 2); // not registered → getSealedFields === []
340
+ var ret = b.retention.create({ db: b.db, audit: false });
341
+ ret.declare({ name: "nosealed", table: "ret_nosealed", ageField: "createdAt", ttlMs: DAYS90, action: "erase" });
342
+ var summary = await ret.run("nosealed");
343
+ check("erase-with-no-sealed-columns processed the rows", summary.processed === 2);
344
+ var left = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_nosealed\"").get();
345
+ check("erase-with-no-sealed-columns fell back to a hard delete", left.n === 0);
346
+ }
347
+
348
+ // ---------------------------------------------------------------------------
349
+ // candidate-query fallback when the table has no __erasedAt column.
350
+ // ---------------------------------------------------------------------------
351
+ async function testNoErasedAtColumnFallback() {
352
+ _seedTable("ret_noerased", 3, { withoutErasedAt: true });
353
+ var ret = b.retention.create({ db: b.db, audit: false });
354
+ ret.declare({ name: "noerased", table: "ret_noerased", ageField: "createdAt", ttlMs: DAYS90, action: "delete" });
355
+ var summary = await ret.run("noerased");
356
+ check("no-__erasedAt table falls back to the plain candidate query", summary.scanned === 3);
357
+ check("no-__erasedAt table still processes rows", summary.processed === 3);
358
+ }
359
+
360
+ // ---------------------------------------------------------------------------
361
+ // preview() — dry-run convenience wrapper, no concurrency-lock consumption.
362
+ // ---------------------------------------------------------------------------
363
+ async function testPreview() {
364
+ b.cryptoField.registerTable("ret_preview", { sealedFields: ["payload"], rowIdField: "_id" });
365
+ _seedTable("ret_preview", 2);
366
+ var ret = b.retention.create({ db: b.db, audit: false });
367
+ ret.declare({ name: "prev", table: "ret_preview", ageField: "createdAt", ttlMs: DAYS90, action: "erase" });
368
+ var preview = await ret.preview("prev");
369
+ check("preview reports would-process count", preview.processed === 2 && preview.dryRun === true);
370
+ var intact = b.db.prepare("SELECT COUNT(*) AS n FROM \"ret_preview\" WHERE \"payload\" IS NOT NULL").get();
371
+ check("preview mutated nothing", intact.n === 2);
372
+ }
373
+
374
+ // ---------------------------------------------------------------------------
375
+ // concurrency lock — an in-flight sweep is not re-entered.
376
+ // ---------------------------------------------------------------------------
377
+ async function testConcurrencyLock() {
378
+ _seedTable("ret_lock", 1);
379
+ var release;
380
+ var gate = new Promise(function (res) { release = res; });
381
+ var ret = b.retention.create({ db: b.db, audit: false });
382
+ ret.declare({ name: "lock", table: "ret_lock", ageField: "createdAt", ttlMs: DAYS90,
383
+ action: async function () { await gate; return { customAction: 1 }; } });
384
+ var p1 = ret.run("lock"); // suspends inside the custom action with running[name]=true
385
+ var r2 = await ret.run("lock"); // sees the lock → skipped
386
+ check("concurrent sweep is skipped", r2.skipped === true);
387
+ check("concurrent sweep names the reason", r2.reason === "concurrent-sweep-in-progress");
388
+ release();
389
+ var r1 = await p1;
390
+ check("the in-flight sweep completes after release", r1.processed === 1);
391
+ // The lock is cleared afterwards — a follow-up sweep runs normally.
392
+ var r3 = await ret.run("lock");
393
+ check("lock released after completion (follow-up sweep runs)", r3.skipped !== true);
394
+ }
395
+
396
+ // ---------------------------------------------------------------------------
397
+ // runAll — success + the per-rule failure branch (rule on a missing table).
398
+ // ---------------------------------------------------------------------------
399
+ async function testRunAll() {
400
+ _seedTable("ret_all", 2);
401
+ var ret = b.retention.create({ db: b.db, audit: false });
402
+ ret.declare({ name: "all-ok", table: "ret_all", ageField: "createdAt", ttlMs: DAYS90, action: "delete" });
403
+ // A valid identifier that names a table that does not exist → SWEEP_FAILED,
404
+ // caught by runAll into a { name, error } entry rather than aborting the batch.
405
+ ret.declare({ name: "all-ghost", table: "ghost_table_absent", ageField: "createdAt", ttlMs: DAYS90, action: "delete" });
406
+ var summaries = await ret.runAll();
407
+ check("runAll returns one summary per rule", summaries.length === 2);
408
+ var ok = summaries.filter(function (s) { return s.name === "all-ok"; })[0];
409
+ var ghost = summaries.filter(function (s) { return s.name === "all-ghost"; })[0];
410
+ check("runAll ran the healthy rule", ok && ok.processed === 2);
411
+ check("runAll captured the failing rule as an error entry", ghost && typeof ghost.error === "string");
412
+ }
413
+
414
+ // run() on a rule that fails mid-sweep throws SWEEP_FAILED.
415
+ async function testSweepFailedThrows() {
416
+ var ret = b.retention.create({ db: b.db, audit: false });
417
+ ret.declare({ name: "boom", table: "another_absent_table", ageField: "createdAt", ttlMs: DAYS90, action: "delete" });
418
+ var threw = null;
419
+ try { await ret.run("boom"); } catch (e) { threw = e; }
420
+ check("sweep against a missing table throws SWEEP_FAILED",
421
+ threw !== null && /SWEEP_FAILED|sweep failed/.test((threw && (threw.code || threw.message)) || ""));
422
+ // The lock is released even on failure — a retry is not permanently blocked.
423
+ var threw2 = null;
424
+ try { await ret.run("boom"); } catch (e) { threw2 = e; }
425
+ check("failed sweep released the lock (retry reaches the same failure, not a skip)",
426
+ threw2 !== null && !(threw2 && threw2.skipped));
427
+ }
428
+
429
+ // ---------------------------------------------------------------------------
430
+ // create() / run() entry-point guards.
431
+ // ---------------------------------------------------------------------------
432
+ function testCreateBadOpt() {
433
+ _expectThrow("create() with no arguments throws BAD_OPT",
434
+ function () { b.retention.create(); }, /db is required|BAD_OPT/);
435
+ _expectThrow("create() with no db throws BAD_OPT",
436
+ function () { b.retention.create({ audit: false }); }, /db is required|BAD_OPT/);
437
+ _expectThrow("create() with a db lacking .prepare throws BAD_OPT",
438
+ function () { b.retention.create({ db: {}, audit: false }); }, /db is required|BAD_OPT/);
439
+ }
440
+
441
+ async function testNoSuchRule() {
442
+ var ret = b.retention.create({ db: b.db, audit: false });
443
+ var threw = null;
444
+ try { await ret.run("never-declared"); } catch (e) { threw = e; }
445
+ check("run() on an undeclared rule throws NO_SUCH_RULE",
446
+ threw !== null && /NO_SUCH_RULE|not declared/.test((threw && (threw.code || threw.message)) || ""));
447
+ }
448
+
449
+ function testDuplicateRule() {
450
+ var ret = b.retention.create({ db: b.db, audit: false });
451
+ ret.declare({ name: "dup", table: "ret_dup", ageField: "createdAt", ttlMs: DAYS90, action: "delete" });
452
+ _expectThrow("declaring the same rule name twice throws DUPLICATE_RULE",
453
+ function () { ret.declare({ name: "dup", table: "ret_dup", ageField: "createdAt", ttlMs: DAYS90, action: "delete" }); },
454
+ /DUPLICATE_RULE|already declared/);
455
+ }
456
+
457
+ // ---------------------------------------------------------------------------
458
+ // _handleDialect — operator handle advertising a dialect (fn / string / throw).
459
+ // ---------------------------------------------------------------------------
460
+ function testHandleDialect() {
461
+ function wrap(dialect) {
462
+ return { prepare: function () { return b.db.prepare.apply(b.db, arguments); }, dialect: dialect };
463
+ }
464
+ // All resolve to "sqlite" so the emitted SQL still runs against the real handle.
465
+ check("dialect() returning a string is threaded through",
466
+ !!b.retention.create({ db: wrap(function () { return "sqlite"; }), audit: false }));
467
+ check("dialect() returning a non-string falls back to sqlite",
468
+ !!b.retention.create({ db: wrap(function () { return 123; }), audit: false }));
469
+ check("dialect() throwing falls back to sqlite",
470
+ !!b.retention.create({ db: wrap(function () { throw new Error("no dialect"); }), audit: false }));
471
+ check("dialect as a string property is honoured",
472
+ !!b.retention.create({ db: { prepare: b.db.prepare.bind(b.db), dialect: "sqlite" }, audit: false }));
473
+ }
474
+
475
+ // ---------------------------------------------------------------------------
476
+ // _validateRule — the full rejection battery (config-time throws).
477
+ // ---------------------------------------------------------------------------
478
+ function testRuleValidation() {
479
+ var ret = b.retention.create({ db: b.db, audit: false });
480
+ function bad(label, rule, matcher) {
481
+ _expectThrow(label, function () { ret.declare(rule); }, matcher || /BAD_RULE/);
482
+ }
483
+ bad("non-object rule rejected", null, /rule must be an object|BAD_RULE/);
484
+ bad("non-object rule (string) rejected", "nope", /rule must be an object|BAD_RULE/);
485
+ bad("missing name rejected", { table: "t", ageField: "createdAt", ttlMs: 1, action: "delete" }, /rule\.name/);
486
+ bad("empty name rejected", { name: "", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete" }, /rule\.name/);
487
+ bad("missing table rejected", { name: "n", ageField: "createdAt", ttlMs: 1, action: "delete" }, /rule\.table/);
488
+ bad("SQLi table identifier rejected",
489
+ { name: "n", table: "users\"; DROP TABLE audit_log;--", ageField: "createdAt", ttlMs: 1, action: "delete" },
490
+ /safe SQL identifier/);
491
+ bad("missing ageField rejected", { name: "n", table: "t", ttlMs: 1, action: "delete" }, /rule\.ageField/);
492
+ bad("SQLi ageField identifier rejected",
493
+ { name: "n", table: "t", ageField: "a b", ttlMs: 1, action: "delete" }, /safe SQL identifier/);
494
+ bad("zero ttlMs rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 0, action: "delete" }, /ttlMs/);
495
+ bad("negative ttlMs rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: -5, action: "delete" }, /ttlMs/);
496
+ bad("non-finite ttlMs rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: Infinity, action: "delete" }, /ttlMs/);
497
+ bad("non-number ttlMs rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: "90d", action: "delete" }, /ttlMs/);
498
+ bad("non-string/non-fn action rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: 5 }, /rule\.action/);
499
+ bad("unknown action string rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "shred" }, /erase|delete|soft-delete/);
500
+ bad("zero batchSize rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", batchSize: 0 }, /batchSize/);
501
+ bad("non-int batchSize rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", batchSize: 2.5 }, /batchSize/);
502
+ bad("empty softDeleteField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", softDeleteField: "" }, /softDeleteField/);
503
+ bad("non-string softDeleteField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", softDeleteField: 7 }, /softDeleteField/);
504
+ bad("SQLi softDeleteField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", softDeleteField: "a;b" }, /safe SQL identifier/);
505
+ bad("empty legalHoldField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", legalHoldField: "" }, /legalHoldField/);
506
+ bad("SQLi legalHoldField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", legalHoldField: "x y" }, /safe SQL identifier/);
507
+ bad("empty subjectField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", subjectField: "" }, /subjectField/);
508
+ bad("SQLi subjectField rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", subjectField: "u-d" }, /safe SQL identifier/);
509
+ bad("non-array cascade rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", cascade: {} }, /cascade/);
510
+ bad("empty cascade rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", cascade: [] }, /cascade/);
511
+ bad("malformed cascade entry rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", cascade: [{ table: "c" }] }, /cascade/);
512
+ bad("SQLi cascade table rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", cascade: [{ table: "c;x", foreignKey: "fk" }] }, /safe SQL identifier/);
513
+ bad("SQLi cascade fk rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", cascade: [{ table: "c", foreignKey: "f k" }] }, /safe SQL identifier/);
514
+ bad("non-array stages rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", stages: {} }, /stages/);
515
+ bad("empty stages rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", stages: [] }, /stages/);
516
+ bad("bad stage atMs rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", stages: [{ atMs: 0, action: "warn" }] }, /atMs/);
517
+ bad("bad stage action type rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", stages: [{ atMs: 5, action: 9 }] }, /stages\[0\]\.action/);
518
+ bad("unknown stage action string rejected", { name: "n", table: "t", ageField: "createdAt", ttlMs: 1, action: "delete", stages: [{ atMs: 5, action: "purge" }] }, /erase|delete|soft-delete|warn/);
519
+ }
520
+
521
+ // ---------------------------------------------------------------------------
522
+ // Posture helpers — complianceFloor / applyPosture / activePosture.
523
+ // ---------------------------------------------------------------------------
524
+ function testPostureHelpers() {
525
+ var r = b.retention;
526
+ var prior = r.activePosture();
527
+ try {
528
+ // Known floors.
529
+ check("complianceFloor(hipaa) returns the 6-year floor",
530
+ r.complianceFloor("hipaa") === b.constants.TIME.days(365 * 6));
531
+ check("complianceFloor candidate > floor keeps candidate",
532
+ r.complianceFloor("pci-dss", b.constants.TIME.days(400)) === b.constants.TIME.days(400));
533
+ check("complianceFloor candidate <= 0 falls back to floor",
534
+ r.complianceFloor("sox", 0) === b.constants.TIME.days(365 * 7));
535
+ // Unknown posture / bad posture type.
536
+ _expectThrow("complianceFloor(unknown) throws unknown-posture",
537
+ function () { r.complianceFloor("not-a-posture", 1000); }, /unknown-posture/);
538
+
539
+ // applyPosture records active state; complianceFloor inherits it.
540
+ r.applyPosture(null);
541
+ check("applyPosture(null) clears the active posture", r.activePosture() === null);
542
+ _expectThrow("complianceFloor with no active posture + omitted arg throws",
543
+ function () { r.complianceFloor(b.constants.TIME.days(30)); }, /bad-posture|posture must be a string/);
544
+
545
+ var applied = r.applyPosture("hipaa");
546
+ check("applyPosture(known) returns { posture, floorMs }",
547
+ applied && applied.posture === "hipaa" && applied.floorMs === b.constants.TIME.days(365 * 6));
548
+ check("activePosture reflects the applied posture", r.activePosture() === "hipaa");
549
+ check("complianceFloor(numeric-only) inherits the active posture",
550
+ r.complianceFloor(b.constants.TIME.days(30)) === b.constants.TIME.days(365 * 6));
551
+
552
+ // A posture string with no retention floor → floorMs null (no throw here;
553
+ // applyPosture records whatever the operator pins).
554
+ var noFloor = r.applyPosture("gdpr");
555
+ check("applyPosture(posture with no floor) reports floorMs null",
556
+ noFloor && noFloor.posture === "gdpr" && noFloor.floorMs === null);
557
+ } finally {
558
+ if (typeof prior === "string") r.applyPosture(prior); else r.applyPosture(null);
559
+ }
560
+ }
561
+
562
+ async function run() {
563
+ var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-retention-"));
564
+ await dbHelper.setupTestDb(tmpDir);
565
+ try {
566
+ await testHappyEraseSweep();
567
+ await testAuditOnEmits();
568
+ await testDeleteActionMultiBatch();
569
+ await testSoftDeleteAction();
570
+ await testSoftDeleteMissingField();
571
+ await testCustomActionFn();
572
+ await testCascade();
573
+ await testEraseWithDerivedHash();
574
+ await testMultiStage();
575
+ await testLegalHoldPerRowField();
576
+ await testLegalHoldSubjectRegistry();
577
+ await testEraseFallbackToDelete();
578
+ await testNoErasedAtColumnFallback();
579
+ await testPreview();
580
+ await testConcurrencyLock();
581
+ await testRunAll();
582
+ await testSweepFailedThrows();
583
+ testCreateBadOpt();
584
+ await testNoSuchRule();
585
+ testDuplicateRule();
586
+ testHandleDialect();
587
+ testRuleValidation();
588
+ testPostureHelpers();
589
+ } finally {
590
+ await dbHelper.teardownTestDb(tmpDir);
591
+ }
592
+ console.log("OK — retention (" + helpers.getChecks() + " checks)");
593
+ }
594
+
595
+ module.exports = { run: run };
596
+
597
+ if (require.main === module) {
598
+ run().then(function () { process.exit(0); })
599
+ .catch(function (err) { process.exitCode = 1; console.error(err && err.stack || err); });
600
+ }