@fedify/fedify 2.0.0-dev.1561 → 2.0.0-dev.158

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 (297) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +40 -18
  3. package/dist/{assert_rejects-DiIiJbZn.js → assert_rejects-Ce45JcFg.js} +1 -1
  4. package/dist/{assert_is_error-BPGph1Jx.js → assert_throws-BNXdRGWP.js} +31 -1
  5. package/dist/{builder-C8mpxJD3.js → builder-BnWso6VP.js} +15 -8
  6. package/dist/chunk-DqRYRqnO.cjs +34 -0
  7. package/dist/client-94iWEfQa.d.cts +222 -0
  8. package/dist/{client-DF8anIB5.d.ts → client-BivSNrEg.d.ts} +3 -75
  9. package/dist/{client-DI0GS_3p.js → client-CgMTXmAD.js} +3 -22
  10. package/dist/compat/mod.cjs +10 -0
  11. package/dist/compat/mod.d.cts +7 -0
  12. package/dist/compat/mod.d.ts +6 -12
  13. package/dist/compat/mod.js +5 -5
  14. package/dist/compat/transformers.test.js +21 -20
  15. package/dist/compat-DmDDELst.cjs +4 -0
  16. package/dist/compat-nxUqe4Z-.js +4 -0
  17. package/dist/context-Bns6uTJq.js +109 -0
  18. package/dist/{context-9gCpIkiz.d.ts → context-CYZ2i00R.d.ts} +321 -129
  19. package/dist/context-D2MrtLch.d.cts +2447 -0
  20. package/dist/deno-CQV858ip.js +117 -0
  21. package/dist/{testing-DsuOHyiF.js → dist-B5f6a8Tt.js} +90 -111
  22. package/dist/{authdocloader-CN-tWO4K.js → docloader-Csc8gQux.js} +17 -8
  23. package/dist/{esm-CtgLSZwm.js → esm-DGl7uK1r.js} +32 -17
  24. package/dist/federation/builder.test.js +12 -13
  25. package/dist/federation/collection.test.js +6 -9
  26. package/dist/federation/handler.test.js +115 -148
  27. package/dist/federation/idempotency.test.js +202 -0
  28. package/dist/federation/inbox.test.js +5 -6
  29. package/dist/federation/keycache.test.js +4 -5
  30. package/dist/federation/kv.test.js +61 -9
  31. package/dist/federation/middleware.test.js +311 -131
  32. package/dist/federation/mod.cjs +25 -0
  33. package/dist/federation/mod.d.cts +7 -0
  34. package/dist/federation/mod.d.ts +7 -13
  35. package/dist/federation/mod.js +11 -16
  36. package/dist/federation/mq.test.js +9 -10
  37. package/dist/federation/negotiation.test.js +25 -0
  38. package/dist/federation/retry.test.js +2 -4
  39. package/dist/federation/router.test.js +6 -8
  40. package/dist/federation/send.test.js +55 -15
  41. package/dist/{webfinger/handler.test.js → federation/webfinger.test.js} +27 -26
  42. package/dist/federation-B431K2gm.cjs +266 -0
  43. package/dist/{federation-CMX7WzeL.js → federation-BbZwNNWj.js} +31 -9
  44. package/dist/{http-B_tXwHIe.js → http-BizGfAHd.js} +375 -15
  45. package/dist/{http-DTJgsmYR.js → http-CXG5ZFqn.js} +4 -3
  46. package/dist/http-ClB3pLcL.d.cts +253 -0
  47. package/dist/{http-DqSNLFNY.d.ts → http-DLBDPal9.d.ts} +2 -2
  48. package/dist/http-DbACqYyq.cjs +1222 -0
  49. package/dist/{inbox-Dx8EjUbq.js → inbox-B7ybw6fk.js} +25 -7
  50. package/dist/{key-olV6hEgm.js → key-C27c_yHR.js} +3 -2
  51. package/dist/{keycache-CExtp4Yl.js → keycache-DRxpZ5r9.js} +1 -1
  52. package/dist/{keys-O0-r0NpJ.js → keys-ZbcByPg9.js} +2 -1
  53. package/dist/{kv-C7sopW2E.d.ts → kv-CtOmTRNc.d.ts} +30 -1
  54. package/dist/kv-D8q9fLkA.d.cts +110 -0
  55. package/dist/{kv-CRZrzyXm.js → kv-QzKcOQgP.js} +22 -0
  56. package/dist/kv-cache-B7dwGQFA.js +122 -0
  57. package/dist/kv-cache-BEeqyGER.js +107 -0
  58. package/dist/kv-cache-rPOPQdj9.cjs +134 -0
  59. package/dist/{ld-DR6b11xZ.js → ld-D_Jn1aGa.js} +6 -4
  60. package/dist/middleware-BVqYHBWm.cjs +12 -0
  61. package/dist/{middleware-GT7W03qw.js → middleware-BjS6_zkf.js} +272 -271
  62. package/dist/middleware-CAJR7KGo.cjs +4242 -0
  63. package/dist/{middleware-CUw3Ys9y.js → middleware-ClkhKNXU.js} +230 -327
  64. package/dist/middleware-DSz6sI16.js +26 -0
  65. package/dist/middleware-OcaFHSk8.js +12 -0
  66. package/dist/mod-BrS8tiad.d.cts +266 -0
  67. package/dist/mod-C81L6_lQ.d.cts +1 -0
  68. package/dist/mod-CJgbdSqb.d.ts +109 -0
  69. package/dist/mod-CNNTHyBC.d.cts +80 -0
  70. package/dist/mod-CS-MS7gZ.d.cts +62 -0
  71. package/dist/{mod-Bqxcp7eN.d.ts → mod-D_cmv2il.d.ts} +4 -4
  72. package/dist/mod-DcPRcifg.d.cts +107 -0
  73. package/dist/mod-DqFSzJA0.d.ts +64 -0
  74. package/dist/{mod-Drmz72EK.d.ts → mod-jOa7W503.d.ts} +3 -3
  75. package/dist/mod.cjs +55 -0
  76. package/dist/mod.d.cts +11 -0
  77. package/dist/mod.d.ts +11 -17
  78. package/dist/mod.js +15 -21
  79. package/dist/negotiation-5NPJL6zp.js +71 -0
  80. package/dist/nodeinfo/client.test.js +29 -111
  81. package/dist/nodeinfo/handler.test.js +26 -26
  82. package/dist/nodeinfo/mod.cjs +10 -0
  83. package/dist/nodeinfo/mod.d.cts +3 -0
  84. package/dist/nodeinfo/mod.d.ts +3 -5
  85. package/dist/nodeinfo/mod.js +6 -7
  86. package/dist/nodeinfo/types.test.js +7 -15
  87. package/dist/nodeinfo-BlLsRSiT.js +4 -0
  88. package/dist/nodeinfo-DuMYTpbZ.cjs +4 -0
  89. package/dist/otel/exporter.test.js +899 -0
  90. package/dist/otel/mod.cjs +262 -0
  91. package/dist/otel/mod.d.cts +230 -0
  92. package/dist/otel/mod.d.ts +232 -0
  93. package/dist/otel/mod.js +261 -0
  94. package/dist/{owner-CQPnQVtf.d.ts → owner-BgI8C-VY.d.ts} +2 -3
  95. package/dist/owner-C-zfmVAD.d.cts +66 -0
  96. package/dist/{owner-BtFz-dZ-.js → owner-Dc8rUE-H.js} +45 -8
  97. package/dist/{proof-DsZjVJ0G.js → proof-BdNM3iSl.js} +4 -3
  98. package/dist/proof-Bx2JqJ-D.cjs +709 -0
  99. package/dist/{proof-DKDM7T5F.js → proof-CTYnbjx5.js} +53 -17
  100. package/dist/router-D9eI0s4b.js +118 -0
  101. package/dist/{send-s0_EjVhZ.js → send-DBRRqVMa.js} +9 -4
  102. package/dist/sig/http.test.js +12 -14
  103. package/dist/sig/key.test.js +9 -11
  104. package/dist/sig/ld.test.js +8 -10
  105. package/dist/sig/mod.cjs +26 -0
  106. package/dist/sig/mod.d.cts +4 -0
  107. package/dist/sig/mod.d.ts +3 -7
  108. package/dist/sig/mod.js +6 -10
  109. package/dist/sig/owner.test.js +33 -12
  110. package/dist/sig/proof.test.js +13 -14
  111. package/dist/sig-CwuONEzF.js +4 -0
  112. package/dist/sig-DeXX2xnj.cjs +4 -0
  113. package/dist/testing/mod.d.ts +180 -6946
  114. package/dist/testing/mod.js +4 -4
  115. package/dist/transformers-BjBg6Lag.cjs +116 -0
  116. package/dist/{transformers-Dna8Fg7k.js → transformers-N_ip_y4P.js} +5 -5
  117. package/dist/{types-BIgY6c-l.js → types-BEdCLHqP.js} +1 -3
  118. package/dist/types-Q-qkJXBV.cjs +315 -0
  119. package/dist/{types-CGB4mJU6.js → types-hKTi53FO.js} +8 -169
  120. package/dist/{runtime/authdocloader.test.js → utils/docloader.test.js} +13 -15
  121. package/dist/utils/kv-cache.test.js +211 -0
  122. package/dist/utils/mod.cjs +10 -0
  123. package/dist/utils/mod.d.cts +4 -0
  124. package/dist/utils/mod.d.ts +6 -0
  125. package/dist/utils/mod.js +9 -0
  126. package/dist/utils-Db0ZmjcD.cjs +4 -0
  127. package/dist/utils-Wranxuoe.js +4 -0
  128. package/package.json +69 -55
  129. package/dist/actor-C22bXuuC.d.ts +0 -130
  130. package/dist/actor-Qc3Ee6k1.js +0 -37311
  131. package/dist/actor-mhluotIb.js +0 -146
  132. package/dist/assert_throws-BOO88avQ.js +0 -39
  133. package/dist/authdocloader-Dp9WS-1G.js +0 -52
  134. package/dist/compat-Bb5myD13.js +0 -4
  135. package/dist/denokv-Bv33Xxea.js +0 -57
  136. package/dist/docloader-CxWcuWqQ.d.ts +0 -221
  137. package/dist/docloader-DIjo5mkd.js +0 -4615
  138. package/dist/fixtures/activitypub.academy/users/brauca_darradiul.json +0 -83
  139. package/dist/fixtures/example.com/announce.json +0 -6
  140. package/dist/fixtures/example.com/collection.json +0 -19
  141. package/dist/fixtures/example.com/create.json +0 -6
  142. package/dist/fixtures/example.com/cross-origin-actor.json +0 -6
  143. package/dist/fixtures/example.com/hong-gildong.json +0 -11
  144. package/dist/fixtures/example.com/invite.json +0 -7
  145. package/dist/fixtures/example.com/key.json +0 -7
  146. package/dist/fixtures/example.com/key2.json +0 -6
  147. package/dist/fixtures/example.com/object.json +0 -6
  148. package/dist/fixtures/example.com/orderedcollectionpage.json +0 -24
  149. package/dist/fixtures/example.com/paged/a.json +0 -13
  150. package/dist/fixtures/example.com/paged/b.json +0 -16
  151. package/dist/fixtures/example.com/paged-collection.json +0 -6
  152. package/dist/fixtures/example.com/person.json +0 -22
  153. package/dist/fixtures/example.com/person2.json +0 -40
  154. package/dist/fixtures/example.com/test.json +0 -5
  155. package/dist/fixtures/example.com/users/handle.json +0 -16
  156. package/dist/fixtures/example.com/wrong-type.json +0 -3
  157. package/dist/fixtures/oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd.json +0 -24
  158. package/dist/fixtures/remote.domain/users/bob.json +0 -20
  159. package/dist/fixtures/server.example/users/alice.json +0 -20
  160. package/dist/fixtures/w3id.org/identity/v1.json +0 -152
  161. package/dist/fixtures/w3id.org/security/data-integrity/v1.json +0 -74
  162. package/dist/fixtures/w3id.org/security/multikey/v1.json +0 -35
  163. package/dist/fixtures/w3id.org/security/v1.json +0 -50
  164. package/dist/fixtures/wizard.casa/users/hongminhee.json +0 -69
  165. package/dist/fixtures/www.w3.org/ns/activitystreams.json +0 -379
  166. package/dist/fixtures/www.w3.org/ns/did/v1.json +0 -58
  167. package/dist/key-CGjkGPkw.js +0 -260
  168. package/dist/key-CaFAQSic.js +0 -10
  169. package/dist/key-DcnCet42.js +0 -10
  170. package/dist/lookup-B8Ld9P9G.js +0 -131
  171. package/dist/lookup-IyAhz9I6.js +0 -322
  172. package/dist/middleware-Bx6Sgkth.js +0 -26
  173. package/dist/middleware-DdRB1d4s.js +0 -17
  174. package/dist/mod-Cxt4Kpf6.d.ts +0 -291
  175. package/dist/mod-DBzN0aCM.d.ts +0 -115
  176. package/dist/mod-TFoH2Ql8.d.ts +0 -104
  177. package/dist/mod-g0xFzAP9.d.ts +0 -2
  178. package/dist/mq-CRGm1e_F.d.ts +0 -143
  179. package/dist/nodeinfo/semver.test.js +0 -143
  180. package/dist/nodeinfo-CyEbLjHs.js +0 -4
  181. package/dist/runtime/docloader.test.js +0 -522
  182. package/dist/runtime/key.test.js +0 -103
  183. package/dist/runtime/langstr.test.js +0 -39
  184. package/dist/runtime/mod.d.ts +0 -8
  185. package/dist/runtime/mod.js +0 -13
  186. package/dist/runtime/multibase/multibase.test.d.ts +0 -3
  187. package/dist/runtime/multibase/multibase.test.js +0 -358
  188. package/dist/runtime/url.test.d.ts +0 -3
  189. package/dist/runtime/url.test.js +0 -45
  190. package/dist/runtime-BSkOVUWM.js +0 -4
  191. package/dist/semver-dArNLkR9.js +0 -149
  192. package/dist/sig-BXJO--F9.js +0 -4
  193. package/dist/src/vocab/accept.yaml +0 -15
  194. package/dist/src/vocab/activity.yaml +0 -98
  195. package/dist/src/vocab/add.yaml +0 -16
  196. package/dist/src/vocab/announce.yaml +0 -30
  197. package/dist/src/vocab/application.yaml +0 -324
  198. package/dist/src/vocab/arrive.yaml +0 -15
  199. package/dist/src/vocab/article.yaml +0 -46
  200. package/dist/src/vocab/audio.yaml +0 -11
  201. package/dist/src/vocab/block.yaml +0 -16
  202. package/dist/src/vocab/chatmessage.yaml +0 -50
  203. package/dist/src/vocab/collection.yaml +0 -154
  204. package/dist/src/vocab/collectionpage.yaml +0 -55
  205. package/dist/src/vocab/create.yaml +0 -28
  206. package/dist/src/vocab/dataintegrityproof.yaml +0 -56
  207. package/dist/src/vocab/delete.yaml +0 -27
  208. package/dist/src/vocab/didservice.yaml +0 -22
  209. package/dist/src/vocab/dislike.yaml +0 -14
  210. package/dist/src/vocab/document.yaml +0 -31
  211. package/dist/src/vocab/emoji.yaml +0 -12
  212. package/dist/src/vocab/emojireact.yaml +0 -17
  213. package/dist/src/vocab/endpoints.yaml +0 -85
  214. package/dist/src/vocab/event.yaml +0 -11
  215. package/dist/src/vocab/export.yaml +0 -9
  216. package/dist/src/vocab/flag.yaml +0 -15
  217. package/dist/src/vocab/follow.yaml +0 -19
  218. package/dist/src/vocab/group.yaml +0 -324
  219. package/dist/src/vocab/hashtag.yaml +0 -14
  220. package/dist/src/vocab/ignore.yaml +0 -14
  221. package/dist/src/vocab/image.yaml +0 -9
  222. package/dist/src/vocab/intransitiveactivity.yaml +0 -15
  223. package/dist/src/vocab/invite.yaml +0 -14
  224. package/dist/src/vocab/join.yaml +0 -14
  225. package/dist/src/vocab/key.yaml +0 -28
  226. package/dist/src/vocab/leave.yaml +0 -14
  227. package/dist/src/vocab/like.yaml +0 -16
  228. package/dist/src/vocab/link.yaml +0 -101
  229. package/dist/src/vocab/listen.yaml +0 -12
  230. package/dist/src/vocab/mention.yaml +0 -9
  231. package/dist/src/vocab/move.yaml +0 -15
  232. package/dist/src/vocab/multikey.yaml +0 -36
  233. package/dist/src/vocab/note.yaml +0 -48
  234. package/dist/src/vocab/object.yaml +0 -404
  235. package/dist/src/vocab/offer.yaml +0 -15
  236. package/dist/src/vocab/orderedcollection.yaml +0 -39
  237. package/dist/src/vocab/orderedcollectionpage.yaml +0 -50
  238. package/dist/src/vocab/organization.yaml +0 -324
  239. package/dist/src/vocab/page.yaml +0 -11
  240. package/dist/src/vocab/person.yaml +0 -324
  241. package/dist/src/vocab/place.yaml +0 -75
  242. package/dist/src/vocab/profile.yaml +0 -26
  243. package/dist/src/vocab/propertyvalue.yaml +0 -32
  244. package/dist/src/vocab/question.yaml +0 -103
  245. package/dist/src/vocab/read.yaml +0 -13
  246. package/dist/src/vocab/reject.yaml +0 -14
  247. package/dist/src/vocab/relationship.yaml +0 -52
  248. package/dist/src/vocab/remove.yaml +0 -14
  249. package/dist/src/vocab/service.yaml +0 -324
  250. package/dist/src/vocab/source.yaml +0 -26
  251. package/dist/src/vocab/tentativeaccept.yaml +0 -14
  252. package/dist/src/vocab/tentativereject.yaml +0 -14
  253. package/dist/src/vocab/tombstone.yaml +0 -24
  254. package/dist/src/vocab/travel.yaml +0 -16
  255. package/dist/src/vocab/undo.yaml +0 -26
  256. package/dist/src/vocab/update.yaml +0 -58
  257. package/dist/src/vocab/video.yaml +0 -11
  258. package/dist/src/vocab/view.yaml +0 -13
  259. package/dist/testing/docloader.test.js +0 -24
  260. package/dist/type-BMGxK0zE.js +0 -42006
  261. package/dist/vocab/actor.test.d.ts +0 -3
  262. package/dist/vocab/actor.test.js +0 -5965
  263. package/dist/vocab/lookup.test.d.ts +0 -3
  264. package/dist/vocab/lookup.test.js +0 -206
  265. package/dist/vocab/mod.d.ts +0 -8
  266. package/dist/vocab/mod.js +0 -10
  267. package/dist/vocab/schema.yaml +0 -247
  268. package/dist/vocab/type.test.d.ts +0 -3
  269. package/dist/vocab/type.test.js +0 -25
  270. package/dist/vocab/vocab.test.d.ts +0 -3
  271. package/dist/vocab/vocab.test.js +0 -3363
  272. package/dist/vocab-CXuKLJjd.js +0 -246
  273. package/dist/vocab-SOE1ifCr.d.ts +0 -14634
  274. package/dist/webfinger/handler.test.d.ts +0 -3
  275. package/dist/webfinger/lookup.test.d.ts +0 -3
  276. package/dist/webfinger/lookup.test.js +0 -195
  277. package/dist/webfinger/mod.d.ts +0 -6
  278. package/dist/webfinger/mod.js +0 -9
  279. package/dist/webfinger-C3GIyXIg.js +0 -4
  280. package/dist/x/cfworkers.d.ts +0 -61
  281. package/dist/x/cfworkers.js +0 -98
  282. package/dist/x/cfworkers.test.d.ts +0 -3
  283. package/dist/x/cfworkers.test.js +0 -179
  284. package/dist/x/hono.d.ts +0 -56
  285. package/dist/x/hono.js +0 -60
  286. package/dist/x/sveltekit.d.ts +0 -48
  287. package/dist/x/sveltekit.js +0 -68
  288. /package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals-C80BG-_5.js} +0 -0
  289. /package/dist/{collection-CSzG2j1P.js → collection-CcnIw1qY.js} +0 -0
  290. /package/dist/{nodeinfo/semver.test.d.ts → federation/idempotency.test.d.ts} +0 -0
  291. /package/dist/{runtime/authdocloader.test.d.ts → federation/negotiation.test.d.ts} +0 -0
  292. /package/dist/{runtime/docloader.test.d.ts → federation/webfinger.test.d.ts} +0 -0
  293. /package/dist/{mod-1pDWKvUL.d.ts → mod-1E3W847c.d.ts} +0 -0
  294. /package/dist/{runtime/key.test.d.ts → otel/exporter.test.d.ts} +0 -0
  295. /package/dist/{std__assert-X-_kMxKM.js → std__assert-DWivtrGR.js} +0 -0
  296. /package/dist/{testing → utils}/docloader.test.d.ts +0 -0
  297. /package/dist/{runtime/langstr.test.d.ts → utils/kv-cache.test.d.ts} +0 -0
@@ -0,0 +1,1222 @@
1
+
2
+ const { Temporal } = require("@js-temporal/polyfill");
3
+ const { URLPattern } = require("urlpattern-polyfill");
4
+
5
+ const require_chunk = require('./chunk-DqRYRqnO.cjs');
6
+ const __logtape_logtape = require_chunk.__toESM(require("@logtape/logtape"));
7
+ const __fedify_vocab = require_chunk.__toESM(require("@fedify/vocab"));
8
+ const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
9
+ const byte_encodings_hex = require_chunk.__toESM(require("byte-encodings/hex"));
10
+ const __opentelemetry_semantic_conventions = require_chunk.__toESM(require("@opentelemetry/semantic-conventions"));
11
+ const byte_encodings_base64 = require_chunk.__toESM(require("byte-encodings/base64"));
12
+ const structured_field_values = require_chunk.__toESM(require("structured-field-values"));
13
+ const __fedify_vocab_runtime = require_chunk.__toESM(require("@fedify/vocab-runtime"));
14
+
15
+ //#region deno.json
16
+ var name = "@fedify/fedify";
17
+ var version = "2.0.0-dev.158+628cd89e";
18
+ var license = "MIT";
19
+ var exports$1 = {
20
+ ".": "./src/mod.ts",
21
+ "./compat": "./src/compat/mod.ts",
22
+ "./federation": "./src/federation/mod.ts",
23
+ "./nodeinfo": "./src/nodeinfo/mod.ts",
24
+ "./otel": "./src/otel/mod.ts",
25
+ "./sig": "./src/sig/mod.ts",
26
+ "./utils": "./src/utils/mod.ts"
27
+ };
28
+ var imports = {
29
+ "@multiformats/base-x": "npm:@multiformats/base-x@^4.0.1",
30
+ "@opentelemetry/core": "npm:@opentelemetry/core@^2.0.0",
31
+ "@opentelemetry/sdk-trace-base": "npm:@opentelemetry/sdk-trace-base@^2.0.0",
32
+ "@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.27.0",
33
+ "@std/assert": "jsr:@std/assert@^0.226.0",
34
+ "@std/url": "jsr:@std/url@^0.225.1",
35
+ "asn1js": "npm:asn1js@^3.0.7",
36
+ "fast-check": "npm:fast-check@^3.22.0",
37
+ "fetch-mock": "npm:fetch-mock@^12.5.2",
38
+ "json-canon": "npm:json-canon@^1.0.1",
39
+ "jsonld": "npm:jsonld@^9.0.0",
40
+ "multicodec": "npm:multicodec@^3.2.1",
41
+ "pkijs": "npm:pkijs@^3.3.3",
42
+ "structured-field-values": "npm:structured-field-values@^2.0.4",
43
+ "uri-template-router": "npm:uri-template-router@^1.0.0",
44
+ "url-template": "npm:url-template@^3.1.1"
45
+ };
46
+ var exclude = [
47
+ ".test-report.xml",
48
+ "apidoc/",
49
+ "dist/",
50
+ "node_modules/",
51
+ "npm/",
52
+ "pnpm-lock.yaml",
53
+ "src/cfworkers/dist/",
54
+ "src/cfworkers/fixtures/",
55
+ "src/cfworkers/imports.ts",
56
+ "src/cfworkers/README.md",
57
+ "src/cfworkers/server.ts",
58
+ "src/cfworkers/server.js",
59
+ "src/cfworkers/server.js.map"
60
+ ];
61
+ var publish = { "exclude": ["**/*.test.ts", "src/testing/"] };
62
+ var tasks = {
63
+ "codegen": "deno task -f @fedify/vocab compile",
64
+ "cache": {
65
+ "command": "deno cache src/mod.ts",
66
+ "dependencies": ["codegen"]
67
+ },
68
+ "check": {
69
+ "command": "deno fmt --check && deno lint && deno check src/**/*.ts",
70
+ "dependencies": ["codegen"]
71
+ },
72
+ "test": {
73
+ "command": "deno test --check --doc --allow-read --allow-write --allow-env --unstable-kv --trace-leaks --parallel",
74
+ "dependencies": ["codegen"]
75
+ },
76
+ "coverage": "deno task test --clean --coverage && deno coverage --html coverage",
77
+ "bench": {
78
+ "command": "deno bench --allow-read --allow-write --allow-net --allow-env --allow-run --unstable-kv",
79
+ "dependencies": ["codegen"]
80
+ },
81
+ "apidoc": {
82
+ "command": "deno doc --html --name=Fedify --output=apidoc/ src/mod.ts",
83
+ "dependencies": ["codegen"]
84
+ },
85
+ "publish": {
86
+ "command": "deno publish",
87
+ "dependencies": ["codegen"]
88
+ },
89
+ "pnpm:install": "pnpm install --silent",
90
+ "pnpm:build": {
91
+ "command": "pnpm exec tsdown",
92
+ "dependencies": ["pnpm:build-vocab"]
93
+ },
94
+ "test:node": {
95
+ "command": "cd dist/ && node --test",
96
+ "dependencies": ["pnpm:build"]
97
+ },
98
+ "test:bun": {
99
+ "command": "cd dist/ && bun test --timeout 60000",
100
+ "dependencies": ["pnpm:build"]
101
+ },
102
+ "test:cfworkers": {
103
+ "command": "pnpm exec wrangler deploy --dry-run --outdir src/cfworkers && node --import=tsx src/cfworkers/client.ts",
104
+ "dependencies": ["pnpm:build"]
105
+ },
106
+ "test-all": { "dependencies": [
107
+ "check",
108
+ "test",
109
+ "test:node",
110
+ "test:bun",
111
+ "test:cfworkers"
112
+ ] }
113
+ };
114
+ var deno_default = {
115
+ name,
116
+ version,
117
+ license,
118
+ exports: exports$1,
119
+ imports,
120
+ exclude,
121
+ publish,
122
+ tasks
123
+ };
124
+
125
+ //#endregion
126
+ //#region src/sig/key.ts
127
+ /**
128
+ * Checks if the given key is valid and supported. No-op if the key is valid,
129
+ * otherwise throws an error.
130
+ * @param key The key to check.
131
+ * @param type Which type of key to check. If not specified, the key can be
132
+ * either public or private.
133
+ * @throws {TypeError} If the key is invalid or unsupported.
134
+ */
135
+ function validateCryptoKey(key, type) {
136
+ if (type != null && key.type !== type) throw new TypeError(`The key is not a ${type} key.`);
137
+ if (!key.extractable) throw new TypeError("The key is not extractable.");
138
+ if (key.algorithm.name !== "RSASSA-PKCS1-v1_5" && key.algorithm.name !== "Ed25519") throw new TypeError("Currently only RSASSA-PKCS1-v1_5 and Ed25519 keys are supported. More algorithms will be added in the future!");
139
+ if (key.algorithm.name === "RSASSA-PKCS1-v1_5") {
140
+ const algorithm = key.algorithm;
141
+ if (algorithm.hash.name !== "SHA-256") throw new TypeError("For compatibility with the existing Fediverse software (e.g., Mastodon), hash algorithm for RSASSA-PKCS1-v1_5 keys must be SHA-256.");
142
+ }
143
+ }
144
+ /**
145
+ * Generates a key pair which is appropriate for Fedify.
146
+ * @param algorithm The algorithm to use. Currently only RSASSA-PKCS1-v1_5 and
147
+ * Ed25519 are supported.
148
+ * @returns The generated key pair.
149
+ * @throws {TypeError} If the algorithm is unsupported.
150
+ */
151
+ function generateCryptoKeyPair(algorithm) {
152
+ if (algorithm == null) (0, __logtape_logtape.getLogger)([
153
+ "fedify",
154
+ "sig",
155
+ "key"
156
+ ]).warn("No algorithm specified. Using RSASSA-PKCS1-v1_5 by default, but it is recommended to specify the algorithm explicitly as the parameter will be required in the future.");
157
+ if (algorithm == null || algorithm === "RSASSA-PKCS1-v1_5") return crypto.subtle.generateKey({
158
+ name: "RSASSA-PKCS1-v1_5",
159
+ modulusLength: 4096,
160
+ publicExponent: new Uint8Array([
161
+ 1,
162
+ 0,
163
+ 1
164
+ ]),
165
+ hash: "SHA-256"
166
+ }, true, ["sign", "verify"]);
167
+ else if (algorithm === "Ed25519") return crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"]);
168
+ throw new TypeError("Unsupported algorithm: " + algorithm);
169
+ }
170
+ /**
171
+ * Exports a key in JWK format.
172
+ * @param key The key to export. Either public or private key.
173
+ * @returns The exported key in JWK format. The key is suitable for
174
+ * serialization and storage.
175
+ * @throws {TypeError} If the key is invalid or unsupported.
176
+ */
177
+ async function exportJwk(key) {
178
+ validateCryptoKey(key);
179
+ const jwk = await crypto.subtle.exportKey("jwk", key);
180
+ if (jwk.crv === "Ed25519") jwk.alg = "Ed25519";
181
+ return jwk;
182
+ }
183
+ /**
184
+ * Imports a key from JWK format.
185
+ * @param jwk The key in JWK format.
186
+ * @param type Which type of key to import, either `"public"` or `"private"`.
187
+ * @returns The imported key.
188
+ * @throws {TypeError} If the key is invalid or unsupported.
189
+ */
190
+ async function importJwk(jwk, type) {
191
+ let key;
192
+ if (jwk.kty === "RSA" && jwk.alg === "RS256") key = await crypto.subtle.importKey("jwk", jwk, {
193
+ name: "RSASSA-PKCS1-v1_5",
194
+ hash: "SHA-256"
195
+ }, true, type === "public" ? ["verify"] : ["sign"]);
196
+ else if (jwk.kty === "OKP" && jwk.crv === "Ed25519") {
197
+ if (navigator?.userAgent === "Cloudflare-Workers") {
198
+ jwk = { ...jwk };
199
+ delete jwk.alg;
200
+ }
201
+ key = await crypto.subtle.importKey("jwk", jwk, "Ed25519", true, type === "public" ? ["verify"] : ["sign"]);
202
+ } else throw new TypeError("Unsupported JWK format.");
203
+ validateCryptoKey(key, type);
204
+ return key;
205
+ }
206
+ /**
207
+ * Fetches a {@link CryptographicKey} or {@link Multikey} from the given URL.
208
+ * If the given URL contains an {@link Actor} object, it tries to find
209
+ * the corresponding key in the `publicKey` or `assertionMethod` property.
210
+ * @template T The type of the key to fetch. Either {@link CryptographicKey}
211
+ * or {@link Multikey}.
212
+ * @param keyId The URL of the key.
213
+ * @param cls The class of the key to fetch. Either {@link CryptographicKey}
214
+ * or {@link Multikey}.
215
+ * @param options Options for fetching the key. See {@link FetchKeyOptions}.
216
+ * @returns The fetched key or `null` if the key is not found.
217
+ * @since 1.3.0
218
+ */
219
+ function fetchKey(keyId, cls, options = {}) {
220
+ const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
221
+ const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
222
+ keyId = typeof keyId === "string" ? new URL(keyId) : keyId;
223
+ return tracer.startActiveSpan("activitypub.fetch_key", {
224
+ kind: __opentelemetry_api.SpanKind.CLIENT,
225
+ attributes: {
226
+ "http.method": "GET",
227
+ "url.full": keyId.href,
228
+ "url.scheme": keyId.protocol.replace(/:$/, ""),
229
+ "url.domain": keyId.hostname,
230
+ "url.path": keyId.pathname,
231
+ "url.query": keyId.search.replace(/^\?/, ""),
232
+ "url.fragment": keyId.hash.replace(/^#/, "")
233
+ }
234
+ }, async (span) => {
235
+ try {
236
+ const result = await fetchKeyInternal(keyId, cls, options);
237
+ span.setAttribute("activitypub.actor.key.cached", result.cached);
238
+ return result;
239
+ } catch (e) {
240
+ span.setStatus({
241
+ code: __opentelemetry_api.SpanStatusCode.ERROR,
242
+ message: String(e)
243
+ });
244
+ throw e;
245
+ } finally {
246
+ span.end();
247
+ }
248
+ });
249
+ }
250
+ async function fetchKeyInternal(keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider } = {}) {
251
+ const logger = (0, __logtape_logtape.getLogger)([
252
+ "fedify",
253
+ "sig",
254
+ "key"
255
+ ]);
256
+ const cacheKey = typeof keyId === "string" ? new URL(keyId) : keyId;
257
+ keyId = typeof keyId === "string" ? keyId : keyId.href;
258
+ if (keyCache != null) {
259
+ const cachedKey = await keyCache.get(cacheKey);
260
+ if (cachedKey instanceof cls && cachedKey.publicKey != null) {
261
+ logger.debug("Key {keyId} found in cache.", { keyId });
262
+ return {
263
+ key: cachedKey,
264
+ cached: true
265
+ };
266
+ } else if (cachedKey === null) {
267
+ logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
268
+ return {
269
+ key: null,
270
+ cached: true
271
+ };
272
+ }
273
+ }
274
+ logger.debug("Fetching key {keyId} to verify signature...", { keyId });
275
+ let document;
276
+ try {
277
+ const remoteDocument = await (documentLoader ?? (0, __fedify_vocab_runtime.getDocumentLoader)())(keyId);
278
+ document = remoteDocument.document;
279
+ } catch (_) {
280
+ logger.debug("Failed to fetch key {keyId}.", { keyId });
281
+ await keyCache?.set(cacheKey, null);
282
+ return {
283
+ key: null,
284
+ cached: false
285
+ };
286
+ }
287
+ let object;
288
+ try {
289
+ object = await __fedify_vocab.Object.fromJsonLd(document, {
290
+ documentLoader,
291
+ contextLoader,
292
+ tracerProvider
293
+ });
294
+ } catch (e) {
295
+ if (!(e instanceof TypeError)) throw e;
296
+ try {
297
+ object = await cls.fromJsonLd(document, {
298
+ documentLoader,
299
+ contextLoader,
300
+ tracerProvider
301
+ });
302
+ } catch (e$1) {
303
+ if (e$1 instanceof TypeError) {
304
+ logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
305
+ await keyCache?.set(cacheKey, null);
306
+ return {
307
+ key: null,
308
+ cached: false
309
+ };
310
+ }
311
+ throw e$1;
312
+ }
313
+ }
314
+ let key = null;
315
+ if (object instanceof cls) key = object;
316
+ else if ((0, __fedify_vocab.isActor)(object)) {
317
+ const keys = cls === __fedify_vocab.CryptographicKey ? object.getPublicKeys({
318
+ documentLoader,
319
+ contextLoader,
320
+ tracerProvider
321
+ }) : object.getAssertionMethods({
322
+ documentLoader,
323
+ contextLoader,
324
+ tracerProvider
325
+ });
326
+ let length = 0;
327
+ let lastKey = null;
328
+ for await (const k of keys) {
329
+ length++;
330
+ lastKey = k;
331
+ if (k.id?.href === keyId) {
332
+ key = k;
333
+ break;
334
+ }
335
+ }
336
+ const keyIdUrl = new URL(keyId);
337
+ if (key == null && keyIdUrl.hash === "" && length === 1) key = lastKey;
338
+ if (key == null) {
339
+ logger.debug("Failed to verify; object {keyId} returned an {actorType}, but has no key matching {keyId}.", {
340
+ keyId,
341
+ actorType: object.constructor.name
342
+ });
343
+ await keyCache?.set(cacheKey, null);
344
+ return {
345
+ key: null,
346
+ cached: false
347
+ };
348
+ }
349
+ } else {
350
+ logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
351
+ await keyCache?.set(cacheKey, null);
352
+ return {
353
+ key: null,
354
+ cached: false
355
+ };
356
+ }
357
+ if (key.publicKey == null) {
358
+ logger.debug("Failed to verify; key {keyId} has no publicKeyPem field.", { keyId });
359
+ await keyCache?.set(cacheKey, null);
360
+ return {
361
+ key: null,
362
+ cached: false
363
+ };
364
+ }
365
+ if (keyCache != null) {
366
+ await keyCache.set(cacheKey, key);
367
+ logger.debug("Key {keyId} cached.", { keyId });
368
+ }
369
+ return {
370
+ key,
371
+ cached: false
372
+ };
373
+ }
374
+
375
+ //#endregion
376
+ //#region src/sig/http.ts
377
+ /**
378
+ * Signs a request using the given private key.
379
+ * @param request The request to sign.
380
+ * @param privateKey The private key to use for signing.
381
+ * @param keyId The key ID to use for the signature. It will be used by the
382
+ * verifier.
383
+ * @returns The signed request.
384
+ * @throws {TypeError} If the private key is invalid or unsupported.
385
+ */
386
+ async function signRequest(request, privateKey, keyId, options = {}) {
387
+ validateCryptoKey(privateKey, "private");
388
+ const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
389
+ const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
390
+ return await tracer.startActiveSpan("http_signatures.sign", async (span) => {
391
+ try {
392
+ const spec = options.spec ?? "draft-cavage-http-signatures-12";
393
+ let signed;
394
+ if (spec === "rfc9421") signed = await signRequestRfc9421(request, privateKey, keyId, span, options.currentTime, options.body);
395
+ else signed = await signRequestDraft(request, privateKey, keyId, span, options.currentTime, options.body);
396
+ if (span.isRecording()) {
397
+ span.setAttribute(__opentelemetry_semantic_conventions.ATTR_HTTP_REQUEST_METHOD, signed.method);
398
+ span.setAttribute(__opentelemetry_semantic_conventions.ATTR_URL_FULL, signed.url);
399
+ for (const [name$1, value] of signed.headers) span.setAttribute((0, __opentelemetry_semantic_conventions.ATTR_HTTP_REQUEST_HEADER)(name$1), value);
400
+ span.setAttribute("http_signatures.key_id", keyId.href);
401
+ }
402
+ return signed;
403
+ } catch (error) {
404
+ span.setStatus({
405
+ code: __opentelemetry_api.SpanStatusCode.ERROR,
406
+ message: String(error)
407
+ });
408
+ throw error;
409
+ } finally {
410
+ span.end();
411
+ }
412
+ });
413
+ }
414
+ async function signRequestDraft(request, privateKey, keyId, span, currentTime, bodyBuffer) {
415
+ if (privateKey.algorithm.name !== "RSASSA-PKCS1-v1_5") throw new TypeError("Unsupported algorithm: " + privateKey.algorithm.name);
416
+ const url = new URL(request.url);
417
+ const body = bodyBuffer !== void 0 ? bodyBuffer : request.method !== "GET" && request.method !== "HEAD" ? await request.clone().arrayBuffer() : null;
418
+ const headers = new Headers(request.headers);
419
+ if (!headers.has("Host")) headers.set("Host", url.host);
420
+ if (!headers.has("Digest") && body != null) {
421
+ const digest = await crypto.subtle.digest("SHA-256", body);
422
+ headers.set("Digest", `SHA-256=${(0, byte_encodings_base64.encodeBase64)(digest)}`);
423
+ if (span.isRecording()) span.setAttribute("http_signatures.digest.sha-256", (0, byte_encodings_hex.encodeHex)(digest));
424
+ }
425
+ if (!headers.has("Date")) headers.set("Date", currentTime == null ? (/* @__PURE__ */ new Date()).toUTCString() : new Date(currentTime.toString()).toUTCString());
426
+ const serialized = [["(request-target)", `${request.method.toLowerCase()} ${url.pathname}`], ...headers];
427
+ const headerNames = serialized.map(([name$1]) => name$1);
428
+ const message = serialized.map(([name$1, value]) => `${name$1}: ${value.trim()}`).join("\n");
429
+ const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, new TextEncoder().encode(message));
430
+ const sigHeader = `keyId="${keyId.href}",algorithm="rsa-sha256",headers="${headerNames.join(" ")}",signature="${(0, byte_encodings_base64.encodeBase64)(signature)}"`;
431
+ headers.set("Signature", sigHeader);
432
+ if (span.isRecording()) {
433
+ span.setAttribute("http_signatures.algorithm", "rsa-sha256");
434
+ span.setAttribute("http_signatures.signature", (0, byte_encodings_hex.encodeHex)(signature));
435
+ }
436
+ return new Request(request, {
437
+ headers,
438
+ body
439
+ });
440
+ }
441
+ function formatRfc9421SignatureParameters(params) {
442
+ return `alg="${params.algorithm}";keyid="${params.keyId.href}";created=${params.created}`;
443
+ }
444
+ /**
445
+ * Creates a signature base for a request according to RFC 9421.
446
+ * @param request The request to create a signature base for.
447
+ * @param components The components to include in the signature base.
448
+ * @param parameters The signature parameters to include in the signature base.
449
+ * @returns The signature base as a string.
450
+ */
451
+ function createRfc9421SignatureBase(request, components, parameters) {
452
+ const url = new URL(request.url);
453
+ const baseComponents = [];
454
+ for (const component of components) {
455
+ let value;
456
+ if (component === "@method") value = request.method.toUpperCase();
457
+ else if (component === "@target-uri") value = request.url;
458
+ else if (component === "@authority") value = url.host;
459
+ else if (component === "@scheme") value = url.protocol.slice(0, -1);
460
+ else if (component === "@request-target") value = `${request.method.toLowerCase()} ${url.pathname}${url.search}`;
461
+ else if (component === "@path") value = url.pathname;
462
+ else if (component === "@query") value = url.search.startsWith("?") ? url.search.slice(1) : url.search;
463
+ else if (component === "@query-param") throw new Error("@query-param requires a parameter name");
464
+ else if (component === "@status") throw new Error("@status is only valid for responses");
465
+ else if (component.startsWith("@")) throw new Error(`Unsupported derived component: ${component}`);
466
+ else {
467
+ const header = request.headers.get(component);
468
+ if (header == null) throw new Error(`Missing header: ${component}`);
469
+ value = header;
470
+ }
471
+ baseComponents.push(`"${component}": ${value}`);
472
+ }
473
+ const sigComponents = components.map((c) => `"${c}"`).join(" ");
474
+ baseComponents.push(`"@signature-params": (${sigComponents});${parameters}`);
475
+ return baseComponents.join("\n");
476
+ }
477
+ /**
478
+ * Formats a signature using rfc9421 format.
479
+ * @param signature The raw signature bytes.
480
+ * @param components The components that were signed.
481
+ * @param parameters The signature parameters.
482
+ * @returns The formatted signature string.
483
+ */
484
+ function formatRfc9421Signature(signature, components, parameters) {
485
+ const signatureInputValue = `sig1=("${components.join("\" \"")}");${parameters}`;
486
+ const signatureValue = `sig1=:${(0, byte_encodings_base64.encodeBase64)(signature)}:`;
487
+ return [signatureInputValue, signatureValue];
488
+ }
489
+ /**
490
+ * Parse RFC 9421 Signature-Input header.
491
+ * @param signatureInput The Signature-Input header value.
492
+ * @returns Parsed signature input parameters.
493
+ */
494
+ function parseRfc9421SignatureInput(signatureInput) {
495
+ let dict;
496
+ try {
497
+ dict = (0, structured_field_values.decodeDict)(signatureInput);
498
+ } catch (error) {
499
+ (0, __logtape_logtape.getLogger)([
500
+ "fedify",
501
+ "sig",
502
+ "http"
503
+ ]).debug("Failed to parse Signature-Input header: {signatureInput}", {
504
+ signatureInput,
505
+ error
506
+ });
507
+ return {};
508
+ }
509
+ const result = {};
510
+ for (const [label, item] of Object.entries(dict)) {
511
+ if (!Array.isArray(item.value) || typeof item.params.keyid !== "string" || typeof item.params.created !== "number") continue;
512
+ const components = item.value.map((subitem) => subitem.value).filter((v) => typeof v === "string");
513
+ const params = (0, structured_field_values.encodeItem)(new structured_field_values.Item(0, item.params));
514
+ result[label] = {
515
+ keyId: item.params.keyid,
516
+ alg: item.params.alg,
517
+ created: item.params.created,
518
+ components,
519
+ parameters: params.slice(params.indexOf(";") + 1)
520
+ };
521
+ }
522
+ return result;
523
+ }
524
+ /**
525
+ * Parse RFC 9421 Signature header.
526
+ * @param signature The Signature header value.
527
+ * @returns Parsed signature values.
528
+ */
529
+ function parseRfc9421Signature(signature) {
530
+ let dict;
531
+ try {
532
+ dict = (0, structured_field_values.decodeDict)(signature);
533
+ } catch (error) {
534
+ (0, __logtape_logtape.getLogger)([
535
+ "fedify",
536
+ "sig",
537
+ "http"
538
+ ]).debug("Failed to parse Signature header: {signature}", {
539
+ signature,
540
+ error
541
+ });
542
+ return {};
543
+ }
544
+ const result = {};
545
+ for (const [key, value] of Object.entries(dict)) if (value.value instanceof Uint8Array) result[key] = value.value;
546
+ return result;
547
+ }
548
+ async function signRequestRfc9421(request, privateKey, keyId, span, currentTime, bodyBuffer) {
549
+ if (privateKey.algorithm.name !== "RSASSA-PKCS1-v1_5") throw new TypeError("Unsupported algorithm: " + privateKey.algorithm.name);
550
+ const url = new URL(request.url);
551
+ const body = bodyBuffer !== void 0 ? bodyBuffer : request.method !== "GET" && request.method !== "HEAD" ? await request.clone().arrayBuffer() : null;
552
+ const headers = new Headers(request.headers);
553
+ if (!headers.has("Host")) headers.set("Host", url.host);
554
+ if (!headers.has("Content-Digest") && body != null) {
555
+ const digest = await crypto.subtle.digest("SHA-256", body);
556
+ headers.set("Content-Digest", `sha-256=:${(0, byte_encodings_base64.encodeBase64)(digest)}:`);
557
+ if (span.isRecording()) span.setAttribute("http_signatures.digest.sha-256", (0, byte_encodings_hex.encodeHex)(digest));
558
+ }
559
+ currentTime ??= Temporal.Now.instant();
560
+ const created = currentTime.epochMilliseconds / 1e3 | 0;
561
+ if (!headers.has("Date")) headers.set("Date", new Date(currentTime.toString()).toUTCString());
562
+ const components = [
563
+ "@method",
564
+ "@target-uri",
565
+ "@authority",
566
+ "host",
567
+ "date"
568
+ ];
569
+ if (body != null) components.push("content-digest");
570
+ const signatureParams = formatRfc9421SignatureParameters({
571
+ algorithm: "rsa-v1_5-sha256",
572
+ keyId,
573
+ created
574
+ });
575
+ let signatureBase;
576
+ try {
577
+ signatureBase = createRfc9421SignatureBase(new Request(request.url, {
578
+ method: request.method,
579
+ headers
580
+ }), components, signatureParams);
581
+ } catch (error) {
582
+ throw new TypeError(`Failed to create signature base: ${String(error)}; it is probably a bug in the implementation. Please report it at Fedify's issue tracker.`);
583
+ }
584
+ const signatureBytes = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", privateKey, new TextEncoder().encode(signatureBase));
585
+ const [signatureInput, signature] = formatRfc9421Signature(signatureBytes, components, signatureParams);
586
+ headers.set("Signature-Input", signatureInput);
587
+ headers.set("Signature", signature);
588
+ if (span.isRecording()) {
589
+ span.setAttribute("http_signatures.algorithm", "rsa-v1_5-sha256");
590
+ span.setAttribute("http_signatures.signature", (0, byte_encodings_hex.encodeHex)(signatureBytes));
591
+ span.setAttribute("http_signatures.created", created.toString());
592
+ }
593
+ return new Request(request, {
594
+ headers,
595
+ body
596
+ });
597
+ }
598
+ const supportedHashAlgorithms = {
599
+ "sha": "SHA-1",
600
+ "sha-256": "SHA-256",
601
+ "sha-512": "SHA-512"
602
+ };
603
+ /**
604
+ * Verifies the signature of a request.
605
+ *
606
+ * Note that this function consumes the request body, so it should not be used
607
+ * if the request body is already consumed. Consuming the request body after
608
+ * calling this function is okay, since this function clones the request
609
+ * under the hood.
610
+ *
611
+ * @param request The request to verify.
612
+ * @param options Options for verifying the request.
613
+ * @returns The public key of the verified signature, or `null` if the signature
614
+ * could not be verified.
615
+ */
616
+ async function verifyRequest(request, options = {}) {
617
+ const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
618
+ const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
619
+ return await tracer.startActiveSpan("http_signatures.verify", async (span) => {
620
+ if (span.isRecording()) {
621
+ span.setAttribute(__opentelemetry_semantic_conventions.ATTR_HTTP_REQUEST_METHOD, request.method);
622
+ span.setAttribute(__opentelemetry_semantic_conventions.ATTR_URL_FULL, request.url);
623
+ for (const [name$1, value] of request.headers) span.setAttribute((0, __opentelemetry_semantic_conventions.ATTR_HTTP_REQUEST_HEADER)(name$1), value);
624
+ }
625
+ try {
626
+ let spec = options.spec;
627
+ if (spec == null) spec = request.headers.has("Signature-Input") ? "rfc9421" : "draft-cavage-http-signatures-12";
628
+ let key;
629
+ if (spec === "rfc9421") key = await verifyRequestRfc9421(request, span, options);
630
+ else key = await verifyRequestDraft(request, span, options);
631
+ if (key == null) span.setStatus({ code: __opentelemetry_api.SpanStatusCode.ERROR });
632
+ return key;
633
+ } catch (error) {
634
+ span.setStatus({
635
+ code: __opentelemetry_api.SpanStatusCode.ERROR,
636
+ message: String(error)
637
+ });
638
+ throw error;
639
+ } finally {
640
+ span.end();
641
+ }
642
+ });
643
+ }
644
+ async function verifyRequestDraft(request, span, { documentLoader, contextLoader, timeWindow, currentTime, keyCache, tracerProvider } = {}) {
645
+ const logger = (0, __logtape_logtape.getLogger)([
646
+ "fedify",
647
+ "sig",
648
+ "http"
649
+ ]);
650
+ if (request.bodyUsed) {
651
+ logger.error("Failed to verify; the request body is already consumed.", { url: request.url });
652
+ return null;
653
+ } else if (request.body?.locked) {
654
+ logger.error("Failed to verify; the request body is locked.", { url: request.url });
655
+ return null;
656
+ }
657
+ const originalRequest = request;
658
+ request = request.clone();
659
+ const dateHeader = request.headers.get("Date");
660
+ if (dateHeader == null) {
661
+ logger.debug("Failed to verify; no Date header found.", { headers: Object.fromEntries(request.headers.entries()) });
662
+ return null;
663
+ }
664
+ const sigHeader = request.headers.get("Signature");
665
+ if (sigHeader == null) {
666
+ logger.debug("Failed to verify; no Signature header found.", { headers: Object.fromEntries(request.headers.entries()) });
667
+ return null;
668
+ }
669
+ const digestHeader = request.headers.get("Digest");
670
+ if (request.method !== "GET" && request.method !== "HEAD" && digestHeader == null) {
671
+ logger.debug("Failed to verify; no Digest header found.", { headers: Object.fromEntries(request.headers.entries()) });
672
+ return null;
673
+ }
674
+ let body = null;
675
+ if (digestHeader != null) {
676
+ body = await request.arrayBuffer();
677
+ const digests = digestHeader.split(",").map((pair) => pair.includes("=") ? pair.split("=", 2) : [pair, ""]);
678
+ let matched = false;
679
+ for (let [algo, digestBase64] of digests) {
680
+ algo = algo.trim().toLowerCase();
681
+ if (!(algo in supportedHashAlgorithms)) continue;
682
+ let digest;
683
+ try {
684
+ digest = (0, byte_encodings_base64.decodeBase64)(digestBase64);
685
+ } catch (error) {
686
+ logger.debug("Failed to verify; invalid base64 encoding: {digest}.", {
687
+ digest: digestBase64,
688
+ error
689
+ });
690
+ return null;
691
+ }
692
+ if (span.isRecording()) span.setAttribute(`http_signatures.digest.${algo}`, (0, byte_encodings_hex.encodeHex)(digest));
693
+ const expectedDigest = await crypto.subtle.digest(supportedHashAlgorithms[algo], body);
694
+ if (!timingSafeEqual(digest, new Uint8Array(expectedDigest))) {
695
+ logger.debug("Failed to verify; digest mismatch ({algorithm}): {digest} != {expectedDigest}.", {
696
+ algorithm: algo,
697
+ digest: digestBase64,
698
+ expectedDigest: (0, byte_encodings_base64.encodeBase64)(expectedDigest)
699
+ });
700
+ return null;
701
+ }
702
+ matched = true;
703
+ }
704
+ if (!matched) {
705
+ logger.debug("Failed to verify; no supported digest algorithm found. Supported: {supportedAlgorithms}; found: {algorithms}.", {
706
+ supportedAlgorithms: Object.keys(supportedHashAlgorithms),
707
+ algorithms: digests.map(([algo]) => algo)
708
+ });
709
+ return null;
710
+ }
711
+ }
712
+ const date = Temporal.Instant.from(new Date(dateHeader).toISOString());
713
+ const now = currentTime ?? Temporal.Now.instant();
714
+ if (timeWindow !== false) {
715
+ const tw = timeWindow ?? { hours: 1 };
716
+ if (Temporal.Instant.compare(date, now.add(tw)) > 0) {
717
+ logger.debug("Failed to verify; Date is too far in the future.", {
718
+ date: date.toString(),
719
+ now: now.toString()
720
+ });
721
+ return null;
722
+ } else if (Temporal.Instant.compare(date, now.subtract(tw)) < 0) {
723
+ logger.debug("Failed to verify; Date is too far in the past.", {
724
+ date: date.toString(),
725
+ now: now.toString()
726
+ });
727
+ return null;
728
+ }
729
+ }
730
+ const sigValues = Object.fromEntries(sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)=(?:"([^"]*)"|(\d+))\s*$/)).filter((m) => m != null).map((m) => [m[1], m[2] ?? m[3]]));
731
+ if (!("keyId" in sigValues)) {
732
+ logger.debug("Failed to verify; no keyId field found in the Signature header.", { signature: sigHeader });
733
+ return null;
734
+ } else if (!("headers" in sigValues)) {
735
+ logger.debug("Failed to verify; no headers field found in the Signature header.", { signature: sigHeader });
736
+ return null;
737
+ } else if (!("signature" in sigValues)) {
738
+ logger.debug("Failed to verify; no signature field found in the Signature header.", { signature: sigHeader });
739
+ return null;
740
+ }
741
+ if ("expires" in sigValues) {
742
+ const expiresSeconds = parseInt(sigValues.expires);
743
+ if (!Number.isInteger(expiresSeconds)) {
744
+ logger.debug("Failed to verify; invalid expires field in the Signature header: {expires}.", {
745
+ expires: sigValues.expires,
746
+ signature: sigHeader
747
+ });
748
+ return null;
749
+ }
750
+ const expires = Temporal.Instant.fromEpochMilliseconds(expiresSeconds * 1e3);
751
+ if (Temporal.Instant.compare(now, expires) > 0) {
752
+ logger.debug("Failed to verify; signature expired at {expires} (now: {now}).", {
753
+ expires: expires.toString(),
754
+ now: now.toString(),
755
+ signature: sigHeader
756
+ });
757
+ return null;
758
+ }
759
+ }
760
+ if ("created" in sigValues) {
761
+ const createdSeconds = parseInt(sigValues.created);
762
+ if (!Number.isInteger(createdSeconds)) {
763
+ logger.debug("Failed to verify; invalid created field in the Signature header: {created}.", {
764
+ created: sigValues.created,
765
+ signature: sigHeader
766
+ });
767
+ return null;
768
+ }
769
+ if (timeWindow !== false) {
770
+ const created = Temporal.Instant.fromEpochMilliseconds(createdSeconds * 1e3);
771
+ const tw = timeWindow ?? { minutes: 1 };
772
+ if (Temporal.Instant.compare(created, now.add(tw)) > 0) {
773
+ logger.debug("Failed to verify; created is too far in the future.", {
774
+ created: created.toString(),
775
+ now: now.toString()
776
+ });
777
+ return null;
778
+ } else if (Temporal.Instant.compare(created, now.subtract(tw)) < 0) {
779
+ logger.debug("Failed to verify; created is too far in the past.", {
780
+ created: created.toString(),
781
+ now: now.toString()
782
+ });
783
+ return null;
784
+ }
785
+ }
786
+ }
787
+ const { keyId, headers, signature } = sigValues;
788
+ span?.setAttribute("http_signatures.key_id", keyId);
789
+ if ("algorithm" in sigValues) span?.setAttribute("http_signatures.algorithm", sigValues.algorithm);
790
+ const { key, cached } = await fetchKey(new URL(keyId), __fedify_vocab.CryptographicKey, {
791
+ documentLoader,
792
+ contextLoader,
793
+ keyCache,
794
+ tracerProvider
795
+ });
796
+ if (key == null) return null;
797
+ const headerNames = headers.split(/\s+/g);
798
+ if (!headerNames.includes("(request-target)") || !headerNames.includes("date")) {
799
+ logger.debug("Failed to verify; required headers missing in the Signature header: {headers}.", { headers });
800
+ return null;
801
+ }
802
+ if (body != null && !headerNames.includes("digest")) {
803
+ logger.debug("Failed to verify; required headers missing in the Signature header: {headers}.", { headers });
804
+ return null;
805
+ }
806
+ const message = headerNames.map((name$1) => `${name$1}: ` + (name$1 === "(request-target)" ? `${request.method.toLowerCase()} ${new URL(request.url).pathname}` : name$1 === "(created)" ? sigValues.created ?? "" : name$1 === "(expires)" ? sigValues.expires ?? "" : name$1 === "host" ? request.headers.get("host") ?? new URL(request.url).host : request.headers.get(name$1))).join("\n");
807
+ const sig = (0, byte_encodings_base64.decodeBase64)(signature);
808
+ span?.setAttribute("http_signatures.signature", (0, byte_encodings_hex.encodeHex)(sig));
809
+ const verified = await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, sig, new TextEncoder().encode(message));
810
+ if (!verified) {
811
+ if (cached) {
812
+ logger.debug("Failed to verify with the cached key {keyId}; signature {signature} is invalid. Retrying with the freshly fetched key...", {
813
+ keyId,
814
+ signature,
815
+ message
816
+ });
817
+ return await verifyRequest(originalRequest, {
818
+ documentLoader,
819
+ contextLoader,
820
+ timeWindow,
821
+ currentTime,
822
+ keyCache: {
823
+ get: () => Promise.resolve(void 0),
824
+ set: async (keyId$1, key$1) => await keyCache?.set(keyId$1, key$1)
825
+ }
826
+ });
827
+ }
828
+ logger.debug("Failed to verify with the fetched key {keyId}; signature {signature} is invalid. Check if the key is correct or if the signed message is correct. The message to sign is:\n{message}", {
829
+ keyId,
830
+ signature,
831
+ message
832
+ });
833
+ return null;
834
+ }
835
+ return key;
836
+ }
837
+ /**
838
+ * RFC 9421 map of algorithm identifiers to WebCrypto algorithms
839
+ */
840
+ const rfc9421AlgorithmMap = {
841
+ "rsa-v1_5-sha256": {
842
+ name: "RSASSA-PKCS1-v1_5",
843
+ hash: "SHA-256"
844
+ },
845
+ "rsa-v1_5-sha512": {
846
+ name: "RSASSA-PKCS1-v1_5",
847
+ hash: "SHA-512"
848
+ },
849
+ "rsa-pss-sha512": {
850
+ name: "RSA-PSS",
851
+ hash: "SHA-512"
852
+ },
853
+ "ecdsa-p256-sha256": {
854
+ name: "ECDSA",
855
+ hash: "SHA-256"
856
+ },
857
+ "ecdsa-p384-sha384": {
858
+ name: "ECDSA",
859
+ hash: "SHA-384"
860
+ },
861
+ "ed25519": { name: "Ed25519" }
862
+ };
863
+ /**
864
+ * Verifies a Content-Digest header according to RFC 9421.
865
+ * @param digestHeader The Content-Digest header value.
866
+ * @param body The message body to verify against.
867
+ * @returns Whether the digest is valid.
868
+ */
869
+ async function verifyRfc9421ContentDigest(digestHeader, body) {
870
+ const digests = digestHeader.split(",").map((pair) => {
871
+ pair = pair.trim();
872
+ const pos = pair.indexOf("=");
873
+ const algo = pos < 0 ? pair : pair.slice(0, pos);
874
+ const value = pos < 0 ? "" : pair.slice(pos + 1);
875
+ return {
876
+ algo: algo.trim().toLowerCase(),
877
+ value: value.trim()
878
+ };
879
+ });
880
+ for (const { algo, value } of digests) {
881
+ let hashAlgo;
882
+ if (algo === "sha-256") hashAlgo = "SHA-256";
883
+ else if (algo === "sha-512") hashAlgo = "SHA-512";
884
+ else continue;
885
+ const base64Match = value.match(/^:([^:]+):$/);
886
+ if (!base64Match) continue;
887
+ let digest;
888
+ try {
889
+ digest = (0, byte_encodings_base64.decodeBase64)(base64Match[1]);
890
+ } catch {
891
+ continue;
892
+ }
893
+ const calculatedDigest = await crypto.subtle.digest(hashAlgo, body);
894
+ if (timingSafeEqual(digest, new Uint8Array(calculatedDigest))) return true;
895
+ }
896
+ return false;
897
+ }
898
+ async function verifyRequestRfc9421(request, span, { documentLoader, contextLoader, timeWindow, currentTime, keyCache, tracerProvider } = {}) {
899
+ const logger = (0, __logtape_logtape.getLogger)([
900
+ "fedify",
901
+ "sig",
902
+ "http"
903
+ ]);
904
+ if (request.bodyUsed) {
905
+ logger.error("Failed to verify; the request body is already consumed.", { url: request.url });
906
+ return null;
907
+ } else if (request.body?.locked) {
908
+ logger.error("Failed to verify; the request body is locked.", { url: request.url });
909
+ return null;
910
+ }
911
+ const originalRequest = request;
912
+ request = request.clone();
913
+ const signatureInputHeader = request.headers.get("Signature-Input");
914
+ if (!signatureInputHeader) {
915
+ logger.debug("Failed to verify; no Signature-Input header found.", { headers: Object.fromEntries(request.headers.entries()) });
916
+ return null;
917
+ }
918
+ const signatureHeader = request.headers.get("Signature");
919
+ if (!signatureHeader) {
920
+ logger.debug("Failed to verify; no Signature header found.", { headers: Object.fromEntries(request.headers.entries()) });
921
+ return null;
922
+ }
923
+ const signatureInputs = parseRfc9421SignatureInput(signatureInputHeader);
924
+ logger.debug("Parsed Signature-Input header: {signatureInputs}", { signatureInputs });
925
+ const signatures = parseRfc9421Signature(signatureHeader);
926
+ const signatureNames = Object.keys(signatureInputs);
927
+ if (signatureNames.length === 0) {
928
+ logger.debug("Failed to verify; no valid signatures found in Signature-Input header.", { header: signatureInputHeader });
929
+ return null;
930
+ }
931
+ let validKey = null;
932
+ for (const sigName of signatureNames) {
933
+ if (!signatures[sigName]) continue;
934
+ const sigInput = signatureInputs[sigName];
935
+ const sigBytes = signatures[sigName];
936
+ if (!sigInput.keyId) {
937
+ logger.debug("Failed to verify; missing keyId in signature {signatureName}.", {
938
+ signatureName: sigName,
939
+ signatureInput: signatureInputHeader
940
+ });
941
+ continue;
942
+ }
943
+ if (!sigInput.created) {
944
+ logger.debug("Failed to verify; missing created timestamp in signature {signatureName}.", {
945
+ signatureName: sigName,
946
+ signatureInput: signatureInputHeader
947
+ });
948
+ continue;
949
+ }
950
+ const signatureCreated = Temporal.Instant.fromEpochMilliseconds(sigInput.created * 1e3);
951
+ const now = currentTime ?? Temporal.Now.instant();
952
+ if (timeWindow !== false) {
953
+ const tw = timeWindow ?? { hours: 1 };
954
+ if (Temporal.Instant.compare(signatureCreated, now.add(tw)) > 0) {
955
+ logger.debug("Failed to verify; signature created time is too far in the future.", {
956
+ created: signatureCreated.toString(),
957
+ now: now.toString()
958
+ });
959
+ continue;
960
+ } else if (Temporal.Instant.compare(signatureCreated, now.subtract(tw)) < 0) {
961
+ logger.debug("Failed to verify; signature created time is too far in the past.", {
962
+ created: signatureCreated.toString(),
963
+ now: now.toString()
964
+ });
965
+ continue;
966
+ }
967
+ }
968
+ if (request.method !== "GET" && request.method !== "HEAD" && sigInput.components.includes("content-digest")) {
969
+ const contentDigestHeader = request.headers.get("Content-Digest");
970
+ if (!contentDigestHeader) {
971
+ logger.debug("Failed to verify; Content-Digest header required but not found.", { components: sigInput.components });
972
+ continue;
973
+ }
974
+ const body = await request.arrayBuffer();
975
+ const digestValid = await verifyRfc9421ContentDigest(contentDigestHeader, body);
976
+ if (!digestValid) {
977
+ logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
978
+ continue;
979
+ }
980
+ }
981
+ span?.setAttribute("http_signatures.key_id", sigInput.keyId);
982
+ span?.setAttribute("http_signatures.created", sigInput.created.toString());
983
+ const { key, cached } = await fetchKey(new URL(sigInput.keyId), __fedify_vocab.CryptographicKey, {
984
+ documentLoader,
985
+ contextLoader,
986
+ keyCache,
987
+ tracerProvider
988
+ });
989
+ if (!key) {
990
+ logger.debug("Failed to fetch key: {keyId}", { keyId: sigInput.keyId });
991
+ continue;
992
+ }
993
+ let alg = sigInput.alg?.toLowerCase();
994
+ if (alg == null) {
995
+ if (key.publicKey.algorithm.name === "RSASSA-PKCS1-v1_5") alg = "hash" in key.publicKey.algorithm ? key.publicKey.algorithm.hash === "SHA-512" ? "rsa-v1_5-sha512" : "rsa-v1_5-sha256" : "rsa-v1_5-sha256";
996
+ else if (key.publicKey.algorithm.name === "RSA-PSS") alg = "rsa-pss-sha512";
997
+ else if (key.publicKey.algorithm.name === "ECDSA") alg = "namedCurve" in key.publicKey.algorithm && key.publicKey.algorithm.namedCurve === "P-256" ? "ecdsa-p256-sha256" : "ecdsa-p384-sha384";
998
+ else if (key.publicKey.algorithm.name === "Ed25519") alg = "ed25519";
999
+ }
1000
+ if (alg) span?.setAttribute("http_signatures.algorithm", alg);
1001
+ const algorithm = alg && rfc9421AlgorithmMap[alg];
1002
+ if (!algorithm) {
1003
+ logger.debug("Failed to verify; unsupported algorithm: {algorithm}", {
1004
+ algorithm: sigInput.alg,
1005
+ supported: Object.keys(rfc9421AlgorithmMap)
1006
+ });
1007
+ continue;
1008
+ }
1009
+ let signatureBase;
1010
+ try {
1011
+ signatureBase = createRfc9421SignatureBase(request, sigInput.components, sigInput.parameters);
1012
+ } catch (error) {
1013
+ logger.debug("Failed to create signature base for verification: {error}", {
1014
+ error,
1015
+ signatureInput: sigInput
1016
+ });
1017
+ continue;
1018
+ }
1019
+ const signatureBaseBytes = new TextEncoder().encode(signatureBase);
1020
+ span?.setAttribute("http_signatures.signature", (0, byte_encodings_hex.encodeHex)(sigBytes));
1021
+ try {
1022
+ const verified = await crypto.subtle.verify(algorithm, key.publicKey, sigBytes.slice(), signatureBaseBytes);
1023
+ if (verified) {
1024
+ validKey = key;
1025
+ break;
1026
+ } else if (cached) {
1027
+ logger.debug("Failed to verify with cached key {keyId}; retrying with fresh key...", { keyId: sigInput.keyId });
1028
+ return await verifyRequest(originalRequest, {
1029
+ documentLoader,
1030
+ contextLoader,
1031
+ timeWindow,
1032
+ currentTime,
1033
+ keyCache: {
1034
+ get: () => Promise.resolve(void 0),
1035
+ set: async (keyId, key$1) => await keyCache?.set(keyId, key$1)
1036
+ },
1037
+ spec: "rfc9421"
1038
+ });
1039
+ } else logger.debug("Failed to verify signature with fetched key {keyId}; signature invalid.", {
1040
+ keyId: sigInput.keyId,
1041
+ signatureBase
1042
+ });
1043
+ } catch (error) {
1044
+ logger.debug("Error during signature verification: {error}", {
1045
+ error,
1046
+ keyId: sigInput.keyId,
1047
+ algorithm: sigInput.alg
1048
+ });
1049
+ }
1050
+ }
1051
+ return validKey;
1052
+ }
1053
+ /**
1054
+ * Helper function to create a new Request for redirect handling.
1055
+ * @param request The original request.
1056
+ * @param location The redirect location.
1057
+ * @param body The request body as ArrayBuffer or null.
1058
+ * @returns A new Request object for the redirect.
1059
+ */
1060
+ function createRedirectRequest(request, location, body) {
1061
+ const url = new URL(location, request.url);
1062
+ return new Request(url, {
1063
+ method: request.method,
1064
+ headers: request.headers,
1065
+ body,
1066
+ redirect: "manual",
1067
+ signal: request.signal,
1068
+ mode: request.mode,
1069
+ credentials: request.credentials,
1070
+ referrer: request.referrer,
1071
+ referrerPolicy: request.referrerPolicy,
1072
+ integrity: request.integrity,
1073
+ keepalive: request.keepalive,
1074
+ cache: request.cache
1075
+ });
1076
+ }
1077
+ /**
1078
+ * Performs a double-knock request to the given URL. For the details of
1079
+ * double-knocking, see
1080
+ * <https://swicg.github.io/activitypub-http-signature/#how-to-upgrade-supported-versions>.
1081
+ * @param request The request to send.
1082
+ * @param identity The identity to use for signing the request.
1083
+ * @param options The options for double-knock requests.
1084
+ * @returns The response to the request.
1085
+ * @since 1.6.0
1086
+ */
1087
+ async function doubleKnock(request, identity, options = {}) {
1088
+ const { specDeterminer, log, tracerProvider, signal } = options;
1089
+ const origin = new URL(request.url).origin;
1090
+ const firstTrySpec = specDeterminer == null ? "rfc9421" : await specDeterminer.determineSpec(origin);
1091
+ const body = options.body !== void 0 ? options.body : request.method !== "GET" && request.method !== "HEAD" ? await request.clone().arrayBuffer() : null;
1092
+ let signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
1093
+ spec: firstTrySpec,
1094
+ tracerProvider,
1095
+ body
1096
+ });
1097
+ log?.(signedRequest);
1098
+ let response = await fetch(signedRequest, {
1099
+ redirect: "manual",
1100
+ signal
1101
+ });
1102
+ if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
1103
+ const location = response.headers.get("Location");
1104
+ return doubleKnock(createRedirectRequest(request, location, body), identity, {
1105
+ ...options,
1106
+ body
1107
+ });
1108
+ } else if (response.status === 400 || response.status === 401 || response.status > 401) {
1109
+ const spec = firstTrySpec === "draft-cavage-http-signatures-12" ? "rfc9421" : "draft-cavage-http-signatures-12";
1110
+ (0, __logtape_logtape.getLogger)([
1111
+ "fedify",
1112
+ "sig",
1113
+ "http"
1114
+ ]).debug("Failed to verify with the spec {spec} ({status} {statusText}); retrying with spec {secondSpec}... (double-knocking)", {
1115
+ spec: firstTrySpec,
1116
+ secondSpec: spec,
1117
+ status: response.status,
1118
+ statusText: response.statusText
1119
+ });
1120
+ signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
1121
+ spec,
1122
+ tracerProvider,
1123
+ body
1124
+ });
1125
+ log?.(signedRequest);
1126
+ response = await fetch(signedRequest, {
1127
+ redirect: "manual",
1128
+ signal
1129
+ });
1130
+ if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
1131
+ const location = response.headers.get("Location");
1132
+ return doubleKnock(createRedirectRequest(request, location, body), identity, {
1133
+ ...options,
1134
+ body
1135
+ });
1136
+ } else if (response.status !== 400 && response.status !== 401) await specDeterminer?.rememberSpec(origin, spec);
1137
+ } else await specDeterminer?.rememberSpec(origin, firstTrySpec);
1138
+ return response;
1139
+ }
1140
+ /**
1141
+ * Performs a timing-safe equality comparison between two `Uint8Array` values.
1142
+ *
1143
+ * This function is designed to take a constant amount of time to execute,
1144
+ * dependent only on the length of the longer of the two arrays,
1145
+ * regardless of where the first difference in bytes occurs. This helps
1146
+ * prevent timing attacks.
1147
+ *
1148
+ * @param a The first bytes.
1149
+ * @param b The second bytes.
1150
+ * @returns `true` if the arrays are of the same length and contain the same
1151
+ * bytes, `false` otherwise.
1152
+ * @since 1.6.0
1153
+ */
1154
+ function timingSafeEqual(a, b) {
1155
+ const lenA = a.length;
1156
+ const lenB = b.length;
1157
+ const commonLength = Math.max(lenA, lenB);
1158
+ let result = 0;
1159
+ for (let i = 0; i < commonLength; i++) {
1160
+ const byteA = i < lenA ? a[i] : 0;
1161
+ const byteB = i < lenB ? b[i] : 0;
1162
+ result |= byteA ^ byteB;
1163
+ }
1164
+ result |= lenA ^ lenB;
1165
+ return result === 0;
1166
+ }
1167
+
1168
+ //#endregion
1169
+ Object.defineProperty(exports, 'deno_default', {
1170
+ enumerable: true,
1171
+ get: function () {
1172
+ return deno_default;
1173
+ }
1174
+ });
1175
+ Object.defineProperty(exports, 'doubleKnock', {
1176
+ enumerable: true,
1177
+ get: function () {
1178
+ return doubleKnock;
1179
+ }
1180
+ });
1181
+ Object.defineProperty(exports, 'exportJwk', {
1182
+ enumerable: true,
1183
+ get: function () {
1184
+ return exportJwk;
1185
+ }
1186
+ });
1187
+ Object.defineProperty(exports, 'fetchKey', {
1188
+ enumerable: true,
1189
+ get: function () {
1190
+ return fetchKey;
1191
+ }
1192
+ });
1193
+ Object.defineProperty(exports, 'generateCryptoKeyPair', {
1194
+ enumerable: true,
1195
+ get: function () {
1196
+ return generateCryptoKeyPair;
1197
+ }
1198
+ });
1199
+ Object.defineProperty(exports, 'importJwk', {
1200
+ enumerable: true,
1201
+ get: function () {
1202
+ return importJwk;
1203
+ }
1204
+ });
1205
+ Object.defineProperty(exports, 'signRequest', {
1206
+ enumerable: true,
1207
+ get: function () {
1208
+ return signRequest;
1209
+ }
1210
+ });
1211
+ Object.defineProperty(exports, 'validateCryptoKey', {
1212
+ enumerable: true,
1213
+ get: function () {
1214
+ return validateCryptoKey;
1215
+ }
1216
+ });
1217
+ Object.defineProperty(exports, 'verifyRequest', {
1218
+ enumerable: true,
1219
+ get: function () {
1220
+ return verifyRequest;
1221
+ }
1222
+ });