@blamejs/blamejs-shop 0.5.11 → 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 (524) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/SECURITY.md +6 -1
  3. package/lib/admin.js +56 -0
  4. package/lib/asset-manifest.json +1 -1
  5. package/lib/operator-sessions.js +68 -5
  6. package/lib/vendor/MANIFEST.json +632 -416
  7. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  8. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  9. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  10. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  11. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  12. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  13. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  14. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  15. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  16. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  17. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  18. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  19. package/lib/vendor/blamejs/.gitignore +2 -0
  20. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  21. package/lib/vendor/blamejs/NOTICE +26 -1
  22. package/lib/vendor/blamejs/SECURITY.md +1 -1
  23. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  24. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  25. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  26. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  27. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  28. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  29. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  30. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  31. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  32. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  33. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  34. package/lib/vendor/blamejs/index.js +6 -0
  35. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  36. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  37. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  38. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  39. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  40. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  41. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  42. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  43. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  44. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  45. package/lib/vendor/blamejs/lib/audit.js +71 -8
  46. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  47. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  48. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  49. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  50. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  51. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  52. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  53. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  54. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  55. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  56. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  57. package/lib/vendor/blamejs/lib/base32.js +21 -0
  58. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  59. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  60. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  61. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  62. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  63. package/lib/vendor/blamejs/lib/cert.js +29 -11
  64. package/lib/vendor/blamejs/lib/cli.js +94 -24
  65. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  66. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  67. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  68. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  69. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  70. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  71. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  72. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  73. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  74. package/lib/vendor/blamejs/lib/cose.js +31 -16
  75. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  76. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  77. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  78. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  79. package/lib/vendor/blamejs/lib/csp.js +11 -3
  80. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  81. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  82. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  83. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  84. package/lib/vendor/blamejs/lib/db.js +18 -6
  85. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  86. package/lib/vendor/blamejs/lib/dev.js +21 -2
  87. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  88. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  89. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  90. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  91. package/lib/vendor/blamejs/lib/forms.js +113 -27
  92. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  93. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  94. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  95. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  96. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  97. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  98. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  99. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  100. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  101. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  102. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  103. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  104. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  105. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  106. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  107. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  108. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  109. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  110. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  111. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  112. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  113. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  114. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  115. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  116. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  117. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  118. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  119. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  120. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  121. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  122. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  123. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  124. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  125. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  126. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  127. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  128. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  129. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  130. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  131. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  132. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  133. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  134. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  135. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  136. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  137. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  138. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  139. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  140. package/lib/vendor/blamejs/lib/mail.js +15 -5
  141. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  142. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  143. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  144. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  145. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  146. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  147. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  148. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  149. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  150. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  151. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  153. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  154. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  155. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  156. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  157. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  158. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  159. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  160. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  161. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  162. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  163. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  164. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  165. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  166. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  167. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  168. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  169. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  170. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  171. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  172. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  173. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  174. package/lib/vendor/blamejs/lib/redact.js +54 -0
  175. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  176. package/lib/vendor/blamejs/lib/restore.js +19 -0
  177. package/lib/vendor/blamejs/lib/retention.js +12 -4
  178. package/lib/vendor/blamejs/lib/router.js +60 -6
  179. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  180. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  181. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  182. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  183. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  184. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  185. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  186. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  187. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  188. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  189. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  190. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  191. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  192. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  193. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  194. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  195. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  196. package/lib/vendor/blamejs/lib/session.js +34 -12
  197. package/lib/vendor/blamejs/lib/sql.js +15 -1
  198. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  199. package/lib/vendor/blamejs/lib/static.js +55 -13
  200. package/lib/vendor/blamejs/lib/storage.js +8 -2
  201. package/lib/vendor/blamejs/lib/subject.js +6 -1
  202. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  203. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  204. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  205. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  206. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  207. package/lib/vendor/blamejs/lib/vc.js +44 -5
  208. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  209. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  210. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  211. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  212. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  213. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  214. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  215. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  216. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  217. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  218. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  219. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  220. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  221. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  222. package/lib/vendor/blamejs/package-lock.json +2 -2
  223. package/lib/vendor/blamejs/package.json +1 -1
  224. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  245. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  246. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  247. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  248. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  249. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  250. package/lib/vendor/blamejs/socket.yml +94 -0
  251. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  252. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  253. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  254. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  255. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  256. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  257. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  258. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  259. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  260. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  261. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  262. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  265. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  270. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  273. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  284. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  287. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  296. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  297. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  302. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  305. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  307. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  310. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  321. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  322. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  324. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  326. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  327. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  330. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  332. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  334. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  335. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  336. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  337. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  338. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  339. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  348. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  376. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  379. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  388. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  413. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  414. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  415. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  416. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  428. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  432. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  434. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  442. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  443. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  445. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  477. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  478. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  480. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  490. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  491. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  492. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  493. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  495. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  502. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  503. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  504. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  505. package/lib/vendor/blamejs/test/smoke.js +2 -0
  506. package/package.json +1 -1
  507. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  508. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  509. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  510. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  511. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  512. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  513. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  514. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  515. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  516. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  517. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  518. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  519. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  520. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  521. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  522. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  523. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  524. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -5,13 +5,22 @@
5
5
  * b.mail.dav — CalDAV (RFC 4791) + CardDAV (RFC 6352) HTTP route
6
6
  * handlers. Tests surface, dispatch shape, per-principal isolation,
7
7
  * iCal / vCard PUT-body validation, REPORT / PROPFIND XML body
8
- * parsing, ETag precondition handling.
8
+ * parsing, ETag precondition handling. Also mounts the returned
9
+ * Express-style handlers on a real node:http listener to drive actor
10
+ * resolution, method gating, every verb's wrong-state / missing-arg /
11
+ * backend-throw / not-found branch, body-cap overflow, MKCALENDAR /
12
+ * MKCOL, and discovery redirects over a live TCP connection.
9
13
  */
10
14
 
11
15
  var helpers = require("../helpers");
16
+ var b = helpers.b;
12
17
  var check = helpers.check;
13
18
  var mailDav = require("../../lib/mail-dav");
14
19
 
20
+ var http = require("node:http");
21
+
22
+ var C = b.constants;
23
+
15
24
  // ---- Mock storage ---------------------------------------------------------
16
25
 
17
26
  function _makeStorage() {
@@ -480,6 +489,806 @@ async function testHttpHandlerInvokesDispatch() {
480
489
  res.statusCode === 200 && /calendar-access/.test(res.headers["dav"]));
481
490
  }
482
491
 
492
+ // ---- Live-listener harness ------------------------------------------------
493
+ //
494
+ // The tests below mount the returned Express-style handlers on a node:http
495
+ // server and exercise them over a real TCP connection: method gating, actor
496
+ // resolution, per-principal isolation, path-traversal refusal, every verb's
497
+ // wrong-state / missing-arg / backend-throw / not-found branch, PROPFIND /
498
+ // REPORT XML body parsing (valid + malformed), ETag precondition failures,
499
+ // body-cap overflow (streamed + pre-parsed), MKCALENDAR / MKCOL, and
500
+ // discovery redirects.
501
+ //
502
+ // A thin wrapper server simulates the operator's mount: it strips the
503
+ // `/caldav` / `/carddav` prefix (as the operator's router would), populates
504
+ // `req.user` / `req.actor` (as auth middleware would), and optionally injects
505
+ // a pre-parsed `req.body` (as a body-parser would) - so every _readBodyBytes
506
+ // branch is reachable over the wire.
507
+
508
+ // ---- configurable storage (stateful + per-method overrides) --------------
509
+ function _storage(over) {
510
+ over = over || {};
511
+ var cal = Object.create(null);
512
+ var ab = Object.create(null);
513
+
514
+ function ensureCal(pid, cid) {
515
+ if (!cal[pid]) cal[pid] = Object.create(null);
516
+ if (cid && !cal[pid][cid]) {
517
+ cal[pid][cid] = { displayName: cid, etag: "\"cal-" + cid + "\"", components: Object.create(null) };
518
+ }
519
+ return cal[pid];
520
+ }
521
+ function ensureBook(pid, bid) {
522
+ if (!ab[pid]) ab[pid] = Object.create(null);
523
+ if (bid && !ab[pid][bid]) {
524
+ ab[pid][bid] = { displayName: bid, etag: "\"book-" + bid + "\"", cards: Object.create(null) };
525
+ }
526
+ return ab[pid];
527
+ }
528
+
529
+ var api = {
530
+ calendar: {
531
+ listCalendars: async function (pid) {
532
+ var p = cal[pid];
533
+ if (!p) return [];
534
+ return Object.keys(p).map(function (k) { return { id: k, displayName: p[k].displayName, etag: p[k].etag }; });
535
+ },
536
+ getComponent: async function (pid, cid, comp) {
537
+ if (!cal[pid] || !cal[pid][cid]) return null;
538
+ var c = cal[pid][cid].components[comp];
539
+ return c ? { id: comp, icalBytes: c.bytes, etag: c.etag, size: c.size } : null;
540
+ },
541
+ listComponents: async function (pid, cid) {
542
+ if (!cal[pid] || !cal[pid][cid]) return [];
543
+ return Object.keys(cal[pid][cid].components).map(function (k) {
544
+ var c = cal[pid][cid].components[k];
545
+ return { id: k, icalBytes: c.bytes, etag: c.etag, size: c.size };
546
+ });
547
+ },
548
+ putComponent: async function (pid, cid, comp, bytes, conds) {
549
+ ensureCal(pid, cid);
550
+ var existing = cal[pid][cid].components[comp];
551
+ if (conds && conds.ifMatch && existing && existing.etag !== conds.ifMatch) {
552
+ var e = new Error("etag-mismatch"); e.code = "etag-mismatch"; throw e;
553
+ }
554
+ var nextEtag = "\"comp-" + comp + (existing ? "-v2" : "-v1") + "\"";
555
+ cal[pid][cid].components[comp] = { bytes: bytes, etag: nextEtag, size: bytes.length };
556
+ return { created: !existing, etag: nextEtag };
557
+ },
558
+ deleteComponent: async function (pid, cid, comp, conds) {
559
+ if (!cal[pid] || !cal[pid][cid]) return { notFound: true };
560
+ var c = cal[pid][cid].components[comp];
561
+ if (!c) return { notFound: true };
562
+ if (conds && conds.ifMatch && c.etag !== conds.ifMatch) {
563
+ var e = new Error("etag-mismatch"); e.code = "etag-mismatch"; throw e;
564
+ }
565
+ delete cal[pid][cid].components[comp];
566
+ return { deleted: true };
567
+ },
568
+ mkcalendar: async function (pid, cid, props) {
569
+ ensureCal(pid, cid);
570
+ if (props && props.displayname) cal[pid][cid].displayName = props.displayname;
571
+ return { created: true };
572
+ },
573
+ },
574
+ addressbook: {
575
+ listAddressbooks: async function (pid) {
576
+ var p = ab[pid];
577
+ if (!p) return [];
578
+ return Object.keys(p).map(function (k) { return { id: k, displayName: p[k].displayName, etag: p[k].etag }; });
579
+ },
580
+ getCard: async function (pid, bid, card) {
581
+ if (!ab[pid] || !ab[pid][bid]) return null;
582
+ var c = ab[pid][bid].cards[card];
583
+ return c ? { id: card, vcardBytes: c.bytes, etag: c.etag, size: c.size } : null;
584
+ },
585
+ listCards: async function (pid, bid) {
586
+ if (!ab[pid] || !ab[pid][bid]) return [];
587
+ return Object.keys(ab[pid][bid].cards).map(function (k) {
588
+ var c = ab[pid][bid].cards[k];
589
+ return { id: k, vcardBytes: c.bytes, etag: c.etag, size: c.size };
590
+ });
591
+ },
592
+ putCard: async function (pid, bid, card, bytes, conds) {
593
+ ensureBook(pid, bid);
594
+ var existing = ab[pid][bid].cards[card];
595
+ if (conds && conds.ifMatch && existing && existing.etag !== conds.ifMatch) {
596
+ var e = new Error("etag-mismatch"); e.code = "etag-mismatch"; throw e;
597
+ }
598
+ var nextEtag = "\"card-" + card + (existing ? "-v2" : "-v1") + "\"";
599
+ ab[pid][bid].cards[card] = { bytes: bytes, etag: nextEtag, size: bytes.length };
600
+ return { created: !existing, etag: nextEtag };
601
+ },
602
+ deleteCard: async function (pid, bid, card, conds) {
603
+ if (!ab[pid] || !ab[pid][bid]) return { notFound: true };
604
+ var c = ab[pid][bid].cards[card];
605
+ if (!c) return { notFound: true };
606
+ if (conds && conds.ifMatch && c.etag !== conds.ifMatch) {
607
+ var e = new Error("etag-mismatch"); e.code = "etag-mismatch"; throw e;
608
+ }
609
+ delete ab[pid][bid].cards[card];
610
+ return { deleted: true };
611
+ },
612
+ mkcol: async function (pid, bid, props) {
613
+ ensureBook(pid, bid);
614
+ if (props && props.displayname) ab[pid][bid].displayName = props.displayname;
615
+ return { created: true };
616
+ },
617
+ },
618
+ _seedCal: function (pid, cid, comp, bytes, etag) {
619
+ ensureCal(pid, cid);
620
+ cal[pid][cid].components[comp] = { bytes: bytes, etag: etag || "\"seed\"", size: bytes.length };
621
+ },
622
+ _seedCard: function (pid, bid, card, bytes, etag) {
623
+ ensureBook(pid, bid);
624
+ ab[pid][bid].cards[card] = { bytes: bytes, etag: etag || "\"seed\"", size: bytes.length };
625
+ },
626
+ };
627
+
628
+ if (over.calendar) {
629
+ Object.keys(over.calendar).forEach(function (k) {
630
+ if (over.calendar[k] === null) delete api.calendar[k]; else api.calendar[k] = over.calendar[k];
631
+ });
632
+ }
633
+ if (over.addressbook) {
634
+ Object.keys(over.addressbook).forEach(function (k) {
635
+ if (over.addressbook[k] === null) delete api.addressbook[k]; else api.addressbook[k] = over.addressbook[k];
636
+ });
637
+ }
638
+ return api;
639
+ }
640
+
641
+ // ---- wrapper server: simulate operator mount + auth middleware -----------
642
+ //
643
+ // Headers understood by the wrapper (all optional):
644
+ // x-test-actor: "up:<id>" user.principalId | "ui:<id>" user.id |
645
+ // "un:<id>" user.username | "ap:<id>" actor.principalId |
646
+ // "empty" user = {} (no usable field)
647
+ // x-test-url-b64: base64 of an already-mount-stripped req.url (lets us
648
+ // drive _parsePath with bytes a raw request line can't
649
+ // carry — e.g. a NUL — while still travelling the wire)
650
+ // x-test-body: "buf" | "str" | "obj" | "bigbuf" | "bigstr" — inject a
651
+ // pre-parsed req.body (simulate a body-parser middleware)
652
+ function _mkServer(davOpts) {
653
+ var dav = b.mail.dav.create(davOpts);
654
+ var propfindXml = "<D:propfind xmlns:D=\"DAV:\"><D:allprop/></D:propfind>";
655
+ var server = http.createServer(function (req, res) {
656
+ var actor = req.headers["x-test-actor"];
657
+ if (actor === "empty") {
658
+ req.user = {};
659
+ } else if (actor) {
660
+ var kind = actor.slice(0, 2);
661
+ var val = actor.slice(3);
662
+ if (kind === "up") req.user = { principalId: val };
663
+ else if (kind === "ui") req.user = { id: val };
664
+ else if (kind === "un") req.user = { username: val };
665
+ else if (kind === "ap") req.actor = { principalId: val };
666
+ }
667
+
668
+ var bodyMode = req.headers["x-test-body"];
669
+ if (bodyMode === "buf") req.body = Buffer.from(propfindXml, "utf8");
670
+ else if (bodyMode === "str") req.body = propfindXml;
671
+ else if (bodyMode === "obj") req.body = { hello: "world" };
672
+ else if (bodyMode === "bigbuf") req.body = Buffer.alloc(40, 0x41);
673
+ else if (bodyMode === "bigstr") req.body = new Array(41).join("A");
674
+
675
+ var urlB64 = req.headers["x-test-url-b64"];
676
+ var path = req.url;
677
+ if (path.indexOf("/.well-known") === 0) { dav.discoveryHandler(req, res); return; }
678
+
679
+ var prefix = path.indexOf("/carddav") === 0 ? "/carddav" : "/caldav";
680
+ if (urlB64) req.url = Buffer.from(urlB64, "base64").toString("utf8");
681
+ else req.url = path.slice(prefix.length) || "/";
682
+
683
+ if (prefix === "/carddav") dav.carddavHandler(req, res);
684
+ else dav.caldavHandler(req, res);
685
+ });
686
+ return new Promise(function (resolve) {
687
+ server.listen(0, "127.0.0.1", function () {
688
+ resolve({ server: server, port: server.address().port });
689
+ });
690
+ });
691
+ }
692
+
693
+ function _close(s) {
694
+ return new Promise(function (resolve) { s.server.close(function () { resolve(); }); });
695
+ }
696
+
697
+ function _req(port, opts) {
698
+ return new Promise(function (resolve, reject) {
699
+ var r = http.request({
700
+ host: "127.0.0.1", port: port, method: opts.method,
701
+ path: opts.path, headers: opts.headers || {},
702
+ }, function (res) {
703
+ var chunks = [];
704
+ res.on("data", function (c) { chunks.push(c); });
705
+ res.on("end", function () {
706
+ resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(chunks).toString("utf8") });
707
+ });
708
+ });
709
+ r.on("error", function (e) {
710
+ // A body-cap overflow on the streamed path destroys the request
711
+ // socket (safeBuffer.collectStream tears the stream down on
712
+ // overflow), so the peer sees a reset rather than a clean status.
713
+ // Surface it as a sentinel the caller can treat as "refused".
714
+ if (opts.tolerateReset) { resolve({ status: 0, reset: true, headers: {}, body: "" }); return; }
715
+ reject(e);
716
+ });
717
+ if (opts.body !== undefined && opts.body !== null) r.write(opts.body);
718
+ r.end();
719
+ });
720
+ }
721
+
722
+ // principal-scoped headers helper
723
+ function _as(principal, extra) {
724
+ var h = { "x-test-actor": "up:" + principal };
725
+ if (extra) Object.keys(extra).forEach(function (k) { h[k] = extra[k]; });
726
+ return h;
727
+ }
728
+
729
+ // =====================================================================
730
+ // 1. Constructor opts — validation + defaults
731
+ // =====================================================================
732
+ function testCreateOpts() {
733
+ var threwBad = false;
734
+ try { b.mail.dav.create(); } catch (e) { threwBad = !!(e && e.code === "mail-dav/bad-opts"); }
735
+ check("create() with no opts → mail-dav/bad-opts", threwBad);
736
+
737
+ var threwNoStore = false;
738
+ try { b.mail.dav.create({}); } catch (e) { threwNoStore = !!(e && e.code === "mail-dav/no-storage"); }
739
+ check("create({}) → mail-dav/no-storage", threwNoStore);
740
+
741
+ var threwStrStore = false;
742
+ try { b.mail.dav.create({ storage: "nope" }); } catch (e) { threwStrStore = !!(e && e.code === "mail-dav/no-storage"); }
743
+ check("create({storage:string}) → mail-dav/no-storage", threwStrStore);
744
+
745
+ // valid finite positive maxRequestBodyBytes accepted
746
+ var okCustom = b.mail.dav.create({ storage: _storage(), maxRequestBodyBytes: C.BYTES.kib(1), profile: "balanced", compliancePosture: "hipaa" });
747
+ check("create() with custom maxRequestBodyBytes + posture builds", typeof okCustom.caldavHandler === "function");
748
+
749
+ // invalid maxRequestBodyBytes (0 / negative / NaN / Infinity / non-number) → falls back to default
750
+ [0, -5, NaN, Infinity, "8"].forEach(function (bad, i) {
751
+ var built = b.mail.dav.create({ storage: _storage(), maxRequestBodyBytes: bad });
752
+ check("create() with invalid maxRequestBodyBytes[" + i + "] falls back", typeof built.dispatchCaldav === "function");
753
+ });
754
+
755
+ check("create() exposes MailDavError", typeof b.mail.dav.MailDavError === "function");
756
+ }
757
+
758
+ // =====================================================================
759
+ // 2. Actor resolution (_actorPrincipalId) — every branch
760
+ // =====================================================================
761
+ async function testActorResolution() {
762
+ var s = await _mkServer({ storage: _storage() });
763
+ try {
764
+ check("user.principalId string → OPTIONS 200",
765
+ (await _req(s.port, { method: "OPTIONS", path: "/caldav/alice/", headers: { "x-test-actor": "up:alice" } })).status === 200);
766
+ check("user.id fallback → OPTIONS 200",
767
+ (await _req(s.port, { method: "OPTIONS", path: "/caldav/alice/", headers: { "x-test-actor": "ui:alice" } })).status === 200);
768
+ check("user.username fallback → OPTIONS 200",
769
+ (await _req(s.port, { method: "OPTIONS", path: "/caldav/alice/", headers: { "x-test-actor": "un:alice" } })).status === 200);
770
+ check("req.actor.principalId fallback → OPTIONS 200",
771
+ (await _req(s.port, { method: "OPTIONS", path: "/caldav/alice/", headers: { "x-test-actor": "ap:alice" } })).status === 200);
772
+ check("actor object with no usable field → 401",
773
+ (await _req(s.port, { method: "OPTIONS", path: "/caldav/alice/", headers: { "x-test-actor": "empty" } })).status === 401);
774
+ check("no actor populated → 401",
775
+ (await _req(s.port, { method: "OPTIONS", path: "/caldav/alice/" })).status === 401);
776
+ } finally { await _close(s); }
777
+ }
778
+
779
+ // =====================================================================
780
+ // 3. CalDAV dispatch — method gate, state, isolation, traversal
781
+ // =====================================================================
782
+ async function testCaldavDispatch() {
783
+ var s = await _mkServer({ storage: _storage() });
784
+ try {
785
+ check("unknown method (POST) → 405",
786
+ (await _req(s.port, { method: "POST", path: "/caldav/alice/cal1/c", headers: _as("alice") })).status === 405);
787
+ check("no actor → 401 (GET)",
788
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/cal1/c" })).status === 401);
789
+ check("cross-principal → 403",
790
+ (await _req(s.port, { method: "GET", path: "/caldav/bob/cal1/c", headers: _as("alice") })).status === 403);
791
+ check("principal-less non-PROPFIND → 400",
792
+ (await _req(s.port, { method: "GET", path: "/caldav/", headers: _as("alice") })).status === 400);
793
+ var rootPf = await _req(s.port, { method: "PROPFIND", path: "/caldav/", headers: _as("alice", { depth: "0" }) });
794
+ check("principal-less PROPFIND allowed → 207", rootPf.status === 207);
795
+
796
+ // traversal sub-branches
797
+ check("literal .. → 400",
798
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/cal1/../x", headers: _as("alice") })).status === 400);
799
+ check("%2e%2e → 400",
800
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/%2e%2e/x", headers: _as("alice") })).status === 400);
801
+ // MIXED encoding: neither a literal ".." nor "%2e%2e", but decodes to ".." —
802
+ // must be refused post-decode (the path-traversal HIGH: raw-only guard bypass).
803
+ check("mixed .%2e → 400 (decode-then-validate)",
804
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/.%2e", headers: _as("alice") })).status === 400);
805
+ check("mixed %2e. → 400 (decode-then-validate)",
806
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/%2e.", headers: _as("alice") })).status === 400);
807
+ check("%00 → 400",
808
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/%00/x", headers: _as("alice") })).status === 400);
809
+ check("malformed %-encoding → 400",
810
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/%zz/x", headers: _as("alice") })).status === 400);
811
+ // raw NUL byte in the (mount-stripped) path — carried as base64 over the wire
812
+ var nulUrl = Buffer.from("/alice/a\x00b/x", "utf8").toString("base64");
813
+ check("raw NUL byte in path → 400",
814
+ (await _req(s.port, { method: "GET", path: "/caldav/x", headers: _as("alice", { "x-test-url-b64": nulUrl }) })).status === 400);
815
+
816
+ // query-string strip: GET a missing component with a ?query → 404 (path parsed, query dropped)
817
+ check("query string dropped before parse → 404 (missing comp)",
818
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/cal1/missing?a=b", headers: _as("alice") })).status === 404);
819
+ } finally { await _close(s); }
820
+
821
+ // no calendar storage configured → 501
822
+ var full = _storage();
823
+ var sNoCal = await _mkServer({ storage: { addressbook: full.addressbook } });
824
+ try {
825
+ check("no calendar backend → 501",
826
+ (await _req(sNoCal.port, { method: "GET", path: "/caldav/alice/cal1/c", headers: _as("alice") })).status === 501);
827
+ } finally { await _close(sNoCal); }
828
+
829
+ // storage throws a generic (non-etag) error → dispatch catch → 500
830
+ var sThrow = await _mkServer({ storage: _storage({ calendar: { listCalendars: async function () { throw new Error("backend boom"); } } }) });
831
+ try {
832
+ check("backend generic throw → 500",
833
+ (await _req(sThrow.port, { method: "PROPFIND", path: "/caldav/alice/", headers: _as("alice", { depth: "1" }) })).status === 500);
834
+ } finally { await _close(sThrow); }
835
+ }
836
+
837
+ // =====================================================================
838
+ // 4. CalDAV PROPFIND — depth / collection / single / prop-list / malformed
839
+ // =====================================================================
840
+ async function testCaldavPropfind() {
841
+ var storage = _storage();
842
+ storage._seedCal("alice", "cal1", "comp1", Buffer.from(_ical(), "utf8"), "\"e1\"");
843
+ var s = await _mkServer({ storage: storage });
844
+ try {
845
+ check("PROPFIND principal depth 0 → 207 (self only)",
846
+ (await _req(s.port, { method: "PROPFIND", path: "/caldav/alice", headers: _as("alice", { depth: "0" }) })).status === 207);
847
+
848
+ var d1 = await _req(s.port, { method: "PROPFIND", path: "/caldav/alice", headers: _as("alice", { depth: "1" }) });
849
+ check("PROPFIND principal depth 1 → lists calendars", d1.status === 207 && /cal1/.test(d1.body));
850
+
851
+ check("PROPFIND calendar collection depth 0 → 207",
852
+ (await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/", headers: _as("alice", { depth: "0" }) })).status === 207);
853
+
854
+ var coll = await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/", headers: _as("alice", { depth: "1" }) });
855
+ check("PROPFIND calendar collection depth 1 → lists components", coll.status === 207 && /comp1/.test(coll.body));
856
+
857
+ var single = await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/comp1", headers: _as("alice", { depth: "0" }) });
858
+ check("PROPFIND single component → getetag present", single.status === 207 && /getetag/.test(single.body));
859
+
860
+ check("PROPFIND missing component → 207 with 404 propstat",
861
+ /404/.test((await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/nope", headers: _as("alice", { depth: "0" }) })).body));
862
+
863
+ // explicit prop list (filters _renderProps) + request calendar-data
864
+ var propList =
865
+ "<?xml version=\"1.0\"?><D:propfind xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" +
866
+ "<D:prop><D:getetag/><D:displayname/><C:calendar-data/></D:prop></D:propfind>";
867
+ var withProps = await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/", headers: _as("alice", { depth: "1" }), body: propList });
868
+ check("PROPFIND with prop list → calendar-data embedded", withProps.status === 207 && /calendar-data/.test(withProps.body));
869
+
870
+ // malformed XML body → client fault → 400 (like MKCALENDAR/MKCOL)
871
+ check("PROPFIND malformed XML body → 400",
872
+ (await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/", headers: _as("alice", { depth: "1" }), body: "<not-xml" })).status === 400);
873
+ } finally { await _close(s); }
874
+ }
875
+
876
+ // =====================================================================
877
+ // 5. CalDAV REPORT — multiget / query / unsupported / empty / malformed
878
+ // =====================================================================
879
+ async function testCaldavReport() {
880
+ var storage = _storage();
881
+ var bytes = Buffer.from(_ical(), "utf8");
882
+ storage._seedCal("alice", "cal1", "comp1", bytes, "\"e1\"");
883
+ storage._seedCal("alice", "cal1", "comp2", bytes, "\"e2\"");
884
+ var s = await _mkServer({ storage: storage });
885
+ try {
886
+ // multiget: one present, one missing, one cross-principal, one traversal-rejected href
887
+ var mg =
888
+ "<C:calendar-multiget xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" +
889
+ "<D:prop><D:getetag/><C:calendar-data/></D:prop>" +
890
+ "<D:href>/alice/cal1/comp1</D:href>" +
891
+ "<D:href>/alice/cal1/missing</D:href>" +
892
+ "<D:href>/bob/cal1/comp1</D:href>" +
893
+ "<D:href>/alice/../x</D:href>" +
894
+ "</C:calendar-multiget>";
895
+ var mgr = await _req(s.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: mg });
896
+ check("REPORT multiget → 207", mgr.status === 207);
897
+ check("REPORT multiget present href → 200 comp1", /comp1/.test(mgr.body));
898
+ check("REPORT multiget missing href → 404", /404/.test(mgr.body));
899
+ check("REPORT multiget cross-principal + traversal href → 403", /403/.test(mgr.body));
900
+
901
+ // calendar-query with explicit prop
902
+ var cq =
903
+ "<C:calendar-query xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" +
904
+ "<D:prop><D:getetag/></D:prop><C:filter/></C:calendar-query>";
905
+ var cqr = await _req(s.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: cq });
906
+ check("REPORT calendar-query → 207 with rows", cqr.status === 207 && /comp1/.test(cqr.body) && /comp2/.test(cqr.body));
907
+
908
+ check("REPORT unsupported kind → 422",
909
+ (await _req(s.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"),
910
+ body: "<C:free-busy-query xmlns:C=\"urn:ietf:params:xml:ns:caldav\"/>" })).status === 422);
911
+
912
+ check("REPORT empty body → 400 (client fault)",
913
+ (await _req(s.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: "" })).status === 400);
914
+ check("REPORT malformed XML → 400 (client fault)",
915
+ (await _req(s.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: "<broken" })).status === 400);
916
+ } finally { await _close(s); }
917
+ }
918
+
919
+ // =====================================================================
920
+ // 6. CalDAV GET — arg gating + found + not-found + etag-less
921
+ // =====================================================================
922
+ async function testCaldavGetHttp() {
923
+ var storage = _storage();
924
+ var bytes = Buffer.from(_ical(), "utf8");
925
+ storage._seedCal("alice", "cal1", "comp1", bytes, "\"e1\"");
926
+ var s = await _mkServer({ storage: storage });
927
+ try {
928
+ check("GET on collection (no component) → 404",
929
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/cal1/", headers: _as("alice") })).status === 404);
930
+ var g = await _req(s.port, { method: "GET", path: "/caldav/alice/cal1/comp1", headers: _as("alice") });
931
+ check("GET component → 200 + body + ETag", g.status === 200 && g.headers["etag"] === "\"e1\"" && g.body === bytes.toString("utf8"));
932
+ check("GET content-type text/calendar", /text\/calendar/.test(g.headers["content-type"]));
933
+ check("GET missing component → 404",
934
+ (await _req(s.port, { method: "GET", path: "/caldav/alice/cal1/gone", headers: _as("alice") })).status === 404);
935
+ } finally { await _close(s); }
936
+
937
+ // component without etag → no ETag header
938
+ var sNoEtag = await _mkServer({ storage: _storage({ calendar: {
939
+ getComponent: async function (pid, cid, comp) { return { id: comp, icalBytes: Buffer.from(_ical(), "utf8") }; },
940
+ } }) });
941
+ try {
942
+ var ge = await _req(sNoEtag.port, { method: "GET", path: "/caldav/alice/cal1/x", headers: _as("alice") });
943
+ check("GET etag-less component → 200, no ETag header", ge.status === 200 && ge.headers["etag"] === undefined);
944
+ } finally { await _close(sNoEtag); }
945
+ }
946
+
947
+ // =====================================================================
948
+ // 7. CalDAV PUT — arg gating, ical refusal, created/updated, etag, throw
949
+ // =====================================================================
950
+ async function testCaldavPut() {
951
+ var storage = _storage();
952
+ var s = await _mkServer({ storage: storage });
953
+ try {
954
+ check("PUT on collection (no component) → 400",
955
+ (await _req(s.port, { method: "PUT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: _ical() })).status === 400);
956
+
957
+ // RRULE COUNT bomb → safeIcal refuses → 415
958
+ var bomb = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//B//\r\nBEGIN:VEVENT\r\nUID:b@x\r\n" +
959
+ "DTSTAMP:20260101T120000Z\r\nDTSTART:20260101T130000Z\r\nRRULE:FREQ=DAILY;COUNT=999999\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n";
960
+ check("PUT invalid iCal (RRULE bomb) → 415",
961
+ (await _req(s.port, { method: "PUT", path: "/caldav/alice/cal1/bomb", headers: _as("alice"), body: bomb })).status === 415);
962
+
963
+ var created = await _req(s.port, { method: "PUT", path: "/caldav/alice/cal1/comp1", headers: _as("alice"), body: _ical() });
964
+ check("PUT new component → 201 + ETag", created.status === 201 && typeof created.headers["etag"] === "string");
965
+
966
+ var updated = await _req(s.port, { method: "PUT", path: "/caldav/alice/cal1/comp1", headers: _as("alice"), body: _ical() });
967
+ check("PUT existing component (no If-Match) → 204", updated.status === 204);
968
+
969
+ // If-Match mismatch → putComponent throws etag-mismatch → 412
970
+ check("PUT If-Match mismatch → 412",
971
+ (await _req(s.port, { method: "PUT", path: "/caldav/alice/cal1/comp1", headers: _as("alice", { "if-match": "\"wrong\"" }), body: _ical() })).status === 412);
972
+ } finally { await _close(s); }
973
+
974
+ // putComponent throws a generic error → rethrow → 500
975
+ var sThrow = await _mkServer({ storage: _storage({ calendar: {
976
+ putComponent: async function () { throw new Error("disk full"); },
977
+ } }) });
978
+ try {
979
+ check("PUT backend generic throw → 500",
980
+ (await _req(sThrow.port, { method: "PUT", path: "/caldav/alice/cal1/x", headers: _as("alice"), body: _ical() })).status === 500);
981
+ } finally { await _close(sThrow); }
982
+
983
+ // putComponent returns no etag → 201 without ETag header
984
+ var sNoEtag = await _mkServer({ storage: _storage({ calendar: {
985
+ putComponent: async function () { return { created: true }; },
986
+ } }) });
987
+ try {
988
+ var r = await _req(sNoEtag.port, { method: "PUT", path: "/caldav/alice/cal1/x", headers: _as("alice"), body: _ical() });
989
+ check("PUT etag-less result → 201, no ETag header", r.status === 201 && r.headers["etag"] === undefined);
990
+ } finally { await _close(sNoEtag); }
991
+ }
992
+
993
+ // =====================================================================
994
+ // 8. CalDAV DELETE — arg gating, success, not-found, etag, throw
995
+ // =====================================================================
996
+ async function testCaldavDeleteHttp() {
997
+ var storage = _storage();
998
+ storage._seedCal("alice", "cal1", "comp1", Buffer.from(_ical(), "utf8"), "\"e1\"");
999
+ var s = await _mkServer({ storage: storage });
1000
+ try {
1001
+ check("DELETE on collection (no component) → 400",
1002
+ (await _req(s.port, { method: "DELETE", path: "/caldav/alice/cal1/", headers: _as("alice") })).status === 400);
1003
+ check("DELETE If-Match mismatch → 412",
1004
+ (await _req(s.port, { method: "DELETE", path: "/caldav/alice/cal1/comp1", headers: _as("alice", { "if-match": "\"nope\"" }) })).status === 412);
1005
+ check("DELETE existing → 204",
1006
+ (await _req(s.port, { method: "DELETE", path: "/caldav/alice/cal1/comp1", headers: _as("alice") })).status === 204);
1007
+ check("DELETE missing → 404",
1008
+ (await _req(s.port, { method: "DELETE", path: "/caldav/alice/cal1/comp1", headers: _as("alice") })).status === 404);
1009
+ } finally { await _close(s); }
1010
+
1011
+ var sThrow = await _mkServer({ storage: _storage({ calendar: {
1012
+ deleteComponent: async function () { throw new Error("io error"); },
1013
+ } }) });
1014
+ try {
1015
+ check("DELETE backend generic throw → 500",
1016
+ (await _req(sThrow.port, { method: "DELETE", path: "/caldav/alice/cal1/x", headers: _as("alice") })).status === 500);
1017
+ } finally { await _close(sThrow); }
1018
+ }
1019
+
1020
+ // =====================================================================
1021
+ // 9. MKCALENDAR — arg gating, unsupported, empty/valid/malformed body
1022
+ // =====================================================================
1023
+ async function testMkcalendarHttp() {
1024
+ var s = await _mkServer({ storage: _storage() });
1025
+ try {
1026
+ check("MKCALENDAR without calendar segment → 400",
1027
+ (await _req(s.port, { method: "MKCALENDAR", path: "/caldav/alice/", headers: _as("alice") })).status === 400);
1028
+ check("MKCALENDAR empty body → 201",
1029
+ (await _req(s.port, { method: "MKCALENDAR", path: "/caldav/alice/newcal/", headers: _as("alice") })).status === 201);
1030
+ var body =
1031
+ "<C:mkcalendar xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" +
1032
+ "<D:set><D:prop><D:displayname>Personal</D:displayname></D:prop></D:set></C:mkcalendar>";
1033
+ check("MKCALENDAR with prop body → 201",
1034
+ (await _req(s.port, { method: "MKCALENDAR", path: "/caldav/alice/personal/", headers: _as("alice"), body: body })).status === 201);
1035
+ check("MKCALENDAR malformed body → 400",
1036
+ (await _req(s.port, { method: "MKCALENDAR", path: "/caldav/alice/broke/", headers: _as("alice"), body: "<nope" })).status === 400);
1037
+ } finally { await _close(s); }
1038
+
1039
+ // mkcalendar backend absent → 501
1040
+ var sNoMk = await _mkServer({ storage: _storage({ calendar: { mkcalendar: null } }) });
1041
+ try {
1042
+ check("MKCALENDAR with no backend fn → 501",
1043
+ (await _req(sNoMk.port, { method: "MKCALENDAR", path: "/caldav/alice/x/", headers: _as("alice") })).status === 501);
1044
+ } finally { await _close(sNoMk); }
1045
+
1046
+ // mkcalendar returns not-created → 200
1047
+ var s200 = await _mkServer({ storage: _storage({ calendar: { mkcalendar: async function () { return { created: false }; } } }) });
1048
+ try {
1049
+ check("MKCALENDAR returns not-created → 200",
1050
+ (await _req(s200.port, { method: "MKCALENDAR", path: "/caldav/alice/x/", headers: _as("alice") })).status === 200);
1051
+ } finally { await _close(s200); }
1052
+ }
1053
+
1054
+ // =====================================================================
1055
+ // 10. _readBodyBytes — pre-parsed req.body branches + cap overflow
1056
+ // =====================================================================
1057
+ async function testReadBody() {
1058
+ var s = await _mkServer({ storage: _storage() });
1059
+ try {
1060
+ check("pre-parsed Buffer body within cap → PROPFIND 207",
1061
+ (await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/", headers: _as("alice", { depth: "0", "x-test-body": "buf" }) })).status === 207);
1062
+ check("pre-parsed string body within cap → PROPFIND 207",
1063
+ (await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/", headers: _as("alice", { depth: "0", "x-test-body": "str" }) })).status === 207);
1064
+ // object body → JSON.stringify'd → not valid XML → parser refuses → 400 (client fault)
1065
+ check("pre-parsed object body → JSON bytes → 400",
1066
+ (await _req(s.port, { method: "PROPFIND", path: "/caldav/alice/cal1/", headers: _as("alice", { depth: "1", "x-test-body": "obj" }) })).status === 400);
1067
+ } finally { await _close(s); }
1068
+
1069
+ // tiny cap: pre-parsed oversize Buffer / string → reject → 500 ; streamed oversize → 500
1070
+ var sCap = await _mkServer({ storage: _storage(), maxRequestBodyBytes: C.BYTES.bytes(16) });
1071
+ try {
1072
+ check("pre-parsed Buffer over cap → 500",
1073
+ (await _req(sCap.port, { method: "PROPFIND", path: "/caldav/alice/", headers: _as("alice", { depth: "0", "x-test-body": "bigbuf" }) })).status === 500);
1074
+ check("pre-parsed string over cap → 500",
1075
+ (await _req(sCap.port, { method: "PROPFIND", path: "/caldav/alice/", headers: _as("alice", { depth: "0", "x-test-body": "bigstr" }) })).status === 500);
1076
+ // Streamed overflow tears down the request socket, so the peer sees
1077
+ // either a 500 (if the refusal races ahead of the destroy) or a reset.
1078
+ var streamed = await _req(sCap.port, { method: "PROPFIND", path: "/caldav/alice/", headers: _as("alice", { depth: "0" }), body: new Array(200).join("x"), tolerateReset: true });
1079
+ check("streamed body over cap → refused (500 or reset)", streamed.status === 500 || streamed.reset === true);
1080
+ } finally { await _close(sCap); }
1081
+ }
1082
+
1083
+ // =====================================================================
1084
+ // 11. _bufToText — string + non-buffer/non-string branches (via REPORT)
1085
+ // =====================================================================
1086
+ async function testBufToText() {
1087
+ // icalBytes as a plain string → _bufToText string branch
1088
+ var sStr = await _mkServer({ storage: _storage({ calendar: {
1089
+ getComponent: async function (pid, cid, comp) { return { id: comp, icalBytes: _ical(), etag: "\"s\"", size: 10 }; },
1090
+ } }) });
1091
+ try {
1092
+ var mg = "<C:calendar-multiget xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" +
1093
+ "<D:prop><C:calendar-data/></D:prop><D:href>/alice/cal1/comp1</D:href></C:calendar-multiget>";
1094
+ var r = await _req(sStr.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: mg });
1095
+ check("REPORT with string icalBytes → 207 (bufToText string branch)", r.status === 207 && /VCALENDAR/.test(r.body));
1096
+ } finally { await _close(sStr); }
1097
+
1098
+ // icalBytes as a number → _bufToText else (String()) branch
1099
+ var sNum = await _mkServer({ storage: _storage({ calendar: {
1100
+ getComponent: async function (pid, cid, comp) { return { id: comp, icalBytes: 12345, etag: "\"n\"", size: 5 }; },
1101
+ } }) });
1102
+ try {
1103
+ var mg2 = "<C:calendar-multiget xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">" +
1104
+ "<D:prop><C:calendar-data/></D:prop><D:href>/alice/cal1/comp1</D:href></C:calendar-multiget>";
1105
+ var r2 = await _req(sNum.port, { method: "REPORT", path: "/caldav/alice/cal1/", headers: _as("alice"), body: mg2 });
1106
+ check("REPORT with numeric icalBytes → 207 (bufToText else branch)", r2.status === 207 && /12345/.test(r2.body));
1107
+ } finally { await _close(sNum); }
1108
+ }
1109
+
1110
+ // =====================================================================
1111
+ // 12. CardDAV dispatch — method gate, state, isolation, verbs
1112
+ // =====================================================================
1113
+ async function testCarddavDispatch() {
1114
+ var storage = _storage();
1115
+ var bytes = Buffer.from(_vcard(), "utf8");
1116
+ storage._seedCard("alice", "book1", "card1", bytes, "\"v1\"");
1117
+ storage._seedCard("alice", "book1", "card2", bytes, "\"v2\"");
1118
+ var s = await _mkServer({ storage: storage });
1119
+ try {
1120
+ var opt = await _req(s.port, { method: "OPTIONS", path: "/carddav/alice/", headers: _as("alice") });
1121
+ check("CardDAV OPTIONS → 200 + addressbook DAV header", opt.status === 200 && /addressbook/.test(opt.headers["dav"]));
1122
+ check("CardDAV unknown method → 405",
1123
+ (await _req(s.port, { method: "PATCH", path: "/carddav/alice/book1/card1", headers: _as("alice") })).status === 405);
1124
+ check("CardDAV no actor → 401",
1125
+ (await _req(s.port, { method: "GET", path: "/carddav/alice/book1/card1" })).status === 401);
1126
+ check("CardDAV cross-principal → 403",
1127
+ (await _req(s.port, { method: "GET", path: "/carddav/bob/book1/card1", headers: _as("alice") })).status === 403);
1128
+ check("CardDAV principal-less non-PROPFIND → 400",
1129
+ (await _req(s.port, { method: "GET", path: "/carddav/", headers: _as("alice") })).status === 400);
1130
+ check("CardDAV traversal → 400",
1131
+ (await _req(s.port, { method: "GET", path: "/carddav/alice/book1/../x", headers: _as("alice") })).status === 400);
1132
+
1133
+ // PROPFIND variants
1134
+ check("CardDAV PROPFIND principal depth 0 → 207",
1135
+ (await _req(s.port, { method: "PROPFIND", path: "/carddav/alice", headers: _as("alice", { depth: "0" }) })).status === 207);
1136
+ var books = await _req(s.port, { method: "PROPFIND", path: "/carddav/alice", headers: _as("alice", { depth: "1" }) });
1137
+ check("CardDAV PROPFIND principal depth 1 → lists books", books.status === 207 && /book1/.test(books.body));
1138
+ check("CardDAV PROPFIND book collection depth 0 → 207",
1139
+ (await _req(s.port, { method: "PROPFIND", path: "/carddav/alice/book1/", headers: _as("alice", { depth: "0" }) })).status === 207);
1140
+ var cards = await _req(s.port, { method: "PROPFIND", path: "/carddav/alice/book1/", headers: _as("alice", { depth: "1" }) });
1141
+ check("CardDAV PROPFIND book collection depth 1 → lists cards", cards.status === 207 && /card1/.test(cards.body));
1142
+ var singleCard = await _req(s.port, { method: "PROPFIND", path: "/carddav/alice/book1/card1", headers: _as("alice", { depth: "0" }) });
1143
+ check("CardDAV PROPFIND single card → 207", singleCard.status === 207 && /getetag/.test(singleCard.body));
1144
+ check("CardDAV PROPFIND missing card → 404 propstat",
1145
+ /404/.test((await _req(s.port, { method: "PROPFIND", path: "/carddav/alice/book1/nope", headers: _as("alice", { depth: "0" }) })).body));
1146
+
1147
+ // REPORT multiget + query + unsupported
1148
+ var mg = "<A:addressbook-multiget xmlns:D=\"DAV:\" xmlns:A=\"urn:ietf:params:xml:ns:carddav\">" +
1149
+ "<D:prop><D:getetag/><A:address-data/></D:prop>" +
1150
+ "<D:href>/alice/book1/card1</D:href>" +
1151
+ "<D:href>/alice/book1/missing</D:href>" +
1152
+ "<D:href>/bob/book1/card1</D:href></A:addressbook-multiget>";
1153
+ var mgr = await _req(s.port, { method: "REPORT", path: "/carddav/alice/book1/", headers: _as("alice"), body: mg });
1154
+ check("CardDAV REPORT multiget → 207 present/missing/cross",
1155
+ mgr.status === 207 && /card1/.test(mgr.body) && /404/.test(mgr.body) && /403/.test(mgr.body));
1156
+ var aq = "<A:addressbook-query xmlns:D=\"DAV:\" xmlns:A=\"urn:ietf:params:xml:ns:carddav\">" +
1157
+ "<D:prop><D:getetag/></D:prop><A:filter/></A:addressbook-query>";
1158
+ check("CardDAV REPORT addressbook-query → 207",
1159
+ (await _req(s.port, { method: "REPORT", path: "/carddav/alice/book1/", headers: _as("alice"), body: aq })).status === 207);
1160
+ check("CardDAV REPORT unsupported kind → 422",
1161
+ (await _req(s.port, { method: "REPORT", path: "/carddav/alice/book1/", headers: _as("alice"),
1162
+ body: "<A:bogus-report xmlns:A=\"urn:ietf:params:xml:ns:carddav\"/>" })).status === 422);
1163
+
1164
+ // GET
1165
+ check("CardDAV GET collection (no card) → 404",
1166
+ (await _req(s.port, { method: "GET", path: "/carddav/alice/book1/", headers: _as("alice") })).status === 404);
1167
+ var gc = await _req(s.port, { method: "GET", path: "/carddav/alice/book1/card1", headers: _as("alice") });
1168
+ check("CardDAV GET card → 200 text/vcard + body", gc.status === 200 && /text\/vcard/.test(gc.headers["content-type"]) && gc.body === bytes.toString("utf8"));
1169
+ check("CardDAV GET missing card → 404",
1170
+ (await _req(s.port, { method: "GET", path: "/carddav/alice/book1/gone", headers: _as("alice") })).status === 404);
1171
+ } finally { await _close(s); }
1172
+
1173
+ // no addressbook storage → 501
1174
+ var full = _storage();
1175
+ var sNoCard = await _mkServer({ storage: { calendar: full.calendar } });
1176
+ try {
1177
+ check("CardDAV no addressbook backend → 501",
1178
+ (await _req(sNoCard.port, { method: "GET", path: "/carddav/alice/book1/c", headers: _as("alice") })).status === 501);
1179
+ } finally { await _close(sNoCard); }
1180
+
1181
+ // dispatch catch → 500 (backend throw)
1182
+ var sThrow = await _mkServer({ storage: _storage({ addressbook: { listAddressbooks: async function () { throw new Error("boom"); } } }) });
1183
+ try {
1184
+ check("CardDAV backend generic throw → 500",
1185
+ (await _req(sThrow.port, { method: "PROPFIND", path: "/carddav/alice", headers: _as("alice", { depth: "1" }) })).status === 500);
1186
+ } finally { await _close(sThrow); }
1187
+ }
1188
+
1189
+ // =====================================================================
1190
+ // 13. CardDAV PUT / DELETE / MKCOL — arg gating, refusal, etag, throw
1191
+ // =====================================================================
1192
+ async function testCarddavWrites() {
1193
+ var storage = _storage();
1194
+ storage._seedCard("alice", "book1", "card1", Buffer.from(_vcard(), "utf8"), "\"v1\"");
1195
+ var s = await _mkServer({ storage: storage });
1196
+ try {
1197
+ check("CardDAV PUT collection (no card) → 400",
1198
+ (await _req(s.port, { method: "PUT", path: "/carddav/alice/book1/", headers: _as("alice"), body: _vcard() })).status === 400);
1199
+ check("CardDAV PUT invalid vCard → 415",
1200
+ (await _req(s.port, { method: "PUT", path: "/carddav/alice/book1/bad", headers: _as("alice"), body: "BEGIN:VCARD\r\nVERSION:4.0\r\nBOGUSPROP:x\r\nEND:VCARD\r\n" })).status === 415);
1201
+ check("CardDAV PUT new card → 201",
1202
+ (await _req(s.port, { method: "PUT", path: "/carddav/alice/book1/card2", headers: _as("alice"), body: _vcard() })).status === 201);
1203
+ check("CardDAV PUT existing card → 204",
1204
+ (await _req(s.port, { method: "PUT", path: "/carddav/alice/book1/card2", headers: _as("alice"), body: _vcard() })).status === 204);
1205
+ check("CardDAV PUT If-Match mismatch → 412",
1206
+ (await _req(s.port, { method: "PUT", path: "/carddav/alice/book1/card1", headers: _as("alice", { "if-match": "\"wrong\"" }), body: _vcard() })).status === 412);
1207
+
1208
+ check("CardDAV DELETE collection (no card) → 400",
1209
+ (await _req(s.port, { method: "DELETE", path: "/carddav/alice/book1/", headers: _as("alice") })).status === 400);
1210
+ check("CardDAV DELETE If-Match mismatch → 412",
1211
+ (await _req(s.port, { method: "DELETE", path: "/carddav/alice/book1/card1", headers: _as("alice", { "if-match": "\"no\"" }) })).status === 412);
1212
+ check("CardDAV DELETE existing → 204",
1213
+ (await _req(s.port, { method: "DELETE", path: "/carddav/alice/book1/card1", headers: _as("alice") })).status === 204);
1214
+ check("CardDAV DELETE missing → 404",
1215
+ (await _req(s.port, { method: "DELETE", path: "/carddav/alice/book1/card1", headers: _as("alice") })).status === 404);
1216
+
1217
+ check("MKCOL without book segment → 400",
1218
+ (await _req(s.port, { method: "MKCOL", path: "/carddav/alice/", headers: _as("alice") })).status === 400);
1219
+ check("MKCOL empty body → 201",
1220
+ (await _req(s.port, { method: "MKCOL", path: "/carddav/alice/newbook/", headers: _as("alice") })).status === 201);
1221
+ var mkbody = "<D:mkcol xmlns:D=\"DAV:\"><D:set><D:prop><D:displayname>Contacts</D:displayname></D:prop></D:set></D:mkcol>";
1222
+ check("MKCOL with prop body → 201",
1223
+ (await _req(s.port, { method: "MKCOL", path: "/carddav/alice/contacts/", headers: _as("alice"), body: mkbody })).status === 201);
1224
+ check("MKCOL malformed body → 400",
1225
+ (await _req(s.port, { method: "MKCOL", path: "/carddav/alice/broke/", headers: _as("alice"), body: "<nope" })).status === 400);
1226
+ } finally { await _close(s); }
1227
+
1228
+ // PUT / DELETE backend generic throw → 500
1229
+ var sPutThrow = await _mkServer({ storage: _storage({ addressbook: { putCard: async function () { throw new Error("io"); } } }) });
1230
+ try {
1231
+ check("CardDAV PUT backend throw → 500",
1232
+ (await _req(sPutThrow.port, { method: "PUT", path: "/carddav/alice/book1/x", headers: _as("alice"), body: _vcard() })).status === 500);
1233
+ } finally { await _close(sPutThrow); }
1234
+
1235
+ var sDelThrow = await _mkServer({ storage: _storage({ addressbook: { deleteCard: async function () { throw new Error("io"); } } }) });
1236
+ try {
1237
+ check("CardDAV DELETE backend throw → 500",
1238
+ (await _req(sDelThrow.port, { method: "DELETE", path: "/carddav/alice/book1/x", headers: _as("alice") })).status === 500);
1239
+ } finally { await _close(sDelThrow); }
1240
+
1241
+ // MKCOL backend absent → 501 ; returns not-created → 200
1242
+ var sNoMkcol = await _mkServer({ storage: _storage({ addressbook: { mkcol: null } }) });
1243
+ try {
1244
+ check("MKCOL with no backend fn → 501",
1245
+ (await _req(sNoMkcol.port, { method: "MKCOL", path: "/carddav/alice/x/", headers: _as("alice") })).status === 501);
1246
+ } finally { await _close(sNoMkcol); }
1247
+
1248
+ var sMk200 = await _mkServer({ storage: _storage({ addressbook: { mkcol: async function () { return { created: false }; } } }) });
1249
+ try {
1250
+ check("MKCOL returns not-created → 200",
1251
+ (await _req(sMk200.port, { method: "MKCOL", path: "/carddav/alice/x/", headers: _as("alice") })).status === 200);
1252
+ } finally { await _close(sMk200); }
1253
+
1254
+ // etag-less putCard result → 201 without ETag
1255
+ var sNoEtag = await _mkServer({ storage: _storage({ addressbook: { putCard: async function () { return { created: true }; } } }) });
1256
+ try {
1257
+ var r = await _req(sNoEtag.port, { method: "PUT", path: "/carddav/alice/book1/x", headers: _as("alice"), body: _vcard() });
1258
+ check("CardDAV PUT etag-less result → 201, no ETag", r.status === 201 && r.headers["etag"] === undefined);
1259
+ } finally { await _close(sNoEtag); }
1260
+ }
1261
+
1262
+ // =====================================================================
1263
+ // 14. discovery redirects — caldav / carddav / custom base URLs
1264
+ // =====================================================================
1265
+ async function testDiscovery() {
1266
+ var s = await _mkServer({ storage: _storage() });
1267
+ try {
1268
+ var cal = await _req(s.port, { method: "GET", path: "/.well-known/caldav" });
1269
+ check("discovery caldav → 301 /caldav/", cal.status === 301 && cal.headers["location"] === "/caldav/");
1270
+ var card = await _req(s.port, { method: "GET", path: "/.well-known/carddav" });
1271
+ check("discovery carddav → 301 /carddav/", card.status === 301 && card.headers["location"] === "/carddav/");
1272
+ } finally { await _close(s); }
1273
+
1274
+ var sCustom = await _mkServer({ storage: _storage(), caldavBaseUrl: "/dav/cal/", carddavBaseUrl: "/dav/card/" });
1275
+ try {
1276
+ check("discovery caldav custom base → 301 /dav/cal/",
1277
+ (await _req(sCustom.port, { method: "GET", path: "/.well-known/caldav" })).headers["location"] === "/dav/cal/");
1278
+ check("discovery carddav custom base → 301 /dav/card/",
1279
+ (await _req(sCustom.port, { method: "GET", path: "/.well-known/carddav" })).headers["location"] === "/dav/card/");
1280
+ } finally { await _close(sCustom); }
1281
+ }
1282
+
1283
+ async function _drainTcpHandles() {
1284
+ if (typeof process.getActiveResourcesInfo !== "function") return;
1285
+ await helpers.waitUntil(function () {
1286
+ return process.getActiveResourcesInfo().filter(function (t) {
1287
+ return t === "TCPSocketWrap" || t === "TCPServerWrap";
1288
+ }).length === 0;
1289
+ }, { timeoutMs: 5000, label: "mail-dav: TCP handle drain after run" });
1290
+ }
1291
+
483
1292
  async function run() {
484
1293
  testSurface();
485
1294
  testRefusesNoStorage();
@@ -506,6 +1315,26 @@ async function run() {
506
1315
  await testCarddavReportMultiget();
507
1316
  testDiscoveryHandler();
508
1317
  await testHttpHandlerInvokesDispatch();
1318
+
1319
+ var wtt = helpers.withTestTimeout;
1320
+ try {
1321
+ testCreateOpts();
1322
+ await wtt("actor resolution", testActorResolution);
1323
+ await wtt("caldav dispatch", testCaldavDispatch);
1324
+ await wtt("caldav propfind", testCaldavPropfind);
1325
+ await wtt("caldav report", testCaldavReport);
1326
+ await wtt("caldav get", testCaldavGetHttp);
1327
+ await wtt("caldav put", testCaldavPut);
1328
+ await wtt("caldav delete", testCaldavDeleteHttp);
1329
+ await wtt("mkcalendar", testMkcalendarHttp);
1330
+ await wtt("read body", testReadBody);
1331
+ await wtt("buf to text", testBufToText);
1332
+ await wtt("carddav dispatch", testCarddavDispatch);
1333
+ await wtt("carddav writes", testCarddavWrites);
1334
+ await wtt("discovery", testDiscovery);
1335
+ } finally {
1336
+ await _drainTcpHandles();
1337
+ }
509
1338
  }
510
1339
 
511
1340
  module.exports = { run: run };