@blamejs/blamejs-shop 0.4.56 → 0.4.58

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 (402) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/affiliates.js +35 -4
  3. package/lib/api-keys.js +17 -2
  4. package/lib/asset-manifest.json +1 -1
  5. package/lib/backorder.js +21 -4
  6. package/lib/click-and-collect.js +11 -2
  7. package/lib/credit-limits.js +132 -84
  8. package/lib/vendor/MANIFEST.json +426 -366
  9. package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
  10. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  11. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
  12. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
  13. package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
  14. package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
  15. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
  16. package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
  17. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
  18. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  19. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  20. package/lib/vendor/blamejs/api-snapshot.json +1381 -4
  21. package/lib/vendor/blamejs/eslint.config.mjs +1 -0
  22. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
  23. package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
  24. package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
  25. package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
  26. package/lib/vendor/blamejs/index.js +2 -0
  27. package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
  28. package/lib/vendor/blamejs/lib/acme.js +6 -5
  29. package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
  30. package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
  31. package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
  32. package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
  33. package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
  34. package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
  35. package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
  36. package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
  37. package/lib/vendor/blamejs/lib/ai-input.js +2 -2
  38. package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
  39. package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
  40. package/lib/vendor/blamejs/lib/api-key.js +37 -28
  41. package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
  42. package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
  43. package/lib/vendor/blamejs/lib/archive-read.js +5 -17
  44. package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
  45. package/lib/vendor/blamejs/lib/archive.js +2 -10
  46. package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
  47. package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
  48. package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
  49. package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
  50. package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
  51. package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
  52. package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
  53. package/lib/vendor/blamejs/lib/audit.js +84 -0
  54. package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
  55. package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
  56. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
  57. package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
  58. package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
  59. package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
  60. package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
  61. package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
  62. package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
  63. package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
  64. package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
  65. package/lib/vendor/blamejs/lib/auth/password.js +7 -1
  66. package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
  67. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
  68. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
  69. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
  70. package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
  71. package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
  72. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
  73. package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
  74. package/lib/vendor/blamejs/lib/backup/index.js +14 -47
  75. package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
  76. package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
  77. package/lib/vendor/blamejs/lib/cache.js +7 -18
  78. package/lib/vendor/blamejs/lib/cbor.js +2 -1
  79. package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
  80. package/lib/vendor/blamejs/lib/cert.js +3 -10
  81. package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
  82. package/lib/vendor/blamejs/lib/cli.js +5 -1
  83. package/lib/vendor/blamejs/lib/client-hints.js +7 -9
  84. package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
  85. package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
  86. package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
  87. package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
  88. package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
  89. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
  90. package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
  91. package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
  92. package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
  93. package/lib/vendor/blamejs/lib/compliance.js +2 -9
  94. package/lib/vendor/blamejs/lib/config-drift.js +2 -12
  95. package/lib/vendor/blamejs/lib/content-digest.js +10 -8
  96. package/lib/vendor/blamejs/lib/cookies.js +5 -11
  97. package/lib/vendor/blamejs/lib/cose.js +19 -11
  98. package/lib/vendor/blamejs/lib/cra-report.js +1 -11
  99. package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
  100. package/lib/vendor/blamejs/lib/crypto.js +120 -3
  101. package/lib/vendor/blamejs/lib/csp.js +235 -3
  102. package/lib/vendor/blamejs/lib/daemon.js +42 -41
  103. package/lib/vendor/blamejs/lib/data-act.js +19 -9
  104. package/lib/vendor/blamejs/lib/db-query.js +6 -40
  105. package/lib/vendor/blamejs/lib/db.js +34 -12
  106. package/lib/vendor/blamejs/lib/dbsc.js +5 -6
  107. package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
  108. package/lib/vendor/blamejs/lib/deprecate.js +4 -5
  109. package/lib/vendor/blamejs/lib/did.js +6 -2
  110. package/lib/vendor/blamejs/lib/dsr.js +8 -12
  111. package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
  112. package/lib/vendor/blamejs/lib/external-db.js +14 -26
  113. package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
  114. package/lib/vendor/blamejs/lib/fdx.js +22 -18
  115. package/lib/vendor/blamejs/lib/file-upload.js +80 -66
  116. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
  117. package/lib/vendor/blamejs/lib/framework-error.js +12 -0
  118. package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
  119. package/lib/vendor/blamejs/lib/fsm.js +7 -12
  120. package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
  121. package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
  122. package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
  123. package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
  124. package/lib/vendor/blamejs/lib/guard-all.js +1 -0
  125. package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
  126. package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
  127. package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
  128. package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
  129. package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
  130. package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
  131. package/lib/vendor/blamejs/lib/guard-email.js +46 -53
  132. package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
  133. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
  134. package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
  135. package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
  136. package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
  137. package/lib/vendor/blamejs/lib/guard-html.js +65 -117
  138. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
  139. package/lib/vendor/blamejs/lib/guard-image.js +280 -77
  140. package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
  141. package/lib/vendor/blamejs/lib/guard-json.js +87 -103
  142. package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
  143. package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
  144. package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
  145. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
  146. package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
  147. package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
  148. package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
  149. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
  150. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
  151. package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
  152. package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
  153. package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
  154. package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
  155. package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
  156. package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
  157. package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
  158. package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
  159. package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
  160. package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
  161. package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
  162. package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
  163. package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
  164. package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
  165. package/lib/vendor/blamejs/lib/guard-template.js +23 -80
  166. package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
  167. package/lib/vendor/blamejs/lib/guard-text.js +592 -0
  168. package/lib/vendor/blamejs/lib/guard-time.js +27 -95
  169. package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
  170. package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
  171. package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
  172. package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
  173. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
  174. package/lib/vendor/blamejs/lib/http-client.js +8 -21
  175. package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
  176. package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
  177. package/lib/vendor/blamejs/lib/i18n.js +83 -26
  178. package/lib/vendor/blamejs/lib/inbox.js +8 -8
  179. package/lib/vendor/blamejs/lib/incident-report.js +3 -21
  180. package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
  181. package/lib/vendor/blamejs/lib/jobs.js +3 -2
  182. package/lib/vendor/blamejs/lib/keychain.js +6 -18
  183. package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
  184. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
  185. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
  186. package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
  187. package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
  188. package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
  189. package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
  190. package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
  191. package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
  192. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
  193. package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
  194. package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
  195. package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
  196. package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
  197. package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
  198. package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
  199. package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
  200. package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
  201. package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
  202. package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
  203. package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
  204. package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
  205. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
  206. package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
  207. package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
  208. package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
  209. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
  210. package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
  211. package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
  212. package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
  213. package/lib/vendor/blamejs/lib/mail-store.js +3 -2
  214. package/lib/vendor/blamejs/lib/mail.js +6 -11
  215. package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
  216. package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
  217. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
  218. package/lib/vendor/blamejs/lib/mcp.js +1 -1
  219. package/lib/vendor/blamejs/lib/mdoc.js +11 -12
  220. package/lib/vendor/blamejs/lib/metrics.js +32 -30
  221. package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
  222. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
  223. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
  224. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
  225. package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
  226. package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
  227. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
  228. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
  229. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
  230. package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
  231. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
  232. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
  233. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
  234. package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
  235. package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
  236. package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
  237. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
  238. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
  239. package/lib/vendor/blamejs/lib/migrations.js +4 -13
  240. package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
  241. package/lib/vendor/blamejs/lib/module-loader.js +44 -0
  242. package/lib/vendor/blamejs/lib/money.js +105 -0
  243. package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
  244. package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
  245. package/lib/vendor/blamejs/lib/network-dane.js +8 -6
  246. package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
  247. package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
  248. package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
  249. package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
  250. package/lib/vendor/blamejs/lib/network-tls.js +40 -42
  251. package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
  252. package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
  253. package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
  254. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
  255. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
  256. package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
  257. package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
  258. package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
  259. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
  260. package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
  261. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
  262. package/lib/vendor/blamejs/lib/observability.js +95 -0
  263. package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
  264. package/lib/vendor/blamejs/lib/otel-export.js +7 -10
  265. package/lib/vendor/blamejs/lib/outbox.js +43 -37
  266. package/lib/vendor/blamejs/lib/pagination.js +11 -15
  267. package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
  268. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
  269. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
  270. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
  271. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
  272. package/lib/vendor/blamejs/lib/pick.js +63 -5
  273. package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
  274. package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
  275. package/lib/vendor/blamejs/lib/problem-details.js +2 -5
  276. package/lib/vendor/blamejs/lib/pubsub.js +4 -8
  277. package/lib/vendor/blamejs/lib/redact.js +2 -1
  278. package/lib/vendor/blamejs/lib/render.js +4 -2
  279. package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
  280. package/lib/vendor/blamejs/lib/restore.js +5 -22
  281. package/lib/vendor/blamejs/lib/retention.js +3 -5
  282. package/lib/vendor/blamejs/lib/safe-async.js +457 -0
  283. package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
  284. package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
  285. package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
  286. package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
  287. package/lib/vendor/blamejs/lib/safe-json.js +7 -8
  288. package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
  289. package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
  290. package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
  291. package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
  292. package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
  293. package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
  294. package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
  295. package/lib/vendor/blamejs/lib/sandbox.js +3 -2
  296. package/lib/vendor/blamejs/lib/scheduler.js +5 -12
  297. package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
  298. package/lib/vendor/blamejs/lib/seeders.js +4 -11
  299. package/lib/vendor/blamejs/lib/self-update.js +92 -69
  300. package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
  301. package/lib/vendor/blamejs/lib/session.js +194 -6
  302. package/lib/vendor/blamejs/lib/sql.js +225 -78
  303. package/lib/vendor/blamejs/lib/sse.js +6 -10
  304. package/lib/vendor/blamejs/lib/static.js +136 -98
  305. package/lib/vendor/blamejs/lib/storage.js +4 -2
  306. package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
  307. package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
  308. package/lib/vendor/blamejs/lib/tsa.js +11 -15
  309. package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
  310. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
  311. package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
  312. package/lib/vendor/blamejs/lib/vc.js +2 -7
  313. package/lib/vendor/blamejs/lib/vex.js +35 -13
  314. package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
  315. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
  316. package/lib/vendor/blamejs/lib/webhook.js +43 -18
  317. package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
  318. package/lib/vendor/blamejs/lib/websocket.js +7 -3
  319. package/lib/vendor/blamejs/lib/worm.js +2 -3
  320. package/lib/vendor/blamejs/lib/ws-client.js +8 -10
  321. package/lib/vendor/blamejs/package.json +1 -1
  322. package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
  323. package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
  324. package/lib/vendor/blamejs/test/00-primitives.js +136 -7
  325. package/lib/vendor/blamejs/test/10-state.js +9 -3
  326. package/lib/vendor/blamejs/test/30-chain.js +40 -0
  327. package/lib/vendor/blamejs/test/helpers/check.js +18 -0
  328. package/lib/vendor/blamejs/test/helpers/db.js +4 -0
  329. package/lib/vendor/blamejs/test/helpers/index.js +1 -0
  330. package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
  331. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
  332. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
  333. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
  334. package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
  335. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
  336. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
  337. package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
  340. package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
  341. package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
  342. package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
  346. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
  348. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
  349. package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
  351. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
  352. package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
  376. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
  388. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
  389. package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
  390. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
  391. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
  392. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
  393. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
  395. package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
  396. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
  400. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
  401. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
  402. package/package.json +1 -1
@@ -448,6 +448,48 @@ function testGuardCsvCellTooLargeCap() {
448
448
  threw && /maxCellBytes|too-large/.test(threw.message));
449
449
  }
450
450
 
451
+ function testGuardCsvCellByteCapMultibyte() {
452
+ // The cap is named in BYTES; a multibyte char must count its UTF-8 byte
453
+ // width, not its UTF-16 code-unit count. "é" (U+00E9) is 1 code unit but
454
+ // 2 UTF-8 bytes. Five of them: .length === 5, byteLength === 10.
455
+ var multibyte = "é".repeat(5);
456
+ check("multibyte fixture: .length 5 < byteLength 10",
457
+ multibyte.length === 5 && Buffer.byteLength(multibyte, "utf8") === 10);
458
+
459
+ // Cap at 6 bytes. byteLength(10) > 6 → refuse. The old char-length check
460
+ // (5 <= 6) would have let this 10-byte cell through under-enforced.
461
+ var threwCell = null;
462
+ try {
463
+ b.guardCsv.escapeCell(multibyte, { maxCellBytes: 6 });
464
+ } catch (e) { threwCell = e; }
465
+ check("escapeCell: multibyte cell over byte cap refused",
466
+ threwCell && threwCell.code === "csv.cell-too-large");
467
+ check("escapeCell: refusal reports the byte count, not the code-unit count",
468
+ threwCell && /\b10 bytes\b/.test(threwCell.message));
469
+
470
+ // The same cell through the shipped serialize consumer path.
471
+ var threwSer = null;
472
+ try {
473
+ b.guardCsv.serialize([[multibyte]], { maxCellBytes: 6 });
474
+ } catch (e) { threwSer = e; }
475
+ check("serialize: multibyte cell over byte cap refused",
476
+ threwSer && /maxCellBytes|too-large/.test(threwSer.message));
477
+
478
+ // A multibyte cell UNDER the byte cap is not falsely flagged: two "é" =
479
+ // 4 bytes < 6. And ASCII at the boundary is unchanged (5 bytes <= 6).
480
+ var underThrew = false;
481
+ try {
482
+ b.guardCsv.escapeCell("éé", { maxCellBytes: 6 });
483
+ } catch (_e) { underThrew = true; }
484
+ check("escapeCell: multibyte cell under byte cap accepted", underThrew === false);
485
+
486
+ var asciiThrew = false;
487
+ try {
488
+ b.guardCsv.escapeCell("alice", { maxCellBytes: 6 });
489
+ } catch (_e) { asciiThrew = true; }
490
+ check("escapeCell: ASCII under byte cap unchanged", asciiThrew === false);
491
+ }
492
+
451
493
  function testGuardCsvTooManyRows() {
452
494
  var threw = null;
453
495
  try {
@@ -560,6 +602,46 @@ function testGuardCsvCompliancePosture() {
560
602
  check("compliancePosture: unknown name throws", threw && /unknown/.test(threw.message));
561
603
  }
562
604
 
605
+ function testGdprPostureMatchesBalancedTier() {
606
+ // csv is a `content` guard. Its four-posture COMPLIANCE_POSTURES map must be
607
+ // built by gateContract.compliancePostures(PROFILES, { base, overlays }) like
608
+ // every other content guard: hipaa/pci/soc2 -> strict tier, gdpr -> balanced
609
+ // tier, with piiPolicy:"redact" overlaid on hipaa/pci/gdpr only.
610
+ //
611
+ // The drift this pins: a hand-written PARTIAL gdpr literal omitted keys
612
+ // (nullByteHandling / trailingWhitespacePolicy / bomPrefix / ...) that
613
+ // backfilled from the strict-leaning DEFAULTS at resolve time, making gdpr an
614
+ // incoherent strict/balanced hybrid. Once routed, gdpr is the balanced tier
615
+ // plus the forensic-snippet budget (base/2 = 128) plus the piiPolicy overlay.
616
+ var P = require("../../lib/guard-csv.js");
617
+ var POSTURES = P.COMPLIANCE_POSTURES;
618
+
619
+ // PRIMARY (deep-equal): gdpr resolves to the balanced tier + 128-byte snippet
620
+ // budget + the piiPolicy overlay — no DEFAULTS backfill.
621
+ var wantGdpr = Object.assign({}, P.PROFILES.balanced, {
622
+ forensicSnippetBytes: 128,
623
+ piiPolicy: "redact",
624
+ });
625
+ check("gdpr posture deep-equals balanced tier + forensic(128) + piiPolicy overlay",
626
+ JSON.stringify(POSTURES.gdpr) === JSON.stringify(wantGdpr));
627
+
628
+ // Overlay lands on the right postures only.
629
+ check("piiPolicy overlay survives on hipaa", POSTURES.hipaa.piiPolicy === "redact");
630
+ check("piiPolicy overlay survives on pci-dss", POSTURES["pci-dss"].piiPolicy === "redact");
631
+ check("piiPolicy overlay survives on gdpr", POSTURES.gdpr.piiPolicy === "redact");
632
+ check("soc2 carries no piiPolicy overlay", POSTURES.soc2.piiPolicy === undefined);
633
+
634
+ // REGRESSION (deep-equal): hipaa is the strict tier + 256-byte snippet budget
635
+ // + the piiPolicy overlay — confirms the strict-tier postures are coherent
636
+ // (no partial-literal backfill) after routing too.
637
+ var wantHipaa = Object.assign({}, P.PROFILES.strict, {
638
+ forensicSnippetBytes: 256,
639
+ piiPolicy: "redact",
640
+ });
641
+ check("hipaa posture deep-equals strict tier + forensic(256) + piiPolicy overlay",
642
+ JSON.stringify(POSTURES.hipaa) === JSON.stringify(wantHipaa));
643
+ }
644
+
563
645
  async function testGuardCsvGateClean() {
564
646
  var g = b.guardCsv.gate({ profile: "strict" });
565
647
  var d = await g.check({ bytes: Buffer.from("a,b\r\n1,2\r\n"), filename: "ok.csv" });
@@ -754,6 +836,7 @@ async function run() {
754
836
  testGuardCsvNullByteReject();
755
837
  testGuardCsvNumericPrecisionDecimalString();
756
838
  testGuardCsvCellTooLargeCap();
839
+ testGuardCsvCellByteCapMultibyte();
757
840
  testGuardCsvTooManyRows();
758
841
  testGuardCsvValidateBidi();
759
842
  testGuardCsvValidateClean();
@@ -766,6 +849,7 @@ async function run() {
766
849
  testGuardCsvSchemaNonNullable();
767
850
  testGuardCsvSchemaRegex();
768
851
  testGuardCsvCompliancePosture();
852
+ testGdprPostureMatchesBalancedTier();
769
853
  await testGuardCsvGateClean();
770
854
  await testGuardCsvGateRefuseBidi();
771
855
  await testGuardCsvGateSanitize();
@@ -65,6 +65,57 @@ function testGuardEmailLengthCaps() {
65
65
  }));
66
66
  }
67
67
 
68
+ function testGuardEmailMultibyteByteCaps() {
69
+ // A cap named in *Bytes must measure UTF-8 bytes, not UTF-16 .length code
70
+ // units. A 2-byte codepoint (U+00E9, "e acute") counts as 1 code unit, so a
71
+ // length-based comparison under-enforces: input over the byte cap slips
72
+ // through. Build inputs whose byteLength EXCEEDS the cap while .length does
73
+ // NOT, and assert each cap fires. Codepoint built programmatically so the
74
+ // source stays pure ASCII.
75
+ var acute = String.fromCodePoint(0x00e9); // U+00E9 = 2 UTF-8 bytes
76
+ var mb40 = new Array(41).join(acute); // .length 40, 80 bytes
77
+ var mb50 = new Array(51).join(acute); // .length 50, 100 bytes
78
+
79
+ // Message total-byte cap (maxBytes).
80
+ var rvMsg = b.guardEmail.validateMessage(mb50, { profile: "strict", maxBytes: 60 });
81
+ check("message maxBytes cap measures bytes (multibyte over byte cap → too-large)",
82
+ rvMsg.issues.some(function (i) { return i.kind === "too-large"; }));
83
+
84
+ // Total-address byte cap (maxAddressBytes).
85
+ var rvAddr = b.guardEmail.validateAddress(mb40 + "@example.com",
86
+ { profile: "strict", maxAddressBytes: 60, maxLocalPartBytes: 100000, maxDomainBytes: 100000 });
87
+ check("address maxAddressBytes cap measures bytes (multibyte over byte cap → address-cap)",
88
+ rvAddr.issues.some(function (i) { return i.kind === "address-cap"; }));
89
+
90
+ // Local-part byte cap (maxLocalPartBytes).
91
+ var rvLp = b.guardEmail.validateAddress(mb40 + "@example.com",
92
+ { profile: "strict", maxLocalPartBytes: 60, maxAddressBytes: 100000, maxDomainBytes: 100000 });
93
+ check("local-part maxLocalPartBytes cap measures bytes (multibyte over byte cap → local-part-cap)",
94
+ rvLp.issues.some(function (i) { return i.kind === "local-part-cap"; }));
95
+
96
+ // Domain byte cap (maxDomainBytes).
97
+ var rvDom = b.guardEmail.validateAddress("a@" + mb40 + ".com",
98
+ { profile: "strict", maxDomainBytes: 60, maxAddressBytes: 100000, maxLocalPartBytes: 100000 });
99
+ check("domain maxDomainBytes cap measures bytes (multibyte over byte cap → domain-cap)",
100
+ rvDom.issues.some(function (i) { return i.kind === "domain-cap"; }));
101
+
102
+ // Header-line byte cap (maxHeaderLineBytes).
103
+ var msg = "From: alice@example.com\r\nSubject: " + mb40 + "\r\n\r\nbody\r\n";
104
+ var rvHdr = b.guardEmail.validateMessage(msg, { profile: "strict", maxHeaderLineBytes: 60 });
105
+ check("header-line maxHeaderLineBytes cap measures bytes (multibyte over byte cap → header-line-cap)",
106
+ rvHdr.issues.some(function (i) { return i.kind === "header-line-cap"; }));
107
+
108
+ // ASCII regression: clean inputs are unchanged; a real over-cap ASCII
109
+ // local-part still fires (byte count == code-unit count for ASCII).
110
+ var cleanAddr = b.guardEmail.validateAddress("alice@example.com", { profile: "strict" });
111
+ check("ASCII clean address unchanged (byte-cap fix is ASCII-transparent)",
112
+ cleanAddr.ok === true && cleanAddr.issues.length === 0);
113
+ var asciiLp = b.guardEmail.validateAddress(new Array(67).join("a") + "@example.com",
114
+ { profile: "strict" });
115
+ check("ASCII local-part > 64 still caps after byte-measure fix",
116
+ asciiLp.issues.some(function (i) { return i.kind === "local-part-cap"; }));
117
+ }
118
+
68
119
  function testGuardEmailIpLiteral() {
69
120
  var rv = b.guardEmail.validateAddress("user@[1.2.3.4]", { profile: "strict" });
70
121
  check("IP literal address detected (DMARC alignment bypass)",
@@ -138,6 +189,31 @@ function testGuardEmailCrlfHeaderInjection() {
138
189
  }));
139
190
  }
140
191
 
192
+ function testGuardEmailAutoRouterHeaderInjection() {
193
+ // The auto-router footgun: a value an operator intends as a single address
194
+ // but that carries CRLF + an injected header. `validate` sees the newline,
195
+ // treats it as a message, and (before the fix) the bare `a@b.com` line was
196
+ // silently dropped while the injected `Bcc` passed — ok:true. The shared
197
+ // mimeParse.classifyHeaderBlock now surfaces the colon-less header-section
198
+ // line as malformed → ok:false.
199
+ var rv = b.guardEmail.validate("a@b.com\r\nBcc: evil@x.com", { profile: "strict" });
200
+ check("auto-router CRLF+injected-header → ok:false",
201
+ rv.ok === false &&
202
+ rv.issues.some(function (i) { return i.kind === "malformed-header-line"; }));
203
+
204
+ // A bare address with a trailing CRLF is the same footgun shape.
205
+ var rv2 = b.guardEmail.validate("alice@example.com\r\n", { profile: "strict" });
206
+ check("auto-router address+trailing-CRLF → ok:false", rv2.ok === false);
207
+
208
+ // A well-formed RFC 5322 message must still pass — header fields, folding, and
209
+ // bare BODY lines after the blank boundary are all legitimate.
210
+ var ok = b.guardEmail.validate(
211
+ "From: a@example.com\r\nTo: b@example.com\r\nSubject: long\r\n folded\r\n" +
212
+ "Date: Mon, 5 May 2026 10:00:00 +0000\r\n\r\nbare body line\r\nanother\r\n",
213
+ { profile: "strict" });
214
+ check("well-formed message (folding + body lines) still passes", ok.ok === true);
215
+ }
216
+
141
217
  function testGuardEmailDisplayNameSpoof() {
142
218
  var msg = 'From: "support@apple.com" <attacker@evil.com>\r\n' +
143
219
  "To: bob@example.com\r\nSubject: x\r\n\r\nbody\r\n";
@@ -227,6 +303,7 @@ async function run() {
227
303
  testGuardEmailCleanAddress();
228
304
  testGuardEmailMultiAt();
229
305
  testGuardEmailLengthCaps();
306
+ testGuardEmailMultibyteByteCaps();
230
307
  testGuardEmailIpLiteral();
231
308
  testGuardEmailAddressComment();
232
309
  testGuardEmailPunycode();
@@ -235,6 +312,7 @@ async function run() {
235
312
  testGuardEmailSyntaxReject();
236
313
  testGuardEmailBareLfSmuggling();
237
314
  testGuardEmailCrlfHeaderInjection();
315
+ testGuardEmailAutoRouterHeaderInjection();
238
316
  testGuardEmailDisplayNameSpoof();
239
317
  testGuardEmailBom();
240
318
  testGuardEmailHeaderLineCap();
@@ -344,6 +344,28 @@ function testGuardFilenameSanitizeStripMode() {
344
344
  captured[0].outcome === "success");
345
345
  }
346
346
 
347
+ function testGdprPostureMatchesBalancedTier() {
348
+ // gdpr is the balanced tier for a filename guard: it allows non-ASCII
349
+ // (data-minimization keeps the value usable) rather than inheriting the
350
+ // strict tier's requireAscii:true. The drift was a partial gdpr posture
351
+ // object that omitted requireAscii, so resolved opts silently backfilled
352
+ // it from the strict-derived defaults — making gdpr a strict/balanced
353
+ // hybrid. Drive the real consumer path: a non-ASCII leaf must NOT raise
354
+ // a non-ascii issue under gdpr.
355
+ var rv = b.guardFilename.validate("café.txt", { compliancePosture: "gdpr" });
356
+ check("gdpr (balanced tier) does not flag non-ascii on a filename leaf",
357
+ !rv.issues.some(function (issue) { return issue.kind === "non-ascii"; }));
358
+
359
+ // The deliberate per-posture overlay survives the routing: gdpr strips
360
+ // bidi / control on leaf names (data-minimization) where the balanced
361
+ // profile would reject them. Both together prove balanced-tier base +
362
+ // intended overlay.
363
+ check("gdpr posture overlay keeps bidiPolicy=strip",
364
+ b.guardFilename.COMPLIANCE_POSTURES.gdpr.bidiPolicy === "strip");
365
+ check("gdpr posture overlay keeps controlPolicy=strip",
366
+ b.guardFilename.COMPLIANCE_POSTURES.gdpr.controlPolicy === "strip");
367
+ }
368
+
347
369
  function testGuardFilenameCompliancePosture() {
348
370
  var hipaa = b.guardFilename.compliancePosture("hipaa");
349
371
  check("compliancePosture('hipaa') sets reject policies",
@@ -386,6 +408,7 @@ async function run() {
386
408
  testGuardFilenameDoubleExtension();
387
409
  testGuardFilenameOverlongUtf8();
388
410
  testGuardFilenameAsciiOnlyStrict();
411
+ testGdprPostureMatchesBalancedTier();
389
412
  testGuardFilenameClean();
390
413
  testGuardFilenameSanitize();
391
414
  testGuardFilenameSanitizeStripMode();
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * Gate-disposition coverage — every finding kind a content guard can emit MUST
4
+ * be classified by that guard's dispositionFor (→ refuse / sanitize / audit), so
5
+ * buildContentGate never falls back to severity for a guard's own finding. The
6
+ * conservative severity fallback exists only for operator-injected extraIssues
7
+ * and as a secure backstop; this test proves it is dead code for guard findings.
8
+ *
9
+ * The kind set is SCANNED from each guard's source (every `kind:` literal,
10
+ * including ternary branches) plus the shared character-threat kinds emitted by
11
+ * codepointClass.detectCharThreats — so a NEW finding kind added to a guard
12
+ * without a dispositionFor mapping fails this test (RED) rather than silently
13
+ * inheriting the conservative refuse.
14
+ */
15
+
16
+ var fs = require("fs");
17
+ var path = require("path");
18
+ var helpers = require("../helpers");
19
+ var check = helpers.check;
20
+
21
+ var LIB = path.join(__dirname, "..", "..", "lib");
22
+
23
+ // Shared char-threat kinds come from codepointClass.detectCharThreats, not the
24
+ // guard source, so they are added to every content guard's expected set
25
+ // (zero-width is opt-in via the detector's 4th arg for the markup guards).
26
+ var SHARED_CHAR_THREATS = ["bidi-override", "null-byte", "control-char", "zero-width"];
27
+
28
+ var GUARDS = [
29
+ { name: "csv", file: "guard-csv.js", profiles: ["strict", "balanced", "permissive", "email-attachment"] },
30
+ { name: "html", file: "guard-html.js", profiles: ["strict", "balanced", "permissive"] },
31
+ { name: "svg", file: "guard-svg.js", profiles: ["strict", "balanced", "permissive"] },
32
+ { name: "xml", file: "guard-xml.js", profiles: ["strict", "balanced", "permissive"] },
33
+ { name: "markdown", file: "guard-markdown.js", profiles: ["strict", "balanced", "permissive"] },
34
+ { name: "json", file: "guard-json.js", profiles: ["strict", "balanced", "permissive"] },
35
+ ];
36
+
37
+ // The guard-KIND taxonomy (INTEGRATION_FIXTURES.kind / the guard's KIND export)
38
+ // is "content" | "entries" | "filename" — not a finding kind, so the scan skips
39
+ // these (they are never produced by detect and never reach a content gate).
40
+ var NON_FINDING_KINDS = { content: true, entries: true, filename: true };
41
+
42
+ // Extract every finding kind from a guard source: the token after `kind:` up to
43
+ // the first comma, then every quoted string inside it (covers both the literal
44
+ // `kind: "x"` and the ternary `kind: c ? "a" : "b"` forms).
45
+ function _scanKinds(source) {
46
+ var kinds = {};
47
+ var re = /kind:\s*([^,\n]+)/g;
48
+ var m;
49
+ while ((m = re.exec(source)) !== null) {
50
+ var seg = m[1];
51
+ var qre = /"([a-z][a-z0-9-]*)"/g;
52
+ var q;
53
+ while ((q = qre.exec(seg)) !== null) {
54
+ if (!NON_FINDING_KINDS[q[1]]) kinds[q[1]] = true;
55
+ }
56
+ }
57
+ return Object.keys(kinds);
58
+ }
59
+
60
+ function run() {
61
+ var VALID = { refuse: true, sanitize: true, audit: true };
62
+
63
+ GUARDS.forEach(function (g) {
64
+ var mod = require(path.join(LIB, g.file));
65
+ check("[" + g.name + "] exposes dispositionFor test hook",
66
+ typeof mod._gateDispositionForTest === "function");
67
+ if (typeof mod._gateDispositionForTest !== "function") return;
68
+
69
+ var kinds = _scanKinds(fs.readFileSync(path.join(LIB, g.file), "utf8"));
70
+ SHARED_CHAR_THREATS.forEach(function (k) { if (kinds.indexOf(k) === -1) kinds.push(k); });
71
+
72
+ check("[" + g.name + "] scanned a non-empty finding-kind set", kinds.length > 0);
73
+
74
+ var unclassified = [];
75
+ g.profiles.forEach(function (profile) {
76
+ var opts = mod.resolveOpts({ profile: profile });
77
+ kinds.forEach(function (kind) {
78
+ var disp = mod._gateDispositionForTest({ kind: kind, severity: "high" }, opts);
79
+ if (!VALID[disp]) unclassified.push(profile + ":" + kind + "=" + disp);
80
+ });
81
+ });
82
+ check("[" + g.name + "] every finding kind is classified across all profiles" +
83
+ (unclassified.length ? " (UNCLASSIFIED: " + unclassified.slice(0, 8).join(", ") + ")" : ""),
84
+ unclassified.length === 0);
85
+ });
86
+ }
87
+
88
+ module.exports = { run: run };
89
+
90
+ if (require.main === module) {
91
+ try { run(); console.log("[guard-gate-disposition-coverage] OK — " + helpers.getChecks() + " checks passed"); }
92
+ catch (e) { console.error("FAIL:", e.stack || e); process.exit(1); }
93
+ }
@@ -233,6 +233,52 @@ function testGuardHtmlSizeCaps() {
233
233
  rv.issues.some(function (issue) { return issue.kind === "depth-cap"; }));
234
234
  }
235
235
 
236
+ // Byte caps measure UTF-8 bytes, not UTF-16 code units — a multibyte
237
+ // payload under the .length cap but over the byte cap must still be
238
+ // refused. "é" is 1 code unit but 2 UTF-8 bytes.
239
+ function testGuardHtmlByteCaps() {
240
+ var multi = "é".repeat(8); // .length 8, 16 UTF-8 bytes
241
+ check("fixture: multibyte byteLength exceeds .length",
242
+ multi.length === 8 && Buffer.byteLength(multi, "utf8") === 16);
243
+
244
+ // Top-level maxBytes — validate path (tokenizer refusal surfaces as an issue).
245
+ var rvSize = b.guardHtml.validate(multi, { profile: "strict", maxBytes: 10 });
246
+ check("maxBytes caps multibyte input over the byte limit (validate)",
247
+ rvSize.issues.some(function (issue) {
248
+ return issue.kind === "tokenize-failed" ||
249
+ /exceeds maxBytes/.test(issue.snippet || "");
250
+ }));
251
+
252
+ // Top-level maxBytes — sanitize path throws.
253
+ var threwBytes = null;
254
+ try { b.guardHtml.sanitize(multi, { profile: "strict", maxBytes: 10 }); }
255
+ catch (e) { threwBytes = e; }
256
+ check("maxBytes caps multibyte input over the byte limit (sanitize)",
257
+ threwBytes && /exceeds maxBytes/.test(threwBytes.message));
258
+
259
+ // Multibyte under BOTH the byte cap and .length stays accepted.
260
+ var smallMulti = "é".repeat(3); // .length 3, 6 bytes
261
+ var rvOk = b.guardHtml.validate(smallMulti, { profile: "strict", maxBytes: 10 });
262
+ check("maxBytes accepts multibyte input under the byte limit",
263
+ !rvOk.issues.some(function (issue) {
264
+ return issue.kind === "tokenize-failed" ||
265
+ /exceeds maxBytes/.test(issue.snippet || "");
266
+ }));
267
+
268
+ // Per-attribute maxAttrValueBytes measures bytes.
269
+ var attrVal = "é".repeat(8); // .length 8, 16 bytes
270
+ var rvAttr = b.guardHtml.validate('<a title="' + attrVal + '">x</a>',
271
+ { profile: "strict", maxAttrValueBytes: 10 });
272
+ check("maxAttrValueBytes caps multibyte attribute value over the byte limit",
273
+ rvAttr.issues.some(function (issue) { return issue.kind === "attr-value-too-large"; }));
274
+
275
+ // ASCII attribute value under the byte cap stays accepted.
276
+ var rvAttrOk = b.guardHtml.validate('<a title="short">x</a>',
277
+ { profile: "strict", maxAttrValueBytes: 10 });
278
+ check("maxAttrValueBytes accepts attribute value under the byte limit",
279
+ !rvAttrOk.issues.some(function (issue) { return issue.kind === "attr-value-too-large"; }));
280
+ }
281
+
236
282
  // ---- Sanitize round-trip ----
237
283
 
238
284
  function testGuardHtmlSanitizeBasic() {
@@ -328,6 +374,18 @@ function testGuardHtmlCompliancePosture() {
328
374
  threw && /unknown/.test(threw.message));
329
375
  }
330
376
 
377
+ // The gdpr posture is the balanced tier (data-minimization strips bytes
378
+ // rather than rejecting the whole value), so it must carry the balanced
379
+ // profile's attribute allowlist — which keeps `href`. The strict tier's
380
+ // 4-attribute allowlist (class/title/lang/dir) drops href; gdpr must not
381
+ // inherit it.
382
+ function testGdprPostureMatchesBalancedTier() {
383
+ var sanitized = b.guardHtml.sanitize(
384
+ '<a href="http://x.com/p">L</a>', { compliancePosture: "gdpr" });
385
+ check("gdpr posture keeps href on <a> (balanced tier, not strict backfill)",
386
+ sanitized === '<a href="http://x.com/p">L</a>');
387
+ }
388
+
331
389
  // ---- Run all ----
332
390
 
333
391
  async function run() {
@@ -345,10 +403,12 @@ async function run() {
345
403
  testGuardHtmlNullByte();
346
404
  testGuardHtmlControlChar();
347
405
  testGuardHtmlSizeCaps();
406
+ testGuardHtmlByteCaps();
348
407
  testGuardHtmlSanitizeBasic();
349
408
  testGuardHtmlEscape();
350
409
  testGuardHtmlBadProfile();
351
410
  testGuardHtmlCompliancePosture();
411
+ testGdprPostureMatchesBalancedTier();
352
412
  await testGuardHtmlGateClean();
353
413
  await testGuardHtmlGateRefuse();
354
414
  await testGuardHtmlGateSanitize();
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ /**
3
+ * guard-image — image content-safety primitive (b.guardImage).
4
+ *
5
+ * Covers: surface; registry parity; magic-byte / declared-MIME mismatch;
6
+ * polyglot rejection; unknown-magic; dimension + frame caps; inspectMagic;
7
+ * and the container-framing metadata strip (sanitize) — EXIF/XMP out of
8
+ * JPEG (APP1), text chunks out of PNG (tEXt), comment/app extensions out of
9
+ * GIF, EXIF/XMP RIFF chunks out of WebP with the VP8X flag bits cleared,
10
+ * the unsupported-format / malformed refusals, and refuse-before-strip for a
11
+ * polyglot / mismatch. The strip is byte-surgery over the linear container
12
+ * framing, not a pixel decoder.
13
+ */
14
+
15
+ var helpers = require("../helpers");
16
+ var b = helpers.b;
17
+ var check = helpers.check;
18
+
19
+ function _has(buf, s) { return buf.toString("latin1").indexOf(s) !== -1; }
20
+ function _code(fn) { try { fn(); return null; } catch (e) { return e && e.code; } }
21
+
22
+ // ---- fixture builders (kept ASCII; metadata payloads carry a sentinel) ----
23
+
24
+ function _jpegWithExif() {
25
+ return Buffer.concat([
26
+ Buffer.from([0xFF, 0xD8]), // SOI
27
+ Buffer.from([0xFF, 0xE1, 0x00, 0x0F]), Buffer.from("Exif GPSDATA", "latin1"), // APP1 (EXIF) len=15
28
+ Buffer.from([0xFF, 0xE0, 0x00, 0x10]), Buffer.from("JFIF ABCDEFGHIJ".slice(0, 14), "latin1"), // APP0 (JFIF) len=16
29
+ Buffer.from([0xFF, 0xD9]), // EOI
30
+ ]);
31
+ }
32
+
33
+ function _pngWithText() {
34
+ var ihdr = Buffer.concat([Buffer.from([0, 0, 0, 13]), Buffer.from("IHDR", "latin1"),
35
+ Buffer.from([0, 0, 0, 1, 0, 0, 0, 1, 8, 0, 0, 0, 0]), Buffer.from([1, 2, 3, 4])]);
36
+ var text = Buffer.concat([Buffer.from([0, 0, 0, 18]), Buffer.from("tEXt", "latin1"),
37
+ Buffer.from("Comment secret-gps", "latin1"), Buffer.from([9, 9, 9, 9])]);
38
+ var iend = Buffer.concat([Buffer.from([0, 0, 0, 0]), Buffer.from("IEND", "latin1"),
39
+ Buffer.from([0xAE, 0x42, 0x60, 0x82])]);
40
+ return Buffer.concat([Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]), ihdr, text, iend]);
41
+ }
42
+
43
+ function _gifWithComment() {
44
+ return Buffer.concat([
45
+ Buffer.from("GIF89a", "latin1"),
46
+ Buffer.from([1, 0, 1, 0, 0x00, 0, 0]), // LSD 1x1, no GCT
47
+ Buffer.from([0x21, 0xFE, 0x0A]), Buffer.from("secret-gps", "latin1"), Buffer.from([0x00]), // comment ext
48
+ Buffer.from([0x2C, 0, 0, 0, 0, 1, 0, 1, 0, 0x00]), // image descriptor
49
+ Buffer.from([0x02, 0x01, 0x44, 0x00]), // LZW min + sub-block + term
50
+ Buffer.from([0x3B]), // trailer
51
+ ]);
52
+ }
53
+
54
+ function _webpWithExif() {
55
+ return Buffer.concat([
56
+ Buffer.from("RIFF", "latin1"), Buffer.from([34, 0, 0, 0]), Buffer.from("WEBP", "latin1"),
57
+ Buffer.from("VP8 ", "latin1"), Buffer.from([4, 0, 0, 0]), Buffer.from([1, 2, 3, 4]),
58
+ Buffer.from("EXIF", "latin1"), Buffer.from([10, 0, 0, 0]), Buffer.from("secret-gps", "latin1"),
59
+ ]);
60
+ }
61
+
62
+ function testGuardImageSurface() {
63
+ check("guardImage is an object", typeof b.guardImage === "object");
64
+ check("guardImage.NAME === 'image'", b.guardImage.NAME === "image");
65
+ check("guardImage.PROFILES has strict", !!b.guardImage.PROFILES["strict"]);
66
+ check("guardImage.COMPLIANCE_POSTURES gdpr", !!b.guardImage.COMPLIANCE_POSTURES["gdpr"]);
67
+ check("guardImage.validate is a function", typeof b.guardImage.validate === "function");
68
+ check("guardImage.sanitize is a function", typeof b.guardImage.sanitize === "function");
69
+ check("guardImage.gate is a function", typeof b.guardImage.gate === "function");
70
+ check("guardImage.inspectMagic is a function", typeof b.guardImage.inspectMagic === "function");
71
+ check("frameworkError.GuardImageError exposed", typeof b.frameworkError.GuardImageError === "function");
72
+ }
73
+
74
+ function testGuardImageRegistryParity() {
75
+ check("guardImage registered in guardAll",
76
+ b.guardAll.allGuards().some(function (g) { return (g.name || g.NAME) === "image"; }));
77
+ }
78
+
79
+ function testInspectMagic() {
80
+ check("inspectMagic detects png",
81
+ b.guardImage.inspectMagic(Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])).indexOf("image/png") !== -1);
82
+ check("inspectMagic empty on garbage",
83
+ b.guardImage.inspectMagic(Buffer.from([0x00, 0x01, 0x02])).length === 0);
84
+ }
85
+
86
+ function testValidateMismatchAndPolyglot() {
87
+ var rv = b.guardImage.validate({ bytes: Buffer.from([0xFF, 0xD8, 0xFF]), declaredMime: "image/png" }, { profile: "strict" });
88
+ check("mismatch: validate ok:false", rv.ok === false);
89
+ check("mismatch: kind reported", rv.issues.some(function (i) { return i.kind === "mime-mismatch"; }));
90
+ }
91
+
92
+ // ---- the real metadata strip ----
93
+
94
+ function testStripJpegExif() {
95
+ var src = _jpegWithExif();
96
+ var out = b.guardImage.sanitize({ bytes: src });
97
+ check("jpeg: EXIF (APP1) payload removed", !_has(out.bytes, "GPSDATA") && !_has(out.bytes, "Exif"));
98
+ check("jpeg: JFIF (APP0) preserved", _has(out.bytes, "JFIF"));
99
+ check("jpeg: output shrank", out.bytes.length < src.length);
100
+ check("jpeg: SOI + EOI intact",
101
+ out.bytes[0] === 0xFF && out.bytes[1] === 0xD8 &&
102
+ out.bytes[out.bytes.length - 2] === 0xFF && out.bytes[out.bytes.length - 1] === 0xD9);
103
+ check("jpeg: bag is a fresh object (bytes replaced)", typeof out === "object" && Buffer.isBuffer(out.bytes));
104
+ }
105
+
106
+ function testStripPngText() {
107
+ var out = b.guardImage.sanitize({ bytes: _pngWithText() });
108
+ check("png: tEXt payload removed", !_has(out.bytes, "secret-gps"));
109
+ check("png: IHDR preserved", _has(out.bytes, "IHDR"));
110
+ check("png: IEND preserved", _has(out.bytes, "IEND"));
111
+ check("png: signature intact", out.bytes[0] === 0x89 && out.bytes[1] === 0x50);
112
+ }
113
+
114
+ function testStripGifComment() {
115
+ var out = b.guardImage.sanitize({ bytes: _gifWithComment() });
116
+ check("gif: comment payload removed", !_has(out.bytes, "secret-gps"));
117
+ check("gif: header preserved", _has(out.bytes, "GIF89a"));
118
+ check("gif: trailer preserved", out.bytes[out.bytes.length - 1] === 0x3B);
119
+ }
120
+
121
+ function testStripWebpExif() {
122
+ var out = b.guardImage.sanitize({ bytes: _webpWithExif() });
123
+ check("webp: EXIF payload removed", !_has(out.bytes, "secret-gps"));
124
+ check("webp: VP8 chunk preserved", _has(out.bytes, "VP8 "));
125
+ check("webp: RIFF size rewritten", out.bytes.readUInt32LE(4) === 16);
126
+ }
127
+
128
+ function testStripWebpVp8xFlags() {
129
+ var webpx = Buffer.concat([
130
+ Buffer.from("RIFF", "latin1"), Buffer.from([0, 0, 0, 0]), Buffer.from("WEBP", "latin1"),
131
+ Buffer.from("VP8X", "latin1"), Buffer.from([10, 0, 0, 0]), Buffer.from([0x0C, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
132
+ Buffer.from("EXIF", "latin1"), Buffer.from([4, 0, 0, 0]), Buffer.from([9, 9, 9, 9]),
133
+ ]);
134
+ var out = b.guardImage.sanitize({ bytes: webpx });
135
+ check("webp: VP8X EXIF+XMP flag bits cleared", (out.bytes[20] & 0x0C) === 0);
136
+ }
137
+
138
+ function testRefuseBeforeStrip() {
139
+ // A MIME-mismatch / polyglot must refuse, never strip-and-serve.
140
+ check("mismatch refuses (not strips)",
141
+ _code(function () { b.guardImage.sanitize({ bytes: _jpegWithExif(), declaredMime: "image/png" }, { profile: "strict" }); }) === "image.mime-mismatch");
142
+ }
143
+
144
+ function testRefuseUnsupportedFormat() {
145
+ var tiff = Buffer.from([0x49, 0x49, 0x2A, 0x00, 8, 0, 0, 0]);
146
+ check("tiff: refuse unsupported-format",
147
+ _code(function () { b.guardImage.sanitize({ bytes: tiff }); }) === "image.sanitize-unsupported-format");
148
+ }
149
+
150
+ function testRefuseMalformed() {
151
+ var bad = Buffer.from([0xFF, 0xD8, 0xFF, 0xE1, 0x00, 0xFF]); // APP1 length overruns
152
+ check("malformed: refuse, not half-strip",
153
+ _code(function () { b.guardImage.sanitize({ bytes: bad }); }) === "image.sanitize-malformed");
154
+ }
155
+
156
+ function testBmpPassthrough() {
157
+ // BMP carries no text/EXIF metadata container — pass through unchanged.
158
+ var bmp = Buffer.from([0x42, 0x4D, 0x10, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0]);
159
+ var out = b.guardImage.sanitize({ bytes: bmp });
160
+ check("bmp: passes through (no metadata container)", out.bytes === bmp);
161
+ }
162
+
163
+ function run() {
164
+ testGuardImageSurface();
165
+ testGuardImageRegistryParity();
166
+ testInspectMagic();
167
+ testValidateMismatchAndPolyglot();
168
+ testStripJpegExif();
169
+ testStripPngText();
170
+ testStripGifComment();
171
+ testStripWebpExif();
172
+ testStripWebpVp8xFlags();
173
+ testRefuseBeforeStrip();
174
+ testRefuseUnsupportedFormat();
175
+ testRefuseMalformed();
176
+ testBmpPassthrough();
177
+ }
178
+
179
+ module.exports = { run: run };
180
+
181
+ if (require.main === module) {
182
+ try { run(); console.log("[guard-image] OK — " + helpers.getChecks() + " checks passed"); }
183
+ catch (e) { console.error("FAIL:", e.stack || e); process.exit(1); }
184
+ }