@blamejs/blamejs-shop 0.5.12 → 0.5.14

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 (522) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/sales-tax-filings.js +143 -0
  4. package/lib/vendor/MANIFEST.json +632 -416
  5. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  6. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  7. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  8. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  9. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  10. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  11. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  12. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  13. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  14. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  15. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  16. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  17. package/lib/vendor/blamejs/.gitignore +2 -0
  18. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  19. package/lib/vendor/blamejs/NOTICE +26 -1
  20. package/lib/vendor/blamejs/SECURITY.md +1 -1
  21. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  22. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  23. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  24. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  25. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  26. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  27. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  28. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  29. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  30. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  31. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  32. package/lib/vendor/blamejs/index.js +6 -0
  33. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  34. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  35. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  36. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  37. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  38. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  39. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  40. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  41. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  42. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  43. package/lib/vendor/blamejs/lib/audit.js +71 -8
  44. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  45. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  46. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  47. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  48. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  49. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  50. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  51. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  52. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  53. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  54. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  55. package/lib/vendor/blamejs/lib/base32.js +21 -0
  56. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  57. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  58. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  59. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  60. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  61. package/lib/vendor/blamejs/lib/cert.js +29 -11
  62. package/lib/vendor/blamejs/lib/cli.js +94 -24
  63. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  64. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  65. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  66. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  67. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  68. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  69. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  70. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  71. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  72. package/lib/vendor/blamejs/lib/cose.js +31 -16
  73. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  74. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  75. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  76. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  77. package/lib/vendor/blamejs/lib/csp.js +11 -3
  78. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  79. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  80. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  81. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  82. package/lib/vendor/blamejs/lib/db.js +18 -6
  83. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  84. package/lib/vendor/blamejs/lib/dev.js +21 -2
  85. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  86. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  87. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  88. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  89. package/lib/vendor/blamejs/lib/forms.js +113 -27
  90. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  91. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  92. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  93. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  94. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  95. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  96. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  97. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  98. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  99. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  100. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  101. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  102. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  103. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  104. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  105. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  106. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  107. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  108. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  109. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  110. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  111. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  112. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  113. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  114. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  115. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  116. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  117. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  118. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  119. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  120. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  121. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  122. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  123. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  124. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  125. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  126. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  127. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  128. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  129. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  130. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  131. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  132. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  133. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  134. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  135. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  136. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  137. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  138. package/lib/vendor/blamejs/lib/mail.js +15 -5
  139. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  140. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  141. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  142. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  143. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  144. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  145. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  146. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  147. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  148. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  149. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  150. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  151. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  153. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  154. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  155. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  156. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  157. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  158. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  159. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  160. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  161. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  162. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  163. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  164. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  165. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  166. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  167. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  168. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  169. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  170. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  171. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  172. package/lib/vendor/blamejs/lib/redact.js +54 -0
  173. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  174. package/lib/vendor/blamejs/lib/restore.js +19 -0
  175. package/lib/vendor/blamejs/lib/retention.js +12 -4
  176. package/lib/vendor/blamejs/lib/router.js +60 -6
  177. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  178. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  179. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  180. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  181. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  182. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  183. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  184. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  185. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  186. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  187. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  188. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  189. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  190. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  191. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  192. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  193. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  194. package/lib/vendor/blamejs/lib/session.js +34 -12
  195. package/lib/vendor/blamejs/lib/sql.js +15 -1
  196. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  197. package/lib/vendor/blamejs/lib/static.js +55 -13
  198. package/lib/vendor/blamejs/lib/storage.js +8 -2
  199. package/lib/vendor/blamejs/lib/subject.js +6 -1
  200. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  201. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  202. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  203. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  204. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  205. package/lib/vendor/blamejs/lib/vc.js +44 -5
  206. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  207. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  208. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  209. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  210. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  212. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  213. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  214. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  215. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  216. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  217. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  218. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  219. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  220. package/lib/vendor/blamejs/package-lock.json +2 -2
  221. package/lib/vendor/blamejs/package.json +1 -1
  222. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  223. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  224. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  245. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  246. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  247. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  248. package/lib/vendor/blamejs/socket.yml +94 -0
  249. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  250. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  251. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  252. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  253. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  254. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  255. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  256. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  257. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  258. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  259. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  260. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  262. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  263. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  269. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  270. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  284. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  285. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  295. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  302. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  303. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  308. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  321. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  322. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  324. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  326. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  327. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  330. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  334. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  335. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  336. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  337. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  348. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  365. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  376. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  377. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  388. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  413. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  414. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  415. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  416. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  428. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  432. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  434. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  442. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  443. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  445. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  477. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  478. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  480. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  490. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  491. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  492. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  493. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  495. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  502. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  503. package/lib/vendor/blamejs/test/smoke.js +2 -0
  504. package/package.json +1 -1
  505. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  506. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  507. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  508. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  509. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  510. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  511. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  512. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  513. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  514. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  515. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  516. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  517. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  518. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  519. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  520. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  521. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  522. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -0,0 +1,946 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) blamejs contributors
3
+ "use strict";
4
+ /**
5
+ * b.auth.openidFederation — OpenID Federation 1.0 trust-chain primitive.
6
+ *
7
+ * Exercises the error / adversarial / defensive / option-default branches of
8
+ * every public surface:
9
+ *
10
+ * parseEntityStatement — empty / oversize / non-3-segment / bad-decode /
11
+ * wrong-typ / unsupported-alg rejections.
12
+ * verifyEntityStatement — no-keys / no-matching-kid / kid-less refuse +
13
+ * opt-in / alg-kty confusion refuse (CVE-2026-22817) / PS256 padding
14
+ * branch / bad-signature / iat-future / expired / missing-iss-sub /
15
+ * tunable clock skew.
16
+ * applyMetadataPolicy — bad-metadata / bad-chain guards and every OIDF
17
+ * §6.2 operator (value / default / add / one_of / subset_of /
18
+ * superset_of / essential / unknown), each with its non-array and
19
+ * constraint-violation rejection, plus top-down multi-node narrowing.
20
+ * buildTrustChain — opts / leaf / anchors validation; self-statement
21
+ * iss==sub==entity_id; no-authority-hints; iss/sub-mismatch + throwing
22
+ * hint → no-ascent; cyclic authority_hints → chain-cycle; maxDepth →
23
+ * chain-too-deep; subordinate-pins-no-jwks → no-attested-jwks; the
24
+ * default httpClient fetcher (fetch-failed / empty-response / success)
25
+ * and default subordinate fetcher (no-fetch-endpoint / success).
26
+ * resolveLeaf — no-kind guard + happy effective-metadata resolution.
27
+ *
28
+ * Keys are generated in-process; a self-signed statement verifies and a
29
+ * wrong-key / tampered one is refused. No network: the default-fetcher
30
+ * paths stub httpClient.request in-memory and restore it in finally.
31
+ */
32
+
33
+ var helpers = require("../helpers");
34
+ var b = helpers.b;
35
+ var check = helpers.check;
36
+ var nodeCrypto = require("crypto");
37
+ var httpClient = require("../../lib/http-client");
38
+
39
+ // ---- entity-statement minting (in-process keys) --------------------------
40
+
41
+ function _b64url(buf) { return Buffer.from(buf).toString("base64url"); }
42
+
43
+ // Generate an EC P-256 entity: private key + public JWK (kid-tagged) + a
44
+ // single-key JWKS. ES256 is the OIDF default and the cheapest keygen.
45
+ function _ecEntity(kid) {
46
+ var kp = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
47
+ var jwk = kp.publicKey.export({ format: "jwk" });
48
+ jwk.kid = kid;
49
+ return { priv: kp.privateKey, jwk: jwk, jwks: { keys: [jwk] } };
50
+ }
51
+
52
+ // One reusable RSA entity for the PS256 padding branch (RSA keygen is slow).
53
+ var _sharedRsa = null;
54
+ function _rsaEntity(kid) {
55
+ if (!_sharedRsa) {
56
+ _sharedRsa = nodeCrypto.generateKeyPairSync("rsa", { modulusLength: 2048 }); // allow:raw-byte-literal — RSA modulus bits
57
+ }
58
+ var jwk = _sharedRsa.publicKey.export({ format: "jwk" });
59
+ jwk.kid = kid;
60
+ return { priv: _sharedRsa.privateKey, jwk: jwk, jwks: { keys: [jwk] } };
61
+ }
62
+
63
+ // Mint a signed entity-statement+jwt. `mopts`:
64
+ // alg — "ES256" (default) | "PS256"
65
+ // noKid — omit header.kid (kid-less-statement path)
66
+ // headerTyp/headerAlg — override header fields for parse-branch tests
67
+ // tamper — flip the signature so verify fails
68
+ function _mint(priv, kid, claims, mopts) {
69
+ mopts = mopts || {};
70
+ var alg = mopts.alg || "ES256";
71
+ var header = { typ: mopts.headerTyp || "entity-statement+jwt", alg: mopts.headerAlg || alg };
72
+ if (!mopts.noKid) header.kid = kid;
73
+ var input = _b64url(JSON.stringify(header)) + "." + _b64url(JSON.stringify(claims));
74
+ var sig;
75
+ if (alg === "PS256") {
76
+ sig = nodeCrypto.sign("sha256", Buffer.from(input, "ascii"), {
77
+ key: priv,
78
+ padding: nodeCrypto.constants.RSA_PKCS1_PSS_PADDING,
79
+ saltLength: nodeCrypto.constants.RSA_PSS_SALTLEN_DIGEST,
80
+ });
81
+ } else {
82
+ sig = nodeCrypto.sign("sha256", Buffer.from(input, "ascii"), { key: priv, dsaEncoding: "ieee-p1363" });
83
+ }
84
+ if (mopts.tamper) { sig = Buffer.from(sig); sig[0] ^= 0xff; }
85
+ return input + "." + _b64url(sig);
86
+ }
87
+
88
+ var _NOW = Math.floor(Date.now() / 1000); // allow:raw-byte-literal — seconds-per-ms
89
+ function _cfg(id, entity, extra) {
90
+ var c = { iss: id, sub: id, iat: _NOW, exp: _NOW + 3600, jwks: entity.jwks }; // allow:raw-byte-literal — 1h validity
91
+ if (extra) Object.keys(extra).forEach(function (k) { c[k] = extra[k]; });
92
+ return c;
93
+ }
94
+
95
+ // Assert an async call rejects with an AuthError whose code matches `re`.
96
+ async function _rejects(label, fn, re) {
97
+ var threw = null;
98
+ try { await fn(); } catch (e) { threw = e; }
99
+ check(label, !!threw && re.test(threw.code || ""));
100
+ }
101
+
102
+ // Assert a sync call throws with a code matching `re`.
103
+ function _throws(label, fn, re) {
104
+ var threw = null;
105
+ try { fn(); } catch (e) { threw = e; }
106
+ check(label, !!threw && re.test(threw.code || ""));
107
+ }
108
+
109
+ // Build a chain array for applyMetadataPolicy: one leaf node whose
110
+ // superior-signed subordinate statement carries `policyForKind`, plus a
111
+ // terminating anchor node (no `.subordinate`, skipped by the walker).
112
+ function _policyChain(policyForKind, kind) {
113
+ var mp = {}; mp[kind] = policyForKind;
114
+ return [{ subordinate: { metadata_policy: mp } }, { claims: { iss: "anchor" } }];
115
+ }
116
+
117
+ // ---- parseEntityStatement branches ---------------------------------------
118
+
119
+ function testParseRejections() {
120
+ _throws("parse: empty string → bad-statement",
121
+ function () { b.auth.openidFederation.parseEntityStatement(""); }, /bad-statement/);
122
+ _throws("parse: oversize input → bad-statement",
123
+ function () { b.auth.openidFederation.parseEntityStatement("x".repeat(70000)); }, /bad-statement/);
124
+ _throws("parse: non-string input → bad-statement",
125
+ function () { b.auth.openidFederation.parseEntityStatement(null); }, /bad-statement/);
126
+ _throws("parse: 2-segment token → malformed",
127
+ function () { b.auth.openidFederation.parseEntityStatement("aaa.bbb"); }, /malformed/);
128
+ _throws("parse: header not JSON → bad-decode",
129
+ function () {
130
+ var bad = _b64url("not json{") + "." + _b64url(JSON.stringify({ iss: "x" })) + "." + _b64url("s");
131
+ b.auth.openidFederation.parseEntityStatement(bad);
132
+ }, /bad-decode/);
133
+ _throws("parse: wrong header.typ → wrong-typ",
134
+ function () {
135
+ var e = _ecEntity("k");
136
+ b.auth.openidFederation.parseEntityStatement(_mint(e.priv, "k", _cfg("https://x", e), { headerTyp: "JWT" }));
137
+ }, /wrong-typ/);
138
+ _throws("parse: unsupported header.alg → unsupported-alg",
139
+ function () {
140
+ var e = _ecEntity("k");
141
+ // Sign with a real ES256 sig but advertise an unsupported alg in the header.
142
+ b.auth.openidFederation.parseEntityStatement(_mint(e.priv, "k", _cfg("https://x", e), { headerAlg: "HS256" }));
143
+ }, /unsupported-alg/);
144
+ }
145
+
146
+ // ---- verifyEntityStatement branches --------------------------------------
147
+
148
+ function testVerifyKeySelection() {
149
+ var e = _ecEntity("kid-a");
150
+ var jwt = _mint(e.priv, "kid-a", _cfg("https://x", e));
151
+
152
+ // Happy self-verify + tunable clock skew (the maxClockSkewSec true branch).
153
+ var claims = b.auth.openidFederation.verifyEntityStatement(jwt, e.jwks, { maxClockSkewSec: 300 });
154
+ check("verify: valid self-signed statement returns claims", claims.iss === "https://x");
155
+
156
+ _throws("verify: jwks with no keys array → no-keys",
157
+ function () { b.auth.openidFederation.verifyEntityStatement(jwt, {}); }, /no-keys/);
158
+ _throws("verify: jwks with empty keys → no-keys",
159
+ function () { b.auth.openidFederation.verifyEntityStatement(jwt, { keys: [] }); }, /no-keys/);
160
+
161
+ // header.kid present but no JWKS key matches it.
162
+ var otherJwk = JSON.parse(JSON.stringify(e.jwk)); otherJwk.kid = "different";
163
+ _throws("verify: kid with no matching JWKS key → no-matching-kid",
164
+ function () { b.auth.openidFederation.verifyEntityStatement(jwt, { keys: [otherJwk] }); }, /no-matching-kid/);
165
+ }
166
+
167
+ function testVerifyKidless() {
168
+ var e = _ecEntity("kid-a");
169
+ var kidlessJwt = _mint(e.priv, "kid-a", _cfg("https://x", e), { noKid: true });
170
+
171
+ // Kid-less refused by default (single key, no opt-in).
172
+ _throws("verify: kid-less statement refused by default → kid-required",
173
+ function () { b.auth.openidFederation.verifyEntityStatement(kidlessJwt, e.jwks); }, /kid-required/);
174
+
175
+ // Kid-less refused even with opt-in when JWKS has >1 key.
176
+ var twoKeyJwks = { keys: [e.jwk, _ecEntity("kid-b").jwk] };
177
+ _throws("verify: kid-less with multi-key JWKS refused even with opt-in → kid-required",
178
+ function () { b.auth.openidFederation.verifyEntityStatement(kidlessJwt, twoKeyJwks, { allowKidlessJwks: true }); },
179
+ /kid-required/);
180
+
181
+ // Kid-less accepted only with single-key JWKS + explicit opt-in.
182
+ var claims = b.auth.openidFederation.verifyEntityStatement(kidlessJwt, e.jwks, { allowKidlessJwks: true });
183
+ check("verify: kid-less single-key JWKS accepted with allowKidlessJwks", claims.iss === "https://x");
184
+ }
185
+
186
+ function testVerifyAlgKtyConfusion() {
187
+ // CVE-2026-22817 — a statement declaring alg ES256 but resolving to an RSA
188
+ // JWK (same kid) must be refused before node:crypto ever sees the key.
189
+ var ec = _ecEntity("shared");
190
+ var rsa = _rsaEntity("shared");
191
+ var jwt = _mint(ec.priv, "shared", _cfg("https://x", ec)); // header alg ES256
192
+ _throws("verify: alg ES256 over RSA JWK refused (alg/kty confusion)",
193
+ function () { b.auth.openidFederation.verifyEntityStatement(jwt, rsa.jwks); }, /alg-kty-mismatch/);
194
+ }
195
+
196
+ function testVerifyPs256() {
197
+ // The PS* padding branch: mint a PS256 statement with an RSA key and verify.
198
+ var rsa = _rsaEntity("rsa-ps");
199
+ var jwt = _mint(rsa.priv, "rsa-ps", _cfg("https://ps.example", rsa), { alg: "PS256" });
200
+ var claims = b.auth.openidFederation.verifyEntityStatement(jwt, rsa.jwks);
201
+ check("verify: valid PS256 statement verifies", claims.iss === "https://ps.example");
202
+ }
203
+
204
+ function testVerifySignatureAndTime() {
205
+ var e = _ecEntity("k");
206
+
207
+ _throws("verify: tampered signature → bad-signature",
208
+ function () { b.auth.openidFederation.verifyEntityStatement(_mint(e.priv, "k", _cfg("https://x", e), { tamper: true }), e.jwks); },
209
+ /bad-signature/);
210
+
211
+ _throws("verify: iat in the future → iat-future",
212
+ function () {
213
+ var c = _cfg("https://x", e); c.iat = _NOW + 100000; c.exp = _NOW + 200000;
214
+ b.auth.openidFederation.verifyEntityStatement(_mint(e.priv, "k", c), e.jwks);
215
+ }, /iat-future/);
216
+
217
+ _throws("verify: iat missing → iat-future",
218
+ function () {
219
+ var c = _cfg("https://x", e); delete c.iat;
220
+ b.auth.openidFederation.verifyEntityStatement(_mint(e.priv, "k", c), e.jwks);
221
+ }, /iat-future/);
222
+
223
+ _throws("verify: expired statement → expired",
224
+ function () {
225
+ var c = _cfg("https://x", e); c.iat = _NOW - 200000; c.exp = _NOW - 100000;
226
+ b.auth.openidFederation.verifyEntityStatement(_mint(e.priv, "k", c), e.jwks);
227
+ }, /expired/);
228
+
229
+ _throws("verify: missing iss/sub → missing-iss-sub",
230
+ function () {
231
+ var c = _cfg("https://x", e); delete c.iss; delete c.sub;
232
+ b.auth.openidFederation.verifyEntityStatement(_mint(e.priv, "k", c), e.jwks);
233
+ }, /missing-iss-sub/);
234
+ }
235
+
236
+ // ---- applyMetadataPolicy: guards + every OIDF §6.2 operator ---------------
237
+
238
+ function testPolicyGuards() {
239
+ _throws("applyMetadataPolicy: non-object metadata → bad-metadata",
240
+ function () { b.auth.openidFederation.applyMetadataPolicy(null, [], "openid_relying_party"); }, /bad-metadata/);
241
+ _throws("applyMetadataPolicy: non-array chain → bad-chain",
242
+ function () { b.auth.openidFederation.applyMetadataPolicy({}, "nope", "openid_relying_party"); }, /bad-chain/);
243
+ _throws("applyMetadataPolicy: rules not an object → bad-policy-rules",
244
+ function () {
245
+ b.auth.openidFederation.applyMetadataPolicy({}, _policyChain({ client_name: "scalar" }, "k"), "k");
246
+ }, /bad-policy-rules/);
247
+ }
248
+
249
+ function testPolicyOperators() {
250
+ var K = "openid_relying_party";
251
+ function apply(meta, pol) { return b.auth.openidFederation.applyMetadataPolicy(meta, _policyChain(pol, K), K); }
252
+
253
+ // value — overrides.
254
+ check("policy value: sets claim to fixed value",
255
+ apply({ client_name: "orig" }, { client_name: { value: "fixed" } }).client_name === "fixed");
256
+
257
+ // default — only when absent.
258
+ check("policy default: fills absent claim",
259
+ apply({}, { contacts: { default: ["a@b.c"] } }).contacts[0] === "a@b.c");
260
+ check("policy default: leaves present claim untouched",
261
+ apply({ contacts: ["keep@x"] }, { contacts: { default: ["a@b.c"] } }).contacts[0] === "keep@x");
262
+
263
+ // add — array append; non-array rejected.
264
+ _throws("policy add: non-array value → bad-policy-add",
265
+ function () { apply({}, { redirect_uris: { add: "not-array" } }); }, /bad-policy-add/);
266
+ var added = apply({ redirect_uris: ["u1"] }, { redirect_uris: { add: ["u1", "u2"] } }).redirect_uris;
267
+ check("policy add: appends only new values", added.length === 2 && added[1] === "u2");
268
+ check("policy add: seeds absent claim as array",
269
+ apply({}, { redirect_uris: { add: ["u1"] } }).redirect_uris[0] === "u1");
270
+
271
+ // one_of.
272
+ _throws("policy one_of: non-array value → bad-policy-one-of",
273
+ function () { apply({ subject_type: "public" }, { subject_type: { one_of: "public" } }); }, /bad-policy-one-of/);
274
+ _throws("policy one_of: value not in set → policy-one-of-failed",
275
+ function () { apply({ subject_type: "pairwise" }, { subject_type: { one_of: ["public"] } }); }, /policy-one-of-failed/);
276
+ check("policy one_of: value in set passes",
277
+ apply({ subject_type: "public" }, { subject_type: { one_of: ["public", "pairwise"] } }).subject_type === "public");
278
+
279
+ // subset_of.
280
+ _throws("policy subset_of: non-array value → bad-policy-subset-of",
281
+ function () { apply({ scopes: ["a"] }, { scopes: { subset_of: "a" } }); }, /bad-policy-subset-of/);
282
+ _throws("policy subset_of: value outside allowed → policy-subset-of-failed",
283
+ function () { apply({ scopes: ["a", "z"] }, { scopes: { subset_of: ["a", "b"] } }); }, /policy-subset-of-failed/);
284
+ check("policy subset_of: subset passes",
285
+ apply({ scopes: ["a"] }, { scopes: { subset_of: ["a", "b"] } }).scopes[0] === "a");
286
+
287
+ // superset_of.
288
+ _throws("policy superset_of: non-array value → bad-policy-superset-of",
289
+ function () { apply({ grant_types: ["x"] }, { grant_types: { superset_of: "x" } }); }, /bad-policy-superset-of/);
290
+ _throws("policy superset_of: missing required value → policy-superset-of-failed",
291
+ function () { apply({ grant_types: ["authorization_code"] }, { grant_types: { superset_of: ["refresh_token"] } }); },
292
+ /policy-superset-of-failed/);
293
+ check("policy superset_of: contains all required passes",
294
+ apply({ grant_types: ["authorization_code", "refresh_token"] },
295
+ { grant_types: { superset_of: ["refresh_token"] } }).grant_types.length === 2);
296
+
297
+ // essential.
298
+ _throws("policy essential: required-but-absent → policy-essential-failed",
299
+ function () { apply({}, { sector_identifier_uri: { essential: true } }); }, /policy-essential-failed/);
300
+ check("policy essential: present claim passes",
301
+ apply({ sector_identifier_uri: "https://s" }, { sector_identifier_uri: { essential: true } }).sector_identifier_uri === "https://s");
302
+
303
+ // unknown operator refuses loudly.
304
+ _throws("policy: unknown operator → unknown-policy-op",
305
+ function () { apply({}, { client_name: { bogus_op: 1 } }); }, /unknown-policy-op/);
306
+ }
307
+
308
+ function testPolicyMultiNodeNarrowing() {
309
+ // Top-down: the anchor-signed (intermediate) policy is applied before the
310
+ // intermediate-signed (leaf) policy. Both narrow the effective metadata.
311
+ var K = "openid_relying_party";
312
+ var chain = [
313
+ { subordinate: { metadata_policy: { "openid_relying_party": { grant_types: { subset_of: ["authorization_code", "refresh_token"] } } } } },
314
+ { subordinate: { metadata_policy: { "openid_relying_party": { scopes: { default: ["openid"] } } } } },
315
+ { claims: { iss: "https://anchor.example" } },
316
+ ];
317
+ var eff = b.auth.openidFederation.applyMetadataPolicy(
318
+ { grant_types: ["authorization_code"] }, chain, K);
319
+ check("policy multi-node: anchor subset_of + intermediate default both applied",
320
+ eff.grant_types[0] === "authorization_code" && eff.scopes[0] === "openid");
321
+ }
322
+
323
+ // The chain levels' policies are MERGED (OIDF 1.0 §6.1.5.3) so a subordinate can
324
+ // only narrow a superior's constraint, never override it — the pre-merge
325
+ // sequential apply let a leaf-ward `value` silently overwrite the anchor's.
326
+ function testPolicyMergeCrossLevel() {
327
+ var K = "openid_relying_party";
328
+ function chainOf(anchorPolicy, subPolicy) {
329
+ // leaf-first: chain[0].subordinate = the intermediate's policy on the leaf
330
+ // (lower); chain[1].subordinate = the anchor's policy on the intermediate.
331
+ return [
332
+ { subordinate: { metadata_policy: { "openid_relying_party": subPolicy } } },
333
+ { subordinate: { metadata_policy: { "openid_relying_party": anchorPolicy } } },
334
+ { claims: { iss: "https://anchor.example" } },
335
+ ];
336
+ }
337
+ _throws("policy merge: conflicting cross-level value refused (trust downgrade)",
338
+ function () {
339
+ b.auth.openidFederation.applyMetadataPolicy({},
340
+ chainOf({ token_endpoint_auth_method: { value: "private_key_jwt" } },
341
+ { token_endpoint_auth_method: { value: "none" } }), K);
342
+ }, /policy-merge-conflict/);
343
+ var same = b.auth.openidFederation.applyMetadataPolicy({},
344
+ chainOf({ token_endpoint_auth_method: { value: "x" } },
345
+ { token_endpoint_auth_method: { value: "x" } }), K);
346
+ check("policy merge: identical cross-level value applies", same.token_endpoint_auth_method === "x");
347
+ _throws("policy merge: one_of intersects (subordinate narrows the anchor's set)",
348
+ function () {
349
+ b.auth.openidFederation.applyMetadataPolicy({ grant_types: "a" },
350
+ chainOf({ grant_types: { one_of: ["a", "b", "c"] } },
351
+ { grant_types: { one_of: ["b", "c"] } }), K);
352
+ }, /one-of/);
353
+ var u = b.auth.openidFederation.applyMetadataPolicy({ scope: [] },
354
+ chainOf({ scope: { add: ["x"] } }, { scope: { add: ["y"] } }), K);
355
+ check("policy merge: add unions across levels",
356
+ u.scope.indexOf("x") !== -1 && u.scope.indexOf("y") !== -1);
357
+
358
+ // Cross-operator downgrades: a subordinate must not escape a superior's
359
+ // constraint by expressing an override with a DIFFERENT operator. The merged
360
+ // constraint is enforced against the FINAL value at apply time, so each is
361
+ // refused -- a value outside the merged one_of, an add widening past the
362
+ // merged subset_of, a value dropping a superset_of-mandated member.
363
+ _throws("policy merge: subordinate value cannot override a superior one_of",
364
+ function () {
365
+ b.auth.openidFederation.applyMetadataPolicy({},
366
+ chainOf({ token_endpoint_auth_method: { one_of: ["private_key_jwt"] } },
367
+ { token_endpoint_auth_method: { value: "none" } }), K);
368
+ }, /policy-one-of-failed/);
369
+ _throws("policy merge: subordinate add cannot widen past a superior subset_of",
370
+ function () {
371
+ b.auth.openidFederation.applyMetadataPolicy({ scope: ["read"] },
372
+ chainOf({ scope: { subset_of: ["read"] } },
373
+ { scope: { add: ["write"] } }), K);
374
+ }, /policy-subset-of-failed/);
375
+ _throws("policy merge: subordinate value cannot drop a superior superset_of member",
376
+ function () {
377
+ b.auth.openidFederation.applyMetadataPolicy({ grant_types: ["authorization_code"] },
378
+ chainOf({ grant_types: { superset_of: ["authorization_code"] } },
379
+ { grant_types: { value: ["implicit"] } }), K);
380
+ }, /policy-superset-of-failed/);
381
+
382
+ // Consistent cross-operator combinations remain valid narrowings.
383
+ var withinSub = b.auth.openidFederation.applyMetadataPolicy({ scope: [] },
384
+ chainOf({ scope: { subset_of: ["read", "write"] } }, { scope: { add: ["read"] } }), K);
385
+ check("policy merge: add within subset_of applies", withinSub.scope[0] === "read");
386
+ var defOneOf = b.auth.openidFederation.applyMetadataPolicy({},
387
+ chainOf({ subject_type: { one_of: ["public", "pairwise"] } },
388
+ { subject_type: { default: "public" } }), K);
389
+ check("policy merge: default consistent with one_of applies", defOneOf.subject_type === "public");
390
+ // A subordinate MAY pin an exact `value` INSIDE the superior's one_of set (a
391
+ // valid narrowing, OIDF 6.1.3.1.1); only a value OUTSIDE it is the downgrade.
392
+ var vInSet = b.auth.openidFederation.applyMetadataPolicy({},
393
+ chainOf({ token_endpoint_auth_method: { one_of: ["private_key_jwt", "self_signed_tls_client_auth"] } },
394
+ { token_endpoint_auth_method: { value: "private_key_jwt" } }), K);
395
+ check("policy merge: value consistent with a superior one_of applies",
396
+ vInSet.token_endpoint_auth_method === "private_key_jwt");
397
+ // A subordinate cannot WIDEN an anchor's exact `value` with `add` (the union
398
+ // would escape the pin) nor pair it with `default` -- value combines with a
399
+ // constraint, never with another modifier.
400
+ _throws("policy merge: subordinate add cannot widen an anchor pinned value",
401
+ function () {
402
+ b.auth.openidFederation.applyMetadataPolicy({ grant_types: ["authorization_code"] },
403
+ chainOf({ grant_types: { value: ["authorization_code"] } },
404
+ { grant_types: { add: ["implicit"] } }), K);
405
+ }, /policy-merge-conflict/);
406
+ // `value` + `add` is a no-op (allowed) when `add` is already within the pin;
407
+ // `value` + `default` is a no-op (the pinned value wins) -- neither widens.
408
+ var vAddNoop = b.auth.openidFederation.applyMetadataPolicy({},
409
+ chainOf({ grant_types: { value: ["authorization_code", "refresh_token"] } },
410
+ { grant_types: { add: ["refresh_token"] } }), K);
411
+ check("policy merge: value + add within the pin is a no-op",
412
+ vAddNoop.grant_types.length === 2 && vAddNoop.grant_types.indexOf("refresh_token") !== -1);
413
+ var vDefault = b.auth.openidFederation.applyMetadataPolicy({},
414
+ chainOf({ subject_type: { value: "public" } },
415
+ { subject_type: { default: "pairwise" } }), K);
416
+ check("policy merge: value + default applies the pinned value", vDefault.subject_type === "public");
417
+ // `superset_of` is satisfied by the FINAL value, so a co-present `add` need not
418
+ // itself supply the mandated member when the leaf already carries it.
419
+ var addSuperLeaf = b.auth.openidFederation.applyMetadataPolicy({ grant_types: ["authorization_code"] },
420
+ chainOf({ grant_types: { superset_of: ["authorization_code"] } },
421
+ { grant_types: { add: ["refresh_token"] } }), K);
422
+ check("policy merge: add + superset_of satisfied by leaf metadata applies",
423
+ addSuperLeaf.grant_types.indexOf("authorization_code") !== -1 &&
424
+ addSuperLeaf.grant_types.indexOf("refresh_token") !== -1);
425
+ // A space-delimited scope value is validated as a subset of the merged subset_of.
426
+ var scopeVal = b.auth.openidFederation.applyMetadataPolicy({},
427
+ chainOf({ scope: { subset_of: ["openid", "email"] } },
428
+ { scope: { value: "openid email" } }), K);
429
+ check("policy merge: scope-string value within subset_of applies", scopeVal.scope === "openid email");
430
+ // Disjoint one_of across levels intersects to the empty set -> refused (no
431
+ // value could ever satisfy the chain), not silently accepted when absent.
432
+ _throws("policy merge: disjoint one_of across levels refused",
433
+ function () {
434
+ b.auth.openidFederation.applyMetadataPolicy({},
435
+ chainOf({ subject_type: { one_of: ["public"] } },
436
+ { subject_type: { one_of: ["pairwise"] } }), K);
437
+ }, /policy-merge-conflict/);
438
+ }
439
+
440
+ // subset_of constrains an array-valued claim; a leaf that self-declares the
441
+ // claim as a scalar (or object) must NOT skip the anchor's allow-list -- it
442
+ // fails closed, symmetric with superset_of. A leaf controls its own base
443
+ // metadata, so a type-confused scalar would otherwise smuggle a forbidden value.
444
+ function testPolicySubsetOfArrayType() {
445
+ var K = "openid_relying_party";
446
+ function apply(meta, pol) { return b.auth.openidFederation.applyMetadataPolicy(meta, _policyChain(pol, K), K); }
447
+ // A space-delimited string claim (OAuth `scope`, OIDF 6.1.3.1.8) is processed
448
+ // as an array: a subset passes; the string type is preserved on the result.
449
+ var okScope = apply({ scope: "openid email" }, { scope: { subset_of: ["openid", "email", "profile"] } });
450
+ check("policy subset_of: scope string within allow-list passes", okScope.scope === "openid email");
451
+ _throws("policy subset_of: scope string with a forbidden token refused",
452
+ function () { apply({ scope: "openid admin" }, { scope: { subset_of: ["openid", "email"] } }); },
453
+ /policy-subset-of-failed/);
454
+ // A claim the leaf type-confuses into a scalar cannot smuggle a forbidden value
455
+ // past the allow-list -- the split tokens are each checked.
456
+ _throws("policy subset_of: scalar with a forbidden token refused (no allow-list bypass)",
457
+ function () { apply({ grant_types: "authorization_code implicit" }, { grant_types: { subset_of: ["authorization_code"] } }); },
458
+ /policy-subset-of-failed/);
459
+ // A genuine non-array, non-string value (object/number) is malformed -> refused.
460
+ _throws("policy subset_of: non-array object claim fails closed",
461
+ function () { apply({ grant_types: { x: 1 } }, { grant_types: { subset_of: ["authorization_code"] } }); },
462
+ /policy-subset-of-failed/);
463
+ // An absent claim under subset_of stays absent -- subset_of does not require
464
+ // presence (that is `essential`), it only constrains a value that IS present.
465
+ var absent = apply({}, { grant_types: { subset_of: ["authorization_code"] } });
466
+ check("policy subset_of: absent claim stays absent", absent.grant_types === undefined);
467
+ }
468
+
469
+ // A metadata_policy claim name, or a base-metadata key, of __proto__ /
470
+ // constructor / prototype must be refused (prototype-pollution guard) and must
471
+ // never write Object.prototype -- the policy and metadata arrive as
472
+ // attacker-influenced JSON, and the merge accumulates into a shared object.
473
+ function testPolicyPrototypePollution() {
474
+ var K = "openid_relying_party";
475
+ function chain(pol) {
476
+ return [{ subordinate: { metadata_policy: { "openid_relying_party": pol } } }, { claims: { iss: "https://a" } }];
477
+ }
478
+ delete Object.prototype.polluted;
479
+ delete Object.prototype.value;
480
+ // A poisoned CLAIM name in a policy block (JSON wire path -> own __proto__ key).
481
+ _throws("policy: __proto__ claim name refused (no prototype pollution)",
482
+ function () { b.auth.openidFederation.applyMetadataPolicy({}, chain(JSON.parse('{"__proto__":{"value":"x"}}')), K); },
483
+ /poisoned-policy-key/);
484
+ _throws("policy: constructor claim name refused",
485
+ function () { b.auth.openidFederation.applyMetadataPolicy({}, chain(JSON.parse('{"constructor":{"value":"x"}}')), K); },
486
+ /poisoned-policy-key/);
487
+ // A poisoned key in the leaf's base metadata.
488
+ _throws("policy: __proto__ base-metadata key refused",
489
+ function () {
490
+ b.auth.openidFederation.applyMetadataPolicy(JSON.parse('{"__proto__":{"polluted":true}}'),
491
+ chain({ client_name: { value: "x" } }), K);
492
+ }, /poisoned-metadata-key/);
493
+ check("policy: Object.prototype left unpolluted",
494
+ ({}).polluted === undefined && ({}).value === undefined);
495
+ }
496
+
497
+ // ---- buildTrustChain: input validation -----------------------------------
498
+
499
+ async function testChainValidation() {
500
+ await _rejects("buildTrustChain: missing opts → throws",
501
+ function () { return b.auth.openidFederation.buildTrustChain(); }, /./);
502
+ await _rejects("buildTrustChain: missing leafEntityId → no-leaf",
503
+ function () { return b.auth.openidFederation.buildTrustChain({ trustAnchors: { a: {} } }); }, /no-leaf/);
504
+ await _rejects("buildTrustChain: empty trustAnchors map → no-anchors",
505
+ function () { return b.auth.openidFederation.buildTrustChain({ leafEntityId: "https://rp", trustAnchors: {} }); },
506
+ /no-anchors/);
507
+ await _rejects("buildTrustChain: non-object trustAnchors → no-anchors",
508
+ function () { return b.auth.openidFederation.buildTrustChain({ leafEntityId: "https://rp", trustAnchors: "x" }); },
509
+ /no-anchors/);
510
+ }
511
+
512
+ // A leaf→anchor pair fetcher over an in-memory map keyed by URL, plus an
513
+ // explicit subordinate fetcher. `sub` is the anchor-signed statement about
514
+ // the leaf. Returns { fetcher, fetchSubordinate }.
515
+ function _memFetchers(byUrl, subByAuthority) {
516
+ return {
517
+ fetcher: function (url) {
518
+ if (Object.prototype.hasOwnProperty.call(byUrl, url)) return Promise.resolve(byUrl[url]);
519
+ return Promise.reject(new Error("no fixture for " + url));
520
+ },
521
+ fetchSubordinate: function (authority) {
522
+ var v = subByAuthority[authority];
523
+ if (typeof v === "function") return v();
524
+ if (v === undefined) return Promise.reject(new Error("no subordinate for " + authority));
525
+ return Promise.resolve(v);
526
+ },
527
+ };
528
+ }
529
+
530
+ // Build a valid leaf + anchor set of statements + fetchers.
531
+ function _validChainFixture(opts) {
532
+ opts = opts || {};
533
+ var leaf = _ecEntity("leaf-k");
534
+ var anchor = _ecEntity("anchor-k");
535
+ var leafId = "https://rp.example", anchorId = "https://anchor.example";
536
+ var leafCfg = _mint(leaf.priv, "leaf-k", _cfg(leafId, leaf, {
537
+ authority_hints: [anchorId],
538
+ metadata: { openid_relying_party: { client_name: "RP", contacts: ["x@rp"] } },
539
+ }));
540
+ var anchorCfg = _mint(anchor.priv, "anchor-k", _cfg(anchorId, anchor));
541
+ // Anchor-signed subordinate statement about the leaf; pins the leaf jwks.
542
+ var subClaims = { iss: anchorId, sub: leafId, iat: _NOW, exp: _NOW + 3600 }; // allow:raw-byte-literal — 1h validity
543
+ if (!opts.noJwks) subClaims.jwks = leaf.jwks;
544
+ if (opts.policy) subClaims.metadata_policy = opts.policy;
545
+ var subStmt = _mint(anchor.priv, "anchor-k", subClaims);
546
+ var byUrl = {};
547
+ byUrl[leafId + "/.well-known/openid-federation"] = leafCfg;
548
+ byUrl[anchorId + "/.well-known/openid-federation"] = anchorCfg;
549
+ var m = _memFetchers(byUrl, {});
550
+ m.fetchSubordinate = function () { return Promise.resolve(subStmt); };
551
+ return { leaf: leaf, anchor: anchor, leafId: leafId, anchorId: anchorId,
552
+ anchorJwks: anchor.jwks, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate };
553
+ }
554
+
555
+ async function testChainHappyAndResolve() {
556
+ var f = _validChainFixture({ policy: { openid_relying_party: { contacts: { default: ["fallback@rp"] } } } });
557
+ var anchors = {}; anchors[f.anchorId] = f.anchorJwks;
558
+
559
+ var chain = await b.auth.openidFederation.buildTrustChain({
560
+ leafEntityId: f.leafId, trustAnchors: anchors, fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate,
561
+ });
562
+ check("buildTrustChain: 2-node chain leaf+anchor", chain.length === 2 &&
563
+ chain[0].role === "leaf" && chain[1].role === "trust_anchor");
564
+
565
+ var resolved = await b.auth.openidFederation.resolveLeaf({
566
+ leafEntityId: f.leafId, trustAnchors: anchors, kind: "openid_relying_party",
567
+ fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate,
568
+ });
569
+ check("resolveLeaf: returns effective metadata + trust anchor",
570
+ resolved.trustAnchor === f.anchorId && resolved.effectiveMetadata.client_name === "RP");
571
+
572
+ await _rejects("resolveLeaf: missing kind → no-kind",
573
+ function () {
574
+ return b.auth.openidFederation.resolveLeaf({ leafEntityId: f.leafId, trustAnchors: anchors,
575
+ fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate });
576
+ }, /no-kind/);
577
+
578
+ // A kind the leaf does not declare resolves from an empty metadata base
579
+ // (the `leafClaims.metadata[kind] || {}` fallback) — no crash.
580
+ var opResolved = await b.auth.openidFederation.resolveLeaf({
581
+ leafEntityId: f.leafId, trustAnchors: anchors, kind: "openid_provider",
582
+ fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate,
583
+ });
584
+ check("resolveLeaf: undeclared kind resolves from empty metadata base",
585
+ opResolved.effectiveMetadata && Object.keys(opResolved.effectiveMetadata).length === 0);
586
+ }
587
+
588
+ async function testChainSelfStatement() {
589
+ // Entity config whose iss != entity_id → bad-self-statement.
590
+ var leaf = _ecEntity("leaf-k");
591
+ var leafId = "https://rp.example";
592
+ var badCfg = _mint(leaf.priv, "leaf-k", _cfg("https://evil.example", leaf, { sub: leafId, authority_hints: ["https://a"] }));
593
+ var byUrl = {}; byUrl[leafId + "/.well-known/openid-federation"] = badCfg;
594
+ var m = _memFetchers(byUrl, {});
595
+ await _rejects("buildTrustChain: iss!=entity_id → bad-self-statement",
596
+ function () {
597
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId,
598
+ trustAnchors: { "https://a": {} }, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
599
+ }, /bad-self-statement/);
600
+ }
601
+
602
+ async function testChainLeafWithoutJwks() {
603
+ // A leaf entity config that publishes no jwks: the self-statement verify
604
+ // falls back to an empty JWKS and is refused (no-keys) rather than being
605
+ // waved through — the `parsedEC.claims.jwks || {}` fallback.
606
+ var leaf = _ecEntity("leaf-k");
607
+ var leafId = "https://rp.example";
608
+ var cfg = _mint(leaf.priv, "leaf-k", { iss: leafId, sub: leafId, iat: _NOW, exp: _NOW + 3600, authority_hints: ["https://a"] });
609
+ var byUrl = {}; byUrl[leafId + "/.well-known/openid-federation"] = cfg;
610
+ var m = _memFetchers(byUrl, {});
611
+ await _rejects("buildTrustChain: entity config with no jwks → no-keys",
612
+ function () {
613
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId,
614
+ trustAnchors: { "https://a": {} }, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
615
+ }, /no-keys/);
616
+ }
617
+
618
+ async function testChainNoAuthorityHints() {
619
+ var leaf = _ecEntity("leaf-k");
620
+ var leafId = "https://rp.example";
621
+ var cfg = _mint(leaf.priv, "leaf-k", _cfg(leafId, leaf)); // no authority_hints
622
+ var byUrl = {}; byUrl[leafId + "/.well-known/openid-federation"] = cfg;
623
+ var m = _memFetchers(byUrl, {});
624
+ await _rejects("buildTrustChain: leaf without authority_hints → no-authority-hints",
625
+ function () {
626
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId,
627
+ trustAnchors: { "https://anchor": {} }, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
628
+ }, /no-authority-hints/);
629
+ }
630
+
631
+ async function testChainNoAscent() {
632
+ // Three hints exercising each ascent-failure arm: a malformed subordinate
633
+ // (parse throws a CODED AuthError), an iss/sub-mismatched subordinate
634
+ // (skipped via continue), and a plain uncoded rejection. None yields an
635
+ // ascent → no-ascent aggregating every reason.
636
+ var leaf = _ecEntity("leaf-k");
637
+ var leafId = "https://rp.example";
638
+ var authA = "https://a.example", authB = "https://b.example",
639
+ authC = "https://c.example", authD = "https://d.example";
640
+ var cfg = _mint(leaf.priv, "leaf-k", _cfg(leafId, leaf, { authority_hints: [authA, authB, authC, authD] }));
641
+ var byUrl = {}; byUrl[leafId + "/.well-known/openid-federation"] = cfg;
642
+ var m = _memFetchers(byUrl, {});
643
+ m.fetchSubordinate = function (authority) {
644
+ if (authority === authA) return Promise.resolve("not.a.valid.jwt"); // parse → coded AuthError
645
+ if (authority === authB) {
646
+ // wrong iss (not authB) → iss-sub-mismatch, skipped via continue.
647
+ return Promise.resolve(_mint(leaf.priv, "leaf-k", { iss: "https://wrong", sub: leafId, iat: _NOW, exp: _NOW + 3600, jwks: leaf.jwks }));
648
+ }
649
+ if (authority === authC) return Promise.reject(new Error("network down")); // uncoded → "unknown"
650
+ // A non-Error rejection: coded but message-less → String(err) diagnostic fallback.
651
+ return Promise.reject({ code: "custom/opaque-reject" });
652
+ };
653
+ await _rejects("buildTrustChain: no hint yields a valid subordinate → no-ascent",
654
+ function () {
655
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId,
656
+ trustAnchors: { "https://anchor": {} }, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
657
+ }, /no-ascent/);
658
+ }
659
+
660
+ async function testChainCycle() {
661
+ // A → B → A : the revisit of A is refused as a cyclic authority_hints graph.
662
+ var a = _ecEntity("a-k"), bEnt = _ecEntity("b-k");
663
+ var idA = "https://a.example", idB = "https://b.example";
664
+ var cfgA = _mint(a.priv, "a-k", _cfg(idA, a, { authority_hints: [idB] }));
665
+ var cfgB = _mint(bEnt.priv, "b-k", _cfg(idB, bEnt, { authority_hints: [idA] }));
666
+ var byUrl = {};
667
+ byUrl[idA + "/.well-known/openid-federation"] = cfgA;
668
+ byUrl[idB + "/.well-known/openid-federation"] = cfgB;
669
+ var m = _memFetchers(byUrl, {});
670
+ m.fetchSubordinate = function (authority, sub) {
671
+ // A well-formed subordinate iss=authority sub=sub, so the cycle guard
672
+ // (not an iss/sub-mismatch) is what refuses.
673
+ var signer = authority === idA ? a : bEnt;
674
+ var kid = authority === idA ? "a-k" : "b-k";
675
+ return Promise.resolve(_mint(signer.priv, kid, { iss: authority, sub: sub, iat: _NOW, exp: _NOW + 3600, jwks: (sub === idA ? a : bEnt).jwks }));
676
+ };
677
+ await _rejects("buildTrustChain: cyclic authority_hints → chain-cycle",
678
+ function () {
679
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: idA,
680
+ trustAnchors: { "https://never": {} }, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
681
+ }, /chain-cycle/);
682
+ }
683
+
684
+ async function testChainTooDeep() {
685
+ // maxDepth 1: leaf ascends once to an intermediate, the loop budget is spent
686
+ // before an anchor is reached → chain-too-deep.
687
+ var leaf = _ecEntity("leaf-k"), inter = _ecEntity("int-k");
688
+ var leafId = "https://rp.example", interId = "https://int.example";
689
+ var cfg = _mint(leaf.priv, "leaf-k", _cfg(leafId, leaf, { authority_hints: [interId] }));
690
+ var byUrl = {}; byUrl[leafId + "/.well-known/openid-federation"] = cfg;
691
+ var m = _memFetchers(byUrl, {});
692
+ m.fetchSubordinate = function (authority, sub) {
693
+ return Promise.resolve(_mint(inter.priv, "int-k", { iss: authority, sub: sub, iat: _NOW, exp: _NOW + 3600, jwks: leaf.jwks }));
694
+ };
695
+ await _rejects("buildTrustChain: maxDepth exceeded → chain-too-deep",
696
+ function () {
697
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId, maxDepth: 1,
698
+ trustAnchors: { "https://anchor": {} }, fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
699
+ }, /chain-too-deep/);
700
+ }
701
+
702
+ async function testChainNoAttestedJwks() {
703
+ // A structurally valid leaf→anchor chain where the anchor-signed
704
+ // subordinate pins NO jwks → Phase-2 refuses with no-attested-jwks.
705
+ var f = _validChainFixture({ noJwks: true });
706
+ var anchors = {}; anchors[f.anchorId] = f.anchorJwks;
707
+ await _rejects("buildTrustChain: subordinate pins no jwks → no-attested-jwks",
708
+ function () {
709
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: f.leafId, trustAnchors: anchors,
710
+ fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate });
711
+ }, /no-attested-jwks/);
712
+ }
713
+
714
+ // ---- self-config bound to superior-attested (pinned) keys ----------------
715
+ // The trust decision for an entity's effective metadata is that its Entity
716
+ // Configuration (the metadata source) was signed by a key the superior
717
+ // ATTESTS for it — not merely self-signed. Phase 1 self-verifies the config
718
+ // against its OWN self-published jwks (integrity only); Phase 2 must re-bind
719
+ // the config to the keys the superior's subordinate statement pins.
720
+
721
+ async function testChainLeafConfigNotBoundToPinnedKeys() {
722
+ // Fail-open repro: an attacker controls the leaf's .well-known endpoint but
723
+ // NOT its federation-attested key. They serve a self-signed config carrying
724
+ // forged metadata + their own jwks (Phase-1 self-verify passes); the honest
725
+ // anchor's subordinate statement pins the leaf's REAL keys. The chain must
726
+ // refuse — the forged config was not signed by an attested key. Same kid on
727
+ // both keys forces a signature check (not a kid mismatch).
728
+ var honest = _ecEntity("leaf-k");
729
+ var evil = _ecEntity("leaf-k");
730
+ var anchor = _ecEntity("anchor-k");
731
+ var leafId = "https://rp.example", anchorId = "https://anchor.example";
732
+
733
+ var forgedLeafCfg = _mint(evil.priv, "leaf-k", _cfg(leafId, evil, {
734
+ authority_hints: [anchorId],
735
+ metadata: { openid_relying_party: { client_name: "ATTACKER", redirect_uris: ["https://evil.example/cb"] } },
736
+ }));
737
+ var anchorCfg = _mint(anchor.priv, "anchor-k", _cfg(anchorId, anchor));
738
+ var subStmt = _mint(anchor.priv, "anchor-k",
739
+ { iss: anchorId, sub: leafId, iat: _NOW, exp: _NOW + 3600, jwks: honest.jwks }); // allow:raw-byte-literal — 1h validity
740
+
741
+ var byUrl = {};
742
+ byUrl[leafId + "/.well-known/openid-federation"] = forgedLeafCfg;
743
+ byUrl[anchorId + "/.well-known/openid-federation"] = anchorCfg;
744
+ var m = _memFetchers(byUrl, {});
745
+ m.fetchSubordinate = function () { return Promise.resolve(subStmt); };
746
+ var anchors = {}; anchors[anchorId] = anchor.jwks;
747
+
748
+ await _rejects("buildTrustChain: leaf config signed by non-attested key refused",
749
+ function () {
750
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId, trustAnchors: anchors,
751
+ fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
752
+ }, /bad-signature/);
753
+
754
+ await _rejects("resolveLeaf: forged leaf metadata never resolved (config unbound to pinned keys)",
755
+ function () {
756
+ return b.auth.openidFederation.resolveLeaf({ leafEntityId: leafId, trustAnchors: anchors,
757
+ kind: "openid_relying_party", fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate });
758
+ }, /bad-signature/);
759
+ }
760
+
761
+ // Build a 3-node leaf → intermediate → anchor fixture. `opts.forgeIntermediate`
762
+ // re-signs the intermediate's self-config with an attacker key of the SAME kid
763
+ // while the anchor still pins the intermediate's REAL keys.
764
+ function _threeNodeFixture(opts) {
765
+ opts = opts || {};
766
+ var leaf = _ecEntity("leaf-k");
767
+ var inter = _ecEntity("int-k");
768
+ var anchor = _ecEntity("anchor-k");
769
+ var leafId = "https://rp.example", interId = "https://int.example", anchorId = "https://anchor.example";
770
+
771
+ var interSigner = opts.forgeIntermediate ? _ecEntity("int-k") : inter;
772
+
773
+ var leafCfg = _mint(leaf.priv, "leaf-k", _cfg(leafId, leaf, {
774
+ authority_hints: [interId],
775
+ metadata: { openid_relying_party: { client_name: "RP" } },
776
+ }));
777
+ // Self-jwks matches whoever signed it so the Phase-1 self-verify passes.
778
+ var interCfg = _mint(interSigner.priv, "int-k", _cfg(interId, interSigner, { authority_hints: [anchorId] }));
779
+ var anchorCfg = _mint(anchor.priv, "anchor-k", _cfg(anchorId, anchor));
780
+
781
+ // Anchor-signed subordinate about the intermediate pins the intermediate's
782
+ // REAL keys; intermediate-signed subordinate about the leaf pins the leaf's.
783
+ var subInter = _mint(anchor.priv, "anchor-k",
784
+ { iss: anchorId, sub: interId, iat: _NOW, exp: _NOW + 3600, jwks: inter.jwks }); // allow:raw-byte-literal — 1h validity
785
+ var subLeaf = _mint(inter.priv, "int-k",
786
+ { iss: interId, sub: leafId, iat: _NOW, exp: _NOW + 3600, jwks: leaf.jwks }); // allow:raw-byte-literal — 1h validity
787
+
788
+ var byUrl = {};
789
+ byUrl[leafId + "/.well-known/openid-federation"] = leafCfg;
790
+ byUrl[interId + "/.well-known/openid-federation"] = interCfg;
791
+ byUrl[anchorId + "/.well-known/openid-federation"] = anchorCfg;
792
+ var m = _memFetchers(byUrl, {});
793
+ m.fetchSubordinate = function (authority) {
794
+ if (authority === interId) return Promise.resolve(subLeaf);
795
+ if (authority === anchorId) return Promise.resolve(subInter);
796
+ return Promise.reject(new Error("no subordinate for " + authority));
797
+ };
798
+ var anchors = {}; anchors[anchorId] = anchor.jwks;
799
+ return { leafId: leafId, interId: interId, anchorId: anchorId, anchors: anchors,
800
+ fetcher: m.fetcher, fetchSubordinate: m.fetchSubordinate };
801
+ }
802
+
803
+ async function testChainThreeNodeHappy() {
804
+ // A full leaf → intermediate → anchor chain resolves and exercises the
805
+ // Phase-2 pinned-key config verify for an INTERMEDIATE node (not just the
806
+ // leaf) on the honest path.
807
+ var f = _threeNodeFixture();
808
+ var chain = await b.auth.openidFederation.buildTrustChain({
809
+ leafEntityId: f.leafId, trustAnchors: f.anchors, fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate });
810
+ check("buildTrustChain: 3-node leaf+intermediate+anchor chain",
811
+ chain.length === 3 && chain[0].role === "leaf" &&
812
+ chain[1].role === "intermediate" && chain[2].role === "trust_anchor");
813
+
814
+ var resolved = await b.auth.openidFederation.resolveLeaf({
815
+ leafEntityId: f.leafId, trustAnchors: f.anchors, kind: "openid_relying_party",
816
+ fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate });
817
+ check("resolveLeaf: 3-node chain resolves effective metadata",
818
+ resolved.trustAnchor === f.anchorId && resolved.effectiveMetadata.client_name === "RP");
819
+ }
820
+
821
+ async function testChainIntermediateConfigNotBoundToPinnedKeys() {
822
+ // The fail-open one hop up: a forged INTERMEDIATE self-config (attacker key,
823
+ // same kid) with the anchor pinning the intermediate's REAL keys must fail
824
+ // the chain — proving the pinned-key config binding covers every non-anchor
825
+ // node, not just the leaf.
826
+ var f = _threeNodeFixture({ forgeIntermediate: true });
827
+ await _rejects("buildTrustChain: intermediate config signed by non-attested key refused",
828
+ function () {
829
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: f.leafId, trustAnchors: f.anchors,
830
+ fetcher: f.fetcher, fetchSubordinate: f.fetchSubordinate });
831
+ }, /bad-signature/);
832
+ }
833
+
834
+ // ---- default httpClient fetcher + default subordinate fetcher ------------
835
+ // These stub httpClient.request (the same module instance openid-federation
836
+ // lazy-requires) so no explicit fetcher/fetchSubordinate is passed and the
837
+ // framework's own fetch closures execute. Restored in finally.
838
+
839
+ async function _withStubbedRequest(handler, fn) {
840
+ var orig = httpClient.request;
841
+ httpClient.request = handler;
842
+ try { return await fn(); }
843
+ finally { httpClient.request = orig; }
844
+ }
845
+
846
+ async function testDefaultFetcherErrorPaths() {
847
+ var leafId = "https://rp.example";
848
+ await _withStubbedRequest(function () { return Promise.resolve({ statusCode: 404 }); }, function () {
849
+ return _rejects("default fetcher: non-2xx status → fetch-failed",
850
+ function () {
851
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId, trustAnchors: { "https://a": {} } });
852
+ }, /fetch-failed/);
853
+ });
854
+ await _withStubbedRequest(function () { return Promise.resolve({ statusCode: 200, body: null }); }, function () {
855
+ return _rejects("default fetcher: empty body → empty-response",
856
+ function () {
857
+ return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId, trustAnchors: { "https://a": {} } });
858
+ }, /empty-response/);
859
+ });
860
+ }
861
+
862
+ async function testDefaultSubordinateFetcher() {
863
+ // Full chain over the default httpClient fetcher AND the default subordinate
864
+ // fetcher (federation_fetch_endpoint discovery). Covers the success return
865
+ // of both closures.
866
+ var leaf = _ecEntity("leaf-k");
867
+ var anchor = _ecEntity("anchor-k");
868
+ var leafId = "https://rp.example", anchorId = "https://anchor.example";
869
+ var fetchEp = anchorId + "/fetch";
870
+ var leafCfg = _mint(leaf.priv, "leaf-k", _cfg(leafId, leaf, {
871
+ authority_hints: [anchorId], metadata: { openid_relying_party: { client_name: "RP" } },
872
+ }));
873
+ var anchorCfg = _mint(anchor.priv, "anchor-k", _cfg(anchorId, anchor, { federation_fetch_endpoint: fetchEp }));
874
+ var subStmt = _mint(anchor.priv, "anchor-k", { iss: anchorId, sub: leafId, iat: _NOW, exp: _NOW + 3600, jwks: leaf.jwks });
875
+ var route = {};
876
+ route[leafId + "/.well-known/openid-federation"] = leafCfg;
877
+ route[anchorId + "/.well-known/openid-federation"] = anchorCfg;
878
+
879
+ function handler(reqOpts) {
880
+ var u = reqOpts.url;
881
+ if (route[u]) return Promise.resolve({ statusCode: 200, body: Buffer.from(route[u], "utf8") });
882
+ if (u.indexOf(fetchEp) === 0) return Promise.resolve({ statusCode: 200, body: Buffer.from(subStmt, "utf8") });
883
+ return Promise.resolve({ statusCode: 404 });
884
+ }
885
+ var anchors = {}; anchors[anchorId] = anchor.jwks;
886
+ await _withStubbedRequest(handler, function () {
887
+ return (async function () {
888
+ var chain = await b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId, trustAnchors: anchors });
889
+ check("default subordinate fetcher: full chain via federation_fetch_endpoint",
890
+ chain.length === 2 && chain[1].role === "trust_anchor");
891
+ })();
892
+ });
893
+
894
+ // no-fetch-endpoint: anchor config omits federation_fetch_endpoint → the
895
+ // default subordinate fetcher throws, surfaced through the ascent path.
896
+ var anchorNoEp = _mint(anchor.priv, "anchor-k", _cfg(anchorId, anchor));
897
+ var route2 = {};
898
+ route2[leafId + "/.well-known/openid-federation"] = leafCfg;
899
+ route2[anchorId + "/.well-known/openid-federation"] = anchorNoEp;
900
+ function handler2(reqOpts) {
901
+ var u = reqOpts.url;
902
+ if (route2[u]) return Promise.resolve({ statusCode: 200, body: Buffer.from(route2[u], "utf8") });
903
+ return Promise.resolve({ statusCode: 404 });
904
+ }
905
+ await _withStubbedRequest(handler2, function () {
906
+ return _rejects("default subordinate fetcher: no federation_fetch_endpoint → no-ascent (no-fetch-endpoint)",
907
+ function () { return b.auth.openidFederation.buildTrustChain({ leafEntityId: leafId, trustAnchors: anchors }); },
908
+ /no-ascent/);
909
+ });
910
+ }
911
+
912
+ async function run() {
913
+ testParseRejections();
914
+ testVerifyKeySelection();
915
+ testVerifyKidless();
916
+ testVerifyAlgKtyConfusion();
917
+ testVerifyPs256();
918
+ testVerifySignatureAndTime();
919
+ testPolicyGuards();
920
+ testPolicyOperators();
921
+ testPolicyMultiNodeNarrowing();
922
+ testPolicyMergeCrossLevel();
923
+ testPolicySubsetOfArrayType();
924
+ testPolicyPrototypePollution();
925
+ await testChainValidation();
926
+ await testChainHappyAndResolve();
927
+ await testChainSelfStatement();
928
+ await testChainLeafWithoutJwks();
929
+ await testChainNoAuthorityHints();
930
+ await testChainNoAscent();
931
+ await testChainCycle();
932
+ await testChainTooDeep();
933
+ await testChainNoAttestedJwks();
934
+ await testChainLeafConfigNotBoundToPinnedKeys();
935
+ await testChainThreeNodeHappy();
936
+ await testChainIntermediateConfigNotBoundToPinnedKeys();
937
+ await testDefaultFetcherErrorPaths();
938
+ await testDefaultSubordinateFetcher();
939
+ }
940
+
941
+ module.exports = { run: run };
942
+
943
+ if (require.main === module) {
944
+ run().then(function () { console.log("OK"); })
945
+ .catch(function (e) { console.error(e.stack || e); process.exit(1); });
946
+ }