@fedify/fedify 2.2.0-dev.613 → 2.2.0-dev.622

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 (207) hide show
  1. package/dist/{accept-D7sAxyNa.js → accept-Dd__NiUL.mjs} +10 -8
  2. package/dist/{assert-MZs1qjMx.js → assert-ddO5KLpe.mjs} +5 -9
  3. package/dist/{assert_equals-DSbWqCm3.js → assert_equals-Ew3jOFa3.mjs} +55 -69
  4. package/dist/{assert_instance_of-DHz7EHNU.js → assert_instance_of-C4Ri6VuN.mjs} +5 -9
  5. package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals--wG9hV7u.mjs} +6 -13
  6. package/dist/{assert_rejects-0h7I2Esa.js → assert_rejects-B-qJtC9Z.mjs} +6 -11
  7. package/dist/{assert_throws-rjdMBf31.js → assert_throws-4NwKEy2q.mjs} +5 -10
  8. package/dist/{builder-OscY92PK.js → builder-DcSpny3g.mjs} +32 -41
  9. package/dist/{chunk-CGaQZ11T.cjs → chunk-DDcVe30Y.cjs} +23 -24
  10. package/dist/{chunk-DJNbSFdH.js → chunk-nlSIicah.js} +8 -8
  11. package/dist/{client-BxMZiQaD.d.ts → client-AtlibPOU.d.ts} +1 -1
  12. package/dist/{client-CoCIaTNO.js → client-DEpOVgY1.mjs} +9 -13
  13. package/dist/{client-C97KOq3x.d.cts → client-z-8dc-e1.d.cts} +1 -1
  14. package/dist/{collection-CSzG2j1P.js → collection-BD6-SZ6O.mjs} +7 -12
  15. package/dist/compat/mod.cjs +5 -8
  16. package/dist/compat/mod.d.cts +78 -6
  17. package/dist/compat/mod.d.ts +78 -6
  18. package/dist/compat/mod.js +4 -8
  19. package/dist/compat/transformers.test.mjs +62 -0
  20. package/dist/{context-DyJjQQ_H.d.ts → context-BOiMZBu5.d.ts} +9 -18
  21. package/dist/{context-BcqA-0BL.d.cts → context-BhZVy7RB.d.cts} +9 -18
  22. package/dist/{context-Aqenou7c.js → context-Juj6bdHC.mjs} +7 -11
  23. package/dist/deno-D682wzlW.mjs +8 -0
  24. package/dist/{docloader-JiZmL7BP.js → docloader-CCWf4tNV.mjs} +8 -14
  25. package/dist/{esm-nLm00z9V.js → esm-DVILvP5e.mjs} +50 -89
  26. package/dist/federation/builder.test.d.mts +2 -0
  27. package/dist/federation/{builder.test.js → builder.test.mjs} +21 -44
  28. package/dist/federation/collection.test.d.mts +2 -0
  29. package/dist/federation/collection.test.mjs +21 -0
  30. package/dist/federation/handler.test.d.mts +2 -0
  31. package/dist/federation/{handler.test.js → handler.test.mjs} +69 -131
  32. package/dist/federation/idempotency.test.d.mts +2 -0
  33. package/dist/federation/{idempotency.test.js → idempotency.test.mjs} +31 -63
  34. package/dist/federation/inbox.test.d.mts +2 -0
  35. package/dist/federation/{inbox.test.js → inbox.test.mjs} +8 -12
  36. package/dist/federation/keycache.test.d.mts +2 -0
  37. package/dist/federation/{keycache.test.js → keycache.test.mjs} +13 -19
  38. package/dist/federation/kv.test.d.mts +2 -0
  39. package/dist/federation/{kv.test.js → kv.test.mjs} +11 -22
  40. package/dist/federation/middleware.test.d.mts +2 -0
  41. package/dist/federation/{middleware.test.js → middleware.test.mjs} +173 -262
  42. package/dist/federation/mod.cjs +327 -16
  43. package/dist/federation/mod.d.cts +3 -6
  44. package/dist/federation/mod.d.ts +3 -6
  45. package/dist/federation/mod.js +322 -13
  46. package/dist/federation/mq.test.d.mts +2 -0
  47. package/dist/federation/{mq.test.js → mq.test.mjs} +21 -35
  48. package/dist/federation/negotiation.test.d.mts +2 -0
  49. package/dist/federation/{negotiation.test.js → negotiation.test.mjs} +9 -16
  50. package/dist/federation/retry.test.d.mts +2 -0
  51. package/dist/federation/{retry.test.js → retry.test.mjs} +8 -11
  52. package/dist/federation/router.test.d.mts +2 -0
  53. package/dist/federation/{router.test.js → router.test.mjs} +11 -16
  54. package/dist/federation/send.test.d.mts +2 -0
  55. package/dist/federation/{send.test.js → send.test.mjs} +22 -30
  56. package/dist/federation/webfinger.test.d.mts +2 -0
  57. package/dist/federation/{webfinger.test.js → webfinger.test.mjs} +22 -56
  58. package/dist/{http-BnsR906R.cjs → http-BQccxQlj.cjs} +177 -302
  59. package/dist/{http-CKaqhjvP.js → http-CNsnyqrO.mjs} +23 -43
  60. package/dist/{http-BudnHZE2.d.cts → http-CrGuipxe.d.cts} +1 -6
  61. package/dist/{http-IFqEftoZ.js → http-DhwEMhtv.js} +53 -184
  62. package/dist/{http-Dax_FIBo.d.ts → http-aQzN9Ayi.d.ts} +1 -6
  63. package/dist/{inbox-Bd91CVJP.js → inbox-DegXbbbS.mjs} +18 -26
  64. package/dist/{key-DFLFXKER.js → key-vL60OvqM.mjs} +29 -37
  65. package/dist/{keycache-CpGWAUbj.js → keycache-CCSwkQcY.mjs} +5 -10
  66. package/dist/{keys-BFve7QQv.js → keys-BAK-tUlf.mjs} +5 -9
  67. package/dist/{kv-BL4nlICN.d.cts → kv-CbLNp3zQ.d.cts} +1 -1
  68. package/dist/{kv-DXEUEP6z.d.ts → kv-GFYnFoOl.d.ts} +1 -1
  69. package/dist/{kv-cache-Bw2F2ABq.js → kv-cache-B01V7s3h.mjs} +4 -8
  70. package/dist/{kv-cache-Drlz6O_Y.js → kv-cache-CTj3iCix.js} +6 -13
  71. package/dist/{kv-cache-BLXcQvyb.cjs → kv-cache-DxdXJNbj.cjs} +27 -34
  72. package/dist/{kv-QzKcOQgP.js → kv-tL2TOE9X.mjs} +6 -10
  73. package/dist/{ld-CGGXZJK0.js → ld-C3CO00YY.mjs} +17 -31
  74. package/dist/{middleware-DcpBikad.js → middleware-BmsVSOeS.js} +335 -382
  75. package/dist/middleware-C7shNcsp.cjs +4 -0
  76. package/dist/{middleware-B51dB75z.cjs → middleware-Cx0Ny6_7.cjs} +532 -587
  77. package/dist/middleware-DqVGYk56.mjs +5 -0
  78. package/dist/{middleware-B53r4pdM.js → middleware-Du-vh7I_.mjs} +282 -317
  79. package/dist/{mod-em2Il1eD.d.cts → mod-Bp_CzKd4.d.cts} +2 -2
  80. package/dist/{mod-DCbh1JQ5.d.ts → mod-CLgIXe9w.d.ts} +3 -3
  81. package/dist/{mod-jfnweK2w.d.cts → mod-CMEbIaNh.d.cts} +3 -3
  82. package/dist/{mod-D6MdymW7.d.ts → mod-DKOAow7a.d.ts} +2 -2
  83. package/dist/{mod-Coe7KEgX.d.cts → mod-DoJBjjnO.d.cts} +2 -2
  84. package/dist/{mod-D6dOd--H.d.ts → mod-DvxszxXC.d.ts} +2 -2
  85. package/dist/mod.cjs +29 -74
  86. package/dist/mod.d.cts +11 -14
  87. package/dist/mod.d.ts +11 -15
  88. package/dist/mod.js +17 -71
  89. package/dist/{negotiation-BlAuS_nr.js → negotiation-DnsfFF8I.mjs} +7 -11
  90. package/dist/nodeinfo/client.test.d.mts +2 -0
  91. package/dist/nodeinfo/{client.test.js → client.test.mjs} +22 -40
  92. package/dist/nodeinfo/handler.test.d.mts +2 -0
  93. package/dist/nodeinfo/{handler.test.js → handler.test.mjs} +13 -43
  94. package/dist/nodeinfo/mod.cjs +5 -8
  95. package/dist/nodeinfo/mod.d.cts +2 -3
  96. package/dist/nodeinfo/mod.d.ts +2 -3
  97. package/dist/nodeinfo/mod.js +4 -8
  98. package/dist/nodeinfo/types.test.d.mts +2 -0
  99. package/dist/nodeinfo/{types.test.js → types.test.mjs} +9 -16
  100. package/dist/otel/exporter.test.d.mts +2 -0
  101. package/dist/otel/{exporter.test.js → exporter.test.mjs} +124 -178
  102. package/dist/otel/mod.cjs +15 -20
  103. package/dist/otel/mod.d.cts +2 -2
  104. package/dist/otel/mod.d.ts +2 -2
  105. package/dist/otel/mod.js +8 -14
  106. package/dist/{owner-gd0Q9FuU.d.ts → owner-74ARJ5TL.d.ts} +1 -1
  107. package/dist/{owner-1AbPBOOZ.d.cts → owner-CptqhsOy.d.cts} +1 -1
  108. package/dist/{owner-Cye0yQB_.js → owner-DF320w6K.mjs} +11 -16
  109. package/dist/{proof-DdGGXVWM.js → proof-BCWk5oas.js} +32 -58
  110. package/dist/{proof-DV5lC_Bw.js → proof-IyDwwmzL.mjs} +21 -33
  111. package/dist/{proof-CN5iR1tW.cjs → proof-WhNxSv_N.cjs} +133 -157
  112. package/dist/{retry-mqLf4b-R.js → retry-B_E3V_Dx.mjs} +4 -7
  113. package/dist/{router-D9eI0s4b.js → router-CrMLXoOr.mjs} +4 -8
  114. package/dist/runtime/mod.cjs +11 -13
  115. package/dist/runtime/mod.d.cts +6 -2
  116. package/dist/runtime/mod.d.ts +0 -1
  117. package/dist/runtime/mod.js +4 -7
  118. package/dist/{send-C2a_3YAF.js → send-CJQubr5t.mjs} +8 -13
  119. package/dist/sig/accept.test.d.mts +2 -0
  120. package/dist/sig/{accept.test.js → accept.test.mjs} +35 -70
  121. package/dist/sig/http.test.d.mts +2 -0
  122. package/dist/sig/{http.test.js → http.test.mjs} +166 -280
  123. package/dist/sig/key.test.d.mts +2 -0
  124. package/dist/sig/{key.test.js → key.test.mjs} +11 -18
  125. package/dist/sig/ld.test.d.mts +2 -0
  126. package/dist/sig/{ld.test.js → ld.test.mjs} +22 -35
  127. package/dist/sig/mod.cjs +6 -9
  128. package/dist/sig/mod.d.cts +3 -3
  129. package/dist/sig/mod.d.ts +3 -3
  130. package/dist/sig/mod.js +5 -9
  131. package/dist/sig/owner.test.d.mts +2 -0
  132. package/dist/sig/{owner.test.js → owner.test.mjs} +19 -34
  133. package/dist/sig/proof.test.d.mts +2 -0
  134. package/dist/sig/{proof.test.js → proof.test.mjs} +16 -27
  135. package/dist/{std__assert-X-_kMxKM.js → std__assert-Duiq_YC9.mjs} +12 -24
  136. package/dist/testing/{mod.d.ts → mod.d.mts} +26 -90
  137. package/dist/testing/mod.mjs +6 -0
  138. package/dist/{transformers-3g8GZwkZ.cjs → transformers-NeAONrAq.cjs} +20 -25
  139. package/dist/{transformers-C3FLHUd6.js → transformers-ve6e2xcg.js} +3 -7
  140. package/dist/{types-CPz01LGH.js → types-DCP0WLdt.mjs} +4 -7
  141. package/dist/{types-Cd_hszr_.cjs → types-KC4QAoxe.cjs} +29 -34
  142. package/dist/{types-C93Ob9cU.js → types-hvL8ElAs.js} +8 -13
  143. package/dist/utils/docloader.test.d.mts +2 -0
  144. package/dist/utils/{docloader.test.js → docloader.test.mjs} +14 -25
  145. package/dist/utils/kv-cache.test.d.mts +2 -0
  146. package/dist/utils/{kv-cache.test.js → kv-cache.test.mjs} +25 -40
  147. package/dist/utils/mod.cjs +5 -9
  148. package/dist/utils/mod.d.cts +1 -3
  149. package/dist/utils/mod.d.ts +1 -3
  150. package/dist/utils/mod.js +4 -9
  151. package/dist/vocab/cjs.test.d.mts +2 -0
  152. package/dist/vocab/cjs.test.mjs +14 -0
  153. package/dist/vocab/mod.cjs +10 -12
  154. package/dist/vocab/mod.js +3 -5
  155. package/package.json +8 -8
  156. package/dist/compat/transformers.test.d.ts +0 -3
  157. package/dist/compat/transformers.test.js +0 -88
  158. package/dist/compat-Bb4NuTUO.js +0 -4
  159. package/dist/compat-DmDDELst.cjs +0 -4
  160. package/dist/deno-CnMqla6T.js +0 -121
  161. package/dist/federation/builder.test.d.ts +0 -3
  162. package/dist/federation/collection.test.d.ts +0 -3
  163. package/dist/federation/collection.test.js +0 -32
  164. package/dist/federation/handler.test.d.ts +0 -3
  165. package/dist/federation/idempotency.test.d.ts +0 -3
  166. package/dist/federation/inbox.test.d.ts +0 -3
  167. package/dist/federation/keycache.test.d.ts +0 -3
  168. package/dist/federation/kv.test.d.ts +0 -3
  169. package/dist/federation/middleware.test.d.ts +0 -3
  170. package/dist/federation/mq.test.d.ts +0 -3
  171. package/dist/federation/negotiation.test.d.ts +0 -3
  172. package/dist/federation/retry.test.d.ts +0 -3
  173. package/dist/federation/router.test.d.ts +0 -3
  174. package/dist/federation/send.test.d.ts +0 -3
  175. package/dist/federation/webfinger.test.d.ts +0 -3
  176. package/dist/federation-Bp3HI26G.cjs +0 -350
  177. package/dist/federation-DaMfqRm4.js +0 -332
  178. package/dist/middleware-B0kNQMO0.js +0 -27
  179. package/dist/middleware-BYQL9cdV.js +0 -12
  180. package/dist/middleware-DfNqksSs.cjs +0 -12
  181. package/dist/mod-B7QkWzrL.d.cts +0 -80
  182. package/dist/mod-Bh8mqlYw.d.cts +0 -9
  183. package/dist/mod-D6HodEq7.d.ts +0 -7
  184. package/dist/mod-SMHOMNpZ.d.ts +0 -82
  185. package/dist/mod-gq_Xfdz8.d.cts +0 -1
  186. package/dist/nodeinfo/client.test.d.ts +0 -3
  187. package/dist/nodeinfo/handler.test.d.ts +0 -3
  188. package/dist/nodeinfo/types.test.d.ts +0 -3
  189. package/dist/nodeinfo-DoESQxq5.js +0 -4
  190. package/dist/nodeinfo-DuMYTpbZ.cjs +0 -4
  191. package/dist/otel/exporter.test.d.ts +0 -3
  192. package/dist/runtime-c2Njxsry.cjs +0 -17
  193. package/dist/runtime-poamPCMb.js +0 -13
  194. package/dist/sig/accept.test.d.ts +0 -3
  195. package/dist/sig/http.test.d.ts +0 -3
  196. package/dist/sig/key.test.d.ts +0 -3
  197. package/dist/sig/ld.test.d.ts +0 -3
  198. package/dist/sig/owner.test.d.ts +0 -3
  199. package/dist/sig/proof.test.d.ts +0 -3
  200. package/dist/sig-BNhspNOf.js +0 -4
  201. package/dist/sig-vX39WyWI.cjs +0 -4
  202. package/dist/testing/mod.js +0 -10
  203. package/dist/utils/docloader.test.d.ts +0 -3
  204. package/dist/utils/kv-cache.test.d.ts +0 -3
  205. package/dist/utils-BQ9KqEK9.cjs +0 -4
  206. package/dist/utils-Dn5OPdSW.js +0 -4
  207. /package/dist/{mod-AGjRfPjT.d.ts → compat/transformers.test.d.mts} +0 -0
@@ -1,37 +1,28 @@
1
-
2
- import { Temporal } from "@js-temporal/polyfill";
3
- import { URLPattern } from "urlpattern-polyfill";
4
- globalThis.addEventListener = () => {};
5
-
6
- import { esm_default } from "../esm-nLm00z9V.js";
7
- import { assertEquals } from "../assert_equals-DSbWqCm3.js";
8
- import { assert } from "../assert-MZs1qjMx.js";
9
- import "../assert_instance_of-DHz7EHNU.js";
10
- import "../deno-CnMqla6T.js";
11
- import "../accept-D7sAxyNa.js";
12
- import { exportJwk } from "../key-DFLFXKER.js";
13
- import { createRfc9421SignatureBase, doubleKnock, formatRfc9421Signature, formatRfc9421SignatureParameters, parseRfc9421Signature, parseRfc9421SignatureInput, signRequest, timingSafeEqual, verifyRequest, verifyRequestDetailed } from "../http-CKaqhjvP.js";
14
- import { assertExists, assertStringIncludes } from "../std__assert-X-_kMxKM.js";
15
- import { assertFalse, assertRejects } from "../assert_rejects-0h7I2Esa.js";
16
- import { assertThrows } from "../assert_throws-rjdMBf31.js";
17
- import "../assert_not_equals-f3m3epl3.js";
18
- import { rsaPrivateKey2, rsaPublicKey1, rsaPublicKey2, rsaPublicKey5 } from "../keys-BFve7QQv.js";
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ import "urlpattern-polyfill";
3
+ globalThis.addEventListener = () => {};
4
+ import { t as esm_default } from "../esm-DVILvP5e.mjs";
5
+ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
+ import { a as assertExists, t as assertStringIncludes } from "../std__assert-Duiq_YC9.mjs";
7
+ import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
+ import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
9
+ import { t as assert } from "../assert-ddO5KLpe.mjs";
10
+ import { t as exportJwk } from "../key-vL60OvqM.mjs";
11
+ import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-CNsnyqrO.mjs";
12
+ import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
19
13
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
20
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
21
15
  import { encodeBase64 } from "byte-encodings/base64";
22
-
23
16
  //#region src/sig/http.test.ts
24
17
  test("signRequest() [draft-cavage]", async () => {
25
- const request = new Request("https://example.com/", {
18
+ assertEquals(await verifyRequest(await signRequest(new Request("https://example.com/", {
26
19
  method: "POST",
27
20
  body: "Hello, world!",
28
21
  headers: {
29
22
  "Content-Type": "text/plain; charset=utf-8",
30
23
  Accept: "text/plain"
31
24
  }
32
- });
33
- const signed = await signRequest(request, rsaPrivateKey2, new URL("https://example.com/key2"));
34
- assertEquals(await verifyRequest(signed, {
25
+ }), rsaPrivateKey2, new URL("https://example.com/key2")), {
35
26
  contextLoader: mockDocumentLoader,
36
27
  documentLoader: mockDocumentLoader
37
28
  }), rsaPublicKey2);
@@ -57,8 +48,8 @@ test("verifyRequest() [draft-cavage]", async () => {
57
48
  get(keyId) {
58
49
  return Promise.resolve(cache[keyId.href]);
59
50
  },
60
- set(keyId, key$1) {
61
- cache[keyId.href] = key$1;
51
+ set(keyId, key) {
52
+ cache[keyId.href] = key;
62
53
  return Promise.resolve();
63
54
  }
64
55
  }
@@ -146,7 +137,7 @@ test("verifyRequest() [draft-cavage]", async () => {
146
137
  currentTime: Temporal.Instant.from("2025-01-01T00:00:00.0000Z"),
147
138
  timeWindow: false
148
139
  }), rsaPublicKey1);
149
- const request2 = new Request("https://c27a97f98d5f.ngrok.app/i/inbox", {
140
+ assert(await verifyRequest(new Request("https://c27a97f98d5f.ngrok.app/i/inbox", {
150
141
  method: "POST",
151
142
  body: "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://w3id.org/security/v1\"],\"actor\":\"https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd\",\"object\":{\"actor\":\"https://c27a97f98d5f.ngrok.app/i\",\"object\":\"https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd\",\"type\":\"Follow\",\"id\":\"https://c27a97f98d5f.ngrok.app/i#follows/https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd\"},\"type\":\"Accept\",\"id\":\"https://oeee.cafe/objects/0fc2608f-5660-4b91-b8c7-63c0c2ac2e20\"}",
152
143
  headers: {
@@ -156,12 +147,10 @@ test("verifyRequest() [draft-cavage]", async () => {
156
147
  Digest: "SHA-256=YZyjeVQW5GwliJowASkteBJhFBTq3eQk/AMqRETc//A=",
157
148
  Signature: "keyId=\"https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd#main-key\",algorithm=\"hs2019\",created=\"1756126694\",expires=\"1756130294\",headers=\"(request-target) (created) (expires) content-type date digest host\",signature=\"XFb0jl2uMhE7RhbneE9sK9Zls2qZec8iy6+9O8UgDQeBGJThORFLjXKlps4QO1WAf1YSVB/i5aV6yF+h73Lm3ZiuAJDx1h+00iLsxoYuIw1CZvF0V2jELoo3sQ2/ZzqeoO6H5TbK7tKnU+ulFAPTuJgjIvPwYl11OMRouVS34NiaHP9Yx9pU813TLv37thG/hUKanyq8kk0IJWtDWteY/zxDvzoe7VOkBXVBHslMyrNAI/5JGulVQAQp/E61dJAhTHHIyGxkc/7iutWFZuqFXIiPJ9KR2OuKDj/B32hEzlsf5xH/CjqOJPIg1qMK8FzDiALCq6zjiKIBEnW8HQc/hQ==\""
158
149
  }
159
- });
160
- const options2 = {
150
+ }), {
161
151
  ...options,
162
152
  currentTime: Temporal.Instant.from("2025-08-25T12:58:14Z")
163
- };
164
- assert(await verifyRequest(request2, options2) != null);
153
+ }) != null);
165
154
  });
166
155
  test("verifyRequestDetailed() classifies malformed signatures as invalid", async () => {
167
156
  const draftMissingKeyId = await verifyRequestDetailed(new Request("https://example.com/", {
@@ -214,7 +203,7 @@ test("verifyRequestDetailed() classifies malformed signatures as invalid", async
214
203
  test("verifyRequestDetailed() records failure details on span", async () => {
215
204
  const [tracerProvider, exporter] = createTestTracerProvider();
216
205
  const keyId = new URL("https://gone.example/actors/alice#main-key");
217
- const request = await signRequest(new Request("https://example.com/inbox", {
206
+ assertFalse((await verifyRequestDetailed(await signRequest(new Request("https://example.com/inbox", {
218
207
  method: "POST",
219
208
  headers: {
220
209
  "Content-Type": "application/activity+json",
@@ -225,16 +214,14 @@ test("verifyRequestDetailed() records failure details on span", async () => {
225
214
  type: "Create",
226
215
  actor: "https://gone.example/actors/alice"
227
216
  })
228
- }), rsaPrivateKey2, keyId);
229
- const result = await verifyRequestDetailed(request, {
217
+ }), rsaPrivateKey2, keyId), {
230
218
  tracerProvider,
231
219
  contextLoader: mockDocumentLoader,
232
220
  documentLoader(url) {
233
221
  if (url === keyId.href) throw new FetchError(keyId, `HTTP 410: ${keyId.href}`, new Response(null, { status: 410 }));
234
222
  return mockDocumentLoader(url);
235
223
  }
236
- });
237
- assertFalse(result.verified);
224
+ })).verified);
238
225
  const spans = exporter.getSpans("http_signatures.verify");
239
226
  assertEquals(spans.length, 1);
240
227
  const span = spans[0];
@@ -282,9 +269,7 @@ test("signRequest() and verifyRequest() [rfc9421] implementation", async () => {
282
269
  const contentDigest = signed.headers.get("Content-Digest");
283
270
  assertExists(contentDigest);
284
271
  assert(contentDigest.startsWith("sha-256=:"), "Content-Digest should use RFC 9421 format");
285
- const expectedDigest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(requestBody));
286
- const expectedDigestBase64 = encodeBase64(expectedDigest);
287
- assertEquals(contentDigest, `sha-256=:${expectedDigestBase64}:`, "Content-Digest should have correct value");
272
+ assertEquals(contentDigest, `sha-256=:${encodeBase64(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(requestBody)))}:`, "Content-Digest should have correct value");
288
273
  const signature = signed.headers.get("Signature");
289
274
  assertExists(signature);
290
275
  const sigFormat = /^sig1=:([A-Za-z0-9+/]+=*):/;
@@ -305,25 +290,22 @@ test("signRequest() and verifyRequest() [rfc9421] implementation", async () => {
305
290
  assertEquals(parsedSig.sig1.byteLength > 0, true, "Signature value should be a non-empty Uint8Array");
306
291
  const verifyHeaders = new Headers();
307
292
  for (const [name, value] of signed.headers.entries()) if (name !== "Signature" && name !== "Signature-Input") verifyHeaders.set(name, value);
308
- const reconstructedRequest = new Request(request.url, {
293
+ const reconstructedBase = createRfc9421SignatureBase(new Request(request.url, {
309
294
  method: request.method,
310
295
  headers: verifyHeaders
311
- });
312
- const reconstructedBase = createRfc9421SignatureBase(reconstructedRequest, parsedInput.sig1.components, parsedInput.sig1.parameters);
296
+ }), parsedInput.sig1.components, parsedInput.sig1.parameters);
313
297
  const signatureBytes = new Uint8Array(parsedSig.sig1);
314
- const signatureVerifies = await crypto.subtle.verify("RSASSA-PKCS1-v1_5", rsaPublicKey2.publicKey, signatureBytes, new TextEncoder().encode(reconstructedBase));
315
- assert(signatureVerifies, "Manual verification of signature should succeed");
298
+ assert(await crypto.subtle.verify("RSASSA-PKCS1-v1_5", rsaPublicKey2.publicKey, signatureBytes, new TextEncoder().encode(reconstructedBase)), "Manual verification of signature should succeed");
316
299
  });
317
300
  test("createRfc9421SignatureBase()", () => {
318
- const request = new Request("https://example.com/path?query=value", {
301
+ assertEquals(createRfc9421SignatureBase(new Request("https://example.com/path?query=value", {
319
302
  method: "POST",
320
303
  headers: {
321
304
  Host: "example.com",
322
305
  Date: "Tue, 05 Mar 2024 07:49:44 GMT",
323
306
  "Content-Type": "text/plain"
324
307
  }
325
- });
326
- const components = [
308
+ }), [
327
309
  {
328
310
  value: "@method",
329
311
  params: {}
@@ -340,21 +322,17 @@ test("createRfc9421SignatureBase()", () => {
340
322
  value: "date",
341
323
  params: {}
342
324
  }
343
- ];
344
- const created = 1709626184;
345
- const signatureBase = createRfc9421SignatureBase(request, components, formatRfc9421SignatureParameters({
325
+ ], formatRfc9421SignatureParameters({
346
326
  algorithm: "rsa-v1_5-sha256",
347
327
  keyId: new URL("https://example.com/key"),
348
- created
349
- }));
350
- const expected = [
328
+ created: 1709626184
329
+ })), [
351
330
  `"@method": POST`,
352
331
  `"@target-uri": https://example.com/path?query=value`,
353
332
  `"host": example.com`,
354
333
  `"date": Tue, 05 Mar 2024 07:49:44 GMT`,
355
334
  `"@signature-params": ("@method" "@target-uri" "host" "date");alg="rsa-v1_5-sha256";keyid="https://example.com/key";created=1709626184`
356
- ].join("\n");
357
- assertEquals(signatureBase, expected);
335
+ ].join("\n"));
358
336
  });
359
337
  test("formatRfc9421Signature()", () => {
360
338
  const signature = new Uint8Array([
@@ -365,7 +343,7 @@ test("formatRfc9421Signature()", () => {
365
343
  ]);
366
344
  const keyId = new URL("https://example.com/key");
367
345
  const algorithm = "rsa-v1_5-sha256";
368
- const components = [
346
+ const [signatureInput, signatureHeader] = formatRfc9421Signature(signature, [
369
347
  {
370
348
  "value": "@method",
371
349
  params: {}
@@ -378,19 +356,16 @@ test("formatRfc9421Signature()", () => {
378
356
  "value": "host",
379
357
  params: {}
380
358
  }
381
- ];
382
- const created = 1709626184;
383
- const [signatureInput, signatureHeader] = formatRfc9421Signature(signature, components, formatRfc9421SignatureParameters({
359
+ ], formatRfc9421SignatureParameters({
384
360
  algorithm,
385
361
  keyId,
386
- created
362
+ created: 1709626184
387
363
  }));
388
364
  assertEquals(signatureInput, `sig1=("@method" "@target-uri" "host");alg="rsa-v1_5-sha256";keyid="https://example.com/key";created=1709626184`);
389
365
  assertEquals(signatureHeader, `sig1=:AQIDBA==:`);
390
366
  });
391
367
  test("parseRfc9421SignatureInput()", () => {
392
- const signatureInput = `sig1=("@method" "@target-uri" "host" "date");keyid="https://example.com/key";alg="rsa-v1_5-sha256";created=1709626184`;
393
- const parsed = parseRfc9421SignatureInput(signatureInput);
368
+ const parsed = parseRfc9421SignatureInput(`sig1=("@method" "@target-uri" "host" "date");keyid="https://example.com/key";alg="rsa-v1_5-sha256";created=1709626184`);
394
369
  assertEquals(parsed.sig1.keyId, "https://example.com/key");
395
370
  assertEquals(parsed.sig1.alg, "rsa-v1_5-sha256");
396
371
  assertEquals(parsed.sig1.created, 1709626184);
@@ -415,8 +390,7 @@ test("parseRfc9421SignatureInput()", () => {
415
390
  assertEquals(parsed.sig1.parameters, "keyid=\"https://example.com/key\";alg=\"rsa-v1_5-sha256\";created=1709626184");
416
391
  });
417
392
  test("parseRfc9421Signature()", () => {
418
- const signature = `sig1=:AQIDBA==:,sig2=:Zm9vYmFy:`;
419
- const parsed = parseRfc9421Signature(signature);
393
+ const parsed = parseRfc9421Signature(`sig1=:AQIDBA==:,sig2=:Zm9vYmFy:`);
420
394
  assertExists(parsed.sig1);
421
395
  assertExists(parsed.sig2);
422
396
  const sig1Bytes = new Uint8Array(parsed.sig1);
@@ -425,37 +399,33 @@ test("parseRfc9421Signature()", () => {
425
399
  assertEquals(sig1Bytes[1], 2);
426
400
  assertEquals(sig1Bytes[2], 3);
427
401
  assertEquals(sig1Bytes[3], 4);
428
- const sig2Text = new TextDecoder().decode(parsed.sig2);
429
- assertEquals(sig2Text, "foobar");
402
+ assertEquals(new TextDecoder().decode(parsed.sig2), "foobar");
430
403
  });
431
404
  test("verifyRequest() [rfc9421] successful GET verification", async () => {
432
405
  const currentTimestamp = 1709626184;
433
406
  const currentTime = Temporal.Instant.from("2024-03-05T08:09:44Z");
434
- const validRequest = new Request("https://example.com/api/resource", {
407
+ assertEquals(await verifyRequest(await signRequest(new Request("https://example.com/api/resource", {
435
408
  method: "GET",
436
409
  headers: {
437
410
  "Accept": "application/json",
438
411
  "Host": "example.com",
439
412
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT"
440
413
  }
441
- });
442
- const signedRequest = await signRequest(validRequest, rsaPrivateKey2, new URL("https://example.com/key2"), {
414
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
443
415
  spec: "rfc9421",
444
416
  currentTime
445
- });
446
- const verifiedKey = await verifyRequest(signedRequest, {
417
+ }), {
447
418
  contextLoader: mockDocumentLoader,
448
419
  documentLoader: mockDocumentLoader,
449
420
  spec: "rfc9421",
450
421
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date(currentTimestamp * 1e3)).toISOString()}`)
451
- });
452
- assertEquals(verifiedKey, rsaPublicKey2, "Valid signature should verify to the correct public key");
422
+ }), rsaPublicKey2, "Valid signature should verify to the correct public key");
453
423
  });
454
424
  test("verifyRequest() [rfc9421] manual POST verification", async () => {
455
425
  const currentTimestamp = 1709626184;
456
426
  const currentTime = Temporal.Instant.from("2024-03-05T08:09:44Z");
457
427
  const postBody = "Test content for signature verification";
458
- const postRequest = new Request("https://example.com/api/resource", {
428
+ const signedPostRequest = await signRequest(new Request("https://example.com/api/resource", {
459
429
  method: "POST",
460
430
  body: postBody,
461
431
  headers: {
@@ -464,8 +434,7 @@ test("verifyRequest() [rfc9421] manual POST verification", async () => {
464
434
  "Host": "example.com",
465
435
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT"
466
436
  }
467
- });
468
- const signedPostRequest = await signRequest(postRequest, rsaPrivateKey2, new URL("https://example.com/key2"), {
437
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
469
438
  spec: "rfc9421",
470
439
  currentTime
471
440
  });
@@ -487,61 +456,54 @@ test("verifyRequest() [rfc9421] manual POST verification", async () => {
487
456
  assertExists(parsedSignature.sig1, "Should have a valid signature value");
488
457
  assertEquals(parsedInput.sig1.keyId, "https://example.com/key2", "Signature should have the correct key ID");
489
458
  assertEquals(parsedInput.sig1.created, currentTimestamp, "Signature should have the correct timestamp");
490
- const manualRequest = new Request("https://example.com/api/resource", {
459
+ const signatureBase = createRfc9421SignatureBase(new Request("https://example.com/api/resource", {
491
460
  method: "POST",
492
461
  body: postBody,
493
462
  headers: new Headers(signedPostRequest.headers)
494
- });
495
- const signatureBase = createRfc9421SignatureBase(manualRequest, parsedInput.sig1.components, parsedInput.sig1.parameters);
496
- const signatureVerified = await crypto.subtle.verify("RSASSA-PKCS1-v1_5", rsaPublicKey2.publicKey, parsedSignature.sig1.slice(), new TextEncoder().encode(signatureBase));
497
- assert(signatureVerified, "Manual verification of POST signature should succeed");
463
+ }), parsedInput.sig1.components, parsedInput.sig1.parameters);
464
+ assert(await crypto.subtle.verify("RSASSA-PKCS1-v1_5", rsaPublicKey2.publicKey, parsedSignature.sig1.slice(), new TextEncoder().encode(signatureBase)), "Manual verification of POST signature should succeed");
498
465
  });
499
466
  test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
500
467
  const currentTimestamp = 1709626184;
501
468
  const currentTime = Temporal.Instant.from("2024-03-05T08:09:44Z");
502
- const validRequest = new Request("https://example.com/api/resource", {
469
+ const signedRequest = await signRequest(new Request("https://example.com/api/resource", {
503
470
  method: "GET",
504
471
  headers: {
505
472
  "Accept": "application/json",
506
473
  "Host": "example.com",
507
474
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT"
508
475
  }
509
- });
510
- const signedRequest = await signRequest(validRequest, rsaPrivateKey2, new URL("https://example.com/key2"), {
476
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
511
477
  spec: "rfc9421",
512
478
  currentTime
513
479
  });
514
480
  const validSignatureInput = signedRequest.headers.get("Signature-Input") || "";
515
481
  const validSignature = signedRequest.headers.get("Signature") || "";
516
- const missingInputHeader = new Request("https://example.com/api/resource", {
482
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
517
483
  method: "GET",
518
484
  headers: new Headers({
519
485
  "Accept": "application/json",
520
486
  "Host": "example.com",
521
487
  "Signature": validSignature
522
488
  })
523
- });
524
- const missingInputResult = await verifyRequest(missingInputHeader, {
489
+ }), {
525
490
  contextLoader: mockDocumentLoader,
526
491
  documentLoader: mockDocumentLoader,
527
492
  spec: "rfc9421"
528
- });
529
- assertEquals(missingInputResult, null, "Should fail verification when Signature-Input header is missing");
530
- const missingSignatureHeader = new Request("https://example.com/api/resource", {
493
+ }), null, "Should fail verification when Signature-Input header is missing");
494
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
531
495
  method: "GET",
532
496
  headers: new Headers({
533
497
  "Accept": "application/json",
534
498
  "Host": "example.com",
535
499
  "Signature-Input": validSignatureInput
536
500
  })
537
- });
538
- const missingSignatureResult = await verifyRequest(missingSignatureHeader, {
501
+ }), {
539
502
  contextLoader: mockDocumentLoader,
540
503
  documentLoader: mockDocumentLoader,
541
504
  spec: "rfc9421"
542
- });
543
- assertEquals(missingSignatureResult, null, "Should fail verification when Signature header is missing");
544
- const tamperedRequest = new Request("https://example.com/api/resource", {
505
+ }), null, "Should fail verification when Signature header is missing");
506
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
545
507
  method: "GET",
546
508
  headers: new Headers({
547
509
  "Accept": "application/json",
@@ -550,14 +512,12 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
550
512
  "Signature-Input": validSignatureInput,
551
513
  "Signature": "sig1=:AAAAAA==:"
552
514
  })
553
- });
554
- const tamperedResult = await verifyRequest(tamperedRequest, {
515
+ }), {
555
516
  contextLoader: mockDocumentLoader,
556
517
  documentLoader: mockDocumentLoader,
557
518
  spec: "rfc9421"
558
- });
559
- assertEquals(tamperedResult, null, "Should fail verification when signature is tampered");
560
- const expiredRequest = new Request("https://example.com/api/resource", {
519
+ }), null, "Should fail verification when signature is tampered");
520
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
561
521
  method: "GET",
562
522
  headers: new Headers({
563
523
  "Accept": "application/json",
@@ -566,16 +526,14 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
566
526
  "Signature-Input": validSignatureInput,
567
527
  "Signature": validSignature
568
528
  })
569
- });
570
- const expiredResult = await verifyRequest(expiredRequest, {
529
+ }), {
571
530
  contextLoader: mockDocumentLoader,
572
531
  documentLoader: mockDocumentLoader,
573
532
  spec: "rfc9421",
574
533
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date((currentTimestamp + 2592e3) * 1e3)).toISOString()}`),
575
534
  timeWindow: { hours: 1 }
576
- });
577
- assertEquals(expiredResult, null, "Should fail verification when signature timestamp is too old");
578
- const futureRequest = new Request("https://example.com/api/resource", {
535
+ }), null, "Should fail verification when signature timestamp is too old");
536
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
579
537
  method: "GET",
580
538
  headers: new Headers({
581
539
  "Accept": "application/json",
@@ -584,16 +542,14 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
584
542
  "Signature-Input": validSignatureInput,
585
543
  "Signature": validSignature
586
544
  })
587
- });
588
- const futureResult = await verifyRequest(futureRequest, {
545
+ }), {
589
546
  contextLoader: mockDocumentLoader,
590
547
  documentLoader: mockDocumentLoader,
591
548
  spec: "rfc9421",
592
549
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date((currentTimestamp - 2592e3) * 1e3)).toISOString()}`),
593
550
  timeWindow: { hours: 1 }
594
- });
595
- assertEquals(futureResult, null, "Should fail verification when signature timestamp is in the future");
596
- const timeCheckRequest = new Request("https://example.com/api/resource", {
551
+ }), null, "Should fail verification when signature timestamp is in the future");
552
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
597
553
  method: "GET",
598
554
  headers: new Headers({
599
555
  "Accept": "application/json",
@@ -602,16 +558,14 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
602
558
  "Signature-Input": validSignatureInput,
603
559
  "Signature": validSignature
604
560
  })
605
- });
606
- const timeDisabledResult = await verifyRequest(timeCheckRequest, {
561
+ }), {
607
562
  contextLoader: mockDocumentLoader,
608
563
  documentLoader: mockDocumentLoader,
609
564
  spec: "rfc9421",
610
565
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date((currentTimestamp + 31536e3) * 1e3)).toISOString()}`),
611
566
  timeWindow: false
612
- });
613
- assertEquals(timeDisabledResult, rsaPublicKey2, "Should verify signature when time checking is disabled");
614
- const postRequest = new Request("https://example.com/api/resource", {
567
+ }), rsaPublicKey2, "Should verify signature when time checking is disabled");
568
+ const freshSignedPostRequest = await signRequest(new Request("https://example.com/api/resource", {
615
569
  method: "POST",
616
570
  body: "Test content for signature verification",
617
571
  headers: {
@@ -620,15 +574,14 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
620
574
  "Host": "example.com",
621
575
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT"
622
576
  }
623
- });
624
- const freshSignedPostRequest = await signRequest(postRequest, rsaPrivateKey2, new URL("https://example.com/key2"), {
577
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
625
578
  spec: "rfc9421",
626
579
  currentTime
627
580
  });
628
581
  const postSignatureInput = freshSignedPostRequest.headers.get("Signature-Input") || "";
629
582
  const postSignature = freshSignedPostRequest.headers.get("Signature") || "";
630
583
  const postContentDigest = freshSignedPostRequest.headers.get("Content-Digest") || "";
631
- const tamperDigestRequest = new Request("https://example.com/api/resource", {
584
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
632
585
  method: "POST",
633
586
  body: "This content won't match the digest",
634
587
  headers: new Headers({
@@ -639,22 +592,19 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
639
592
  "Signature": postSignature,
640
593
  "Content-Digest": postContentDigest
641
594
  })
642
- });
643
- const tamperDigestResult = await verifyRequest(tamperDigestRequest, {
595
+ }), {
644
596
  contextLoader: mockDocumentLoader,
645
597
  documentLoader: mockDocumentLoader,
646
598
  spec: "rfc9421",
647
599
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date(currentTimestamp * 1e3)).toISOString()}`)
648
- });
649
- assertEquals(tamperDigestResult, null, "Should fail verification with invalid Content-Digest");
600
+ }), null, "Should fail verification with invalid Content-Digest");
650
601
  const testRequest = new Request("https://example.com/", { headers: new Headers({
651
602
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT",
652
603
  "Host": "example.com",
653
604
  "Signature-Input": `sig1=("@method" "@target-uri" "host" "date");keyid="https://example.com/key";alg="rsa-v1_5-sha256";created=1709626184`,
654
605
  "Signature": `sig1=:YXNkZmprc2RmaGprc2RoZmprc2hkZmtqaHNkZg==:`
655
606
  }) });
656
- const signatureInput = testRequest.headers.get("Signature-Input") || "";
657
- const parsedInput = parseRfc9421SignatureInput(signatureInput);
607
+ const parsedInput = parseRfc9421SignatureInput(testRequest.headers.get("Signature-Input") || "");
658
608
  assertExists(parsedInput.sig1);
659
609
  assertEquals(parsedInput.sig1.keyId, "https://example.com/key");
660
610
  assertEquals(parsedInput.sig1.alg, "rsa-v1_5-sha256");
@@ -677,12 +627,10 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
677
627
  params: {}
678
628
  }
679
629
  ]);
680
- const signature = testRequest.headers.get("Signature") || "";
681
- const parsedSig = parseRfc9421Signature(signature);
630
+ const parsedSig = parseRfc9421Signature(testRequest.headers.get("Signature") || "");
682
631
  assertExists(parsedSig.sig1);
683
632
  assert(new TextDecoder().decode(parsedSig.sig1).length > 0, "Signature base64 should decode to non-empty string");
684
- const complexSignatureInput = "sig1=(\"@method\" \"@target-uri\" \"host\" \"content-type\" \"value with \\\"quotes\\\" and spaces\");keyid=\"https://example.com/key with spaces\";alg=\"rsa-v1_5-sha256\";created=1709626184";
685
- const complexParsedInput = parseRfc9421SignatureInput(complexSignatureInput);
633
+ const complexParsedInput = parseRfc9421SignatureInput("sig1=(\"@method\" \"@target-uri\" \"host\" \"content-type\" \"value with \\\"quotes\\\" and spaces\");keyid=\"https://example.com/key with spaces\";alg=\"rsa-v1_5-sha256\";created=1709626184");
686
634
  assertExists(complexParsedInput.sig1);
687
635
  assertEquals(complexParsedInput.sig1.keyId, "https://example.com/key with spaces");
688
636
  assertEquals(complexParsedInput.sig1.alg, "rsa-v1_5-sha256");
@@ -701,16 +649,13 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
701
649
  assertEquals(multiParsedInput.sig2.alg, "rsa-pss-sha512");
702
650
  const multiParsedSig = parseRfc9421Signature(multiSigRequest.headers.get("Signature") || "");
703
651
  assertEquals(Object.keys(multiParsedSig).length, 2, "Should parse multiple signature values");
704
- const invalidInputFormat = "this is not a valid signature-input format";
705
- const parsedInvalidInput = parseRfc9421SignatureInput(invalidInputFormat);
652
+ const parsedInvalidInput = parseRfc9421SignatureInput("this is not a valid signature-input format");
706
653
  assertEquals(Object.keys(parsedInvalidInput).length, 0, "Should handle invalid Signature-Input format");
707
- const invalidSigFormat = "this is not a valid signature format";
708
- const parsedInvalidSig = parseRfc9421Signature(invalidSigFormat);
654
+ const parsedInvalidSig = parseRfc9421Signature("this is not a valid signature format");
709
655
  assertEquals(Object.keys(parsedInvalidSig).length, 0, "Should handle invalid Signature format");
710
- const invalidBase64Sig = "sig1=:!@#$%%^&*():";
711
- const parsedInvalidBase64 = parseRfc9421Signature(invalidBase64Sig);
656
+ const parsedInvalidBase64 = parseRfc9421Signature("sig1=:!@#$%%^&*():");
712
657
  assertEquals(Object.keys(parsedInvalidBase64).length, 0, "Should handle invalid base64 in signature");
713
- const mixedRequest = new Request("https://example.com/api/resource", {
658
+ assertEquals(await verifyRequest(new Request("https://example.com/api/resource", {
714
659
  method: "GET",
715
660
  headers: new Headers({
716
661
  "Accept": "application/json",
@@ -719,14 +664,12 @@ test("verifyRequest() [rfc9421] error cases and edge cases", async () => {
719
664
  "Signature-Input": `${validSignatureInput},sig2=("@method" "@target-uri" "host" "date");keyid="https://example.com/invalid-key";alg="rsa-v1_5-sha256";created=${currentTimestamp}`,
720
665
  "Signature": `${validSignature},sig2=:AAAAAA==:`
721
666
  })
722
- });
723
- const mixedResult = await verifyRequest(mixedRequest, {
667
+ }), {
724
668
  contextLoader: mockDocumentLoader,
725
669
  documentLoader: mockDocumentLoader,
726
670
  spec: "rfc9421",
727
671
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date(currentTimestamp * 1e3)).toISOString()}`)
728
- });
729
- assertEquals(mixedResult, rsaPublicKey2, "Should verify when at least one signature is valid");
672
+ }), rsaPublicKey2, "Should verify when at least one signature is valid");
730
673
  });
731
674
  test("verifyRequest() [rfc9421] test vector from Mastodon", async () => {
732
675
  const signedRequest = new Request("https://www.example.com/activitypub/success", {
@@ -789,14 +732,13 @@ test("doubleKnock() function with successful first attempt", async () => {
789
732
  const logFunction = (req) => {
790
733
  loggedRequest = req;
791
734
  };
792
- const response = await doubleKnock(request, {
735
+ assertEquals((await doubleKnock(request, {
793
736
  keyId: rsaPublicKey2.id,
794
737
  privateKey: rsaPrivateKey2
795
738
  }, {
796
739
  specDeterminer,
797
740
  log: logFunction
798
- });
799
- assertEquals(response.status, 202, "Response status should be 202 Accepted");
741
+ })).status, 202, "Response status should be 202 Accepted");
800
742
  assertEquals(requestCount, 1, "Only one request should have been made");
801
743
  assertEquals(firstRequestSpec, "rfc9421", "First attempt should use RFC 9421");
802
744
  assertEquals(specDeterminer.usedSpec, "rfc9421", "Spec should be remembered");
@@ -837,11 +779,10 @@ test("doubleKnock() function with fallback to draft-cavage", async () => {
837
779
  this.rememberedSpec = spec;
838
780
  }
839
781
  };
840
- const response = await doubleKnock(request, {
782
+ assertEquals((await doubleKnock(request, {
841
783
  keyId: rsaPublicKey2.id,
842
784
  privateKey: rsaPrivateKey2
843
- }, { specDeterminer });
844
- assertEquals(response.status, 202, "Response status should be 202 Accepted");
785
+ }, { specDeterminer })).status, 202, "Response status should be 202 Accepted");
845
786
  assertEquals(requestCount, 2, "Two requests should have been made");
846
787
  assertEquals(firstSpec, "rfc9421", "First attempt should use RFC 9421");
847
788
  assertEquals(secondSpec, "draft-cavage-http-signatures-12", "Second attempt should use draft-cavage");
@@ -863,16 +804,14 @@ test("doubleKnock() function with redirect handling", async () => {
863
804
  responseCodes.push(202);
864
805
  return new Response("", { status: 202 });
865
806
  });
866
- const request = new Request("https://example.com/redirect-endpoint", {
807
+ assertEquals((await doubleKnock(new Request("https://example.com/redirect-endpoint", {
867
808
  method: "POST",
868
809
  body: "Test message that will be redirected",
869
810
  headers: { "Content-Type": "text/plain" }
870
- });
871
- const response = await doubleKnock(request, {
811
+ }), {
872
812
  keyId: rsaPublicKey2.id,
873
813
  privateKey: rsaPrivateKey2
874
- });
875
- assertEquals(response.status, 202, "Final response status should be 202 Accepted");
814
+ })).status, 202, "Final response status should be 202 Accepted");
876
815
  assertEquals(requestedUrls.length, 2, "Two URLs should have been requested");
877
816
  assertEquals(requestedUrls[0], "https://example.com/redirect-endpoint", "First request should be to redirect-endpoint");
878
817
  assertEquals(requestedUrls[1], "https://example.com/final-endpoint", "Second request should be to final-endpoint");
@@ -891,16 +830,14 @@ test("doubleKnock() function with both specs rejected", async () => {
891
830
  else attempts.push("unknown");
892
831
  return new Response("Unauthorized", { status: 401 });
893
832
  });
894
- const request = new Request("https://example.com/inbox-rejects-all", {
833
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-rejects-all", {
895
834
  method: "POST",
896
835
  body: "Test message that will be rejected regardless of signature format",
897
836
  headers: { "Content-Type": "text/plain" }
898
- });
899
- const response = await doubleKnock(request, {
837
+ }), {
900
838
  keyId: rsaPublicKey2.id,
901
839
  privateKey: rsaPrivateKey2
902
- });
903
- assertEquals(response.status, 401, "Final response status should be 401 Unauthorized");
840
+ })).status, 401, "Final response status should be 401 Unauthorized");
904
841
  assertEquals(requestCount, 2, "Two requests should have been made");
905
842
  assertEquals(attempts.length, 2, "Two signature attempts should have been made");
906
843
  assertEquals(attempts[0], "rfc9421", "First attempt should use RFC 9421");
@@ -924,16 +861,14 @@ test("doubleKnock() function with specDeterminer choosing draft-cavage first", a
924
861
  },
925
862
  rememberSpec(_origin, _spec) {}
926
863
  };
927
- const request = new Request("https://example.com/inbox-accepts-any", {
864
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-accepts-any", {
928
865
  method: "POST",
929
866
  body: "Test message with draft-cavage preference",
930
867
  headers: { "Content-Type": "text/plain" }
931
- });
932
- const response = await doubleKnock(request, {
868
+ }), {
933
869
  keyId: rsaPublicKey2.id,
934
870
  privateKey: rsaPrivateKey2
935
- }, { specDeterminer });
936
- assertEquals(response.status, 202, "Response status should be 202 Accepted");
871
+ }, { specDeterminer })).status, 202, "Response status should be 202 Accepted");
937
872
  assertEquals(requestCount, 1, "Only one request should have been made");
938
873
  assertEquals(firstSpec, "draft-cavage", "First attempt should use draft-cavage");
939
874
  esm_default.hardReset();
@@ -1064,25 +999,21 @@ test("doubleKnock() async specDeterminer test", async () => {
1064
999
  await new Promise((resolve) => setTimeout(resolve, 10));
1065
1000
  }
1066
1001
  };
1067
- const request = new Request("https://example.com/inbox-async-determiner", {
1002
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-async-determiner", {
1068
1003
  method: "POST",
1069
1004
  body: "Test message with async spec determiner",
1070
1005
  headers: { "Content-Type": "text/plain" }
1071
- });
1072
- const response = await doubleKnock(request, {
1006
+ }), {
1073
1007
  keyId: rsaPublicKey2.id,
1074
1008
  privateKey: rsaPrivateKey2
1075
- }, { specDeterminer });
1076
- assertEquals(response.status, 202, "Response status should be 202 Accepted");
1009
+ }, { specDeterminer })).status, 202, "Response status should be 202 Accepted");
1077
1010
  assertEquals(requestCount, 1, "Only one request should have been made");
1078
1011
  assertEquals(specUsed, "draft-cavage-http-signatures-12", "Should use spec from async determiner");
1079
1012
  esm_default.hardReset();
1080
1013
  });
1081
1014
  test("timingSafeEqual()", async (t) => {
1082
1015
  await t.step("should return true for equal empty arrays", () => {
1083
- const a = new Uint8Array([]);
1084
- const b = new Uint8Array([]);
1085
- assert(timingSafeEqual(a, b));
1016
+ assert(timingSafeEqual(new Uint8Array([]), new Uint8Array([])));
1086
1017
  });
1087
1018
  await t.step("should return true for equal non-empty arrays", async (t2) => {
1088
1019
  const testCases = [
@@ -1149,7 +1080,7 @@ test("timingSafeEqual()", async (t) => {
1149
1080
  assert(timingSafeEqual(arr, arr), "Array should be equal to itself by reference");
1150
1081
  });
1151
1082
  await t.step("should return false for arrays with same length but different content", async (t2) => {
1152
- const testCases = [
1083
+ for (const tc of [
1153
1084
  {
1154
1085
  a: [
1155
1086
  1,
@@ -1207,13 +1138,12 @@ test("timingSafeEqual()", async (t) => {
1207
1138
  ],
1208
1139
  name: "middle byte differs with edge values"
1209
1140
  }
1210
- ];
1211
- for (const tc of testCases) await t2.step(tc.name, () => {
1141
+ ]) await t2.step(tc.name, () => {
1212
1142
  assertFalse(timingSafeEqual(new Uint8Array(tc.a), new Uint8Array(tc.b)));
1213
1143
  });
1214
1144
  });
1215
1145
  await t.step("should return false for arrays with different lengths", async (t2) => {
1216
- const testCases = [
1146
+ for (const tc of [
1217
1147
  {
1218
1148
  a: [
1219
1149
  1,
@@ -1250,13 +1180,12 @@ test("timingSafeEqual()", async (t) => {
1250
1180
  b: [],
1251
1181
  name: "a non-empty, b empty"
1252
1182
  }
1253
- ];
1254
- for (const tc of testCases) await t2.step(tc.name, () => {
1183
+ ]) await t2.step(tc.name, () => {
1255
1184
  assertFalse(timingSafeEqual(new Uint8Array(tc.a), new Uint8Array(tc.b)));
1256
1185
  });
1257
1186
  });
1258
1187
  await t.step("should return false where content matches up to shorter length", async (t2) => {
1259
- const testCases = [
1188
+ for (const tc of [
1260
1189
  {
1261
1190
  a: [1, 2],
1262
1191
  b: [
@@ -1285,21 +1214,16 @@ test("timingSafeEqual()", async (t) => {
1285
1214
  b: [0],
1286
1215
  name: "two zeros vs single zero"
1287
1216
  }
1288
- ];
1289
- for (const tc of testCases) await t2.step(tc.name, () => {
1217
+ ]) await t2.step(tc.name, () => {
1290
1218
  assertFalse(timingSafeEqual(new Uint8Array(tc.a), new Uint8Array(tc.b)));
1291
1219
  });
1292
1220
  });
1293
1221
  await t.step("should correctly handle comparisons involving padding bytes", async (t2) => {
1294
1222
  await t2.step("a=[1], b=[1,0] (b longer with trailing zero)", () => {
1295
- const a1 = new Uint8Array([1]);
1296
- const b1 = new Uint8Array([1, 0]);
1297
- assertFalse(timingSafeEqual(a1, b1));
1223
+ assertFalse(timingSafeEqual(new Uint8Array([1]), new Uint8Array([1, 0])));
1298
1224
  });
1299
1225
  await t2.step("a=[1,0], b=[1] (a longer with trailing zero)", () => {
1300
- const a2 = new Uint8Array([1, 0]);
1301
- const b2 = new Uint8Array([1]);
1302
- assertFalse(timingSafeEqual(a2, b2));
1226
+ assertFalse(timingSafeEqual(new Uint8Array([1, 0]), new Uint8Array([1])));
1303
1227
  });
1304
1228
  });
1305
1229
  });
@@ -1319,20 +1243,18 @@ test("signRequest() [rfc9421] error handling for invalid signature base creation
1319
1243
  assertExists(signedRequest.headers.get("Signature"));
1320
1244
  });
1321
1245
  test("verifyRequest() [rfc9421] error handling for invalid signature base creation", async () => {
1322
- const request = new Request("https://example.com/test", {
1246
+ assertEquals(await verifyRequest(new Request("https://example.com/test", {
1323
1247
  method: "GET",
1324
1248
  headers: {
1325
1249
  "Accept": "application/json",
1326
1250
  "Signature-Input": "sig1=(\"@unsupported\");alg=\"rsa-pss-sha256\";keyid=\"https://example.com/key2\";created=1234567890",
1327
1251
  "Signature": "sig1=:invalid_signature_data:"
1328
1252
  }
1329
- });
1330
- const result = await verifyRequest(request, {
1253
+ }), {
1331
1254
  spec: "rfc9421",
1332
1255
  documentLoader: mockDocumentLoader,
1333
1256
  contextLoader: mockDocumentLoader
1334
- });
1335
- assertEquals(result, null, "Verification should fail gracefully for malformed signature inputs");
1257
+ }), null, "Verification should fail gracefully for malformed signature inputs");
1336
1258
  });
1337
1259
  test("doubleKnock() regression test for TypeError: unusable bug #294", async () => {
1338
1260
  esm_default.spyGlobal();
@@ -1346,16 +1268,14 @@ test("doubleKnock() regression test for TypeError: unusable bug #294", async ()
1346
1268
  esm_default.post("https://example.com/final-destination", () => {
1347
1269
  return new Response("Success", { status: 200 });
1348
1270
  });
1349
- const request = new Request("https://example.com/inbox-retry-redirect", {
1271
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-retry-redirect", {
1350
1272
  method: "POST",
1351
1273
  body: "Test activity content",
1352
1274
  headers: { "Content-Type": "application/activity+json" }
1353
- });
1354
- const response = await doubleKnock(request, {
1275
+ }), {
1355
1276
  keyId: rsaPublicKey2.id,
1356
1277
  privateKey: rsaPrivateKey2
1357
- });
1358
- assertEquals(response.status, 200);
1278
+ })).status, 200);
1359
1279
  assertEquals(requestCount, 2, "Should make 2 requests before redirect");
1360
1280
  esm_default.hardReset();
1361
1281
  });
@@ -1370,16 +1290,14 @@ test("doubleKnock() regression test for redirect handling bug", async () => {
1370
1290
  esm_default.post("https://example.com/final-destination", () => {
1371
1291
  return new Response("Success", { status: 200 });
1372
1292
  });
1373
- const request = new Request("https://example.com/inbox-retry-redirect", {
1293
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-retry-redirect", {
1374
1294
  method: "POST",
1375
1295
  body: "Test activity content",
1376
1296
  headers: { "Content-Type": "application/activity+json" }
1377
- });
1378
- const response = await doubleKnock(request, {
1297
+ }), {
1379
1298
  keyId: rsaPublicKey2.id,
1380
1299
  privateKey: rsaPrivateKey2
1381
- });
1382
- assertEquals(response.status, 200);
1300
+ })).status, 200);
1383
1301
  esm_default.hardReset();
1384
1302
  });
1385
1303
  test("signRequest() and verifyRequest() cancellation", {
@@ -1425,22 +1343,19 @@ test("signRequest() and verifyRequest() cancellation", {
1425
1343
  esm_default.hardReset();
1426
1344
  });
1427
1345
  test("signRequest() with custom label", async () => {
1428
- const request = new Request("https://example.com/api", {
1346
+ const signed = await signRequest(new Request("https://example.com/api", {
1429
1347
  method: "POST",
1430
1348
  body: "test",
1431
1349
  headers: { "Content-Type": "text/plain" }
1432
- });
1433
- const signed = await signRequest(request, rsaPrivateKey2, new URL("https://example.com/key2"), {
1350
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
1434
1351
  spec: "rfc9421",
1435
1352
  rfc9421: { label: "mysig" }
1436
1353
  });
1437
- const sigInput = signed.headers.get("Signature-Input");
1438
- assertStringIncludes(sigInput, "mysig=");
1439
- const sig = signed.headers.get("Signature");
1440
- assertStringIncludes(sig, "mysig=");
1354
+ assertStringIncludes(signed.headers.get("Signature-Input"), "mysig=");
1355
+ assertStringIncludes(signed.headers.get("Signature"), "mysig=");
1441
1356
  });
1442
1357
  test("signRequest() with custom components", async () => {
1443
- const request = new Request("https://example.com/api", {
1358
+ const sigInput = (await signRequest(new Request("https://example.com/api", {
1444
1359
  method: "POST",
1445
1360
  body: "test",
1446
1361
  headers: {
@@ -1448,8 +1363,7 @@ test("signRequest() with custom components", async () => {
1448
1363
  "Host": "example.com",
1449
1364
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT"
1450
1365
  }
1451
- });
1452
- const signed = await signRequest(request, rsaPrivateKey2, new URL("https://example.com/key2"), {
1366
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
1453
1367
  spec: "rfc9421",
1454
1368
  rfc9421: { components: [
1455
1369
  {
@@ -1465,29 +1379,26 @@ test("signRequest() with custom components", async () => {
1465
1379
  params: {}
1466
1380
  }
1467
1381
  ] }
1468
- });
1469
- const sigInput = signed.headers.get("Signature-Input");
1382
+ })).headers.get("Signature-Input");
1470
1383
  assertStringIncludes(sigInput, "\"@method\"");
1471
1384
  assertStringIncludes(sigInput, "\"@target-uri\"");
1472
1385
  assertStringIncludes(sigInput, "\"@authority\"");
1473
1386
  assertStringIncludes(sigInput, "\"content-digest\"");
1474
1387
  });
1475
1388
  test("signRequest() with nonce and tag", async () => {
1476
- const request = new Request("https://example.com/api", {
1389
+ const sigInput = (await signRequest(new Request("https://example.com/api", {
1477
1390
  method: "GET",
1478
1391
  headers: {
1479
1392
  "Host": "example.com",
1480
1393
  "Date": "Tue, 05 Mar 2024 07:49:44 GMT"
1481
1394
  }
1482
- });
1483
- const signed = await signRequest(request, rsaPrivateKey2, new URL("https://example.com/key2"), {
1395
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
1484
1396
  spec: "rfc9421",
1485
1397
  rfc9421: {
1486
1398
  nonce: "test-nonce-123",
1487
1399
  tag: "app-v1"
1488
1400
  }
1489
- });
1490
- const sigInput = signed.headers.get("Signature-Input");
1401
+ })).headers.get("Signature-Input");
1491
1402
  assertStringIncludes(sigInput, "nonce=\"test-nonce-123\"");
1492
1403
  assertStringIncludes(sigInput, "tag=\"app-v1\"");
1493
1404
  });
@@ -1497,26 +1408,22 @@ test("formatRfc9421SignatureParameters() escapes nonce and tag", () => {
1497
1408
  keyId: new URL("https://example.com/key"),
1498
1409
  created: 1709626184
1499
1410
  };
1500
- const slashNonce = formatRfc9421SignatureParameters({
1411
+ assertStringIncludes(formatRfc9421SignatureParameters({
1501
1412
  ...commonParams,
1502
1413
  nonce: "x\\y"
1503
- });
1504
- assertStringIncludes(slashNonce, "nonce=\"x\\\\y\"");
1505
- const quoteNonce = formatRfc9421SignatureParameters({
1414
+ }), "nonce=\"x\\\\y\"");
1415
+ assertStringIncludes(formatRfc9421SignatureParameters({
1506
1416
  ...commonParams,
1507
1417
  nonce: "a\"b"
1508
- });
1509
- assertStringIncludes(quoteNonce, "nonce=\"a\\\"b\"");
1510
- const slashTag = formatRfc9421SignatureParameters({
1418
+ }), "nonce=\"a\\\"b\"");
1419
+ assertStringIncludes(formatRfc9421SignatureParameters({
1511
1420
  ...commonParams,
1512
1421
  tag: "x\\y"
1513
- });
1514
- assertStringIncludes(slashTag, "tag=\"x\\\\y\"");
1515
- const quoteTag = formatRfc9421SignatureParameters({
1422
+ }), "tag=\"x\\\\y\"");
1423
+ assertStringIncludes(formatRfc9421SignatureParameters({
1516
1424
  ...commonParams,
1517
1425
  tag: "a\"b"
1518
- });
1519
- assertStringIncludes(quoteTag, "tag=\"a\\\"b\"");
1426
+ }), "tag=\"a\\\"b\"");
1520
1427
  const mixed = formatRfc9421SignatureParameters({
1521
1428
  ...commonParams,
1522
1429
  nonce: "n\"o\\nce",
@@ -1526,12 +1433,11 @@ test("formatRfc9421SignatureParameters() escapes nonce and tag", () => {
1526
1433
  assertStringIncludes(mixed, "tag=\"t\\\"ag\\\\value\"");
1527
1434
  });
1528
1435
  test("signRequest() [rfc9421] accumulates multiple signatures when called sequentially", async () => {
1529
- const request = new Request("https://example.com/inbox", {
1436
+ const twiceSigned = await signRequest(await signRequest(new Request("https://example.com/inbox", {
1530
1437
  method: "POST",
1531
1438
  body: "Hello",
1532
1439
  headers: { "Content-Type": "text/plain" }
1533
- });
1534
- const onceSigned = await signRequest(request, rsaPrivateKey2, new URL("https://example.com/key2"), {
1440
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
1535
1441
  spec: "rfc9421",
1536
1442
  rfc9421: {
1537
1443
  label: "sig1",
@@ -1543,8 +1449,7 @@ test("signRequest() [rfc9421] accumulates multiple signatures when called sequen
1543
1449
  params: {}
1544
1450
  }]
1545
1451
  }
1546
- });
1547
- const twiceSigned = await signRequest(onceSigned, rsaPrivateKey2, new URL("https://example.com/key2"), {
1452
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
1548
1453
  spec: "rfc9421",
1549
1454
  rfc9421: {
1550
1455
  label: "sig2",
@@ -1571,20 +1476,17 @@ test("doubleKnock(): Accept-Signature challenge retry succeeds", async () => {
1571
1476
  status: 401,
1572
1477
  headers: { "Accept-Signature": "sig1=(\"@method\" \"@target-uri\" \"@authority\" \"content-digest\");created;nonce=\"challenge-nonce-1\"" }
1573
1478
  });
1574
- const sigInput = req.headers.get("Signature-Input") ?? "";
1575
- if (sigInput.includes("challenge-nonce-1")) return new Response("", { status: 202 });
1479
+ if ((req.headers.get("Signature-Input") ?? "").includes("challenge-nonce-1")) return new Response("", { status: 202 });
1576
1480
  return new Response("Bad", { status: 400 });
1577
1481
  });
1578
- const request = new Request("https://example.com/inbox-challenge-ok", {
1482
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-challenge-ok", {
1579
1483
  method: "POST",
1580
1484
  body: "Test message",
1581
1485
  headers: { "Content-Type": "text/plain" }
1582
- });
1583
- const response = await doubleKnock(request, {
1486
+ }), {
1584
1487
  keyId: rsaPublicKey2.id,
1585
1488
  privateKey: rsaPrivateKey2
1586
- });
1587
- assertEquals(response.status, 202);
1489
+ })).status, 202);
1588
1490
  assertEquals(requestCount, 2);
1589
1491
  esm_default.hardReset();
1590
1492
  });
@@ -1601,16 +1503,14 @@ test("doubleKnock(): unfulfillable Accept-Signature falls to legacy fallback", a
1601
1503
  if (req.headers.has("Signature") && !req.headers.has("Signature-Input")) return new Response("", { status: 202 });
1602
1504
  return new Response("Bad", { status: 400 });
1603
1505
  });
1604
- const request = new Request("https://example.com/inbox-unfulfillable", {
1506
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-unfulfillable", {
1605
1507
  method: "POST",
1606
1508
  body: "Test message",
1607
1509
  headers: { "Content-Type": "text/plain" }
1608
- });
1609
- const response = await doubleKnock(request, {
1510
+ }), {
1610
1511
  keyId: rsaPublicKey2.id,
1611
1512
  privateKey: rsaPrivateKey2
1612
- });
1613
- assertEquals(response.status, 202);
1513
+ })).status, 202);
1614
1514
  assertEquals(requestCount, 2);
1615
1515
  esm_default.hardReset();
1616
1516
  });
@@ -1624,16 +1524,14 @@ test("doubleKnock(): no Accept-Signature falls to legacy fallback", async () =>
1624
1524
  if (req.headers.has("Signature")) return new Response("", { status: 202 });
1625
1525
  return new Response("Bad", { status: 400 });
1626
1526
  });
1627
- const request = new Request("https://example.com/inbox-no-challenge", {
1527
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-no-challenge", {
1628
1528
  method: "POST",
1629
1529
  body: "Test message",
1630
1530
  headers: { "Content-Type": "text/plain" }
1631
- });
1632
- const response = await doubleKnock(request, {
1531
+ }), {
1633
1532
  keyId: rsaPublicKey2.id,
1634
1533
  privateKey: rsaPrivateKey2
1635
- });
1636
- assertEquals(response.status, 202);
1534
+ })).status, 202);
1637
1535
  assertEquals(requestCount, 2);
1638
1536
  esm_default.hardReset();
1639
1537
  });
@@ -1651,16 +1549,14 @@ test("doubleKnock(): challenge retry also fails → legacy fallback attempted",
1651
1549
  if (req.headers.has("Signature") && !req.headers.has("Signature-Input")) return new Response("", { status: 202 });
1652
1550
  return new Response("Bad", { status: 400 });
1653
1551
  });
1654
- const request = new Request("https://example.com/inbox-challenge-fails", {
1552
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-challenge-fails", {
1655
1553
  method: "POST",
1656
1554
  body: "Test message",
1657
1555
  headers: { "Content-Type": "text/plain" }
1658
- });
1659
- const response = await doubleKnock(request, {
1556
+ }), {
1660
1557
  keyId: rsaPublicKey2.id,
1661
1558
  privateKey: rsaPrivateKey2
1662
- });
1663
- assertEquals(response.status, 202);
1559
+ })).status, 202);
1664
1560
  assertEquals(requestCount, 3);
1665
1561
  esm_default.hardReset();
1666
1562
  });
@@ -1681,16 +1577,14 @@ test("doubleKnock(): challenge retry returns another challenge → not followed"
1681
1577
  if (req.headers.has("Signature") && !req.headers.has("Signature-Input")) return new Response("", { status: 202 });
1682
1578
  return new Response("Bad", { status: 400 });
1683
1579
  });
1684
- const request = new Request("https://example.com/inbox-challenge-loop", {
1580
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-challenge-loop", {
1685
1581
  method: "POST",
1686
1582
  body: "Test message",
1687
1583
  headers: { "Content-Type": "text/plain" }
1688
- });
1689
- const response = await doubleKnock(request, {
1584
+ }), {
1690
1585
  keyId: rsaPublicKey2.id,
1691
1586
  privateKey: rsaPrivateKey2
1692
- });
1693
- assertEquals(response.status, 202);
1587
+ })).status, 202);
1694
1588
  assertEquals(requestCount, 3);
1695
1589
  esm_default.hardReset();
1696
1590
  });
@@ -1707,16 +1601,14 @@ test("doubleKnock(): Accept-Signature with unsupported component falls to legacy
1707
1601
  if (req.headers.has("Signature") && !req.headers.has("Signature-Input")) return new Response("", { status: 202 });
1708
1602
  return new Response("Bad", { status: 400 });
1709
1603
  });
1710
- const request = new Request("https://example.com/inbox-bad-challenge", {
1604
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-bad-challenge", {
1711
1605
  method: "POST",
1712
1606
  body: "Test message",
1713
1607
  headers: { "Content-Type": "text/plain" }
1714
- });
1715
- const response = await doubleKnock(request, {
1608
+ }), {
1716
1609
  keyId: rsaPublicKey2.id,
1717
1610
  privateKey: rsaPrivateKey2
1718
- });
1719
- assertEquals(response.status, 202);
1611
+ })).status, 202);
1720
1612
  assertEquals(requestCount, 2);
1721
1613
  esm_default.hardReset();
1722
1614
  });
@@ -1733,16 +1625,14 @@ test("doubleKnock(): Accept-Signature with unsupported derived component falls t
1733
1625
  if (req.headers.has("Signature") && !req.headers.has("Signature-Input")) return new Response("", { status: 202 });
1734
1626
  return new Response("Bad", { status: 400 });
1735
1627
  });
1736
- const request = new Request("https://example.com/inbox-bad-derived", {
1628
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-bad-derived", {
1737
1629
  method: "POST",
1738
1630
  body: "Test message",
1739
1631
  headers: { "Content-Type": "text/plain" }
1740
- });
1741
- const response = await doubleKnock(request, {
1632
+ }), {
1742
1633
  keyId: rsaPublicKey2.id,
1743
1634
  privateKey: rsaPrivateKey2
1744
- });
1745
- assertEquals(response.status, 202);
1635
+ })).status, 202);
1746
1636
  assertEquals(requestCount, 2);
1747
1637
  esm_default.hardReset();
1748
1638
  });
@@ -1759,16 +1649,14 @@ test("doubleKnock(): Accept-Signature with multiple entries where first throws f
1759
1649
  if (req.headers.has("Signature-Input")) return new Response("", { status: 202 });
1760
1650
  return new Response("Bad", { status: 400 });
1761
1651
  });
1762
- const request = new Request("https://example.com/inbox-multi-challenge", {
1652
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-multi-challenge", {
1763
1653
  method: "POST",
1764
1654
  body: "Test message",
1765
1655
  headers: { "Content-Type": "text/plain" }
1766
- });
1767
- const response = await doubleKnock(request, {
1656
+ }), {
1768
1657
  keyId: rsaPublicKey2.id,
1769
1658
  privateKey: rsaPrivateKey2
1770
- });
1771
- assertEquals(response.status, 202);
1659
+ })).status, 202);
1772
1660
  assertEquals(requestCount, 2);
1773
1661
  esm_default.hardReset();
1774
1662
  });
@@ -1787,18 +1675,16 @@ test("doubleKnock(): Accept-Signature with multiple compatible entries fulfills
1787
1675
  if (sigInput.includes("sig1=") && sigInput.includes("sig2=") && sig.includes("sig1=") && sig.includes("sig2=")) return new Response("", { status: 202 });
1788
1676
  return new Response("Missing signatures", { status: 400 });
1789
1677
  });
1790
- const request = new Request("https://example.com/inbox-multi-compat", {
1678
+ assertEquals((await doubleKnock(new Request("https://example.com/inbox-multi-compat", {
1791
1679
  method: "POST",
1792
1680
  body: "Test message",
1793
1681
  headers: { "Content-Type": "text/plain" }
1794
- });
1795
- const response = await doubleKnock(request, {
1682
+ }), {
1796
1683
  keyId: rsaPublicKey2.id,
1797
1684
  privateKey: rsaPrivateKey2
1798
- });
1799
- assertEquals(response.status, 202);
1685
+ })).status, 202);
1800
1686
  assertEquals(requestCount, 2);
1801
1687
  esm_default.hardReset();
1802
1688
  });
1803
-
1804
- //#endregion
1689
+ //#endregion
1690
+ export {};