@blamejs/blamejs-shop 0.4.31 → 0.4.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -1
  3. package/lib/asset-manifest.json +1 -1
  4. package/lib/vendor/MANIFEST.json +400 -282
  5. package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
  6. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
  7. package/lib/vendor/blamejs/.gitignore +6 -0
  8. package/lib/vendor/blamejs/CHANGELOG.md +28 -0
  9. package/lib/vendor/blamejs/MIGRATING.md +55 -0
  10. package/lib/vendor/blamejs/README.md +8 -6
  11. package/lib/vendor/blamejs/SECURITY.md +19 -3
  12. package/lib/vendor/blamejs/api-snapshot.json +2190 -664
  13. package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
  14. package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
  15. package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
  16. package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
  17. package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
  18. package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
  19. package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
  20. package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
  21. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
  22. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
  23. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
  24. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
  25. package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
  26. package/lib/vendor/blamejs/index.js +4 -0
  27. package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
  28. package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
  29. package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
  30. package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
  31. package/lib/vendor/blamejs/lib/api-key.js +158 -77
  32. package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
  33. package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
  34. package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
  35. package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
  36. package/lib/vendor/blamejs/lib/audit.js +259 -123
  37. package/lib/vendor/blamejs/lib/auth/elevation-grant.js +6 -2
  38. package/lib/vendor/blamejs/lib/auth/oauth.js +66 -9
  39. package/lib/vendor/blamejs/lib/auth/openid-federation.js +108 -47
  40. package/lib/vendor/blamejs/lib/auth/saml.js +6 -8
  41. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +36 -7
  42. package/lib/vendor/blamejs/lib/backup/index.js +45 -10
  43. package/lib/vendor/blamejs/lib/break-glass.js +355 -147
  44. package/lib/vendor/blamejs/lib/cache.js +174 -105
  45. package/lib/vendor/blamejs/lib/chain-writer.js +38 -16
  46. package/lib/vendor/blamejs/lib/cli.js +19 -14
  47. package/lib/vendor/blamejs/lib/cluster-provider-db.js +130 -104
  48. package/lib/vendor/blamejs/lib/cluster-storage.js +119 -22
  49. package/lib/vendor/blamejs/lib/cluster.js +119 -71
  50. package/lib/vendor/blamejs/lib/codepoint-class.js +23 -0
  51. package/lib/vendor/blamejs/lib/compliance.js +210 -4
  52. package/lib/vendor/blamejs/lib/consent.js +82 -29
  53. package/lib/vendor/blamejs/lib/constants.js +27 -11
  54. package/lib/vendor/blamejs/lib/credential-hash.js +9 -0
  55. package/lib/vendor/blamejs/lib/crypto-field.js +916 -156
  56. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
  57. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
  58. package/lib/vendor/blamejs/lib/db-query.js +882 -260
  59. package/lib/vendor/blamejs/lib/db-schema.js +228 -44
  60. package/lib/vendor/blamejs/lib/db.js +249 -99
  61. package/lib/vendor/blamejs/lib/dsr.js +385 -55
  62. package/lib/vendor/blamejs/lib/error-page.js +14 -1
  63. package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
  64. package/lib/vendor/blamejs/lib/external-db.js +549 -34
  65. package/lib/vendor/blamejs/lib/file-upload.js +52 -7
  66. package/lib/vendor/blamejs/lib/framework-error.js +20 -1
  67. package/lib/vendor/blamejs/lib/framework-files.js +73 -0
  68. package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
  69. package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
  70. package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
  71. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  72. package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
  73. package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
  74. package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
  75. package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
  76. package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
  77. package/lib/vendor/blamejs/lib/guard-email.js +47 -69
  78. package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
  79. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
  80. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
  81. package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
  82. package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
  83. package/lib/vendor/blamejs/lib/guard-html.js +53 -108
  84. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
  85. package/lib/vendor/blamejs/lib/guard-image.js +46 -103
  86. package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
  87. package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
  88. package/lib/vendor/blamejs/lib/guard-json.js +38 -108
  89. package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
  90. package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
  91. package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
  92. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
  93. package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
  94. package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
  95. package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
  96. package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
  97. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
  98. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
  99. package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
  100. package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
  101. package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
  102. package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
  105. package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
  106. package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
  107. package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
  108. package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
  109. package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
  110. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
  111. package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
  112. package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
  113. package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
  114. package/lib/vendor/blamejs/lib/guard-template.js +35 -172
  115. package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
  116. package/lib/vendor/blamejs/lib/guard-time.js +32 -154
  117. package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
  118. package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
  119. package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
  120. package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
  121. package/lib/vendor/blamejs/lib/http-client.js +37 -9
  122. package/lib/vendor/blamejs/lib/inbox.js +120 -107
  123. package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
  124. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
  125. package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
  126. package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
  128. package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
  129. package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
  130. package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
  131. package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
  132. package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
  133. package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
  134. package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
  136. package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
  137. package/lib/vendor/blamejs/lib/mail-store.js +293 -154
  138. package/lib/vendor/blamejs/lib/mail.js +8 -4
  139. package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
  140. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
  141. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
  142. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
  143. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
  144. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
  145. package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
  146. package/lib/vendor/blamejs/lib/migrations.js +108 -66
  147. package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
  148. package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
  149. package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
  150. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
  151. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
  152. package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
  153. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
  154. package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
  155. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
  156. package/lib/vendor/blamejs/lib/observability.js +124 -0
  157. package/lib/vendor/blamejs/lib/otel-export.js +12 -3
  158. package/lib/vendor/blamejs/lib/outbox.js +184 -83
  159. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
  160. package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
  161. package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
  162. package/lib/vendor/blamejs/lib/queue-local.js +225 -140
  163. package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
  164. package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
  165. package/lib/vendor/blamejs/lib/queue.js +7 -0
  166. package/lib/vendor/blamejs/lib/redact.js +68 -11
  167. package/lib/vendor/blamejs/lib/redis-client.js +160 -31
  168. package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
  169. package/lib/vendor/blamejs/lib/retention.js +117 -42
  170. package/lib/vendor/blamejs/lib/router.js +212 -5
  171. package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
  172. package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
  173. package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
  174. package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
  175. package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
  176. package/lib/vendor/blamejs/lib/safe-url.js +170 -3
  177. package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
  178. package/lib/vendor/blamejs/lib/scheduler.js +47 -12
  179. package/lib/vendor/blamejs/lib/seeders.js +122 -74
  180. package/lib/vendor/blamejs/lib/session-stores.js +42 -14
  181. package/lib/vendor/blamejs/lib/session.js +175 -77
  182. package/lib/vendor/blamejs/lib/sql.js +3842 -0
  183. package/lib/vendor/blamejs/lib/sse.js +26 -0
  184. package/lib/vendor/blamejs/lib/ssrf-guard.js +169 -4
  185. package/lib/vendor/blamejs/lib/static.js +177 -34
  186. package/lib/vendor/blamejs/lib/subject.js +96 -49
  187. package/lib/vendor/blamejs/lib/vault/index.js +3 -2
  188. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
  189. package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
  190. package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
  191. package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
  192. package/lib/vendor/blamejs/lib/websocket.js +35 -5
  193. package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
  194. package/lib/vendor/blamejs/package.json +2 -2
  195. package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
  196. package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
  197. package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
  198. package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
  199. package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
  200. package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
  201. package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
  202. package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
  203. package/lib/vendor/blamejs/release-notes/v0.15.7.json +43 -0
  204. package/lib/vendor/blamejs/scripts/check-services.js +21 -0
  205. package/lib/vendor/blamejs/scripts/gen-migrating.js +67 -0
  206. package/lib/vendor/blamejs/scripts/release.js +398 -38
  207. package/lib/vendor/blamejs/test/00-primitives.js +168 -0
  208. package/lib/vendor/blamejs/test/10-state.js +140 -14
  209. package/lib/vendor/blamejs/test/20-db.js +65 -2
  210. package/lib/vendor/blamejs/test/helpers/db.js +9 -0
  211. package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
  212. package/lib/vendor/blamejs/test/helpers/services.js +21 -0
  213. package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
  214. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
  215. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
  216. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
  217. package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
  218. package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
  219. package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
  220. package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
  221. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
  222. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
  223. package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
  224. package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
  225. package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
  226. package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
  227. package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
  228. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
  229. package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
  230. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
  231. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
  232. package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
  233. package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
  234. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
  235. package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
  236. package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
  237. package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
  238. package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
  239. package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
  240. package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
  241. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
  242. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
  243. package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
  244. package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
  245. package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
  246. package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
  247. package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
  248. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
  249. package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
  250. package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
  251. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
  252. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1196 -14
  253. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
  254. package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +18 -0
  255. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
  256. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
  257. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
  258. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
  259. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
  262. package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
  263. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
  264. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
  267. package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
  270. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
  275. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
  276. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
  277. package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
  278. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
  282. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
  283. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
  284. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
  286. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
  287. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
  288. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
  296. package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +59 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
  302. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +362 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-watchdog-stale-settle.test.js +71 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
  309. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
  315. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
  317. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
  318. package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
  319. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
  320. package/lib/vendor/blamejs/test/smoke.js +79 -21
  321. package/package.json +2 -2
  322. package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
  323. package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
  324. package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
  325. package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
  326. package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
  327. package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
  328. package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
  329. package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
  330. package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
  331. package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
  332. package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
  333. package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
  334. package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
  335. package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
  336. package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
  337. package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
  338. package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
  339. package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
  340. package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
  341. package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
  342. package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
  343. package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
@@ -53,6 +53,11 @@ var nodeUrl = require("node:url");
53
53
  var { URL } = require("node:url");
54
54
 
55
55
  var audit = lazyRequire(function () { return require("./audit"); });
56
+ // ssrf-guard requires safe-url at top of file (the SSRF gate parses through
57
+ // the framework's defensive URL parser); lazyRequire breaks that cycle so the
58
+ // canonicalizer can reuse ssrf-guard's IP-literal canonicalization without an
59
+ // at-load circular require.
60
+ var ssrfGuard = lazyRequire(function () { return require("./ssrf-guard"); });
56
61
 
57
62
  /**
58
63
  * @primitive b.safeUrl.ALLOW_HTTP_TLS
@@ -168,9 +173,9 @@ var ALLOW_ANY = Object.freeze(["http:", "https:", "ws:", "wss:"]);
168
173
  * Extends `FrameworkError`. Carries a stable `.code`:
169
174
  * `safe-url/missing` / `safe-url/too-long` / `safe-url/malformed` /
170
175
  * `safe-url/protocol-disallowed` / `safe-url/userinfo-disallowed` /
171
- * `safe-url/idn-homograph` / `safe-url/bad-opt`. HTTP middleware
172
- * inspects `.code` to translate the throw into a 400 without
173
- * leaking parser internals.
176
+ * `safe-url/idn-homograph` / `safe-url/uncanonicalizable` /
177
+ * `safe-url/bad-opt`. HTTP middleware inspects `.code` to translate
178
+ * the throw into a 400 without leaking parser internals.
174
179
  *
175
180
  * @example
176
181
  * var b = require("blamejs");
@@ -205,6 +210,38 @@ function _makeError(errorClass, code, message) {
205
210
  // payloads) override via opts.maxUrlLength.
206
211
  var DEFAULT_MAX_URL_LENGTH = C.BYTES.kib(8);
207
212
 
213
+ // RFC 3986 §6.2.2 percent-encoding normalization applied CONSERVATIVELY to a
214
+ // path segment string: uppercase the two hex digits of every valid escape
215
+ // (§6.2.2.2) and decode an escape of an unreserved character to its literal
216
+ // (§6.2.2.3). A malformed escape (`%`, `%g`, `%4`) is passed through verbatim
217
+ // so no information is invented. Query and fragment are NOT touched —
218
+ // reordering / re-decoding there can change application semantics (a `%26`
219
+ // inside a value is NOT the same as a literal `&`).
220
+ function _normalizePctPath(path) {
221
+ if (typeof path !== "string" || path.indexOf("%") === -1) return path;
222
+ var out = "";
223
+ for (var i = 0; i < path.length; i += 1) {
224
+ var ch = path.charAt(i);
225
+ if (ch === "%") {
226
+ // The escape's two hex digits — sliced to a fixed two-char window so
227
+ // the regex test runs on a length-bounded string (no ReDoS surface).
228
+ var pair = path.slice(i + 1, i + 3);
229
+ if (pair.length === 2 && codepointClass.HEX_PAIR_RE.test(pair)) {
230
+ var cc = parseInt(pair, 16);
231
+ if (codepointClass.isUnreserved(cc)) {
232
+ out += String.fromCharCode(cc);
233
+ } else {
234
+ out += "%" + pair.toUpperCase();
235
+ }
236
+ i += 2;
237
+ continue;
238
+ }
239
+ }
240
+ out += ch;
241
+ }
242
+ return out;
243
+ }
244
+
208
245
  /**
209
246
  * @primitive b.safeUrl.parse
210
247
  * @signature b.safeUrl.parse(url, opts?)
@@ -416,9 +453,139 @@ function format(url) {
416
453
  }
417
454
  }
418
455
 
456
+ /**
457
+ * @primitive b.safeUrl.canonicalize
458
+ * @signature b.safeUrl.canonicalize(input, opts?)
459
+ * @since 0.15.6
460
+ * @status stable
461
+ * @related b.safeUrl.parse, b.ssrfGuard.canonicalizeHost, b.ssrfGuard.checkUrl
462
+ *
463
+ * Return the single canonical, comparable form of a URL so two
464
+ * spellings of the same destination compare equal as strings. The use
465
+ * cases are host allowlists, dedup / cache keys, and SSRF pre-checks —
466
+ * exactly the places an attacker reaches for an obfuscated host
467
+ * (`http://0177.0.0.1/`, `http://2130706433/`, `http://[::ffff:7f00:1]/`,
468
+ * an IDN homograph, a trailing-dot or default-port variation) to slip
469
+ * past a naive `===` allowlist. Routing every comparison through one
470
+ * audited canonicalizer closes that class instead of leaving each
471
+ * caller to re-derive normalization (which is how the bypasses happen).
472
+ *
473
+ * The canonical form is built from `parse`'s defensive gates plus the
474
+ * security-relevant normalization set:
475
+ *
476
+ * - Scheme and host lowercased (the WHATWG URL parser does this).
477
+ * - Host IDN labels emitted as their punycode `xn--` A-label; a
478
+ * mixed-script / confusable host label THROWS exactly as
479
+ * `parse` does (a homograph is never silently passed) unless the
480
+ * caller opts in via `allowMixedScript` / `allowedScripts`.
481
+ * - A trailing dot on the host is removed (`example.com.` →
482
+ * `example.com`) — DNS-equivalent but breaks string comparison.
483
+ * - An IP-literal host in ANY notation collapses to one canonical
484
+ * string via `b.ssrfGuard.canonicalizeHost` (the SAME byte parser
485
+ * the SSRF classifier matches on): IPv4 decimal / octal / hex /
486
+ * shorthand → dotted-quad; IPv6 (incl. IPv4-mapped + any
487
+ * zero-compression) → RFC 5952 lower-hex, bracketed.
488
+ * - The default port for the scheme is stripped (`:80` http/ws,
489
+ * `:443` https/wss — the parser does this).
490
+ * - Path `.` / `..` segments resolved (WHATWG), then RFC 3986 §6.2.2
491
+ * percent-normalization applied to the path: hex digits uppercased,
492
+ * escapes of unreserved characters decoded. Query and fragment are
493
+ * left BYTE-FOR-BYTE as parsed — reordering or re-decoding there can
494
+ * change application semantics.
495
+ *
496
+ * Throws `SafeUrlError` (or `opts.errorClass`): the `parse` codes for a
497
+ * missing / too-long / malformed / disallowed-scheme / userinfo /
498
+ * homograph input, plus `safe-url/uncanonicalizable` when a parsed URL
499
+ * cannot be reduced to a safe canonical form. This is a config /
500
+ * entry-point validator — it THROWS on bad input, it does NOT return a
501
+ * best-effort string.
502
+ *
503
+ * @opts
504
+ * allowedSchemes: string[], // default ALLOW_ANY (http/https/ws/wss); canonicalize is a compare tool, not a fetch gate
505
+ * allowUserinfo: boolean, // default false; opt-in to keep user:pass@ (still discouraged)
506
+ * allowMixedScript: boolean, // default false; opt-in to mixed-script host labels
507
+ * allowedScripts: string[], // narrow mixed-script allowlist (e.g. ["latin","cyrillic"])
508
+ * maxUrlLength: number, // default 8192 (RFC 7230 §3.1.1)
509
+ * errorClass: Function, // throw this instead of SafeUrlError
510
+ *
511
+ * @example
512
+ * var b = require("blamejs");
513
+ *
514
+ * // Every obfuscated loopback spelling collapses to one string.
515
+ * b.safeUrl.canonicalize("http://0177.0.0.1/"); // → "http://127.0.0.1/"
516
+ * b.safeUrl.canonicalize("http://2130706433/"); // → "http://127.0.0.1/"
517
+ * b.safeUrl.canonicalize("http://127.1/"); // → "http://127.0.0.1/"
518
+ *
519
+ * // Case, default port, trailing dot, and `..` all normalize.
520
+ * b.safeUrl.canonicalize("https://Example.COM:443/a/../b");
521
+ * // → "https://example.com/b"
522
+ *
523
+ * // A disallowed scheme throws SafeUrlError.
524
+ * try { b.safeUrl.canonicalize("ftp://example.com/"); }
525
+ * catch (e) { e.code; } // → "safe-url/protocol-disallowed"
526
+ */
527
+ function canonicalize(input, opts) {
528
+ opts = opts || {};
529
+ var allowedSchemes = Array.isArray(opts.allowedSchemes) && opts.allowedSchemes.length > 0
530
+ ? opts.allowedSchemes
531
+ : ALLOW_ANY;
532
+
533
+ // Route through parse — it owns the length cap, the scheme allowlist,
534
+ // userinfo refusal, and the IDN-homograph defense. A parse throw (with
535
+ // its stable .code) propagates unchanged so callers branch on the same
536
+ // codes parse documents.
537
+ var parsed = parse(input, {
538
+ allowedProtocols: allowedSchemes,
539
+ maxUrlLength: opts.maxUrlLength,
540
+ allowUserinfo: opts.allowUserinfo,
541
+ allowMixedScript: opts.allowMixedScript,
542
+ allowedScripts: opts.allowedScripts,
543
+ errorClass: opts.errorClass,
544
+ });
545
+
546
+ try {
547
+ // The parser already lowercased the scheme + host, stripped the
548
+ // default port, emitted IDN as punycode, and resolved `.`/`..`. The
549
+ // canonicalizer adds: IP-literal collapse (shared with the SSRF
550
+ // classifier), trailing-dot removal, and path percent-normalization.
551
+ var scheme = parsed.protocol; // e.g. "https:"
552
+ var rawHost = parsed.hostname; // already lowercase / punycode / default-port-free
553
+ var canonHost = ssrfGuard().canonicalizeHost(rawHost);
554
+ // canonicalizeHost returns IPv6 UNbracketed; a URL authority needs the
555
+ // brackets back. net.isIP via the colon is a sufficient discriminator
556
+ // (a DNS label can't contain a colon).
557
+ var host = canonHost.indexOf(":") !== -1 ? "[" + canonHost + "]" : canonHost;
558
+
559
+ // Userinfo (`user:pass@`) is deliberately DROPPED from the canonical form.
560
+ // The canonical string is built to be compared, used as a dedup / cache
561
+ // key, or logged; carrying a credential into any of those leaks it, and
562
+ // the username/password are not part of the resource's target identity for
563
+ // an allowlist / SSRF decision. parse() already refuses userinfo unless
564
+ // allowUserinfo:true; even then, the canonical output omits it (never reads
565
+ // parsed.password), so two URLs that differ only in credentials canonicalize
566
+ // equal.
567
+
568
+ var port = parsed.port !== "" ? ":" + parsed.port : "";
569
+ var path = _normalizePctPath(parsed.pathname);
570
+ // Query + fragment: byte-for-byte as the parser emitted them. Reordering
571
+ // a query or re-decoding a value changes semantics — out of scope for a
572
+ // safe canonicalizer.
573
+ var query = parsed.search;
574
+ var fragment = parsed.hash;
575
+
576
+ return scheme + "//" + host + port + path + query + fragment;
577
+ } catch (e) {
578
+ if (e && e.isSafeUrlError) throw e;
579
+ throw _makeError(opts.errorClass, "safe-url/uncanonicalizable",
580
+ "safeUrl.canonicalize could not reduce the URL to a canonical form: " +
581
+ ((e && e.message) || String(e)));
582
+ }
583
+ }
584
+
419
585
  module.exports = {
420
586
  parse: parse,
421
587
  format: format,
588
+ canonicalize: canonicalize,
422
589
  SafeUrlError: SafeUrlError,
423
590
  ALLOW_HTTP_TLS: ALLOW_HTTP_TLS,
424
591
  ALLOW_HTTP_ALL: ALLOW_HTTP_ALL,
@@ -63,6 +63,7 @@
63
63
 
64
64
  var C = require("./constants");
65
65
  var { defineClass } = require("./framework-error");
66
+ var gateContract = require("./gate-contract");
66
67
 
67
68
  var SafeVcardError = defineClass("SafeVcardError", { alwaysPermanent: true });
68
69
 
@@ -90,12 +91,7 @@ var PROFILES = Object.freeze({
90
91
  }),
91
92
  });
92
93
 
93
- var COMPLIANCE_POSTURES = Object.freeze({
94
- hipaa: "strict",
95
- "pci-dss": "strict",
96
- gdpr: "strict",
97
- soc2: "strict",
98
- });
94
+ var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
99
95
 
100
96
  // Property-name allowlist per RFC 6350 §6 (vCard 4.0 property
101
97
  // registry) + RFC 2426 §3 (legacy 3.0 properties retained for
@@ -217,24 +213,6 @@ function parse(text, opts) {
217
213
  return { vcards: vcards };
218
214
  }
219
215
 
220
- /**
221
- * @primitive b.safeVcard.compliancePosture
222
- * @signature b.safeVcard.compliancePosture(name)
223
- * @since 0.9.81
224
- * @status stable
225
- * @related b.safeVcard.parse
226
- *
227
- * Map a compliance-posture name to its profile. Returns the profile
228
- * string for a known posture, `null` for unknown names.
229
- *
230
- * @example
231
- * b.safeVcard.compliancePosture("hipaa"); // -> "strict"
232
- * b.safeVcard.compliancePosture("loose"); // -> null
233
- */
234
- function compliancePosture(name) {
235
- return COMPLIANCE_POSTURES[name] || null;
236
- }
237
-
238
216
  // ---- Internal ----
239
217
 
240
218
  function _resolveCaps(opts) {
@@ -462,12 +440,19 @@ function _preview(s) {
462
440
  return s.length > 64 ? s.slice(0, 64) + "..." : s; // log-preview length cap
463
441
  }
464
442
 
465
- module.exports = {
466
- parse: parse,
467
- compliancePosture: compliancePosture,
468
- PROFILES: PROFILES,
469
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
470
- KNOWN_PROPERTIES: KNOWN_PROPERTIES,
471
- EMBED_PROPERTIES: EMBED_PROPERTIES,
472
- SafeVcardError: SafeVcardError,
473
- };
443
+ // compliancePosture is assembled by gateContract.defineParser below; its
444
+ // wiki section renders from the single-sourced @abiTemplate (defineParser)
445
+ // block in gate-contract.js, instantiated for this guard by the page
446
+ // generator.
447
+ module.exports = gateContract.defineParser({
448
+ name: "vcard",
449
+ entry: parse,
450
+ entryName: "parse",
451
+ errorClass: SafeVcardError,
452
+ profiles: PROFILES,
453
+ postures: COMPLIANCE_POSTURES,
454
+ extra: {
455
+ KNOWN_PROPERTIES: KNOWN_PROPERTIES,
456
+ EMBED_PROPERTIES: EMBED_PROPERTIES,
457
+ },
458
+ });
@@ -43,6 +43,7 @@ var lazyRequire = require("./lazy-require");
43
43
  var audit = lazyRequire(function () { return require("./audit"); });
44
44
  var log = lazyRequire(function () { return require("./log").boot("scheduler"); });
45
45
  var clusterStorage = require("./cluster-storage");
46
+ var sql = require("./sql");
46
47
  var validateOpts = require("./validate-opts");
47
48
  var C = require("./constants");
48
49
  var { SchedulerError } = require("./framework-error");
@@ -51,6 +52,18 @@ var DEFAULT_MAX_JOB_MS = C.TIME.minutes(10);
51
52
  var DEFAULT_TICK_RETENTION_MS = C.TIME.days(7);
52
53
  var DEFAULT_TICK_PRUNE_INTERVAL_MS = C.TIME.minutes(1);
53
54
 
55
+ // b.sql opts for every _blamejs_scheduler_ticks statement: thread the ACTIVE
56
+ // backend dialect (clusterStorage.dialect() — "sqlite" single-node,
57
+ // "postgres" | "mysql" in cluster mode) so the emitted identifier quoting +
58
+ // dialect idioms (ON CONFLICT DO NOTHING vs the MySQL no-op fold) match the
59
+ // backend the SQL dispatches to. Defaulting to "sqlite" works on Postgres
60
+ // only by accident (both double-quote identifiers) and emits the wrong
61
+ // quoting on MySQL. clusterStorage.execute still rewrites the bare table name
62
+ // + translates `?` placeholders at dispatch; this controls only the builder-
63
+ // side quoting + idiom selection. The table name stays BARE (no quoteName)
64
+ // so clusterStorage's prefix rewrite still fires.
65
+ function _ticksSqlOpts() { return { dialect: clusterStorage.dialect() }; }
66
+
54
67
  // ---- Cron parsing ----
55
68
 
56
69
  var CRON_SHORTHANDS = {
@@ -475,6 +488,10 @@ function create(opts) {
475
488
  lastError: null,
476
489
  running: false,
477
490
  runningSince: 0,
491
+ // Monotonic run tag. The watchdog and each fire bump it, so a run the
492
+ // watchdog abandoned can't clobber state / emit a stale settle event
493
+ // when its slow promise finally resolves.
494
+ runGeneration: 0,
478
495
  fires: 0,
479
496
  misses: 0, // skipped because previous run still in-flight
480
497
  nonLeaderSkips: 0,
@@ -497,7 +514,7 @@ function create(opts) {
497
514
  task.nextRun = Date.now() + spec.every;
498
515
  }
499
516
  task.exprDesc = "every " + spec.every + "ms" +
500
- (spec.baseline ? " from " + spec.baseline : "") +
517
+ (spec.baseline ? " anchored " + spec.baseline : "") +
501
518
  (tz ? " " + tz : "");
502
519
  }
503
520
 
@@ -527,6 +544,8 @@ function create(opts) {
527
544
  (maxJobMs / C.TIME.seconds(1)) + "s — forcing reset");
528
545
  } catch (_e) { /* logger best-effort */ }
529
546
  _emit("system.scheduler.task.watchdog", { name: task.name }, "failure");
547
+ // Supersede the abandoned run so its late settle is ignored.
548
+ task.runGeneration++;
530
549
  task.running = false;
531
550
  } else {
532
551
  task.misses++;
@@ -562,13 +581,23 @@ function create(opts) {
562
581
  var tickKey = task.name + ":" + nominalRun;
563
582
  var claimedBy = (typeof clusterInstance.currentNodeId === "function")
564
583
  ? clusterInstance.currentNodeId() : "unknown";
565
- clusterStorage.execute(
566
- "INSERT INTO _blamejs_scheduler_ticks " +
567
- "(tickKey, name, scheduledAtUnix, claimedAtUnix, claimedBy) " +
568
- "VALUES (?, ?, ?, ?, ?) " +
569
- "ON CONFLICT (tickKey) DO NOTHING",
570
- [tickKey, task.name, nominalRun, Date.now(), claimedBy]
571
- ).then(function (result) {
584
+ // BARE logical table name — clusterStorage rewrites _blamejs_scheduler_ticks
585
+ // to the configured prefix and placeholderizes the ? markers. The
586
+ // PRIMARY KEY race on tickKey deduplicates the split-brain window; the
587
+ // loser's ON CONFLICT DO NOTHING reports zero rowCount and skips.
588
+ var claimBuilt = sql.upsert("_blamejs_scheduler_ticks", _ticksSqlOpts()) // allow:hand-rolled-sql — bare logical name for clusterStorage rewrite
589
+ .columns(["tickKey", "name", "scheduledAtUnix", "claimedAtUnix", "claimedBy"])
590
+ .values({
591
+ tickKey: tickKey,
592
+ name: task.name,
593
+ scheduledAtUnix: nominalRun,
594
+ claimedAtUnix: Date.now(),
595
+ claimedBy: claimedBy,
596
+ })
597
+ .onConflict(["tickKey"])
598
+ .doNothing()
599
+ .toSql();
600
+ clusterStorage.execute(claimBuilt.sql, claimBuilt.params).then(function (result) {
572
601
  var won = (result && result.rowCount > 0);
573
602
  if (won) {
574
603
  _runFire(task);
@@ -604,10 +633,10 @@ function create(opts) {
604
633
  var threshold = Date.now() - (
605
634
  typeof olderThanMs === "number" ? olderThanMs : tickRetentionMs
606
635
  );
607
- var result = await clusterStorage.execute(
608
- "DELETE FROM _blamejs_scheduler_ticks WHERE scheduledAtUnix < ?",
609
- [threshold]
610
- );
636
+ var pruneBuilt = sql.delete("_blamejs_scheduler_ticks", _ticksSqlOpts()) // allow:hand-rolled-sql — bare logical name for clusterStorage rewrite
637
+ .where("scheduledAtUnix", "<", threshold)
638
+ .toSql();
639
+ var result = await clusterStorage.execute(pruneBuilt.sql, pruneBuilt.params);
611
640
  var removed = (result && result.rowCount) || 0;
612
641
  if (removed > 0) {
613
642
  _emit("system.scheduler.tick.pruned", {
@@ -642,6 +671,10 @@ function create(opts) {
642
671
  task.runningSince = Date.now();
643
672
  task.lastRun = new Date().toISOString();
644
673
  var startedAt = Date.now();
674
+ // Tag this run. The settle handlers below only write back if the tag still
675
+ // matches — so a run the watchdog reset (or a newer fire) can't clobber the
676
+ // current run's state or emit a stale success/failure when it settles late.
677
+ var gen = (task.runGeneration = (task.runGeneration || 0) + 1);
645
678
 
646
679
  var promise;
647
680
  try {
@@ -655,6 +688,7 @@ function create(opts) {
655
688
  }
656
689
 
657
690
  Promise.resolve(promise).then(function (_v) {
691
+ if (task.runGeneration !== gen) return; // watchdog/newer fire superseded this run
658
692
  task.running = false;
659
693
  task.runningSince = 0;
660
694
  task.lastFinish = new Date().toISOString();
@@ -666,6 +700,7 @@ function create(opts) {
666
700
  viaJob: !!task.job,
667
701
  });
668
702
  }, function (e) {
703
+ if (task.runGeneration !== gen) return; // watchdog/newer fire superseded this run
669
704
  task.running = false;
670
705
  task.runningSince = 0;
671
706
  task.lastFinish = new Date().toISOString();