@fedify/fedify 2.0.0-dev.1485 → 2.0.0-dev.150

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 (311) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +38 -18
  3. package/dist/actor-Bhc5FasL.cjs +42079 -0
  4. package/dist/{actor-7ivEf1H3.js → actor-C6cDxaJJ.js} +4 -1
  5. package/dist/{actor-DXTdNCfp.js → actor-DPvScYuz.js} +7058 -2722
  6. package/dist/{actor-C22bXuuC.d.ts → actor-DqFajh9s.d.ts} +2 -2
  7. package/dist/actor-f2NtjyCg.d.cts +128 -0
  8. package/dist/{assert-MZs1qjMx.js → assert-Dp5_aoAs.js} +1 -1
  9. package/dist/{assert_instance_of-DHz7EHNU.js → assert_instance_of-D1m8F7x0.js} +1 -1
  10. package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals-B2R_8p36.js} +1 -1
  11. package/dist/{assert_rejects-DiIiJbZn.js → assert_rejects-BoKYY0g1.js} +2 -2
  12. package/dist/{assert_is_error-BPGph1Jx.js → assert_throws-DjkXin1a.js} +32 -2
  13. package/dist/{builder-BPGqEvtB.js → builder-DcDoTCBH.js} +20 -8
  14. package/dist/chunk-DqRYRqnO.cjs +34 -0
  15. package/dist/chunk-HsBuZ-b2.js +41 -0
  16. package/dist/client-94iWEfQa.d.cts +222 -0
  17. package/dist/{client-DF8anIB5.d.ts → client-BsGzbnV-.d.ts} +3 -75
  18. package/dist/{client-g2FDBoeY.js → client-CD87uCL_.js} +4 -23
  19. package/dist/compat/mod.cjs +10 -0
  20. package/dist/compat/mod.d.cts +11 -0
  21. package/dist/compat/mod.d.ts +10 -12
  22. package/dist/compat/mod.js +5 -5
  23. package/dist/compat/transformers.test.js +29 -24
  24. package/dist/compat-DmDDELst.cjs +4 -0
  25. package/dist/compat-nxUqe4Z-.js +4 -0
  26. package/dist/context-DBQ7nMCw.d.cts +2449 -0
  27. package/dist/context-DpN-0qNU.js +109 -0
  28. package/dist/{context-DmlbRh9p.d.ts → context-mM0Nu5yo.d.ts} +335 -134
  29. package/dist/deno-DHmnBq8X.js +131 -0
  30. package/dist/{testing-BG_8Fyas.js → dist-lStjlyET.js} +73 -114
  31. package/dist/{authdocloader-D_IvQE4z.js → docloader-C2QNrF7j.js} +17 -8
  32. package/dist/{esm-CPZhxxGc.js → esm-B52TuumP.js} +32 -17
  33. package/dist/federation/builder.test.js +16 -16
  34. package/dist/federation/collection.test.js +9 -12
  35. package/dist/federation/handler.test.js +123 -152
  36. package/dist/federation/idempotency.test.js +206 -0
  37. package/dist/federation/inbox.test.js +7 -7
  38. package/dist/federation/keycache.test.js +7 -8
  39. package/dist/federation/kv.test.js +64 -12
  40. package/dist/federation/middleware.test.js +281 -99
  41. package/dist/federation/mod.cjs +27 -0
  42. package/dist/federation/mod.d.cts +11 -0
  43. package/dist/federation/mod.d.ts +11 -13
  44. package/dist/federation/mod.js +13 -15
  45. package/dist/federation/mq.test.js +12 -13
  46. package/dist/federation/negotiation.test.js +25 -0
  47. package/dist/federation/retry.test.js +4 -6
  48. package/dist/federation/router.test.js +9 -11
  49. package/dist/federation/send.test.js +61 -18
  50. package/dist/federation-CoW-KDKv.cjs +266 -0
  51. package/dist/{federation-CMX7WzeL.js → federation-D0hkM4T7.js} +25 -3
  52. package/dist/{http-zsOxPKCt.js → http-B1d-Jhbj.js} +260 -10
  53. package/dist/{http-DqSNLFNY.d.ts → http-BbO0ejuk.d.ts} +2 -2
  54. package/dist/http-CS6iqtXa.cjs +1106 -0
  55. package/dist/http-M8k5mKc0.d.cts +253 -0
  56. package/dist/{http-C7rxW7Kh.js → http-b10BrywC.js} +4 -3
  57. package/dist/{inbox-eK2W2MF3.js → inbox-gPnuScsy.js} +26 -7
  58. package/dist/{key-CYOcZ9G5.js → key-W6YaI4J_.js} +4 -2
  59. package/dist/{keycache-BLq6GT4_.js → keycache-DkTZcjkH.js} +1 -1
  60. package/dist/{keys-BIwlbtMN.js → keys-CfcSjjys.js} +2 -1
  61. package/dist/{kv-C7sopW2E.d.ts → kv-BpJND1Hr.d.ts} +30 -1
  62. package/dist/{kv-CRZrzyXm.js → kv-DaWUKuhD.js} +22 -0
  63. package/dist/kv-cD_d4hg-.d.cts +110 -0
  64. package/dist/kv-cache-C6NrTtII.js +107 -0
  65. package/dist/kv-cache-DhRe6qxQ.js +122 -0
  66. package/dist/kv-cache-a7LD3ze0.cjs +134 -0
  67. package/dist/{ld-DWwLYT4e.js → ld-UYagkye9.js} +7 -4
  68. package/dist/lookup-C-ajaa9S.js +256 -0
  69. package/dist/{lookup-DNQyH8UQ.js → lookup-CjgzNtAk.js} +33 -125
  70. package/dist/lookup-DI7YTXtl.cjs +268 -0
  71. package/dist/{lookup-BHYMosdS.js → lookup-DP8Hm9oD.js} +3 -1
  72. package/dist/middleware-Botvlnr6.js +31 -0
  73. package/dist/{middleware-DakCaqXu.js → middleware-C2V0Hmj1.js} +105 -188
  74. package/dist/middleware-D5o8ITlx.cjs +4237 -0
  75. package/dist/middleware-ESmU0CBL.cjs +15 -0
  76. package/dist/middleware-JqrIzuk6.js +15 -0
  77. package/dist/{middleware-BcVqlHyD.js → middleware-V7PNM-lv.js} +143 -136
  78. package/dist/mod-B-hUPT2N.d.cts +1 -0
  79. package/dist/{mod-Cxt4Kpf6.d.ts → mod-BlVovdcy.d.ts} +20 -2
  80. package/dist/mod-BxRCHTz-.d.cts +307 -0
  81. package/dist/mod-C58MZ7Wx.d.cts +113 -0
  82. package/dist/mod-CAdoBu0x.d.ts +109 -0
  83. package/dist/mod-CcDPcLJW.d.cts +1 -0
  84. package/dist/{mod-Drmz72EK.d.ts → mod-D5Z2tISD.d.ts} +3 -3
  85. package/dist/mod-DgxG-byT.d.cts +266 -0
  86. package/dist/{lookup-3czM5mmU.d.ts → mod-Ds0mpFZU.d.ts} +9 -2
  87. package/dist/mod-Dy2fJtmN.d.cts +80 -0
  88. package/dist/{mod-0EysZ-dJ.d.ts → mod-GetHzY6F.d.ts} +2 -2
  89. package/dist/mod-fxr25Gv7.d.cts +107 -0
  90. package/dist/mod.cjs +137 -0
  91. package/dist/mod.d.cts +15 -0
  92. package/dist/mod.d.ts +15 -18
  93. package/dist/mod.js +19 -21
  94. package/dist/negotiation-B4NJHk1f.js +71 -0
  95. package/dist/nodeinfo/client.test.js +32 -114
  96. package/dist/nodeinfo/handler.test.js +35 -30
  97. package/dist/nodeinfo/mod.cjs +10 -0
  98. package/dist/nodeinfo/mod.d.cts +3 -0
  99. package/dist/nodeinfo/mod.d.ts +3 -5
  100. package/dist/nodeinfo/mod.js +6 -7
  101. package/dist/nodeinfo/types.test.js +10 -18
  102. package/dist/nodeinfo-BnthBobC.js +4 -0
  103. package/dist/nodeinfo-CdN0rEnZ.cjs +4 -0
  104. package/dist/otel/exporter.test.js +899 -0
  105. package/dist/otel/mod.cjs +262 -0
  106. package/dist/otel/mod.d.cts +230 -0
  107. package/dist/otel/mod.d.ts +232 -0
  108. package/dist/otel/mod.js +261 -0
  109. package/dist/owner-B4HbyP8s.d.cts +67 -0
  110. package/dist/{owner-smArESGi.js → owner-DgNCw_Z-.js} +46 -8
  111. package/dist/{owner-CQPnQVtf.d.ts → owner-kQRGVXG1.d.ts} +3 -3
  112. package/dist/{proof-C6z-uqeO.js → proof-BwleRoo3.js} +5 -3
  113. package/dist/proof-M11sS3Oq.cjs +710 -0
  114. package/dist/{proof-CT1SITRP.js → proof-TlLZC_r7.js} +53 -16
  115. package/dist/router-CVRQXlZi.js +118 -0
  116. package/dist/{send-1zdmNlUo.js → send-BMU9B7Sm.js} +9 -4
  117. package/dist/sig/http.test.js +19 -17
  118. package/dist/sig/key.test.js +15 -14
  119. package/dist/sig/ld.test.js +13 -12
  120. package/dist/sig/mod.cjs +28 -0
  121. package/dist/sig/mod.d.cts +6 -0
  122. package/dist/sig/mod.d.ts +5 -7
  123. package/dist/sig/mod.js +8 -10
  124. package/dist/sig/owner.test.js +40 -15
  125. package/dist/sig/proof.test.js +19 -17
  126. package/dist/sig-C34-oHBl.js +4 -0
  127. package/dist/sig-YYj5tCnr.cjs +4 -0
  128. package/dist/{std__assert-X-_kMxKM.js → std__assert-Cm-MfI66.js} +1 -1
  129. package/dist/testing/mod.d.ts +410 -232
  130. package/dist/testing/mod.js +9 -4
  131. package/dist/{transformers-Dna8Fg7k.js → transformers-BFT6d7J5.js} +3 -3
  132. package/dist/transformers-CoBS-oFG.cjs +116 -0
  133. package/dist/type-BSNcIxTd.js +14 -0
  134. package/dist/{types-BzyGRkRt.js → types-BtUjyi5y.js} +9 -170
  135. package/dist/types-CWgzGaqk.cjs +315 -0
  136. package/dist/{types-BIgY6c-l.js → types-D2jhK2VG.js} +1 -3
  137. package/dist/{runtime/authdocloader.test.js → utils/docloader.test.js} +20 -18
  138. package/dist/utils/kv-cache.test.js +211 -0
  139. package/dist/utils/mod.cjs +12 -0
  140. package/dist/utils/mod.d.cts +5 -0
  141. package/dist/utils/mod.d.ts +7 -0
  142. package/dist/utils/mod.js +11 -0
  143. package/dist/utils-D-Va7aXC.js +4 -0
  144. package/dist/utils-DyRU1gdZ.cjs +4 -0
  145. package/dist/vocab/actor.test.js +15 -13
  146. package/dist/vocab/lookup.test.js +285 -12
  147. package/dist/vocab/mod.cjs +86 -0
  148. package/dist/vocab/mod.d.cts +4 -0
  149. package/dist/vocab/mod.d.ts +3 -5
  150. package/dist/vocab/mod.js +6 -7
  151. package/dist/vocab/type.test.js +4 -4
  152. package/dist/vocab/vocab.test.js +8058 -1987
  153. package/dist/{vocab-SOE1ifCr.d.ts → vocab-BCWe1Ih5.d.ts} +292 -21
  154. package/dist/vocab-CeDBzu-f.d.cts +14903 -0
  155. package/dist/{type-I68qwqmo.js → vocab-Durhw0Gx.js} +6947 -7381
  156. package/dist/{vocab-Bg1J3mu4.js → vocab-NOF1dCjQ.js} +32 -18
  157. package/dist/vocab-Vw1RxMp6.cjs +296 -0
  158. package/dist/webfinger/handler.test.js +62 -29
  159. package/dist/webfinger/lookup.test.js +11 -12
  160. package/dist/webfinger/mod.cjs +8 -0
  161. package/dist/webfinger/mod.d.cts +2 -0
  162. package/dist/webfinger/mod.d.ts +1 -4
  163. package/dist/webfinger/mod.js +5 -6
  164. package/dist/webfinger-C72Y8lrh.js +4 -0
  165. package/dist/webfinger-vAtLmxOF.cjs +4 -0
  166. package/package.json +81 -45
  167. package/dist/assert_throws-BOO88avQ.js +0 -39
  168. package/dist/authdocloader-Bq0gEHRj.js +0 -52
  169. package/dist/compat-Bb5myD13.js +0 -4
  170. package/dist/denokv-Bv33Xxea.js +0 -57
  171. package/dist/docloader-BlVueewg.js +0 -4615
  172. package/dist/docloader-CxWcuWqQ.d.ts +0 -221
  173. package/dist/fixtures/activitypub.academy/users/brauca_darradiul.json +0 -83
  174. package/dist/fixtures/example.com/announce.json +0 -6
  175. package/dist/fixtures/example.com/collection.json +0 -19
  176. package/dist/fixtures/example.com/create.json +0 -6
  177. package/dist/fixtures/example.com/cross-origin-actor.json +0 -6
  178. package/dist/fixtures/example.com/hong-gildong.json +0 -11
  179. package/dist/fixtures/example.com/invite.json +0 -7
  180. package/dist/fixtures/example.com/key.json +0 -7
  181. package/dist/fixtures/example.com/key2.json +0 -6
  182. package/dist/fixtures/example.com/object.json +0 -6
  183. package/dist/fixtures/example.com/orderedcollectionpage.json +0 -24
  184. package/dist/fixtures/example.com/paged/a.json +0 -13
  185. package/dist/fixtures/example.com/paged/b.json +0 -16
  186. package/dist/fixtures/example.com/paged-collection.json +0 -6
  187. package/dist/fixtures/example.com/person.json +0 -22
  188. package/dist/fixtures/example.com/person2.json +0 -40
  189. package/dist/fixtures/example.com/test.json +0 -5
  190. package/dist/fixtures/example.com/users/handle.json +0 -16
  191. package/dist/fixtures/example.com/wrong-type.json +0 -3
  192. package/dist/fixtures/oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd.json +0 -24
  193. package/dist/fixtures/remote.domain/users/bob.json +0 -20
  194. package/dist/fixtures/server.example/users/alice.json +0 -20
  195. package/dist/fixtures/w3id.org/identity/v1.json +0 -152
  196. package/dist/fixtures/w3id.org/security/data-integrity/v1.json +0 -74
  197. package/dist/fixtures/w3id.org/security/multikey/v1.json +0 -35
  198. package/dist/fixtures/w3id.org/security/v1.json +0 -50
  199. package/dist/fixtures/wizard.casa/users/hongminhee.json +0 -69
  200. package/dist/fixtures/www.w3.org/ns/activitystreams.json +0 -379
  201. package/dist/fixtures/www.w3.org/ns/did/v1.json +0 -58
  202. package/dist/key-Dn7Lram-.js +0 -260
  203. package/dist/key-S7WllAWz.js +0 -10
  204. package/dist/key-rRCUafNm.js +0 -10
  205. package/dist/middleware-CWbGhXnl.js +0 -26
  206. package/dist/middleware-D-OlNiyj.js +0 -17
  207. package/dist/mod-TFoH2Ql8.d.ts +0 -104
  208. package/dist/mod-g0xFzAP9.d.ts +0 -2
  209. package/dist/mq-CRGm1e_F.d.ts +0 -143
  210. package/dist/nodeinfo/semver.test.js +0 -143
  211. package/dist/nodeinfo-CyEbLjHs.js +0 -4
  212. package/dist/runtime/docloader.test.js +0 -522
  213. package/dist/runtime/key.test.js +0 -103
  214. package/dist/runtime/langstr.test.d.ts +0 -3
  215. package/dist/runtime/langstr.test.js +0 -39
  216. package/dist/runtime/mod.d.ts +0 -8
  217. package/dist/runtime/mod.js +0 -13
  218. package/dist/runtime/multibase/multibase.test.d.ts +0 -3
  219. package/dist/runtime/multibase/multibase.test.js +0 -358
  220. package/dist/runtime/url.test.d.ts +0 -3
  221. package/dist/runtime/url.test.js +0 -45
  222. package/dist/runtime-BSkOVUWM.js +0 -4
  223. package/dist/semver-dArNLkR9.js +0 -149
  224. package/dist/sig-BXJO--F9.js +0 -4
  225. package/dist/src/vocab/accept.yaml +0 -15
  226. package/dist/src/vocab/activity.yaml +0 -98
  227. package/dist/src/vocab/add.yaml +0 -16
  228. package/dist/src/vocab/announce.yaml +0 -30
  229. package/dist/src/vocab/application.yaml +0 -324
  230. package/dist/src/vocab/arrive.yaml +0 -15
  231. package/dist/src/vocab/article.yaml +0 -46
  232. package/dist/src/vocab/audio.yaml +0 -11
  233. package/dist/src/vocab/block.yaml +0 -16
  234. package/dist/src/vocab/chatmessage.yaml +0 -50
  235. package/dist/src/vocab/collection.yaml +0 -154
  236. package/dist/src/vocab/collectionpage.yaml +0 -55
  237. package/dist/src/vocab/create.yaml +0 -28
  238. package/dist/src/vocab/dataintegrityproof.yaml +0 -56
  239. package/dist/src/vocab/delete.yaml +0 -27
  240. package/dist/src/vocab/didservice.yaml +0 -22
  241. package/dist/src/vocab/dislike.yaml +0 -14
  242. package/dist/src/vocab/document.yaml +0 -31
  243. package/dist/src/vocab/emoji.yaml +0 -12
  244. package/dist/src/vocab/emojireact.yaml +0 -17
  245. package/dist/src/vocab/endpoints.yaml +0 -85
  246. package/dist/src/vocab/event.yaml +0 -11
  247. package/dist/src/vocab/export.yaml +0 -9
  248. package/dist/src/vocab/flag.yaml +0 -15
  249. package/dist/src/vocab/follow.yaml +0 -19
  250. package/dist/src/vocab/group.yaml +0 -324
  251. package/dist/src/vocab/hashtag.yaml +0 -14
  252. package/dist/src/vocab/ignore.yaml +0 -14
  253. package/dist/src/vocab/image.yaml +0 -9
  254. package/dist/src/vocab/intransitiveactivity.yaml +0 -15
  255. package/dist/src/vocab/invite.yaml +0 -14
  256. package/dist/src/vocab/join.yaml +0 -14
  257. package/dist/src/vocab/key.yaml +0 -28
  258. package/dist/src/vocab/leave.yaml +0 -14
  259. package/dist/src/vocab/like.yaml +0 -16
  260. package/dist/src/vocab/link.yaml +0 -101
  261. package/dist/src/vocab/listen.yaml +0 -12
  262. package/dist/src/vocab/mention.yaml +0 -9
  263. package/dist/src/vocab/move.yaml +0 -15
  264. package/dist/src/vocab/multikey.yaml +0 -36
  265. package/dist/src/vocab/note.yaml +0 -48
  266. package/dist/src/vocab/object.yaml +0 -404
  267. package/dist/src/vocab/offer.yaml +0 -15
  268. package/dist/src/vocab/orderedcollection.yaml +0 -39
  269. package/dist/src/vocab/orderedcollectionpage.yaml +0 -50
  270. package/dist/src/vocab/organization.yaml +0 -324
  271. package/dist/src/vocab/page.yaml +0 -11
  272. package/dist/src/vocab/person.yaml +0 -324
  273. package/dist/src/vocab/place.yaml +0 -75
  274. package/dist/src/vocab/profile.yaml +0 -26
  275. package/dist/src/vocab/propertyvalue.yaml +0 -32
  276. package/dist/src/vocab/question.yaml +0 -103
  277. package/dist/src/vocab/read.yaml +0 -13
  278. package/dist/src/vocab/reject.yaml +0 -14
  279. package/dist/src/vocab/relationship.yaml +0 -52
  280. package/dist/src/vocab/remove.yaml +0 -14
  281. package/dist/src/vocab/service.yaml +0 -324
  282. package/dist/src/vocab/source.yaml +0 -26
  283. package/dist/src/vocab/tentativeaccept.yaml +0 -14
  284. package/dist/src/vocab/tentativereject.yaml +0 -14
  285. package/dist/src/vocab/tombstone.yaml +0 -24
  286. package/dist/src/vocab/travel.yaml +0 -16
  287. package/dist/src/vocab/undo.yaml +0 -26
  288. package/dist/src/vocab/update.yaml +0 -58
  289. package/dist/src/vocab/video.yaml +0 -11
  290. package/dist/src/vocab/view.yaml +0 -13
  291. package/dist/testing/docloader.test.js +0 -24
  292. package/dist/vocab/schema.yaml +0 -247
  293. package/dist/webfinger-C3GIyXIg.js +0 -4
  294. package/dist/x/cfworkers.d.ts +0 -61
  295. package/dist/x/cfworkers.js +0 -98
  296. package/dist/x/cfworkers.test.d.ts +0 -3
  297. package/dist/x/cfworkers.test.js +0 -179
  298. package/dist/x/hono.d.ts +0 -56
  299. package/dist/x/hono.js +0 -60
  300. package/dist/x/sveltekit.d.ts +0 -48
  301. package/dist/x/sveltekit.js +0 -68
  302. /package/dist/{assert_equals-DSbWqCm3.js → assert_equals-Gbplq4lg.js} +0 -0
  303. /package/dist/{collection-CSzG2j1P.js → collection-CrkRM5Ep.js} +0 -0
  304. /package/dist/{nodeinfo/semver.test.d.ts → federation/idempotency.test.d.ts} +0 -0
  305. /package/dist/{runtime/authdocloader.test.d.ts → federation/negotiation.test.d.ts} +0 -0
  306. /package/dist/{mod-1pDWKvUL.d.ts → mod-CVgZgliM.d.ts} +0 -0
  307. /package/dist/{mod-GIh5OYxW.d.ts → mod-bjzj5QIb.d.ts} +0 -0
  308. /package/dist/{runtime/docloader.test.d.ts → otel/exporter.test.d.ts} +0 -0
  309. /package/dist/{retry-D4GJ670a.js → retry-Bz5pP75o.js} +0 -0
  310. /package/dist/{testing → utils}/docloader.test.d.ts +0 -0
  311. /package/dist/{runtime/key.test.d.ts → utils/kv-cache.test.d.ts} +0 -0
@@ -3,8 +3,6 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { formatSemVer } from "./semver-dArNLkR9.js";
7
-
8
6
  //#region src/nodeinfo/types.ts
9
7
  /**
10
8
  * Converts a {@link NodeInfo} object to a JSON value.
@@ -25,7 +23,7 @@ function nodeInfoToJson(nodeInfo) {
25
23
  version: "2.1",
26
24
  software: {
27
25
  name: nodeInfo.software.name,
28
- version: formatSemVer(nodeInfo.software.version),
26
+ version: nodeInfo.software.version,
29
27
  repository: nodeInfo.software.repository?.href,
30
28
  homepage: nodeInfo.software.homepage?.href
31
29
  },
@@ -3,25 +3,27 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { UrlError } from "../type-I68qwqmo.js";
7
- import { assertEquals } from "../assert_equals-DSbWqCm3.js";
8
- import "../assert-MZs1qjMx.js";
9
- import "../assert_instance_of-DHz7EHNU.js";
10
- import "../lookup-DNQyH8UQ.js";
11
- import "../actor-7ivEf1H3.js";
12
- import "../key-CYOcZ9G5.js";
13
- import { verifyRequest } from "../http-C7rxW7Kh.js";
14
- import { getAuthenticatedDocumentLoader } from "../authdocloader-D_IvQE4z.js";
15
- import { mockDocumentLoader, test } from "../testing-BG_8Fyas.js";
16
- import "../std__assert-X-_kMxKM.js";
17
- import { assertRejects } from "../assert_rejects-DiIiJbZn.js";
18
- import "../assert_is_error-BPGph1Jx.js";
19
- import "../assert_not_equals-f3m3epl3.js";
20
- import "../assert_throws-BOO88avQ.js";
21
- import { rsaPrivateKey2 } from "../keys-BIwlbtMN.js";
22
- import { esm_default } from "../esm-CPZhxxGc.js";
6
+ import { mockDocumentLoader, test } from "../dist-lStjlyET.js";
7
+ import { assertEquals } from "../assert_equals-Gbplq4lg.js";
8
+ import "../assert-Dp5_aoAs.js";
9
+ import "../assert_instance_of-D1m8F7x0.js";
10
+ import "../deno-DHmnBq8X.js";
11
+ import "../vocab-Durhw0Gx.js";
12
+ import "../lookup-DP8Hm9oD.js";
13
+ import "../type-BSNcIxTd.js";
14
+ import "../actor-C6cDxaJJ.js";
15
+ import "../key-W6YaI4J_.js";
16
+ import { verifyRequest } from "../http-b10BrywC.js";
17
+ import { getAuthenticatedDocumentLoader } from "../docloader-C2QNrF7j.js";
18
+ import "../std__assert-Cm-MfI66.js";
19
+ import { assertRejects } from "../assert_rejects-BoKYY0g1.js";
20
+ import "../assert_throws-DjkXin1a.js";
21
+ import "../assert_not_equals-B2R_8p36.js";
22
+ import { rsaPrivateKey2 } from "../keys-CfcSjjys.js";
23
+ import { esm_default } from "../esm-B52TuumP.js";
24
+ import { UrlError } from "@fedify/vocab-runtime";
23
25
 
24
- //#region src/runtime/authdocloader.test.ts
26
+ //#region src/utils/docloader.test.ts
25
27
  test("getAuthenticatedDocumentLoader()", async (t) => {
26
28
  esm_default.spyGlobal();
27
29
  esm_default.get("begin:https://example.com/object", async (cl) => {
@@ -0,0 +1,211 @@
1
+
2
+ import { Temporal } from "@js-temporal/polyfill";
3
+ import { URLPattern } from "urlpattern-polyfill";
4
+ globalThis.addEventListener = () => {};
5
+
6
+ import { mockDocumentLoader, test } from "../dist-lStjlyET.js";
7
+ import { MockKvStore, kvCache } from "../kv-cache-C6NrTtII.js";
8
+ import { preloadedContexts } from "@fedify/vocab-runtime";
9
+ import { deepStrictEqual, throws } from "node:assert";
10
+
11
+ //#region src/utils/kv-cache.test.ts
12
+ test("kvCache()", async (t) => {
13
+ const kv = new MockKvStore();
14
+ await t.step("cached", async () => {
15
+ const loader = kvCache({
16
+ kv,
17
+ loader: mockDocumentLoader,
18
+ rules: [
19
+ ["https://example.org/", Temporal.Duration.from({ days: 1 })],
20
+ [new URL("https://example.net/"), Temporal.Duration.from({ days: 1 })],
21
+ [new URLPattern("https://example.com/*"), Temporal.Duration.from({ days: 30 })]
22
+ ],
23
+ prefix: ["_test", "cached"]
24
+ });
25
+ const result = await loader("https://example.com/object");
26
+ deepStrictEqual(result, {
27
+ contextUrl: null,
28
+ documentUrl: "https://example.com/object",
29
+ document: {
30
+ "@context": "https://www.w3.org/ns/activitystreams",
31
+ id: "https://example.com/object",
32
+ name: "Fetched object",
33
+ type: "Object"
34
+ }
35
+ });
36
+ const cache = await kv.get([
37
+ "_test",
38
+ "cached",
39
+ "https://example.com/object"
40
+ ]);
41
+ deepStrictEqual(cache, result);
42
+ await kv.set([
43
+ "_test",
44
+ "cached",
45
+ "https://example.org/"
46
+ ], {
47
+ contextUrl: null,
48
+ documentUrl: "https://example.org/",
49
+ document: { "id": "https://example.org/" }
50
+ });
51
+ const result2 = await loader("https://example.org/");
52
+ deepStrictEqual(result2, {
53
+ contextUrl: null,
54
+ documentUrl: "https://example.org/",
55
+ document: { "id": "https://example.org/" }
56
+ });
57
+ await kv.set([
58
+ "_test",
59
+ "cached",
60
+ "https://example.net/"
61
+ ], {
62
+ contextUrl: null,
63
+ documentUrl: "https://example.net/",
64
+ document: { "id": "https://example.net/" }
65
+ });
66
+ const result3 = await loader("https://example.net/");
67
+ deepStrictEqual(result3, {
68
+ contextUrl: null,
69
+ documentUrl: "https://example.net/",
70
+ document: { "id": "https://example.net/" }
71
+ });
72
+ });
73
+ await t.step("not cached", async () => {
74
+ const loader = kvCache({
75
+ kv,
76
+ loader: mockDocumentLoader,
77
+ rules: [],
78
+ prefix: ["_test", "not cached"]
79
+ });
80
+ const result = await loader("https://example.com/object");
81
+ deepStrictEqual(result, {
82
+ contextUrl: null,
83
+ documentUrl: "https://example.com/object",
84
+ document: {
85
+ "@context": "https://www.w3.org/ns/activitystreams",
86
+ id: "https://example.com/object",
87
+ name: "Fetched object",
88
+ type: "Object"
89
+ }
90
+ });
91
+ const cache = await kv.get([
92
+ "test2",
93
+ "not cached",
94
+ "https://example.com/object"
95
+ ]);
96
+ deepStrictEqual(cache, void 0);
97
+ });
98
+ await t.step("maximum cache duration", () => {
99
+ throws(() => kvCache({
100
+ kv,
101
+ loader: mockDocumentLoader,
102
+ rules: [["https://example.com/", Temporal.Duration.from({
103
+ days: 30,
104
+ seconds: 1
105
+ })]]
106
+ }), TypeError, "The maximum cache duration is 30 days");
107
+ throws(() => kvCache({
108
+ kv,
109
+ loader: mockDocumentLoader,
110
+ rules: [[new URLPattern("https://example.com/*"), Temporal.Duration.from({
111
+ days: 30,
112
+ seconds: 1
113
+ })]]
114
+ }), TypeError, "The maximum cache duration is 30 days");
115
+ });
116
+ await t.step("on kv store exception", async () => {
117
+ class KvStoreThrowsException {
118
+ get(_key) {
119
+ throw new Error("Failed to get key");
120
+ }
121
+ set(_key, _value, _options) {
122
+ throw new Error("Failed to set key");
123
+ }
124
+ delete(_key) {
125
+ throw new Error("Failed to delete key");
126
+ }
127
+ async *list(_prefix) {
128
+ throw new Error("Failed to list keys");
129
+ }
130
+ }
131
+ const loader = kvCache({
132
+ kv: new KvStoreThrowsException(),
133
+ loader: mockDocumentLoader,
134
+ rules: [
135
+ ["https://example.org/", Temporal.Duration.from({ days: 1 })],
136
+ [new URL("https://example.net/"), Temporal.Duration.from({ days: 1 })],
137
+ [new URLPattern("https://example.com/*"), Temporal.Duration.from({ days: 30 })]
138
+ ],
139
+ prefix: ["_test", "not cached"]
140
+ });
141
+ const result = await loader("https://example.com/object");
142
+ deepStrictEqual(result, {
143
+ contextUrl: null,
144
+ documentUrl: "https://example.com/object",
145
+ document: {
146
+ "@context": "https://www.w3.org/ns/activitystreams",
147
+ id: "https://example.com/object",
148
+ name: "Fetched object",
149
+ type: "Object"
150
+ }
151
+ });
152
+ });
153
+ await t.step("preloaded contexts bypass cache", async () => {
154
+ const kv$1 = new MockKvStore();
155
+ let loaderCalled = false;
156
+ const mockLoader = (url) => {
157
+ loaderCalled = true;
158
+ return Promise.resolve({
159
+ contextUrl: null,
160
+ documentUrl: url,
161
+ document: { "mock": "document" }
162
+ });
163
+ };
164
+ const loader = kvCache({
165
+ kv: kv$1,
166
+ loader: mockLoader,
167
+ prefix: ["_test", "preloaded"]
168
+ });
169
+ const activityStreamsUrl = "https://www.w3.org/ns/activitystreams";
170
+ loaderCalled = false;
171
+ const result = await loader(activityStreamsUrl);
172
+ deepStrictEqual(result, {
173
+ contextUrl: null,
174
+ documentUrl: activityStreamsUrl,
175
+ document: preloadedContexts[activityStreamsUrl]
176
+ });
177
+ deepStrictEqual(loaderCalled, false, "Loader should not be called for preloaded contexts");
178
+ const cachedValue = await kv$1.get([
179
+ "_test",
180
+ "preloaded",
181
+ activityStreamsUrl
182
+ ]);
183
+ deepStrictEqual(cachedValue, void 0, "Preloaded contexts should not be cached in KV store");
184
+ const securityUrl = "https://w3id.org/security/v1";
185
+ loaderCalled = false;
186
+ const result2 = await loader(securityUrl);
187
+ deepStrictEqual(result2, {
188
+ contextUrl: null,
189
+ documentUrl: securityUrl,
190
+ document: preloadedContexts[securityUrl]
191
+ });
192
+ deepStrictEqual(loaderCalled, false, "Loader should not be called for preloaded contexts");
193
+ const nonPreloadedUrl = "https://example.com/not-preloaded";
194
+ loaderCalled = false;
195
+ const result3 = await loader(nonPreloadedUrl);
196
+ deepStrictEqual(result3, {
197
+ contextUrl: null,
198
+ documentUrl: nonPreloadedUrl,
199
+ document: { "mock": "document" }
200
+ });
201
+ deepStrictEqual(loaderCalled, true, "Loader should be called for non-preloaded URLs");
202
+ const cachedValue2 = await kv$1.get([
203
+ "_test",
204
+ "preloaded",
205
+ nonPreloadedUrl
206
+ ]);
207
+ deepStrictEqual(cachedValue2, result3, "Non-preloaded URLs should be cached");
208
+ });
209
+ });
210
+
211
+ //#endregion
@@ -0,0 +1,12 @@
1
+
2
+ const { Temporal } = require("@js-temporal/polyfill");
3
+ const { URLPattern } = require("urlpattern-polyfill");
4
+
5
+ require('../lookup-DI7YTXtl.cjs');
6
+ require('../actor-Bhc5FasL.cjs');
7
+ require('../http-CS6iqtXa.cjs');
8
+ const require_kv_cache = require('../kv-cache-a7LD3ze0.cjs');
9
+ require('../utils-DyRU1gdZ.cjs');
10
+
11
+ exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
12
+ exports.kvCache = require_kv_cache.kvCache;
@@ -0,0 +1,5 @@
1
+ import "../vocab-CeDBzu-f.cjs";
2
+ import "../http-M8k5mKc0.cjs";
3
+ import "../kv-cD_d4hg-.cjs";
4
+ import { getAuthenticatedDocumentLoader, kvCache } from "../mod-fxr25Gv7.cjs";
5
+ export { getAuthenticatedDocumentLoader, kvCache };
@@ -0,0 +1,7 @@
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ import { URLPattern } from "urlpattern-polyfill";
3
+ import "../vocab-BCWe1Ih5.js";
4
+ import "../http-BbO0ejuk.js";
5
+ import "../kv-BpJND1Hr.js";
6
+ import { getAuthenticatedDocumentLoader, kvCache } from "../mod-CAdoBu0x.js";
7
+ export { getAuthenticatedDocumentLoader, kvCache };
@@ -0,0 +1,11 @@
1
+
2
+ import { Temporal } from "@js-temporal/polyfill";
3
+ import { URLPattern } from "urlpattern-polyfill";
4
+
5
+ import "../lookup-C-ajaa9S.js";
6
+ import "../actor-DPvScYuz.js";
7
+ import "../http-B1d-Jhbj.js";
8
+ import { getAuthenticatedDocumentLoader, kvCache } from "../kv-cache-DhRe6qxQ.js";
9
+ import "../utils-D-Va7aXC.js";
10
+
11
+ export { getAuthenticatedDocumentLoader, kvCache };
@@ -0,0 +1,4 @@
1
+
2
+ import { Temporal } from "@js-temporal/polyfill";
3
+ import { URLPattern } from "urlpattern-polyfill";
4
+
@@ -0,0 +1,4 @@
1
+
2
+ const { Temporal } = require("@js-temporal/polyfill");
3
+ const { URLPattern } = require("urlpattern-polyfill");
4
+
@@ -3,19 +3,21 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Application, Group, Organization, Person, Service, __export } from "../type-I68qwqmo.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 "../lookup-DNQyH8UQ.js";
11
- import { getActorClassByTypeName, getActorHandle, getActorTypeName, isActor, normalizeActorHandle } from "../actor-7ivEf1H3.js";
12
- import { test } from "../testing-BG_8Fyas.js";
13
- import { assertStrictEquals } from "../std__assert-X-_kMxKM.js";
14
- import { assertFalse, assertRejects } from "../assert_rejects-DiIiJbZn.js";
15
- import "../assert_is_error-BPGph1Jx.js";
16
- import "../assert_not_equals-f3m3epl3.js";
17
- import { assertThrows } from "../assert_throws-BOO88avQ.js";
18
- import { esm_default } from "../esm-CPZhxxGc.js";
6
+ import { __export } from "../chunk-HsBuZ-b2.js";
7
+ import { test } from "../dist-lStjlyET.js";
8
+ import { assertEquals } from "../assert_equals-Gbplq4lg.js";
9
+ import { assert } from "../assert-Dp5_aoAs.js";
10
+ import "../assert_instance_of-D1m8F7x0.js";
11
+ import "../deno-DHmnBq8X.js";
12
+ import { Application, Group, Organization, Person, Service } from "../vocab-Durhw0Gx.js";
13
+ import "../lookup-DP8Hm9oD.js";
14
+ import "../type-BSNcIxTd.js";
15
+ import { getActorClassByTypeName, getActorHandle, getActorTypeName, isActor, normalizeActorHandle } from "../actor-C6cDxaJJ.js";
16
+ import { assertStrictEquals } from "../std__assert-Cm-MfI66.js";
17
+ import { assertFalse, assertRejects } from "../assert_rejects-BoKYY0g1.js";
18
+ import { assertThrows } from "../assert_throws-DjkXin1a.js";
19
+ import "../assert_not_equals-B2R_8p36.js";
20
+ import { esm_default } from "../esm-B52TuumP.js";
19
21
 
20
22
  //#region ../../node_modules/.pnpm/fast-check@3.23.2/node_modules/fast-check/lib/esm/check/precondition/PreconditionFailure.js
21
23
  var PreconditionFailure = class PreconditionFailure extends Error {
@@ -3,18 +3,20 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Collection, Note, Object as Object$1, Person } from "../type-I68qwqmo.js";
7
- import { assertEquals } from "../assert_equals-DSbWqCm3.js";
8
- import "../assert-MZs1qjMx.js";
9
- import { assertInstanceOf } from "../assert_instance_of-DHz7EHNU.js";
10
- import { lookupObject, traverseCollection } from "../lookup-DNQyH8UQ.js";
11
- import { mockDocumentLoader, test } from "../testing-BG_8Fyas.js";
12
- import "../std__assert-X-_kMxKM.js";
13
- import "../assert_rejects-DiIiJbZn.js";
14
- import "../assert_is_error-BPGph1Jx.js";
15
- import "../assert_not_equals-f3m3epl3.js";
16
- import "../assert_throws-BOO88avQ.js";
17
- import { esm_default } from "../esm-CPZhxxGc.js";
6
+ import { createTestTracerProvider, mockDocumentLoader, test } from "../dist-lStjlyET.js";
7
+ import { assertEquals } from "../assert_equals-Gbplq4lg.js";
8
+ import { assert } from "../assert-Dp5_aoAs.js";
9
+ import { assertInstanceOf } from "../assert_instance_of-D1m8F7x0.js";
10
+ import "../deno-DHmnBq8X.js";
11
+ import { Collection, Note, Object as Object$1, Person } from "../vocab-Durhw0Gx.js";
12
+ import "../lookup-DP8Hm9oD.js";
13
+ import "../type-BSNcIxTd.js";
14
+ import { lookupObject, traverseCollection } from "../lookup-CjgzNtAk.js";
15
+ import "../std__assert-Cm-MfI66.js";
16
+ import { assertRejects } from "../assert_rejects-BoKYY0g1.js";
17
+ import "../assert_throws-DjkXin1a.js";
18
+ import "../assert_not_equals-B2R_8p36.js";
19
+ import { esm_default } from "../esm-B52TuumP.js";
18
20
 
19
21
  //#region src/vocab/lookup.test.ts
20
22
  test("lookupObject()", {
@@ -202,5 +204,276 @@ test("traverseCollection()", {
202
204
  new Note({ content: "This is a third simple note" })
203
205
  ]);
204
206
  });
207
+ test("FEP-fe34: lookupObject() cross-origin security", {
208
+ sanitizeResources: false,
209
+ sanitizeOps: false
210
+ }, async (t) => {
211
+ await t.step("crossOrigin: ignore (default) - returns null for cross-origin objects", async () => {
212
+ const crossOriginDocumentLoader = async (url) => {
213
+ if (url === "https://example.com/note") return {
214
+ documentUrl: url,
215
+ contextUrl: null,
216
+ document: {
217
+ "@context": "https://www.w3.org/ns/activitystreams",
218
+ type: "Note",
219
+ id: "https://malicious.com/fake-note",
220
+ content: "This is a spoofed note from a different origin"
221
+ }
222
+ };
223
+ throw new Error(`Unexpected URL: ${url}`);
224
+ };
225
+ const result = await lookupObject("https://example.com/note", {
226
+ documentLoader: crossOriginDocumentLoader,
227
+ contextLoader: mockDocumentLoader
228
+ });
229
+ assertEquals(result, null);
230
+ });
231
+ await t.step("crossOrigin: throw - throws error for cross-origin objects", async () => {
232
+ const crossOriginDocumentLoader = async (url) => {
233
+ if (url === "https://example.com/note") return {
234
+ documentUrl: url,
235
+ contextUrl: null,
236
+ document: {
237
+ "@context": "https://www.w3.org/ns/activitystreams",
238
+ type: "Note",
239
+ id: "https://malicious.com/fake-note",
240
+ content: "This is a spoofed note from a different origin"
241
+ }
242
+ };
243
+ throw new Error(`Unexpected URL: ${url}`);
244
+ };
245
+ await assertRejects(() => lookupObject("https://example.com/note", {
246
+ documentLoader: crossOriginDocumentLoader,
247
+ contextLoader: mockDocumentLoader,
248
+ crossOrigin: "throw"
249
+ }), Error, "The object's @id (https://malicious.com/fake-note) has a different origin than the document URL (https://example.com/note)");
250
+ });
251
+ await t.step("crossOrigin: trust - allows cross-origin objects", async () => {
252
+ const crossOriginDocumentLoader = async (url) => {
253
+ if (url === "https://example.com/note") return {
254
+ documentUrl: url,
255
+ contextUrl: null,
256
+ document: {
257
+ "@context": "https://www.w3.org/ns/activitystreams",
258
+ type: "Note",
259
+ id: "https://malicious.com/fake-note",
260
+ content: "This is a spoofed note from a different origin"
261
+ }
262
+ };
263
+ throw new Error(`Unexpected URL: ${url}`);
264
+ };
265
+ const result = await lookupObject("https://example.com/note", {
266
+ documentLoader: crossOriginDocumentLoader,
267
+ contextLoader: mockDocumentLoader,
268
+ crossOrigin: "trust"
269
+ });
270
+ assertInstanceOf(result, Note);
271
+ assertEquals(result.id, new URL("https://malicious.com/fake-note"));
272
+ assertEquals(result.content, "This is a spoofed note from a different origin");
273
+ });
274
+ await t.step("same-origin objects are always trusted", async () => {
275
+ const sameOriginDocumentLoader = async (url) => {
276
+ if (url === "https://example.com/note") return {
277
+ documentUrl: url,
278
+ contextUrl: null,
279
+ document: {
280
+ "@context": "https://www.w3.org/ns/activitystreams",
281
+ type: "Note",
282
+ id: "https://example.com/note",
283
+ content: "This is a legitimate note from the same origin"
284
+ }
285
+ };
286
+ throw new Error(`Unexpected URL: ${url}`);
287
+ };
288
+ const result = await lookupObject("https://example.com/note", {
289
+ documentLoader: sameOriginDocumentLoader,
290
+ contextLoader: mockDocumentLoader
291
+ });
292
+ assertInstanceOf(result, Note);
293
+ assertEquals(result.id, new URL("https://example.com/note"));
294
+ assertEquals(result.content, "This is a legitimate note from the same origin");
295
+ });
296
+ await t.step("objects without @id are trusted", async () => {
297
+ const noIdDocumentLoader = async (url) => {
298
+ if (url === "https://example.com/note") return {
299
+ documentUrl: url,
300
+ contextUrl: null,
301
+ document: {
302
+ "@context": "https://www.w3.org/ns/activitystreams",
303
+ type: "Note",
304
+ content: "This is a note without an ID"
305
+ }
306
+ };
307
+ throw new Error(`Unexpected URL: ${url}`);
308
+ };
309
+ const result = await lookupObject("https://example.com/note", {
310
+ documentLoader: noIdDocumentLoader,
311
+ contextLoader: mockDocumentLoader
312
+ });
313
+ assertInstanceOf(result, Note);
314
+ assertEquals(result.id, null);
315
+ assertEquals(result.content, "This is a note without an ID");
316
+ });
317
+ await t.step("WebFinger lookup with cross-origin actor URL", async () => {
318
+ esm_default.spyGlobal();
319
+ esm_default.get("begin:https://example.com/.well-known/webfinger", {
320
+ subject: "acct:user@example.com",
321
+ links: [{
322
+ rel: "self",
323
+ href: "https://different-origin.com/actor",
324
+ type: "application/activity+json"
325
+ }]
326
+ });
327
+ const webfingerDocumentLoader = async (url) => {
328
+ if (url === "https://different-origin.com/actor") return {
329
+ documentUrl: url,
330
+ contextUrl: null,
331
+ document: {
332
+ "@context": "https://www.w3.org/ns/activitystreams",
333
+ type: "Person",
334
+ id: "https://malicious.com/fake-actor",
335
+ name: "Fake Actor"
336
+ }
337
+ };
338
+ throw new Error(`Unexpected URL: ${url}`);
339
+ };
340
+ const result1 = await lookupObject("@user@example.com", {
341
+ documentLoader: webfingerDocumentLoader,
342
+ contextLoader: mockDocumentLoader
343
+ });
344
+ assertEquals(result1, null);
345
+ await assertRejects(() => lookupObject("@user@example.com", {
346
+ documentLoader: webfingerDocumentLoader,
347
+ contextLoader: mockDocumentLoader,
348
+ crossOrigin: "throw"
349
+ }), Error, "The object's @id (https://malicious.com/fake-actor) has a different origin than the document URL (https://different-origin.com/actor)");
350
+ const result2 = await lookupObject("@user@example.com", {
351
+ documentLoader: webfingerDocumentLoader,
352
+ contextLoader: mockDocumentLoader,
353
+ crossOrigin: "trust"
354
+ });
355
+ assertInstanceOf(result2, Person);
356
+ assertEquals(result2.id, new URL("https://malicious.com/fake-actor"));
357
+ esm_default.removeRoutes();
358
+ esm_default.hardReset();
359
+ });
360
+ await t.step("subdomain same-origin check", async () => {
361
+ const subdomainDocumentLoader = async (url) => {
362
+ if (url === "https://api.example.com/note") return {
363
+ documentUrl: url,
364
+ contextUrl: null,
365
+ document: {
366
+ "@context": "https://www.w3.org/ns/activitystreams",
367
+ type: "Note",
368
+ id: "https://www.example.com/note",
369
+ content: "Cross-subdomain note"
370
+ }
371
+ };
372
+ throw new Error(`Unexpected URL: ${url}`);
373
+ };
374
+ const result = await lookupObject("https://api.example.com/note", {
375
+ documentLoader: subdomainDocumentLoader,
376
+ contextLoader: mockDocumentLoader
377
+ });
378
+ assertEquals(result, null);
379
+ });
380
+ await t.step("different port same-origin check", async () => {
381
+ const differentPortDocumentLoader = async (url) => {
382
+ if (url === "https://example.com:8080/note") return {
383
+ documentUrl: url,
384
+ contextUrl: null,
385
+ document: {
386
+ "@context": "https://www.w3.org/ns/activitystreams",
387
+ type: "Note",
388
+ id: "https://example.com:9090/note",
389
+ content: "Cross-port note"
390
+ }
391
+ };
392
+ throw new Error(`Unexpected URL: ${url}`);
393
+ };
394
+ const result = await lookupObject("https://example.com:8080/note", {
395
+ documentLoader: differentPortDocumentLoader,
396
+ contextLoader: mockDocumentLoader
397
+ });
398
+ assertEquals(result, null);
399
+ });
400
+ await t.step("protocol difference same-origin check", async () => {
401
+ const differentProtocolDocumentLoader = async (url) => {
402
+ if (url === "https://example.com/note") return {
403
+ documentUrl: url,
404
+ contextUrl: null,
405
+ document: {
406
+ "@context": "https://www.w3.org/ns/activitystreams",
407
+ type: "Note",
408
+ id: "http://example.com/note",
409
+ content: "Cross-protocol note"
410
+ }
411
+ };
412
+ throw new Error(`Unexpected URL: ${url}`);
413
+ };
414
+ const result = await lookupObject("https://example.com/note", {
415
+ documentLoader: differentProtocolDocumentLoader,
416
+ contextLoader: mockDocumentLoader
417
+ });
418
+ assertEquals(result, null);
419
+ });
420
+ await t.step("error handling with crossOrigin throw option", async () => {
421
+ const errorDocumentLoader = async (_url) => {
422
+ throw new Error("Network error");
423
+ };
424
+ const result = await lookupObject("https://example.com/note", {
425
+ documentLoader: errorDocumentLoader,
426
+ contextLoader: mockDocumentLoader,
427
+ crossOrigin: "throw"
428
+ });
429
+ assertEquals(result, null);
430
+ });
431
+ await t.step("malformed JSON handling with cross-origin policy", async () => {
432
+ const malformedJsonDocumentLoader = async (url) => {
433
+ if (url === "https://example.com/note") return {
434
+ documentUrl: url,
435
+ contextUrl: null,
436
+ document: "invalid json"
437
+ };
438
+ throw new Error(`Unexpected URL: ${url}`);
439
+ };
440
+ assertEquals(await lookupObject("https://example.com/note", {
441
+ documentLoader: malformedJsonDocumentLoader,
442
+ contextLoader: mockDocumentLoader,
443
+ crossOrigin: "ignore"
444
+ }), null);
445
+ assertEquals(await lookupObject("https://example.com/note", {
446
+ documentLoader: malformedJsonDocumentLoader,
447
+ contextLoader: mockDocumentLoader,
448
+ crossOrigin: "throw"
449
+ }), null);
450
+ assertEquals(await lookupObject("https://example.com/note", {
451
+ documentLoader: malformedJsonDocumentLoader,
452
+ contextLoader: mockDocumentLoader,
453
+ crossOrigin: "trust"
454
+ }), null);
455
+ });
456
+ });
457
+ test("lookupObject() records OpenTelemetry span events", async () => {
458
+ const [tracerProvider, exporter] = createTestTracerProvider();
459
+ const object = await lookupObject("https://example.com/object", {
460
+ documentLoader: mockDocumentLoader,
461
+ contextLoader: mockDocumentLoader,
462
+ tracerProvider
463
+ });
464
+ assertInstanceOf(object, Object$1);
465
+ const spans = exporter.getSpans("activitypub.lookup_object");
466
+ assertEquals(spans.length, 1);
467
+ const span = spans[0];
468
+ assertEquals(span.attributes["activitypub.object.id"], "https://example.com/object");
469
+ const events = exporter.getEvents("activitypub.lookup_object", "activitypub.object.fetched");
470
+ assertEquals(events.length, 1);
471
+ const event = events[0];
472
+ assert(event.attributes != null);
473
+ assert(typeof event.attributes["activitypub.object.type"] === "string");
474
+ assert(typeof event.attributes["activitypub.object.json"] === "string");
475
+ const recordedObject = JSON.parse(event.attributes["activitypub.object.json"]);
476
+ assertEquals(recordedObject.id, "https://example.com/object");
477
+ });
205
478
 
206
479
  //#endregion