@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,1877 @@
1
+ "use strict";
2
+ /**
3
+ * @module b.externalDb
4
+ * @nav Data
5
+ * @title External Database
6
+ *
7
+ * @intro
8
+ * External-database integration for app data — Postgres / MySQL /
9
+ * SQLite / MongoDB connection pooling, retry, circuit breaker,
10
+ * classification routing, residency enforcement, and audit hooks.
11
+ *
12
+ * Framework state (audit_log, consent_log, _blamejs_*) stays in the
13
+ * local SQLite via `b.db`. This module is for APP DATA — when an
14
+ * operator keeps domain tables in Postgres / MySQL / MongoDB / libsql,
15
+ * they configure a backend here and use `b.externalDb.query()` instead
16
+ * of `b.db.from()` for those tables. The same surface also serves
17
+ * cluster-mode coordination (leader election advisory locks,
18
+ * cross-replica routing) when the cluster provider points at the same
19
+ * backend.
20
+ *
21
+ * Bring-your-own-client design (per "zero npm runtime deps" rule):
22
+ * the operator supplies the actual DB driver via each backend's
23
+ * `connect` / `query` / `close` hooks. The framework layers
24
+ * connection pooling (lazy-create, idle reaping), transient-error
25
+ * retry, per-backend circuit breaker, classification routing
26
+ * (which backend serves which data class), residency enforcement
27
+ * against `db.getDataResidency().region`, and audit hooks
28
+ * (`system.externaldb.{query,transaction,read}`).
29
+ *
30
+ * Read-replica routing exposes `b.externalDb.read.query()` and
31
+ * `b.externalDb.write.query()` — reads weight-round-robin across
32
+ * declared replicas with health tracking and primary fallback;
33
+ * writes always route to primary.
34
+ *
35
+ * @card
36
+ * External-database integration for app data — Postgres / MySQL / SQLite / MongoDB connection pooling, retry, circuit breaker, classification routing, residency enforcement, and audit hooks.
37
+ */
38
+ var retryHelper = require("./retry");
39
+ var bCrypto = require("./crypto");
40
+ var C = require("./constants");
41
+ var dbRoleContext = require("./db-role-context");
42
+ var externalDbMigrate = require("./external-db-migrate");
43
+ var lazyRequire = require("./lazy-require");
44
+ var { boot } = require("./log");
45
+ var safeAsync = require("./safe-async");
46
+ var safeSql = require("./safe-sql");
47
+ var { ExternalDbError } = require("./framework-error");
48
+
49
+ var log = boot("external-db");
50
+
51
+ var audit = lazyRequire(function () { return require("./audit"); });
52
+ var db = lazyRequire(function () { return require("./db"); });
53
+ var observability = lazyRequire(function () { return require("./observability"); });
54
+
55
+ function _emitMetric(name, value, labels) {
56
+ try { observability().event(name, value, labels || {}); }
57
+ catch (_e) { /* hot-path observability sink — drop silent by design */ }
58
+ }
59
+
60
+ // Statement-class classifier for auth-failure forensics (D-M2). Inspects
61
+ // the leading keyword only so an attacker-controlled trailing fragment
62
+ // can't smuggle a false classification. Skips leading whitespace plus
63
+ // SQL line / block comments before reading the keyword.
64
+ var _STATEMENT_CLASS_RE = /^\s*(?:\/\*[\s\S]*?\*\/\s*|--[^\n]*\n\s*)*([A-Za-z]+)/;
65
+ var _STATEMENT_CLASS_MAP = Object.freeze({
66
+ SELECT: "SELECT", WITH: "SELECT", VALUES: "SELECT", TABLE: "SELECT",
67
+ INSERT: "DML", UPDATE: "DML", DELETE: "DML", MERGE: "DML", UPSERT: "DML",
68
+ CREATE: "DDL", DROP: "DDL", ALTER: "DDL", TRUNCATE: "DDL",
69
+ RENAME: "DDL", COMMENT: "DDL",
70
+ GRANT: "DCL", REVOKE: "DCL",
71
+ SET: "SESSION", RESET: "SESSION",
72
+ BEGIN: "TX", START: "TX", COMMIT: "TX", ROLLBACK: "TX",
73
+ SAVEPOINT: "TX", RELEASE: "TX",
74
+ CALL: "ROUTINE", EXECUTE: "ROUTINE",
75
+ COPY: "BULK",
76
+ EXPLAIN: "META", ANALYZE: "META", VACUUM: "META",
77
+ });
78
+
79
+ function _classifyStatement(sql) {
80
+ if (typeof sql !== "string" || sql.length === 0) return "UNKNOWN";
81
+ var m = _STATEMENT_CLASS_RE.exec(sql);
82
+ if (!m) return "UNKNOWN";
83
+ return _STATEMENT_CLASS_MAP[m[1].toUpperCase()] || "OTHER";
84
+ }
85
+
86
+ // Postgres SQLSTATE classes that indicate authentication / authorization
87
+ // failure at the DB level. SOC2 forensic gap (D-M2) — every match emits
88
+ // db.auth.failed with the SQL identity attempted, the database, and
89
+ // the statement class.
90
+ var _AUTH_FAILURE_CODES = Object.freeze({
91
+ "28000": "invalid_authorization_specification",
92
+ "28P01": "invalid_password",
93
+ "42501": "insufficient_privilege",
94
+ });
95
+
96
+ function _emitAuthFailureAudit(backend, role, sql, e) {
97
+ if (!e || !e.code) return;
98
+ var kind = _AUTH_FAILURE_CODES[e.code];
99
+ if (!kind) return;
100
+ audit().safeEmit({
101
+ action: "db.auth.failed",
102
+ actor: {},
103
+ resource: { kind: "db.backend", id: backend.name },
104
+ outcome: "denied",
105
+ reason: kind,
106
+ metadata: {
107
+ backend: backend.name,
108
+ dialect: backend.dialect,
109
+ sqlIdentity: role || null,
110
+ sqlstate: e.code,
111
+ statementClass: _classifyStatement(sql),
112
+ },
113
+ });
114
+ _emitMetric("db.auth.failed", 1, {
115
+ backend: backend.name,
116
+ sqlstate: e.code,
117
+ statementClass: _classifyStatement(sql),
118
+ });
119
+ }
120
+
121
+ // Slow-query bucket emitter (D-L7). Single-shot per query — highest
122
+ // matched bucket wins. Operators dashboard on the `bucket` label
123
+ // rather than separate counters per threshold.
124
+ var _SLOW_QUERY_BUCKETS = Object.freeze([
125
+ { ms: C.TIME.seconds(30), label: "30s" },
126
+ { ms: C.TIME.seconds(5), label: "5s" },
127
+ { ms: C.TIME.seconds(1), label: "1s" },
128
+ ]);
129
+
130
+ function _emitSlowQuery(backendName, role, durationMs, statementClass) {
131
+ if (typeof durationMs !== "number" || !isFinite(durationMs)) return;
132
+ for (var i = 0; i < _SLOW_QUERY_BUCKETS.length; i++) {
133
+ var bucket = _SLOW_QUERY_BUCKETS[i];
134
+ if (durationMs >= bucket.ms) {
135
+ _emitMetric("db.query.slow", durationMs, {
136
+ backend: backendName,
137
+ role: role || "(none)",
138
+ bucket: bucket.label,
139
+ statementClass: statementClass || "UNKNOWN",
140
+ });
141
+ return;
142
+ }
143
+ }
144
+ }
145
+
146
+ var _err = ExternalDbError.factory;
147
+
148
+ var initialized = false;
149
+ var backends = {};
150
+ var defaultBackend = null;
151
+ // Operator-declared { role: backendName } map for request-time pool pick.
152
+ // Populated at init() from opts.dbRoleBackends. Read by _pickBackend
153
+ // when no explicit opts.backend is supplied AND the ALS scope has a role.
154
+ var dbRoleBackends = {};
155
+
156
+ // ---- Pool ----
157
+ //
158
+ // Per-backend pool with lazy creation + LRU-ish reuse. Connections returned
159
+ // to the pool when query/transaction completes; idle connections expire.
160
+
161
+ class Pool {
162
+ constructor(name, config) {
163
+ this.name = name;
164
+ this.config = Object.assign({ min: 1, max: 10, idleTimeoutMs: C.TIME.minutes(1) }, config.pool || {});
165
+ this.connect = config.connect;
166
+ this.close = config.close || function () { return Promise.resolve(); };
167
+ this.idle = []; // [{ client, lastUsedAt }]
168
+ this.active = 0; // count of in-use clients
169
+ this.waiters = []; // queued acquisitions when at max
170
+ this._reaper = safeAsync.repeating(this._reapIdle.bind(this),
171
+ C.TIME.seconds(10), { name: "external-db-reaper" });
172
+ }
173
+
174
+ async acquire() {
175
+ if (this.idle.length > 0) {
176
+ var entry = this.idle.pop();
177
+ this.active += 1;
178
+ return entry.client;
179
+ }
180
+ if (this.active < this.config.max) {
181
+ this.active += 1;
182
+ try {
183
+ return await this.connect();
184
+ } catch (e) {
185
+ this.active -= 1;
186
+ throw e;
187
+ }
188
+ }
189
+ // At max — wait for a release. The waiter's clock starts now;
190
+ // when release() resolves the waiter we emit the wait duration so
191
+ // operators can see backpressure on the pool.
192
+ var self = this;
193
+ var waitStartedAt = Date.now();
194
+ return new Promise(function (resolve, reject) {
195
+ self.waiters.push({
196
+ resolve: function (client) {
197
+ _emitMetric("externaldb.pool.acquire_wait", Date.now() - waitStartedAt,
198
+ { backend: self.name });
199
+ resolve(client);
200
+ },
201
+ reject: reject,
202
+ });
203
+ });
204
+ }
205
+
206
+ release(client) {
207
+ this.active -= 1;
208
+ if (this.waiters.length > 0) {
209
+ var w = this.waiters.shift();
210
+ this.active += 1;
211
+ w.resolve(client);
212
+ return;
213
+ }
214
+ this.idle.push({ client: client, lastUsedAt: Date.now() });
215
+ }
216
+
217
+ async destroy(client) {
218
+ this.active -= 1;
219
+ try { await this.close(client); } catch (_e) { /* best effort */ }
220
+ if (this.waiters.length > 0) {
221
+ var w = this.waiters.shift();
222
+ this.acquire().then(w.resolve, w.reject);
223
+ }
224
+ }
225
+
226
+ _reapIdle() {
227
+ var now = Date.now();
228
+ var keep = [];
229
+ var self = this;
230
+ this.idle.forEach(function (entry) {
231
+ if ((now - entry.lastUsedAt) >= self.config.idleTimeoutMs) {
232
+ Promise.resolve().then(function () { return self.close(entry.client); }).catch(function () {});
233
+ } else {
234
+ keep.push(entry);
235
+ }
236
+ });
237
+ this.idle = keep;
238
+ }
239
+
240
+ async drain() {
241
+ if (this._reaper) { this._reaper.stop(); this._reaper = null; }
242
+ var idleClients = this.idle.map(function (e) { return e.client; });
243
+ this.idle = [];
244
+ var self = this;
245
+ await Promise.all(idleClients.map(function (c) {
246
+ return Promise.resolve().then(function () { return self.close(c); }).catch(function () {});
247
+ }));
248
+ this.waiters.forEach(function (w) { w.reject(_err("POOL_DRAINED", "pool is shutting down", true)); });
249
+ this.waiters = [];
250
+ }
251
+
252
+ stats() {
253
+ return { active: this.active, idle: this.idle.length, waiters: this.waiters.length };
254
+ }
255
+ }
256
+
257
+ // ---- Init ----
258
+
259
+ /**
260
+ * @primitive b.externalDb.init
261
+ * @signature b.externalDb.init(opts)
262
+ * @since 0.4.0
263
+ * @related b.externalDb.query, b.externalDb.shutdown, b.externalDb.adapters.connectAs
264
+ *
265
+ * Register one or more app-data backends. Each backend declares its
266
+ * `connect` / `query` driver hooks plus optional pooling, classification,
267
+ * residency, retry, and replica configuration. Throws synchronously on
268
+ * malformed input (missing hooks, unknown dialect, residency mismatch
269
+ * against `db.getDataResidency()`, dotted GUC names that fail
270
+ * identifier validation).
271
+ *
272
+ * Boot-time residency check: when `db.getDataResidency().region` is set,
273
+ * any backend serving `personal` (or `*`) data must carry a
274
+ * `residencyTag` in the allowed-region list — refused with
275
+ * `RESIDENCY_VIOLATION` when not.
276
+ *
277
+ * @opts
278
+ * backends: { [name]: BackendConfig }, // required; one or more named backends
279
+ * defaultBackend?: string, // pool used when no opts.backend / classification / role match (defaults to first)
280
+ * dbRoleBackends?: { [sqlRole]: backendName }, // request-time role → backend mapping for the dbRoleFor middleware
281
+ *
282
+ * // BackendConfig shape:
283
+ * // connect(): async () → driver client (required)
284
+ * // query(client, sql, p): async → { rows, rowCount } (required)
285
+ * // close(client): async → void (optional; default no-op)
286
+ * // ping(client): async → void (optional; default `SELECT 1`)
287
+ * // beginTx / commit / rollback(client): async → void (optional; default `BEGIN`/`COMMIT`/`ROLLBACK`)
288
+ * // dialect: "postgres" | "mysql" | "sqlite" | "mongodb" | "other" (default "postgres")
289
+ * // applicationName: string ≤ 63 bytes, no CR/LF/NUL (Postgres pg_stat_activity tag; default null)
290
+ * // pool: { min, max, idleTimeoutMs } (defaults: 1 / 10 / C.TIME.minutes(1))
291
+ * // classifications: string[] (defaults to ["*"])
292
+ * // residencyTag: "EU" | "US" | "unrestricted" | ... (defaults to "unrestricted")
293
+ * // retry, breaker: passthrough to b.retry / CircuitBreaker
294
+ * // replicas: [{ connect, query, weight?, residencyTag?, allowCrossBorder? }]
295
+ * // replicaFallbackToPrimary: boolean (default true)
296
+ *
297
+ * @example
298
+ * var pg = require("pg");
299
+ * var pool = new pg.Pool({ connectionString: "postgres://app:pw@db.example.com/app" });
300
+ *
301
+ * b.externalDb.init({
302
+ * backends: {
303
+ * main: {
304
+ * dialect: "postgres",
305
+ * applicationName: "blamejs-app",
306
+ * connect: function () { return pool.connect(); },
307
+ * query: function (client, sql, params) { return client.query(sql, params); },
308
+ * close: function (client) { return client.release(); },
309
+ * classifications: ["personal", "operational"],
310
+ * residencyTag: "EU",
311
+ * pool: { min: 2, max: 20, idleTimeoutMs: 60000 },
312
+ * },
313
+ * },
314
+ * defaultBackend: "main",
315
+ * });
316
+ */
317
+ function init(opts) {
318
+ if (initialized) return;
319
+ if (!opts || !opts.backends) throw new Error("externalDb.init({ backends }) is required");
320
+
321
+ backends = {};
322
+ dbRoleBackends = {};
323
+ for (var name in opts.backends) {
324
+ var cfg = opts.backends[name];
325
+ if (typeof cfg.connect !== "function") {
326
+ throw _err("INVALID_CONFIG", "backend '" + name + "' missing connect() function", true);
327
+ }
328
+ if (typeof cfg.query !== "function") {
329
+ throw _err("INVALID_CONFIG", "backend '" + name + "' missing query() function", true);
330
+ }
331
+ // dialect — informational marker so dialect-specific consumers
332
+ // (e.g. b.db.declareView) can fail-fast at apply time. Defaults to
333
+ // "postgres" because that's the dominant blamejs externalDb target;
334
+ // operators on SQLite/MySQL/etc. set this explicitly so downstream
335
+ // primitives surface NOT_SUPPORTED with a clear message instead of
336
+ // emitting Postgres-flavored DDL into the wrong dialect.
337
+ var dialect = (cfg.dialect || "postgres").toLowerCase();
338
+ if (["postgres", "mysql", "sqlite", "mongodb", "other"].indexOf(dialect) === -1) {
339
+ throw _err("INVALID_CONFIG",
340
+ "backend '" + name + "': dialect must be one of " +
341
+ "'postgres' | 'mysql' | 'sqlite' | 'mongodb' | 'other', got '" + dialect + "'", true);
342
+ }
343
+ // OWASP-3 — application_name normalization for Postgres backends.
344
+ // Always set on every fresh connection (not just connectAs branch)
345
+ // so pg_stat_activity / log_line_prefix / audit log surfaces show
346
+ // a stable identifier instead of falling back to the driver's
347
+ // bare process name. CR / LF / NUL refused at config-time —
348
+ // those characters terminate the SET statement early in some
349
+ // drivers and have no legitimate use in an application_name.
350
+ // OWASP-3 — application_name normalization for Postgres backends.
351
+ // Opt-in via `cfg.applicationName` to surface a stable identifier
352
+ // in pg_stat_activity / log_line_prefix / Postgres audit log
353
+ // surfaces. Default leaves application_name to the driver — issuing
354
+ // a SET on every fresh connection at framework default would
355
+ // double-count queries for operators counting per-pool query
356
+ // activity (and break test fakes that count tracker.query calls).
357
+ var applicationName = cfg.applicationName !== undefined ? cfg.applicationName : null;
358
+ if (applicationName !== null && (typeof applicationName !== "string" || applicationName.length === 0)) {
359
+ throw _err("INVALID_CONFIG",
360
+ "backend '" + name + "': applicationName must be a non-empty string", true);
361
+ }
362
+ if (applicationName !== null) {
363
+ // eslint-disable-next-line no-control-regex
364
+ if (/[\r\n\u0000]/.test(applicationName)) {
365
+ throw _err("INVALID_CONFIG",
366
+ "backend '" + name + "': applicationName must not contain CR, LF, or NUL characters", true);
367
+ }
368
+ if (applicationName.length > C.BYTES.bytes(63)) {
369
+ throw _err("INVALID_CONFIG",
370
+ "backend '" + name + "': applicationName exceeds Postgres 63-byte limit (got " +
371
+ applicationName.length + ")", true);
372
+ }
373
+ }
374
+ var rawConnect = cfg.connect;
375
+ var rawQuery = cfg.query;
376
+ var connectFn = rawConnect;
377
+ if (dialect === "postgres" && applicationName !== null) {
378
+ // IIFE captures per-iteration rawConnect/rawQuery; without this
379
+ // the var-hoisted bindings are shared across the for-loop and
380
+ // every backend's connectFn ends up calling the LAST iteration's
381
+ // rawQuery (classic closure-in-loop bug).
382
+ connectFn = (function (cn, qn, appName) {
383
+ var quotedAppName = "'" + appName.replace(/'/g, "''") + "'";
384
+ return async function () {
385
+ var client = await cn();
386
+ try {
387
+ await qn(client, "SET application_name TO " + quotedAppName, []);
388
+ } catch (_e) {
389
+ // Best-effort. Real Postgres always supports SET
390
+ // application_name; a driver that refuses it is a shim
391
+ // (test fake / non-PG backend mislabeled "postgres") and
392
+ // there's nothing useful to surface — keep the connection
393
+ // and let the operator hit any real query failure
394
+ // immediately afterwards.
395
+ void _e;
396
+ }
397
+ return client;
398
+ };
399
+ })(rawConnect, rawQuery, applicationName);
400
+ }
401
+ var poolCfg = Object.assign({}, cfg, { connect: connectFn });
402
+ backends[name] = {
403
+ name: name,
404
+ dialect: dialect,
405
+ applicationName: applicationName,
406
+ pool: new Pool(name, poolCfg),
407
+ query: cfg.query,
408
+ ping: cfg.ping || null,
409
+ beginTx: cfg.beginTx || function (client) { return cfg.query(client, "BEGIN", []); },
410
+ commit: cfg.commit || function (client) { return cfg.query(client, "COMMIT", []); },
411
+ rollback: cfg.rollback || function (client) { return cfg.query(client, "ROLLBACK", []); },
412
+ classifications: Array.isArray(cfg.classifications) && cfg.classifications.length > 0
413
+ ? cfg.classifications.slice()
414
+ : ["*"],
415
+ residencyTag: cfg.residencyTag || "unrestricted",
416
+ breaker: new retryHelper.CircuitBreaker("externalDb:" + name, cfg.breaker),
417
+ retryConfig: cfg.retry || null,
418
+ replicas: _buildReplicas(name, cfg),
419
+ replicaIdx: 0, // round-robin cursor
420
+ replicaFallbackToPrimary: cfg.replicaFallbackToPrimary !== false,
421
+ };
422
+ }
423
+
424
+ defaultBackend = opts.defaultBackend || Object.keys(backends)[0];
425
+
426
+ // dbRoleBackends — request-time role → backend mapping. Each role name
427
+ // validates as a SQL identifier at init (matches the dbRoleFor
428
+ // middleware's runtime check) so a typo surfaces at boot rather than
429
+ // as a silent default-backend fallback at the first request.
430
+ if (opts.dbRoleBackends !== undefined && opts.dbRoleBackends !== null) {
431
+ if (typeof opts.dbRoleBackends !== "object" || Array.isArray(opts.dbRoleBackends)) {
432
+ throw _err("INVALID_CONFIG",
433
+ "dbRoleBackends must be an object map of role → backendName", true);
434
+ }
435
+ for (var role in opts.dbRoleBackends) {
436
+ if (!Object.prototype.hasOwnProperty.call(opts.dbRoleBackends, role)) continue;
437
+ try {
438
+ safeSql.validateIdentifier(role, { allowReserved: false });
439
+ } catch (e) {
440
+ throw _err("INVALID_CONFIG",
441
+ "dbRoleBackends: role '" + role + "' is not a valid SQL identifier: " +
442
+ ((e && e.message) || String(e)), true);
443
+ }
444
+ var bn = opts.dbRoleBackends[role];
445
+ if (typeof bn !== "string" || bn.length === 0) {
446
+ throw _err("INVALID_CONFIG",
447
+ "dbRoleBackends['" + role + "']: backend name must be a non-empty string", true);
448
+ }
449
+ if (!Object.prototype.hasOwnProperty.call(backends, bn)) {
450
+ throw _err("INVALID_CONFIG",
451
+ "dbRoleBackends['" + role + "']: no backend named '" + bn + "' " +
452
+ "(declared backends: " + Object.keys(backends).join(", ") + ")", true);
453
+ }
454
+ dbRoleBackends[role] = bn;
455
+ }
456
+ }
457
+
458
+ _validateResidency();
459
+ initialized = true;
460
+ }
461
+
462
+ function _validateResidency() {
463
+ var residency;
464
+ try { residency = db().getDataResidency(); } catch (_e) { residency = null; }
465
+ if (!residency || !residency.region) return;
466
+
467
+ var allowed = [residency.region].concat(residency.allowedStorageRegions || []);
468
+ for (var name in backends) {
469
+ var b = backends[name];
470
+ var serves = b.classifications.indexOf("*") !== -1 || b.classifications.indexOf("personal") !== -1;
471
+ if (!serves) continue;
472
+ if (allowed.indexOf(b.residencyTag) === -1) {
473
+ throw _err("RESIDENCY_VIOLATION",
474
+ "externalDb backend '" + name + "' serves 'personal' data with residencyTag '" +
475
+ b.residencyTag + "' but app's dataResidency.region is '" + residency.region + "'",
476
+ true);
477
+ }
478
+ }
479
+ }
480
+
481
+ // ---- Backend selection ----
482
+ //
483
+ // Pick precedence:
484
+ // 1. opts.backend — explicit override always wins
485
+ // 2. opts.classification — first backend serving that class
486
+ // 3. ALS-bound dbRole + dbRoleBackends — request-time auto-pick
487
+ // 4. defaultBackend — final fallback
488
+ //
489
+ // The ALS path matches the dbRoleFor middleware shape: middleware sets
490
+ // the role; deep async reads pick up the matching backend without having
491
+ // to thread `req` through every call site.
492
+
493
+ function _pickBackend(opts) {
494
+ opts = opts || {};
495
+ if (opts.backend) {
496
+ var b = backends[opts.backend];
497
+ if (!b) throw _err("UNKNOWN_BACKEND", "no backend named '" + opts.backend + "'", true);
498
+ if (opts.classification && !_servesClassification(b, opts.classification)) {
499
+ throw _err("CLASSIFICATION_MISMATCH",
500
+ "backend '" + opts.backend + "' does not serve classification '" + opts.classification + "'", true);
501
+ }
502
+ return b;
503
+ }
504
+ var classification = opts.classification;
505
+ if (classification) {
506
+ for (var name in backends) {
507
+ if (_servesClassification(backends[name], classification)) return backends[name];
508
+ }
509
+ throw _err("NO_BACKEND_FOR_CLASSIFICATION",
510
+ "no backend serves classification '" + classification + "'", true);
511
+ }
512
+ var role = dbRoleContext.getRole();
513
+ if (role && Object.prototype.hasOwnProperty.call(dbRoleBackends, role)) {
514
+ return backends[dbRoleBackends[role]];
515
+ }
516
+ return backends[defaultBackend] || null;
517
+ }
518
+
519
+ function _servesClassification(b, cls) {
520
+ return b.classifications.indexOf("*") !== -1 || b.classifications.indexOf(cls) !== -1;
521
+ }
522
+
523
+ // ---- Public API ----
524
+
525
+ /**
526
+ * @primitive b.externalDb.query
527
+ * @signature b.externalDb.query(sql, params, opts)
528
+ * @since 0.4.0
529
+ * @related b.externalDb.transaction, b.externalDb.read.query, b.externalDb.write.query
530
+ *
531
+ * Execute a single statement against the picked backend. Returns the
532
+ * driver-shaped `{ rows, rowCount }` from the backend's `query` hook.
533
+ * Wraps the call in `b.retry.withRetry` for transient driver errors
534
+ * and the per-backend circuit breaker; emits `system.externaldb.query`
535
+ * audit events plus duration / slow-query metrics; surfaces Postgres
536
+ * SQLSTATE 28000 / 28P01 / 42501 as `db.auth.failed` audit rows for
537
+ * SOC2 forensic walks.
538
+ *
539
+ * Backend selection precedence: `opts.backend` (explicit) →
540
+ * `opts.classification` (first backend serving the class) → ALS-bound
541
+ * dbRole + `dbRoleBackends` map (set by `b.middleware.dbRoleFor` or
542
+ * `b.externalDb.runAs`) → the configured `defaultBackend`.
543
+ *
544
+ * @opts
545
+ * backend?: string, // explicit backend name; bypasses classification + role pick
546
+ * classification?: string, // route to first backend whose classifications include this value
547
+ * includeSqlInAudit?: boolean, // emit SQL text in audit metadata (off by default — may carry literal PII)
548
+ *
549
+ * @example
550
+ * var res = await b.externalDb.query(
551
+ * "SELECT id, email FROM users WHERE tenant_id = $1",
552
+ * ["acme"],
553
+ * { classification: "personal" }
554
+ * );
555
+ * res.rowCount; // → 42
556
+ * res.rows[0]; // → { id: 1, email: "ada@example.com" }
557
+ */
558
+ async function query(sql, params, opts) {
559
+ _requireInit();
560
+ opts = opts || {};
561
+ var b = _pickBackend(opts);
562
+ var role = dbRoleContext.getRole();
563
+
564
+ var t0 = Date.now();
565
+ try {
566
+ var result = await retryHelper.withRetry(function () {
567
+ return b.breaker.wrap(async function () {
568
+ var client = await b.pool.acquire();
569
+ try {
570
+ var res = await b.query(client, sql, params || []);
571
+ b.pool.release(client);
572
+ return res;
573
+ } catch (e) {
574
+ // Connection-level errors → destroy the client; query errors →
575
+ // release back to the pool. Heuristic: any error with a code
576
+ // looking like a network/connection issue → destroy.
577
+ if (e && (e.code === "ECONNRESET" || e.code === "ECONNREFUSED" ||
578
+ e.code === "ETIMEDOUT" || e.code === "ENOTFOUND" ||
579
+ e.code === "EPIPE")) {
580
+ await b.pool.destroy(client);
581
+ } else {
582
+ b.pool.release(client);
583
+ }
584
+ throw e;
585
+ }
586
+ });
587
+ }, b.retryConfig);
588
+
589
+ var durationMs = Date.now() - t0;
590
+ _emit("system.externaldb.query", "success", {
591
+ backend: b.name,
592
+ role: role,
593
+ durationMs: durationMs,
594
+ classification: opts.classification || null,
595
+ rowCount: result && result.rowCount,
596
+ // SQL is NOT logged by default — may contain sensitive literal values
597
+ // even in parameterized queries. Operators who want SQL in audit
598
+ // metadata pass opts.includeSqlInAudit: true (then sealed via
599
+ // field-crypto on the audit row).
600
+ sql: opts.includeSqlInAudit ? sql : null,
601
+ });
602
+ _emitMetric("externaldb.query.success", 1,
603
+ { backend: b.name, role: role || "(none)" });
604
+ _emitMetric("externaldb.query.duration_ms", durationMs,
605
+ { backend: b.name, role: role || "(none)" });
606
+ _emitSlowQuery(b.name, role, durationMs, _classifyStatement(sql));
607
+ return result;
608
+ } catch (e) {
609
+ var failureMs = Date.now() - t0;
610
+ _emit("system.externaldb.query", "failure", {
611
+ backend: b.name,
612
+ role: role,
613
+ durationMs: failureMs,
614
+ classification: opts.classification || null,
615
+ errorCode: e.code || null,
616
+ }, (e && e.message) || String(e));
617
+ _emitMetric("externaldb.query.failure", 1,
618
+ { backend: b.name, role: role || "(none)", errorCode: e.code || "(none)" });
619
+ _emitSlowQuery(b.name, role, failureMs, _classifyStatement(sql));
620
+ // Postgres signals authorization-denied as SQLSTATE 42501
621
+ // (insufficient_privilege). RLS-shaped writes that violate a
622
+ // policy and GRANT-denied SELECTs both surface this code. The
623
+ // operator's role-views recipe relies on this signal: a row of
624
+ // db.role.denied means a request-time role attempted something its
625
+ // grant or RLS policy forbids — the highest-signal compliance event
626
+ // the externalDb layer can emit.
627
+ if (e && e.code === "42501") {
628
+ _emitMetric("db.role.denied", 1,
629
+ { backend: b.name, role: role || "(none)" });
630
+ }
631
+ // D-M2 — DB-auth audit visibility. Every 28000 / 28P01 / 42501
632
+ // surfaces an auditable db.auth.failed row tagged with the SQL
633
+ // identity and the statement class so SOC2 reviewers can
634
+ // reconstruct the denial timeline.
635
+ _emitAuthFailureAudit(b, role, sql, e);
636
+ throw e;
637
+ }
638
+ }
639
+
640
+ /**
641
+ * @primitive b.externalDb.transaction
642
+ * @signature b.externalDb.transaction(fn, opts)
643
+ * @since 0.4.0
644
+ * @related b.externalDb.query, b.externalDb.write.query
645
+ *
646
+ * Run `fn(tx)` inside a transaction on the picked backend. Wraps the
647
+ * body in `BEGIN` / `COMMIT` / `ROLLBACK` via the backend's hooks;
648
+ * commits on resolve, rolls back on throw. Transient deadlock /
649
+ * serialization failures (Postgres SQLSTATE `40P01` / `40001`) retry
650
+ * automatically with a small jittered backoff (default 3 attempts;
651
+ * tune via `opts.deadlockRetries`).
652
+ *
653
+ * `tx.query(sql, params)` runs against the same client used by
654
+ * `BEGIN`, so RLS state set by `sessionGucs` (`SET LOCAL`) applies for
655
+ * the duration of the transaction and resets at COMMIT/ROLLBACK.
656
+ *
657
+ * @opts
658
+ * backend?: string, // explicit backend name
659
+ * classification?: string, // route by data class
660
+ * sessionGucs?: { [name]: string|number|boolean }, // SET LOCAL bindings (e.g. { "app.tenant_id": "acme" })
661
+ * statementTimeoutMs?: number, // SET LOCAL statement_timeout
662
+ * idleInTransactionTimeoutMs?: number, // SET LOCAL idle_in_transaction_session_timeout
663
+ * deadlockRetries?: number, // retries for 40P01 / 40001 (default 3)
664
+ *
665
+ * @example
666
+ * var summary = await b.externalDb.transaction(async function (tx) {
667
+ * await tx.query("INSERT INTO orders(id, total) VALUES ($1, $2)", ["o-1", 4200]);
668
+ * await tx.query("UPDATE inventory SET qty = qty - 1 WHERE sku = $1", ["sku-7"]);
669
+ * var res = await tx.query("SELECT count(*) AS n FROM orders WHERE id = $1", ["o-1"]);
670
+ * return res.rows[0];
671
+ * }, {
672
+ * classification: "operational",
673
+ * sessionGucs: { "app.tenant_id": "acme" },
674
+ * statementTimeoutMs: 5000,
675
+ * });
676
+ * summary.n; // → 1
677
+ */
678
+ async function transaction(fn, opts) {
679
+ _requireInit();
680
+ if (typeof fn !== "function") throw _err("INVALID_FN", "transaction requires a function", true);
681
+ opts = opts || {};
682
+ var b = _pickBackend(opts);
683
+ var role = dbRoleContext.getRole();
684
+
685
+ // sessionGucs — per-transaction `SET LOCAL "name" = value` plumbing.
686
+ // Each name validates as a SQL identifier (Postgres GUC names follow
687
+ // the same NAMEDATALEN-shaped rules; dotted GUCs like 'app.tenant_id'
688
+ // validate per-segment via quoteQualified). Values are emitted as SQL
689
+ // string literals (single-quote escaped) for strings, raw for finite
690
+ // numbers. SET LOCAL ties the binding to the surrounding transaction
691
+ // so the tenant_id used by RLS policies resets cleanly at
692
+ // COMMIT/ROLLBACK without caller cleanup.
693
+ var prebuiltGucs = _buildSessionGucsStatements(opts.sessionGucs);
694
+
695
+ var t0 = Date.now();
696
+ // D-H4 — per-statement timeout. SET LOCAL statement_timeout binds
697
+ // the query-cancel ceiling to this transaction; D-M7 wires
698
+ // idle_in_transaction_session_timeout from the same opt. Both
699
+ // emit at SET LOCAL scope so the next pool checkout starts clean.
700
+ var stmtTimeoutMs = opts.statementTimeoutMs;
701
+ var idleTimeoutMs = opts.idleInTransactionTimeoutMs;
702
+ // D-M8 — deadlock-retry policy. 40P01 (deadlock_detected) and 40001
703
+ // (serialization_failure) are transient — retry with capped attempts
704
+ // and a small jittered backoff. Operators tune retries via opts.deadlockRetries (default 3).
705
+ // numeric-bounds doesn't have a non-negative-int helper; use a
706
+ // direct check with allow marker (zero is permitted to disable
707
+ // retries entirely).
708
+ if (opts.deadlockRetries !== undefined) {
709
+ if (typeof opts.deadlockRetries !== "number" || !isFinite(opts.deadlockRetries) ||
710
+ opts.deadlockRetries < 0 || (opts.deadlockRetries | 0) !== opts.deadlockRetries) {
711
+ throw _err("INVALID_OPT",
712
+ "transaction: opts.deadlockRetries must be a non-negative integer");
713
+ }
714
+ }
715
+ var maxRetries = (typeof opts.deadlockRetries === "number")
716
+ ? Math.floor(opts.deadlockRetries) : 3; // allow:numeric-opt-Infinity
717
+ return await b.breaker.wrap(async function () {
718
+ var client = await b.pool.acquire();
719
+ var txClient = {
720
+ query: function (sql, params) { return b.query(client, sql, params || []); },
721
+ };
722
+ var committed = false;
723
+ var attempt = 0;
724
+ try {
725
+ for (;;) {
726
+ attempt += 1;
727
+ committed = false;
728
+ try {
729
+ await b.beginTx(client);
730
+ if (typeof stmtTimeoutMs === "number" && isFinite(stmtTimeoutMs) && stmtTimeoutMs > 0) {
731
+ await b.query(client, "SET LOCAL statement_timeout = " + Math.floor(stmtTimeoutMs), []);
732
+ }
733
+ if (typeof idleTimeoutMs === "number" && isFinite(idleTimeoutMs) && idleTimeoutMs > 0) {
734
+ await b.query(client, "SET LOCAL idle_in_transaction_session_timeout = " + Math.floor(idleTimeoutMs), []);
735
+ }
736
+ for (var gi = 0; gi < prebuiltGucs.length; gi++) {
737
+ await b.query(client, prebuiltGucs[gi], []);
738
+ }
739
+ var result = await fn(txClient);
740
+ await b.commit(client);
741
+ committed = true;
742
+ var durationMs = Date.now() - t0;
743
+ _emit("system.externaldb.transaction", "success", {
744
+ backend: b.name, role: role, durationMs: durationMs,
745
+ classification: opts.classification || null,
746
+ });
747
+ _emitMetric("externaldb.transaction.success", 1,
748
+ { backend: b.name, role: role || "(none)" });
749
+ _emitMetric("externaldb.transaction.duration_ms", durationMs,
750
+ { backend: b.name, role: role || "(none)" });
751
+ return result;
752
+ } catch (txErr) {
753
+ try { if (!committed) await b.rollback(client); } catch (_e) { /* best-effort */ }
754
+ var isTransient = txErr && (txErr.code === "40P01" || txErr.code === "40001");
755
+ if (isTransient && attempt <= maxRetries) {
756
+ _emitMetric("externaldb.transaction.retry", 1,
757
+ { backend: b.name, code: txErr.code, attempt: String(attempt) });
758
+ var jitter = bCrypto.randomInt(0, 6); // allow:raw-byte-literal — 0-5ms jitter
759
+ await safeAsync.sleep(attempt * 5 + jitter); // allow:raw-time-literal — sub-second backoff
760
+ continue;
761
+ }
762
+ var failureMs = Date.now() - t0;
763
+ _emit("system.externaldb.transaction", "failure", {
764
+ backend: b.name, role: role, durationMs: failureMs,
765
+ classification: opts.classification || null,
766
+ errorCode: txErr.code || null,
767
+ }, (txErr && txErr.message) || String(txErr));
768
+ _emitMetric("externaldb.transaction.failure", 1,
769
+ { backend: b.name, role: role || "(none)", errorCode: txErr.code || "(none)" });
770
+ if (txErr && txErr.code === "42501") {
771
+ _emitMetric("db.role.denied", 1,
772
+ { backend: b.name, role: role || "(none)" });
773
+ }
774
+ // D-M2 — DB-auth audit visibility on transaction-shaped denials.
775
+ // Statement class always reads as "TX" since the failure
776
+ // surface inside a transaction body could be any statement;
777
+ // operators correlate via the transaction's audit row.
778
+ _emitAuthFailureAudit(b, role, "BEGIN", txErr);
779
+ throw txErr;
780
+ }
781
+ }
782
+ } finally {
783
+ b.pool.release(client);
784
+ }
785
+ });
786
+ }
787
+
788
+ /**
789
+ * @primitive b.externalDb.healthCheck
790
+ * @signature b.externalDb.healthCheck(backendName)
791
+ * @since 0.4.0
792
+ * @related b.externalDb.listBackends, b.externalDb.shutdown
793
+ *
794
+ * Ping a backend by acquiring a client and running its `ping` hook (or
795
+ * `SELECT 1` when none is supplied). Returns `{ ok, breakerState, pool }`
796
+ * for a single backend, or a `{ [name]: result }` map when called with
797
+ * no argument. Connection-shape errors destroy the client; the breaker
798
+ * state is reflected in the returned record so health endpoints can
799
+ * surface circuit-open conditions.
800
+ *
801
+ * @example
802
+ * var all = await b.externalDb.healthCheck();
803
+ * all.main.ok; // → true
804
+ * all.main.breakerState; // → "closed"
805
+ * all.main.pool; // → { idle: 1, active: 0, waiters: 0 }
806
+ *
807
+ * var one = await b.externalDb.healthCheck("main");
808
+ * one.ok; // → true
809
+ */
810
+ async function healthCheck(backendName) {
811
+ _requireInit();
812
+ if (backendName) {
813
+ return _pingBackend(backends[backendName]);
814
+ }
815
+ var out = {};
816
+ for (var name in backends) {
817
+ out[name] = await _pingBackend(backends[name]);
818
+ }
819
+ return out;
820
+ }
821
+
822
+ async function _pingBackend(b) {
823
+ if (!b) return { ok: false, error: "unknown backend" };
824
+ try {
825
+ var client = await b.pool.acquire();
826
+ try {
827
+ if (b.ping) await b.ping(client);
828
+ else await b.query(client, "SELECT 1", []);
829
+ b.pool.release(client);
830
+ return { ok: true, breakerState: b.breaker.getState(), pool: b.pool.stats() };
831
+ } catch (e) {
832
+ await b.pool.destroy(client);
833
+ return { ok: false, error: e.message, breakerState: b.breaker.getState() };
834
+ }
835
+ } catch (e) {
836
+ return { ok: false, error: e.message, breakerState: b.breaker.getState() };
837
+ }
838
+ }
839
+
840
+ /**
841
+ * @primitive b.externalDb.listBackends
842
+ * @signature b.externalDb.listBackends()
843
+ * @since 0.4.0
844
+ * @related b.externalDb.healthCheck, b.externalDb.init
845
+ *
846
+ * Snapshot every registered backend's name, dialect, classifications,
847
+ * residency tag, breaker state, and live pool stats. Returns `[]` when
848
+ * `init()` has not run. Cheap — does not open any new connections.
849
+ *
850
+ * @example
851
+ * var rows = b.externalDb.listBackends();
852
+ * rows[0].name; // → "main"
853
+ * rows[0].dialect; // → "postgres"
854
+ * rows[0].classifications; // → ["personal", "operational"]
855
+ * rows[0].residencyTag; // → "EU"
856
+ * rows[0].breakerState; // → "closed"
857
+ * rows[0].pool; // → { idle: 2, active: 0, waiters: 0 }
858
+ */
859
+ function listBackends() {
860
+ if (!initialized) return [];
861
+ return Object.keys(backends).map(function (name) {
862
+ var b = backends[name];
863
+ return {
864
+ name: name,
865
+ dialect: b.dialect,
866
+ classifications: b.classifications.slice(),
867
+ residencyTag: b.residencyTag,
868
+ breakerState: b.breaker.getState(),
869
+ pool: b.pool.stats(),
870
+ };
871
+ });
872
+ }
873
+
874
+ /**
875
+ * @primitive b.externalDb.shutdown
876
+ * @signature b.externalDb.shutdown()
877
+ * @since 0.4.0
878
+ * @related b.externalDb.init, b.externalDb.healthCheck
879
+ *
880
+ * Drain every backend pool (and replica pool), close idle clients,
881
+ * then clear all registry state so a subsequent `init()` starts from
882
+ * scratch. Idempotent — calling before `init()` is a no-op. Wire to
883
+ * `b.appShutdown` so process exit waits for in-flight queries to
884
+ * release their clients.
885
+ *
886
+ * @example
887
+ * process.on("SIGTERM", async function () {
888
+ * await b.externalDb.shutdown();
889
+ * process.exit(0);
890
+ * });
891
+ */
892
+ async function shutdown() {
893
+ if (!initialized) return;
894
+ for (var name in backends) {
895
+ try { await backends[name].pool.drain(); } catch (_e) { /* best effort */ }
896
+ var bk = backends[name];
897
+ if (bk && bk.replicas) {
898
+ for (var i = 0; i < bk.replicas.length; i++) {
899
+ try { await bk.replicas[i].pool.drain(); } catch (_e) { /* best effort */ }
900
+ }
901
+ }
902
+ }
903
+ backends = {};
904
+ defaultBackend = null;
905
+ initialized = false;
906
+ }
907
+
908
+ // Build the SET LOCAL statements for a transaction's sessionGucs map.
909
+ // Identifier-validates each GUC name (per dot-segment so dotted names
910
+ // like 'app.tenant_id' work), quotes them with the Postgres dialect,
911
+ // and renders the value as either a SQL string literal (single-quoted,
912
+ // embedded quotes doubled) or a numeric literal for finite numbers.
913
+ // Bad shapes throw at the call site rather than as a confused Postgres
914
+ // error mid-transaction.
915
+ function _buildSessionGucsStatements(sessionGucs) {
916
+ if (sessionGucs === undefined || sessionGucs === null) return [];
917
+ if (typeof sessionGucs !== "object" || Array.isArray(sessionGucs)) {
918
+ throw _err("INVALID_SESSION_GUCS",
919
+ "sessionGucs must be an object map of name → value", true);
920
+ }
921
+ var out = [];
922
+ for (var name in sessionGucs) {
923
+ if (!Object.prototype.hasOwnProperty.call(sessionGucs, name)) continue;
924
+ if (typeof name !== "string" || name.length === 0) {
925
+ throw _err("INVALID_SESSION_GUCS",
926
+ "sessionGucs: GUC name must be a non-empty string", true);
927
+ }
928
+ // Validate per-segment so dotted GUCs (Postgres custom GUC class.
929
+ // setting form) pass. quoteQualified handles both the validation
930
+ // and the dot-quoted rendering.
931
+ var qName;
932
+ try {
933
+ qName = safeSql.quoteQualified(name, "postgres");
934
+ } catch (e) {
935
+ throw _err("INVALID_SESSION_GUCS",
936
+ "sessionGucs: name '" + name + "' is not a valid identifier: " +
937
+ ((e && e.message) || String(e)), true);
938
+ }
939
+ var value = sessionGucs[name];
940
+ var literal;
941
+ if (typeof value === "number" && isFinite(value)) {
942
+ literal = String(value);
943
+ } else if (typeof value === "boolean") {
944
+ // Postgres SET accepts on/off/true/false — render true/false.
945
+ literal = value ? "true" : "false";
946
+ } else if (typeof value === "string") {
947
+ // Cap the value length so an operator-controlled tenant_id of
948
+ // 100 KB doesn't hit Postgres' SET LOCAL parser with payload
949
+ // that bloats query logs and consumes max_stack_depth. The cap
950
+ // is generous for legitimate tenant identifiers but rejects
951
+ // amplification.
952
+ if (value.length > C.BYTES.kib(4)) {
953
+ throw _err("INVALID_SESSION_GUCS",
954
+ "sessionGucs['" + name + "']: value exceeds 4 KiB cap (got " +
955
+ value.length + " chars)", true);
956
+ }
957
+ literal = "'" + value.replace(/'/g, "''") + "'";
958
+ } else if (value === null || value === undefined) {
959
+ throw _err("INVALID_SESSION_GUCS",
960
+ "sessionGucs['" + name + "']: value must be a string, finite number, or boolean (got " +
961
+ (value === null ? "null" : "undefined") + ")", true);
962
+ } else {
963
+ throw _err("INVALID_SESSION_GUCS",
964
+ "sessionGucs['" + name + "']: value must be a string, finite number, or boolean (got " +
965
+ typeof value + ")", true);
966
+ }
967
+ out.push("SET LOCAL " + qName + " = " + literal);
968
+ }
969
+ return out;
970
+ }
971
+
972
+ // Fire-and-forget audit emission. We CANNOT await this in cluster mode:
973
+ // audit storage routes back through external-db when cluster mode is
974
+ // active, so awaiting would create a recursive dependency (every audit
975
+ // row insert triggers an external-db query which would await another
976
+ // audit row insert). Tests that need audit-row durability before reading
977
+ // audit_log should flush microtasks explicitly.
978
+ function _emit(action, outcome, metadata, reason) {
979
+ audit().safeEmit({ action: action, outcome: outcome, reason: reason, metadata: metadata });
980
+ }
981
+
982
+ function _requireInit() {
983
+ if (!initialized) throw _err("NOT_INITIALIZED", "externalDb.init() must be called first", true);
984
+ }
985
+
986
+ // ---- Read-replica routing ----
987
+ //
988
+ // Operators with a primary + replicas declare replicas alongside the
989
+ // primary backend config:
990
+ //
991
+ // externalDb.init({
992
+ // backends: {
993
+ // main: {
994
+ // connect, query, // primary
995
+ // replicas: [
996
+ // { connect: replica1, query, weight: 1 },
997
+ // { connect: replica2, query, weight: 2 },
998
+ // ],
999
+ // replicaFallbackToPrimary: true, // default; on all-replicas-unhealthy,
1000
+ // // read.query falls back to primary
1001
+ // },
1002
+ // },
1003
+ // });
1004
+ //
1005
+ // await externalDb.read.query("SELECT * FROM users"); // → replica
1006
+ // await externalDb.write.query("INSERT INTO users ..."); // → primary
1007
+ // await externalDb.query("..."); // → primary (legacy, unchanged)
1008
+ //
1009
+ // Load balancing: weighted round-robin (default weight 1). Weights
1010
+ // expand into a static plan at init — a [w1, w2, w3] vector becomes a
1011
+ // pre-built index sequence, then read.query() advances replicaIdx.
1012
+ //
1013
+ // Health: each replica tracks `lastFailureAt`. After UNHEALTHY_COOLDOWN_MS
1014
+ // since the last failure, the replica re-enters the rotation. Operators
1015
+ // observing all-replicas-down see read.query() fall back to primary
1016
+ // (overridable via replicaFallbackToPrimary: false).
1017
+
1018
+ var REPLICA_UNHEALTHY_COOLDOWN_MS = C.TIME.seconds(30);
1019
+
1020
+ // F-CBT-2 — replica residency-tag compatibility.
1021
+ //
1022
+ // A primary tagged "EU" replicating to a "US" replica is a GDPR
1023
+ // Article 46 cross-border transfer; without an explicit operator
1024
+ // opt-in the framework refuses init under gdpr / dpdp / pipl-cn /
1025
+ // uk-gdpr postures. Operator suppresses the gate per replica via
1026
+ // allowCrossBorder: true (which the framework records in the audit
1027
+ // chain so a compliance reviewer sees the conscious decision).
1028
+ //
1029
+ // Compatible-residency rules:
1030
+ // - Identical tags (EU↔EU, US↔US): always compatible.
1031
+ // - "unrestricted" tag on either side: compatible (operator
1032
+ // declared no constraint).
1033
+ // - Different tags: compatible only when allowCrossBorder is true.
1034
+ var CROSS_BORDER_REGULATED_POSTURES = Object.freeze([
1035
+ "gdpr", "uk-gdpr", "dpdp", "pipl-cn", "lgpd-br", "appi-jp", "pdpa-sg",
1036
+ ]);
1037
+
1038
+ function _residencyCompatible(primaryTag, replicaTag) {
1039
+ if (!primaryTag || !replicaTag) return true;
1040
+ if (primaryTag === replicaTag) return true; // allow:raw-hash-compare — residency tag string, not a secret hash
1041
+ if (primaryTag === "unrestricted" || replicaTag === "unrestricted") return true;
1042
+ return false;
1043
+ }
1044
+
1045
+ function _activePosture() {
1046
+ try {
1047
+ var compliance = require("./compliance"); // allow:inline-require — defensive against optional load
1048
+ return compliance.current();
1049
+ } catch (_e) { return null; }
1050
+ }
1051
+
1052
+ function _buildReplicas(backendName, cfg) {
1053
+ if (!cfg.replicas) return null;
1054
+ if (!Array.isArray(cfg.replicas) || cfg.replicas.length === 0) {
1055
+ throw _err("INVALID_CONFIG",
1056
+ "backend '" + backendName + "': replicas must be a non-empty array", true);
1057
+ }
1058
+ var primaryTag = cfg.residencyTag || "unrestricted";
1059
+ var posture = _activePosture();
1060
+ var out = [];
1061
+ for (var i = 0; i < cfg.replicas.length; i++) {
1062
+ var r = cfg.replicas[i];
1063
+ if (!r || typeof r.connect !== "function") {
1064
+ throw _err("INVALID_CONFIG",
1065
+ "backend '" + backendName + "': replicas[" + i + "].connect must be a function", true);
1066
+ }
1067
+ if (typeof r.query !== "function") {
1068
+ throw _err("INVALID_CONFIG",
1069
+ "backend '" + backendName + "': replicas[" + i + "].query must be a function", true);
1070
+ }
1071
+ var weight = r.weight !== undefined ? r.weight : 1;
1072
+ if (typeof weight !== "number" || !isFinite(weight) || weight <= 0 ||
1073
+ Math.floor(weight) !== weight) {
1074
+ throw _err("INVALID_CONFIG",
1075
+ "backend '" + backendName + "': replicas[" + i + "].weight must be a positive integer", true);
1076
+ }
1077
+ var replicaTag = r.residencyTag || "unrestricted";
1078
+ var allowCrossBorder = r.allowCrossBorder === true;
1079
+ if (!_residencyCompatible(primaryTag, replicaTag) && !allowCrossBorder) {
1080
+ var underPosture = posture && CROSS_BORDER_REGULATED_POSTURES.indexOf(posture) !== -1;
1081
+ throw _err("RESIDENCY_MISMATCH",
1082
+ "backend '" + backendName + "': replica[" + i +
1083
+ "] residencyTag '" + replicaTag +
1084
+ "' is not compatible with primary residencyTag '" + primaryTag +
1085
+ "'" + (underPosture ? " under '" + posture + "' posture" : "") +
1086
+ ". This is a cross-border data transfer (GDPR Art 46 / DPDP / PIPL " +
1087
+ "category). Pass allowCrossBorder: true on the replica config with a " +
1088
+ "documented legal basis (SCCs / BCRs / adequacy decision) to suppress.", true);
1089
+ }
1090
+ if (!_residencyCompatible(primaryTag, replicaTag) && allowCrossBorder) {
1091
+ _emit("externalDb.replica.cross_border_allowed", "warning",
1092
+ { backend: backendName, replicaIndex: i,
1093
+ primaryTag: primaryTag, replicaTag: replicaTag,
1094
+ legalBasis: r.legalBasis || null,
1095
+ posture: posture || null });
1096
+ }
1097
+ out.push({
1098
+ index: i,
1099
+ pool: new Pool(backendName + ":replica:" + i, r),
1100
+ query: r.query,
1101
+ weight: weight,
1102
+ residencyTag: replicaTag,
1103
+ allowCrossBorder: allowCrossBorder,
1104
+ lastFailureAt: 0,
1105
+ consecutiveFailures: 0,
1106
+ });
1107
+ }
1108
+ return out;
1109
+ }
1110
+
1111
+ function _pickReplica(b) {
1112
+ if (!b.replicas || b.replicas.length === 0) return null;
1113
+ var now = Date.now();
1114
+ // Build a healthy candidate set.
1115
+ var healthy = [];
1116
+ for (var i = 0; i < b.replicas.length; i++) {
1117
+ var r = b.replicas[i];
1118
+ if (now - r.lastFailureAt >= REPLICA_UNHEALTHY_COOLDOWN_MS) healthy.push(r);
1119
+ }
1120
+ if (healthy.length === 0) return null;
1121
+ // Weighted round-robin: walk by weight, advancing replicaIdx by 1 each
1122
+ // call and modding by total weight. Each replica's "slot" in the
1123
+ // sequence repeats `weight` times.
1124
+ var totalWeight = 0;
1125
+ for (var w = 0; w < healthy.length; w++) totalWeight += healthy[w].weight;
1126
+ var cursor = (b.replicaIdx++) % totalWeight;
1127
+ var acc = 0;
1128
+ for (var c = 0; c < healthy.length; c++) {
1129
+ acc += healthy[c].weight;
1130
+ if (cursor < acc) return healthy[c];
1131
+ }
1132
+ return healthy[0]; // unreachable; defensive
1133
+ }
1134
+
1135
+ async function _readQuery(sql, params, opts) {
1136
+ _requireInit();
1137
+ opts = opts || {};
1138
+ var b = _pickBackend(opts);
1139
+ if (!b.replicas || b.replicas.length === 0) {
1140
+ // No replicas configured — read.query() returns primary.
1141
+ return query(sql, params, opts);
1142
+ }
1143
+ var replica = _pickReplica(b);
1144
+ if (!replica) {
1145
+ if (b.replicaFallbackToPrimary) return query(sql, params, opts);
1146
+ throw _err("ALL_REPLICAS_UNHEALTHY",
1147
+ "backend '" + b.name + "': all replicas unhealthy and fallback disabled", true);
1148
+ }
1149
+ var role = dbRoleContext.getRole();
1150
+ var t0 = Date.now();
1151
+ try {
1152
+ var client = await replica.pool.acquire();
1153
+ try {
1154
+ var res = await replica.query(client, sql, params || []);
1155
+ replica.pool.release(client);
1156
+ replica.consecutiveFailures = 0;
1157
+ var durationMs = Date.now() - t0;
1158
+ _emit("system.externaldb.read", "success", {
1159
+ backend: b.name,
1160
+ role: role,
1161
+ replicaIdx: replica.index,
1162
+ durationMs: durationMs,
1163
+ rowCount: res && res.rowCount,
1164
+ });
1165
+ _emitMetric("externaldb.read.success", 1,
1166
+ { backend: b.name, role: role || "(none)", replicaIdx: replica.index });
1167
+ _emitMetric("externaldb.read.duration_ms", durationMs,
1168
+ { backend: b.name, role: role || "(none)", replicaIdx: replica.index });
1169
+ return res;
1170
+ } catch (e) {
1171
+ // Connection-shape errors mark unhealthy + destroy.
1172
+ if (e && (e.code === "ECONNRESET" || e.code === "ECONNREFUSED" ||
1173
+ e.code === "ETIMEDOUT" || e.code === "ENOTFOUND" ||
1174
+ e.code === "EPIPE")) {
1175
+ await replica.pool.destroy(client);
1176
+ replica.lastFailureAt = Date.now();
1177
+ replica.consecutiveFailures += 1;
1178
+ } else {
1179
+ replica.pool.release(client);
1180
+ }
1181
+ throw e;
1182
+ }
1183
+ } catch (e) {
1184
+ _emit("system.externaldb.read", "failure", {
1185
+ backend: b.name,
1186
+ role: role,
1187
+ replicaIdx: replica.index,
1188
+ durationMs: Date.now() - t0,
1189
+ errorCode: e.code || null,
1190
+ }, (e && e.message) || String(e));
1191
+ _emitMetric("externaldb.read.failure", 1,
1192
+ { backend: b.name, role: role || "(none)", errorCode: e.code || "(none)" });
1193
+ if (e && e.code === "42501") {
1194
+ _emitMetric("db.role.denied", 1,
1195
+ { backend: b.name, role: role || "(none)" });
1196
+ }
1197
+ // D-M2 — DB-auth audit visibility for read-replica denials too.
1198
+ _emitAuthFailureAudit(b, role, sql, e);
1199
+ // Fallback to primary on a failed replica read when allowed.
1200
+ if (b.replicaFallbackToPrimary) {
1201
+ return query(sql, params, opts);
1202
+ }
1203
+ throw e;
1204
+ }
1205
+ }
1206
+
1207
+ /**
1208
+ * @primitive b.externalDb.read.query
1209
+ * @signature b.externalDb.read.query(sql, params, opts)
1210
+ * @since 0.4.0
1211
+ * @related b.externalDb.write.query, b.externalDb.query, b.externalDb.init
1212
+ *
1213
+ * Route a read against the backend's declared replicas using weighted
1214
+ * round-robin. A failed replica is sidelined for 30 seconds and the
1215
+ * call falls back to primary when `replicaFallbackToPrimary` is true
1216
+ * (the default). Backends without replicas transparently route to
1217
+ * primary. Same `opts` selection rules as `b.externalDb.query`
1218
+ * (`backend` / `classification` / ALS-bound role).
1219
+ *
1220
+ * @opts
1221
+ * backend?: string, // explicit backend name
1222
+ * classification?: string, // route by data class
1223
+ *
1224
+ * @example
1225
+ * var res = await b.externalDb.read.query(
1226
+ * "SELECT id, total FROM orders WHERE tenant_id = $1",
1227
+ * ["acme"],
1228
+ * { classification: "operational" }
1229
+ * );
1230
+ * res.rowCount; // → 7
1231
+ * res.rows[0]; // → { id: "o-1", total: 4200 }
1232
+ */
1233
+ var read = {
1234
+ query: _readQuery,
1235
+ };
1236
+
1237
+ /**
1238
+ * @primitive b.externalDb.write.query
1239
+ * @signature b.externalDb.write.query(sql, params, opts)
1240
+ * @since 0.4.0
1241
+ * @related b.externalDb.read.query, b.externalDb.query, b.externalDb.write.transaction
1242
+ *
1243
+ * Symmetric alias for `b.externalDb.query` — always routes to primary.
1244
+ * Pair with `b.externalDb.read.query` when an operator wants the call
1245
+ * site to express read/write intent without a magic-comment hint.
1246
+ * Same `opts` selection rules as `b.externalDb.query`.
1247
+ *
1248
+ * @opts
1249
+ * backend?: string, // explicit backend name
1250
+ * classification?: string, // route by data class
1251
+ * includeSqlInAudit?: boolean, // emit SQL text in audit metadata
1252
+ *
1253
+ * @example
1254
+ * var res = await b.externalDb.write.query(
1255
+ * "INSERT INTO orders(id, tenant_id, total) VALUES ($1, $2, $3)",
1256
+ * ["o-2", "acme", 1500],
1257
+ * { classification: "operational" }
1258
+ * );
1259
+ * res.rowCount; // → 1
1260
+ */
1261
+ /**
1262
+ * @primitive b.externalDb.write.transaction
1263
+ * @signature b.externalDb.write.transaction(fn, opts)
1264
+ * @since 0.4.0
1265
+ * @related b.externalDb.transaction, b.externalDb.write.query
1266
+ *
1267
+ * Symmetric alias for `b.externalDb.transaction` — always runs against
1268
+ * primary. Same `opts` shape (sessionGucs / statementTimeoutMs /
1269
+ * idleInTransactionTimeoutMs / deadlockRetries) as the canonical form.
1270
+ *
1271
+ * @opts
1272
+ * backend?: string,
1273
+ * classification?: string,
1274
+ * sessionGucs?: { [name]: string|number|boolean },
1275
+ * statementTimeoutMs?: number,
1276
+ * idleInTransactionTimeoutMs?: number,
1277
+ * deadlockRetries?: number,
1278
+ *
1279
+ * @example
1280
+ * var n = await b.externalDb.write.transaction(async function (tx) {
1281
+ * await tx.query("UPDATE counters SET n = n + 1 WHERE k = $1", ["hits"]);
1282
+ * var res = await tx.query("SELECT n FROM counters WHERE k = $1", ["hits"]);
1283
+ * return res.rows[0].n;
1284
+ * }, { sessionGucs: { "app.tenant_id": "acme" } });
1285
+ * typeof n; // → "number"
1286
+ */
1287
+ // write namespace — alias for the primary path. Lets operators express
1288
+ // intent symmetrically with read.query without a magic-comment hint.
1289
+ var write = {
1290
+ query: function (sql, params, opts) { return query(sql, params, opts); },
1291
+ transaction: function (fn, opts) { return transaction(fn, opts); },
1292
+ };
1293
+
1294
+ function _resetForTest() {
1295
+ Object.keys(backends).forEach(function (n) {
1296
+ try { backends[n].pool.drain(); }
1297
+ catch (e) { log.debug("test-reset pool drain failed", { backend: n, error: e.message }); }
1298
+ var bk = backends[n];
1299
+ if (bk && bk.replicas) {
1300
+ bk.replicas.forEach(function (r) {
1301
+ try { r.pool.drain(); }
1302
+ catch (e2) { log.debug("test-reset replica drain failed", { backend: n, error: e2.message }); }
1303
+ });
1304
+ }
1305
+ });
1306
+ backends = {};
1307
+ defaultBackend = null;
1308
+ dbRoleBackends = {};
1309
+ initialized = false;
1310
+ audit.reset();
1311
+ db.reset();
1312
+ }
1313
+
1314
+ // ---- configurePool — runtime resize of an existing backend's pool ----
1315
+ //
1316
+ // Operators tune pool sizing without restarting the app. Existing idle
1317
+ // clients are kept; new acquisitions respect the new max. min is honored
1318
+ // the next time the pool refills. idleTimeoutMs takes effect on the next
1319
+ // reaper tick.
1320
+ /**
1321
+ * @primitive b.externalDb.configurePool
1322
+ * @signature b.externalDb.configurePool(backendName, opts)
1323
+ * @since 0.4.0
1324
+ * @related b.externalDb.init, b.externalDb.listBackends
1325
+ *
1326
+ * Resize a registered backend's pool at runtime. New `max` takes effect
1327
+ * on the next acquire; existing idle clients are kept; `min` is honored
1328
+ * when the pool next refills; `idleTimeoutMs` applies on the next
1329
+ * reaper tick. Throws on unknown options or non-positive integers so a
1330
+ * config typo surfaces at the call site.
1331
+ *
1332
+ * @opts
1333
+ * min?: number, // positive integer; floor on idle clients
1334
+ * max?: number, // positive integer; ceiling on total clients (must be >= min)
1335
+ * idleTimeoutMs?: number, // positive integer; reap idle clients after this many ms
1336
+ *
1337
+ * @example
1338
+ * b.externalDb.configurePool("main", {
1339
+ * min: 4,
1340
+ * max: 50,
1341
+ * idleTimeoutMs: 120000,
1342
+ * });
1343
+ */
1344
+ function configurePool(backendName, opts) {
1345
+ _requireInit();
1346
+ if (typeof backendName !== "string" || backendName.length === 0) {
1347
+ throw _err("INVALID_CONFIG", "configurePool: backendName must be a non-empty string", true);
1348
+ }
1349
+ var bk = backends[backendName];
1350
+ if (!bk) throw _err("UNKNOWN_BACKEND", "configurePool: no backend named '" + backendName + "'", true);
1351
+ if (!opts || typeof opts !== "object") {
1352
+ throw _err("INVALID_CONFIG", "configurePool: opts must be an object", true);
1353
+ }
1354
+ var allowed = ["min", "max", "idleTimeoutMs"];
1355
+ for (var k in opts) {
1356
+ if (!Object.prototype.hasOwnProperty.call(opts, k)) continue;
1357
+ if (allowed.indexOf(k) === -1) {
1358
+ throw _err("INVALID_CONFIG",
1359
+ "configurePool: unknown option '" + k + "'. Allowed: " + allowed.join(", "), true);
1360
+ }
1361
+ }
1362
+ function _requirePosInt(name, value) {
1363
+ if (typeof value !== "number" || !isFinite(value) || value <= 0 || Math.floor(value) !== value) {
1364
+ throw _err("INVALID_CONFIG",
1365
+ "configurePool: " + name + " must be a positive integer, got " + JSON.stringify(value), true);
1366
+ }
1367
+ }
1368
+ if (opts.min !== undefined) _requirePosInt("min", opts.min);
1369
+ if (opts.max !== undefined) _requirePosInt("max", opts.max);
1370
+ if (opts.idleTimeoutMs !== undefined) _requirePosInt("idleTimeoutMs", opts.idleTimeoutMs);
1371
+ if (opts.min !== undefined && opts.max !== undefined && opts.min > opts.max) {
1372
+ throw _err("INVALID_CONFIG", "configurePool: min must be <= max", true);
1373
+ }
1374
+ Object.assign(bk.pool.config, opts);
1375
+ }
1376
+
1377
+ // ---- adapters.connectAs — Postgres role-aware connect wrapper ----
1378
+ //
1379
+ // Wraps an operator's connect() so that every fresh client runs
1380
+ // `SET ROLE`, `SET search_path`, `SET application_name`, and any other
1381
+ // operator-supplied GUCs at acquire time. The pattern enables the
1382
+ // search_path-views shape: the same SQL `SELECT * FROM sessions`
1383
+ // resolves to `public.sessions` for app_user and to
1384
+ // `analytics.sessions` (a view with PHI redacted) for analytics_user.
1385
+ // See the "Compliance Patterns" wiki page.
1386
+ //
1387
+ // Identifier inputs (role, schemas in searchPath) are validated via
1388
+ // safeSql.validateIdentifier — bad shapes throw at the call site. String
1389
+ // values (applicationName, statement_timeout) are quoted as SQL string
1390
+ // literals with single-quote escaping per the SQL standard.
1391
+ //
1392
+ // connect: b.externalDb.adapters.connectAs(rawConnect, {
1393
+ // role: "analytics_user",
1394
+ // searchPath: ["analytics", "public"],
1395
+ // applicationName: "wiki:analytics",
1396
+ // statementTimeoutMs: C.TIME.seconds(30),
1397
+ // gucs: {
1398
+ // idle_in_transaction_session_timeout: "60s",
1399
+ // },
1400
+ // })
1401
+ //
1402
+ // `query` is the same query function the backend declares; the wrapper
1403
+ // uses it to issue the SET statements.
1404
+ function _connectAs(rawConnect, query, opts) {
1405
+ if (typeof rawConnect !== "function") {
1406
+ throw _err("INVALID_CONFIG", "connectAs: connect must be a function", true);
1407
+ }
1408
+ if (typeof query !== "function") {
1409
+ throw _err("INVALID_CONFIG", "connectAs: query must be a function", true);
1410
+ }
1411
+ opts = opts || {};
1412
+ var allowed = ["role", "searchPath", "applicationName", "statementTimeoutMs", "gucs"];
1413
+ for (var k in opts) {
1414
+ if (!Object.prototype.hasOwnProperty.call(opts, k)) continue;
1415
+ if (allowed.indexOf(k) === -1) {
1416
+ throw _err("INVALID_CONFIG",
1417
+ "connectAs: unknown option '" + k + "'. Allowed: " + allowed.join(", "), true);
1418
+ }
1419
+ }
1420
+
1421
+ // Validate inputs at config time so a malformed name surfaces at
1422
+ // boot rather than on the first connection.
1423
+ if (opts.role !== undefined) {
1424
+ safeSql.validateIdentifier(String(opts.role), { allowReserved: false });
1425
+ }
1426
+ var pathSegments = null;
1427
+ if (opts.searchPath !== undefined) {
1428
+ var raw = Array.isArray(opts.searchPath) ? opts.searchPath : [opts.searchPath];
1429
+ if (raw.length === 0) {
1430
+ throw _err("INVALID_CONFIG", "connectAs: searchPath must have at least one schema", true);
1431
+ }
1432
+ pathSegments = [];
1433
+ for (var pi = 0; pi < raw.length; pi++) {
1434
+ safeSql.validateIdentifier(String(raw[pi]), { allowReserved: false });
1435
+ pathSegments.push(String(raw[pi]));
1436
+ }
1437
+ }
1438
+ if (opts.applicationName !== undefined && typeof opts.applicationName !== "string") {
1439
+ throw _err("INVALID_CONFIG", "connectAs: applicationName must be a string", true);
1440
+ }
1441
+ if (opts.statementTimeoutMs !== undefined) {
1442
+ if (typeof opts.statementTimeoutMs !== "number" || !isFinite(opts.statementTimeoutMs) ||
1443
+ opts.statementTimeoutMs <= 0 || Math.floor(opts.statementTimeoutMs) !== opts.statementTimeoutMs) {
1444
+ throw _err("INVALID_CONFIG",
1445
+ "connectAs: statementTimeoutMs must be a positive integer", true);
1446
+ }
1447
+ }
1448
+ if (opts.gucs !== undefined && (typeof opts.gucs !== "object" || opts.gucs === null)) {
1449
+ throw _err("INVALID_CONFIG", "connectAs: gucs must be an object", true);
1450
+ }
1451
+ if (opts.gucs) {
1452
+ for (var gname in opts.gucs) {
1453
+ // GUC names: Postgres NAMEDATALEN-shaped identifiers.
1454
+ safeSql.validateIdentifier(gname, { allowReserved: true });
1455
+ }
1456
+ }
1457
+
1458
+ // Pre-compute the SET statements once — every fresh client runs the
1459
+ // same list, so building it per-connect would burn microbenchmarks.
1460
+ var stmts = [];
1461
+ if (opts.role) {
1462
+ stmts.push('SET ROLE "' + opts.role + '"');
1463
+ }
1464
+ if (pathSegments) {
1465
+ var pathSql = pathSegments.map(function (s) { return '"' + s + '"'; }).join(", ");
1466
+ stmts.push("SET search_path TO " + pathSql);
1467
+ }
1468
+ if (opts.applicationName !== undefined) {
1469
+ // Single-quoted string literal — SQL-standard escape doubles embedded
1470
+ // single quotes.
1471
+ var an = String(opts.applicationName).replace(/'/g, "''");
1472
+ stmts.push("SET application_name TO '" + an + "'");
1473
+ }
1474
+ if (opts.statementTimeoutMs !== undefined) {
1475
+ stmts.push("SET statement_timeout TO " + opts.statementTimeoutMs);
1476
+ }
1477
+ if (opts.gucs) {
1478
+ for (var gn in opts.gucs) {
1479
+ var gv = opts.gucs[gn];
1480
+ if (typeof gv === "number") {
1481
+ // Numeric GUCs must be finite — Infinity / NaN serialize as
1482
+ // tokens that Postgres would reject at parse time, but only
1483
+ // AFTER the connection started using a half-set state. Refuse
1484
+ // at config-time instead.
1485
+ if (!isFinite(gv)) {
1486
+ throw _err("INVALID_CONFIG",
1487
+ "connectAs: gucs[" + gn + "] number must be finite (got " + gv + ")",
1488
+ true);
1489
+ }
1490
+ stmts.push('SET "' + gn + '" TO ' + gv);
1491
+ } else {
1492
+ var gvs = String(gv).replace(/'/g, "''");
1493
+ // Refuse embedded NUL / line breaks in GUC string values —
1494
+ // they have no legitimate use and would terminate the SET
1495
+ // statement early in some drivers.
1496
+ // eslint-disable-next-line no-control-regex
1497
+ if (/[\r\n\u0000]/.test(gvs)) {
1498
+ throw _err("INVALID_CONFIG",
1499
+ "connectAs: gucs[" + gn + "] string value must not contain NUL or newline characters",
1500
+ true);
1501
+ }
1502
+ stmts.push('SET "' + gn + '" TO \'' + gvs + "'");
1503
+ }
1504
+ }
1505
+ }
1506
+
1507
+ return async function wrappedConnect() {
1508
+ var client = await rawConnect();
1509
+ try {
1510
+ for (var i = 0; i < stmts.length; i++) {
1511
+ await query(client, stmts[i], []);
1512
+ }
1513
+ } catch (e) {
1514
+ // Initialization failed — the operator's close hook isn't visible
1515
+ // here, so we throw and let the pool's catch destroy the partial
1516
+ // client.
1517
+ throw e;
1518
+ }
1519
+ return client;
1520
+ };
1521
+ }
1522
+
1523
+ /**
1524
+ * @primitive b.externalDb.adapters.connectAs
1525
+ * @signature b.externalDb.adapters.connectAs(connect, opts)
1526
+ * @since 0.4.0
1527
+ * @related b.externalDb.init, b.externalDb.runAs
1528
+ *
1529
+ * Wrap a Postgres `connect` so every fresh client runs `SET ROLE`,
1530
+ * `SET search_path`, `SET application_name`, `SET statement_timeout`,
1531
+ * and any operator-supplied `gucs` before being handed to the pool.
1532
+ * Identifier inputs (role, schemas, GUC names) are validated via
1533
+ * `safeSql.validateIdentifier` at call time so a bad name throws once
1534
+ * at boot rather than per acquired client. Returns the wrapped
1535
+ * `connect` function suitable for a backend's `connect` hook.
1536
+ *
1537
+ * @opts
1538
+ * query: function, // required — the backend's query function (used to issue SET statements)
1539
+ * role?: string, // SQL identifier; runs SET ROLE "<role>"
1540
+ * searchPath?: string[], // SQL identifiers; runs SET search_path TO "<a>", "<b>", ...
1541
+ * applicationName?: string, // appears in pg_stat_activity
1542
+ * statementTimeoutMs?: number, // positive integer; SET statement_timeout TO <ms>
1543
+ * gucs?: { [name]: string|number }, // raw GUC bindings; finite numbers required for numeric values
1544
+ *
1545
+ * @example
1546
+ * var pg = require("pg");
1547
+ * var pool = new pg.Pool({ connectionString: "postgres://app:pw@db.example.com/app" });
1548
+ * var rawConnect = function () { return pool.connect(); };
1549
+ * var rawQuery = function (client, sql, params) { return client.query(sql, params); };
1550
+ *
1551
+ * b.externalDb.init({
1552
+ * backends: {
1553
+ * analytics: {
1554
+ * dialect: "postgres",
1555
+ * connect: b.externalDb.adapters.connectAs(rawConnect, {
1556
+ * query: rawQuery,
1557
+ * role: "analytics_user",
1558
+ * searchPath: ["analytics", "public"],
1559
+ * applicationName: "blamejs:analytics",
1560
+ * statementTimeoutMs: 30000,
1561
+ * gucs: { idle_in_transaction_session_timeout: "60s" },
1562
+ * }),
1563
+ * query: rawQuery,
1564
+ * },
1565
+ * },
1566
+ * });
1567
+ */
1568
+ // Operators import the helper as `b.externalDb.adapters.connectAs(connect, opts)`
1569
+ // — declarative wrapping with shared input validation.
1570
+ function _adaptersConnectAs(connect, opts) {
1571
+ // The backend's query function is needed to issue SET statements on a
1572
+ // freshly-acquired client. Operators pass it via opts.query — same
1573
+ // function they declare on the backend itself.
1574
+ if (!opts || typeof opts !== "object") {
1575
+ throw _err("INVALID_CONFIG",
1576
+ "adapters.connectAs: opts must be an object", true);
1577
+ }
1578
+ if (typeof opts.query !== "function") {
1579
+ throw _err("INVALID_CONFIG",
1580
+ "adapters.connectAs: opts.query is required (the backend's query function)", true);
1581
+ }
1582
+ // Pull query off and pass the remaining role-aware opts.
1583
+ var query = opts.query;
1584
+ var roleOpts = {};
1585
+ for (var k in opts) {
1586
+ if (Object.prototype.hasOwnProperty.call(opts, k) && k !== "query") {
1587
+ roleOpts[k] = opts[k];
1588
+ }
1589
+ }
1590
+ return _connectAs(connect, query, roleOpts);
1591
+ }
1592
+
1593
+ // ---- runAs / currentRole — out-of-request role binding ----
1594
+ //
1595
+ // Inside an HTTP request the dbRoleFor middleware already pushes the
1596
+ // role into the shared db-role-context ALS. Background workers (jobs,
1597
+ // schedulers, CLI commands) don't run under that middleware — they wrap
1598
+ // their work in runAs(role, fn) so the same backend-pick logic applies.
1599
+ //
1600
+ // await b.externalDb.runAs("analytics_user", async function () {
1601
+ // return await b.externalDb.read.query("SELECT ..."); // → analytics backend
1602
+ // });
1603
+ //
1604
+ // currentRole() returns the active role (or null) — useful for diagnostic
1605
+ // logs and observability labels.
1606
+ /**
1607
+ * @primitive b.externalDb.runAs
1608
+ * @signature b.externalDb.runAs(role, fn)
1609
+ * @since 0.4.0
1610
+ * @related b.externalDb.currentRole, b.externalDb.adapters.connectAs
1611
+ *
1612
+ * Bind a SQL role on the deep async-local context for the duration of
1613
+ * `fn()`. Every `b.externalDb.query` / `read.query` / `write.query` /
1614
+ * `transaction` call inside the bound region picks the backend mapped
1615
+ * to `role` via the `dbRoleBackends` map declared at `init()`, so
1616
+ * background workers (cron, queue consumers, CLI commands) get the
1617
+ * same role-aware routing as HTTP requests under
1618
+ * `b.middleware.dbRoleFor`. Pass `null` to clear. Audits role
1619
+ * transitions as `db.role.switched`. Identifier-validates the role at
1620
+ * the call site so a typo throws synchronously.
1621
+ *
1622
+ * @example
1623
+ * await b.externalDb.runAs("analytics_user", async function () {
1624
+ * var res = await b.externalDb.read.query(
1625
+ * "SELECT count(*) AS n FROM events WHERE day = $1",
1626
+ * ["2026-05-09"]
1627
+ * );
1628
+ * return res.rows[0].n;
1629
+ * });
1630
+ */
1631
+ function runAs(role, fn) {
1632
+ if (typeof fn !== "function") {
1633
+ throw _err("INVALID_FN", "externalDb.runAs: fn must be a function", true);
1634
+ }
1635
+ if (role !== null && role !== undefined) {
1636
+ if (typeof role !== "string" || role.length === 0) {
1637
+ throw _err("INVALID_ROLE",
1638
+ "externalDb.runAs: role must be a non-empty string or null", true);
1639
+ }
1640
+ safeSql.validateIdentifier(role, { allowReserved: false });
1641
+ }
1642
+ // Audit the role transition. runAs has no req, so the actor 5 W's
1643
+ // come from whatever the caller has bound on the audit-context ALS
1644
+ // (log.js requestId, plus any request-bound actor that was set in
1645
+ // an outer scope). Same audit shape as the dbRoleFor middleware
1646
+ // path — forensic walkers can reconstruct the role timeline whether
1647
+ // the binding came from request middleware or a job runner.
1648
+ var previousRole = dbRoleContext.getRole();
1649
+ var newRole = role || null;
1650
+ if (previousRole !== newRole) {
1651
+ audit().safeEmit({
1652
+ action: "db.role.switched",
1653
+ actor: {},
1654
+ resource: { kind: "db.role", id: newRole || "(none)" },
1655
+ outcome: "success",
1656
+ metadata: {
1657
+ previousRole: previousRole,
1658
+ newRole: newRole,
1659
+ source: "runAs",
1660
+ },
1661
+ });
1662
+ }
1663
+ return dbRoleContext.runWithRole(role || null, fn);
1664
+ }
1665
+
1666
+ /**
1667
+ * @primitive b.externalDb.currentRole
1668
+ * @signature b.externalDb.currentRole()
1669
+ * @since 0.4.0
1670
+ * @related b.externalDb.runAs
1671
+ *
1672
+ * Read the SQL role bound on the deep async-local context. Returns
1673
+ * `null` when no role is bound. Useful for diagnostic logs, audit
1674
+ * metadata, and observability labels — the value flows through the
1675
+ * same context that `b.externalDb.query` consults for backend pick.
1676
+ *
1677
+ * @example
1678
+ * await b.externalDb.runAs("analytics_user", async function () {
1679
+ * b.externalDb.currentRole(); // → "analytics_user"
1680
+ * });
1681
+ * b.externalDb.currentRole(); // → null
1682
+ */
1683
+ function currentRole() {
1684
+ return dbRoleContext.getRole();
1685
+ }
1686
+
1687
+ // OWASP-2 — pg_roles enumeration / unrecognized-role guard.
1688
+ //
1689
+ // Boot-time check that compares pg_roles membership to the operator-
1690
+ // declared role list. Operators declare every role they expect to
1691
+ // exist on the cluster (via opts.declaredRoles); the gate refuses or
1692
+ // audits when pg_roles surfaces names not in that list — typical
1693
+ // signal of a forgotten ALTER ROLE / a leftover migration role / a
1694
+ // privileged role added outside change-management.
1695
+ //
1696
+ // await b.externalDb.assertRoleHardening({
1697
+ // backend: "main",
1698
+ // declaredRoles: ["app_user", "analytics_user", "admin"],
1699
+ // mode: "audit", // "audit" | "throw"
1700
+ // ignoreSystem: true, // skip rds_*, pg_*, postgres
1701
+ // });
1702
+ //
1703
+ // Returns { declared, observed, unrecognized, missing }. mode="throw"
1704
+ // raises ROLE_HARDENING_FAIL when unrecognized rows surface; default
1705
+ // "audit" emits db.role.hardening.unrecognized so dashboards see the
1706
+ // drift without breaking boot.
1707
+ /**
1708
+ * @primitive b.externalDb.assertRoleHardening
1709
+ * @signature b.externalDb.assertRoleHardening(opts)
1710
+ * @since 0.7.0
1711
+ * @related b.externalDb.runAs, b.externalDb.adapters.connectAs
1712
+ *
1713
+ * Compare `pg_roles` membership against an operator-declared role
1714
+ * allowlist on a Postgres backend. Surfaces unrecognized roles
1715
+ * (forgotten ALTER ROLE leftovers, migration roles, privileged grants
1716
+ * added outside change-management) and missing roles (declared but not
1717
+ * present). Default `mode: "audit"` emits
1718
+ * `db.role.hardening.unrecognized` / `.ok` so dashboards see drift
1719
+ * without breaking boot; `mode: "throw"` fails boot when unrecognized
1720
+ * roles surface. Non-Postgres dialects emit `db.role.hardening.skipped`
1721
+ * and return empty observed lists.
1722
+ *
1723
+ * @opts
1724
+ * declaredRoles: string[], // required; allowlist of expected role names
1725
+ * backend?: string, // explicit backend name (defaults to defaultBackend)
1726
+ * mode?: "audit" | "throw", // default "audit"
1727
+ * ignoreSystem?: boolean, // skip postgres / pg_* / rds_* / azure_* / cloudsqlsuperuser (default true)
1728
+ *
1729
+ * @example
1730
+ * var report = await b.externalDb.assertRoleHardening({
1731
+ * backend: "main",
1732
+ * declaredRoles: ["app_user", "analytics_user", "admin"],
1733
+ * mode: "audit",
1734
+ * ignoreSystem: true,
1735
+ * });
1736
+ * report.unrecognized; // → []
1737
+ * report.missing; // → []
1738
+ * report.observed; // → ["admin", "analytics_user", "app_user"]
1739
+ */
1740
+ async function assertRoleHardening(opts) {
1741
+ _requireInit();
1742
+ if (!opts || typeof opts !== "object") {
1743
+ throw _err("INVALID_CONFIG",
1744
+ "assertRoleHardening: opts is required ({ declaredRoles, backend?, mode? })", true);
1745
+ }
1746
+ if (!Array.isArray(opts.declaredRoles)) {
1747
+ throw _err("INVALID_CONFIG",
1748
+ "assertRoleHardening: opts.declaredRoles must be an array of role names", true);
1749
+ }
1750
+ for (var i = 0; i < opts.declaredRoles.length; i++) {
1751
+ var r = opts.declaredRoles[i];
1752
+ if (typeof r !== "string" || r.length === 0) {
1753
+ throw _err("INVALID_CONFIG",
1754
+ "assertRoleHardening: declaredRoles[" + i + "] must be a non-empty string", true);
1755
+ }
1756
+ }
1757
+ var mode = opts.mode || "audit";
1758
+ if (mode !== "audit" && mode !== "throw") {
1759
+ throw _err("INVALID_CONFIG",
1760
+ "assertRoleHardening: mode must be 'audit' or 'throw' (got '" + mode + "')", true);
1761
+ }
1762
+ var backendName = opts.backend || defaultBackend;
1763
+ var b = backends[backendName];
1764
+ if (!b) {
1765
+ throw _err("UNKNOWN_BACKEND",
1766
+ "assertRoleHardening: no backend named '" + backendName + "'", true);
1767
+ }
1768
+ if (b.dialect !== "postgres") {
1769
+ // Non-Postgres dialects don't have pg_roles. The check is a no-op
1770
+ // with a clear audit row so operators see the skip rather than
1771
+ // assume hardening ran.
1772
+ audit().safeEmit({
1773
+ action: "db.role.hardening.skipped",
1774
+ actor: {},
1775
+ resource: { kind: "db.backend", id: backendName },
1776
+ outcome: "success",
1777
+ metadata: { dialect: b.dialect, reason: "non-postgres" },
1778
+ });
1779
+ return { declared: opts.declaredRoles.slice(), observed: [], unrecognized: [], missing: [] };
1780
+ }
1781
+ var ignoreSystem = opts.ignoreSystem !== false; // default true
1782
+ var rows;
1783
+ try {
1784
+ var res = await query(
1785
+ "SELECT rolname FROM pg_roles ORDER BY rolname",
1786
+ [],
1787
+ { backend: backendName }
1788
+ );
1789
+ rows = (res && res.rows) || [];
1790
+ } catch (e) {
1791
+ audit().safeEmit({
1792
+ action: "db.role.hardening.unreadable",
1793
+ actor: {},
1794
+ resource: { kind: "db.backend", id: backendName },
1795
+ outcome: "failure",
1796
+ reason: (e && e.message) || String(e),
1797
+ metadata: { backend: backendName },
1798
+ });
1799
+ throw _err("ROLE_HARDENING_UNREADABLE",
1800
+ "assertRoleHardening: could not read pg_roles on backend '" + backendName + "': " +
1801
+ ((e && e.message) || String(e)), true);
1802
+ }
1803
+ var observed = rows.map(function (r) { return r.rolname; });
1804
+ if (ignoreSystem) {
1805
+ observed = observed.filter(function (n) {
1806
+ return !(n === "postgres" || n.indexOf("pg_") === 0 || n.indexOf("rds_") === 0 ||
1807
+ n.indexOf("rdsadmin") === 0 || n.indexOf("azure_") === 0 ||
1808
+ n.indexOf("cloudsqlsuperuser") === 0);
1809
+ });
1810
+ }
1811
+ var declaredSet = {};
1812
+ opts.declaredRoles.forEach(function (n) { declaredSet[n] = true; });
1813
+ var observedSet = {};
1814
+ observed.forEach(function (n) { observedSet[n] = true; });
1815
+ var unrecognized = observed.filter(function (n) { return !declaredSet[n]; });
1816
+ var missing = opts.declaredRoles.filter(function (n) { return !observedSet[n]; });
1817
+ if (unrecognized.length > 0 || missing.length > 0) {
1818
+ audit().safeEmit({
1819
+ action: "db.role.hardening.unrecognized",
1820
+ actor: {},
1821
+ resource: { kind: "db.backend", id: backendName },
1822
+ outcome: unrecognized.length > 0 ? "denied" : "failure",
1823
+ metadata: {
1824
+ backend: backendName,
1825
+ unrecognized: unrecognized,
1826
+ missing: missing,
1827
+ observedCount: observed.length,
1828
+ },
1829
+ });
1830
+ if (mode === "throw" && unrecognized.length > 0) {
1831
+ throw _err("ROLE_HARDENING_FAIL",
1832
+ "assertRoleHardening: pg_roles surfaces " + unrecognized.length +
1833
+ " unrecognized role(s) on backend '" + backendName + "': " +
1834
+ unrecognized.join(", ") + ". Either add them to declaredRoles after " +
1835
+ "review, REVOKE them, or set mode: 'audit' to downgrade to audit-only.",
1836
+ true);
1837
+ }
1838
+ } else {
1839
+ audit().safeEmit({
1840
+ action: "db.role.hardening.ok",
1841
+ actor: {},
1842
+ resource: { kind: "db.backend", id: backendName },
1843
+ outcome: "success",
1844
+ metadata: { backend: backendName, observedCount: observed.length },
1845
+ });
1846
+ }
1847
+ return {
1848
+ declared: opts.declaredRoles.slice(),
1849
+ observed: observed,
1850
+ unrecognized: unrecognized,
1851
+ missing: missing,
1852
+ };
1853
+ }
1854
+
1855
+ module.exports = {
1856
+ init: init,
1857
+ query: query,
1858
+ transaction: transaction,
1859
+ healthCheck: healthCheck,
1860
+ listBackends: listBackends,
1861
+ shutdown: shutdown,
1862
+ configurePool: configurePool,
1863
+ read: read,
1864
+ write: write,
1865
+ runAs: runAs,
1866
+ currentRole: currentRole,
1867
+ assertRoleHardening: assertRoleHardening,
1868
+ adapters: {
1869
+ connectAs: _adaptersConnectAs,
1870
+ },
1871
+ // Migration runner targeting an externalDb backend. Mirrors b.migrations
1872
+ // (which targets local SQLite) but runs against externalDb. Tracking +
1873
+ // lock tables live on the externalDb side. See lib/external-db-migrate.js.
1874
+ migrate: externalDbMigrate,
1875
+ Pool: Pool,
1876
+ _resetForTest: _resetForTest,
1877
+ };