@blamejs/blamejs-shop 0.0.44

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 (1220) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +17 -0
  3. package/README.md +117 -0
  4. package/SECURITY.md +139 -0
  5. package/lib/admin.js +952 -0
  6. package/lib/analytics.js +267 -0
  7. package/lib/cart.js +279 -0
  8. package/lib/catalog-import.js +344 -0
  9. package/lib/catalog.js +769 -0
  10. package/lib/checkout.js +320 -0
  11. package/lib/config.js +151 -0
  12. package/lib/customers.js +322 -0
  13. package/lib/email.js +242 -0
  14. package/lib/externaldb-d1.js +283 -0
  15. package/lib/index.js +57 -0
  16. package/lib/inventory-alerts.js +198 -0
  17. package/lib/newsletter.js +142 -0
  18. package/lib/order.js +380 -0
  19. package/lib/payment.js +318 -0
  20. package/lib/pricing.js +185 -0
  21. package/lib/r2-bridge.js +169 -0
  22. package/lib/shipping.js +185 -0
  23. package/lib/storefront.js +2160 -0
  24. package/lib/subscriptions.js +410 -0
  25. package/lib/tax.js +161 -0
  26. package/lib/theme.js +194 -0
  27. package/lib/vendor/MANIFEST.json +19 -0
  28. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +23 -0
  29. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +34 -0
  30. package/lib/vendor/blamejs/.clusterfuzzlite/project.yaml +16 -0
  31. package/lib/vendor/blamejs/.dockerignore +45 -0
  32. package/lib/vendor/blamejs/.gitattributes +42 -0
  33. package/lib/vendor/blamejs/.github/CODEOWNERS +4 -0
  34. package/lib/vendor/blamejs/.github/FUNDING.yml +2 -0
  35. package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/bug_report.md +58 -0
  36. package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/config.yml +8 -0
  37. package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/feature_request.md +99 -0
  38. package/lib/vendor/blamejs/.github/PULL_REQUEST_TEMPLATE.md +77 -0
  39. package/lib/vendor/blamejs/.github/dependabot.yml +37 -0
  40. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +148 -0
  41. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +107 -0
  42. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +122 -0
  43. package/lib/vendor/blamejs/.github/workflows/ci.yml +511 -0
  44. package/lib/vendor/blamejs/.github/workflows/codeql.yml +50 -0
  45. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +655 -0
  46. package/lib/vendor/blamejs/.github/workflows/release-container.yml +406 -0
  47. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +101 -0
  48. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +134 -0
  49. package/lib/vendor/blamejs/.gitignore +102 -0
  50. package/lib/vendor/blamejs/.gitleaks.toml +166 -0
  51. package/lib/vendor/blamejs/.hadolint.yaml +18 -0
  52. package/lib/vendor/blamejs/.npmrc +5 -0
  53. package/lib/vendor/blamejs/.pinact.yaml +17 -0
  54. package/lib/vendor/blamejs/ARCHITECTURE.md +158 -0
  55. package/lib/vendor/blamejs/CHANGELOG.md +1351 -0
  56. package/lib/vendor/blamejs/CODE_OF_CONDUCT.md +86 -0
  57. package/lib/vendor/blamejs/CONTRIBUTING.md +156 -0
  58. package/lib/vendor/blamejs/GOVERNANCE.md +201 -0
  59. package/lib/vendor/blamejs/LICENSE +201 -0
  60. package/lib/vendor/blamejs/LTS-CALENDAR.md +29 -0
  61. package/lib/vendor/blamejs/MIGRATING.md +29 -0
  62. package/lib/vendor/blamejs/NOTICE +81 -0
  63. package/lib/vendor/blamejs/README.md +304 -0
  64. package/lib/vendor/blamejs/SECURITY.md +432 -0
  65. package/lib/vendor/blamejs/api-snapshot.json +48709 -0
  66. package/lib/vendor/blamejs/assets/BlameJS_Logo.png +0 -0
  67. package/lib/vendor/blamejs/assets/BlameJS_Logo.svg +129 -0
  68. package/lib/vendor/blamejs/bench/README.md +77 -0
  69. package/lib/vendor/blamejs/bench/_helpers.js +70 -0
  70. package/lib/vendor/blamejs/bench/baseline.json +183 -0
  71. package/lib/vendor/blamejs/bench/crypto-hash.bench.js +19 -0
  72. package/lib/vendor/blamejs/bench/crypto-symmetric.bench.js +28 -0
  73. package/lib/vendor/blamejs/bench/run.js +140 -0
  74. package/lib/vendor/blamejs/bench/safe-json.bench.js +31 -0
  75. package/lib/vendor/blamejs/bin/blamejs.js +13 -0
  76. package/lib/vendor/blamejs/docker/caddy/Caddyfile +46 -0
  77. package/lib/vendor/blamejs/docker/coredns/Corefile +37 -0
  78. package/lib/vendor/blamejs/docker/haproxy/haproxy.cfg +52 -0
  79. package/lib/vendor/blamejs/docker/init/generate-certs.sh +118 -0
  80. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +87 -0
  81. package/lib/vendor/blamejs/docker/mitmproxy/config.yaml +16 -0
  82. package/lib/vendor/blamejs/docker/mongo/init-tls.sh +17 -0
  83. package/lib/vendor/blamejs/docker/mysql/my.cnf +12 -0
  84. package/lib/vendor/blamejs/docker/nats/nats.conf +33 -0
  85. package/lib/vendor/blamejs/docker/postgres/init-tls.sh +17 -0
  86. package/lib/vendor/blamejs/docker/postgres/postgresql.conf +18 -0
  87. package/lib/vendor/blamejs/docker/rabbitmq/rabbitmq.conf +18 -0
  88. package/lib/vendor/blamejs/docker/redis/redis.conf +15 -0
  89. package/lib/vendor/blamejs/docker/squid/squid.conf +24 -0
  90. package/lib/vendor/blamejs/docker/syslog/syslog-ng.conf +34 -0
  91. package/lib/vendor/blamejs/docker-compose.test.yml +545 -0
  92. package/lib/vendor/blamejs/docs/cis-postgres-crosswalk.md +102 -0
  93. package/lib/vendor/blamejs/docs/cis-sqlite-equivalent.md +92 -0
  94. package/lib/vendor/blamejs/eslint.config.mjs +204 -0
  95. package/lib/vendor/blamejs/examples/wiki/Caddyfile +40 -0
  96. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +218 -0
  97. package/lib/vendor/blamejs/examples/wiki/Dockerfile +120 -0
  98. package/lib/vendor/blamejs/examples/wiki/README.md +157 -0
  99. package/lib/vendor/blamejs/examples/wiki/cli-snapshot.json +250 -0
  100. package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +231 -0
  101. package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +166 -0
  102. package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +217 -0
  103. package/lib/vendor/blamejs/examples/wiki/lib/auto-site-entries.js +139 -0
  104. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +555 -0
  105. package/lib/vendor/blamejs/examples/wiki/lib/harvest-cli.js +507 -0
  106. package/lib/vendor/blamejs/examples/wiki/lib/harvest-env-vars.js +435 -0
  107. package/lib/vendor/blamejs/examples/wiki/lib/harvest-errors.js +282 -0
  108. package/lib/vendor/blamejs/examples/wiki/lib/harvest-vendored-deps.js +321 -0
  109. package/lib/vendor/blamejs/examples/wiki/lib/nav.js +15 -0
  110. package/lib/vendor/blamejs/examples/wiki/lib/opts-resolver.js +75 -0
  111. package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +508 -0
  112. package/lib/vendor/blamejs/examples/wiki/lib/section.js +276 -0
  113. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +587 -0
  114. package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +318 -0
  115. package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +122 -0
  116. package/lib/vendor/blamejs/examples/wiki/migrations/0001-pages-schema.js +74 -0
  117. package/lib/vendor/blamejs/examples/wiki/package.json +18 -0
  118. package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.png +0 -0
  119. package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.svg +129 -0
  120. package/lib/vendor/blamejs/examples/wiki/public/robots.txt +5 -0
  121. package/lib/vendor/blamejs/examples/wiki/public/vendor/MANIFEST.json +30 -0
  122. package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.css +1 -0
  123. package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.js +15 -0
  124. package/lib/vendor/blamejs/examples/wiki/public/wiki.css +1250 -0
  125. package/lib/vendor/blamejs/examples/wiki/routes/admin.js +366 -0
  126. package/lib/vendor/blamejs/examples/wiki/routes/integration.js +230 -0
  127. package/lib/vendor/blamejs/examples/wiki/routes/pages.js +266 -0
  128. package/lib/vendor/blamejs/examples/wiki/scripts/backfill-module-metadata.js +214 -0
  129. package/lib/vendor/blamejs/examples/wiki/seeders/prod/0001-default-pages.js +35 -0
  130. package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/_index.js +34 -0
  131. package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/api.js +76 -0
  132. package/lib/vendor/blamejs/examples/wiki/server.js +129 -0
  133. package/lib/vendor/blamejs/examples/wiki/site.config.js +197 -0
  134. package/lib/vendor/blamejs/examples/wiki/snippets/README.md +38 -0
  135. package/lib/vendor/blamejs/examples/wiki/snippets/auth/password-hash.example.js +15 -0
  136. package/lib/vendor/blamejs/examples/wiki/src/editor.js +103 -0
  137. package/lib/vendor/blamejs/examples/wiki/src/wiki.js +349 -0
  138. package/lib/vendor/blamejs/examples/wiki/test/AUDIT.md +155 -0
  139. package/lib/vendor/blamejs/examples/wiki/test/codebase-patterns.test.js +594 -0
  140. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +741 -0
  141. package/lib/vendor/blamejs/examples/wiki/test/find-missing-pages.js +254 -0
  142. package/lib/vendor/blamejs/examples/wiki/test/integration.js +391 -0
  143. package/lib/vendor/blamejs/examples/wiki/test/validate-cli-snapshot.js +379 -0
  144. package/lib/vendor/blamejs/examples/wiki/test/validate-env-snapshot.js +346 -0
  145. package/lib/vendor/blamejs/examples/wiki/test/validate-nav-coverage.js +212 -0
  146. package/lib/vendor/blamejs/examples/wiki/test/validate-site-coverage.js +252 -0
  147. package/lib/vendor/blamejs/examples/wiki/test/validate-source-comment-blocks.js +107 -0
  148. package/lib/vendor/blamejs/examples/wiki/views/_layout.html +115 -0
  149. package/lib/vendor/blamejs/examples/wiki/views/admin/api-keys.html +51 -0
  150. package/lib/vendor/blamejs/examples/wiki/views/admin/dashboard.html +22 -0
  151. package/lib/vendor/blamejs/examples/wiki/views/admin/edit.html +17 -0
  152. package/lib/vendor/blamejs/examples/wiki/views/home.html +85 -0
  153. package/lib/vendor/blamejs/examples/wiki/views/login.html +18 -0
  154. package/lib/vendor/blamejs/examples/wiki/views/page.html +5 -0
  155. package/lib/vendor/blamejs/examples/wiki/views/partials/nav.html +13 -0
  156. package/lib/vendor/blamejs/examples/wiki/views/search.html +19 -0
  157. package/lib/vendor/blamejs/examples/wiki/wiki.config.js +15 -0
  158. package/lib/vendor/blamejs/fuzz/README.md +137 -0
  159. package/lib/vendor/blamejs/fuzz/_expected.js +35 -0
  160. package/lib/vendor/blamejs/fuzz/guard-agent-registry.fuzz.js +22 -0
  161. package/lib/vendor/blamejs/fuzz/guard-csv.fuzz.js +16 -0
  162. package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/01-basic.csv +3 -0
  163. package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/02-formula.csv +1 -0
  164. package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/03-hyperlink.csv +1 -0
  165. package/lib/vendor/blamejs/fuzz/guard-dsn.fuzz.js +22 -0
  166. package/lib/vendor/blamejs/fuzz/guard-email.fuzz.js +16 -0
  167. package/lib/vendor/blamejs/fuzz/guard-email_seed_corpus/01-basic.eml +5 -0
  168. package/lib/vendor/blamejs/fuzz/guard-envelope.fuzz.js +24 -0
  169. package/lib/vendor/blamejs/fuzz/guard-event-bus-payload.fuzz.js +24 -0
  170. package/lib/vendor/blamejs/fuzz/guard-event-bus-topic.fuzz.js +20 -0
  171. package/lib/vendor/blamejs/fuzz/guard-html.fuzz.js +16 -0
  172. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/01-basic.html +1 -0
  173. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/02-script.html +1 -0
  174. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/03-event.html +1 -0
  175. package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/04-jsurl.html +1 -0
  176. package/lib/vendor/blamejs/fuzz/guard-idempotency-key.fuzz.js +20 -0
  177. package/lib/vendor/blamejs/fuzz/guard-imap-command.fuzz.js +35 -0
  178. package/lib/vendor/blamejs/fuzz/guard-jmap.fuzz.js +41 -0
  179. package/lib/vendor/blamejs/fuzz/guard-json.fuzz.js +16 -0
  180. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/01-basic.json +1 -0
  181. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/02-proto.json +1 -0
  182. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/03-dupkey.json +1 -0
  183. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/04-nan.json +1 -0
  184. package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/05-bom.json +1 -0
  185. package/lib/vendor/blamejs/fuzz/guard-list-id.fuzz.js +21 -0
  186. package/lib/vendor/blamejs/fuzz/guard-list-unsubscribe.fuzz.js +25 -0
  187. package/lib/vendor/blamejs/fuzz/guard-mail-compose.fuzz.js +22 -0
  188. package/lib/vendor/blamejs/fuzz/guard-mail-move.fuzz.js +22 -0
  189. package/lib/vendor/blamejs/fuzz/guard-mail-query.fuzz.js +27 -0
  190. package/lib/vendor/blamejs/fuzz/guard-mail-reply.fuzz.js +23 -0
  191. package/lib/vendor/blamejs/fuzz/guard-mail-sieve.fuzz.js +36 -0
  192. package/lib/vendor/blamejs/fuzz/guard-managesieve-command.fuzz.js +26 -0
  193. package/lib/vendor/blamejs/fuzz/guard-markdown.fuzz.js +16 -0
  194. package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/01-basic.md +2 -0
  195. package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/02-jsurl.md +1 -0
  196. package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/03-jsimg.md +1 -0
  197. package/lib/vendor/blamejs/fuzz/guard-message-id.fuzz.js +26 -0
  198. package/lib/vendor/blamejs/fuzz/guard-pop3-command.fuzz.js +23 -0
  199. package/lib/vendor/blamejs/fuzz/guard-posture-chain.fuzz.js +22 -0
  200. package/lib/vendor/blamejs/fuzz/guard-saga-config.fuzz.js +32 -0
  201. package/lib/vendor/blamejs/fuzz/guard-smtp-command.fuzz.js +27 -0
  202. package/lib/vendor/blamejs/fuzz/guard-snapshot-envelope.fuzz.js +22 -0
  203. package/lib/vendor/blamejs/fuzz/guard-stream-args.fuzz.js +22 -0
  204. package/lib/vendor/blamejs/fuzz/guard-svg.fuzz.js +16 -0
  205. package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/01-basic.svg +1 -0
  206. package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/02-script.svg +1 -0
  207. package/lib/vendor/blamejs/fuzz/guard-tenant-id.fuzz.js +20 -0
  208. package/lib/vendor/blamejs/fuzz/guard-trace-context.fuzz.js +30 -0
  209. package/lib/vendor/blamejs/fuzz/guard-xml.fuzz.js +16 -0
  210. package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/01-basic.xml +1 -0
  211. package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/02-xxe.xml +1 -0
  212. package/lib/vendor/blamejs/fuzz/guard-yaml.fuzz.js +16 -0
  213. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/01-basic.yaml +2 -0
  214. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/02-anchor.yaml +2 -0
  215. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/03-norway.yaml +1 -0
  216. package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/04-multidoc.yaml +4 -0
  217. package/lib/vendor/blamejs/fuzz/parsers__safe-ini.fuzz.js +16 -0
  218. package/lib/vendor/blamejs/fuzz/parsers__safe-ini_seed_corpus/01-basic.ini +2 -0
  219. package/lib/vendor/blamejs/fuzz/parsers__safe-toml.fuzz.js +16 -0
  220. package/lib/vendor/blamejs/fuzz/parsers__safe-toml_seed_corpus/01-basic.toml +4 -0
  221. package/lib/vendor/blamejs/fuzz/parsers__safe-xml.fuzz.js +16 -0
  222. package/lib/vendor/blamejs/fuzz/parsers__safe-xml_seed_corpus/01-basic.xml +1 -0
  223. package/lib/vendor/blamejs/fuzz/parsers__safe-yaml.fuzz.js +16 -0
  224. package/lib/vendor/blamejs/fuzz/parsers__safe-yaml_seed_corpus/01-basic.yaml +4 -0
  225. package/lib/vendor/blamejs/fuzz/safe-decompress.fuzz.js +49 -0
  226. package/lib/vendor/blamejs/fuzz/safe-dns.fuzz.js +29 -0
  227. package/lib/vendor/blamejs/fuzz/safe-ical.fuzz.js +16 -0
  228. package/lib/vendor/blamejs/fuzz/safe-icap.fuzz.js +42 -0
  229. package/lib/vendor/blamejs/fuzz/safe-json.fuzz.js +25 -0
  230. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/01-object.txt +1 -0
  231. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/02-array.txt +1 -0
  232. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/03-string.txt +1 -0
  233. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/04-proto.txt +1 -0
  234. package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/05-deep.txt +1 -0
  235. package/lib/vendor/blamejs/fuzz/safe-jsonpath.fuzz.js +16 -0
  236. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/01-basic.txt +1 -0
  237. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/02-filter.txt +1 -0
  238. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/03-deepscan.txt +1 -0
  239. package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/04-slice.txt +1 -0
  240. package/lib/vendor/blamejs/fuzz/safe-mime.fuzz.js +27 -0
  241. package/lib/vendor/blamejs/fuzz/safe-mount-info.fuzz.js +33 -0
  242. package/lib/vendor/blamejs/fuzz/safe-sieve.fuzz.js +28 -0
  243. package/lib/vendor/blamejs/fuzz/safe-smtp.fuzz.js +64 -0
  244. package/lib/vendor/blamejs/fuzz/safe-url.fuzz.js +16 -0
  245. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/01-basic.txt +1 -0
  246. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/02-userinfo.txt +1 -0
  247. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/03-dangerous.txt +1 -0
  248. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/04-data.txt +1 -0
  249. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/05-ipv6.txt +1 -0
  250. package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/06-idn.txt +1 -0
  251. package/lib/vendor/blamejs/fuzz/safe-vcard.fuzz.js +16 -0
  252. package/lib/vendor/blamejs/index.js +678 -0
  253. package/lib/vendor/blamejs/keys/release-pqc-pub.json +7 -0
  254. package/lib/vendor/blamejs/lib/_test/crypto-fixtures.js +67 -0
  255. package/lib/vendor/blamejs/lib/a2a-tasks.js +598 -0
  256. package/lib/vendor/blamejs/lib/a2a.js +407 -0
  257. package/lib/vendor/blamejs/lib/acme.js +1448 -0
  258. package/lib/vendor/blamejs/lib/agent-audit.js +45 -0
  259. package/lib/vendor/blamejs/lib/agent-event-bus.js +382 -0
  260. package/lib/vendor/blamejs/lib/agent-idempotency.js +497 -0
  261. package/lib/vendor/blamejs/lib/agent-orchestrator.js +717 -0
  262. package/lib/vendor/blamejs/lib/agent-posture-chain.js +366 -0
  263. package/lib/vendor/blamejs/lib/agent-saga.js +321 -0
  264. package/lib/vendor/blamejs/lib/agent-snapshot.js +676 -0
  265. package/lib/vendor/blamejs/lib/agent-stream.js +269 -0
  266. package/lib/vendor/blamejs/lib/agent-tenant.js +632 -0
  267. package/lib/vendor/blamejs/lib/agent-trace.js +281 -0
  268. package/lib/vendor/blamejs/lib/ai-adverse-decision.js +184 -0
  269. package/lib/vendor/blamejs/lib/ai-content-detect.js +268 -0
  270. package/lib/vendor/blamejs/lib/ai-input.js +201 -0
  271. package/lib/vendor/blamejs/lib/ai-model-manifest.js +363 -0
  272. package/lib/vendor/blamejs/lib/ai-pref.js +340 -0
  273. package/lib/vendor/blamejs/lib/api-key.js +721 -0
  274. package/lib/vendor/blamejs/lib/api-snapshot.js +458 -0
  275. package/lib/vendor/blamejs/lib/app-shutdown.js +557 -0
  276. package/lib/vendor/blamejs/lib/app.js +365 -0
  277. package/lib/vendor/blamejs/lib/archive.js +547 -0
  278. package/lib/vendor/blamejs/lib/arg-parser.js +697 -0
  279. package/lib/vendor/blamejs/lib/argon2-builtin.js +173 -0
  280. package/lib/vendor/blamejs/lib/asn1-der.js +424 -0
  281. package/lib/vendor/blamejs/lib/asyncapi-bindings.js +160 -0
  282. package/lib/vendor/blamejs/lib/asyncapi-traits.js +143 -0
  283. package/lib/vendor/blamejs/lib/asyncapi.js +575 -0
  284. package/lib/vendor/blamejs/lib/atomic-file.js +1023 -0
  285. package/lib/vendor/blamejs/lib/audit-chain.js +266 -0
  286. package/lib/vendor/blamejs/lib/audit-daily-review.js +389 -0
  287. package/lib/vendor/blamejs/lib/audit-sign.js +751 -0
  288. package/lib/vendor/blamejs/lib/audit-tools.js +1113 -0
  289. package/lib/vendor/blamejs/lib/audit.js +1671 -0
  290. package/lib/vendor/blamejs/lib/auth/aal.js +169 -0
  291. package/lib/vendor/blamejs/lib/auth/access-lock.js +220 -0
  292. package/lib/vendor/blamejs/lib/auth/acr-vocabulary.js +265 -0
  293. package/lib/vendor/blamejs/lib/auth/ato-kill-switch.js +112 -0
  294. package/lib/vendor/blamejs/lib/auth/auth-time-tracker.js +111 -0
  295. package/lib/vendor/blamejs/lib/auth/bot-challenge.js +573 -0
  296. package/lib/vendor/blamejs/lib/auth/ciba.js +637 -0
  297. package/lib/vendor/blamejs/lib/auth/dpop.js +516 -0
  298. package/lib/vendor/blamejs/lib/auth/elevation-grant.js +306 -0
  299. package/lib/vendor/blamejs/lib/auth/fal.js +229 -0
  300. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +681 -0
  301. package/lib/vendor/blamejs/lib/auth/jwt-external.js +519 -0
  302. package/lib/vendor/blamejs/lib/auth/jwt.js +430 -0
  303. package/lib/vendor/blamejs/lib/auth/lockout.js +449 -0
  304. package/lib/vendor/blamejs/lib/auth/oauth.js +2141 -0
  305. package/lib/vendor/blamejs/lib/auth/oid4vci.js +657 -0
  306. package/lib/vendor/blamejs/lib/auth/oid4vp.js +531 -0
  307. package/lib/vendor/blamejs/lib/auth/openid-federation.js +600 -0
  308. package/lib/vendor/blamejs/lib/auth/passkey.js +676 -0
  309. package/lib/vendor/blamejs/lib/auth/password.js +693 -0
  310. package/lib/vendor/blamejs/lib/auth/saml.js +2109 -0
  311. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-disclosure.js +95 -0
  312. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +225 -0
  313. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +197 -0
  314. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +728 -0
  315. package/lib/vendor/blamejs/lib/auth/status-list.js +272 -0
  316. package/lib/vendor/blamejs/lib/auth/step-up-policy.js +335 -0
  317. package/lib/vendor/blamejs/lib/auth/step-up.js +454 -0
  318. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +505 -0
  319. package/lib/vendor/blamejs/lib/auth-header.js +148 -0
  320. package/lib/vendor/blamejs/lib/backup/bundle.js +265 -0
  321. package/lib/vendor/blamejs/lib/backup/crypto.js +176 -0
  322. package/lib/vendor/blamejs/lib/backup/index.js +1001 -0
  323. package/lib/vendor/blamejs/lib/backup/manifest.js +443 -0
  324. package/lib/vendor/blamejs/lib/boot-gates.js +174 -0
  325. package/lib/vendor/blamejs/lib/breach-deadline.js +272 -0
  326. package/lib/vendor/blamejs/lib/break-glass.js +1753 -0
  327. package/lib/vendor/blamejs/lib/budr.js +205 -0
  328. package/lib/vendor/blamejs/lib/bundler.js +461 -0
  329. package/lib/vendor/blamejs/lib/cache-redis.js +256 -0
  330. package/lib/vendor/blamejs/lib/cache-status.js +288 -0
  331. package/lib/vendor/blamejs/lib/cache.js +1331 -0
  332. package/lib/vendor/blamejs/lib/calendar.js +1240 -0
  333. package/lib/vendor/blamejs/lib/canonical-json.js +143 -0
  334. package/lib/vendor/blamejs/lib/cdn-cache-control.js +473 -0
  335. package/lib/vendor/blamejs/lib/cert.js +763 -0
  336. package/lib/vendor/blamejs/lib/chain-writer.js +259 -0
  337. package/lib/vendor/blamejs/lib/circuit-breaker.js +101 -0
  338. package/lib/vendor/blamejs/lib/cli-helpers.js +237 -0
  339. package/lib/vendor/blamejs/lib/cli.js +2328 -0
  340. package/lib/vendor/blamejs/lib/client-hints.js +318 -0
  341. package/lib/vendor/blamejs/lib/cloud-events.js +277 -0
  342. package/lib/vendor/blamejs/lib/cluster-provider-db.js +317 -0
  343. package/lib/vendor/blamejs/lib/cluster-storage.js +351 -0
  344. package/lib/vendor/blamejs/lib/cluster.js +1017 -0
  345. package/lib/vendor/blamejs/lib/cms-codec.js +826 -0
  346. package/lib/vendor/blamejs/lib/codepoint-class.js +262 -0
  347. package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +190 -0
  348. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +205 -0
  349. package/lib/vendor/blamejs/lib/compliance-ai-act-risk.js +189 -0
  350. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +200 -0
  351. package/lib/vendor/blamejs/lib/compliance-ai-act.js +821 -0
  352. package/lib/vendor/blamejs/lib/compliance-eaa.js +204 -0
  353. package/lib/vendor/blamejs/lib/compliance-sanctions-aliases.js +167 -0
  354. package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +206 -0
  355. package/lib/vendor/blamejs/lib/compliance-sanctions-fuzzy.js +297 -0
  356. package/lib/vendor/blamejs/lib/compliance-sanctions.js +569 -0
  357. package/lib/vendor/blamejs/lib/compliance.js +1558 -0
  358. package/lib/vendor/blamejs/lib/config-drift.js +426 -0
  359. package/lib/vendor/blamejs/lib/config.js +446 -0
  360. package/lib/vendor/blamejs/lib/consent.js +369 -0
  361. package/lib/vendor/blamejs/lib/constants.js +209 -0
  362. package/lib/vendor/blamejs/lib/content-credentials.js +704 -0
  363. package/lib/vendor/blamejs/lib/cookies.js +560 -0
  364. package/lib/vendor/blamejs/lib/cra-report.js +299 -0
  365. package/lib/vendor/blamejs/lib/credential-hash.js +394 -0
  366. package/lib/vendor/blamejs/lib/crypto-field.js +1017 -0
  367. package/lib/vendor/blamejs/lib/crypto-hpke-pq.js +187 -0
  368. package/lib/vendor/blamejs/lib/crypto-hpke.js +256 -0
  369. package/lib/vendor/blamejs/lib/crypto.js +1908 -0
  370. package/lib/vendor/blamejs/lib/csp.js +271 -0
  371. package/lib/vendor/blamejs/lib/csv.js +418 -0
  372. package/lib/vendor/blamejs/lib/daemon.js +481 -0
  373. package/lib/vendor/blamejs/lib/dark-patterns.js +488 -0
  374. package/lib/vendor/blamejs/lib/data-act.js +328 -0
  375. package/lib/vendor/blamejs/lib/db-collection.js +587 -0
  376. package/lib/vendor/blamejs/lib/db-declare-row-policy.js +267 -0
  377. package/lib/vendor/blamejs/lib/db-declare-view.js +420 -0
  378. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +333 -0
  379. package/lib/vendor/blamejs/lib/db-query.js +802 -0
  380. package/lib/vendor/blamejs/lib/db-role-context.js +50 -0
  381. package/lib/vendor/blamejs/lib/db-schema.js +322 -0
  382. package/lib/vendor/blamejs/lib/db.js +3111 -0
  383. package/lib/vendor/blamejs/lib/dbsc.js +299 -0
  384. package/lib/vendor/blamejs/lib/ddl-change-control.js +523 -0
  385. package/lib/vendor/blamejs/lib/deprecate.js +377 -0
  386. package/lib/vendor/blamejs/lib/dev.js +405 -0
  387. package/lib/vendor/blamejs/lib/dora.js +402 -0
  388. package/lib/vendor/blamejs/lib/dr-runbook.js +368 -0
  389. package/lib/vendor/blamejs/lib/dsr.js +1188 -0
  390. package/lib/vendor/blamejs/lib/dual-control.js +526 -0
  391. package/lib/vendor/blamejs/lib/early-hints.js +212 -0
  392. package/lib/vendor/blamejs/lib/error-page.js +420 -0
  393. package/lib/vendor/blamejs/lib/events.js +214 -0
  394. package/lib/vendor/blamejs/lib/external-db-migrate.js +659 -0
  395. package/lib/vendor/blamejs/lib/external-db.js +1877 -0
  396. package/lib/vendor/blamejs/lib/fapi2.js +394 -0
  397. package/lib/vendor/blamejs/lib/fda-21cfr11.js +395 -0
  398. package/lib/vendor/blamejs/lib/fdx.js +370 -0
  399. package/lib/vendor/blamejs/lib/fedcm.js +264 -0
  400. package/lib/vendor/blamejs/lib/file-type.js +360 -0
  401. package/lib/vendor/blamejs/lib/file-upload.js +1256 -0
  402. package/lib/vendor/blamejs/lib/flag-cache.js +136 -0
  403. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +135 -0
  404. package/lib/vendor/blamejs/lib/flag-providers.js +279 -0
  405. package/lib/vendor/blamejs/lib/flag-targeting.js +210 -0
  406. package/lib/vendor/blamejs/lib/flag.js +346 -0
  407. package/lib/vendor/blamejs/lib/forms.js +525 -0
  408. package/lib/vendor/blamejs/lib/framework-error.js +724 -0
  409. package/lib/vendor/blamejs/lib/framework-schema.js +845 -0
  410. package/lib/vendor/blamejs/lib/framework-sha1-hibp.js +34 -0
  411. package/lib/vendor/blamejs/lib/fsm.js +469 -0
  412. package/lib/vendor/blamejs/lib/gate-contract.js +1661 -0
  413. package/lib/vendor/blamejs/lib/gdpr-ropa.js +261 -0
  414. package/lib/vendor/blamejs/lib/graphql-federation.js +234 -0
  415. package/lib/vendor/blamejs/lib/guard-agent-registry.js +179 -0
  416. package/lib/vendor/blamejs/lib/guard-all.js +555 -0
  417. package/lib/vendor/blamejs/lib/guard-archive.js +901 -0
  418. package/lib/vendor/blamejs/lib/guard-auth.js +451 -0
  419. package/lib/vendor/blamejs/lib/guard-cidr.js +676 -0
  420. package/lib/vendor/blamejs/lib/guard-csv.js +1176 -0
  421. package/lib/vendor/blamejs/lib/guard-domain.js +814 -0
  422. package/lib/vendor/blamejs/lib/guard-dsn.js +382 -0
  423. package/lib/vendor/blamejs/lib/guard-email.js +951 -0
  424. package/lib/vendor/blamejs/lib/guard-envelope.js +294 -0
  425. package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +217 -0
  426. package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +150 -0
  427. package/lib/vendor/blamejs/lib/guard-filename.js +956 -0
  428. package/lib/vendor/blamejs/lib/guard-graphql.js +731 -0
  429. package/lib/vendor/blamejs/lib/guard-html-wcag-aria.js +164 -0
  430. package/lib/vendor/blamejs/lib/guard-html-wcag-forms.js +144 -0
  431. package/lib/vendor/blamejs/lib/guard-html-wcag-tables.js +154 -0
  432. package/lib/vendor/blamejs/lib/guard-html-wcag-tagwalk.js +44 -0
  433. package/lib/vendor/blamejs/lib/guard-html-wcag.js +470 -0
  434. package/lib/vendor/blamejs/lib/guard-html.js +1209 -0
  435. package/lib/vendor/blamejs/lib/guard-idempotency-key.js +151 -0
  436. package/lib/vendor/blamejs/lib/guard-image.js +584 -0
  437. package/lib/vendor/blamejs/lib/guard-imap-command.js +337 -0
  438. package/lib/vendor/blamejs/lib/guard-jmap.js +321 -0
  439. package/lib/vendor/blamejs/lib/guard-json.js +935 -0
  440. package/lib/vendor/blamejs/lib/guard-jsonpath.js +512 -0
  441. package/lib/vendor/blamejs/lib/guard-jwt.js +772 -0
  442. package/lib/vendor/blamejs/lib/guard-list-id.js +318 -0
  443. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +412 -0
  444. package/lib/vendor/blamejs/lib/guard-mail-compose.js +282 -0
  445. package/lib/vendor/blamejs/lib/guard-mail-move.js +202 -0
  446. package/lib/vendor/blamejs/lib/guard-mail-query.js +310 -0
  447. package/lib/vendor/blamejs/lib/guard-mail-reply.js +172 -0
  448. package/lib/vendor/blamejs/lib/guard-mail-sieve.js +207 -0
  449. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +566 -0
  450. package/lib/vendor/blamejs/lib/guard-markdown.js +768 -0
  451. package/lib/vendor/blamejs/lib/guard-message-id.js +267 -0
  452. package/lib/vendor/blamejs/lib/guard-mime.js +609 -0
  453. package/lib/vendor/blamejs/lib/guard-oauth.js +650 -0
  454. package/lib/vendor/blamejs/lib/guard-pdf.js +569 -0
  455. package/lib/vendor/blamejs/lib/guard-pop3-command.js +317 -0
  456. package/lib/vendor/blamejs/lib/guard-posture-chain.js +201 -0
  457. package/lib/vendor/blamejs/lib/guard-regex.js +632 -0
  458. package/lib/vendor/blamejs/lib/guard-saga-config.js +157 -0
  459. package/lib/vendor/blamejs/lib/guard-shell.js +522 -0
  460. package/lib/vendor/blamejs/lib/guard-smtp-command.js +594 -0
  461. package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +168 -0
  462. package/lib/vendor/blamejs/lib/guard-stream-args.js +166 -0
  463. package/lib/vendor/blamejs/lib/guard-svg.js +1163 -0
  464. package/lib/vendor/blamejs/lib/guard-template.js +490 -0
  465. package/lib/vendor/blamejs/lib/guard-tenant-id.js +138 -0
  466. package/lib/vendor/blamejs/lib/guard-time.js +586 -0
  467. package/lib/vendor/blamejs/lib/guard-trace-context.js +172 -0
  468. package/lib/vendor/blamejs/lib/guard-uuid.js +548 -0
  469. package/lib/vendor/blamejs/lib/guard-xml.js +666 -0
  470. package/lib/vendor/blamejs/lib/guard-yaml.js +726 -0
  471. package/lib/vendor/blamejs/lib/hal.js +125 -0
  472. package/lib/vendor/blamejs/lib/handlers.js +350 -0
  473. package/lib/vendor/blamejs/lib/honeytoken.js +168 -0
  474. package/lib/vendor/blamejs/lib/html-balance.js +347 -0
  475. package/lib/vendor/blamejs/lib/http-client-cache.js +923 -0
  476. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +519 -0
  477. package/lib/vendor/blamejs/lib/http-client.js +2152 -0
  478. package/lib/vendor/blamejs/lib/http-message-signature.js +589 -0
  479. package/lib/vendor/blamejs/lib/http2-teardown.js +34 -0
  480. package/lib/vendor/blamejs/lib/i18n-messageformat.js +398 -0
  481. package/lib/vendor/blamejs/lib/i18n.js +931 -0
  482. package/lib/vendor/blamejs/lib/iab-mspa.js +257 -0
  483. package/lib/vendor/blamejs/lib/iab-tcf.js +461 -0
  484. package/lib/vendor/blamejs/lib/importmap-integrity.js +90 -0
  485. package/lib/vendor/blamejs/lib/inbox.js +435 -0
  486. package/lib/vendor/blamejs/lib/incident-report.js +314 -0
  487. package/lib/vendor/blamejs/lib/ip-utils.js +102 -0
  488. package/lib/vendor/blamejs/lib/jobs.js +185 -0
  489. package/lib/vendor/blamejs/lib/jose-jwe-experimental.js +228 -0
  490. package/lib/vendor/blamejs/lib/jsonapi.js +230 -0
  491. package/lib/vendor/blamejs/lib/keychain.js +865 -0
  492. package/lib/vendor/blamejs/lib/lazy-require.js +48 -0
  493. package/lib/vendor/blamejs/lib/legal-hold.js +374 -0
  494. package/lib/vendor/blamejs/lib/local-db-thin.js +321 -0
  495. package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +369 -0
  496. package/lib/vendor/blamejs/lib/log-stream-local.js +146 -0
  497. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +410 -0
  498. package/lib/vendor/blamejs/lib/log-stream-otlp.js +286 -0
  499. package/lib/vendor/blamejs/lib/log-stream-syslog.js +310 -0
  500. package/lib/vendor/blamejs/lib/log-stream-webhook.js +199 -0
  501. package/lib/vendor/blamejs/lib/log-stream.js +584 -0
  502. package/lib/vendor/blamejs/lib/log.js +625 -0
  503. package/lib/vendor/blamejs/lib/lro.js +200 -0
  504. package/lib/vendor/blamejs/lib/mail-agent.js +786 -0
  505. package/lib/vendor/blamejs/lib/mail-arc-sign.js +417 -0
  506. package/lib/vendor/blamejs/lib/mail-arf.js +343 -0
  507. package/lib/vendor/blamejs/lib/mail-auth.js +2144 -0
  508. package/lib/vendor/blamejs/lib/mail-bimi.js +1047 -0
  509. package/lib/vendor/blamejs/lib/mail-bounce.js +955 -0
  510. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +1286 -0
  511. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +789 -0
  512. package/lib/vendor/blamejs/lib/mail-crypto.js +108 -0
  513. package/lib/vendor/blamejs/lib/mail-dav.js +1224 -0
  514. package/lib/vendor/blamejs/lib/mail-deploy.js +1119 -0
  515. package/lib/vendor/blamejs/lib/mail-dkim.js +1250 -0
  516. package/lib/vendor/blamejs/lib/mail-greylist.js +448 -0
  517. package/lib/vendor/blamejs/lib/mail-helo.js +473 -0
  518. package/lib/vendor/blamejs/lib/mail-journal.js +435 -0
  519. package/lib/vendor/blamejs/lib/mail-mdn.js +424 -0
  520. package/lib/vendor/blamejs/lib/mail-rbl.js +392 -0
  521. package/lib/vendor/blamejs/lib/mail-require-tls.js +198 -0
  522. package/lib/vendor/blamejs/lib/mail-scan.js +502 -0
  523. package/lib/vendor/blamejs/lib/mail-send-deliver.js +629 -0
  524. package/lib/vendor/blamejs/lib/mail-server-imap.js +1858 -0
  525. package/lib/vendor/blamejs/lib/mail-server-jmap.js +1565 -0
  526. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +908 -0
  527. package/lib/vendor/blamejs/lib/mail-server-mx.js +969 -0
  528. package/lib/vendor/blamejs/lib/mail-server-pop3.js +915 -0
  529. package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +315 -0
  530. package/lib/vendor/blamejs/lib/mail-server-registry.js +378 -0
  531. package/lib/vendor/blamejs/lib/mail-server-submission.js +1396 -0
  532. package/lib/vendor/blamejs/lib/mail-server-tls.js +445 -0
  533. package/lib/vendor/blamejs/lib/mail-sieve.js +557 -0
  534. package/lib/vendor/blamejs/lib/mail-spam-score.js +284 -0
  535. package/lib/vendor/blamejs/lib/mail-srs.js +248 -0
  536. package/lib/vendor/blamejs/lib/mail-store-fts.js +394 -0
  537. package/lib/vendor/blamejs/lib/mail-store.js +929 -0
  538. package/lib/vendor/blamejs/lib/mail-unsubscribe.js +400 -0
  539. package/lib/vendor/blamejs/lib/mail.js +1971 -0
  540. package/lib/vendor/blamejs/lib/mcp-tool-registry.js +473 -0
  541. package/lib/vendor/blamejs/lib/mcp.js +950 -0
  542. package/lib/vendor/blamejs/lib/metrics.js +1503 -0
  543. package/lib/vendor/blamejs/lib/middleware/age-gate.js +177 -0
  544. package/lib/vendor/blamejs/lib/middleware/ai-act-disclosure.js +203 -0
  545. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +981 -0
  546. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +137 -0
  547. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +171 -0
  548. package/lib/vendor/blamejs/lib/middleware/attach-user.js +220 -0
  549. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +293 -0
  550. package/lib/vendor/blamejs/lib/middleware/body-parser.js +1519 -0
  551. package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +183 -0
  552. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +217 -0
  553. package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +122 -0
  554. package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +355 -0
  555. package/lib/vendor/blamejs/lib/middleware/compression.js +489 -0
  556. package/lib/vendor/blamejs/lib/middleware/cookies.js +130 -0
  557. package/lib/vendor/blamejs/lib/middleware/cors.js +386 -0
  558. package/lib/vendor/blamejs/lib/middleware/csp-nonce.js +388 -0
  559. package/lib/vendor/blamejs/lib/middleware/csp-report.js +167 -0
  560. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +499 -0
  561. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +243 -0
  562. package/lib/vendor/blamejs/lib/middleware/db-role-for.js +304 -0
  563. package/lib/vendor/blamejs/lib/middleware/dpop.js +402 -0
  564. package/lib/vendor/blamejs/lib/middleware/error-handler.js +69 -0
  565. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +168 -0
  566. package/lib/vendor/blamejs/lib/middleware/flag-context.js +110 -0
  567. package/lib/vendor/blamejs/lib/middleware/gpc.js +153 -0
  568. package/lib/vendor/blamejs/lib/middleware/headers.js +242 -0
  569. package/lib/vendor/blamejs/lib/middleware/health.js +438 -0
  570. package/lib/vendor/blamejs/lib/middleware/host-allowlist.js +189 -0
  571. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +964 -0
  572. package/lib/vendor/blamejs/lib/middleware/index.js +183 -0
  573. package/lib/vendor/blamejs/lib/middleware/nel.js +214 -0
  574. package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +237 -0
  575. package/lib/vendor/blamejs/lib/middleware/no-cache.js +106 -0
  576. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +177 -0
  577. package/lib/vendor/blamejs/lib/middleware/protected-resource-metadata.js +277 -0
  578. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +556 -0
  579. package/lib/vendor/blamejs/lib/middleware/request-id.js +79 -0
  580. package/lib/vendor/blamejs/lib/middleware/request-log.js +205 -0
  581. package/lib/vendor/blamejs/lib/middleware/require-aal.js +138 -0
  582. package/lib/vendor/blamejs/lib/middleware/require-auth.js +144 -0
  583. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +290 -0
  584. package/lib/vendor/blamejs/lib/middleware/require-content-type.js +113 -0
  585. package/lib/vendor/blamejs/lib/middleware/require-methods.js +97 -0
  586. package/lib/vendor/blamejs/lib/middleware/require-mtls.js +212 -0
  587. package/lib/vendor/blamejs/lib/middleware/require-step-up.js +226 -0
  588. package/lib/vendor/blamejs/lib/middleware/scim-server.js +375 -0
  589. package/lib/vendor/blamejs/lib/middleware/security-headers.js +285 -0
  590. package/lib/vendor/blamejs/lib/middleware/security-txt.js +170 -0
  591. package/lib/vendor/blamejs/lib/middleware/span-http-server.js +280 -0
  592. package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +323 -0
  593. package/lib/vendor/blamejs/lib/middleware/sse.js +200 -0
  594. package/lib/vendor/blamejs/lib/middleware/trace-log-correlation.js +167 -0
  595. package/lib/vendor/blamejs/lib/middleware/trace-propagate.js +148 -0
  596. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +749 -0
  597. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +164 -0
  598. package/lib/vendor/blamejs/lib/migration-files.js +37 -0
  599. package/lib/vendor/blamejs/lib/migrations.js +385 -0
  600. package/lib/vendor/blamejs/lib/mime-parse.js +198 -0
  601. package/lib/vendor/blamejs/lib/money.js +699 -0
  602. package/lib/vendor/blamejs/lib/mtls-ca.js +572 -0
  603. package/lib/vendor/blamejs/lib/mtls-engine-default.js +501 -0
  604. package/lib/vendor/blamejs/lib/network-byte-quota.js +308 -0
  605. package/lib/vendor/blamejs/lib/network-dns-resolver.js +533 -0
  606. package/lib/vendor/blamejs/lib/network-dns.js +1930 -0
  607. package/lib/vendor/blamejs/lib/network-heartbeat.js +425 -0
  608. package/lib/vendor/blamejs/lib/network-nts.js +574 -0
  609. package/lib/vendor/blamejs/lib/network-proxy.js +265 -0
  610. package/lib/vendor/blamejs/lib/network-smtp-policy.js +836 -0
  611. package/lib/vendor/blamejs/lib/network-tls.js +3126 -0
  612. package/lib/vendor/blamejs/lib/network.js +346 -0
  613. package/lib/vendor/blamejs/lib/nis2-report.js +181 -0
  614. package/lib/vendor/blamejs/lib/nist-crosswalk.js +293 -0
  615. package/lib/vendor/blamejs/lib/nonce-store.js +177 -0
  616. package/lib/vendor/blamejs/lib/notify.js +683 -0
  617. package/lib/vendor/blamejs/lib/ntp-check.js +458 -0
  618. package/lib/vendor/blamejs/lib/numeric-bounds.js +111 -0
  619. package/lib/vendor/blamejs/lib/numeric-checks.js +40 -0
  620. package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +349 -0
  621. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +488 -0
  622. package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +351 -0
  623. package/lib/vendor/blamejs/lib/object-store/gcs.js +515 -0
  624. package/lib/vendor/blamejs/lib/object-store/http-put.js +153 -0
  625. package/lib/vendor/blamejs/lib/object-store/http-request.js +38 -0
  626. package/lib/vendor/blamejs/lib/object-store/index.js +197 -0
  627. package/lib/vendor/blamejs/lib/object-store/local.js +163 -0
  628. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +1133 -0
  629. package/lib/vendor/blamejs/lib/object-store/sigv4.js +957 -0
  630. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +420 -0
  631. package/lib/vendor/blamejs/lib/observability-tracer.js +395 -0
  632. package/lib/vendor/blamejs/lib/observability.js +720 -0
  633. package/lib/vendor/blamejs/lib/openapi-paths-builder.js +248 -0
  634. package/lib/vendor/blamejs/lib/openapi-schema-walk.js +192 -0
  635. package/lib/vendor/blamejs/lib/openapi-security.js +169 -0
  636. package/lib/vendor/blamejs/lib/openapi-yaml.js +154 -0
  637. package/lib/vendor/blamejs/lib/openapi.js +489 -0
  638. package/lib/vendor/blamejs/lib/otel-export.js +278 -0
  639. package/lib/vendor/blamejs/lib/outbox.js +547 -0
  640. package/lib/vendor/blamejs/lib/pagination.js +542 -0
  641. package/lib/vendor/blamejs/lib/parsers/index.js +91 -0
  642. package/lib/vendor/blamejs/lib/parsers/safe-env.js +642 -0
  643. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +293 -0
  644. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +784 -0
  645. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +390 -0
  646. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +1015 -0
  647. package/lib/vendor/blamejs/lib/permissions.js +793 -0
  648. package/lib/vendor/blamejs/lib/pick.js +105 -0
  649. package/lib/vendor/blamejs/lib/pqc-agent.js +351 -0
  650. package/lib/vendor/blamejs/lib/pqc-gate.js +279 -0
  651. package/lib/vendor/blamejs/lib/pqc-software.js +271 -0
  652. package/lib/vendor/blamejs/lib/problem-details.js +482 -0
  653. package/lib/vendor/blamejs/lib/process-spawn.js +196 -0
  654. package/lib/vendor/blamejs/lib/promise-pool.js +162 -0
  655. package/lib/vendor/blamejs/lib/protobuf-encoder.js +190 -0
  656. package/lib/vendor/blamejs/lib/protocol-dispatcher.js +161 -0
  657. package/lib/vendor/blamejs/lib/public-suffix.js +403 -0
  658. package/lib/vendor/blamejs/lib/pubsub-cluster.js +154 -0
  659. package/lib/vendor/blamejs/lib/pubsub-redis.js +167 -0
  660. package/lib/vendor/blamejs/lib/pubsub.js +463 -0
  661. package/lib/vendor/blamejs/lib/queue-local.js +476 -0
  662. package/lib/vendor/blamejs/lib/queue-redis.js +745 -0
  663. package/lib/vendor/blamejs/lib/queue-sqs.js +319 -0
  664. package/lib/vendor/blamejs/lib/queue.js +1016 -0
  665. package/lib/vendor/blamejs/lib/redact.js +1007 -0
  666. package/lib/vendor/blamejs/lib/redis-client.js +520 -0
  667. package/lib/vendor/blamejs/lib/render.js +285 -0
  668. package/lib/vendor/blamejs/lib/request-helpers.js +767 -0
  669. package/lib/vendor/blamejs/lib/resource-access-lock.js +116 -0
  670. package/lib/vendor/blamejs/lib/restore-bundle.js +340 -0
  671. package/lib/vendor/blamejs/lib/restore-rollback.js +365 -0
  672. package/lib/vendor/blamejs/lib/restore.js +409 -0
  673. package/lib/vendor/blamejs/lib/retention.js +640 -0
  674. package/lib/vendor/blamejs/lib/retry.js +523 -0
  675. package/lib/vendor/blamejs/lib/router.js +1289 -0
  676. package/lib/vendor/blamejs/lib/safe-async.js +1184 -0
  677. package/lib/vendor/blamejs/lib/safe-buffer.js +562 -0
  678. package/lib/vendor/blamejs/lib/safe-decompress.js +297 -0
  679. package/lib/vendor/blamejs/lib/safe-dns.js +665 -0
  680. package/lib/vendor/blamejs/lib/safe-ical.js +634 -0
  681. package/lib/vendor/blamejs/lib/safe-icap.js +502 -0
  682. package/lib/vendor/blamejs/lib/safe-json.js +946 -0
  683. package/lib/vendor/blamejs/lib/safe-jsonpath.js +285 -0
  684. package/lib/vendor/blamejs/lib/safe-mime.js +831 -0
  685. package/lib/vendor/blamejs/lib/safe-mount-info.js +306 -0
  686. package/lib/vendor/blamejs/lib/safe-path.js +254 -0
  687. package/lib/vendor/blamejs/lib/safe-redirect.js +106 -0
  688. package/lib/vendor/blamejs/lib/safe-schema.js +1810 -0
  689. package/lib/vendor/blamejs/lib/safe-sieve.js +684 -0
  690. package/lib/vendor/blamejs/lib/safe-smtp.js +185 -0
  691. package/lib/vendor/blamejs/lib/safe-sql.js +363 -0
  692. package/lib/vendor/blamejs/lib/safe-url.js +428 -0
  693. package/lib/vendor/blamejs/lib/safe-vcard.js +473 -0
  694. package/lib/vendor/blamejs/lib/sandbox-worker.js +135 -0
  695. package/lib/vendor/blamejs/lib/sandbox.js +358 -0
  696. package/lib/vendor/blamejs/lib/scheduler.js +827 -0
  697. package/lib/vendor/blamejs/lib/sd-notify.js +269 -0
  698. package/lib/vendor/blamejs/lib/sec-cyber.js +214 -0
  699. package/lib/vendor/blamejs/lib/security-assert.js +395 -0
  700. package/lib/vendor/blamejs/lib/seeders.js +620 -0
  701. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +309 -0
  702. package/lib/vendor/blamejs/lib/self-update.js +804 -0
  703. package/lib/vendor/blamejs/lib/server-timing.js +174 -0
  704. package/lib/vendor/blamejs/lib/session-device-binding.js +431 -0
  705. package/lib/vendor/blamejs/lib/session-stores.js +138 -0
  706. package/lib/vendor/blamejs/lib/session.js +1162 -0
  707. package/lib/vendor/blamejs/lib/slug.js +381 -0
  708. package/lib/vendor/blamejs/lib/sse.js +349 -0
  709. package/lib/vendor/blamejs/lib/ssrf-guard.js +792 -0
  710. package/lib/vendor/blamejs/lib/standard-webhooks.js +183 -0
  711. package/lib/vendor/blamejs/lib/static.js +1249 -0
  712. package/lib/vendor/blamejs/lib/storage.js +1272 -0
  713. package/lib/vendor/blamejs/lib/stream-throttle.js +235 -0
  714. package/lib/vendor/blamejs/lib/structured-fields.js +244 -0
  715. package/lib/vendor/blamejs/lib/subject.js +667 -0
  716. package/lib/vendor/blamejs/lib/tcpa-10dlc.js +175 -0
  717. package/lib/vendor/blamejs/lib/template.js +931 -0
  718. package/lib/vendor/blamejs/lib/tenant-quota.js +545 -0
  719. package/lib/vendor/blamejs/lib/test-harness.js +275 -0
  720. package/lib/vendor/blamejs/lib/testing.js +1185 -0
  721. package/lib/vendor/blamejs/lib/time.js +578 -0
  722. package/lib/vendor/blamejs/lib/tls-exporter.js +239 -0
  723. package/lib/vendor/blamejs/lib/totp.js +318 -0
  724. package/lib/vendor/blamejs/lib/tracing.js +546 -0
  725. package/lib/vendor/blamejs/lib/uuid.js +207 -0
  726. package/lib/vendor/blamejs/lib/validate-opts.js +381 -0
  727. package/lib/vendor/blamejs/lib/vault/index.js +638 -0
  728. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +311 -0
  729. package/lib/vendor/blamejs/lib/vault/passphrase-source.js +198 -0
  730. package/lib/vendor/blamejs/lib/vault/rotate.js +803 -0
  731. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +471 -0
  732. package/lib/vendor/blamejs/lib/vault/wrap.js +296 -0
  733. package/lib/vendor/blamejs/lib/vault-aad.js +259 -0
  734. package/lib/vendor/blamejs/lib/vendor/.vendor-data-pubkey +4 -0
  735. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +161 -0
  736. package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.data.js +68 -0
  737. package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.pem +33 -0
  738. package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.data.js +1325 -0
  739. package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.txt +10002 -0
  740. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +9 -0
  741. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +18 -0
  742. package/lib/vendor/blamejs/lib/vendor/pki.cjs +181 -0
  743. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +16382 -0
  744. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5881 -0
  745. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +328 -0
  746. package/lib/vendor/blamejs/lib/vendor/vendor-data-pubkey.js +16 -0
  747. package/lib/vendor/blamejs/lib/vendor-data.js +520 -0
  748. package/lib/vendor/blamejs/lib/vex.js +630 -0
  749. package/lib/vendor/blamejs/lib/watcher.js +608 -0
  750. package/lib/vendor/blamejs/lib/web-push-vapid.js +322 -0
  751. package/lib/vendor/blamejs/lib/webhook.js +977 -0
  752. package/lib/vendor/blamejs/lib/websocket-channels.js +327 -0
  753. package/lib/vendor/blamejs/lib/websocket.js +1561 -0
  754. package/lib/vendor/blamejs/lib/wiki-concepts.js +338 -0
  755. package/lib/vendor/blamejs/lib/worker-pool.js +464 -0
  756. package/lib/vendor/blamejs/lib/ws-client.js +978 -0
  757. package/lib/vendor/blamejs/lib/xml-c14n.js +506 -0
  758. package/lib/vendor/blamejs/memory/specs/node-26-map-getorinsert-migration.md +164 -0
  759. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +19 -0
  760. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/README.md +88 -0
  761. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/build.sh +26 -0
  762. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/project.yaml +28 -0
  763. package/lib/vendor/blamejs/package.json +81 -0
  764. package/lib/vendor/blamejs/release-notes/v0.0.x.json +310 -0
  765. package/lib/vendor/blamejs/release-notes/v0.1.x.json +1798 -0
  766. package/lib/vendor/blamejs/release-notes/v0.10.x.json +1288 -0
  767. package/lib/vendor/blamejs/release-notes/v0.11.x.json +2551 -0
  768. package/lib/vendor/blamejs/release-notes/v0.12.0.json +64 -0
  769. package/lib/vendor/blamejs/release-notes/v0.12.1.json +32 -0
  770. package/lib/vendor/blamejs/release-notes/v0.12.2.json +45 -0
  771. package/lib/vendor/blamejs/release-notes/v0.2.x.json +706 -0
  772. package/lib/vendor/blamejs/release-notes/v0.3.x.json +786 -0
  773. package/lib/vendor/blamejs/release-notes/v0.4.x.json +588 -0
  774. package/lib/vendor/blamejs/release-notes/v0.5.x.json +390 -0
  775. package/lib/vendor/blamejs/release-notes/v0.6.x.json +1947 -0
  776. package/lib/vendor/blamejs/release-notes/v0.7.x.json +3811 -0
  777. package/lib/vendor/blamejs/release-notes/v0.8.x.json +3318 -0
  778. package/lib/vendor/blamejs/release-notes/v0.9.x.json +2257 -0
  779. package/lib/vendor/blamejs/scripts/build-vendored-sbom.js +325 -0
  780. package/lib/vendor/blamejs/scripts/check-api-snapshot.js +62 -0
  781. package/lib/vendor/blamejs/scripts/check-changelog-extract.js +108 -0
  782. package/lib/vendor/blamejs/scripts/check-pack-against-gitignore.js +83 -0
  783. package/lib/vendor/blamejs/scripts/check-services.js +483 -0
  784. package/lib/vendor/blamejs/scripts/check-vendor-currency.js +349 -0
  785. package/lib/vendor/blamejs/scripts/consolidate-release-notes.js +216 -0
  786. package/lib/vendor/blamejs/scripts/gen-migrating.js +275 -0
  787. package/lib/vendor/blamejs/scripts/generate-changelog-entry.js +577 -0
  788. package/lib/vendor/blamejs/scripts/generate-release-signing-key.js +79 -0
  789. package/lib/vendor/blamejs/scripts/publish-dep-confusion-placeholder.sh +101 -0
  790. package/lib/vendor/blamejs/scripts/refresh-api-snapshot.js +31 -0
  791. package/lib/vendor/blamejs/scripts/refresh-vendor-manifest.js +132 -0
  792. package/lib/vendor/blamejs/scripts/release.js +652 -0
  793. package/lib/vendor/blamejs/scripts/sha3-digest.js +62 -0
  794. package/lib/vendor/blamejs/scripts/sign-release-artifact.js +92 -0
  795. package/lib/vendor/blamejs/scripts/test-integration.js +181 -0
  796. package/lib/vendor/blamejs/scripts/test-wiki-integration.js +126 -0
  797. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +77 -0
  798. package/lib/vendor/blamejs/scripts/vendor-data-gen.js +186 -0
  799. package/lib/vendor/blamejs/scripts/vendor-data-keygen.js +101 -0
  800. package/lib/vendor/blamejs/scripts/vendor-update.sh +278 -0
  801. package/lib/vendor/blamejs/test/00-primitives.js +19075 -0
  802. package/lib/vendor/blamejs/test/10-state.js +622 -0
  803. package/lib/vendor/blamejs/test/20-db.js +561 -0
  804. package/lib/vendor/blamejs/test/30-chain.js +2110 -0
  805. package/lib/vendor/blamejs/test/40-consumers.js +2453 -0
  806. package/lib/vendor/blamejs/test/50-integration.js +486 -0
  807. package/lib/vendor/blamejs/test/_helpers.js +10 -0
  808. package/lib/vendor/blamejs/test/_smoke-worker.js +69 -0
  809. package/lib/vendor/blamejs/test/fixtures/exploit-corpus/corpus.json +368 -0
  810. package/lib/vendor/blamejs/test/fixtures/http-client-stream-payload.txt +2 -0
  811. package/lib/vendor/blamejs/test/fixtures/worker-pool/echo.js +52 -0
  812. package/lib/vendor/blamejs/test/helpers/_codebase-shingle-worker.js +24 -0
  813. package/lib/vendor/blamejs/test/helpers/_codebase-shingle.js +203 -0
  814. package/lib/vendor/blamejs/test/helpers/_shape-match.js +513 -0
  815. package/lib/vendor/blamejs/test/helpers/check.js +36 -0
  816. package/lib/vendor/blamejs/test/helpers/cluster.js +70 -0
  817. package/lib/vendor/blamejs/test/helpers/db.js +143 -0
  818. package/lib/vendor/blamejs/test/helpers/drivers.js +207 -0
  819. package/lib/vendor/blamejs/test/helpers/fs-watch.js +101 -0
  820. package/lib/vendor/blamejs/test/helpers/http.js +14 -0
  821. package/lib/vendor/blamejs/test/helpers/index.js +93 -0
  822. package/lib/vendor/blamejs/test/helpers/json-round-trip.js +120 -0
  823. package/lib/vendor/blamejs/test/helpers/mocks.js +20 -0
  824. package/lib/vendor/blamejs/test/helpers/otel.js +13 -0
  825. package/lib/vendor/blamejs/test/helpers/services.js +380 -0
  826. package/lib/vendor/blamejs/test/helpers/wait.js +206 -0
  827. package/lib/vendor/blamejs/test/integration/cache.test.js +235 -0
  828. package/lib/vendor/blamejs/test/integration/cluster-provider-mysql.test.js +174 -0
  829. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +611 -0
  830. package/lib/vendor/blamejs/test/integration/http-client.test.js +129 -0
  831. package/lib/vendor/blamejs/test/integration/log-stream.test.js +219 -0
  832. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +181 -0
  833. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +152 -0
  834. package/lib/vendor/blamejs/test/integration/mail-smtp.test.js +161 -0
  835. package/lib/vendor/blamejs/test/integration/mtls-ca.test.js +289 -0
  836. package/lib/vendor/blamejs/test/integration/network-dns.test.js +123 -0
  837. package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +101 -0
  838. package/lib/vendor/blamejs/test/integration/ntp-check.test.js +89 -0
  839. package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +403 -0
  840. package/lib/vendor/blamejs/test/integration/pqc-pkcs8-forward-compat.test.js +271 -0
  841. package/lib/vendor/blamejs/test/integration/pubsub.test.js +137 -0
  842. package/lib/vendor/blamejs/test/integration/queue-redis.test.js +352 -0
  843. package/lib/vendor/blamejs/test/integration/redis-client-tls.test.js +96 -0
  844. package/lib/vendor/blamejs/test/integration/ssrf-guard.test.js +98 -0
  845. package/lib/vendor/blamejs/test/integration/websocket-permessage-deflate.test.js +261 -0
  846. package/lib/vendor/blamejs/test/integration/ws-client-roundtrip.test.js +230 -0
  847. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +211 -0
  848. package/lib/vendor/blamejs/test/layer-0-primitives/a2a.test.js +59 -0
  849. package/lib/vendor/blamejs/test/layer-0-primitives/access-lock.test.js +136 -0
  850. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +219 -0
  851. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +69 -0
  852. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +266 -0
  853. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +262 -0
  854. package/lib/vendor/blamejs/test/layer-0-primitives/agent-orchestrator.test.js +390 -0
  855. package/lib/vendor/blamejs/test/layer-0-primitives/agent-posture-chain.test.js +174 -0
  856. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +279 -0
  857. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +322 -0
  858. package/lib/vendor/blamejs/test/layer-0-primitives/agent-stream.test.js +227 -0
  859. package/lib/vendor/blamejs/test/layer-0-primitives/agent-tenant.test.js +302 -0
  860. package/lib/vendor/blamejs/test/layer-0-primitives/agent-trace.test.js +150 -0
  861. package/lib/vendor/blamejs/test/layer-0-primitives/ai-adverse-decision.test.js +44 -0
  862. package/lib/vendor/blamejs/test/layer-0-primitives/ai-content-detect.test.js +150 -0
  863. package/lib/vendor/blamejs/test/layer-0-primitives/ai-input.test.js +50 -0
  864. package/lib/vendor/blamejs/test/layer-0-primitives/ai-model-manifest.test.js +96 -0
  865. package/lib/vendor/blamejs/test/layer-0-primitives/ai-pref.test.js +76 -0
  866. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +1080 -0
  867. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +311 -0
  868. package/lib/vendor/blamejs/test/layer-0-primitives/archive-zip-stream.test.js +291 -0
  869. package/lib/vendor/blamejs/test/layer-0-primitives/archive.test.js +140 -0
  870. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +267 -0
  871. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +108 -0
  872. package/lib/vendor/blamejs/test/layer-0-primitives/asyncapi.test.js +929 -0
  873. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-conflict-path.test.js +80 -0
  874. package/lib/vendor/blamejs/test/layer-0-primitives/audit-cve-defensive.test.js +176 -0
  875. package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +132 -0
  876. package/lib/vendor/blamejs/test/layer-0-primitives/audit-export-cadf.test.js +97 -0
  877. package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +141 -0
  878. package/lib/vendor/blamejs/test/layer-0-primitives/audit-segregation.test.js +115 -0
  879. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-ml-dsa-65.test.js +163 -0
  880. package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +246 -0
  881. package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge-verifier.test.js +485 -0
  882. package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +331 -0
  883. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +352 -0
  884. package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +572 -0
  885. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password-audit.test.js +61 -0
  886. package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-bucket-ops.test.js +258 -0
  887. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +105 -0
  888. package/lib/vendor/blamejs/test/layer-0-primitives/backup-worker.test.js +34 -0
  889. package/lib/vendor/blamejs/test/layer-0-primitives/bearer-auth.test.js +107 -0
  890. package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-chunked-malformed.test.js +131 -0
  891. package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-smuggling.test.js +118 -0
  892. package/lib/vendor/blamejs/test/layer-0-primitives/boot-gates.test.js +85 -0
  893. package/lib/vendor/blamejs/test/layer-0-primitives/breach-deadline.test.js +38 -0
  894. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +861 -0
  895. package/lib/vendor/blamejs/test/layer-0-primitives/budr.test.js +55 -0
  896. package/lib/vendor/blamejs/test/layer-0-primitives/bundler-engine.test.js +209 -0
  897. package/lib/vendor/blamejs/test/layer-0-primitives/cache-status.test.js +129 -0
  898. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +871 -0
  899. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +891 -0
  900. package/lib/vendor/blamejs/test/layer-0-primitives/canonical-json-jcs.test.js +43 -0
  901. package/lib/vendor/blamejs/test/layer-0-primitives/cdn-cache-control.test.js +243 -0
  902. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +550 -0
  903. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +107 -0
  904. package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +147 -0
  905. package/lib/vendor/blamejs/test/layer-0-primitives/cli-audit-verify-chain.test.js +104 -0
  906. package/lib/vendor/blamejs/test/layer-0-primitives/cli-backup.test.js +135 -0
  907. package/lib/vendor/blamejs/test/layer-0-primitives/cli-config-drift.test.js +67 -0
  908. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +75 -0
  909. package/lib/vendor/blamejs/test/layer-0-primitives/cli-file-type.test.js +98 -0
  910. package/lib/vendor/blamejs/test/layer-0-primitives/cli-helpers.test.js +145 -0
  911. package/lib/vendor/blamejs/test/layer-0-primitives/cli-mtls.test.js +133 -0
  912. package/lib/vendor/blamejs/test/layer-0-primitives/cli-password.test.js +97 -0
  913. package/lib/vendor/blamejs/test/layer-0-primitives/cli-restore.test.js +160 -0
  914. package/lib/vendor/blamejs/test/layer-0-primitives/cli-retention.test.js +84 -0
  915. package/lib/vendor/blamejs/test/layer-0-primitives/cli-security.test.js +69 -0
  916. package/lib/vendor/blamejs/test/layer-0-primitives/cli-vault.test.js +142 -0
  917. package/lib/vendor/blamejs/test/layer-0-primitives/client-hints.test.js +133 -0
  918. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +237 -0
  919. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +9600 -0
  920. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +575 -0
  921. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-cascade.test.js +89 -0
  922. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-eaa.test.js +36 -0
  923. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +712 -0
  924. package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +278 -0
  925. package/lib/vendor/blamejs/test/layer-0-primitives/config-drift.test.js +97 -0
  926. package/lib/vendor/blamejs/test/layer-0-primitives/config.test.js +424 -0
  927. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +94 -0
  928. package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +357 -0
  929. package/lib/vendor/blamejs/test/layer-0-primitives/cra-report.test.js +31 -0
  930. package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +226 -0
  931. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +86 -0
  932. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-envelope.test.js +85 -0
  933. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +193 -0
  934. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +98 -0
  935. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke-pq.test.js +132 -0
  936. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke.test.js +155 -0
  937. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-mlkem768-x25519.test.js +129 -0
  938. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-namespace-hash.test.js +0 -0
  939. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-random-int.test.js +72 -0
  940. package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +96 -0
  941. package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +401 -0
  942. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +34 -0
  943. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +180 -0
  944. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +210 -0
  945. package/lib/vendor/blamejs/test/layer-0-primitives/daily-byte-quota.test.js +153 -0
  946. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +66 -0
  947. package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +74 -0
  948. package/lib/vendor/blamejs/test/layer-0-primitives/db-collection-extensions.test.js +226 -0
  949. package/lib/vendor/blamejs/test/layer-0-primitives/db-collection.test.js +136 -0
  950. package/lib/vendor/blamejs/test/layer-0-primitives/db-init-extensions.test.js +165 -0
  951. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +150 -0
  952. package/lib/vendor/blamejs/test/layer-0-primitives/db-query-extensions.test.js +191 -0
  953. package/lib/vendor/blamejs/test/layer-0-primitives/db-role-for.test.js +228 -0
  954. package/lib/vendor/blamejs/test/layer-0-primitives/db-vacuum.test.js +55 -0
  955. package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +89 -0
  956. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +184 -0
  957. package/lib/vendor/blamejs/test/layer-0-primitives/declare-row-policy.test.js +203 -0
  958. package/lib/vendor/blamejs/test/layer-0-primitives/declare-view.test.js +303 -0
  959. package/lib/vendor/blamejs/test/layer-0-primitives/dns-dnssec-algorithm.test.js +163 -0
  960. package/lib/vendor/blamejs/test/layer-0-primitives/dns-null-mx.test.js +39 -0
  961. package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +165 -0
  962. package/lib/vendor/blamejs/test/layer-0-primitives/dr-runbook.test.js +59 -0
  963. package/lib/vendor/blamejs/test/layer-0-primitives/dsr-state-rules.test.js +55 -0
  964. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +786 -0
  965. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +105 -0
  966. package/lib/vendor/blamejs/test/layer-0-primitives/early-hints.test.js +147 -0
  967. package/lib/vendor/blamejs/test/layer-0-primitives/events.test.js +105 -0
  968. package/lib/vendor/blamejs/test/layer-0-primitives/exploit-replay.test.js +243 -0
  969. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +181 -0
  970. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +190 -0
  971. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-routing.test.js +531 -0
  972. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +118 -0
  973. package/lib/vendor/blamejs/test/layer-0-primitives/fapi2.test.js +89 -0
  974. package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +156 -0
  975. package/lib/vendor/blamejs/test/layer-0-primitives/fdx.test.js +79 -0
  976. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +216 -0
  977. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +434 -0
  978. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +432 -0
  979. package/lib/vendor/blamejs/test/layer-0-primitives/file-type.test.js +81 -0
  980. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +887 -0
  981. package/lib/vendor/blamejs/test/layer-0-primitives/forensic-snapshot.test.js +51 -0
  982. package/lib/vendor/blamejs/test/layer-0-primitives/fsm.test.js +375 -0
  983. package/lib/vendor/blamejs/test/layer-0-primitives/gcs-bucket-ops.test.js +321 -0
  984. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +41 -0
  985. package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +32 -0
  986. package/lib/vendor/blamejs/test/layer-0-primitives/guard-agent-registry.test.js +87 -0
  987. package/lib/vendor/blamejs/test/layer-0-primitives/guard-all.test.js +328 -0
  988. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +339 -0
  989. package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +694 -0
  990. package/lib/vendor/blamejs/test/layer-0-primitives/guard-dsn.test.js +296 -0
  991. package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +234 -0
  992. package/lib/vendor/blamejs/test/layer-0-primitives/guard-envelope.test.js +192 -0
  993. package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-payload.test.js +89 -0
  994. package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-topic.test.js +71 -0
  995. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +386 -0
  996. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html-wcag.test.js +859 -0
  997. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +357 -0
  998. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +92 -0
  999. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  1000. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +174 -0
  1001. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +317 -0
  1002. package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-id.test.js +199 -0
  1003. package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-unsubscribe.test.js +214 -0
  1004. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-compose.test.js +111 -0
  1005. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-move.test.js +110 -0
  1006. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-query.test.js +112 -0
  1007. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-reply.test.js +86 -0
  1008. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-sieve.test.js +92 -0
  1009. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +301 -0
  1010. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +265 -0
  1011. package/lib/vendor/blamejs/test/layer-0-primitives/guard-message-id.test.js +0 -0
  1012. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +161 -0
  1013. package/lib/vendor/blamejs/test/layer-0-primitives/guard-posture-chain.test.js +100 -0
  1014. package/lib/vendor/blamejs/test/layer-0-primitives/guard-saga-config.test.js +79 -0
  1015. package/lib/vendor/blamejs/test/layer-0-primitives/guard-smtp-command.test.js +269 -0
  1016. package/lib/vendor/blamejs/test/layer-0-primitives/guard-snapshot-envelope.test.js +89 -0
  1017. package/lib/vendor/blamejs/test/layer-0-primitives/guard-stream-args.test.js +78 -0
  1018. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +288 -0
  1019. package/lib/vendor/blamejs/test/layer-0-primitives/guard-tenant-id.test.js +69 -0
  1020. package/lib/vendor/blamejs/test/layer-0-primitives/guard-trace-context.test.js +102 -0
  1021. package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +202 -0
  1022. package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +203 -0
  1023. package/lib/vendor/blamejs/test/layer-0-primitives/hal.test.js +51 -0
  1024. package/lib/vendor/blamejs/test/layer-0-primitives/honeytoken.test.js +50 -0
  1025. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +37 -0
  1026. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +692 -0
  1027. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +280 -0
  1028. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +225 -0
  1029. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +203 -0
  1030. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +991 -0
  1031. package/lib/vendor/blamejs/test/layer-0-primitives/iab-mspa.test.js +63 -0
  1032. package/lib/vendor/blamejs/test/layer-0-primitives/iab-tcf.test.js +73 -0
  1033. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +612 -0
  1034. package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +56 -0
  1035. package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +166 -0
  1036. package/lib/vendor/blamejs/test/layer-0-primitives/incident-report.test.js +29 -0
  1037. package/lib/vendor/blamejs/test/layer-0-primitives/jose-jwe-experimental.test.js +121 -0
  1038. package/lib/vendor/blamejs/test/layer-0-primitives/json-api.test.js +58 -0
  1039. package/lib/vendor/blamejs/test/layer-0-primitives/json-round-trip-helper.test.js +110 -0
  1040. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +159 -0
  1041. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  1042. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +118 -0
  1043. package/lib/vendor/blamejs/test/layer-0-primitives/local-db-thin.test.js +150 -0
  1044. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-cloudwatch.test.js +489 -0
  1045. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp-grpc.test.js +207 -0
  1046. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp.test.js +283 -0
  1047. package/lib/vendor/blamejs/test/layer-0-primitives/lro.test.js +65 -0
  1048. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +417 -0
  1049. package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +208 -0
  1050. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +910 -0
  1051. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +502 -0
  1052. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +680 -0
  1053. package/lib/vendor/blamejs/test/layer-0-primitives/mail-canspam.test.js +128 -0
  1054. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +149 -0
  1055. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +323 -0
  1056. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +297 -0
  1057. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +514 -0
  1058. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy-tlsrpt.test.js +369 -0
  1059. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +199 -0
  1060. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +627 -0
  1061. package/lib/vendor/blamejs/test/layer-0-primitives/mail-feedback-id.test.js +56 -0
  1062. package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +217 -0
  1063. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +283 -0
  1064. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +217 -0
  1065. package/lib/vendor/blamejs/test/layer-0-primitives/mail-mdn.test.js +334 -0
  1066. package/lib/vendor/blamejs/test/layer-0-primitives/mail-rbl.test.js +271 -0
  1067. package/lib/vendor/blamejs/test/layer-0-primitives/mail-require-tls.test.js +128 -0
  1068. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +215 -0
  1069. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +336 -0
  1070. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +732 -0
  1071. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +840 -0
  1072. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +130 -0
  1073. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +285 -0
  1074. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +74 -0
  1075. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +112 -0
  1076. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +229 -0
  1077. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +394 -0
  1078. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +147 -0
  1079. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +151 -0
  1080. package/lib/vendor/blamejs/test/layer-0-primitives/mail-spam-score.test.js +204 -0
  1081. package/lib/vendor/blamejs/test/layer-0-primitives/mail-srs.test.js +152 -0
  1082. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +279 -0
  1083. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +323 -0
  1084. package/lib/vendor/blamejs/test/layer-0-primitives/mail-unsubscribe.test.js +165 -0
  1085. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +439 -0
  1086. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-tool-registry.test.js +202 -0
  1087. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +155 -0
  1088. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-shadow-registry.test.js +112 -0
  1089. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +224 -0
  1090. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-compose-pipeline.test.js +278 -0
  1091. package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +376 -0
  1092. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-paths.test.js +89 -0
  1093. package/lib/vendor/blamejs/test/layer-0-primitives/nel.test.js +200 -0
  1094. package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +106 -0
  1095. package/lib/vendor/blamejs/test/layer-0-primitives/network-byte-quota.test.js +133 -0
  1096. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +372 -0
  1097. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +635 -0
  1098. package/lib/vendor/blamejs/test/layer-0-primitives/network-heartbeat-passive.test.js +128 -0
  1099. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-build-options.test.js +130 -0
  1100. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-ct-inclusion.test.js +179 -0
  1101. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +447 -0
  1102. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +369 -0
  1103. package/lib/vendor/blamejs/test/layer-0-primitives/nis2-report.test.js +21 -0
  1104. package/lib/vendor/blamejs/test/layer-0-primitives/nist-crosswalk.test.js +42 -0
  1105. package/lib/vendor/blamejs/test/layer-0-primitives/no-cache.test.js +98 -0
  1106. package/lib/vendor/blamejs/test/layer-0-primitives/notify.test.js +707 -0
  1107. package/lib/vendor/blamejs/test/layer-0-primitives/numeric-bounds.test.js +142 -0
  1108. package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +72 -0
  1109. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +597 -0
  1110. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +190 -0
  1111. package/lib/vendor/blamejs/test/layer-0-primitives/openapi.test.js +877 -0
  1112. package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +257 -0
  1113. package/lib/vendor/blamejs/test/layer-0-primitives/pagination.test.js +522 -0
  1114. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +216 -0
  1115. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +324 -0
  1116. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +546 -0
  1117. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +153 -0
  1118. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-software.test.js +94 -0
  1119. package/lib/vendor/blamejs/test/layer-0-primitives/problem-details.test.js +195 -0
  1120. package/lib/vendor/blamejs/test/layer-0-primitives/process-spawn.test.js +62 -0
  1121. package/lib/vendor/blamejs/test/layer-0-primitives/promise-pool.test.js +93 -0
  1122. package/lib/vendor/blamejs/test/layer-0-primitives/protected-resource-metadata.test.js +68 -0
  1123. package/lib/vendor/blamejs/test/layer-0-primitives/protobuf-encoder.test.js +138 -0
  1124. package/lib/vendor/blamejs/test/layer-0-primitives/protocol-dispatcher.test.js +174 -0
  1125. package/lib/vendor/blamejs/test/layer-0-primitives/public-suffix.test.js +197 -0
  1126. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +232 -0
  1127. package/lib/vendor/blamejs/test/layer-0-primitives/queue-dlq-extend-lease.test.js +178 -0
  1128. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +322 -0
  1129. package/lib/vendor/blamejs/test/layer-0-primitives/queue-priority-rate-progress.test.js +266 -0
  1130. package/lib/vendor/blamejs/test/layer-0-primitives/queue-sqs.test.js +300 -0
  1131. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-cluster.test.js +338 -0
  1132. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-registry.test.js +75 -0
  1133. package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +246 -0
  1134. package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +130 -0
  1135. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +335 -0
  1136. package/lib/vendor/blamejs/test/layer-0-primitives/request-log.test.js +170 -0
  1137. package/lib/vendor/blamejs/test/layer-0-primitives/require-auth-cache-control.test.js +93 -0
  1138. package/lib/vendor/blamejs/test/layer-0-primitives/require-mtls.test.js +34 -0
  1139. package/lib/vendor/blamejs/test/layer-0-primitives/resource-access-lock.test.js +52 -0
  1140. package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +67 -0
  1141. package/lib/vendor/blamejs/test/layer-0-primitives/retry.test.js +535 -0
  1142. package/lib/vendor/blamejs/test/layer-0-primitives/router-cross-origin-redirect.test.js +0 -0
  1143. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +128 -0
  1144. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +163 -0
  1145. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-parallel.test.js +170 -0
  1146. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +248 -0
  1147. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +451 -0
  1148. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +289 -0
  1149. package/lib/vendor/blamejs/test/layer-0-primitives/safe-icap.test.js +206 -0
  1150. package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +104 -0
  1151. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +339 -0
  1152. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mount-info.test.js +180 -0
  1153. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +78 -0
  1154. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sieve.test.js +123 -0
  1155. package/lib/vendor/blamejs/test/layer-0-primitives/safe-smtp.test.js +95 -0
  1156. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-idn-homograph.test.js +77 -0
  1157. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +257 -0
  1158. package/lib/vendor/blamejs/test/layer-0-primitives/saml-slo.test.js +249 -0
  1159. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +228 -0
  1160. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-exactly-once.test.js +238 -0
  1161. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +92 -0
  1162. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +700 -0
  1163. package/lib/vendor/blamejs/test/layer-0-primitives/sd-notify.test.js +67 -0
  1164. package/lib/vendor/blamejs/test/layer-0-primitives/sec-cyber.test.js +85 -0
  1165. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +107 -0
  1166. package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +175 -0
  1167. package/lib/vendor/blamejs/test/layer-0-primitives/seeders.test.js +816 -0
  1168. package/lib/vendor/blamejs/test/layer-0-primitives/self-update-standalone-verifier.test.js +168 -0
  1169. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +302 -0
  1170. package/lib/vendor/blamejs/test/layer-0-primitives/server-timing.test.js +93 -0
  1171. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +247 -0
  1172. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +295 -0
  1173. package/lib/vendor/blamejs/test/layer-0-primitives/shape-match.test.js +142 -0
  1174. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +952 -0
  1175. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-multipart-sse.test.js +441 -0
  1176. package/lib/vendor/blamejs/test/layer-0-primitives/slug.test.js +330 -0
  1177. package/lib/vendor/blamejs/test/layer-0-primitives/smtp-policy.test.js +233 -0
  1178. package/lib/vendor/blamejs/test/layer-0-primitives/source-comment-blocks.test.js +105 -0
  1179. package/lib/vendor/blamejs/test/layer-0-primitives/speculation-rules.test.js +319 -0
  1180. package/lib/vendor/blamejs/test/layer-0-primitives/sse.test.js +148 -0
  1181. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +283 -0
  1182. package/lib/vendor/blamejs/test/layer-0-primitives/standard-webhooks.test.js +67 -0
  1183. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +266 -0
  1184. package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +487 -0
  1185. package/lib/vendor/blamejs/test/layer-0-primitives/storage-chunk-scratch.test.js +0 -0
  1186. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +773 -0
  1187. package/lib/vendor/blamejs/test/layer-0-primitives/stream-throttle.test.js +173 -0
  1188. package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +180 -0
  1189. package/lib/vendor/blamejs/test/layer-0-primitives/tcpa-10dlc.test.js +66 -0
  1190. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +89 -0
  1191. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +571 -0
  1192. package/lib/vendor/blamejs/test/layer-0-primitives/test-harness.test.js +190 -0
  1193. package/lib/vendor/blamejs/test/layer-0-primitives/testing-request.test.js +119 -0
  1194. package/lib/vendor/blamejs/test/layer-0-primitives/testing.test.js +522 -0
  1195. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +151 -0
  1196. package/lib/vendor/blamejs/test/layer-0-primitives/tls-exporter.test.js +168 -0
  1197. package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-ct.test.js +275 -0
  1198. package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-verify.test.js +105 -0
  1199. package/lib/vendor/blamejs/test/layer-0-primitives/tls-pinset-drift.test.js +35 -0
  1200. package/lib/vendor/blamejs/test/layer-0-primitives/tls-preferred-groups.test.js +81 -0
  1201. package/lib/vendor/blamejs/test/layer-0-primitives/tracing.test.js +280 -0
  1202. package/lib/vendor/blamejs/test/layer-0-primitives/uuid.test.js +93 -0
  1203. package/lib/vendor/blamejs/test/layer-0-primitives/vault-aad.test.js +277 -0
  1204. package/lib/vendor/blamejs/test/layer-0-primitives/vault-seal-pem-file.test.js +252 -0
  1205. package/lib/vendor/blamejs/test/layer-0-primitives/vendor-data.test.js +149 -0
  1206. package/lib/vendor/blamejs/test/layer-0-primitives/vendor-manifest.test.js +92 -0
  1207. package/lib/vendor/blamejs/test/layer-0-primitives/vex.test.js +661 -0
  1208. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +308 -0
  1209. package/lib/vendor/blamejs/test/layer-0-primitives/web-push-vapid.test.js +144 -0
  1210. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +674 -0
  1211. package/lib/vendor/blamejs/test/layer-0-primitives/websocket-channels.test.js +360 -0
  1212. package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool.test.js +302 -0
  1213. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +349 -0
  1214. package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +717 -0
  1215. package/lib/vendor/blamejs/test/layer-5-integration/bundler-output.test.js +444 -0
  1216. package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +597 -0
  1217. package/lib/vendor/blamejs/test/layer-5-integration/security-chaos.test.js +308 -0
  1218. package/lib/vendor/blamejs/test/smoke.js +431 -0
  1219. package/lib/webhooks.js +305 -0
  1220. package/package.json +43 -0
@@ -0,0 +1,1753 @@
1
+ "use strict";
2
+ /**
3
+ * @module b.breakGlass
4
+ * @nav Identity
5
+ * @title Break Glass
6
+ *
7
+ * @intro
8
+ * Column-policy / row-enforcement step-up auth — PHI / PCI columns
9
+ * require a fresh second-factor grant + operator-supplied reason;
10
+ * every unseal is audited row-by-row.
11
+ *
12
+ * The operator declares which columns of which tables are
13
+ * GLASS-LOCKED. Reading a glass-locked column on any row requires
14
+ * the caller to (1) prove identity with a fresh second factor (TOTP
15
+ * or passkey), (2) supply a reason the audit chain captures, and
16
+ * (3) hold a short-lived scope-bounded grant. Each row read emits a
17
+ * per-row audit event; the default `maxRowsPerGrant: 1` enforces
18
+ * row-by-row auth so every PHI / PCI access is its own discrete
19
+ * authenticated event.
20
+ *
21
+ * Two crypto models ship side-by-side. Model A — the default — is a
22
+ * policy gate: glass-locked columns sit in the regular cryptoField
23
+ * sealed-row pipeline, and break-glass enforces the grant + audit
24
+ * contract on every read path. Model B (`cryptographic: true` on the
25
+ * policy) layers per-cell encryption on top: every (table, rowId,
26
+ * column) triple gets its own key derived `K_cell = SHAKE256(DEK ||
27
+ * table || rowId || column)`, AEAD-bound to AAD = `SHA3-512(table ||
28
+ * rowId || column)` so swapping ciphertexts between rows fails
29
+ * closed. Operators opt into Model B per-policy, then run
30
+ * `b.breakGlass.migrate(table)` to convert existing rows.
31
+ *
32
+ * Service-account bypass (`policy.serviceAccountBypass`) is opt-in
33
+ * per-table — both an apiKey-id allowlist and a required role must
34
+ * match. Admin tools (`listActiveAll`, `revokeAll`) cover security-
35
+ * team dashboards and incident-response offboarding.
36
+ *
37
+ * @card
38
+ * Column-policy / row-enforcement step-up auth — PHI / PCI columns require a fresh second-factor grant + operator-supplied reason; every unseal is audited row-by-row.
39
+ */
40
+ var audit = require("./audit");
41
+ var C = require("./constants");
42
+ var cache = require("./cache");
43
+ var clusterStorage = require("./cluster-storage");
44
+ var { generateBytes, generateToken, kdf, sha3Hash, encryptPacked, decryptPacked } = require("./crypto");
45
+ var cryptoField = require("./crypto-field");
46
+ var lazyRequire = require("./lazy-require");
47
+ var observability = require("./observability");
48
+ var requestHelpers = require("./request-helpers");
49
+ var safeAsync = require("./safe-async");
50
+ var safeJson = require("./safe-json");
51
+ var safeSql = require("./safe-sql");
52
+ var totp = require("./totp");
53
+ var validateOpts = require("./validate-opts");
54
+ var { defineClass } = require("./framework-error");
55
+
56
+ var vault = lazyRequire(function () { return require("./vault"); });
57
+
58
+ var lockout = lazyRequire(function () { return require("./auth/lockout"); });
59
+ var passkey = lazyRequire(function () { return require("./auth/passkey"); });
60
+
61
+ // Errors — all 14 codes documented in the spec. `permanent: true`
62
+ // means caller's input is bad (config-time / call-site reject);
63
+ // `permanent: false` means transient (factor failed, rate-limited)
64
+ // — caller may retry.
65
+ var BreakGlassError = defineClass("BreakGlassError", { alwaysPermanent: false });
66
+
67
+ // ---- Defaults (matched to operator-locked decisions) ----
68
+
69
+ // Symmetric byte counts: 32-byte cell-key (kdf output, XChaCha20 key
70
+ // length); 32-byte DEK (AEAD key); 16-byte grant-id randomness (128-bit
71
+ // uniqueness for cross-table grant lookups). All routed through C.BYTES
72
+ // so the framework's byte math has a single source of truth.
73
+ var CELL_KEY_BYTES = C.BYTES.bytes(32);
74
+ var DEK_BYTES = C.BYTES.bytes(32);
75
+ var GRANT_ID_BYTES = C.BYTES.bytes(16);
76
+
77
+ var DEFAULT_GRANT_TTL_MS = C.TIME.minutes(15);
78
+ var DEFAULT_MAX_ROWS = 1; // operator-locked: row-by-row auth
79
+ var DEFAULT_REASON_MIN_LEN = 12;
80
+ var DEFAULT_LOCKED_BEHAVIOR = "throw"; // or "redact"
81
+ var DEFAULT_AUDIT_REASON = "cleartext";
82
+ var ALLOWED_FACTORS = ["totp", "passkey"];
83
+ var ALLOWED_REASON_STORAGE = ["cleartext", "hmac", "both"];
84
+
85
+ // In-memory policy cache. Cluster-shared via the policies table; the
86
+ // cache short-circuits the DB roundtrip on the unsealRow hot path.
87
+ // Populated on first access per-table; invalidated on policy.set/delete.
88
+ var policyCache = new Map(); // table -> policy
89
+ var initialized = false;
90
+ // Framework-wide trustProxy setting (set at init). When true, the
91
+ // break-glass primitive consults X-Forwarded-For to populate the
92
+ // grant row's `ip` field — same trust boundary as middleware.
93
+ var _trustProxy = false;
94
+
95
+ // Factor lockout — wrap auth.lockout so a hostile actor brute-forcing
96
+ // TOTP codes against break-glass gets shut out after a few failures.
97
+ // Lazy-init on first grant attempt so init() doesn't require the
98
+ // cache primitive to be wired before break-glass loads.
99
+ var _factorLockout = null;
100
+ var _factorLockoutCache = null;
101
+ function _ensureFactorLockout() {
102
+ if (_factorLockout) return _factorLockout;
103
+ _factorLockoutCache = cache.create({
104
+ namespace: "breakglass.factor",
105
+ backend: "memory",
106
+ });
107
+ _factorLockout = lockout().create({
108
+ namespace: "breakglass.factor",
109
+ cache: _factorLockoutCache,
110
+ maxAttempts: 5,
111
+ windowMs: C.TIME.minutes(15),
112
+ audit: audit,
113
+ });
114
+ return _factorLockout;
115
+ }
116
+
117
+ // ---- Cryptographic mode (Model B) — per-cell encryption with context binding ----
118
+ //
119
+ // Each policy in cryptographic mode has a per-policy DEK (data
120
+ // encryption key) generated at first use. The DEK is vault-sealed so
121
+ // it survives restarts. At cell encrypt time, the framework derives a
122
+ // per-cell key K_cell = SHAKE256(DEK || table || rowId || column) so
123
+ // every (table, rowId, column) triple gets a unique key. Encryption
124
+ // uses XChaCha20-Poly1305 with AAD = SHA3-512(table || rowId || column)
125
+ // — the AEAD tag itself is bound to the encryption context, so a
126
+ // ciphertext from row A literally cannot be decrypted as row B even
127
+ // with the same DEK.
128
+ //
129
+ // THREAT MODEL HONESTY: this provides defense-in-depth via per-cell
130
+ // keys + encryption-context binding (cross-cell tampering / accidental
131
+ // row-swap fails closed). It does NOT defend against vault-key
132
+ // compromise alone — the DEK is still vault-recoverable. True
133
+ // second-factor cryptographic gating ships in v0.5.2 with passkey
134
+ // integration (the passkey private key lives on the YubiKey, not in
135
+ // the framework, so a vault leak alone can't unwrap).
136
+
137
+ // In-memory DEK cache. Keyed by table name. Cleared on _resetForTest.
138
+ var dekCache = new Map();
139
+
140
+ function _aadFor(table, rowId, column) {
141
+ return sha3Hash(table + "|" + String(rowId) + "|" + column);
142
+ }
143
+
144
+ function _kCell(dek, table, rowId, column) {
145
+ return kdf(Buffer.concat([
146
+ Buffer.isBuffer(dek) ? dek : Buffer.from(dek, "base64"),
147
+ Buffer.from("breakglass.cell|" + table + "|" + String(rowId) + "|" + column, "utf8"),
148
+ ]), CELL_KEY_BYTES);
149
+ }
150
+
151
+ async function _ensureDek(table) {
152
+ if (dekCache.has(table)) return dekCache.get(table);
153
+ // DEK is vault-sealed and stored in the policy row's `dekSealed`
154
+ // column. Generated lazily on first use of cryptographic-mode for
155
+ // the table. Cached in-memory after first read.
156
+ var rows = await clusterStorage.executeAll(
157
+ "SELECT dekSealed FROM _blamejs_break_glass_policies WHERE tableName = ?",
158
+ [table]
159
+ );
160
+ if (!rows || rows.length === 0) {
161
+ throw new BreakGlassError("breakglass/policy-not-set",
162
+ "_ensureDek: no policy for table '" + table + "'", true);
163
+ }
164
+ var sealed = rows[0].dekSealed;
165
+ var dek;
166
+ if (sealed) {
167
+ dek = Buffer.from(vault().unseal(sealed), "base64");
168
+ } else {
169
+ dek = generateBytes(DEK_BYTES);
170
+ var sealedDek = vault().seal(dek.toString("base64"));
171
+ await clusterStorage.execute(
172
+ "UPDATE _blamejs_break_glass_policies SET dekSealed = ? WHERE tableName = ?",
173
+ [sealedDek, table]
174
+ );
175
+ }
176
+ dekCache.set(table, dek);
177
+ return dek;
178
+ }
179
+
180
+ /**
181
+ * @primitive b.breakGlass.encryptCell
182
+ * @signature b.breakGlass.encryptCell(plaintext, ctx)
183
+ * @since 0.5.1
184
+ * @status stable
185
+ * @related b.breakGlass.decryptCell, b.breakGlass.migrate, b.breakGlass.policy.set
186
+ *
187
+ * Encrypt a single glass-locked cell value with encryption-context
188
+ * binding. Operators running a policy in `cryptographic: true` mode
189
+ * call this at write time INSTEAD of letting `cryptoField.sealRow`
190
+ * seal the column. The framework derives a per-cell key from the
191
+ * policy's vault-sealed DEK plus `(table, rowId, column)`, encrypts
192
+ * with XChaCha20-Poly1305, and sets AAD to `SHA3-512(table || rowId
193
+ * || column)` so a ciphertext literally cannot be decrypted under a
194
+ * different row identifier even with the same DEK.
195
+ *
196
+ * Returns a string of the form `bgcell:1:<base64>` ready to write
197
+ * back to the column. Throws `breakglass/policy-not-set` when the
198
+ * table has no policy or the policy isn't in cryptographic mode, and
199
+ * `breakglass/grant-column-mismatch` when the column isn't glass-
200
+ * locked on the policy.
201
+ *
202
+ * @example
203
+ * await b.breakGlass.policy.set("patients", {
204
+ * columns: ["ssn"],
205
+ * factors: ["totp"],
206
+ * cryptographic: true,
207
+ * });
208
+ * var sealed = await b.breakGlass.encryptCell("123-45-6789", {
209
+ * table: "patients",
210
+ * rowId: "patient-001",
211
+ * column: "ssn",
212
+ * });
213
+ * // → "bgcell:1:AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="
214
+ */
215
+ async function encryptCell(plaintext, ctx) {
216
+ _requireInit();
217
+ if (!ctx || typeof ctx !== "object" ||
218
+ typeof ctx.table !== "string" || ctx.table.length === 0 ||
219
+ ctx.rowId === undefined || ctx.rowId === null ||
220
+ typeof ctx.column !== "string" || ctx.column.length === 0) {
221
+ throw new BreakGlassError("breakglass/bad-cell-ctx",
222
+ "encryptCell: ctx must be { table, rowId, column }");
223
+ }
224
+ var policy = await policyGet(ctx.table);
225
+ if (!policy || !policy.cryptographic) {
226
+ throw new BreakGlassError("breakglass/policy-not-set",
227
+ "encryptCell: table '" + ctx.table + "' is not in cryptographic mode " +
228
+ "(set policy.cryptographic = true to opt in)", true);
229
+ }
230
+ if (policy.columns.indexOf(ctx.column) === -1) {
231
+ throw new BreakGlassError("breakglass/grant-column-mismatch",
232
+ "encryptCell: column '" + ctx.column + "' is not glass-locked on '" + ctx.table + "'", true);
233
+ }
234
+ var dek = await _ensureDek(ctx.table);
235
+ var kCell = _kCell(dek, ctx.table, ctx.rowId, ctx.column);
236
+ var aad = _aadFor(ctx.table, ctx.rowId, ctx.column);
237
+ var pt = Buffer.isBuffer(plaintext) ? plaintext : Buffer.from(String(plaintext), "utf8");
238
+ var packed = encryptPacked(pt, kCell, aad);
239
+ return "bgcell:1:" + packed.toString("base64");
240
+ }
241
+
242
+ /**
243
+ * @primitive b.breakGlass.decryptCell
244
+ * @signature b.breakGlass.decryptCell(ciphertext, ctx)
245
+ * @since 0.5.1
246
+ * @status stable
247
+ * @related b.breakGlass.encryptCell, b.breakGlass.unsealRow
248
+ *
249
+ * Decrypt a Model-B `bgcell:1:<base64>` cell value. Internal — the
250
+ * caller must already hold a valid grant covering the (table,
251
+ * column); operator-facing reads route through `b.breakGlass.unsealRow`
252
+ * which gates this call. The encryption context (`table, rowId,
253
+ * column`) is fed into BOTH the per-cell key derivation AND the AEAD
254
+ * AAD, so a caller passing the wrong `rowId` trying to swap
255
+ * ciphertexts between rows fails closed at the AEAD verify step.
256
+ *
257
+ * @example
258
+ * // unsealRow routes here automatically for cryptographic-mode
259
+ * // policies; calling decryptCell directly is rare and only for
260
+ * // operator tooling that's already enforced its own grant gate.
261
+ * var plaintext = await b.breakGlass.decryptCell(sealed, {
262
+ * table: "patients",
263
+ * rowId: "patient-001",
264
+ * column: "ssn",
265
+ * });
266
+ * // → "123-45-6789"
267
+ */
268
+ async function decryptCell(ciphertext, ctx) {
269
+ _requireInit();
270
+ if (typeof ciphertext !== "string" || ciphertext.indexOf("bgcell:1:") !== 0) {
271
+ throw new BreakGlassError("breakglass/bad-ciphertext",
272
+ "decryptCell: expected 'bgcell:1:<base64>' format");
273
+ }
274
+ if (!ctx || typeof ctx !== "object") {
275
+ throw new BreakGlassError("breakglass/bad-cell-ctx",
276
+ "decryptCell: ctx must be { table, rowId, column }");
277
+ }
278
+ var dek = await _ensureDek(ctx.table);
279
+ var kCell = _kCell(dek, ctx.table, ctx.rowId, ctx.column);
280
+ var aad = _aadFor(ctx.table, ctx.rowId, ctx.column);
281
+ var packed = Buffer.from(ciphertext.slice("bgcell:1:".length), "base64");
282
+ return decryptPacked(packed, kCell, aad).toString("utf8");
283
+ }
284
+
285
+ // ---- Migration support ----
286
+ //
287
+ // Operator runs `b.breakGlass.migrate(table, opts)` (or the CLI
288
+ // equivalent) to convert existing Model-A-sealed rows into Model B
289
+ // per-cell-encrypted form. Each row's glass-locked columns are
290
+ // unsealed via cryptoField, re-encrypted via encryptCell, and written
291
+ // back. The migration is idempotent — a row already in Model B form
292
+ // (column starts with "bgcell:") is skipped.
293
+
294
+ /**
295
+ * @primitive b.breakGlass.migrate
296
+ * @signature b.breakGlass.migrate(table, opts)
297
+ * @since 0.5.1
298
+ * @status stable
299
+ * @related b.breakGlass.encryptCell, b.breakGlass.policy.set
300
+ *
301
+ * One-shot migration that converts every existing row of a glass-
302
+ * locked table from Model A (cryptoField.sealRow only) into Model B
303
+ * per-cell ciphertext. Iterates via `_id`-keyset paging so memory
304
+ * stays bounded; rows already in Model B (column starts with
305
+ * `bgcell:`) are skipped, making the migration idempotent and safe
306
+ * to re-run after a partial failure.
307
+ *
308
+ * Emits a `breakglass.migrate` audit event on completion with totals
309
+ * and skipped counts. Refuses to run when the policy isn't in
310
+ * cryptographic mode — operator must `policy.set({ cryptographic:
311
+ * true })` first.
312
+ *
313
+ * @opts
314
+ * batchSize: number, // _id-keyset page size (default 100)
315
+ * callerOpts: object, // forwarded to audit actor resolution
316
+ *
317
+ * @example
318
+ * await b.breakGlass.policy.set("patients", {
319
+ * columns: ["ssn", "dob"],
320
+ * factors: ["totp"],
321
+ * cryptographic: true,
322
+ * });
323
+ * var summary = await b.breakGlass.migrate("patients", { batchSize: 250 });
324
+ * // → { table: "patients", totalRows: 1200, migratedRows: 1198, skippedRows: 2 }
325
+ */
326
+ async function migrate(table, opts) {
327
+ _requireInit();
328
+ opts = opts || {};
329
+ validateOpts(opts, ["batchSize", "callerOpts"], "breakGlass.migrate");
330
+ var policy = await policyGet(table);
331
+ if (!policy) {
332
+ throw new BreakGlassError("breakglass/policy-not-set",
333
+ "migrate: no policy for table '" + table + "'", true);
334
+ }
335
+ if (!policy.cryptographic) {
336
+ throw new BreakGlassError("breakglass/bad-policy",
337
+ "migrate: policy must be cryptographic: true to migrate to Model B", true);
338
+ }
339
+ var batchSize = opts.batchSize || 100;
340
+ var totalRows = 0;
341
+ var migratedRows = 0;
342
+ var skippedRows = 0;
343
+ var lastId = "";
344
+ // Iterate via _id-keyset paging so we don't load the whole table into memory.
345
+ while (true) {
346
+ // table is already validated as a safe identifier shape via
347
+ // _validatePolicySet — wrap in "..." per the framework's
348
+ // identifier-quoting convention.
349
+ var qTable = '"' + table + '"';
350
+ var rows = await clusterStorage.executeAll(
351
+ "SELECT * FROM " + qTable + " WHERE _id > ? ORDER BY _id ASC LIMIT ?",
352
+ [lastId, batchSize]
353
+ );
354
+ if (!rows || rows.length === 0) break;
355
+ for (var i = 0; i < rows.length; i++) {
356
+ totalRows++;
357
+ var row = rows[i];
358
+ var unsealed = cryptoField.unsealRow(table, row);
359
+ var anyChanged = false;
360
+ var update = { _id: row._id };
361
+ for (var c = 0; c < policy.columns.length; c++) {
362
+ var col = policy.columns[c];
363
+ var current = unsealed[col];
364
+ if (current == null) continue;
365
+ if (typeof current === "string" && current.indexOf("bgcell:") === 0) {
366
+ continue; // already migrated
367
+ }
368
+ var encrypted = await encryptCell(current, { table: table, rowId: row._id, column: col });
369
+ update[col] = encrypted;
370
+ anyChanged = true;
371
+ }
372
+ if (anyChanged) {
373
+ // Write Model B ciphertext directly — bypassing cryptoField so
374
+ // the cell ciphertext stays as a literal string, not double-sealed.
375
+ var setCols = Object.keys(update).filter(function (k) { return k !== "_id"; });
376
+ if (setCols.length > 0) {
377
+ // Column names came from the validated policy.columns —
378
+ // also wrap each in "..." for the same identifier-quoting
379
+ // convention.
380
+ var setSql = setCols.map(function (k) { return '"' + k + '" = ?'; }).join(", ");
381
+ var vals = setCols.map(function (k) { return update[k]; });
382
+ vals.push(row._id);
383
+ await clusterStorage.execute(
384
+ "UPDATE " + qTable + " SET " + setSql + " WHERE _id = ?",
385
+ vals
386
+ );
387
+ migratedRows++;
388
+ }
389
+ } else {
390
+ skippedRows++;
391
+ }
392
+ lastId = row._id;
393
+ }
394
+ if (rows.length < batchSize) break;
395
+ }
396
+ audit.safeEmit({
397
+ action: "breakglass.migrate",
398
+ outcome: "success",
399
+ actor: requestHelpers.resolveActorWithOverride(opts.callerOpts),
400
+ metadata: {
401
+ table: table,
402
+ totalRows: totalRows,
403
+ migratedRows: migratedRows,
404
+ skippedRows: skippedRows,
405
+ },
406
+ });
407
+ return { table: table, totalRows: totalRows, migratedRows: migratedRows, skippedRows: skippedRows };
408
+ }
409
+
410
+ // ---- init ----
411
+
412
+ /**
413
+ * @primitive b.breakGlass.init
414
+ * @signature b.breakGlass.init(opts)
415
+ * @since 0.5.0
416
+ * @status stable
417
+ * @related b.breakGlass.policy.set, b.breakGlass.grant
418
+ *
419
+ * One-shot boot wiring. Clears the in-memory policy cache, resets the
420
+ * factor-lockout counter, and records the framework-wide trustProxy
421
+ * boundary so subsequent `grant()` calls populate the grant row's `ip`
422
+ * field from `X-Forwarded-For` only when proxies are trusted. Operators
423
+ * call this once at boot, before any policy / grant / unseal call —
424
+ * every other primitive throws `breakglass/not-initialized` until init
425
+ * has run.
426
+ *
427
+ * @opts
428
+ * now: number, // testing-only override of Date.now (fixtures)
429
+ * trustProxy: boolean, // honor X-Forwarded-For when populating grant.ip (default false)
430
+ *
431
+ * @example
432
+ * b.breakGlass.init({ trustProxy: true });
433
+ * // → undefined (init returns nothing; throws on bad opts)
434
+ */
435
+ function init(opts) {
436
+ opts = opts || {};
437
+ validateOpts(opts, ["now", "trustProxy"], "breakGlass.init");
438
+ initialized = true;
439
+ policyCache.clear();
440
+ _factorLockout = null;
441
+ _trustProxy = opts.trustProxy === true || typeof opts.trustProxy === "number"
442
+ ? opts.trustProxy : false;
443
+ }
444
+
445
+ function _resetForTest() {
446
+ initialized = false;
447
+ policyCache.clear();
448
+ dekCache.clear();
449
+ if (_factorLockoutCache && typeof _factorLockoutCache.close === "function") {
450
+ try { _factorLockoutCache.close(); } catch (_e) { /* best-effort */ }
451
+ }
452
+ _factorLockout = null;
453
+ _factorLockoutCache = null;
454
+ _trustProxy = false;
455
+ }
456
+
457
+ function _requireInit() {
458
+ if (!initialized) {
459
+ throw new BreakGlassError("breakglass/not-initialized",
460
+ "b.breakGlass.init() must be called before use");
461
+ }
462
+ }
463
+
464
+ // ---- Policy CRUD ----
465
+
466
+ function _validatePolicySet(table, opts) {
467
+ if (typeof table !== "string" || table.length === 0) {
468
+ throw new BreakGlassError("breakglass/bad-policy",
469
+ "policy.set: table must be a non-empty string");
470
+ }
471
+ // Identifier safety: the table name flows raw into SQL via interpolation
472
+ // in migrate() / unsealRowAsService(). safeSql.validateIdentifier closes
473
+ // the shape so a malicious / mistyped name with embedded `"` or
474
+ // SQL-keyword shape can't break out of the wrapping quotes.
475
+ // allowReserved: true because every interpolation site quotes the
476
+ // identifier, so reserved-word names work via the SQL standard quoting
477
+ // rule.
478
+ try {
479
+ safeSql.validateIdentifier(table, { allowReserved: true });
480
+ } catch (e) {
481
+ throw new BreakGlassError("breakglass/bad-policy",
482
+ "policy.set: table '" + table + "' is not a valid SQL identifier: " +
483
+ ((e && e.message) || String(e)));
484
+ }
485
+ if (!opts || typeof opts !== "object") {
486
+ throw new BreakGlassError("breakglass/bad-policy",
487
+ "policy.set: opts is required");
488
+ }
489
+ validateOpts(opts, [
490
+ "columns", "factors", "cryptographic", "grantTtl", "maxRowsPerGrant",
491
+ "reasonRequired", "reasonMinLength", "pinIp", "sessionPin",
492
+ "onLockedAccess", "requireScope", "serviceAccountBypass",
493
+ "auditReasonStorage",
494
+ ], "breakglass.policy.set");
495
+ if (!Array.isArray(opts.columns) || opts.columns.length === 0) {
496
+ throw new BreakGlassError("breakglass/bad-policy",
497
+ "policy.set: columns must be a non-empty array");
498
+ }
499
+ for (var i = 0; i < opts.columns.length; i++) {
500
+ var colName = opts.columns[i];
501
+ if (typeof colName !== "string" || colName.length === 0) {
502
+ throw new BreakGlassError("breakglass/bad-policy",
503
+ "policy.set: columns[" + i + "] must be a non-empty string");
504
+ }
505
+ // Same identifier-shape check as the table — column names flow into
506
+ // the migrate() UPDATE statement as bare names.
507
+ try {
508
+ safeSql.validateIdentifier(colName, { allowReserved: true });
509
+ } catch (e) {
510
+ throw new BreakGlassError("breakglass/bad-policy",
511
+ "policy.set: columns[" + i + "]='" + colName + "' is not a valid SQL identifier: " +
512
+ ((e && e.message) || String(e)));
513
+ }
514
+ }
515
+ if (!Array.isArray(opts.factors) || opts.factors.length === 0) {
516
+ throw new BreakGlassError("breakglass/bad-policy",
517
+ "policy.set: factors must be a non-empty array");
518
+ }
519
+ for (var j = 0; j < opts.factors.length; j++) {
520
+ if (ALLOWED_FACTORS.indexOf(opts.factors[j]) === -1) {
521
+ throw new BreakGlassError("breakglass/bad-policy",
522
+ "policy.set: factors[" + j + "] '" + opts.factors[j] +
523
+ "' not in v0.5.0 allowed factors [" + ALLOWED_FACTORS.join(",") + "]" +
524
+ " (passkey lands in v0.5.2)");
525
+ }
526
+ }
527
+ // Model B (cryptographic mode) ships in v0.5.1. When enabled,
528
+ // glass-locked columns must be encrypted with `b.breakGlass.encryptCell`
529
+ // at write time (the framework can't auto-encrypt at write because
530
+ // policy-set may post-date existing data; operators run the migration
531
+ // CLI to convert existing rows). At unseal time, the row's
532
+ // glass-locked columns are decrypted via decryptCell with encryption
533
+ // context binding (table, rowId, column).
534
+ validateOpts.optionalBoolean(opts.cryptographic, "policy.set: cryptographic", BreakGlassError, "breakglass/bad-policy");
535
+ var grantTtl = opts.grantTtl != null ? opts.grantTtl : DEFAULT_GRANT_TTL_MS;
536
+ if (typeof grantTtl !== "number" || !isFinite(grantTtl) || grantTtl <= 0) {
537
+ throw new BreakGlassError("breakglass/bad-policy",
538
+ "policy.set: grantTtl must be a positive number of milliseconds");
539
+ }
540
+ var maxRows = opts.maxRowsPerGrant != null ? opts.maxRowsPerGrant : DEFAULT_MAX_ROWS;
541
+ if (!Number.isInteger(maxRows) || maxRows < 1) {
542
+ throw new BreakGlassError("breakglass/bad-policy",
543
+ "policy.set: maxRowsPerGrant must be a positive integer (default 1 — row-by-row auth)");
544
+ }
545
+ if (opts.onLockedAccess != null &&
546
+ opts.onLockedAccess !== "throw" && opts.onLockedAccess !== "redact") {
547
+ throw new BreakGlassError("breakglass/bad-policy",
548
+ "policy.set: onLockedAccess must be 'throw' or 'redact'");
549
+ }
550
+ if (opts.auditReasonStorage != null &&
551
+ ALLOWED_REASON_STORAGE.indexOf(opts.auditReasonStorage) === -1) {
552
+ throw new BreakGlassError("breakglass/bad-policy",
553
+ "policy.set: auditReasonStorage must be one of " + ALLOWED_REASON_STORAGE.join("/"));
554
+ }
555
+ // Service-account bypass: explicit opt-in per table. Operators
556
+ // declare the apiKey ids that may bypass + a required role; the
557
+ // framework requires BOTH to grant the bypass. Without this opt set,
558
+ // there is NO bypass path — every read of a glass-locked column
559
+ // requires a fresh grant.
560
+ var serviceAccountBypass = null;
561
+ if (opts.serviceAccountBypass != null && opts.serviceAccountBypass !== false) {
562
+ var sab = opts.serviceAccountBypass;
563
+ if (!sab || typeof sab !== "object") {
564
+ throw new BreakGlassError("breakglass/bad-policy",
565
+ "policy.set: serviceAccountBypass must be an object { enabled, apiKeyIds, requireRole }");
566
+ }
567
+ if (sab.enabled !== true) {
568
+ throw new BreakGlassError("breakglass/bad-policy",
569
+ "policy.set: serviceAccountBypass.enabled must be true (set serviceAccountBypass: false to disable)");
570
+ }
571
+ if (!Array.isArray(sab.apiKeyIds) || sab.apiKeyIds.length === 0) {
572
+ throw new BreakGlassError("breakglass/bad-policy",
573
+ "policy.set: serviceAccountBypass.apiKeyIds must be a non-empty array of apiKey ids");
574
+ }
575
+ if (typeof sab.requireRole !== "string" || sab.requireRole.length === 0) {
576
+ throw new BreakGlassError("breakglass/bad-policy",
577
+ "policy.set: serviceAccountBypass.requireRole must be a non-empty role / scope string");
578
+ }
579
+ serviceAccountBypass = {
580
+ enabled: true,
581
+ apiKeyIds: sab.apiKeyIds.slice(),
582
+ requireRole: sab.requireRole,
583
+ };
584
+ }
585
+ return {
586
+ cryptographic: opts.cryptographic === true,
587
+ grantTtl: grantTtl,
588
+ maxRowsPerGrant: maxRows,
589
+ reasonRequired: opts.reasonRequired !== false,
590
+ reasonMinLength: opts.reasonMinLength != null ? opts.reasonMinLength : DEFAULT_REASON_MIN_LEN,
591
+ pinIp: opts.pinIp !== false,
592
+ sessionPin: opts.sessionPin !== false,
593
+ onLockedAccess: opts.onLockedAccess || DEFAULT_LOCKED_BEHAVIOR,
594
+ requireScope: opts.requireScope != null ? opts.requireScope : null,
595
+ auditReasonStorage: opts.auditReasonStorage || DEFAULT_AUDIT_REASON,
596
+ serviceAccountBypass: serviceAccountBypass,
597
+ };
598
+ }
599
+
600
+ /**
601
+ * @primitive b.breakGlass.policy.set
602
+ * @signature b.breakGlass.policy.set(table, opts, callerOpts)
603
+ * @since 0.5.0
604
+ * @status stable
605
+ * @compliance hipaa, pci-dss, gdpr, soc2
606
+ * @related b.breakGlass.policy.get, b.breakGlass.policy.delete, b.breakGlass.grant
607
+ *
608
+ * Declare the column-policy that gates step-up auth on the named
609
+ * table. The listed columns become GLASS-LOCKED — every read of one of
610
+ * those columns on any row requires the caller to hold a fresh
611
+ * second-factor grant whose scope covers the column. Stored
612
+ * cluster-wide in `_blamejs_break_glass_policies` (sealed via
613
+ * cryptoField) so every node honors the same gate. Re-runs UPSERT;
614
+ * the policy cache flushes for the table.
615
+ *
616
+ * @opts
617
+ * columns: Array<string>, // glass-locked column names (required, ≥1)
618
+ * factors: Array<string>, // allowed second factors: "totp" / "passkey"
619
+ * cryptographic: boolean, // opt into Model B per-cell encryption (default false)
620
+ * grantTtl: number, // grant lifetime in ms (default 15 minutes)
621
+ * maxRowsPerGrant: number, // rows a grant may unseal (default 1 — row-by-row)
622
+ * reasonRequired: boolean, // require operator reason on grant (default true)
623
+ * reasonMinLength: number, // minimum reason length in chars (default 12)
624
+ * pinIp: boolean, // bind grant to issuing IP (default true)
625
+ * sessionPin: boolean, // bind grant to issuing session (default true)
626
+ * onLockedAccess: string, // "throw" | "redact" on unauthorized read (default "throw")
627
+ * requireScope: string, // actor scope required before grant mints (e.g. "phi:admin")
628
+ * serviceAccountBypass: object, // { enabled, apiKeyIds, requireRole } — opt-in machine bypass
629
+ * auditReasonStorage: string, // "cleartext" | "hmac" | "both" (default "cleartext")
630
+ *
631
+ * @example
632
+ * await b.breakGlass.policy.set("patients", {
633
+ * columns: ["ssn", "dob"],
634
+ * factors: ["totp"],
635
+ * grantTtl: 600000,
636
+ * maxRowsPerGrant: 1,
637
+ * requireScope: "phi:admin",
638
+ * });
639
+ * // → { applied: true, table: "patients" }
640
+ */
641
+ async function policySet(table, opts, callerOpts) {
642
+ _requireInit();
643
+ var validated = _validatePolicySet(table, opts);
644
+ var policyRow = {
645
+ tableName: table,
646
+ columnsJson: JSON.stringify(opts.columns),
647
+ factorsJson: JSON.stringify(opts.factors),
648
+ cryptographic: validated.cryptographic ? 1 : 0,
649
+ grantTtlMs: validated.grantTtl,
650
+ maxRowsPerGrant: validated.maxRowsPerGrant,
651
+ reasonRequired: validated.reasonRequired ? 1 : 0,
652
+ reasonMinLength: validated.reasonMinLength,
653
+ pinIp: validated.pinIp ? 1 : 0,
654
+ sessionPin: validated.sessionPin ? 1 : 0,
655
+ onLockedAccess: validated.onLockedAccess,
656
+ requireScope: validated.requireScope,
657
+ serviceAccountBypassJson: validated.serviceAccountBypass
658
+ ? JSON.stringify(validated.serviceAccountBypass)
659
+ : null,
660
+ auditReasonStorage: validated.auditReasonStorage,
661
+ updatedAt: Date.now(),
662
+ };
663
+ var sealed = cryptoField.sealRow("_blamejs_break_glass_policies", policyRow);
664
+ // UPSERT — both Postgres and SQLite support ON CONFLICT.
665
+ var keys = Object.keys(sealed);
666
+ var cols = keys.join(", ");
667
+ var qs = keys.map(function () { return "?"; }).join(", ");
668
+ var setSql = keys.filter(function (k) { return k !== "tableName"; })
669
+ .map(function (k) { return k + " = excluded." + k; }).join(", ");
670
+ var sql = "INSERT INTO _blamejs_break_glass_policies (" + cols + ") " +
671
+ "VALUES (" + qs + ") " +
672
+ "ON CONFLICT (tableName) DO UPDATE SET " + setSql;
673
+ await clusterStorage.execute(sql, keys.map(function (k) { return sealed[k]; }));
674
+ policyCache.delete(table);
675
+
676
+ audit.safeEmit({
677
+ action: "breakglass.policy.set",
678
+ outcome: "success",
679
+ actor: requestHelpers.resolveActorWithOverride(callerOpts),
680
+ metadata: {
681
+ table: table,
682
+ columnCount: opts.columns.length,
683
+ factors: opts.factors,
684
+ grantTtlMs: validated.grantTtl,
685
+ maxRowsPerGrant: validated.maxRowsPerGrant,
686
+ },
687
+ });
688
+ observability.event("breakglass.policy.set", { table: table });
689
+ return { applied: true, table: table };
690
+ }
691
+
692
+ /**
693
+ * @primitive b.breakGlass.policy.get
694
+ * @signature b.breakGlass.policy.get(table)
695
+ * @since 0.5.0
696
+ * @status stable
697
+ * @related b.breakGlass.policy.set, b.breakGlass.policy.list
698
+ *
699
+ * Read the current break-glass policy for `table` from the cluster-
700
+ * shared policies table, with an in-process cache that short-circuits
701
+ * the DB roundtrip on the unsealRow hot path. Returns `null` when the
702
+ * table has no policy declared (a non-glass-locked table). The cache
703
+ * invalidates on `policy.set` / `policy.delete`.
704
+ *
705
+ * @example
706
+ * var policy = await b.breakGlass.policy.get("patients");
707
+ * // → { table: "patients", columns: ["ssn", "dob"], factors: ["totp"], ... }
708
+ *
709
+ * var none = await b.breakGlass.policy.get("posts");
710
+ * // → null
711
+ */
712
+ async function policyGet(table) {
713
+ _requireInit();
714
+ if (typeof table !== "string" || table.length === 0) return null;
715
+ if (policyCache.has(table)) return policyCache.get(table);
716
+ var rows = await clusterStorage.executeAll(
717
+ "SELECT * FROM _blamejs_break_glass_policies WHERE tableName = ?",
718
+ [table]
719
+ );
720
+ if (!rows || rows.length === 0) {
721
+ policyCache.set(table, null);
722
+ return null;
723
+ }
724
+ var unsealed = cryptoField.unsealRow("_blamejs_break_glass_policies", rows[0]);
725
+ var policy = {
726
+ table: unsealed.tableName,
727
+ columns: safeJson.parse(unsealed.columnsJson, { maxBytes: C.BYTES.kib(64) }),
728
+ factors: safeJson.parse(unsealed.factorsJson, { maxBytes: C.BYTES.kib(8) }),
729
+ cryptographic: unsealed.cryptographic === 1,
730
+ grantTtl: Number(unsealed.grantTtlMs),
731
+ maxRowsPerGrant: Number(unsealed.maxRowsPerGrant),
732
+ reasonRequired: unsealed.reasonRequired === 1,
733
+ reasonMinLength: Number(unsealed.reasonMinLength),
734
+ pinIp: unsealed.pinIp === 1,
735
+ sessionPin: unsealed.sessionPin === 1,
736
+ onLockedAccess: unsealed.onLockedAccess,
737
+ requireScope: unsealed.requireScope,
738
+ serviceAccountBypass: unsealed.serviceAccountBypassJson
739
+ ? safeJson.parse(unsealed.serviceAccountBypassJson, { maxBytes: C.BYTES.kib(8) })
740
+ : null,
741
+ auditReasonStorage: unsealed.auditReasonStorage,
742
+ updatedAt: Number(unsealed.updatedAt),
743
+ };
744
+ policyCache.set(table, policy);
745
+ return policy;
746
+ }
747
+
748
+ /**
749
+ * @primitive b.breakGlass.policy.list
750
+ * @signature b.breakGlass.policy.list()
751
+ * @since 0.5.0
752
+ * @status stable
753
+ * @related b.breakGlass.policy.get, b.breakGlass.policy.set
754
+ *
755
+ * Enumerate every glass-locked table the cluster knows about. Used by
756
+ * compliance dashboards (which tables hold PHI / PCI?) and migration
757
+ * tooling that needs to walk the full set. Returns hydrated policy
758
+ * objects in `tableName` order — no abbreviated row form.
759
+ *
760
+ * @example
761
+ * var policies = await b.breakGlass.policy.list();
762
+ * // → [{ table: "patients", columns: ["ssn", "dob"], ... }, { table: "cards", ... }]
763
+ * policies.length;
764
+ * // → 2
765
+ */
766
+ async function policyList() {
767
+ _requireInit();
768
+ var rows = await clusterStorage.executeAll(
769
+ "SELECT tableName FROM _blamejs_break_glass_policies ORDER BY tableName"
770
+ );
771
+ var out = [];
772
+ for (var i = 0; i < (rows || []).length; i++) {
773
+ var p = await policyGet(rows[i].tableName);
774
+ if (p) out.push(p);
775
+ }
776
+ return out;
777
+ }
778
+
779
+ /**
780
+ * @primitive b.breakGlass.policy.delete
781
+ * @signature b.breakGlass.policy.delete(table, callerOpts)
782
+ * @since 0.5.0
783
+ * @status stable
784
+ * @related b.breakGlass.policy.set
785
+ *
786
+ * Remove the break-glass policy for `table`. Subsequent reads of the
787
+ * previously glass-locked columns no longer require a grant — operators
788
+ * call this only when a column genuinely stops being PHI / PCI (rare;
789
+ * almost always the operator wants `policy.set` with a revised column
790
+ * list instead). Emits a `breakglass.policy.delete` audit event.
791
+ *
792
+ * @example
793
+ * await b.breakGlass.policy.delete("legacy_patients");
794
+ * // → { deleted: true, table: "legacy_patients" }
795
+ */
796
+ async function policyDelete(table, callerOpts) {
797
+ _requireInit();
798
+ if (typeof table !== "string" || table.length === 0) {
799
+ throw new BreakGlassError("breakglass/bad-policy",
800
+ "policy.delete: table must be a non-empty string");
801
+ }
802
+ await clusterStorage.execute(
803
+ "DELETE FROM _blamejs_break_glass_policies WHERE tableName = ?",
804
+ [table]
805
+ );
806
+ policyCache.delete(table);
807
+ audit.safeEmit({
808
+ action: "breakglass.policy.delete",
809
+ outcome: "success",
810
+ actor: requestHelpers.resolveActorWithOverride(callerOpts),
811
+ metadata: { table: table },
812
+ });
813
+ return { deleted: true, table: table };
814
+ }
815
+
816
+ // ---- Grant issuance ----
817
+
818
+ function _verifyTotpFactor(factor) {
819
+ if (!factor || typeof factor !== "object") return { ok: false };
820
+ if (typeof factor.secret !== "string" || factor.secret.length === 0) return { ok: false };
821
+ if (typeof factor.code !== "string" || factor.code.length === 0) return { ok: false };
822
+ var verified = totp.verify(factor.secret, factor.code);
823
+ return { ok: verified !== false, step: verified };
824
+ }
825
+
826
+ // Passkey factor — operator presents a WebAuthn assertion plus the
827
+ // challenge/origin/RPID + the previously-enrolled credential record.
828
+ // Phishing-resistant; the private key lives on the YubiKey, not in
829
+ // the framework's vault. v0.5.2 uses passkey for identity verification
830
+ // to gate grant issuance; PRF-derived per-policy DEK material (which
831
+ // would give true vault-key-alone-doesn't-decrypt defense) is a
832
+ // follow-up.
833
+ async function _verifyPasskeyFactor(factor) {
834
+ if (!factor || typeof factor !== "object") return { ok: false };
835
+ if (!factor.response || !factor.expectedChallenge ||
836
+ !factor.expectedOrigin || !factor.expectedRPID || !factor.credential) {
837
+ return { ok: false };
838
+ }
839
+ try {
840
+ var result = await passkey().verifyAuthentication({
841
+ response: factor.response,
842
+ expectedChallenge: factor.expectedChallenge,
843
+ expectedOrigin: factor.expectedOrigin,
844
+ expectedRPID: factor.expectedRPID,
845
+ credential: factor.credential,
846
+ requireUserVerification: factor.requireUserVerification !== false,
847
+ });
848
+ return { ok: result && result.verified === true };
849
+ } catch (_e) {
850
+ return { ok: false };
851
+ }
852
+ }
853
+
854
+ /**
855
+ * @primitive b.breakGlass.grant
856
+ * @signature b.breakGlass.grant(opts)
857
+ * @since 0.5.0
858
+ * @status stable
859
+ * @compliance hipaa, pci-dss, soc2
860
+ * @related b.breakGlass.unsealRow, b.breakGlass.revoke, b.breakGlass.policy.set
861
+ *
862
+ * Mint a short-lived, scope-bounded break-glass grant. The framework
863
+ * verifies the operator's second factor (TOTP code or passkey
864
+ * assertion), records the operator-supplied reason into the audit
865
+ * chain, and issues a grant whose scope covers the named columns of
866
+ * the named table for `policy.grantTtl` ms or `policy.maxRowsPerGrant`
867
+ * row reads — whichever ends first. Failures emit a denied-grant audit
868
+ * row; repeated factor failures trigger the lockout primitive.
869
+ *
870
+ * @opts
871
+ * req: object, // the active request (carries actor identity, ip, session)
872
+ * table: string, // glass-locked table the grant scopes to
873
+ * columns: Array<string>, // optional subset of policy.columns (default = full policy)
874
+ * reason: string, // operator-supplied reason (length-gated by policy.reasonMinLength)
875
+ * factor: object, // { type: "totp", secret, code } or { type: "passkey", response, ... }
876
+ *
877
+ * @example
878
+ * var handle = await b.breakGlass.grant({
879
+ * req: req,
880
+ * table: "patients",
881
+ * columns: ["ssn"],
882
+ * reason: "ER admit verifying identity for patient-001",
883
+ * factor: { type: "totp", secret: req.user.totpSecret, code: "123456" },
884
+ * });
885
+ * // → { id: "bg-...", expiresAt: 1735000000000, rowsRemaining: 1, scopeTable: "patients", scopeColumns: ["ssn"] }
886
+ */
887
+ async function grant(opts) {
888
+ _requireInit();
889
+ if (!opts || typeof opts !== "object") {
890
+ throw new BreakGlassError("breakglass/bad-grant-opts",
891
+ "grant: opts is required");
892
+ }
893
+ validateOpts(opts, ["req", "table", "columns", "reason", "factor"], "breakGlass.grant");
894
+
895
+ var table = opts.table;
896
+ var policy = await policyGet(table);
897
+ if (!policy) {
898
+ throw new BreakGlassError("breakglass/policy-not-set",
899
+ "no break-glass policy is configured for table '" + table + "'", true);
900
+ }
901
+
902
+ // Reason validation
903
+ var reason = typeof opts.reason === "string" ? opts.reason : "";
904
+ if (policy.reasonRequired && reason.length === 0) {
905
+ throw new BreakGlassError("breakglass/missing-reason",
906
+ "grant: reason is required for table '" + table + "'", true);
907
+ }
908
+ if (policy.reasonRequired && reason.length < policy.reasonMinLength) {
909
+ throw new BreakGlassError("breakglass/short-reason",
910
+ "grant: reason must be at least " + policy.reasonMinLength + " characters", true);
911
+ }
912
+
913
+ // Column scoping
914
+ var requestedColumns = Array.isArray(opts.columns) && opts.columns.length > 0
915
+ ? opts.columns.slice()
916
+ : policy.columns.slice();
917
+ for (var i = 0; i < requestedColumns.length; i++) {
918
+ if (policy.columns.indexOf(requestedColumns[i]) === -1) {
919
+ throw new BreakGlassError("breakglass/grant-column-mismatch",
920
+ "grant: requested column '" + requestedColumns[i] +
921
+ "' is not glass-locked on table '" + table + "'", true);
922
+ }
923
+ }
924
+
925
+ // Actor identity
926
+ var actor = requestHelpers.extractActorContext(opts.req);
927
+ var actorId = actor.userId || (opts.req && opts.req.apiKey && opts.req.apiKey.id) || null;
928
+ if (!actorId) {
929
+ throw new BreakGlassError("breakglass/unauthorized",
930
+ "grant: no authenticated actor on request (req.user.id / req.apiKey.id required)", true);
931
+ }
932
+
933
+ // Scope-gate enforcement — when the policy declares requireScope,
934
+ // the actor must carry the named scope (or matching wildcard via
935
+ // b.permissions.match) before the framework will mint a grant.
936
+ // Without this, every TOTP-passing actor could glass-unseal PHI
937
+ // even when the operator explicitly declared `requireScope:
938
+ // "phi:admin"`.
939
+ if (policy.requireScope) {
940
+ var actorScopes = (opts.req && opts.req.user && Array.isArray(opts.req.user.scopes))
941
+ ? opts.req.user.scopes
942
+ : ((opts.req && opts.req.apiKey && Array.isArray(opts.req.apiKey.scopes))
943
+ ? opts.req.apiKey.scopes
944
+ : []);
945
+ var scopeOk = false;
946
+ for (var sci = 0; sci < actorScopes.length; sci += 1) {
947
+ if (actorScopes[sci] === policy.requireScope) { scopeOk = true; break; }
948
+ // Wildcard support: "phi:*" matches "phi:admin" and "phi:read".
949
+ if (typeof actorScopes[sci] === "string" &&
950
+ actorScopes[sci].length > 0 &&
951
+ actorScopes[sci].charAt(actorScopes[sci].length - 1) === "*") {
952
+ var prefix = actorScopes[sci].slice(0, -1);
953
+ if (typeof policy.requireScope === "string" &&
954
+ policy.requireScope.indexOf(prefix) === 0) {
955
+ scopeOk = true; break;
956
+ }
957
+ }
958
+ }
959
+ if (!scopeOk) {
960
+ audit.safeEmit({
961
+ action: "breakglass.grant.requested",
962
+ outcome: "denied",
963
+ actor: actor,
964
+ reason: "missing-scope",
965
+ metadata: { table: table, requireScope: policy.requireScope },
966
+ });
967
+ throw new BreakGlassError("breakglass/missing-scope",
968
+ "grant: actor does not carry required scope '" + policy.requireScope + "'", true);
969
+ }
970
+ }
971
+
972
+ // Factor verification + lockout
973
+ var factorType = opts.factor && opts.factor.type;
974
+ if (!factorType || policy.factors.indexOf(factorType) === -1) {
975
+ throw new BreakGlassError("breakglass/bad-factor",
976
+ "grant: factor.type must be one of [" + policy.factors.join(",") + "]");
977
+ }
978
+ var fl = _ensureFactorLockout();
979
+ var lockKey = actorId;
980
+ var locked = await fl.check(lockKey);
981
+ if (locked && locked.locked) {
982
+ audit.safeEmit({
983
+ action: "breakglass.grant.requested",
984
+ outcome: "denied",
985
+ actor: actor,
986
+ reason: "factor-rate-limited",
987
+ metadata: { table: table, factorType: factorType, lockUntil: locked.lockedUntil },
988
+ });
989
+ throw new BreakGlassError("breakglass/factor-rate-limited",
990
+ "grant: too many recent factor failures; locked until " +
991
+ new Date(locked.lockedUntil).toISOString());
992
+ }
993
+
994
+ var factorOk = false;
995
+ if (factorType === "totp") {
996
+ factorOk = _verifyTotpFactor(opts.factor).ok;
997
+ } else if (factorType === "passkey") {
998
+ factorOk = (await _verifyPasskeyFactor(opts.factor)).ok;
999
+ }
1000
+
1001
+ if (!factorOk) {
1002
+ await fl.recordFailure(lockKey, { reason: factorType + "-bad" });
1003
+ audit.safeEmit({
1004
+ action: "breakglass.grant.requested",
1005
+ outcome: "denied",
1006
+ actor: actor,
1007
+ reason: "bad-factor",
1008
+ metadata: { table: table, factorType: factorType, columns: requestedColumns },
1009
+ });
1010
+ throw new BreakGlassError("breakglass/bad-factor",
1011
+ "grant: " + factorType + " factor verification failed");
1012
+ }
1013
+ await fl.recordSuccess(lockKey);
1014
+
1015
+ // Build + persist the grant row
1016
+ var nowMs = Date.now();
1017
+ var grantId = "bg-" + generateToken(GRANT_ID_BYTES);
1018
+ var sessionId = (opts.req && opts.req.session && opts.req.session.id) || null;
1019
+ // Honor the framework-wide trustProxy setting from init() — same
1020
+ // boundary as middleware. Without trustProxy, X-Forwarded-For is
1021
+ // ignored as attacker-forgeable, and the grant pins to the socket
1022
+ // remoteAddress only.
1023
+ var ipFromReq = requestHelpers.clientIp(opts.req, { trustProxy: _trustProxy });
1024
+
1025
+ var grantRow = {
1026
+ _id: grantId,
1027
+ issuedToActorId: actorId,
1028
+ factorType: factorType,
1029
+ reasonSealed: reason,
1030
+ scopeTable: table,
1031
+ scopeColumnsJson: JSON.stringify(requestedColumns),
1032
+ issuedAt: nowMs,
1033
+ expiresAt: nowMs + policy.grantTtl,
1034
+ maxRowsPerGrant: policy.maxRowsPerGrant,
1035
+ rowsConsumed: 0,
1036
+ revokedAt: null,
1037
+ sessionId: sessionId,
1038
+ ip: ipFromReq,
1039
+ kwGrantHalf: null,
1040
+ };
1041
+ var sealed = cryptoField.sealRow("_blamejs_break_glass_grants", grantRow);
1042
+ var keys = Object.keys(sealed);
1043
+ var cols = keys.join(", ");
1044
+ var qs = keys.map(function () { return "?"; }).join(", ");
1045
+ await clusterStorage.execute(
1046
+ "INSERT INTO _blamejs_break_glass_grants (" + cols + ") VALUES (" + qs + ")",
1047
+ keys.map(function (k) { return sealed[k]; })
1048
+ );
1049
+
1050
+ // Audit
1051
+ var reasonForAudit = _reasonForAudit(reason, policy.auditReasonStorage);
1052
+ audit.safeEmit({
1053
+ action: "breakglass.grant.requested",
1054
+ outcome: "success",
1055
+ actor: actor,
1056
+ reason: reasonForAudit.cleartext,
1057
+ metadata: {
1058
+ grantId: grantId,
1059
+ table: table,
1060
+ columns: requestedColumns,
1061
+ factorType: factorType,
1062
+ ttlMs: policy.grantTtl,
1063
+ maxRowsPerGrant: policy.maxRowsPerGrant,
1064
+ reasonHmac: reasonForAudit.hmac,
1065
+ },
1066
+ });
1067
+ observability.event("breakGlass.grant", { table: table });
1068
+
1069
+ return {
1070
+ id: grantId,
1071
+ expiresAt: grantRow.expiresAt,
1072
+ rowsRemaining: policy.maxRowsPerGrant,
1073
+ scopeTable: table,
1074
+ scopeColumns: requestedColumns,
1075
+ };
1076
+ }
1077
+
1078
+ function _reasonForAudit(reason, mode) {
1079
+ // HMAC variant uses SHA3-512 keyed by a stable framework-wide tag —
1080
+ // operators with multiple deployments can correlate via the hash
1081
+ // without re-deriving from the same secret. Cleartext is the default
1082
+ // (compliance reviewers WANT to read the reason).
1083
+ var out = { cleartext: null, hmac: null };
1084
+ if (mode === "cleartext" || mode === "both") out.cleartext = reason;
1085
+ if (mode === "hmac" || mode === "both") {
1086
+ out.hmac = sha3Hash("breakGlass.reason:" + reason);
1087
+ }
1088
+ return out;
1089
+ }
1090
+
1091
+ // ---- Use a grant ----
1092
+
1093
+ /**
1094
+ * @primitive b.breakGlass.unsealRow
1095
+ * @signature b.breakGlass.unsealRow(grantHandle, table, rowId, opts)
1096
+ * @since 0.5.0
1097
+ * @status stable
1098
+ * @compliance hipaa, pci-dss, soc2
1099
+ * @related b.breakGlass.grant, b.breakGlass.decryptCell, b.breakGlass.revoke
1100
+ *
1101
+ * Read one row's glass-locked columns under an active grant. The
1102
+ * framework validates the grant (not revoked, not expired, not
1103
+ * exhausted, scope matches the table), atomically increments
1104
+ * `rowsConsumed`, fetches and unseals the row, and emits a per-row
1105
+ * `breakglass.unsealrow` audit event carrying the reason + actor +
1106
+ * remaining rows. For Model B (cryptographic) policies, glass-locked
1107
+ * columns route through `decryptCell` with encryption-context binding
1108
+ * — a swapped ciphertext from another row fails closed at AEAD verify.
1109
+ *
1110
+ * @opts
1111
+ * req: object, // optional originating request — populates ip / userAgent / sessionId / requestId on the audit row
1112
+ *
1113
+ * @example
1114
+ * var row = await b.breakGlass.unsealRow(handle, "patients", "patient-001", { req: req });
1115
+ * // → { _id: "patient-001", name: "Alice", ssn: "123-45-6789", dob: "1980-04-12", ... }
1116
+ */
1117
+ async function unsealRow(grantHandle, table, rowId, opts) {
1118
+ _requireInit();
1119
+ if (!grantHandle || typeof grantHandle !== "object" || typeof grantHandle.id !== "string") {
1120
+ throw new BreakGlassError("breakglass/bad-grant-opts",
1121
+ "unsealRow: grant handle is required (returned from b.breakGlass.grant())");
1122
+ }
1123
+ // Optional opts.req lets the caller thread the originating request
1124
+ // into per-row audit emits so the 5 W's (ip / userAgent / sessionId /
1125
+ // requestId / method / route) populate alongside the grant's actor
1126
+ // userId. Backward-compatible — calls without opts continue to work
1127
+ // and simply audit with userId-only actor.
1128
+ opts = opts || {};
1129
+ function _actorFor(grantRow) {
1130
+ return requestHelpers.extractActorContext(opts.req, {
1131
+ userId: grantRow.issuedToActorId,
1132
+ });
1133
+ }
1134
+ if (typeof table !== "string" || table.length === 0) {
1135
+ throw new BreakGlassError("breakglass/bad-grant-opts",
1136
+ "unsealRow: table must be a non-empty string");
1137
+ }
1138
+ if (rowId === undefined || rowId === null || rowId === "") {
1139
+ throw new BreakGlassError("breakglass/bad-grant-opts",
1140
+ "unsealRow: rowId is required");
1141
+ }
1142
+ var grantRows = await clusterStorage.executeAll(
1143
+ "SELECT * FROM _blamejs_break_glass_grants WHERE _id = ?",
1144
+ [grantHandle.id]
1145
+ );
1146
+ if (!grantRows || grantRows.length === 0) {
1147
+ throw new BreakGlassError("breakglass/grant-revoked",
1148
+ "unsealRow: grant " + grantHandle.id + " not found (deleted or never issued)", true);
1149
+ }
1150
+ var sealedGrant = grantRows[0];
1151
+ var grantRow = cryptoField.unsealRow("_blamejs_break_glass_grants", sealedGrant);
1152
+
1153
+ // Table mismatch
1154
+ if (grantRow.scopeTable !== table) {
1155
+ audit.safeEmit({
1156
+ action: "breakglass.unsealrow",
1157
+ outcome: "denied",
1158
+ actor: _actorFor(grantRow),
1159
+ reason: "grant-table-mismatch",
1160
+ metadata: { grantId: grantRow._id, expectedTable: grantRow.scopeTable, gotTable: table, rowId: String(rowId) },
1161
+ });
1162
+ throw new BreakGlassError("breakglass/grant-table-mismatch",
1163
+ "unsealRow: grant " + grantHandle.id + " is scoped to '" +
1164
+ grantRow.scopeTable + "', not '" + table + "'", true);
1165
+ }
1166
+
1167
+ // Revoked
1168
+ if (grantRow.revokedAt) {
1169
+ throw new BreakGlassError("breakglass/grant-revoked",
1170
+ "unsealRow: grant " + grantHandle.id + " was revoked at " +
1171
+ new Date(Number(grantRow.revokedAt)).toISOString(), true);
1172
+ }
1173
+
1174
+ // Expired
1175
+ if (Number(grantRow.expiresAt) <= Date.now()) {
1176
+ audit.safeEmit({
1177
+ action: "breakglass.grant.expired",
1178
+ outcome: "success",
1179
+ actor: _actorFor(grantRow),
1180
+ metadata: { grantId: grantRow._id, table: table, rowsConsumed: Number(grantRow.rowsConsumed) },
1181
+ });
1182
+ throw new BreakGlassError("breakglass/grant-expired",
1183
+ "unsealRow: grant " + grantHandle.id + " expired at " +
1184
+ new Date(Number(grantRow.expiresAt)).toISOString(), true);
1185
+ }
1186
+
1187
+ // Exhausted
1188
+ if (Number(grantRow.rowsConsumed) >= Number(grantRow.maxRowsPerGrant)) {
1189
+ audit.safeEmit({
1190
+ action: "breakglass.grant.exhausted",
1191
+ outcome: "success",
1192
+ actor: _actorFor(grantRow),
1193
+ metadata: { grantId: grantRow._id, table: table, rowsConsumed: Number(grantRow.rowsConsumed) },
1194
+ });
1195
+ throw new BreakGlassError("breakglass/grant-exhausted",
1196
+ "unsealRow: grant " + grantHandle.id + " has consumed all " +
1197
+ grantRow.maxRowsPerGrant + " allowed rows", true);
1198
+ }
1199
+
1200
+ // SELECT-before-increment — fetch the target row FIRST. If the row
1201
+ // doesn't exist (operator typo, race with row-deletion, etc.), the
1202
+ // grant should not be consumed. Without this ordering, a single
1203
+ // typo against `maxRowsPerGrant: 1` (the default) exhausts the
1204
+ // grant and forces the operator to re-do the step-up ceremony.
1205
+ var rows = await clusterStorage.executeAll(
1206
+ "SELECT * FROM " + '"' + table + '"' + " WHERE _id = ?",
1207
+ [String(rowId)]
1208
+ );
1209
+ if (!rows || rows.length === 0) {
1210
+ throw new BreakGlassError("breakglass/row-not-found",
1211
+ "unsealRow: " + table + "[" + rowId + "] not found", true);
1212
+ }
1213
+
1214
+ // Increment rowsConsumed (atomic UPDATE with WHERE rowsConsumed < cap
1215
+ // so concurrent unseals can't both pass the runtime check above).
1216
+ var updateRes = await clusterStorage.execute(
1217
+ "UPDATE _blamejs_break_glass_grants " +
1218
+ "SET rowsConsumed = rowsConsumed + 1 " +
1219
+ "WHERE _id = ? AND rowsConsumed < maxRowsPerGrant AND " +
1220
+ "(revokedAt IS NULL) AND expiresAt > ?",
1221
+ [grantHandle.id, Date.now()]
1222
+ );
1223
+ // executeAll-style result; some backends return rowsAffected, others a count.
1224
+ // Re-query to confirm the increment landed and get the post-increment counter.
1225
+ var postRows = await clusterStorage.executeAll(
1226
+ "SELECT rowsConsumed, revokedAt, expiresAt FROM _blamejs_break_glass_grants WHERE _id = ?",
1227
+ [grantHandle.id]
1228
+ );
1229
+ if (!postRows || postRows.length === 0) {
1230
+ throw new BreakGlassError("breakglass/grant-revoked",
1231
+ "unsealRow: grant " + grantHandle.id + " disappeared during unseal", true);
1232
+ }
1233
+ var postRowsConsumed = Number(postRows[0].rowsConsumed);
1234
+ // If the UPDATE didn't actually increment (race lost — another unseal
1235
+ // exhausted the grant or it was revoked / expired between our check
1236
+ // and the UPDATE), refuse this read.
1237
+ if (postRowsConsumed === Number(grantRow.rowsConsumed)) {
1238
+ throw new BreakGlassError("breakglass/grant-exhausted",
1239
+ "unsealRow: grant " + grantHandle.id + " was exhausted by a concurrent read", true);
1240
+ }
1241
+ void updateRes;
1242
+ var policy = await policyGet(table);
1243
+ var unsealedRow;
1244
+ if (policy && policy.cryptographic) {
1245
+ // Snapshot the raw glass-locked column ciphertexts BEFORE
1246
+ // cryptoField.unsealRow runs — cryptoField doesn't know about the
1247
+ // bgcell: format and would no-op (or error) on it. Then unseal the
1248
+ // rest of the row, then decrypt the glass-locked columns via
1249
+ // decryptCell with encryption-context binding.
1250
+ var rawCipher = {};
1251
+ for (var c = 0; c < policy.columns.length; c++) {
1252
+ rawCipher[policy.columns[c]] = rows[0][policy.columns[c]];
1253
+ }
1254
+ var rowMinusLocked = Object.assign({}, rows[0]);
1255
+ for (var c2 = 0; c2 < policy.columns.length; c2++) {
1256
+ delete rowMinusLocked[policy.columns[c2]];
1257
+ }
1258
+ unsealedRow = cryptoField.unsealRow(table, rowMinusLocked);
1259
+ for (var c3 = 0; c3 < policy.columns.length; c3++) {
1260
+ var col = policy.columns[c3];
1261
+ if (rawCipher[col] == null) continue;
1262
+ try {
1263
+ unsealedRow[col] = await decryptCell(rawCipher[col],
1264
+ { table: table, rowId: String(rowId), column: col });
1265
+ } catch (e) {
1266
+ throw new BreakGlassError("breakglass/cell-decrypt-failed",
1267
+ "unsealRow: cell decrypt failed for " + table + "[" + rowId +
1268
+ "]." + col + " (was the row migrated to Model B?): " +
1269
+ ((e && e.message) || String(e)), true);
1270
+ }
1271
+ }
1272
+ } else {
1273
+ unsealedRow = cryptoField.unsealRow(table, rows[0]);
1274
+ }
1275
+
1276
+ // Per-row audit. The grant's reasonSealed is already cleartext after
1277
+ // unsealRow on the grant; pass it into the audit row honoring the
1278
+ // policy's auditReasonStorage mode.
1279
+ var reasonForAudit = _reasonForAudit(grantRow.reasonSealed || "",
1280
+ policy ? policy.auditReasonStorage : DEFAULT_AUDIT_REASON);
1281
+ audit.safeEmit({
1282
+ action: "breakglass.unsealrow",
1283
+ outcome: "success",
1284
+ actor: _actorFor(grantRow),
1285
+ reason: reasonForAudit.cleartext,
1286
+ metadata: {
1287
+ grantId: grantRow._id,
1288
+ table: table,
1289
+ rowId: String(rowId),
1290
+ columns: safeJson.parse(grantRow.scopeColumnsJson || "[]", { maxBytes: C.BYTES.kib(64) }),
1291
+ rowsRemaining: Number(grantRow.maxRowsPerGrant) - postRowsConsumed,
1292
+ reasonHmac: reasonForAudit.hmac,
1293
+ },
1294
+ });
1295
+ observability.event("breakglass.unsealrow", { table: table });
1296
+
1297
+ return unsealedRow;
1298
+ }
1299
+
1300
+ // ---- Revoke ----
1301
+
1302
+ /**
1303
+ * @primitive b.breakGlass.revoke
1304
+ * @signature b.breakGlass.revoke(grantId, opts)
1305
+ * @since 0.5.0
1306
+ * @status stable
1307
+ * @related b.breakGlass.grant, b.breakGlass.revokeAll
1308
+ *
1309
+ * Mark a single grant revoked. Subsequent `unsealRow` calls against the
1310
+ * grant id throw `breakglass/grant-revoked`. Idempotent — already-
1311
+ * revoked grants stay at their original `revokedAt` timestamp because
1312
+ * the UPDATE clause is gated on `revokedAt IS NULL`.
1313
+ *
1314
+ * @opts
1315
+ * reason: string, // operator note recorded into the audit row
1316
+ * callerOpts: object, // forwarded to audit actor resolution
1317
+ *
1318
+ * @example
1319
+ * await b.breakGlass.revoke("bg-abc123", { reason: "operator finished read; releasing" });
1320
+ * // → { revoked: true, grantId: "bg-abc123" }
1321
+ */
1322
+ async function revoke(grantId, opts) {
1323
+ _requireInit();
1324
+ if (typeof grantId !== "string" || grantId.length === 0) {
1325
+ throw new BreakGlassError("breakglass/bad-grant-opts",
1326
+ "revoke: grantId is required");
1327
+ }
1328
+ opts = opts || {};
1329
+ var nowMs = Date.now();
1330
+ await clusterStorage.execute(
1331
+ "UPDATE _blamejs_break_glass_grants SET revokedAt = ? " +
1332
+ "WHERE _id = ? AND revokedAt IS NULL",
1333
+ [nowMs, grantId]
1334
+ );
1335
+ audit.safeEmit({
1336
+ action: "breakglass.grant.revoked",
1337
+ outcome: "success",
1338
+ actor: requestHelpers.resolveActorWithOverride(opts),
1339
+ reason: typeof opts.reason === "string" ? opts.reason : null,
1340
+ metadata: { grantId: grantId },
1341
+ });
1342
+ return { revoked: true, grantId: grantId };
1343
+ }
1344
+
1345
+ // ---- listActive ----
1346
+
1347
+ /**
1348
+ * @primitive b.breakGlass.listActive
1349
+ * @signature b.breakGlass.listActive(opts)
1350
+ * @since 0.5.0
1351
+ * @status stable
1352
+ * @related b.breakGlass.listActiveAll, b.breakGlass.revoke
1353
+ *
1354
+ * Enumerate the active (not revoked, not expired, rows remaining)
1355
+ * grants the caller currently holds. Lookup is keyed via cryptoField's
1356
+ * `computeDerived` so the actor's id never appears in cleartext on the
1357
+ * grants table — the framework hashes via the table's namespaced
1358
+ * derivation. Unauthenticated callers (no actorId on `req`) get an
1359
+ * empty array.
1360
+ *
1361
+ * @opts
1362
+ * req: object, // request carrying the actor identity (req.user.id or req.apiKey.id)
1363
+ *
1364
+ * @example
1365
+ * var grants = await b.breakGlass.listActive({ req: req });
1366
+ * // → [{ id: "bg-...", scopeTable: "patients", scopeColumns: ["ssn"], expiresAt: ..., rowsRemaining: 1, factorType: "totp" }]
1367
+ */
1368
+ async function listActive(opts) {
1369
+ _requireInit();
1370
+ opts = opts || {};
1371
+ var actor = requestHelpers.extractActorContext(opts.req);
1372
+ var actorId = actor.userId || (opts.req && opts.req.apiKey && opts.req.apiKey.id) || null;
1373
+ if (!actorId) return [];
1374
+ // Use cryptoField's computeDerived so the hash matches the table's
1375
+ // hashNamespace prefix — raw sha3Hash would produce a different value.
1376
+ var derived = cryptoField.computeDerived(
1377
+ "_blamejs_break_glass_grants", "issuedToActorId", actorId
1378
+ );
1379
+ if (!derived) return [];
1380
+ var nowMs = Date.now();
1381
+ var rows = await clusterStorage.executeAll(
1382
+ "SELECT * FROM _blamejs_break_glass_grants " +
1383
+ "WHERE issuedToActorHash = ? AND (revokedAt IS NULL) AND expiresAt > ? AND rowsConsumed < maxRowsPerGrant " +
1384
+ "ORDER BY issuedAt DESC",
1385
+ [derived.value, nowMs]
1386
+ );
1387
+ var out = [];
1388
+ for (var i = 0; i < (rows || []).length; i++) {
1389
+ var u = cryptoField.unsealRow("_blamejs_break_glass_grants", rows[i]);
1390
+ out.push({
1391
+ id: u._id,
1392
+ scopeTable: u.scopeTable,
1393
+ scopeColumns: safeJson.parse(u.scopeColumnsJson || "[]", { maxBytes: C.BYTES.kib(64) }),
1394
+ issuedAt: Number(u.issuedAt),
1395
+ expiresAt: Number(u.expiresAt),
1396
+ rowsRemaining: Number(u.maxRowsPerGrant) - Number(u.rowsConsumed),
1397
+ factorType: u.factorType,
1398
+ });
1399
+ }
1400
+ return out;
1401
+ }
1402
+
1403
+ // ---- Service-account bypass ----
1404
+ //
1405
+ // Some legitimate workloads (nightly de-identification, scheduled
1406
+ // compliance reports) need PHI access without a human at the
1407
+ // keyboard. The framework refuses to silently bypass — operators
1408
+ // declare explicit service-account bypasses per-table with an apiKey
1409
+ // allowlist + required role. Both must match (verified apiKey id is
1410
+ // in the allowlist AND the apiKey carries the required role/scope)
1411
+ // before the bypass is granted. Each bypass emits its own distinct
1412
+ // audit row so post-incident review can distinguish operator-initiated
1413
+ // from service-initiated reads.
1414
+
1415
+ /**
1416
+ * @primitive b.breakGlass.unsealRowAsService
1417
+ * @signature b.breakGlass.unsealRowAsService(req, table, rowId, opts)
1418
+ * @since 0.5.0
1419
+ * @status stable
1420
+ * @compliance hipaa, pci-dss, soc2
1421
+ * @related b.breakGlass.policy.set, b.breakGlass.unsealRow
1422
+ *
1423
+ * Machine-account read of a glass-locked row. Bypass is gated by the
1424
+ * policy's `serviceAccountBypass` block — both the verified `req.apiKey.id`
1425
+ * must be on the operator-declared allowlist AND the apiKey must
1426
+ * carry the operator-declared role. Both checks must pass; either
1427
+ * failure emits a denied bypass audit row and throws
1428
+ * `breakglass/bypass-unauthorized`. Each successful bypass emits a
1429
+ * distinct `breakglass.grant.bypass` audit row so post-incident review
1430
+ * separates operator-initiated reads from scheduled-job reads.
1431
+ *
1432
+ * @opts
1433
+ * reason: string, // operator-supplied reason recorded into the audit row
1434
+ *
1435
+ * @example
1436
+ * var row = await b.breakGlass.unsealRowAsService(req, "patients", "patient-001", {
1437
+ * reason: "nightly de-identification job",
1438
+ * });
1439
+ * // → { _id: "patient-001", name: "Alice", ssn: "123-45-6789", ... }
1440
+ */
1441
+ async function unsealRowAsService(req, table, rowId, opts) {
1442
+ _requireInit();
1443
+ opts = opts || {};
1444
+ if (!req || typeof req !== "object") {
1445
+ throw new BreakGlassError("breakglass/bad-grant-opts",
1446
+ "unsealRowAsService: req is required (with verified req.apiKey)");
1447
+ }
1448
+ if (typeof table !== "string" || table.length === 0) {
1449
+ throw new BreakGlassError("breakglass/bad-grant-opts",
1450
+ "unsealRowAsService: table must be a non-empty string");
1451
+ }
1452
+ var policy = await policyGet(table);
1453
+ if (!policy) {
1454
+ throw new BreakGlassError("breakglass/policy-not-set",
1455
+ "unsealRowAsService: no break-glass policy for table '" + table + "'", true);
1456
+ }
1457
+ if (!policy.serviceAccountBypass) {
1458
+ throw new BreakGlassError("breakglass/bypass-not-configured",
1459
+ "unsealRowAsService: serviceAccountBypass is not configured for '" + table + "'", true);
1460
+ }
1461
+ var apiKeyOnReq = req.apiKey;
1462
+ if (!apiKeyOnReq || typeof apiKeyOnReq.id !== "string") {
1463
+ throw new BreakGlassError("breakglass/bypass-no-apikey",
1464
+ "unsealRowAsService: req.apiKey.id is required (operator must run b.middleware.requireApiKey before this path)", true);
1465
+ }
1466
+ if (policy.serviceAccountBypass.apiKeyIds.indexOf(apiKeyOnReq.id) === -1) {
1467
+ audit.safeEmit({
1468
+ action: "breakglass.grant.bypass",
1469
+ outcome: "denied",
1470
+ actor: requestHelpers.extractActorContext(req),
1471
+ reason: "apikey-not-in-allowlist",
1472
+ metadata: { table: table, rowId: String(rowId), apiKeyId: apiKeyOnReq.id },
1473
+ });
1474
+ throw new BreakGlassError("breakglass/bypass-unauthorized",
1475
+ "unsealRowAsService: apiKey '" + apiKeyOnReq.id +
1476
+ "' is not in the bypass allowlist for '" + table + "'", true);
1477
+ }
1478
+ // Role check — actor must carry policy.serviceAccountBypass.requireRole
1479
+ // either as a direct scope or via b.permissions.check resolution.
1480
+ var actorScopes = Array.isArray(apiKeyOnReq.scopes) ? apiKeyOnReq.scopes :
1481
+ Array.isArray(apiKeyOnReq.roles) ? apiKeyOnReq.roles :
1482
+ [];
1483
+ var requiredRole = policy.serviceAccountBypass.requireRole;
1484
+ var hasRole = actorScopes.indexOf(requiredRole) !== -1;
1485
+ if (!hasRole) {
1486
+ audit.safeEmit({
1487
+ action: "breakglass.grant.bypass",
1488
+ outcome: "denied",
1489
+ actor: requestHelpers.extractActorContext(req),
1490
+ reason: "missing-role",
1491
+ metadata: { table: table, rowId: String(rowId), apiKeyId: apiKeyOnReq.id, requiredRole: requiredRole },
1492
+ });
1493
+ throw new BreakGlassError("breakglass/bypass-unauthorized",
1494
+ "unsealRowAsService: apiKey '" + apiKeyOnReq.id +
1495
+ "' lacks required role '" + requiredRole + "'", true);
1496
+ }
1497
+
1498
+ // Fetch + unseal the row (Model A or Model B path, same as
1499
+ // operator-initiated unsealRow).
1500
+ var rows = await clusterStorage.executeAll(
1501
+ "SELECT * FROM " + '"' + table + '"' + " WHERE _id = ?",
1502
+ [String(rowId)]
1503
+ );
1504
+ if (!rows || rows.length === 0) {
1505
+ throw new BreakGlassError("breakglass/row-not-found",
1506
+ "unsealRowAsService: " + table + "[" + rowId + "] not found", true);
1507
+ }
1508
+ var unsealedRow;
1509
+ if (policy.cryptographic) {
1510
+ var rawCipher = {};
1511
+ for (var c = 0; c < policy.columns.length; c++) rawCipher[policy.columns[c]] = rows[0][policy.columns[c]];
1512
+ var rowMinusLocked = Object.assign({}, rows[0]);
1513
+ for (var c2 = 0; c2 < policy.columns.length; c2++) delete rowMinusLocked[policy.columns[c2]];
1514
+ unsealedRow = cryptoField.unsealRow(table, rowMinusLocked);
1515
+ for (var c3 = 0; c3 < policy.columns.length; c3++) {
1516
+ var col = policy.columns[c3];
1517
+ if (rawCipher[col] == null) continue;
1518
+ unsealedRow[col] = await decryptCell(rawCipher[col],
1519
+ { table: table, rowId: String(rowId), column: col });
1520
+ }
1521
+ } else {
1522
+ unsealedRow = cryptoField.unsealRow(table, rows[0]);
1523
+ }
1524
+
1525
+ audit.safeEmit({
1526
+ action: "breakglass.grant.bypass",
1527
+ outcome: "success",
1528
+ actor: requestHelpers.extractActorContext(req),
1529
+ reason: typeof opts.reason === "string" ? opts.reason : null,
1530
+ metadata: {
1531
+ table: table,
1532
+ rowId: String(rowId),
1533
+ apiKeyId: apiKeyOnReq.id,
1534
+ requiredRole: requiredRole,
1535
+ columns: policy.columns.slice(),
1536
+ },
1537
+ });
1538
+ observability.event("breakglass.grant.bypass", { table: table });
1539
+ return unsealedRow;
1540
+ }
1541
+
1542
+ // ---- Admin tools ----
1543
+ //
1544
+ // `listActiveAll` returns every active grant (across all actors) —
1545
+ // for security-team dashboards and offboarding workflows.
1546
+ // `revokeAll` mass-revokes grants matching criteria — used by IR
1547
+ // teams when an account is suspected compromised. Both require
1548
+ // admin scope (operator wires via opts.requireScope or their own gate).
1549
+
1550
+ /**
1551
+ * @primitive b.breakGlass.listActiveAll
1552
+ * @signature b.breakGlass.listActiveAll(opts)
1553
+ * @since 0.5.0
1554
+ * @status stable
1555
+ * @related b.breakGlass.listActive, b.breakGlass.revokeAll
1556
+ *
1557
+ * Admin variant of `listActive` — returns every active grant across
1558
+ * every actor. Used by security-team dashboards and offboarding
1559
+ * workflows; operators wire their own gate (`requireScope` or a
1560
+ * middleware) on the calling route so non-admins can't enumerate the
1561
+ * full grant pool. Each call emits a `breakglass.admin.listactiveall`
1562
+ * audit row.
1563
+ *
1564
+ * @opts
1565
+ * table: string, // optional filter — only grants scoped to this table
1566
+ * since: number, // optional issuedAt floor (ms epoch)
1567
+ * callerOpts: object, // forwarded to audit actor resolution
1568
+ *
1569
+ * @example
1570
+ * var all = await b.breakGlass.listActiveAll({ table: "patients" });
1571
+ * // → [{ id: "bg-...", issuedToActorId: "user-42", scopeTable: "patients", ... }]
1572
+ */
1573
+ async function listActiveAll(opts) {
1574
+ _requireInit();
1575
+ opts = opts || {};
1576
+ var nowMs = Date.now();
1577
+ var clauses = ["(revokedAt IS NULL)", "expiresAt > ?", "rowsConsumed < maxRowsPerGrant"];
1578
+ var params = [nowMs];
1579
+ if (opts.table) {
1580
+ clauses.push("scopeTable = ?");
1581
+ params.push(opts.table);
1582
+ }
1583
+ if (opts.since) {
1584
+ clauses.push("issuedAt >= ?");
1585
+ params.push(opts.since);
1586
+ }
1587
+ var rows = await clusterStorage.executeAll(
1588
+ "SELECT * FROM _blamejs_break_glass_grants WHERE " + clauses.join(" AND ") +
1589
+ " ORDER BY issuedAt DESC",
1590
+ params
1591
+ );
1592
+ var out = [];
1593
+ for (var i = 0; i < (rows || []).length; i++) {
1594
+ var u = cryptoField.unsealRow("_blamejs_break_glass_grants", rows[i]);
1595
+ out.push({
1596
+ id: u._id,
1597
+ issuedToActorId: u.issuedToActorId,
1598
+ scopeTable: u.scopeTable,
1599
+ scopeColumns: safeJson.parse(u.scopeColumnsJson || "[]", { maxBytes: C.BYTES.kib(64) }),
1600
+ factorType: u.factorType,
1601
+ issuedAt: Number(u.issuedAt),
1602
+ expiresAt: Number(u.expiresAt),
1603
+ rowsRemaining: Number(u.maxRowsPerGrant) - Number(u.rowsConsumed),
1604
+ });
1605
+ }
1606
+ audit.safeEmit({
1607
+ action: "breakglass.admin.listactiveall",
1608
+ outcome: "success",
1609
+ actor: requestHelpers.resolveActorWithOverride(opts.callerOpts),
1610
+ metadata: { resultCount: out.length, filterTable: opts.table || null },
1611
+ });
1612
+ return out;
1613
+ }
1614
+
1615
+ /**
1616
+ * @primitive b.breakGlass.revokeAll
1617
+ * @signature b.breakGlass.revokeAll(criteria, opts)
1618
+ * @since 0.5.0
1619
+ * @status stable
1620
+ * @related b.breakGlass.revoke, b.breakGlass.listActiveAll
1621
+ *
1622
+ * Mass-revoke grants matching a scope predicate. Refuses to run with
1623
+ * empty criteria — IR teams must name at least one of `actorId` or
1624
+ * `table` so the framework never silently revokes every grant in the
1625
+ * cluster. The to-be-revoked grant ids are snapshotted into the audit
1626
+ * row before the UPDATE, so post-incident timelines have the exact
1627
+ * list. Common shape: revoke every active grant held by a suspected-
1628
+ * compromised account.
1629
+ *
1630
+ * @opts
1631
+ * callerOpts: object, // forwarded to audit actor resolution
1632
+ *
1633
+ * @example
1634
+ * var result = await b.breakGlass.revokeAll(
1635
+ * { actorId: "user-42", reason: "account compromise — IR-2026-0042" },
1636
+ * { callerOpts: { actor: { userId: "soc-on-call" } } }
1637
+ * );
1638
+ * // → { revokedCount: 3 }
1639
+ */
1640
+ async function revokeAll(criteria, opts) {
1641
+ _requireInit();
1642
+ if (!criteria || typeof criteria !== "object") {
1643
+ throw new BreakGlassError("breakglass/bad-revoke-criteria",
1644
+ "revokeAll: criteria is required ({ actorId?, table? })");
1645
+ }
1646
+ if (!criteria.actorId && !criteria.table) {
1647
+ throw new BreakGlassError("breakglass/bad-revoke-criteria",
1648
+ "revokeAll: at least one of { actorId, table } is required (refusing to mass-revoke without scope)");
1649
+ }
1650
+ opts = opts || {};
1651
+ var clauses = ["revokedAt IS NULL"];
1652
+ var params = [];
1653
+ if (criteria.actorId) {
1654
+ var derived = cryptoField.computeDerived(
1655
+ "_blamejs_break_glass_grants", "issuedToActorId", criteria.actorId
1656
+ );
1657
+ if (derived) {
1658
+ clauses.push("issuedToActorHash = ?");
1659
+ params.push(derived.value);
1660
+ }
1661
+ }
1662
+ if (criteria.table) {
1663
+ clauses.push("scopeTable = ?");
1664
+ params.push(criteria.table);
1665
+ }
1666
+ // Snapshot the to-be-revoked grant ids first so audit captures specifics.
1667
+ var ids = await clusterStorage.executeAll(
1668
+ "SELECT _id FROM _blamejs_break_glass_grants WHERE " + clauses.join(" AND "),
1669
+ params
1670
+ );
1671
+ var nowMs = Date.now();
1672
+ await clusterStorage.execute(
1673
+ "UPDATE _blamejs_break_glass_grants SET revokedAt = ? WHERE " + clauses.join(" AND "),
1674
+ [nowMs].concat(params)
1675
+ );
1676
+ audit.safeEmit({
1677
+ action: "breakglass.admin.revokeall",
1678
+ outcome: "success",
1679
+ actor: requestHelpers.resolveActorWithOverride(opts.callerOpts),
1680
+ reason: typeof criteria.reason === "string" ? criteria.reason : null,
1681
+ metadata: {
1682
+ filterActorId: criteria.actorId || null,
1683
+ filterTable: criteria.table || null,
1684
+ revokedCount: (ids || []).length,
1685
+ revokedIds: (ids || []).map(function (r) { return r._id; }),
1686
+ },
1687
+ });
1688
+ return { revokedCount: (ids || []).length };
1689
+ }
1690
+
1691
+ // ---- Sweep (best-effort cleanup of expired grants) ----
1692
+
1693
+ async function _sweepExpired(opts) {
1694
+ opts = opts || {};
1695
+ var nowMs = Date.now();
1696
+ var expired = await clusterStorage.executeAll(
1697
+ "SELECT _id, issuedToActorId, scopeTable, rowsConsumed FROM _blamejs_break_glass_grants " +
1698
+ "WHERE revokedAt IS NULL AND expiresAt <= ?",
1699
+ [nowMs]
1700
+ );
1701
+ for (var i = 0; i < (expired || []).length; i++) {
1702
+ var row = expired[i];
1703
+ audit.safeEmit({
1704
+ action: "breakglass.grant.expired",
1705
+ outcome: "success",
1706
+ actor: { userId: row.issuedToActorId },
1707
+ metadata: { grantId: row._id, table: row.scopeTable, rowsConsumed: Number(row.rowsConsumed) },
1708
+ });
1709
+ }
1710
+ await clusterStorage.execute(
1711
+ "UPDATE _blamejs_break_glass_grants SET revokedAt = ? " +
1712
+ "WHERE revokedAt IS NULL AND expiresAt <= ?",
1713
+ [nowMs, nowMs]
1714
+ );
1715
+ return { expired: (expired || []).length };
1716
+ }
1717
+
1718
+ void safeAsync; // kept import for future grant-async ops in v0.5.1+
1719
+
1720
+ module.exports = {
1721
+ init: init,
1722
+ policy: {
1723
+ set: policySet,
1724
+ get: policyGet,
1725
+ list: policyList,
1726
+ delete: policyDelete,
1727
+ },
1728
+ grant: grant,
1729
+ unsealRow: unsealRow,
1730
+ revoke: revoke,
1731
+ listActive: listActive,
1732
+ // Cryptographic mode (Model B) — per-cell encryption with context
1733
+ // binding. Operators in cryptographic mode call encryptCell at write
1734
+ // time; unsealRow auto-routes to decryptCell for glass-locked columns.
1735
+ encryptCell: encryptCell,
1736
+ decryptCell: decryptCell,
1737
+ migrate: migrate,
1738
+ // Service-account bypass — operator-declared per-table, gated by
1739
+ // (apiKey id in allowlist) AND (apiKey carries required role).
1740
+ unsealRowAsService: unsealRowAsService,
1741
+ // Admin tools — for security-team dashboards (listActiveAll) and
1742
+ // incident-response offboarding (revokeAll). Operators wire their
1743
+ // own gate (requireScope or middleware) on the calling routes.
1744
+ listActiveAll: listActiveAll,
1745
+ revokeAll: revokeAll,
1746
+ BreakGlassError: BreakGlassError,
1747
+
1748
+ // Test-only / sweep — operators with active grant volume wire this
1749
+ // into a scheduler; the framework doesn't auto-start the timer so
1750
+ // boot doesn't depend on anything firing in the background.
1751
+ _sweepExpiredForTest: _sweepExpired,
1752
+ _resetForTest: _resetForTest,
1753
+ };