@blamejs/blamejs-shop 0.5.12 → 0.5.13

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 (521) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +632 -416
  4. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  5. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  6. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  7. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  8. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  9. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  10. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  11. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  12. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  13. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  14. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  15. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  16. package/lib/vendor/blamejs/.gitignore +2 -0
  17. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  18. package/lib/vendor/blamejs/NOTICE +26 -1
  19. package/lib/vendor/blamejs/SECURITY.md +1 -1
  20. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  21. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  22. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  23. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  24. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  25. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  26. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  27. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  28. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  29. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  30. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  31. package/lib/vendor/blamejs/index.js +6 -0
  32. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  33. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  34. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  35. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  36. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  37. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  38. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  39. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  40. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  41. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  42. package/lib/vendor/blamejs/lib/audit.js +71 -8
  43. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  44. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  45. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  46. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  47. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  48. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  49. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  50. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  51. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  52. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  53. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  54. package/lib/vendor/blamejs/lib/base32.js +21 -0
  55. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  56. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  57. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  58. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  59. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  60. package/lib/vendor/blamejs/lib/cert.js +29 -11
  61. package/lib/vendor/blamejs/lib/cli.js +94 -24
  62. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  63. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  65. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  66. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  67. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  68. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  69. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  70. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  71. package/lib/vendor/blamejs/lib/cose.js +31 -16
  72. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  73. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  74. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  75. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  76. package/lib/vendor/blamejs/lib/csp.js +11 -3
  77. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  78. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  79. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  80. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  81. package/lib/vendor/blamejs/lib/db.js +18 -6
  82. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  83. package/lib/vendor/blamejs/lib/dev.js +21 -2
  84. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  85. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  86. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  87. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  88. package/lib/vendor/blamejs/lib/forms.js +113 -27
  89. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  90. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  91. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  92. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  93. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  94. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  95. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  96. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  97. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  98. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  99. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  100. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  101. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  102. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  105. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  106. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  107. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  108. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  109. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  110. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  111. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  112. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  113. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  114. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  115. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  116. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  117. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  118. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  119. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  120. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  121. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  123. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  124. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  125. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  126. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  128. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  129. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  130. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  131. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  132. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  133. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  134. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  136. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  137. package/lib/vendor/blamejs/lib/mail.js +15 -5
  138. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  139. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  140. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  141. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  142. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  143. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  144. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  145. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  146. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  147. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  148. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  149. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  150. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  151. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  153. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  154. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  155. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  156. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  157. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  158. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  159. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  160. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  161. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  162. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  163. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  164. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  165. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  166. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  167. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  168. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  169. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  170. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  171. package/lib/vendor/blamejs/lib/redact.js +54 -0
  172. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  173. package/lib/vendor/blamejs/lib/restore.js +19 -0
  174. package/lib/vendor/blamejs/lib/retention.js +12 -4
  175. package/lib/vendor/blamejs/lib/router.js +60 -6
  176. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  177. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  178. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  179. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  180. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  181. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  182. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  183. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  184. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  185. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  186. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  187. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  188. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  189. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  190. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  191. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  192. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  193. package/lib/vendor/blamejs/lib/session.js +34 -12
  194. package/lib/vendor/blamejs/lib/sql.js +15 -1
  195. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  196. package/lib/vendor/blamejs/lib/static.js +55 -13
  197. package/lib/vendor/blamejs/lib/storage.js +8 -2
  198. package/lib/vendor/blamejs/lib/subject.js +6 -1
  199. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  200. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  201. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  202. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  203. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  204. package/lib/vendor/blamejs/lib/vc.js +44 -5
  205. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  206. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  207. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  208. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  209. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  210. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  212. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  213. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  214. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  215. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  216. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  217. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  218. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  219. package/lib/vendor/blamejs/package-lock.json +2 -2
  220. package/lib/vendor/blamejs/package.json +1 -1
  221. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  222. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  223. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  224. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  245. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  246. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  247. package/lib/vendor/blamejs/socket.yml +94 -0
  248. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  249. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  250. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  251. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  252. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  253. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  254. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  255. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  256. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  257. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  258. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  259. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  262. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  268. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  284. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  293. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  302. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  307. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  321. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  322. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  324. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  326. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  327. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  330. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  334. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  335. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  336. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  337. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  348. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  376. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  388. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  413. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  414. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  415. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  416. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  428. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  432. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  434. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  442. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  443. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  445. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  477. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  478. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  480. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  490. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  491. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  492. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  493. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  495. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  502. package/lib/vendor/blamejs/test/smoke.js +2 -0
  503. package/package.json +1 -1
  504. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  505. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  506. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  507. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  508. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  509. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  510. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  511. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  512. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  513. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  514. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  515. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  516. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  517. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  518. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  519. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  520. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  521. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -8,14 +8,28 @@
8
8
  * out of scope for the smoke runner; what ships here is the create-
9
9
  * time validation, JWS shape, AKI/serial extraction, and the renewIfDue
10
10
  * before/in/after-window verdicts via the AcmeError shape.
11
+ * Also here: the create() key-normalization branches, the pure PKCS#10
12
+ * buildCsr builder (P-256 / P-384 / RSA, with signature verification),
13
+ * the offline-reachable order / challenge / revoke / deactivate guards,
14
+ * and the network-driven flows (directory, account + EAB, order,
15
+ * finalize, cert polling, authorizations, ARI verdicts, key rollover,
16
+ * listProfiles) driven through a loopback-stubbed httpClient.request —
17
+ * no CA is ever contacted.
11
18
  */
12
19
 
13
20
  var helpers = require("../helpers");
14
21
  var b = helpers.b;
15
22
  var check = helpers.check;
16
23
 
24
+ var nodeCrypto = require("node:crypto");
25
+
26
+ var asn1 = require("../../lib/asn1-der");
27
+ var C = require("../../lib/constants");
28
+ var httpClient = require("../../lib/http-client");
29
+
30
+ var CA = "https://ca.example.test";
31
+
17
32
  function _newKey() {
18
- var nodeCrypto = require("node:crypto");
19
33
  return nodeCrypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
20
34
  }
21
35
 
@@ -41,7 +55,6 @@ function testCreateRefusesNonHttpsDirectory() {
41
55
  }
42
56
 
43
57
  function testCreateRefusesNonP256Key() {
44
- var nodeCrypto = require("node:crypto");
45
58
  var rsa = nodeCrypto.generateKeyPairSync("rsa", { modulusLength: 2048 });
46
59
  var threw = null;
47
60
  try {
@@ -204,6 +217,1553 @@ function testV0883NewOrderProfileValidation() {
204
217
  typeof acme.newOrder === "function");
205
218
  }
206
219
 
220
+ function _handle() {
221
+ var k = _newKey();
222
+ return b.acme.create({
223
+ directory: "https://ca.example.test/directory",
224
+ accountKey: k.privateKey,
225
+ });
226
+ }
227
+
228
+ // Capture the AcmeError code from a synchronous throw.
229
+ function _codeOf(fn) {
230
+ try { fn(); return null; }
231
+ catch (e) { return (e && e.code) || null; }
232
+ }
233
+
234
+ // Capture the AcmeError code from a rejected promise.
235
+ async function _acode(promise) {
236
+ try { await promise; return "NO-THROW"; }
237
+ catch (e) { return (e && e.code) || ("PLAIN:" + (e && e.message)); }
238
+ }
239
+
240
+ // ---- minimal DER TLV reader — used ONLY to verify buildCsr output ----
241
+ // (definite-form length; returns the byte boundaries of one TLV).
242
+ function _readTLV(buf, off) {
243
+ var lenByte = buf[off + 1];
244
+ var contentStart, contentLen;
245
+ if (lenByte < 0x80) {
246
+ contentLen = lenByte;
247
+ contentStart = off + 2;
248
+ } else {
249
+ var n = lenByte & 0x7f;
250
+ contentLen = 0;
251
+ for (var i = 0; i < n; i += 1) contentLen = (contentLen * 256) + buf[off + 2 + i];
252
+ contentStart = off + 2 + n;
253
+ }
254
+ return {
255
+ tag: buf[off],
256
+ contentStart: contentStart,
257
+ contentLen: contentLen,
258
+ tlvEnd: contentStart + contentLen,
259
+ };
260
+ }
261
+
262
+ function _csrPemToDer(pem) {
263
+ var b64 = pem
264
+ .replace(/-----BEGIN CERTIFICATE REQUEST-----/, "")
265
+ .replace(/-----END CERTIFICATE REQUEST-----/, "")
266
+ .replace(/\s+/g, "");
267
+ return Buffer.from(b64, "base64");
268
+ }
269
+
270
+ // Verify the signature inside a CSR: signature is over the DER of the
271
+ // first child (CertificationRequestInfo) using the supplied public key.
272
+ function _csrSignatureVerifies(pem, publicKey, digest) {
273
+ var der = _csrPemToDer(pem);
274
+ var outer = _readTLV(der, 0); // CertificationRequest SEQUENCE
275
+ var cri = _readTLV(der, outer.contentStart); // certReqInfo SEQUENCE (child 0)
276
+ var criTlv = der.subarray(outer.contentStart, cri.tlvEnd);
277
+ var sigAlg = _readTLV(der, cri.tlvEnd); // signatureAlgorithm (child 1)
278
+ var sigBit = _readTLV(der, sigAlg.tlvEnd); // signature BIT STRING (child 2)
279
+ // BIT STRING content: first byte = unused-bits count (0), rest = sig.
280
+ var sig = der.subarray(sigBit.contentStart + 1, sigBit.tlvEnd);
281
+ var v = nodeCrypto.createVerify(digest);
282
+ v.update(criTlv);
283
+ return v.verify(publicKey, sig);
284
+ }
285
+
286
+ // ---- create(): directory + accountKey normalization branches ----
287
+
288
+ function testCreateRefusesMissingDirectory() {
289
+ var k = _newKey();
290
+ check("create refuses missing directory",
291
+ _codeOf(function () { b.acme.create({ accountKey: k.privateKey }); }) === "acme/bad-directory");
292
+ check("create refuses empty directory string",
293
+ _codeOf(function () {
294
+ b.acme.create({ directory: "", accountKey: k.privateKey });
295
+ }) === "acme/bad-directory");
296
+ }
297
+
298
+ function testCreateRefusesMissingAccountKey() {
299
+ check("create refuses missing accountKey",
300
+ _codeOf(function () {
301
+ b.acme.create({ directory: "https://ca.example.test/directory" });
302
+ }) === "acme/bad-account-key");
303
+ }
304
+
305
+ function testCreateRefusesPublicKeyObject() {
306
+ var k = _newKey();
307
+ // A public KeyObject is not "private", carries no privatePem and no
308
+ // nested privateKey → the create() normalizer must refuse it.
309
+ check("create refuses a public KeyObject as accountKey",
310
+ _codeOf(function () {
311
+ b.acme.create({ directory: "https://ca.example.test/directory", accountKey: k.publicKey });
312
+ }) === "acme/bad-account-key");
313
+ }
314
+
315
+ function testCreateAcceptsPrivatePem() {
316
+ var k = _newKey();
317
+ var privatePem = k.privateKey.export({ type: "pkcs8", format: "pem" });
318
+ var acme = b.acme.create({
319
+ directory: "https://ca.example.test/directory",
320
+ accountKey: { privatePem: privatePem },
321
+ });
322
+ var jwk = acme.publicJwk();
323
+ check("create accepts { privatePem } and derives the P-256 public JWK",
324
+ jwk.kty === "EC" && jwk.crv === "P-256" &&
325
+ typeof jwk.x === "string" && typeof jwk.y === "string");
326
+ }
327
+
328
+ function testCreateAcceptsNestedPrivateKey() {
329
+ var k = _newKey();
330
+ var acme = b.acme.create({
331
+ directory: "https://ca.example.test/directory",
332
+ accountKey: { privateKey: k.privateKey },
333
+ });
334
+ check("create accepts { privateKey: KeyObject } nested shape",
335
+ acme.publicJwk().kty === "EC");
336
+ }
337
+
338
+ function testCreateRefusesBadPrivatePem() {
339
+ check("create refuses an unparseable privatePem",
340
+ _codeOf(function () {
341
+ b.acme.create({
342
+ directory: "https://ca.example.test/directory",
343
+ accountKey: { privatePem: "-----BEGIN PRIVATE KEY-----\nnope\n-----END PRIVATE KEY-----" },
344
+ });
345
+ }) === "acme/bad-account-key");
346
+ }
347
+
348
+ function testCreateRefusesUnknownOpt() {
349
+ var k = _newKey();
350
+ var threw = null;
351
+ try {
352
+ b.acme.create({
353
+ directory: "https://ca.example.test/directory",
354
+ accountKey: k.privateKey,
355
+ bogusOption: true,
356
+ });
357
+ } catch (e) { threw = e; }
358
+ // validateOpts throws a plain Error (code-shaped message) for typos.
359
+ check("create refuses an unknown opt key (typo guard)",
360
+ threw && /unknown option 'bogusOption'/.test(threw.message || ""));
361
+ }
362
+
363
+ function testCreateContactShapeBranches() {
364
+ var k = _newKey();
365
+ function mk(contact) {
366
+ return b.acme.create({
367
+ directory: "https://ca.example.test/directory",
368
+ accountKey: k.privateKey,
369
+ contact: contact,
370
+ });
371
+ }
372
+ check("create refuses a non-array contact",
373
+ _codeOf(function () { mk("mailto:ops@example.com"); }) === "acme/bad-contact");
374
+ var longContact = "mailto:" + "a".repeat(300) + "@example.com";
375
+ check("create refuses an over-length contact URI",
376
+ _codeOf(function () { mk([longContact]); }) === "acme/bad-contact");
377
+ check("create accepts a valid mailto contact",
378
+ typeof mk(["mailto:ops@example.com"]).newAccount === "function");
379
+ check("create accepts a valid tel contact",
380
+ typeof mk(["tel:+15551234567"]).newAccount === "function");
381
+ }
382
+
383
+ // ---- getters + pure key-derived helpers ----
384
+
385
+ function testGettersNullBeforeLifecycle() {
386
+ var acme = _handle();
387
+ check("accountUrl() is null before newAccount()", acme.accountUrl() === null);
388
+ check("directory() is null before fetchDirectory()", acme.directory() === null);
389
+ }
390
+
391
+ function testPublicJwkReturnsIsolatedCopy() {
392
+ var acme = _handle();
393
+ var j = acme.publicJwk();
394
+ j.x = "TAMPERED";
395
+ j.injected = "x";
396
+ check("publicJwk() returns a fresh copy (mutation does not leak back)",
397
+ acme.publicJwk().x !== "TAMPERED" && acme.publicJwk().injected === undefined);
398
+ }
399
+
400
+ function testKeyAuthorizationDeterministicAndDistinct() {
401
+ var acme = _handle();
402
+ var a1 = acme.keyAuthorization("tokenA");
403
+ var a2 = acme.keyAuthorization("tokenA");
404
+ var b1 = acme.keyAuthorization("tokenB");
405
+ check("keyAuthorization is deterministic for the same token", a1 === a2);
406
+ check("keyAuthorization differs across tokens", a1 !== b1);
407
+ // token + "." + thumbprint — the thumbprint segment is base64url.
408
+ check("keyAuthorization thumbprint segment is base64url",
409
+ /^tokenA\.[A-Za-z0-9_-]+$/.test(a1));
410
+ }
411
+
412
+ function testTlsAlpn01KeyAuthorization() {
413
+ var acme = _handle();
414
+ var digest = acme.tlsAlpn01KeyAuthorization("tok-xyz");
415
+ check("tlsAlpn01KeyAuthorization returns a 32-byte SHA-256 Buffer",
416
+ Buffer.isBuffer(digest) && digest.length === 32);
417
+ // RFC 8737: digest == SHA-256(keyAuthorization(token)).
418
+ var expected = nodeCrypto.createHash("sha256")
419
+ .update(acme.keyAuthorization("tok-xyz"), "utf8").digest();
420
+ check("tlsAlpn01KeyAuthorization == SHA-256(keyAuthorization(token))",
421
+ Buffer.compare(digest, expected) === 0);
422
+ check("tlsAlpn01KeyAuthorization refuses an empty token",
423
+ _codeOf(function () { acme.tlsAlpn01KeyAuthorization(""); }) === "acme/bad-token");
424
+ check("tlsAlpn01KeyAuthorization refuses a non-string token",
425
+ _codeOf(function () { acme.tlsAlpn01KeyAuthorization(123); }) === "acme/bad-token");
426
+ }
427
+
428
+ function testDnsAccount01ValidationBeforeAccount() {
429
+ var acme = _handle();
430
+ // token + identifier validation fire BEFORE the accountUrl guard.
431
+ check("dnsAccount01ChallengeRecord refuses an empty token",
432
+ _codeOf(function () {
433
+ acme.dnsAccount01ChallengeRecord("", { identifier: "example.com" });
434
+ }) === "acme/bad-token");
435
+ check("dnsAccount01ChallengeRecord refuses a non-string token",
436
+ _codeOf(function () {
437
+ acme.dnsAccount01ChallengeRecord(42, { identifier: "example.com" });
438
+ }) === "acme/bad-token");
439
+ check("dnsAccount01ChallengeRecord refuses a missing identifier",
440
+ _codeOf(function () {
441
+ acme.dnsAccount01ChallengeRecord("tok", {});
442
+ }) === "acme/bad-identifier");
443
+ check("dnsAccount01ChallengeRecord refuses an over-length identifier",
444
+ _codeOf(function () {
445
+ acme.dnsAccount01ChallengeRecord("tok", { identifier: "a".repeat(300) });
446
+ }) === "acme/bad-identifier");
447
+ }
448
+
449
+ // ---- buildCsr: pure PKCS#10 builder ----
450
+
451
+ function testBuildCsrInputValidation() {
452
+ var acme = _handle();
453
+ var ec = _newKey();
454
+ check("buildCsr refuses missing opts",
455
+ _codeOf(function () { acme.buildCsr(); }) === "acme/bad-csr-opts");
456
+ check("buildCsr refuses a non-private privateKey",
457
+ _codeOf(function () {
458
+ acme.buildCsr({ privateKey: ec.publicKey, publicKey: ec.publicKey, domains: ["x.com"] });
459
+ }) === "acme/bad-csr-private-key");
460
+ check("buildCsr refuses a non-public publicKey",
461
+ _codeOf(function () {
462
+ acme.buildCsr({ privateKey: ec.privateKey, publicKey: ec.privateKey, domains: ["x.com"] });
463
+ }) === "acme/bad-csr-public-key");
464
+ check("buildCsr refuses a non-array domains",
465
+ _codeOf(function () {
466
+ acme.buildCsr({ privateKey: ec.privateKey, publicKey: ec.publicKey, domains: "x.com" });
467
+ }) === "acme/bad-csr-domains");
468
+ check("buildCsr refuses an empty domains array",
469
+ _codeOf(function () {
470
+ acme.buildCsr({ privateKey: ec.privateKey, publicKey: ec.publicKey, domains: [] });
471
+ }) === "acme/bad-csr-domains");
472
+ check("buildCsr refuses a non-string domain element",
473
+ _codeOf(function () {
474
+ acme.buildCsr({ privateKey: ec.privateKey, publicKey: ec.publicKey, domains: [123] });
475
+ }) === "acme/bad-csr-domain");
476
+ check("buildCsr refuses an empty domain element",
477
+ _codeOf(function () {
478
+ acme.buildCsr({ privateKey: ec.privateKey, publicKey: ec.publicKey, domains: [""] });
479
+ }) === "acme/bad-csr-domain");
480
+ check("buildCsr refuses an over-length domain element",
481
+ _codeOf(function () {
482
+ acme.buildCsr({ privateKey: ec.privateKey, publicKey: ec.publicKey, domains: ["a".repeat(300)] });
483
+ }) === "acme/bad-csr-domain");
484
+ }
485
+
486
+ function testBuildCsrP256() {
487
+ var acme = _handle();
488
+ var pair = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
489
+ var csr = acme.buildCsr({
490
+ privateKey: pair.privateKey,
491
+ publicKey: pair.publicKey,
492
+ domains: ["example.com", "www.example.com"],
493
+ });
494
+ check("buildCsr (P-256) emits a CERTIFICATE REQUEST PEM",
495
+ csr.indexOf("-----BEGIN CERTIFICATE REQUEST-----") === 0 &&
496
+ csr.indexOf("-----END CERTIFICATE REQUEST-----") !== -1);
497
+ check("buildCsr (P-256) produces a signature that verifies (ecdsa-with-SHA256)",
498
+ _csrSignatureVerifies(csr, pair.publicKey, "sha256"));
499
+ }
500
+
501
+ function testBuildCsrP384() {
502
+ var acme = _handle();
503
+ var pair = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "P-384" });
504
+ var csr = acme.buildCsr({
505
+ privateKey: pair.privateKey,
506
+ publicKey: pair.publicKey,
507
+ domains: ["p384.example.com"],
508
+ });
509
+ check("buildCsr (P-384) produces a signature that verifies (ecdsa-with-SHA384)",
510
+ _csrSignatureVerifies(csr, pair.publicKey, "sha384"));
511
+ }
512
+
513
+ function testBuildCsrRsa() {
514
+ var acme = _handle();
515
+ var pair = nodeCrypto.generateKeyPairSync("rsa", { modulusLength: 2048 });
516
+ var csr = acme.buildCsr({
517
+ privateKey: pair.privateKey,
518
+ publicKey: pair.publicKey,
519
+ domains: ["rsa.example.com"],
520
+ });
521
+ check("buildCsr (RSA-2048) produces a signature that verifies (sha256WithRSAEncryption)",
522
+ _csrSignatureVerifies(csr, pair.publicKey, "sha256"));
523
+ }
524
+
525
+ function testBuildCsrRejectsUnsupportedKeys() {
526
+ var acme = _handle();
527
+ var ed = nodeCrypto.generateKeyPairSync("ed25519");
528
+ check("buildCsr rejects Ed25519 leaf keys",
529
+ _codeOf(function () {
530
+ acme.buildCsr({ privateKey: ed.privateKey, publicKey: ed.publicKey, domains: ["ed.example.com"] });
531
+ }) === "acme/bad-csr-key-type");
532
+ var p521 = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "secp521r1" });
533
+ check("buildCsr rejects an unsupported ECDSA curve (P-521)",
534
+ _codeOf(function () {
535
+ acme.buildCsr({ privateKey: p521.privateKey, publicKey: p521.publicKey, domains: ["p521.example.com"] });
536
+ }) === "acme/bad-csr-curve");
537
+ }
538
+
539
+ // ---- offline-reachable order / challenge / revoke / deactivate guards ----
540
+
541
+ async function testFinalizeValidation() {
542
+ var acme = _handle();
543
+ check("finalize refuses a null order",
544
+ (await _acode(acme.finalize(null, Buffer.from([1])))) === "acme/bad-order");
545
+ check("finalize refuses an order without a finalize URL",
546
+ (await _acode(acme.finalize({}, Buffer.from([1])))) === "acme/bad-order");
547
+ check("finalize refuses a CSR that is neither Buffer nor PEM string",
548
+ (await _acode(acme.finalize({ finalize: "https://ca.example.test/f" }, 12345))) === "acme/bad-csr");
549
+ check("finalize refuses a CSR string without the PEM marker",
550
+ (await _acode(acme.finalize({ finalize: "https://ca.example.test/f" }, "xxxxx"))) === "acme/bad-csr");
551
+ check("finalize refuses an empty CSR buffer",
552
+ (await _acode(acme.finalize({ finalize: "https://ca.example.test/f" }, Buffer.alloc(0)))) === "acme/bad-csr");
553
+ check("finalize refuses an oversize CSR buffer (> 64 KiB)",
554
+ (await _acode(acme.finalize({ finalize: "https://ca.example.test/f" }, Buffer.alloc(64 * 1024 + 1)))) === "acme/bad-csr");
555
+ }
556
+
557
+ async function testSignedPostNeedsDirectory() {
558
+ // A well-formed finalize call clears validation, then the first signed
559
+ // POST demands a fetched directory for the nonce — surfaced offline.
560
+ var acme = _handle();
561
+ var pair = nodeCrypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
562
+ var csr = acme.buildCsr({ privateKey: pair.privateKey, publicKey: pair.publicKey, domains: ["x.example.com"] });
563
+ check("a signed POST without a fetched directory throws acme/no-directory",
564
+ (await _acode(acme.finalize({ finalize: "https://ca.example.test/f", url: "https://ca.example.test/o" }, csr))) === "acme/no-directory");
565
+ }
566
+
567
+ async function testRevokeCertRejectsNonBuffer() {
568
+ var acme = _handle();
569
+ check("revokeCert refuses a non-Buffer cert argument",
570
+ (await _acode(acme.revokeCert("not-a-buffer"))) === "acme/revoke-bad-cert");
571
+ }
572
+
573
+ async function testDeactivateAccountNeedsAccount() {
574
+ var acme = _handle();
575
+ check("deactivateAccount refuses before newAccount()",
576
+ (await _acode(acme.deactivateAccount())) === "acme/no-account");
577
+ }
578
+
579
+ async function testChallengeUrlValidation() {
580
+ var acme = _handle();
581
+ check("fetchAuthorization refuses an empty authUrl",
582
+ (await _acode(acme.fetchAuthorization(""))) === "acme/bad-auth-url");
583
+ check("notifyChallengeReady refuses an empty challengeUrl",
584
+ (await _acode(acme.notifyChallengeReady(""))) === "acme/bad-challenge-url");
585
+ }
586
+
587
+ async function testFetchAriRejectsUnparseableCert() {
588
+ var acme = _handle();
589
+ // Carries the BEGIN marker (clears the string check) but is not a
590
+ // parseable X.509 — the second guard (X509 parse) must reject it.
591
+ var fakePem = "-----BEGIN CERTIFICATE-----\nQUJD\n-----END CERTIFICATE-----";
592
+ check("fetchAri rejects a marker-bearing but unparseable certPem",
593
+ (await _acode(acme.fetchAri({ certPem: fakePem }))) === "acme/bad-cert");
594
+ }
595
+
596
+ // ---- transport-stub helpers ---------------------------------------------
597
+
598
+ function _resp(status, headers, body) {
599
+ return {
600
+ statusCode: status,
601
+ headers: headers || {},
602
+ body: body === undefined ? "" : (typeof body === "string" ? body : JSON.stringify(body)),
603
+ };
604
+ }
605
+
606
+ // Install a fake httpClient.request, run fn, always restore.
607
+ async function _withHttp(handler, fn) {
608
+ var orig = httpClient.request;
609
+ httpClient.request = handler;
610
+ try { return await fn(); }
611
+ finally { httpClient.request = orig; }
612
+ }
613
+
614
+ // A rolling replay-nonce header generator.
615
+ function _nonceState() {
616
+ var n = 0;
617
+ return function () { n += 1; return { "replay-nonce": "nonce-" + n }; };
618
+ }
619
+
620
+ // A capturing audit sink (audit.safeEmit shape).
621
+ function _auditSink() {
622
+ var events = [];
623
+ return { events: events, safeEmit: function (e) { events.push(e); } };
624
+ }
625
+
626
+ function _acme(opts) {
627
+ var k = _newKey();
628
+ var base = {
629
+ directory: CA + "/directory",
630
+ accountKey: k.privateKey,
631
+ };
632
+ if (opts) { for (var key in opts) { if (Object.prototype.hasOwnProperty.call(opts, key)) base[key] = opts[key]; } }
633
+ return b.acme.create(base);
634
+ }
635
+
636
+ // ---- self-signed cert builder (carries an AKI keyIdentifier) -----------
637
+ // Uses the framework's own DER writer so no external toolchain is needed.
638
+ // Node's X509Certificate parses structure without verifying the chain, so
639
+ // the self-signed shape is sufficient to drive AKI + serial extraction.
640
+
641
+ function _utcTime(s) { return asn1.writeNode(0x17, Buffer.from(s, "ascii")); }
642
+
643
+ // A default 4-byte serial; individual tests override it (e.g. a serial of 0
644
+ // to drive the odd-length-hex guard in _extractAkiAndSerial).
645
+ var _DEFAULT_SERIAL = Buffer.from([0x12, 0x34, 0x56, 0x78]);
646
+
647
+ // BasicConstraints with all-default fields — an empty SEQUENCE. Placing a
648
+ // non-AKI extension first lets the AKI walker exercise its skip path.
649
+ function _bcExt() {
650
+ return asn1.writeSequence([
651
+ asn1.writeOid("2.5.29.19"), // id-ce-basicConstraints
652
+ asn1.writeOctetString(asn1.writeSequence([])),
653
+ ]);
654
+ }
655
+
656
+ // An AuthorityKeyIdentifier extension whose extnValue OCTET STRING wraps
657
+ // `innerOctetContent` verbatim. A well-formed AKI passes a SEQUENCE
658
+ // containing the keyIdentifier [0]; the malformed-shape tests pass raw
659
+ // non-SEQUENCE bytes to drive the walker's reject branches.
660
+ function _akiExt(innerOctetContent) {
661
+ return asn1.writeSequence([
662
+ asn1.writeOid("2.5.29.35"), // id-ce-authorityKeyIdentifier
663
+ asn1.writeOctetString(innerOctetContent),
664
+ ]);
665
+ }
666
+
667
+ // Build a self-signed cert from an explicit serial + extension list. `exts`
668
+ // false/null omits the extensions [3] field entirely. Node's
669
+ // X509Certificate parses structure without verifying the chain, so the
670
+ // self-signed shape is sufficient to drive AKI + serial extraction.
671
+ function _buildCertGeneric(serial, exts) {
672
+ var pair = _newKey();
673
+ var spkiDer = pair.publicKey.export({ type: "spki", format: "der" });
674
+ var sigAlg = asn1.writeSequence([asn1.writeOid("1.2.840.10045.4.3.2")]); // ecdsa-with-SHA256
675
+ var cnAttr = asn1.writeSequence([asn1.writeOid("2.5.4.3"), asn1.writePrintableString("acme-ari-test")]);
676
+ var name = asn1.writeSequence([asn1.writeSet([cnAttr])]);
677
+ var validity = asn1.writeSequence([_utcTime("250101000000Z"), _utcTime("350101000000Z")]);
678
+ var tbsChildren = [
679
+ asn1.writeContextExplicit(0, asn1.writeInteger(Buffer.from([2]))), // version v3
680
+ asn1.writeInteger(serial), // serialNumber
681
+ sigAlg, name, validity, name, spkiDer,
682
+ ];
683
+ if (exts) tbsChildren.push(asn1.writeContextExplicit(3, asn1.writeSequence(exts)));
684
+ var tbs = asn1.writeSequence(tbsChildren);
685
+ var signer = nodeCrypto.createSign("SHA256");
686
+ signer.update(tbs);
687
+ var sig = signer.sign(pair.privateKey);
688
+ var cert = asn1.writeSequence([tbs, sigAlg, asn1.writeBitString(sig, 0)]);
689
+ return "-----BEGIN CERTIFICATE-----\n" +
690
+ cert.toString("base64").match(/.{1,64}/g).join("\n") +
691
+ "\n-----END CERTIFICATE-----\n";
692
+ }
693
+
694
+ // A well-formed cert: BasicConstraints followed (optionally) by an AKI
695
+ // carrying keyIdentifier [0]. keyIdBytes null -> no AKI extension.
696
+ function _buildCert(keyIdBytes) {
697
+ var exts = [_bcExt()];
698
+ if (keyIdBytes) {
699
+ exts.push(_akiExt(asn1.writeSequence([asn1.writeContextImplicit(0, keyIdBytes)]))); // [0] keyIdentifier
700
+ }
701
+ return _buildCertGeneric(_DEFAULT_SERIAL, exts);
702
+ }
703
+
704
+ // A cert WITH an AKI keyIdentifier; built once, reused across ARI tests.
705
+ var CERT_WITH_AKI = _buildCert(Buffer.from("0102030405060708090a0b0c0d0e0f1011121314", "hex"));
706
+ var CERT_NO_AKI = _buildCert(null);
707
+
708
+ // Adversarial cert variants driving _extractAkiAndSerial + the AKI walker.
709
+ // - serial 0 renders as odd-length hex ("0") -> malformed-serial guard.
710
+ // - no extensions [3] field -> the walker finds no extensions node.
711
+ // - AKI with only authorityCertSerialNumber [2] -> no keyIdentifier [0].
712
+ // - AKI OCTET STRING that is an un-parseable TLV / a primitive (NULL) /
713
+ // a SEQUENCE with a truncated inner body -> the walker's parse-guard
714
+ // continue branches.
715
+ var CERT_SERIAL_ZERO = _buildCertGeneric(Buffer.from([0x00]), [_bcExt()]);
716
+ var CERT_NO_EXTENSIONS = _buildCertGeneric(_DEFAULT_SERIAL, null);
717
+ var CERT_AKI_NO_KEYID = _buildCertGeneric(_DEFAULT_SERIAL,
718
+ [_bcExt(), _akiExt(asn1.writeSequence([asn1.writeContextImplicit(2, Buffer.from([0x01, 0x02]))]))]);
719
+ var CERT_AKI_OCTET_UNPARSEABLE = _buildCertGeneric(_DEFAULT_SERIAL,
720
+ [_bcExt(), _akiExt(Buffer.from([0x30, 0x82, 0xff, 0xff]))]);
721
+ var CERT_AKI_OCTET_NOT_SEQ = _buildCertGeneric(_DEFAULT_SERIAL,
722
+ [_bcExt(), _akiExt(Buffer.from([0x05, 0x00]))]);
723
+ var CERT_AKI_INNER_BAD = _buildCertGeneric(_DEFAULT_SERIAL,
724
+ [_bcExt(), _akiExt(Buffer.from([0x30, 0x02, 0x30, 0x05]))]);
725
+
726
+ // ---- directory shapes ---------------------------------------------------
727
+
728
+ function _fullDir() {
729
+ return {
730
+ newNonce: CA + "/new-nonce",
731
+ newAccount: CA + "/new-account",
732
+ newOrder: CA + "/new-order",
733
+ keyChange: CA + "/key-change",
734
+ revokeCert: CA + "/revoke-cert",
735
+ renewalInfo: CA + "/renewal-info",
736
+ meta: { profiles: { def: "Standard 90-day", short: "47-day", broken: 42 } },
737
+ };
738
+ }
739
+
740
+ // ---- create(): provided-numeric-opt branches ---------------------------
741
+
742
+ function testCreateNumericOpts() {
743
+ var acme = _acme({
744
+ timeoutMs: C.TIME.seconds(10),
745
+ pollIntervalMs: C.TIME.seconds(1),
746
+ pollMaxMs: C.TIME.minutes(2),
747
+ maxBytes: C.BYTES.mib(1),
748
+ });
749
+ check("create honors explicit timeout / poll / maxBytes opts (handle still built)",
750
+ typeof acme.newAccount === "function" && typeof acme.fetchAri === "function");
751
+ }
752
+
753
+ // ---- fetchDirectory: status + shape + JSON guards -----------------------
754
+
755
+ async function testFetchDirectoryStatusAndShape() {
756
+ var acme = _acme();
757
+ await _withHttp(function () { return Promise.resolve(_resp(500, {}, "")); }, async function () {
758
+ check("fetchDirectory non-200 -> acme/directory-fetch",
759
+ (await _acode(acme.fetchDirectory())) === "acme/directory-fetch");
760
+ });
761
+
762
+ var acme2 = _acme();
763
+ await _withHttp(function () {
764
+ return Promise.resolve(_resp(200, {}, { newNonce: CA + "/n", newAccount: CA + "/a" })); // missing newOrder
765
+ }, async function () {
766
+ check("fetchDirectory missing required field -> acme/directory-shape",
767
+ (await _acode(acme2.fetchDirectory())) === "acme/directory-shape");
768
+ });
769
+
770
+ var acme3 = _acme();
771
+ await _withHttp(function () { return Promise.resolve(_resp(200, {}, "5")); }, async function () {
772
+ check("fetchDirectory non-object JSON body -> acme/bad-json",
773
+ (await _acode(acme3.fetchDirectory())) === "acme/bad-json");
774
+ });
775
+
776
+ var acme4 = _acme();
777
+ await _withHttp(function () { return Promise.resolve(_resp(200, {}, "not json at all")); }, async function () {
778
+ check("fetchDirectory invalid JSON body -> acme/bad-json",
779
+ (await _acode(acme4.fetchDirectory())) === "acme/bad-json");
780
+ });
781
+ }
782
+
783
+ async function testFetchDirectoryNetworkError() {
784
+ var acme = _acme();
785
+ await _withHttp(function () { return Promise.reject(new Error("ECONNREFUSED")); }, async function () {
786
+ check("fetchDirectory transport throw -> acme/network",
787
+ (await _acode(acme.fetchDirectory())) === "acme/network");
788
+ });
789
+ }
790
+
791
+ async function testFetchDirectorySuccessBranches() {
792
+ // With renewalInfo -> hasAri true; capitalized Replay-Nonce header read.
793
+ var sink = _auditSink();
794
+ var acme = _acme({ audit: sink });
795
+ await _withHttp(function () {
796
+ return Promise.resolve(_resp(200, { "Replay-Nonce": "cap-nonce-1" }, _fullDir()));
797
+ }, async function () {
798
+ var dir = await acme.fetchDirectory();
799
+ check("fetchDirectory success returns the directory body", dir && dir.newOrder === CA + "/new-order");
800
+ check("fetchDirectory getter now returns the cached directory", acme.directory() && acme.directory().newNonce === CA + "/new-nonce");
801
+ });
802
+ check("fetchDirectory emits acme.directory.fetched success audit",
803
+ sink.events.some(function (e) { return e.action === "acme.directory.fetched" && e.outcome === "success" && e.metadata.hasAri === true; }));
804
+
805
+ // Without renewalInfo -> hasAri false. Audit sink lacking safeEmit hits
806
+ // the _emitAudit early-return branch.
807
+ var noAri = _fullDir(); delete noAri.renewalInfo;
808
+ var acme2 = _acme({ audit: {} });
809
+ await _withHttp(function () { return Promise.resolve(_resp(200, {}, noAri)); }, async function () {
810
+ var dir = await acme2.fetchDirectory();
811
+ check("fetchDirectory (no renewalInfo) still succeeds", dir && typeof dir.newOrder === "string");
812
+ });
813
+ }
814
+
815
+ // ---- newAccount: EAB, failure, location branches ------------------------
816
+
817
+ function _accountHandler(dir, acctResp) {
818
+ var nonce = _nonceState();
819
+ return function (req) {
820
+ var h = nonce();
821
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, dir));
822
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
823
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) {
824
+ var merged = Object.assign(h, acctResp.headers || {});
825
+ return Promise.resolve(_resp(acctResp.status, merged, acctResp.body === undefined ? { status: "valid" } : acctResp.body));
826
+ }
827
+ return Promise.resolve(_resp(404, h, ""));
828
+ };
829
+ }
830
+
831
+ async function testNewAccountEabValidation() {
832
+ var acme = _acme();
833
+ await _withHttp(_accountHandler(_fullDir(), { status: 201, headers: { location: CA + "/acct/1" } }), async function () {
834
+ check("newAccount EAB missing kid -> acme/eab-no-kid",
835
+ (await _acode(acme.newAccount({ externalAccountBinding: { hmacKey: "AAAA" } }))) === "acme/eab-no-kid");
836
+ check("newAccount EAB missing hmacKey -> acme/eab-no-hmac",
837
+ (await _acode(acme.newAccount({ externalAccountBinding: { kid: "kid-1" } }))) === "acme/eab-no-hmac");
838
+ });
839
+ }
840
+
841
+ async function testNewAccountEabSuccess() {
842
+ var acme = _acme();
843
+ var captured = { body: null };
844
+ var handler = function (req) {
845
+ var h = { "replay-nonce": "n" + Math.random() };
846
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
847
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
848
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) {
849
+ captured.body = req.body;
850
+ h.location = CA + "/acct/eab";
851
+ return Promise.resolve(_resp(201, h, { status: "valid" }));
852
+ }
853
+ return Promise.resolve(_resp(404, h, ""));
854
+ };
855
+ await _withHttp(handler, async function () {
856
+ var hmac = Buffer.from("super-secret-hmac-key").toString("base64url");
857
+ var res = await acme.newAccount({ externalAccountBinding: { kid: "kid-xyz", hmacKey: hmac } });
858
+ check("newAccount with EAB resolves to an account URL", res && res.accountUrl === CA + "/acct/eab");
859
+ });
860
+ var outer = JSON.parse(captured.body);
861
+ var payload = JSON.parse(Buffer.from(outer.payload, "base64url").toString("utf8"));
862
+ check("newAccount EAB embeds externalAccountBinding in the account payload",
863
+ payload.externalAccountBinding && typeof payload.externalAccountBinding.signature === "string" &&
864
+ typeof payload.externalAccountBinding.protected === "string");
865
+ }
866
+
867
+ async function testNewAccountFailureBranches() {
868
+ // Failure status carrying a problem+json `type` -> extractProblemReason.
869
+ var sink = _auditSink();
870
+ var acme = _acme({ audit: sink });
871
+ await _withHttp(_accountHandler(_fullDir(), { status: 403, body: { type: "urn:ietf:params:acme:error:unauthorized" } }),
872
+ async function () {
873
+ check("newAccount non-2xx -> acme/newaccount",
874
+ (await _acode(acme.newAccount())) === "acme/newaccount");
875
+ });
876
+ check("newAccount failure audit records the RFC 7807 type as reason",
877
+ sink.events.some(function (e) { return e.action === "acme.account.registered" && e.outcome === "failure" &&
878
+ e.metadata.reason === "urn:ietf:params:acme:error:unauthorized"; }));
879
+
880
+ // 2xx but no Location header.
881
+ var acme2 = _acme();
882
+ await _withHttp(_accountHandler(_fullDir(), { status: 200, body: { status: "valid" } }), async function () {
883
+ check("newAccount 200 without Location -> acme/newaccount-no-location",
884
+ (await _acode(acme2.newAccount())) === "acme/newaccount-no-location");
885
+ });
886
+
887
+ // Failure whose body is unparseable JSON -> _extractProblemReason swallows
888
+ // the parse error and records reason null (the catch branch).
889
+ var sink3 = _auditSink();
890
+ var acme3 = _acme({ audit: sink3 });
891
+ await _withHttp(_accountHandler(_fullDir(), { status: 500, body: "not-json-at-all" }), async function () {
892
+ check("newAccount failure with an unparseable body still throws acme/newaccount",
893
+ (await _acode(acme3.newAccount())) === "acme/newaccount");
894
+ });
895
+ check("newAccount failure audit reason is null when the body is not RFC 7807 JSON",
896
+ sink3.events.some(function (e) { return e.action === "acme.account.registered" && e.outcome === "failure" && e.metadata.reason === null; }));
897
+ }
898
+
899
+ async function testNewAccountSuccessWithContact() {
900
+ var sink = _auditSink();
901
+ var acme = _acme({ audit: sink, contact: ["mailto:ops@example.com"] });
902
+ await _withHttp(_accountHandler(_fullDir(), { status: 201, headers: { "Location": CA + "/acct/9" }, body: { status: "valid" } }),
903
+ async function () {
904
+ var res = await acme.newAccount();
905
+ check("newAccount success returns accountUrl + body", res.accountUrl === CA + "/acct/9" && res.body && res.body.status === "valid");
906
+ check("accountUrl() getter now reflects the registered account", acme.accountUrl() === CA + "/acct/9");
907
+ });
908
+ check("newAccount success audit carries the contact list",
909
+ sink.events.some(function (e) { return e.action === "acme.account.registered" && e.outcome === "success" &&
910
+ Array.isArray(e.metadata.contact) && e.metadata.contact[0] === "mailto:ops@example.com"; }));
911
+ }
912
+
913
+ // ---- _newNonce: HEAD path (nonce not pre-seeded) ------------------------
914
+
915
+ function _noSeedNonceHandler(dir, headResp, revokeResp) {
916
+ return function (req) {
917
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, {}, dir)); // no nonce header
918
+ if (req.method === "HEAD") return Promise.resolve(headResp);
919
+ if (req.method === "POST" && req.url.indexOf("/revoke-cert") !== -1) return Promise.resolve(revokeResp || _resp(200, {}, ""));
920
+ return Promise.resolve(_resp(404, {}, ""));
921
+ };
922
+ }
923
+
924
+ async function testNewNonceHeadBranches() {
925
+ var der = Buffer.from([0x30, 0x03, 0x02, 0x01, 0x05]); // trivial DER cert bytes for revoke
926
+
927
+ var acme1 = _acme();
928
+ await _withHttp(_noSeedNonceHandler(_fullDir(), _resp(500, {}, "")), async function () {
929
+ check("newNonce HEAD non-200 -> acme/newnonce-failed",
930
+ (await _acode(acme1.revokeCert(der))) === "acme/newnonce-failed");
931
+ });
932
+
933
+ var acme2 = _acme();
934
+ await _withHttp(_noSeedNonceHandler(_fullDir(), _resp(200, {}, "")), async function () {
935
+ check("newNonce HEAD 200 without Replay-Nonce -> acme/newnonce-no-header",
936
+ (await _acode(acme2.revokeCert(der))) === "acme/newnonce-no-header");
937
+ });
938
+
939
+ var acme3 = _acme();
940
+ await _withHttp(_noSeedNonceHandler(_fullDir(), _resp(200, { "replay-nonce": "fresh-1" }, ""), _resp(200, {}, "")), async function () {
941
+ check("newNonce HEAD 200 + Replay-Nonce feeds a successful revoke",
942
+ (await acme3.revokeCert(der)) === true);
943
+ });
944
+ }
945
+
946
+ // ---- newOrder: guards + success -----------------------------------------
947
+
948
+ function _orderHandler(dir, orderResp) {
949
+ var nonce = _nonceState();
950
+ return function (req) {
951
+ var h = nonce();
952
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, dir));
953
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
954
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) {
955
+ h.location = CA + "/acct/1";
956
+ return Promise.resolve(_resp(201, h, { status: "valid" }));
957
+ }
958
+ if (req.method === "POST" && req.url.indexOf("/new-order") !== -1) {
959
+ var merged = Object.assign(h, orderResp.headers || {});
960
+ return Promise.resolve(_resp(orderResp.status, merged, orderResp.body === undefined ? { status: "pending" } : orderResp.body));
961
+ }
962
+ return Promise.resolve(_resp(404, h, ""));
963
+ };
964
+ }
965
+
966
+ async function testNewOrderGuards() {
967
+ var acme = _acme();
968
+ // No account yet (directory not fetched either) -> newOrder auto-fetches
969
+ // directory, then trips the no-account guard.
970
+ await _withHttp(_orderHandler(_fullDir(), { status: 201 }), async function () {
971
+ check("newOrder before newAccount -> acme/no-account",
972
+ (await _acode(acme.newOrder({ identifiers: [{ type: "dns", value: "x.com" }] }))) === "acme/no-account");
973
+ });
974
+
975
+ var acme2 = _acme();
976
+ await _withHttp(_orderHandler(_fullDir(), { status: 201 }), async function () {
977
+ await acme2.newAccount();
978
+ check("newOrder without identifiers -> acme/bad-order",
979
+ (await _acode(acme2.newOrder({}))) === "acme/bad-order");
980
+ check("newOrder with empty identifiers -> acme/bad-order",
981
+ (await _acode(acme2.newOrder({ identifiers: [] }))) === "acme/bad-order");
982
+ check("newOrder with a malformed identifier -> acme/bad-identifier",
983
+ (await _acode(acme2.newOrder({ identifiers: [{ type: "dns" }] }))) === "acme/bad-identifier");
984
+ check("newOrder with an over-length identifier -> acme/bad-identifier",
985
+ (await _acode(acme2.newOrder({ identifiers: [{ type: "dns", value: "a".repeat(300) }] }))) === "acme/bad-identifier");
986
+ check("newOrder with a non-string profile -> acme/bad-profile",
987
+ (await _acode(acme2.newOrder({ identifiers: [{ type: "dns", value: "x.com" }], profile: 42 }))) === "acme/bad-profile");
988
+ check("newOrder with an empty profile string -> acme/bad-profile",
989
+ (await _acode(acme2.newOrder({ identifiers: [{ type: "dns", value: "x.com" }], profile: "" }))) === "acme/bad-profile");
990
+ check("newOrder with an over-length profile -> acme/bad-profile",
991
+ (await _acode(acme2.newOrder({ identifiers: [{ type: "dns", value: "x.com" }], profile: "p".repeat(80) }))) === "acme/bad-profile");
992
+ });
993
+ }
994
+
995
+ async function testNewOrderFailureAndSuccess() {
996
+ var sink = _auditSink();
997
+ var acme = _acme({ audit: sink });
998
+ await _withHttp(_orderHandler(_fullDir(), { status: 400, body: { detail: "policy refused" } }), async function () {
999
+ await acme.newAccount();
1000
+ check("newOrder non-201 -> acme/neworder",
1001
+ (await _acode(acme.newOrder({ identifiers: [{ type: "dns", value: "x.com" }] }))) === "acme/neworder");
1002
+ });
1003
+ check("newOrder failure audit extracts RFC 7807 detail",
1004
+ sink.events.some(function (e) { return e.action === "acme.order.created" && e.outcome === "failure" && e.metadata.reason === "policy refused"; }));
1005
+
1006
+ var sink2 = _auditSink();
1007
+ var acme2 = _acme({ audit: sink2 });
1008
+ await _withHttp(_orderHandler(_fullDir(), { status: 201, headers: { location: CA + "/order/77" }, body: { status: "pending", finalize: CA + "/finalize/77" } }),
1009
+ async function () {
1010
+ await acme2.newAccount();
1011
+ var order = await acme2.newOrder({
1012
+ identifiers: [{ type: "dns", value: "good.com" }],
1013
+ notBefore: "2026-01-01T00:00:00Z",
1014
+ notAfter: "2026-04-01T00:00:00Z",
1015
+ profile: "short",
1016
+ });
1017
+ check("newOrder success returns the order with its url", order.url === CA + "/order/77" && order.finalize === CA + "/finalize/77");
1018
+ });
1019
+ check("newOrder success emits acme.order.created success audit",
1020
+ sink2.events.some(function (e) { return e.action === "acme.order.created" && e.outcome === "success"; }));
1021
+ }
1022
+
1023
+ // ---- finalize: network success + failure --------------------------------
1024
+
1025
+ function _finalizeHandler(finalizeResp) {
1026
+ var nonce = _nonceState();
1027
+ return function (req) {
1028
+ var h = nonce();
1029
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1030
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1031
+ if (req.method === "POST" && req.url.indexOf("/finalize") !== -1) return Promise.resolve(_resp(finalizeResp.status, h, finalizeResp.body));
1032
+ return Promise.resolve(_resp(404, h, ""));
1033
+ };
1034
+ }
1035
+
1036
+ async function testFinalizeNetworkBranches() {
1037
+ var pair = _newKey();
1038
+ var sink = _auditSink();
1039
+ var acme = _acme({ audit: sink });
1040
+ var csr = acme.buildCsr({ privateKey: pair.privateKey, publicKey: pair.publicKey, domains: ["f.example.com"] });
1041
+ var order = { finalize: CA + "/finalize/1", url: CA + "/order/1" };
1042
+
1043
+ await _withHttp(_finalizeHandler({ status: 200, body: { status: "processing" } }), async function () {
1044
+ await acme.fetchDirectory();
1045
+ var updated = await acme.finalize(order, csr);
1046
+ check("finalize success returns the updated order carrying its url", updated.url === CA + "/order/1" && updated.status === "processing");
1047
+ });
1048
+ check("finalize success emits acme.order.finalize success audit",
1049
+ sink.events.some(function (e) { return e.action === "acme.order.finalize" && e.outcome === "success"; }));
1050
+
1051
+ var sink2 = _auditSink();
1052
+ var acme2 = _acme({ audit: sink2 });
1053
+ await _withHttp(_finalizeHandler({ status: 400, body: { title: "bad CSR" } }), async function () {
1054
+ await acme2.fetchDirectory();
1055
+ check("finalize non-2xx -> acme/finalize",
1056
+ (await _acode(acme2.finalize(order, Buffer.from([0x30, 0x03, 0x02, 0x01, 0x00])))) === "acme/finalize");
1057
+ });
1058
+ check("finalize failure audit extracts RFC 7807 title",
1059
+ sink2.events.some(function (e) { return e.action === "acme.order.finalize" && e.outcome === "failure" && e.metadata.reason === "bad CSR"; }));
1060
+ }
1061
+
1062
+ // ---- retrieveCert: polling + download branches --------------------------
1063
+
1064
+ var PEM_CERT = "-----BEGIN CERTIFICATE-----\nMIIB\n-----END CERTIFICATE-----\n";
1065
+
1066
+ async function testRetrieveCertBadOrder() {
1067
+ var acme = _acme();
1068
+ check("retrieveCert without order.url -> acme/bad-order",
1069
+ (await _acode(acme.retrieveCert({}))) === "acme/bad-order");
1070
+ }
1071
+
1072
+ async function testRetrieveCertImmediateValid() {
1073
+ var sink = _auditSink();
1074
+ var acme = _acme({ audit: sink });
1075
+ var handler = function (req) {
1076
+ var h = { "replay-nonce": "n-" + Math.random() };
1077
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1078
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1079
+ if (req.method === "POST" && req.url.indexOf("/cert/1") !== -1) return Promise.resolve(_resp(200, h, PEM_CERT));
1080
+ return Promise.resolve(_resp(404, h, ""));
1081
+ };
1082
+ await _withHttp(handler, async function () {
1083
+ await acme.fetchDirectory();
1084
+ var order = { url: CA + "/order/1", status: "valid", certificate: CA + "/cert/1" };
1085
+ var pem = await acme.retrieveCert(order);
1086
+ check("retrieveCert (already valid) downloads the PEM", pem.indexOf("-----BEGIN CERTIFICATE-----") === 0);
1087
+ });
1088
+ check("retrieveCert success emits acme.cert.issued success audit",
1089
+ sink.events.some(function (e) { return e.action === "acme.cert.issued" && e.outcome === "success"; }));
1090
+ }
1091
+
1092
+ async function testRetrieveCertInvalidOrder() {
1093
+ var sink = _auditSink();
1094
+ var acme = _acme({ audit: sink });
1095
+ check("retrieveCert on an invalid order -> acme/order-invalid",
1096
+ (await _acode(acme.retrieveCert({ url: CA + "/order/x", status: "invalid" }))) === "acme/order-invalid");
1097
+ check("retrieveCert invalid emits acme.order.poll failure audit",
1098
+ sink.events.some(function (e) { return e.action === "acme.order.poll" && e.outcome === "failure"; }));
1099
+ }
1100
+
1101
+ async function testRetrieveCertPollToValid() {
1102
+ var acme = _acme({ pollIntervalMs: 1, pollMaxMs: C.TIME.seconds(5) });
1103
+ var polls = 0;
1104
+ var handler = function (req) {
1105
+ var h = { "replay-nonce": "n-" + Math.random() };
1106
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1107
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1108
+ if (req.method === "POST" && req.url.indexOf("/order/poll") !== -1) {
1109
+ polls += 1;
1110
+ if (polls < 2) return Promise.resolve(_resp(200, h, { status: "pending" }));
1111
+ return Promise.resolve(_resp(200, h, { status: "valid", certificate: CA + "/cert/poll" }));
1112
+ }
1113
+ if (req.method === "POST" && req.url.indexOf("/cert/poll") !== -1) return Promise.resolve(_resp(200, h, PEM_CERT));
1114
+ return Promise.resolve(_resp(404, h, ""));
1115
+ };
1116
+ await _withHttp(handler, async function () {
1117
+ await acme.fetchDirectory();
1118
+ var pem = await acme.retrieveCert({ url: CA + "/order/poll", status: "pending" });
1119
+ check("retrieveCert polls pending->valid then downloads", pem.indexOf("-----BEGIN CERTIFICATE-----") === 0 && polls >= 2);
1120
+ });
1121
+ }
1122
+
1123
+ async function testRetrieveCertPollNon2xx() {
1124
+ var acme = _acme({ pollIntervalMs: 1, pollMaxMs: C.TIME.seconds(5) });
1125
+ var handler = function (req) {
1126
+ var h = { "replay-nonce": "n-" + Math.random() };
1127
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1128
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1129
+ if (req.method === "POST" && req.url.indexOf("/order/pollerr") !== -1) return Promise.resolve(_resp(500, h, ""));
1130
+ return Promise.resolve(_resp(404, h, ""));
1131
+ };
1132
+ await _withHttp(handler, async function () {
1133
+ await acme.fetchDirectory();
1134
+ check("retrieveCert poll non-2xx -> acme/order-poll",
1135
+ (await _acode(acme.retrieveCert({ url: CA + "/order/pollerr", status: "pending" }))) === "acme/order-poll");
1136
+ });
1137
+ }
1138
+
1139
+ async function testRetrieveCertTimeout() {
1140
+ var acme = _acme({ pollIntervalMs: 5, pollMaxMs: 40 });
1141
+ var handler = function (req) {
1142
+ var h = { "replay-nonce": "n-" + Math.random() };
1143
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1144
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1145
+ if (req.method === "POST" && req.url.indexOf("/order/slow") !== -1) return Promise.resolve(_resp(200, h, { status: "pending" }));
1146
+ return Promise.resolve(_resp(404, h, ""));
1147
+ };
1148
+ await _withHttp(handler, async function () {
1149
+ await acme.fetchDirectory();
1150
+ check("retrieveCert never-valid -> acme/order-timeout",
1151
+ (await _acode(acme.retrieveCert({ url: CA + "/order/slow", status: "pending" }))) === "acme/order-timeout");
1152
+ });
1153
+ }
1154
+
1155
+ async function testRetrieveCertDownloadBranches() {
1156
+ var sink = _auditSink();
1157
+ var acme = _acme({ audit: sink });
1158
+ var handler = function (req) {
1159
+ var h = { "replay-nonce": "n-" + Math.random() };
1160
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1161
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1162
+ if (req.method === "POST" && req.url.indexOf("/cert/500") !== -1) return Promise.resolve(_resp(500, h, ""));
1163
+ if (req.method === "POST" && req.url.indexOf("/cert/notpem") !== -1) return Promise.resolve(_resp(200, h, "this is not a certificate"));
1164
+ return Promise.resolve(_resp(404, h, ""));
1165
+ };
1166
+ await _withHttp(handler, async function () {
1167
+ await acme.fetchDirectory();
1168
+ check("retrieveCert download non-200 -> acme/cert-download",
1169
+ (await _acode(acme.retrieveCert({ url: CA + "/order/a", status: "valid", certificate: CA + "/cert/500" }))) === "acme/cert-download");
1170
+ check("retrieveCert download non-PEM body -> acme/bad-cert-bytes",
1171
+ (await _acode(acme.retrieveCert({ url: CA + "/order/b", status: "valid", certificate: CA + "/cert/notpem" }))) === "acme/bad-cert-bytes");
1172
+ });
1173
+ check("retrieveCert download failure emits acme.cert.issued failure audit",
1174
+ sink.events.some(function (e) { return e.action === "acme.cert.issued" && e.outcome === "failure"; }));
1175
+ }
1176
+
1177
+ // ---- authorization flow -------------------------------------------------
1178
+
1179
+ function _authHandler(map) {
1180
+ var nonce = _nonceState();
1181
+ return function (req) {
1182
+ var h = nonce();
1183
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1184
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1185
+ for (var key in map) {
1186
+ if (Object.prototype.hasOwnProperty.call(map, key) && req.url.indexOf(key) !== -1) {
1187
+ var r = map[key](req);
1188
+ return Promise.resolve(_resp(r.status, h, r.body));
1189
+ }
1190
+ }
1191
+ return Promise.resolve(_resp(404, h, ""));
1192
+ };
1193
+ }
1194
+
1195
+ async function testAuthorizationFlow() {
1196
+ var acme = _acme();
1197
+ await _withHttp(_authHandler({
1198
+ "/auth/ok": function () { return { status: 200, body: { status: "pending", challenges: [{ type: "http-01", url: CA + "/chal/1", token: "tok" }] } }; },
1199
+ "/auth/err": function () { return { status: 500, body: "" }; },
1200
+ "/chal/ok": function () { return { status: 200, body: { status: "processing" } }; },
1201
+ "/chal/err": function () { return { status: 403, body: "" }; },
1202
+ }), async function () {
1203
+ await acme.fetchDirectory();
1204
+ var auth = await acme.fetchAuthorization(CA + "/auth/ok");
1205
+ check("fetchAuthorization returns the auth object with its url", auth.url === CA + "/auth/ok" && Array.isArray(auth.challenges));
1206
+ check("fetchAuthorization non-2xx -> acme/auth-fetch",
1207
+ (await _acode(acme.fetchAuthorization(CA + "/auth/err"))) === "acme/auth-fetch");
1208
+ var updated = await acme.notifyChallengeReady(CA + "/chal/ok");
1209
+ check("notifyChallengeReady returns the updated challenge", updated.status === "processing");
1210
+ check("notifyChallengeReady non-2xx -> acme/challenge-ready",
1211
+ (await _acode(acme.notifyChallengeReady(CA + "/chal/err"))) === "acme/challenge-ready");
1212
+ });
1213
+ }
1214
+
1215
+ async function testWaitForAuthorization() {
1216
+ // valid immediately (default interval/deadline branch).
1217
+ var acme = _acme();
1218
+ await _withHttp(_authHandler({ "/auth/valid": function () { return { status: 200, body: { status: "valid" } }; } }), async function () {
1219
+ await acme.fetchDirectory();
1220
+ var auth = await acme.waitForAuthorization(CA + "/auth/valid");
1221
+ check("waitForAuthorization returns when status is valid", auth.status === "valid");
1222
+ });
1223
+
1224
+ // invalid -> throw + audit.
1225
+ var sink = _auditSink();
1226
+ var acme2 = _acme({ audit: sink });
1227
+ await _withHttp(_authHandler({ "/auth/bad": function () { return { status: 200, body: { status: "invalid", challenges: [{ error: { detail: "dns failed" } }] } }; } }),
1228
+ async function () {
1229
+ await acme2.fetchDirectory();
1230
+ check("waitForAuthorization invalid -> acme/auth-invalid",
1231
+ (await _acode(acme2.waitForAuthorization(CA + "/auth/bad"))) === "acme/auth-invalid");
1232
+ });
1233
+ check("waitForAuthorization invalid emits acme.auth.poll failure audit",
1234
+ sink.events.some(function (e) { return e.action === "acme.auth.poll" && e.outcome === "failure"; }));
1235
+
1236
+ // timeout (explicit intervalMs/timeoutMs opts branch).
1237
+ var acme3 = _acme();
1238
+ await _withHttp(_authHandler({ "/auth/slow": function () { return { status: 200, body: { status: "pending" } }; } }), async function () {
1239
+ await acme3.fetchDirectory();
1240
+ check("waitForAuthorization never-valid -> acme/auth-timeout",
1241
+ (await _acode(acme3.waitForAuthorization(CA + "/auth/slow", { intervalMs: 5, timeoutMs: 30 }))) === "acme/auth-timeout");
1242
+ });
1243
+ }
1244
+
1245
+ // ---- fetchAri + renewIfDue ----------------------------------------------
1246
+
1247
+ function _ariHandler(dir, ariResponder) {
1248
+ var nonce = _nonceState();
1249
+ return function (req) {
1250
+ var h = nonce();
1251
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, dir));
1252
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1253
+ if (req.method === "GET" && req.url.indexOf("/renewal-info/") !== -1) {
1254
+ var r = ariResponder(req);
1255
+ return Promise.resolve({ statusCode: r.status, headers: Object.assign(h, r.headers || {}), body: typeof r.body === "string" ? r.body : JSON.stringify(r.body) });
1256
+ }
1257
+ return Promise.resolve(_resp(404, h, ""));
1258
+ };
1259
+ }
1260
+
1261
+ async function testFetchAriGuards() {
1262
+ // Directory has no renewalInfo -> acme/no-ari.
1263
+ var noAri = _fullDir(); delete noAri.renewalInfo;
1264
+ var acme = _acme();
1265
+ await _withHttp(_ariHandler(noAri, function () { return { status: 200, body: {} }; }), async function () {
1266
+ check("fetchAri when directory lacks renewalInfo -> acme/no-ari",
1267
+ (await _acode(acme.fetchAri({ certPem: CERT_WITH_AKI }))) === "acme/no-ari");
1268
+ });
1269
+
1270
+ // Cert without AKI -> acme/no-aki (extraction fails before network).
1271
+ var acme2 = _acme();
1272
+ await _withHttp(_ariHandler(_fullDir(), function () { return { status: 200, body: {} }; }), async function () {
1273
+ check("fetchAri on a cert with no AKI -> acme/no-aki",
1274
+ (await _acode(acme2.fetchAri({ certPem: CERT_NO_AKI }))) === "acme/no-aki");
1275
+ });
1276
+
1277
+ // ARI GET non-200.
1278
+ var acme3 = _acme();
1279
+ await _withHttp(_ariHandler(_fullDir(), function () { return { status: 404, body: "" }; }), async function () {
1280
+ check("fetchAri ARI GET non-200 -> acme/ari-fetch",
1281
+ (await _acode(acme3.fetchAri({ certPem: CERT_WITH_AKI }))) === "acme/ari-fetch");
1282
+ });
1283
+ }
1284
+
1285
+ async function _assertAriShape(label, body) {
1286
+ var acme = _acme();
1287
+ await _withHttp(_ariHandler(_fullDir(), function () { return { status: 200, body: body }; }), async function () {
1288
+ check("fetchAri " + label + " -> acme/ari-shape",
1289
+ (await _acode(acme.fetchAri({ certPem: CERT_WITH_AKI }))) === "acme/ari-shape");
1290
+ });
1291
+ }
1292
+
1293
+ async function testFetchAriShapeGuards() {
1294
+ await _assertAriShape("missing suggestedWindow", { foo: 1 });
1295
+ await _assertAriShape("non-string window bounds", { suggestedWindow: { start: 1, end: 2 } });
1296
+ await _assertAriShape("unparseable timestamps", { suggestedWindow: { start: "nope", end: "also-nope" } });
1297
+ await _assertAriShape("end before start", { suggestedWindow: { start: "2027-01-02T00:00:00Z", end: "2027-01-01T00:00:00Z" } });
1298
+ }
1299
+
1300
+ async function testFetchAriSuccess() {
1301
+ var now = Date.now();
1302
+ var start = new Date(now - C.TIME.hours(1)).toISOString();
1303
+ var end = new Date(now + C.TIME.hours(1)).toISOString();
1304
+ var acme = _acme();
1305
+ await _withHttp(_ariHandler(_fullDir(), function () {
1306
+ return { status: 200, headers: { "retry-after": "21600" }, body: { suggestedWindow: { start: start, end: end }, explanationURL: "https://ca.example.test/why" } };
1307
+ }), async function () {
1308
+ var ari = await acme.fetchAri({ certPem: CERT_WITH_AKI });
1309
+ check("fetchAri returns a certId derived from AKI + serial", typeof ari.certId === "string" && ari.certId.indexOf(".") > 0);
1310
+ check("fetchAri surfaces retry-after + explanationURL", ari.retryAfter === "21600" && ari.explanationURL === "https://ca.example.test/why");
1311
+ check("fetchAri parses the window into epoch ms", isFinite(ari.suggestedWindow.startMs) && isFinite(ari.suggestedWindow.endMs));
1312
+ });
1313
+
1314
+ // retry-after absent + explanationURL non-string -> both normalize to null.
1315
+ var acme2 = _acme();
1316
+ await _withHttp(_ariHandler(_fullDir(), function () {
1317
+ return { status: 200, body: { suggestedWindow: { start: start, end: end }, explanationURL: 12345 } };
1318
+ }), async function () {
1319
+ var ari = await acme2.fetchAri({ certPem: CERT_WITH_AKI });
1320
+ check("fetchAri null retryAfter + null explanationURL when absent/non-string", ari.retryAfter === null && ari.explanationURL === null);
1321
+ });
1322
+ }
1323
+
1324
+ function _ariWindowFake(startOffset, endOffset) {
1325
+ var now = Date.now();
1326
+ var start = new Date(now + startOffset).toISOString();
1327
+ var end = new Date(now + endOffset).toISOString();
1328
+ return _ariHandler(_fullDir(), function () {
1329
+ return { status: 200, body: { suggestedWindow: { start: start, end: end } } };
1330
+ });
1331
+ }
1332
+
1333
+ async function testRenewIfDueVerdicts() {
1334
+ var H = C.TIME.hours(1);
1335
+
1336
+ // before-window
1337
+ var sink = _auditSink();
1338
+ var acme = _acme({ audit: sink });
1339
+ await _withHttp(_ariWindowFake(H, 2 * H), async function () {
1340
+ var v = await acme.renewIfDue({ certPem: CERT_WITH_AKI });
1341
+ check("renewIfDue before the window -> shouldRenew false, before-window", v.shouldRenew === false && v.reason === "before-window");
1342
+ });
1343
+ check("renewIfDue before-window emits acme.cert.renew.skipped audit",
1344
+ sink.events.some(function (e) { return e.action === "acme.cert.renew.skipped"; }));
1345
+
1346
+ // in-window
1347
+ var acme2 = _acme();
1348
+ await _withHttp(_ariWindowFake(-H, H), async function () {
1349
+ var v = await acme2.renewIfDue({ certPem: CERT_WITH_AKI });
1350
+ check("renewIfDue inside the window -> shouldRenew true, in-window", v.shouldRenew === true && v.reason === "in-window");
1351
+ });
1352
+
1353
+ // past-window
1354
+ var acme3 = _acme();
1355
+ await _withHttp(_ariWindowFake(-2 * H, -H), async function () {
1356
+ var v = await acme3.renewIfDue({ certPem: CERT_WITH_AKI });
1357
+ check("renewIfDue past the window -> shouldRenew true, past-window", v.shouldRenew === true && v.reason === "past-window");
1358
+ });
1359
+ }
1360
+
1361
+ async function testRenewIfDueJitter() {
1362
+ var H = C.TIME.hours(1);
1363
+
1364
+ // before-window + jitter -> renewAt is an ISO string within [start, end].
1365
+ var acme = _acme();
1366
+ await _withHttp(_ariWindowFake(H, 2 * H), async function () {
1367
+ var v = await acme.renewIfDue({ certPem: CERT_WITH_AKI, jitter: true });
1368
+ check("renewIfDue before-window jitter yields an ISO renewAt", v.shouldRenew === false && typeof v.renewAt === "string" &&
1369
+ isFinite(Date.parse(v.renewAt)));
1370
+ });
1371
+
1372
+ // in-window + jitter.
1373
+ var acme2 = _acme();
1374
+ await _withHttp(_ariWindowFake(-H, H), async function () {
1375
+ var v = await acme2.renewIfDue({ certPem: CERT_WITH_AKI, jitter: true });
1376
+ check("renewIfDue in-window jitter yields an ISO renewAt", v.shouldRenew === true && typeof v.renewAt === "string");
1377
+ });
1378
+
1379
+ // past-window + jitter -> jHi < jLo branch (renewAt == now).
1380
+ var acme3 = _acme();
1381
+ await _withHttp(_ariWindowFake(-2 * H, -H), async function () {
1382
+ var v = await acme3.renewIfDue({ certPem: CERT_WITH_AKI, jitter: true });
1383
+ check("renewIfDue past-window jitter yields an ISO renewAt", v.shouldRenew === true && typeof v.renewAt === "string");
1384
+ });
1385
+ }
1386
+
1387
+ // ---- revokeCert branches ------------------------------------------------
1388
+
1389
+ function _revokeHandler(dir, revokeResp) {
1390
+ var nonce = _nonceState();
1391
+ return function (req) {
1392
+ var h = nonce();
1393
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, dir));
1394
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1395
+ if (req.method === "POST" && req.url.indexOf("/revoke-cert") !== -1) return Promise.resolve(_resp(revokeResp.status, h, revokeResp.body));
1396
+ return Promise.resolve(_resp(404, h, ""));
1397
+ };
1398
+ }
1399
+
1400
+ async function testRevokeCertBranches() {
1401
+ var der = Buffer.from([0x30, 0x03, 0x02, 0x01, 0x05]);
1402
+
1403
+ // directory without revokeCert endpoint.
1404
+ var noRevoke = _fullDir(); delete noRevoke.revokeCert;
1405
+ var acme0 = _acme();
1406
+ await _withHttp(_revokeHandler(noRevoke, { status: 200, body: "" }), async function () {
1407
+ check("revokeCert when directory lacks revokeCert -> acme/revoke-not-supported",
1408
+ (await _acode(acme0.revokeCert(der))) === "acme/revoke-not-supported");
1409
+ });
1410
+
1411
+ // useCertKey: true is a reserved/deferred path -> throws.
1412
+ var acme1 = _acme();
1413
+ await _withHttp(_revokeHandler(_fullDir(), { status: 200, body: "" }), async function () {
1414
+ check("revokeCert useCertKey:true -> acme/revoke-cert-key-not-implemented",
1415
+ (await _acode(acme1.revokeCert(der, { useCertKey: true }))) === "acme/revoke-cert-key-not-implemented");
1416
+ });
1417
+
1418
+ // success with a reason code + Uint8Array input.
1419
+ var sink = _auditSink();
1420
+ var acme2 = _acme({ audit: sink });
1421
+ await _withHttp(_revokeHandler(_fullDir(), { status: 200, body: "" }), async function () {
1422
+ var ok = await acme2.revokeCert(new Uint8Array([0x30, 0x03, 0x02, 0x01, 0x04]), { reason: 4 });
1423
+ check("revokeCert (Uint8Array + reason) resolves true", ok === true);
1424
+ });
1425
+ check("revokeCert success emits acme.cert.revoked success audit",
1426
+ sink.events.some(function (e) { return e.action === "acme.cert.revoked" && e.outcome === "success"; }));
1427
+
1428
+ // failure status with an empty body (extractProblemReason(null) branch).
1429
+ var sink2 = _auditSink();
1430
+ var acme3 = _acme({ audit: sink2 });
1431
+ await _withHttp(_revokeHandler(_fullDir(), { status: 409, body: "" }), async function () {
1432
+ check("revokeCert non-200 -> acme/revoke-failed",
1433
+ (await _acode(acme3.revokeCert(der))) === "acme/revoke-failed");
1434
+ });
1435
+ check("revokeCert failure emits acme.cert.revoked failure audit with null reason",
1436
+ sink2.events.some(function (e) { return e.action === "acme.cert.revoked" && e.outcome === "failure" && e.metadata.reason === null; }));
1437
+ }
1438
+
1439
+ // ---- accountKeyRollover branches ----------------------------------------
1440
+
1441
+ async function testRolloverBranches() {
1442
+ // No account (directory fetched, but newAccount not called).
1443
+ var acme0 = _acme();
1444
+ await _withHttp(_orderHandler(_fullDir(), { status: 201 }), async function () {
1445
+ await acme0.fetchDirectory();
1446
+ check("accountKeyRollover before newAccount -> acme/no-account",
1447
+ (await _acode(acme0.accountKeyRollover(_newKey().privateKey))) === "acme/no-account");
1448
+ });
1449
+
1450
+ // Account present but directory lacks keyChange.
1451
+ var noKc = _fullDir(); delete noKc.keyChange;
1452
+ var acme1 = _acme();
1453
+ await _withHttp(_accountHandler(noKc, { status: 201, headers: { location: CA + "/acct/1" } }), async function () {
1454
+ await acme1.newAccount();
1455
+ check("accountKeyRollover without keyChange endpoint -> acme/key-change-not-supported",
1456
+ (await _acode(acme1.accountKeyRollover(_newKey().privateKey))) === "acme/key-change-not-supported");
1457
+ });
1458
+
1459
+ // Bad new key.
1460
+ var acme2 = _acme();
1461
+ await _withHttp(_accountHandler(_fullDir(), { status: 201, headers: { location: CA + "/acct/1" } }), async function () {
1462
+ await acme2.newAccount();
1463
+ check("accountKeyRollover with a non-object new key -> acme/bad-new-key",
1464
+ (await _acode(acme2.accountKeyRollover("not-a-key"))) === "acme/bad-new-key");
1465
+ // An object lacking a KeyObject export() reaches _publicJwkFromKeyObject.
1466
+ check("accountKeyRollover with a bare object (no export) -> acme/bad-account-key",
1467
+ (await _acode(acme2.accountKeyRollover({}))) === "acme/bad-account-key");
1468
+ });
1469
+
1470
+ // keyChange POST failure.
1471
+ var sink = _auditSink();
1472
+ var acme3 = _acme({ audit: sink });
1473
+ var handler = function (req) {
1474
+ var h = { "replay-nonce": "n-" + Math.random() };
1475
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1476
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1477
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) { h.location = CA + "/acct/1"; return Promise.resolve(_resp(201, h, { status: "valid" })); }
1478
+ if (req.method === "POST" && req.url.indexOf("/key-change") !== -1) return Promise.resolve(_resp(500, h, { detail: "rotation refused" }));
1479
+ return Promise.resolve(_resp(404, h, ""));
1480
+ };
1481
+ await _withHttp(handler, async function () {
1482
+ await acme3.newAccount();
1483
+ check("accountKeyRollover keyChange non-200 -> acme/key-change-failed",
1484
+ (await _acode(acme3.accountKeyRollover(_newKey().privateKey))) === "acme/key-change-failed");
1485
+ });
1486
+ check("accountKeyRollover failure emits acme.account.key_rotated failure audit",
1487
+ sink.events.some(function (e) { return e.action === "acme.account.key_rotated" && e.outcome === "failure"; }));
1488
+ }
1489
+
1490
+ // ---- deactivateAccount + dnsAccount01 record success --------------------
1491
+
1492
+ async function testDeactivateBranches() {
1493
+ // failure.
1494
+ var sink = _auditSink();
1495
+ var acme = _acme({ audit: sink });
1496
+ var handlerFail = function (req) {
1497
+ var h = { "replay-nonce": "n-" + Math.random() };
1498
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1499
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1500
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) { h.location = CA + "/acct/d"; return Promise.resolve(_resp(201, h, { status: "valid" })); }
1501
+ if (req.method === "POST" && req.url.indexOf("/acct/d") !== -1) return Promise.resolve(_resp(500, h, ""));
1502
+ return Promise.resolve(_resp(404, h, ""));
1503
+ };
1504
+ await _withHttp(handlerFail, async function () {
1505
+ await acme.newAccount();
1506
+ check("deactivateAccount non-200 -> acme/deactivate-failed",
1507
+ (await _acode(acme.deactivateAccount())) === "acme/deactivate-failed");
1508
+ });
1509
+ check("deactivateAccount failure emits audit", sink.events.some(function (e) { return e.action === "acme.account.deactivated" && e.outcome === "failure"; }));
1510
+
1511
+ // success.
1512
+ var sink2 = _auditSink();
1513
+ var acme2 = _acme({ audit: sink2 });
1514
+ var handlerOk = function (req) {
1515
+ var h = { "replay-nonce": "n-" + Math.random() };
1516
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1517
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1518
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) { h.location = CA + "/acct/e"; return Promise.resolve(_resp(201, h, { status: "valid" })); }
1519
+ if (req.method === "POST" && req.url.indexOf("/acct/e") !== -1) return Promise.resolve(_resp(200, h, { status: "deactivated" }));
1520
+ return Promise.resolve(_resp(404, h, ""));
1521
+ };
1522
+ await _withHttp(handlerOk, async function () {
1523
+ await acme2.newAccount();
1524
+ check("deactivateAccount success resolves true", (await acme2.deactivateAccount()) === true);
1525
+ });
1526
+ check("deactivateAccount success emits audit", sink2.events.some(function (e) { return e.action === "acme.account.deactivated" && e.outcome === "success"; }));
1527
+ }
1528
+
1529
+ async function testDnsAccount01Success() {
1530
+ var acme = _acme();
1531
+ await _withHttp(_accountHandler(_fullDir(), { status: 201, headers: { location: CA + "/acct/dns" } }), async function () {
1532
+ await acme.newAccount();
1533
+ // ttl validation branch (after accountUrl guard).
1534
+ var threw = null;
1535
+ try { acme.dnsAccount01ChallengeRecord("tok", { identifier: "example.com", ttl: -5 }); }
1536
+ catch (e) { threw = e; }
1537
+ check("dnsAccount01ChallengeRecord rejects a negative ttl -> acme/bad-ttl", threw && threw.code === "acme/bad-ttl");
1538
+ var threw2 = null;
1539
+ try { acme.dnsAccount01ChallengeRecord("tok", { identifier: "example.com", ttl: 90000 }); }
1540
+ catch (e) { threw2 = e; }
1541
+ check("dnsAccount01ChallengeRecord rejects a ttl above 86400 -> acme/bad-ttl", threw2 && threw2.code === "acme/bad-ttl");
1542
+
1543
+ var rec = acme.dnsAccount01ChallengeRecord("tok123", { identifier: "example.com" });
1544
+ check("dnsAccount01ChallengeRecord default ttl is 60", rec.ttl === 60);
1545
+ check("dnsAccount01ChallengeRecord name is _<label>._acme-challenge.<identifier>",
1546
+ /^_[a-z2-7]+\._acme-challenge\.example\.com$/.test(rec.name));
1547
+ check("dnsAccount01ChallengeRecord value is base64url", /^[A-Za-z0-9_-]+$/.test(rec.value));
1548
+
1549
+ var rec2 = acme.dnsAccount01ChallengeRecord("tok123", { identifier: "example.com", ttl: 300 });
1550
+ check("dnsAccount01ChallengeRecord honors a provided ttl", rec2.ttl === 300);
1551
+ });
1552
+ }
1553
+
1554
+ // ---- listProfiles branches ----------------------------------------------
1555
+
1556
+ async function testListProfiles() {
1557
+ // full map (string + non-string values).
1558
+ var acme = _acme();
1559
+ await _withHttp(function (req) {
1560
+ var h = { "replay-nonce": "n" };
1561
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1562
+ return Promise.resolve(_resp(404, h, ""));
1563
+ }, async function () {
1564
+ await acme.fetchDirectory();
1565
+ var p = acme.listProfiles();
1566
+ check("listProfiles surfaces advertised profile names", p.def === "Standard 90-day" && p.short === "47-day");
1567
+ check("listProfiles coerces a non-string profile description to \"\"", p.broken === "");
1568
+ });
1569
+
1570
+ // meta not an object -> {}.
1571
+ var acme2 = _acme();
1572
+ var dirMetaBad = _fullDir(); dirMetaBad.meta = "x";
1573
+ await _withHttp(function (req) {
1574
+ var h = { "replay-nonce": "n" };
1575
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, dirMetaBad));
1576
+ return Promise.resolve(_resp(404, h, ""));
1577
+ }, async function () {
1578
+ await acme2.fetchDirectory();
1579
+ check("listProfiles with non-object meta -> {}", Object.keys(acme2.listProfiles()).length === 0);
1580
+ });
1581
+
1582
+ // profiles not an object -> {}.
1583
+ var acme3 = _acme();
1584
+ var dirProfBad = _fullDir(); dirProfBad.meta = { profiles: 5 };
1585
+ await _withHttp(function (req) {
1586
+ var h = { "replay-nonce": "n" };
1587
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, dirProfBad));
1588
+ return Promise.resolve(_resp(404, h, ""));
1589
+ }, async function () {
1590
+ await acme3.fetchDirectory();
1591
+ check("listProfiles with non-object profiles -> {}", Object.keys(acme3.listProfiles()).length === 0);
1592
+ });
1593
+ }
1594
+
1595
+ // ---- audit best-effort catch --------------------------------------------
1596
+
1597
+ async function testAuditThrowIsSwallowed() {
1598
+ var throwing = { safeEmit: function () { throw new Error("audit sink exploded"); } };
1599
+ var acme = _acme({ audit: throwing });
1600
+ await _withHttp(function (req) {
1601
+ var h = { "replay-nonce": "n" };
1602
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1603
+ return Promise.resolve(_resp(404, h, ""));
1604
+ }, async function () {
1605
+ var dir = await acme.fetchDirectory();
1606
+ check("a throwing audit sink does not break fetchDirectory (best-effort emit)", dir && typeof dir.newOrder === "string");
1607
+ });
1608
+ }
1609
+
1610
+ // ---- cert-variant driven _extractAkiAndSerial + AKI-walker rejections ----
1611
+
1612
+ async function testFetchAriSerialZeroCert() {
1613
+ // A serial of 0 renders as an odd-length hex string ("0"); the serial
1614
+ // guard in _extractAkiAndSerial refuses it before any network call.
1615
+ var acme = _acme();
1616
+ check("fetchAri on a serial-0 cert (odd-length hex serial) -> acme/bad-cert",
1617
+ (await _acode(acme.fetchAri({ certPem: CERT_SERIAL_ZERO }))) === "acme/bad-cert");
1618
+ }
1619
+
1620
+ async function testFetchAriAkiWalkerRejections() {
1621
+ // Every malformed-AKI shape resolves to acme/no-aki (fail-closed) — the
1622
+ // walker never surfaces a truncated/garbage keyIdentifier as valid.
1623
+ var acme = _acme();
1624
+ check("fetchAri on a cert with no extensions field -> acme/no-aki",
1625
+ (await _acode(acme.fetchAri({ certPem: CERT_NO_EXTENSIONS }))) === "acme/no-aki");
1626
+ check("fetchAri on an AKI lacking keyIdentifier [0] -> acme/no-aki",
1627
+ (await _acode(acme.fetchAri({ certPem: CERT_AKI_NO_KEYID }))) === "acme/no-aki");
1628
+ check("fetchAri on an AKI whose octet content is an un-parseable TLV -> acme/no-aki",
1629
+ (await _acode(acme.fetchAri({ certPem: CERT_AKI_OCTET_UNPARSEABLE }))) === "acme/no-aki");
1630
+ check("fetchAri on an AKI whose octet content is a primitive (not a SEQUENCE) -> acme/no-aki",
1631
+ (await _acode(acme.fetchAri({ certPem: CERT_AKI_OCTET_NOT_SEQ }))) === "acme/no-aki");
1632
+ check("fetchAri on an AKI SEQUENCE with a truncated inner body -> acme/no-aki",
1633
+ (await _acode(acme.fetchAri({ certPem: CERT_AKI_INNER_BAD }))) === "acme/no-aki");
1634
+ }
1635
+
1636
+ // ---- accountKeyRollover: auto-fetch, key-material failures, success ------
1637
+
1638
+ async function testRolloverAutoFetchesDirectory() {
1639
+ // A fresh handle (directory not yet fetched) must fetch it inside
1640
+ // accountKeyRollover before the no-account guard fires.
1641
+ var acme = _acme();
1642
+ await _withHttp(_orderHandler(_fullDir(), { status: 201 }), async function () {
1643
+ check("accountKeyRollover on a fresh handle fetches the directory then trips no-account",
1644
+ (await _acode(acme.accountKeyRollover(_newKey().privateKey))) === "acme/no-account");
1645
+ check("accountKeyRollover populated the directory cache during the auto-fetch",
1646
+ acme.directory() && acme.directory().keyChange === CA + "/key-change");
1647
+ });
1648
+ }
1649
+
1650
+ async function testRolloverBadKeyMaterial() {
1651
+ var acme = _acme();
1652
+ await _withHttp(_accountHandler(_fullDir(), { status: 201, headers: { location: CA + "/acct/1" } }), async function () {
1653
+ await acme.newAccount();
1654
+ // A DH KeyObject exposes export() but export({format:"jwk"}) throws;
1655
+ // _publicJwkFromKeyObject surfaces acme/bad-account-key.
1656
+ var dh = nodeCrypto.generateKeyPairSync("dh", { group: "modp14" });
1657
+ check("accountKeyRollover with a non-EC key (jwk export throws) -> acme/bad-account-key",
1658
+ (await _acode(acme.accountKeyRollover(dh.privateKey))) === "acme/bad-account-key");
1659
+ // A P-256 *public* KeyObject passes the JWK shape check but cannot sign
1660
+ // the inner JWS -> the ES256 signer throws acme/sign-failed.
1661
+ var pub = _newKey().publicKey;
1662
+ check("accountKeyRollover with a public KeyObject (cannot sign) -> acme/sign-failed",
1663
+ (await _acode(acme.accountKeyRollover(pub))) === "acme/sign-failed");
1664
+ });
1665
+ }
1666
+
1667
+ async function testRolloverSuccessSwapsKey() {
1668
+ var sink = _auditSink();
1669
+ var acme = _acme({ audit: sink });
1670
+ var captured = { keyChangeBody: null };
1671
+ var nonce = _nonceState();
1672
+ var handler = function (req) {
1673
+ var h = nonce();
1674
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1675
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1676
+ if (req.method === "POST" && req.url.indexOf("/new-account") !== -1) { h.location = CA + "/acct/roll"; return Promise.resolve(_resp(201, h, { status: "valid" })); }
1677
+ if (req.method === "POST" && req.url.indexOf("/key-change") !== -1) { captured.keyChangeBody = req.body; return Promise.resolve(_resp(200, h, { status: "valid" })); }
1678
+ return Promise.resolve(_resp(404, h, ""));
1679
+ };
1680
+ var newKey = _newKey();
1681
+ var newJwk = newKey.publicKey.export({ format: "jwk" });
1682
+ var oldX;
1683
+ await _withHttp(handler, async function () {
1684
+ await acme.newAccount();
1685
+ oldX = acme.publicJwk().x;
1686
+ var ok = await acme.accountKeyRollover(newKey.privateKey);
1687
+ check("accountKeyRollover success resolves true", ok === true);
1688
+ check("accountKeyRollover swaps publicJwk() to the new key",
1689
+ acme.publicJwk().x === newJwk.x && acme.publicJwk().y === newJwk.y && acme.publicJwk().x !== oldX);
1690
+ });
1691
+ // RFC 8555 §7.3.5 — the inner JWS is signed by the NEW key and commits
1692
+ // { account, oldKey } as its payload.
1693
+ var outer = JSON.parse(captured.keyChangeBody);
1694
+ var innerJws = JSON.parse(Buffer.from(outer.payload, "base64url").toString("utf8"));
1695
+ var innerProt = JSON.parse(Buffer.from(innerJws.protected, "base64url").toString("utf8"));
1696
+ var innerPayload = JSON.parse(Buffer.from(innerJws.payload, "base64url").toString("utf8"));
1697
+ check("rollover inner JWS protected header carries the NEW key jwk", innerProt.jwk && innerProt.jwk.x === newJwk.x);
1698
+ check("rollover inner JWS payload commits the OLD key + account url",
1699
+ innerPayload.oldKey && innerPayload.oldKey.x === oldX && innerPayload.account === CA + "/acct/roll");
1700
+ check("accountKeyRollover success emits acme.account.key_rotated success audit",
1701
+ sink.events.some(function (e) { return e.action === "acme.account.key_rotated" && e.outcome === "success"; }));
1702
+ }
1703
+
1704
+ // ---- newOrder capitalized Location header --------------------------------
1705
+
1706
+ async function testNewOrderCapitalLocationHeader() {
1707
+ // A CA returning only a capitalized "Location" header still yields the
1708
+ // order URL (case-insensitive header read).
1709
+ var acme = _acme();
1710
+ await _withHttp(_orderHandler(_fullDir(), { status: 201, headers: { "Location": CA + "/order/cap" }, body: { status: "pending", finalize: CA + "/finalize/cap" } }), async function () {
1711
+ await acme.newAccount();
1712
+ var order = await acme.newOrder({ identifiers: [{ type: "dns", value: "cap.com" }] });
1713
+ check("newOrder reads a capitalized Location header for order.url", order.url === CA + "/order/cap");
1714
+ });
1715
+ }
1716
+
1717
+ // ---- waitForAuthorization timeout using the client-default pollMaxMs -----
1718
+
1719
+ async function testWaitForAuthorizationDefaultTimeout() {
1720
+ var acme = _acme({ pollIntervalMs: 5, pollMaxMs: 30 });
1721
+ await _withHttp(_authHandler({ "/auth/pending": function () { return { status: 200, body: { status: "pending" } }; } }), async function () {
1722
+ await acme.fetchDirectory();
1723
+ check("waitForAuthorization with no opts times out via the client pollMaxMs -> acme/auth-timeout",
1724
+ (await _acode(acme.waitForAuthorization(CA + "/auth/pending"))) === "acme/auth-timeout");
1725
+ });
1726
+ }
1727
+
1728
+ // ---- _parseJsonBody empty-body + Buffer-body branches --------------------
1729
+
1730
+ async function testParseJsonBodyEmptyAndBufferBranches() {
1731
+ var acme = _acme();
1732
+ var nonce = _nonceState();
1733
+ var handler = function (req) {
1734
+ var h = nonce();
1735
+ if (req.method === "GET" && req.url.indexOf("/directory") !== -1) return Promise.resolve(_resp(200, h, _fullDir()));
1736
+ if (req.method === "HEAD") return Promise.resolve(_resp(200, h, ""));
1737
+ if (req.method === "POST" && req.url.indexOf("/chal/empty-str") !== -1) return Promise.resolve({ statusCode: 200, headers: h, body: "" });
1738
+ if (req.method === "POST" && req.url.indexOf("/chal/buffer") !== -1) return Promise.resolve({ statusCode: 200, headers: h, body: Buffer.from(JSON.stringify({ status: "processing" }), "utf8") });
1739
+ if (req.method === "POST" && req.url.indexOf("/chal/empty-buf") !== -1) return Promise.resolve({ statusCode: 200, headers: h, body: Buffer.alloc(0) });
1740
+ return Promise.resolve(_resp(404, h, ""));
1741
+ };
1742
+ await _withHttp(handler, async function () {
1743
+ await acme.fetchDirectory();
1744
+ var emptyStr = await acme.notifyChallengeReady(CA + "/chal/empty-str");
1745
+ check("notifyChallengeReady with an empty-string body parses to {}", emptyStr && typeof emptyStr === "object" && emptyStr.status === undefined);
1746
+ var bufBody = await acme.notifyChallengeReady(CA + "/chal/buffer");
1747
+ check("notifyChallengeReady with a Buffer body parses the JSON", bufBody.status === "processing");
1748
+ var emptyBuf = await acme.notifyChallengeReady(CA + "/chal/empty-buf");
1749
+ check("notifyChallengeReady with an empty Buffer body parses to {}", emptyBuf && typeof emptyBuf === "object" && emptyBuf.status === undefined);
1750
+ });
1751
+ }
1752
+
1753
+ // ---- _extractProblemReason with no recognized fields ---------------------
1754
+
1755
+ async function testExtractProblemReasonNoRecognizedFields() {
1756
+ var sink = _auditSink();
1757
+ var acme = _acme({ audit: sink });
1758
+ await _withHttp(_orderHandler(_fullDir(), { status: 400, body: { instance: "urn:x", extra: 7 } }), async function () {
1759
+ await acme.newAccount();
1760
+ check("newOrder failure with no type/detail/title still -> acme/neworder",
1761
+ (await _acode(acme.newOrder({ identifiers: [{ type: "dns", value: "x.com" }] }))) === "acme/neworder");
1762
+ });
1763
+ check("newOrder failure audit reason is null when the problem doc has no type/detail/title",
1764
+ sink.events.some(function (e) { return e.action === "acme.order.created" && e.outcome === "failure" && e.metadata.reason === null; }));
1765
+ }
1766
+
207
1767
  async function run() {
208
1768
  testCreateRefusesBadOpts();
209
1769
  testCreateRefusesNonHttpsDirectory();
@@ -216,6 +1776,93 @@ async function run() {
216
1776
  testV0883NewSurface();
217
1777
  testV0883Base32Helper();
218
1778
  testV0883NewOrderProfileValidation();
1779
+ testCreateRefusesMissingDirectory();
1780
+ testCreateRefusesMissingAccountKey();
1781
+ testCreateRefusesPublicKeyObject();
1782
+ testCreateAcceptsPrivatePem();
1783
+ testCreateAcceptsNestedPrivateKey();
1784
+ testCreateRefusesBadPrivatePem();
1785
+ testCreateRefusesUnknownOpt();
1786
+ testCreateContactShapeBranches();
1787
+ testGettersNullBeforeLifecycle();
1788
+ testPublicJwkReturnsIsolatedCopy();
1789
+ testKeyAuthorizationDeterministicAndDistinct();
1790
+ testTlsAlpn01KeyAuthorization();
1791
+ testDnsAccount01ValidationBeforeAccount();
1792
+ testBuildCsrInputValidation();
1793
+ testBuildCsrP256();
1794
+ testBuildCsrP384();
1795
+ testBuildCsrRsa();
1796
+ testBuildCsrRejectsUnsupportedKeys();
1797
+ await testFinalizeValidation();
1798
+ await testSignedPostNeedsDirectory();
1799
+ await testRevokeCertRejectsNonBuffer();
1800
+ await testDeactivateAccountNeedsAccount();
1801
+ await testChallengeUrlValidation();
1802
+ await testFetchAriRejectsUnparseableCert();
1803
+ await testFetchAriSerialZeroCert();
1804
+ await testFetchAriAkiWalkerRejections();
1805
+
1806
+ // acme's internal poll uses an unref'd timer (it must not pin a host
1807
+ // process). Standalone, that means the event loop can empty mid-poll and
1808
+ // Node would exit before run() resolves. A ref'd keep-alive timer holds
1809
+ // the loop open while the transport-stubbed tests below run; cleared in
1810
+ // finally so the process (and the forked smoke child) exits cleanly once
1811
+ // every check has run.
1812
+ var keepAlive = setInterval(function () {}, C.TIME.seconds(1));
1813
+ try {
1814
+ testCreateNumericOpts();
1815
+ await testFetchDirectoryStatusAndShape();
1816
+ await testFetchDirectoryNetworkError();
1817
+ await testFetchDirectorySuccessBranches();
1818
+ await testNewAccountEabValidation();
1819
+ await testNewAccountEabSuccess();
1820
+ await testNewAccountFailureBranches();
1821
+ await testNewAccountSuccessWithContact();
1822
+ await testNewNonceHeadBranches();
1823
+ await testNewOrderGuards();
1824
+ await testNewOrderFailureAndSuccess();
1825
+ await testFinalizeNetworkBranches();
1826
+ await testRetrieveCertBadOrder();
1827
+ await testRetrieveCertImmediateValid();
1828
+ await testRetrieveCertInvalidOrder();
1829
+ await testRetrieveCertPollToValid();
1830
+ await testRetrieveCertPollNon2xx();
1831
+ await testRetrieveCertTimeout();
1832
+ await testRetrieveCertDownloadBranches();
1833
+ await testAuthorizationFlow();
1834
+ await testWaitForAuthorization();
1835
+ await testFetchAriGuards();
1836
+ await testFetchAriShapeGuards();
1837
+ await testFetchAriSuccess();
1838
+ await testRenewIfDueVerdicts();
1839
+ await testRenewIfDueJitter();
1840
+ await testRevokeCertBranches();
1841
+ await testRolloverBranches();
1842
+ await testDeactivateBranches();
1843
+ await testDnsAccount01Success();
1844
+ await testListProfiles();
1845
+ await testAuditThrowIsSwallowed();
1846
+ await testRolloverAutoFetchesDirectory();
1847
+ await testRolloverBadKeyMaterial();
1848
+ await testRolloverSuccessSwapsKey();
1849
+ await testNewOrderCapitalLocationHeader();
1850
+ await testWaitForAuthorizationDefaultTimeout();
1851
+ await testParseJsonBodyEmptyAndBufferBranches();
1852
+ await testExtractProblemReasonNoRecognizedFields();
1853
+ } finally {
1854
+ clearInterval(keepAlive);
1855
+ }
219
1856
  }
220
1857
 
221
1858
  module.exports = { run: run };
1859
+
1860
+ // Allow direct execution: `node test/layer-0-primitives/acme.test.js`
1861
+ if (require.main === module) {
1862
+ run().then(function () {
1863
+ console.log("OK — acme " + helpers.getChecks() + " checks passed");
1864
+ }).catch(function (e) {
1865
+ console.error(helpers.formatErr(e));
1866
+ process.exit(1);
1867
+ });
1868
+ }