@blamejs/blamejs-shop 0.4.56 → 0.4.57

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 (397) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +426 -366
  4. package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
  5. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  6. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
  7. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
  8. package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
  9. package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
  10. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
  11. package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
  12. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
  13. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  14. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  15. package/lib/vendor/blamejs/api-snapshot.json +1381 -4
  16. package/lib/vendor/blamejs/eslint.config.mjs +1 -0
  17. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
  18. package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
  19. package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
  20. package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
  21. package/lib/vendor/blamejs/index.js +2 -0
  22. package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
  23. package/lib/vendor/blamejs/lib/acme.js +6 -5
  24. package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
  25. package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
  26. package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
  27. package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
  28. package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
  29. package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
  30. package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
  31. package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
  32. package/lib/vendor/blamejs/lib/ai-input.js +2 -2
  33. package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
  34. package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
  35. package/lib/vendor/blamejs/lib/api-key.js +37 -28
  36. package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
  37. package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
  38. package/lib/vendor/blamejs/lib/archive-read.js +5 -17
  39. package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
  40. package/lib/vendor/blamejs/lib/archive.js +2 -10
  41. package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
  42. package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
  43. package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
  44. package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
  45. package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
  46. package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
  47. package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
  48. package/lib/vendor/blamejs/lib/audit.js +84 -0
  49. package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
  50. package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
  51. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
  52. package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
  53. package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
  54. package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
  55. package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
  56. package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
  57. package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
  58. package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
  59. package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
  60. package/lib/vendor/blamejs/lib/auth/password.js +7 -1
  61. package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
  62. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
  63. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
  64. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
  65. package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
  66. package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
  67. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
  68. package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
  69. package/lib/vendor/blamejs/lib/backup/index.js +14 -47
  70. package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
  71. package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
  72. package/lib/vendor/blamejs/lib/cache.js +7 -18
  73. package/lib/vendor/blamejs/lib/cbor.js +2 -1
  74. package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
  75. package/lib/vendor/blamejs/lib/cert.js +3 -10
  76. package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
  77. package/lib/vendor/blamejs/lib/cli.js +5 -1
  78. package/lib/vendor/blamejs/lib/client-hints.js +7 -9
  79. package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
  80. package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
  81. package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
  82. package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
  83. package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
  84. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
  85. package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
  86. package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
  87. package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
  88. package/lib/vendor/blamejs/lib/compliance.js +2 -9
  89. package/lib/vendor/blamejs/lib/config-drift.js +2 -12
  90. package/lib/vendor/blamejs/lib/content-digest.js +10 -8
  91. package/lib/vendor/blamejs/lib/cookies.js +5 -11
  92. package/lib/vendor/blamejs/lib/cose.js +19 -11
  93. package/lib/vendor/blamejs/lib/cra-report.js +1 -11
  94. package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
  95. package/lib/vendor/blamejs/lib/crypto.js +120 -3
  96. package/lib/vendor/blamejs/lib/csp.js +235 -3
  97. package/lib/vendor/blamejs/lib/daemon.js +42 -41
  98. package/lib/vendor/blamejs/lib/data-act.js +19 -9
  99. package/lib/vendor/blamejs/lib/db-query.js +6 -40
  100. package/lib/vendor/blamejs/lib/db.js +34 -12
  101. package/lib/vendor/blamejs/lib/dbsc.js +5 -6
  102. package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
  103. package/lib/vendor/blamejs/lib/deprecate.js +4 -5
  104. package/lib/vendor/blamejs/lib/did.js +6 -2
  105. package/lib/vendor/blamejs/lib/dsr.js +8 -12
  106. package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
  107. package/lib/vendor/blamejs/lib/external-db.js +14 -26
  108. package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
  109. package/lib/vendor/blamejs/lib/fdx.js +22 -18
  110. package/lib/vendor/blamejs/lib/file-upload.js +80 -66
  111. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
  112. package/lib/vendor/blamejs/lib/framework-error.js +12 -0
  113. package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
  114. package/lib/vendor/blamejs/lib/fsm.js +7 -12
  115. package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
  116. package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
  117. package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
  118. package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
  119. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  120. package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
  121. package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
  122. package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
  123. package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
  124. package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
  125. package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
  126. package/lib/vendor/blamejs/lib/guard-email.js +46 -53
  127. package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
  128. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
  129. package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
  130. package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
  131. package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
  132. package/lib/vendor/blamejs/lib/guard-html.js +65 -117
  133. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
  134. package/lib/vendor/blamejs/lib/guard-image.js +280 -77
  135. package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
  136. package/lib/vendor/blamejs/lib/guard-json.js +87 -103
  137. package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
  138. package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
  139. package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
  140. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
  141. package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
  142. package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
  143. package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
  144. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
  145. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
  146. package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
  147. package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
  148. package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
  149. package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
  150. package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
  151. package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
  152. package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
  153. package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
  154. package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
  155. package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
  156. package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
  157. package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
  158. package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
  159. package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
  160. package/lib/vendor/blamejs/lib/guard-template.js +23 -80
  161. package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
  162. package/lib/vendor/blamejs/lib/guard-text.js +592 -0
  163. package/lib/vendor/blamejs/lib/guard-time.js +27 -95
  164. package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
  165. package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
  166. package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
  167. package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
  168. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
  169. package/lib/vendor/blamejs/lib/http-client.js +8 -21
  170. package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
  171. package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
  172. package/lib/vendor/blamejs/lib/i18n.js +83 -26
  173. package/lib/vendor/blamejs/lib/inbox.js +8 -8
  174. package/lib/vendor/blamejs/lib/incident-report.js +3 -21
  175. package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
  176. package/lib/vendor/blamejs/lib/jobs.js +3 -2
  177. package/lib/vendor/blamejs/lib/keychain.js +6 -18
  178. package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
  179. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
  180. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
  181. package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
  182. package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
  183. package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
  184. package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
  185. package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
  186. package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
  187. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
  188. package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
  189. package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
  190. package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
  191. package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
  192. package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
  193. package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
  194. package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
  195. package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
  196. package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
  197. package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
  198. package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
  199. package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
  200. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
  201. package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
  202. package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
  203. package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
  204. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
  205. package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
  206. package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
  207. package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
  208. package/lib/vendor/blamejs/lib/mail-store.js +3 -2
  209. package/lib/vendor/blamejs/lib/mail.js +6 -11
  210. package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
  211. package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
  212. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
  213. package/lib/vendor/blamejs/lib/mcp.js +1 -1
  214. package/lib/vendor/blamejs/lib/mdoc.js +11 -12
  215. package/lib/vendor/blamejs/lib/metrics.js +32 -30
  216. package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
  217. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
  218. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
  219. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
  220. package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
  221. package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
  222. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
  223. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
  224. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
  225. package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
  226. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
  227. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
  228. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
  229. package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
  230. package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
  231. package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
  232. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
  233. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
  234. package/lib/vendor/blamejs/lib/migrations.js +4 -13
  235. package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
  236. package/lib/vendor/blamejs/lib/module-loader.js +44 -0
  237. package/lib/vendor/blamejs/lib/money.js +105 -0
  238. package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
  239. package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
  240. package/lib/vendor/blamejs/lib/network-dane.js +8 -6
  241. package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
  242. package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
  243. package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
  244. package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
  245. package/lib/vendor/blamejs/lib/network-tls.js +40 -42
  246. package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
  247. package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
  248. package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
  249. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
  250. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
  251. package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
  252. package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
  253. package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
  254. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
  255. package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
  256. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
  257. package/lib/vendor/blamejs/lib/observability.js +95 -0
  258. package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
  259. package/lib/vendor/blamejs/lib/otel-export.js +7 -10
  260. package/lib/vendor/blamejs/lib/outbox.js +43 -37
  261. package/lib/vendor/blamejs/lib/pagination.js +11 -15
  262. package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
  263. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
  264. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
  265. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
  266. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
  267. package/lib/vendor/blamejs/lib/pick.js +63 -5
  268. package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
  269. package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
  270. package/lib/vendor/blamejs/lib/problem-details.js +2 -5
  271. package/lib/vendor/blamejs/lib/pubsub.js +4 -8
  272. package/lib/vendor/blamejs/lib/redact.js +2 -1
  273. package/lib/vendor/blamejs/lib/render.js +4 -2
  274. package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
  275. package/lib/vendor/blamejs/lib/restore.js +5 -22
  276. package/lib/vendor/blamejs/lib/retention.js +3 -5
  277. package/lib/vendor/blamejs/lib/safe-async.js +457 -0
  278. package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
  279. package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
  280. package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
  281. package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
  282. package/lib/vendor/blamejs/lib/safe-json.js +7 -8
  283. package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
  284. package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
  285. package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
  286. package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
  287. package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
  288. package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
  289. package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
  290. package/lib/vendor/blamejs/lib/sandbox.js +3 -2
  291. package/lib/vendor/blamejs/lib/scheduler.js +5 -12
  292. package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
  293. package/lib/vendor/blamejs/lib/seeders.js +4 -11
  294. package/lib/vendor/blamejs/lib/self-update.js +92 -69
  295. package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
  296. package/lib/vendor/blamejs/lib/session.js +194 -6
  297. package/lib/vendor/blamejs/lib/sql.js +225 -78
  298. package/lib/vendor/blamejs/lib/sse.js +6 -10
  299. package/lib/vendor/blamejs/lib/static.js +136 -98
  300. package/lib/vendor/blamejs/lib/storage.js +4 -2
  301. package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
  302. package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
  303. package/lib/vendor/blamejs/lib/tsa.js +11 -15
  304. package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
  305. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
  306. package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
  307. package/lib/vendor/blamejs/lib/vc.js +2 -7
  308. package/lib/vendor/blamejs/lib/vex.js +35 -13
  309. package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
  310. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
  311. package/lib/vendor/blamejs/lib/webhook.js +43 -18
  312. package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
  313. package/lib/vendor/blamejs/lib/websocket.js +7 -3
  314. package/lib/vendor/blamejs/lib/worm.js +2 -3
  315. package/lib/vendor/blamejs/lib/ws-client.js +8 -10
  316. package/lib/vendor/blamejs/package.json +1 -1
  317. package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
  318. package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
  319. package/lib/vendor/blamejs/test/00-primitives.js +136 -7
  320. package/lib/vendor/blamejs/test/10-state.js +9 -3
  321. package/lib/vendor/blamejs/test/30-chain.js +40 -0
  322. package/lib/vendor/blamejs/test/helpers/check.js +18 -0
  323. package/lib/vendor/blamejs/test/helpers/db.js +4 -0
  324. package/lib/vendor/blamejs/test/helpers/index.js +1 -0
  325. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
  326. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
  327. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
  328. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
  329. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
  330. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
  334. package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
  335. package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
  336. package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
  337. package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
  341. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
  344. package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
  346. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
  347. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
  348. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
  376. package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
  387. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
  388. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
  389. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
  391. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
  392. package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
  395. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
  396. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
  397. package/package.json +1 -1
@@ -45,12 +45,14 @@ var safeAsync = require("./safe-async");
45
45
  var safeSql = require("./safe-sql");
46
46
  var sql = require("./sql");
47
47
  var C = require("./constants");
48
+ var boundedMap = require("./bounded-map");
48
49
  var { FrameworkError } = require("./framework-error");
49
50
 
50
- // Allowlist of chain table names. Adding a new chain-backed table
51
- // (e.g. some future _blamejs_security_log) requires registering it here
52
- // so an operator can't accidentally point a chain-writer at a non-chain
53
- // table and corrupt the chain semantics.
51
+ // Allowlist of chain table names. The two framework chains ship registered; a
52
+ // consumer's own append-only hash-chained table is added at config time via
53
+ // registerTable() BEFORE create() accepts it. The allowlist is never bypassed
54
+ // — an unregistered table throws at create(), so a misconfig can't point a
55
+ // chain-writer at a non-chain table and corrupt the chain semantics.
54
56
  var ALLOWED_CHAIN_TABLES = new Set(["audit_log", "consent_log"]);
55
57
 
56
58
  var FRAMEWORK_SQL_TIMEOUT_MS = C.TIME.seconds(30);
@@ -74,24 +76,83 @@ class ChainWriterError extends FrameworkError {
74
76
  }
75
77
  }
76
78
 
79
+ /**
80
+ * @primitive b.chainWriter.registerTable
81
+ * @signature b.chainWriter.registerTable(table)
82
+ * @since 0.15.13
83
+ * @status stable
84
+ * @related b.chainWriter.create, b.safeSql.validateIdentifier
85
+ *
86
+ * Register a consumer-owned append-only table as chain-writable so
87
+ * `b.chainWriter.create({ table })` accepts it. Call once at boot (config
88
+ * time) for each app table carrying the chain columns (`monotonicCounter`,
89
+ * `recordedAt`, `nonce`, `prevHash`, `rowHash` — plus `fencingToken` in
90
+ * cluster mode). The framework chains (`audit_log`, `consent_log`) are
91
+ * pre-registered. Throws `ChainWriterError` (`chain-writer/invalid-config`) on
92
+ * a non-identifier name; the name is validated against the SQL identifier
93
+ * rules because it is interpolated into the chain SQL. Idempotent. Returns the
94
+ * registered name.
95
+ *
96
+ * Operator footgun to avoid on a MULTI-chain table (one configured with a
97
+ * `chainKey`): the per-key writer restarts `monotonicCounter` at 1 for each
98
+ * key, so a UNIQUE index on `monotonicCounter` ALONE (the shape the framework
99
+ * `audit_log` uses for its single chain) will reject the second key's first
100
+ * row. A keyed chain's uniqueness must be the composite
101
+ * `(chainKey, monotonicCounter)`, never `monotonicCounter` by itself.
102
+ *
103
+ * @example
104
+ * b.chainWriter.registerTable("device_event_log");
105
+ * var writer = b.chainWriter.create({
106
+ * table: "device_event_log",
107
+ * chainKey: "deviceId",
108
+ * columnsForInsert: ["_id", "deviceId", "monotonicCounter", "recordedAt",
109
+ * "kind", "payload",
110
+ * "prevHash", "rowHash", "nonce", "fencingToken"],
111
+ * hashableColumns: ["_id", "deviceId", "monotonicCounter", "recordedAt",
112
+ * "kind", "payload"],
113
+ * });
114
+ */
115
+ function registerTable(table) {
116
+ if (typeof table !== "string" || table.length === 0) {
117
+ throw new ChainWriterError(
118
+ "registerTable requires a non-empty table name",
119
+ "chain-writer/invalid-config"
120
+ );
121
+ }
122
+ // Identifier-validate before admitting to the allowlist — the name is
123
+ // interpolated into the chain SQL, so the same shape rules create() relies
124
+ // on must hold here, at the config-time entry point.
125
+ safeSql.validateIdentifier(table);
126
+ ALLOWED_CHAIN_TABLES.add(table);
127
+ return table;
128
+ }
129
+
77
130
  /**
78
131
  * @primitive b.chainWriter.create
79
132
  * @signature b.chainWriter.create(opts)
80
133
  * @since 0.8.48
81
134
  * @status stable
82
- * @related b.audit, b.consent, b.auditChain
135
+ * @related b.audit, b.consent, b.auditChain, b.chainWriter.registerTable
83
136
  *
84
137
  * Build a chain-writer bound to a single hash-chained table. Returns
85
- * `{ table, append, _resetForTest, _getMutexForTest }`. `append(logical)`
86
- * is the public surface — async, leader-gated, mutex-serialized; on
87
- * success it returns the logical row decorated with the computed
88
- * `rowHash` and `prevHash`.
138
+ * `{ table, chainKey, append, _resetForTest, _getMutexForTest }`.
139
+ * `append(logical)` is the public surface — async, leader-gated,
140
+ * mutex-serialized; on success it returns the logical row decorated with the
141
+ * computed `rowHash` and `prevHash`.
142
+ *
143
+ * A `chainKey` makes one table hold many independent chains (one per account /
144
+ * device / tenant): tip-read, counter monotonicity, and the append Mutex all
145
+ * scope per key, so concurrent appends to DIFFERENT keys run in parallel while
146
+ * same-key appends serialize. Bind `chainKey` into `hashableColumns` so the
147
+ * partition is tamper-evident in the row hash, and key the table's uniqueness
148
+ * constraint on `(chainKey, monotonicCounter)`, never `monotonicCounter` alone.
89
149
  *
90
150
  * @opts
91
- * table: string, // one of ALLOWED_CHAIN_TABLES (audit_log | consent_log)
151
+ * table: string, // a registered chain table (audit_log | consent_log | registerTable name)
152
+ * chainKey: string, // optional partition column — one independent chain per key value
92
153
  * columnsForInsert: string[], // INSERT column order (every name is identifier-validated)
93
154
  * hashableColumns: string[], // columns that participate in the rowHash canonicalization
94
- * validateInput: Function, // optional; (logical) throws on invalid shape
155
+ * validateInput: Function, // optional; (logical) -> throws on invalid shape
95
156
  *
96
157
  * @example
97
158
  * var writer = b.chainWriter.create({
@@ -136,27 +197,57 @@ function create(opts) {
136
197
  var hashableColumns = opts.hashableColumns.slice();
137
198
  var validateInput = opts.validateInput || null;
138
199
 
139
- // Per-chain Mutex serializes the read-prev-tip + compute-hash + insert
200
+ // chainKey: the partition column for many independent chains in one table
201
+ // (one chain per account / device / tenant). When set, the tip read,
202
+ // counter priming, and the append Mutex all scope to a single key value, so
203
+ // appends to DIFFERENT keys run in parallel while same-key appends
204
+ // serialize. Identifier-validated at config time (THROW tier) because it is
205
+ // interpolated as a column name; it must also appear in columnsForInsert so
206
+ // every row carries its partition key.
207
+ var chainKey = opts.chainKey || null;
208
+ if (chainKey !== null) {
209
+ safeSql.validateIdentifier(chainKey);
210
+ if (columnsForInsert.indexOf(chainKey) === -1) {
211
+ throw new ChainWriterError(
212
+ "chainKey '" + chainKey + "' must be listed in columnsForInsert so " +
213
+ "every appended row carries its partition key",
214
+ "chain-writer/invalid-config"
215
+ );
216
+ }
217
+ }
218
+
219
+ // Per-CHAIN-KEY Mutex serializes the read-prev-tip + compute-hash + insert
140
220
  // sequence. Without serialization, two concurrent awaiting append() calls
141
- // would hash against the same prev-tip and produce sibling rows with the
142
- // same prevHash forking the chain.
143
- var _chainMutex = new safeAsync.Mutex();
221
+ // would hash against the same prev-tip and fork the chain. A single-chain
222
+ // writer (no chainKey) uses one shared lock under the sentinel key; a
223
+ // multi-chain writer keys the lock by the partition value so appends to
224
+ // DIFFERENT keys run concurrently while same-key appends serialize.
225
+ var _SINGLE_CHAIN_KEY = "__single_chain__"; // sentinel; not a valid driver value
226
+ var _mutexByKey = new Map();
227
+ function _mutexFor(keyValue) {
228
+ var k = chainKey !== null ? String(keyValue) : _SINGLE_CHAIN_KEY;
229
+ return boundedMap.getOrInsert(_mutexByKey, k, function () { return new safeAsync.Mutex(); });
230
+ }
144
231
 
145
- // Lazy counter primer — first append reads MAX(monotonicCounter) and
146
- // increments from there. Once ensures concurrent first-callers share
147
- // one in-flight init Promise.
148
- var _nextCounter = 1;
149
- var _counterInit = null;
232
+ // Lazy counter primer — first append for a given key reads
233
+ // MAX(monotonicCounter) [WHERE chainKey = ?] and increments from there.
234
+ // Per-key so each chain's counter is independent; a per-key Once shares one
235
+ // in-flight init across concurrent first-callers for the same key.
236
+ var _nextCounterByKey = new Map();
237
+ var _counterInitByKey = new Map();
150
238
 
151
- function _ensureCounterInit() {
152
- if (!_counterInit) {
153
- _counterInit = new safeAsync.Once(async function () {
239
+ function _ensureCounterInit(keyValue) {
240
+ var k = chainKey !== null ? String(keyValue) : _SINGLE_CHAIN_KEY;
241
+ var once = boundedMap.getOrInsert(_counterInitByKey, k, function () {
242
+ return new safeAsync.Once(async function () {
154
243
  // BARE logical table name — clusterStorage rewrites the framework
155
- // name to the configured-prefix form and placeholderizes; b.sql
156
- // quotes the camelCase column + emits the MAX aggregate.
157
- var maxBuilt = sql.select(table, _sqlOpts())
158
- .max("monotonicCounter", "m")
159
- .toSql();
244
+ // name to the configured-prefix form (consumer tables pass through
245
+ // unchanged) and placeholderizes; b.sql quotes the camelCase column +
246
+ // emits the MAX aggregate. A keyed writer scopes the MAX to the
247
+ // partition via a bound WHERE.
248
+ var maxQ = sql.select(table, _sqlOpts()).max("monotonicCounter", "m");
249
+ if (chainKey !== null) maxQ = maxQ.where(chainKey, keyValue);
250
+ var maxBuilt = maxQ.toSql();
160
251
  var row = await safeAsync.withTimeout(
161
252
  safeAsync.asyncRetry(function () {
162
253
  return clusterStorage.executeOne(maxBuilt.sql, maxBuilt.params);
@@ -164,18 +255,21 @@ function create(opts) {
164
255
  FRAMEWORK_SQL_TIMEOUT_MS,
165
256
  { name: table + ".readMaxCounter" }
166
257
  );
167
- _nextCounter = (row && row.m ? Number(row.m) : 0) + 1;
258
+ _nextCounterByKey.set(k, (row && row.m ? Number(row.m) : 0) + 1);
168
259
  });
169
- }
170
- return _counterInit.invoke();
260
+ });
261
+ return once.invoke();
171
262
  }
172
263
 
173
- async function _readChainTipRow() {
174
- var tipBuilt = sql.select(table, _sqlOpts())
264
+ async function _readChainTipRow(keyValue) {
265
+ var tipQ = sql.select(table, _sqlOpts())
175
266
  .columns(["rowHash"])
176
267
  .orderBy("monotonicCounter", "desc")
177
- .limit(1)
178
- .toSql();
268
+ .limit(1);
269
+ // Scope the tip to the partition so per-key chains link correctly —
270
+ // bound value, never interpolated.
271
+ if (chainKey !== null) tipQ = tipQ.where(chainKey, keyValue);
272
+ var tipBuilt = tipQ.toSql();
179
273
  return await safeAsync.withTimeout(
180
274
  safeAsync.asyncRetry(function () {
181
275
  return clusterStorage.executeOne(tipBuilt.sql, tipBuilt.params);
@@ -209,15 +303,33 @@ function create(opts) {
209
303
  async function append(logical) {
210
304
  if (validateInput) validateInput(logical);
211
305
  cluster.requireLeader();
212
- await _ensureCounterInit();
213
306
 
214
- return await _chainMutex.runExclusive(async function () {
215
- return await _appendInsideMutex(logical);
307
+ // Resolve the partition key from the logical row for a multi-chain writer.
308
+ // Fail closed: a keyed writer with a missing / empty key can't pick a
309
+ // chain to append to, so refuse rather than silently fold the row into the
310
+ // wrong chain.
311
+ var keyValue = _SINGLE_CHAIN_KEY;
312
+ if (chainKey !== null) {
313
+ keyValue = logical ? logical[chainKey] : undefined;
314
+ if (keyValue === undefined || keyValue === null || String(keyValue).length === 0) {
315
+ throw new ChainWriterError(
316
+ "append: a chainKey writer requires logical['" + chainKey + "'] to be a " +
317
+ "non-empty partition value",
318
+ "chain-writer/invalid-input"
319
+ );
320
+ }
321
+ }
322
+ await _ensureCounterInit(keyValue);
323
+
324
+ return await _mutexFor(keyValue).runExclusive(async function () {
325
+ return await _appendInsideMutex(logical, keyValue);
216
326
  });
217
327
  }
218
328
 
219
- async function _appendInsideMutex(logical) {
220
- var counter = _nextCounter++;
329
+ async function _appendInsideMutex(logical, keyValue) {
330
+ var _ck = chainKey !== null ? String(keyValue) : _SINGLE_CHAIN_KEY;
331
+ var counter = _nextCounterByKey.get(_ck);
332
+ _nextCounterByKey.set(_ck, counter + 1);
221
333
  var nowMs = Date.now();
222
334
  var nonce = generateBytes(C.BYTES.bytes(16));
223
335
 
@@ -239,8 +351,8 @@ function create(opts) {
239
351
  if (!(hashableColumns[hci] in sealed)) sealed[hashableColumns[hci]] = null;
240
352
  }
241
353
 
242
- // Compute rowHash over the sealed content fields
243
- var tipRow = await _readChainTipRow();
354
+ // Compute rowHash over the sealed content fields, linking to THIS key's tip.
355
+ var tipRow = await _readChainTipRow(keyValue);
244
356
  var prevHash = tipRow ? tipRow.rowHash : auditChain.ZERO_HASH;
245
357
  var rowHash = auditChain.computeRowHash(prevHash, sealed, nonce);
246
358
 
@@ -259,22 +371,25 @@ function create(opts) {
259
371
  }
260
372
 
261
373
  function _resetForTest() {
262
- _chainMutex = new safeAsync.Mutex();
263
- _counterInit = null;
264
- _nextCounter = 1;
374
+ _mutexByKey = new Map();
375
+ _counterInitByKey = new Map();
376
+ _nextCounterByKey = new Map();
265
377
  }
266
378
 
267
379
  return {
268
380
  table: table,
381
+ chainKey: chainKey,
269
382
  append: append,
270
383
  _resetForTest: _resetForTest,
271
- // Expose for diagnostic introspection
272
- _getMutexForTest: function () { return _chainMutex; },
384
+ // Expose for diagnostic introspection — the lock for a given key (or the
385
+ // single-chain lock when no chainKey is configured).
386
+ _getMutexForTest: function (keyValue) { return _mutexFor(keyValue); },
273
387
  };
274
388
  }
275
389
 
276
390
  module.exports = {
277
391
  create: create,
392
+ registerTable: registerTable,
278
393
  ChainWriterError: ChainWriterError,
279
394
  ALLOWED_CHAIN_TABLES: ALLOWED_CHAIN_TABLES,
280
395
  FRAMEWORK_SQL_TIMEOUT_MS: FRAMEWORK_SQL_TIMEOUT_MS,
@@ -1110,12 +1110,16 @@ async function _runApiKey(args, ctx) {
1110
1110
  return report.error("--scopes must contain at least one non-empty scope", 2);
1111
1111
  }
1112
1112
  var label = typeof args.flags.label === "string" ? args.flags.label : null;
1113
+ // --expires-ms is the absolute expiry as a unix-ms timestamp; the
1114
+ // registry's validated opt is `expiresAt` (apiKey.issue rejects any other
1115
+ // key). Passing `expiresMs` silently did nothing before — the lib only
1116
+ // ever read `expiresAt` — so the flag was a no-op; map it correctly.
1113
1117
  var expiresMs = args.flags["expires-ms"];
1114
1118
  var issued = await registry.issue({
1115
1119
  ownerId: String(ownerId),
1116
1120
  scopes: scopeList,
1117
1121
  metadata: label ? { label: label } : null,
1118
- expiresMs: expiresMs && expiresMs !== true ? Number(expiresMs) : undefined,
1122
+ expiresAt: expiresMs && expiresMs !== true ? Number(expiresMs) : undefined,
1119
1123
  });
1120
1124
  report.write("id: " + issued.id);
1121
1125
  report.write("key: " + issued.key);
@@ -158,15 +158,13 @@ function _parseBrandMember(piece) {
158
158
  var brand = _parseSfString(params[0].trim());
159
159
  if (brand === null) return null;
160
160
  var member = { brand: brand, version: null, params: {} };
161
- for (var i = 1; i < params.length; i += 1) {
162
- var kv = params[i].trim();
163
- if (kv.length === 0) continue;
164
- var eq = kv.indexOf("=");
165
- if (eq === -1) { member.params[kv.toLowerCase()] = true; continue; }
166
- var k = kv.slice(0, eq).trim().toLowerCase();
167
- var v = _parseSfString(kv.slice(eq + 1));
168
- member.params[k] = v;
169
- if (k === "v" && v !== null) member.version = v;
161
+ var kvps = structuredFields.parseKeyValuePieces(params, 1);
162
+ for (var i = 0; i < kvps.length; i += 1) {
163
+ var kv = kvps[i];
164
+ if (kv.value === null) { member.params[kv.key] = true; continue; }
165
+ var v = _parseSfString(kv.value);
166
+ member.params[kv.key] = v;
167
+ if (kv.key === "v" && v !== null) member.version = v;
170
168
  }
171
169
  return member;
172
170
  }
@@ -118,21 +118,41 @@ function _genId() {
118
118
  * // → "1.0"
119
119
  */
120
120
  function wrap(opts) {
121
- validateOpts.requireObject(opts, "cloudEvents.wrap", CloudEventsError);
122
- validateOpts.requireNonEmptyString(opts.source,
123
- "cloudEvents.wrap: source", CloudEventsError, "cloud-events/bad-source");
124
- validateOpts.requireNonEmptyString(opts.type,
125
- "cloudEvents.wrap: type", CloudEventsError, "cloud-events/bad-type");
126
- validateOpts.optionalNonEmptyString(opts.id,
127
- "cloudEvents.wrap: id", CloudEventsError, "cloud-events/bad-id");
128
- validateOpts.optionalNonEmptyString(opts.subject,
129
- "cloudEvents.wrap: subject", CloudEventsError, "cloud-events/bad-subject");
130
- validateOpts.optionalNonEmptyString(opts.time,
131
- "cloudEvents.wrap: time", CloudEventsError, "cloud-events/bad-time");
132
- validateOpts.optionalNonEmptyString(opts.datacontenttype,
133
- "cloudEvents.wrap: datacontenttype", CloudEventsError, "cloud-events/bad-datacontenttype");
134
- validateOpts.optionalNonEmptyString(opts.dataschema,
135
- "cloudEvents.wrap: dataschema", CloudEventsError, "cloud-events/bad-dataschema");
121
+ validateOpts.shape(opts, {
122
+ source: { rule: "required-string", code: "cloud-events/bad-source" },
123
+ type: { rule: "required-string", code: "cloud-events/bad-type" },
124
+ id: { rule: "optional-string", code: "cloud-events/bad-id" },
125
+ subject: { rule: "optional-string", code: "cloud-events/bad-subject" },
126
+ time: { rule: "optional-string", code: "cloud-events/bad-time" },
127
+ datacontenttype: { rule: "optional-string", code: "cloud-events/bad-datacontenttype" },
128
+ dataschema: { rule: "optional-string", code: "cloud-events/bad-dataschema" },
129
+ // data is any JSON value or a Buffer — wrap routes Buffers to
130
+ // data_base64 and everything else to the data attribute, imposing no
131
+ // type constraint of its own, so accept any value here.
132
+ data: function () {},
133
+ // extensions plain object whose keys conform to the §3.1 naming
134
+ // rules (lowercase ASCII alnum, 1-20 chars) and collide with no spec
135
+ // attribute. Validation lives IN the shape; the body only copies the
136
+ // validated keys onto the envelope.
137
+ extensions: function (v) {
138
+ validateOpts.optionalPlainObject(v,
139
+ "cloudEvents.wrap: extensions", CloudEventsError, "cloud-events/bad-extensions");
140
+ if (v === undefined || v === null) return;
141
+ var extKeys = Object.keys(v);
142
+ for (var i = 0; i < extKeys.length; i += 1) {
143
+ var k = extKeys[i];
144
+ // bound BEFORE regex test — k.length > 0 && k.length <= 20
145
+ if (typeof k !== "string" || k.length === 0 || k.length > 20 || !EXT_ATTR_NAME_RE.test(k)) {
146
+ throw new CloudEventsError("cloud-events/bad-extension-name",
147
+ "cloudEvents.wrap: extension '" + k + "' must match [a-z0-9]{1,20}");
148
+ }
149
+ if (REQUIRED_ATTRS.indexOf(k) !== -1 || KNOWN_OPTIONAL_ATTRS[k]) {
150
+ throw new CloudEventsError("cloud-events/extension-conflicts-with-spec",
151
+ "cloudEvents.wrap: extension '" + k + "' conflicts with a spec attribute");
152
+ }
153
+ }
154
+ },
155
+ }, "cloudEvents.wrap", CloudEventsError);
136
156
 
137
157
  var out = {
138
158
  specversion: SPECVERSION,
@@ -158,24 +178,13 @@ function wrap(opts) {
158
178
  out.datacontenttype = opts.datacontenttype;
159
179
  }
160
180
 
161
- // Extension attributes — operator-defined, must conform to the
162
- // §3.1 naming rules (lowercase ASCII alnum, 1-20 chars).
181
+ // Extension attributes — validated in the shape above (plain object,
182
+ // §3.1 key naming, no spec collisions); copy the validated keys onto
183
+ // the envelope.
163
184
  if (opts.extensions !== undefined && opts.extensions !== null) {
164
- validateOpts.optionalPlainObject(opts.extensions,
165
- "cloudEvents.wrap: extensions", CloudEventsError, "cloud-events/bad-extensions");
166
185
  var extKeys = Object.keys(opts.extensions);
167
186
  for (var i = 0; i < extKeys.length; i += 1) {
168
- var k = extKeys[i];
169
- // bound BEFORE regex test — k.length > 0 && k.length <= 20
170
- if (typeof k !== "string" || k.length === 0 || k.length > 20 || !EXT_ATTR_NAME_RE.test(k)) {
171
- throw new CloudEventsError("cloud-events/bad-extension-name",
172
- "cloudEvents.wrap: extension '" + k + "' must match [a-z0-9]{1,20}");
173
- }
174
- if (REQUIRED_ATTRS.indexOf(k) !== -1 || KNOWN_OPTIONAL_ATTRS[k]) {
175
- throw new CloudEventsError("cloud-events/extension-conflicts-with-spec",
176
- "cloudEvents.wrap: extension '" + k + "' conflicts with a spec attribute");
177
- }
178
- out[k] = opts.extensions[k];
187
+ out[extKeys[i]] = opts.extensions[extKeys[i]];
179
188
  }
180
189
  }
181
190
  return out;
@@ -668,7 +677,7 @@ function decodeBinary(headers, body, opts) {
668
677
  else if (Buffer.isBuffer(body)) raw = body;
669
678
  else if (typeof body === "string") raw = Buffer.from(body, "utf8");
670
679
  else throw new CloudEventsError("cloud-events/bad-input", "cloudEvents.http.decodeBinary: body must be a string or Buffer");
671
- if (raw.length > maxBytes) throw new CloudEventsError("cloud-events/too-large", "cloudEvents.http.decodeBinary: body exceeds maxBytes (" + maxBytes + ")");
680
+ if (safeBuffer.byteLengthOf(raw) > maxBytes) throw new CloudEventsError("cloud-events/too-large", "cloudEvents.http.decodeBinary: body exceeds maxBytes (" + maxBytes + ")");
672
681
  if (raw.length > 0) {
673
682
  if (_isJsonMedia(ct)) {
674
683
  try { event.data = safeJson.parse(raw, { maxBytes: maxBytes }); }
@@ -30,6 +30,7 @@
30
30
  var cluster = require("./cluster");
31
31
  var frameworkSchema = require("./framework-schema");
32
32
  var externalDb = require("./external-db");
33
+ var safeSql = require("./safe-sql");
33
34
  var lazyRequire = require("./lazy-require");
34
35
  var { FrameworkError } = require("./framework-error");
35
36
 
@@ -277,44 +278,7 @@ function resolveTables(sql) {
277
278
  * // → "SELECT id FROM audit_log WHERE counter > $1 AND actor = $2"
278
279
  */
279
280
  function placeholderize(sql, dialect) {
280
- if (dialect !== "postgres") return sql;
281
- var out = "";
282
- var n = 0;
283
- var i = 0;
284
- var len = sql.length;
285
- while (i < len) {
286
- var c = sql.charAt(i);
287
- var nx = i + 1 < len ? sql.charAt(i + 1) : "";
288
- // Quote contexts: ' string literal, " identifier, ` mysql identifier.
289
- // A doubled quote escapes itself within the span.
290
- if (c === "'" || c === '"' || c === "`") {
291
- out += c;
292
- i += 1;
293
- while (i < len) {
294
- var q = sql.charAt(i);
295
- if (q === c) {
296
- if (sql.charAt(i + 1) === c) { out += c + c; i += 2; continue; }
297
- out += c; i += 1; break;
298
- }
299
- out += q; i += 1;
300
- }
301
- continue;
302
- }
303
- if (c === "-" && nx === "-") { // line comment
304
- while (i < len && sql.charAt(i) !== "\n") { out += sql.charAt(i); i += 1; }
305
- continue;
306
- }
307
- if (c === "/" && nx === "*") { // block comment
308
- out += "/*"; i += 2;
309
- while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) { out += sql.charAt(i); i += 1; }
310
- if (i < len) { out += "*/"; i += 2; }
311
- continue;
312
- }
313
- if (c === "?") { n += 1; out += "$" + n; i += 1; continue; }
314
- out += c;
315
- i += 1;
316
- }
317
- return out;
281
+ return safeSql.toPositional(sql, dialect);
318
282
  }
319
283
 
320
284
  // ---- execute() ----
@@ -68,6 +68,7 @@
68
68
  */
69
69
 
70
70
  var nodeCrypto = require("node:crypto");
71
+ var safeBuffer = require("./safe-buffer");
71
72
  var asn1 = require("./asn1-der");
72
73
  var bCrypto = require("./crypto");
73
74
  var pqcSoftware = require("./pqc-software");
@@ -322,7 +323,7 @@ function decode(buf, opts) {
322
323
  throw new CmsCodecError("cms/bad-input", "decode: buf must be a Buffer");
323
324
  }
324
325
  var maxBytes = opts.maxBytes || DEFAULT_MAX_LEN;
325
- if (buf.length > maxBytes) {
326
+ if (safeBuffer.byteLengthOf(buf) > maxBytes) {
326
327
  throw new CmsCodecError("cms/oversize",
327
328
  "decode: input " + buf.length + " bytes exceeds maxBytes=" + maxBytes);
328
329
  }
@@ -172,7 +172,7 @@ function detectMixedScripts(label, allowedScripts) {
172
172
  //
173
173
  // issues.push.apply(issues,
174
174
  // codepointClass.detectCharThreats(text, opts, "html"));
175
- function detectCharThreats(text, opts, codePrefix) {
175
+ function detectCharThreats(text, opts, codePrefix, zeroWidthSeverity) {
176
176
  var issues = [];
177
177
  if (typeof text !== "string") return issues;
178
178
  if (opts && opts.bidiPolicy !== "allow") {
@@ -208,6 +208,28 @@ function detectCharThreats(text, opts, codePrefix) {
208
208
  });
209
209
  }
210
210
  }
211
+ // Zero-width / invisible-formatting chars — the fourth Trojan-source-class
212
+ // character threat, detected here alongside its siblings so no guard
213
+ // hand-rolls it. OPT-IN AND severity via zeroWidthSeverity: a caller that
214
+ // wants zero-width detection passes the context-appropriate severity
215
+ // ("high" where an invisible char spoofs an identifier / filename / line of
216
+ // text; "warn" where it is cosmetic), and omitting it skips the scan. Gated
217
+ // further on a defined non-`allow` zeroWidthPolicy — flagged under `strip`
218
+ // too (like bidi / null / control) so a zero-width-only input under `strip`
219
+ // reaches the sanitizer and is removed rather than served unchanged.
220
+ if (zeroWidthSeverity && opts && opts.zeroWidthPolicy &&
221
+ opts.zeroWidthPolicy !== "allow") {
222
+ var zwMatch = text.match(ZERO_WIDTH_RE);
223
+ if (zwMatch) {
224
+ issues.push({
225
+ kind: "zero-width", severity: zeroWidthSeverity,
226
+ ruleId: codePrefix + ".zero-width",
227
+ location: zwMatch.index,
228
+ snippet: "zero-width / invisible-formatting char U+" +
229
+ zwMatch[0].charCodeAt(0).toString(HEX_RADIX) + " at byte " + zwMatch.index,
230
+ });
231
+ }
232
+ }
211
233
  return issues;
212
234
  }
213
235
 
@@ -292,7 +314,51 @@ function isUnreserved(cc) {
292
314
  cc === 0x7e; // ~
293
315
  }
294
316
 
317
+ // isForbiddenControlChar — the header-injection / RFC 5322 control-byte
318
+ // predicate every "refuse control bytes in a header / line / value" loop
319
+ // shares across the mail guards (dsn / imap / list-id / list-unsubscribe /
320
+ // mail-compose / mail-sieve / managesieve) and the safe-* text parsers
321
+ // (ical / mime / vcard / toml). TRUE for DEL (0x7f) and any C0 control
322
+ // (< 0x20) other than TAB (0x09); LF (0x0a) and CR (0x0d) are refused by
323
+ // default but can be permitted per call (a line reader that has already
324
+ // split on CRLF, or a grammar that allows folding). Distinct from the
325
+ // C0_CTRL_RANGES regex above, which is the stripping/scanning table that
326
+ // always exempts LF/CR and never matches DEL.
327
+ //
328
+ // opts.forbidTab — TAB (0x09) is normally permitted (it is folding
329
+ // whitespace in RFC 5322 header values). The stricter identifier / key /
330
+ // name / single-line-value contexts (idempotency keys, step-up challenge
331
+ // values, mailbox / folder / message-id names, assembly ids, DNSBL-free
332
+ // single-line values) forbid EVERY C0 control plus DEL — there is no
333
+ // folding to honour — so they pass `{ forbidTab: true }`, making the
334
+ // predicate exactly `code < 0x20 || code === 0x7f`.
335
+ function isForbiddenControlChar(code, opts) {
336
+ if (code === 0x7f) return true; // DEL
337
+ if (code >= 0x20) return false;
338
+ if (code === 0x09 && (!opts || !opts.forbidTab)) return false; // TAB — permitted unless forbidTab
339
+ if (opts) {
340
+ if (opts.allowLf && code === 0x0a) return false;
341
+ if (opts.allowCr && code === 0x0d) return false;
342
+ }
343
+ return true;
344
+ }
345
+
346
+ // firstControlCharOffset — index of the first isForbiddenControlChar in `s`
347
+ // (under the same opts), or -1 when none. Callers wrap it as a boolean
348
+ // (`offset !== -1`), throw with the offending code (`s.charCodeAt(offset)`),
349
+ // or derive a byte offset from the index — replacing the open-coded
350
+ // `for (i) { c = charCodeAt(i); if (c === 0 || c === 0x7f || (c < 0x20 &&
351
+ // c !== 0x09)) … }` scan each parser previously rolled by hand.
352
+ function firstControlCharOffset(s, opts) {
353
+ for (var i = 0; i < s.length; i += 1) {
354
+ if (isForbiddenControlChar(s.charCodeAt(i), opts)) return i;
355
+ }
356
+ return -1;
357
+ }
358
+
295
359
  module.exports = {
360
+ isForbiddenControlChar: isForbiddenControlChar,
361
+ firstControlCharOffset: firstControlCharOffset,
296
362
  isAsciiAlnum: isAsciiAlnum,
297
363
  isUnreserved: isUnreserved,
298
364
  hex4: hex4,
@@ -131,12 +131,7 @@ function emit(event) {
131
131
  // namespace uses underscores, so the kind is rewritten before emit.
132
132
  try {
133
133
  var kindCanonical = String(event.kind || "log").replace(/-/g, "_");
134
- audit().safeEmit({
135
- action: "compliance.aiact." + kindCanonical,
136
- outcome: event.outcome || "success",
137
- actor: event.actor || null,
138
- metadata: event,
139
- });
134
+ audit().namespaced("compliance.aiact")(kindCanonical, event.outcome || "success", event, { actor: event.actor || null });
140
135
  } catch (_e) { /* drop-silent */ }
141
136
  return event;
142
137
  }
@@ -39,6 +39,7 @@
39
39
  */
40
40
 
41
41
  var validateOpts = require("./validate-opts");
42
+ var markupEscape = require("./markup-escape").markupEscape;
42
43
  var { ComplianceError } = require("./framework-error");
43
44
 
44
45
  var BANNER_KINDS = Object.freeze([
@@ -118,10 +119,7 @@ function htmlBanner(opts) {
118
119
 
119
120
  function _escapeHtml(s) {
120
121
  if (typeof s !== "string") return "";
121
- return s.replace(/&/g, "&amp;")
122
- .replace(/</g, "&lt;")
123
- .replace(/>/g, "&gt;")
124
- .replace(/"/g, "&quot;");
122
+ return markupEscape(s);
125
123
  }
126
124
 
127
125
  // Watermark builder for Art. 50(2). Operators integrate with C2PA /