@fedify/fedify 2.4.0-pr.936.41 → 2.5.0-dev.2271

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 (244) hide show
  1. package/README.md +50 -39
  2. package/dist/{assert-CJ1KXcvv.mjs → assert-D1Eafmd_.mjs} +1 -1
  3. package/dist/{assert_equals-BV7oLMxm.mjs → assert_equals-Z6IcEbWU.mjs} +2 -28
  4. package/dist/assert_exists-cffSpJ7X.mjs +28 -0
  5. package/dist/assert_false-CPdRnc3E.mjs +23 -0
  6. package/dist/assert_greater_or_equal-BlafOF4-.mjs +31 -0
  7. package/dist/{assert_instance_of-Q9KTBnrf.mjs → assert_instance_of-mrXWWNY-.mjs} +1 -1
  8. package/dist/{assert_not_equals-EPJPoxuf.mjs → assert_not_equals-CpPK2t89.mjs} +2 -1
  9. package/dist/assert_rejects-CTptdYck.mjs +39 -0
  10. package/dist/{assert_strict_equals-Ec20AUwa.mjs → assert_strict_equals-CYvBmkpC.mjs} +2 -1
  11. package/dist/{assert_throws-NiFfqbnH.mjs → assert_throws-BYITOvPO.mjs} +2 -1
  12. package/dist/assertion_error-B-cx0fFA.mjs +31 -0
  13. package/dist/audience-CHQ-FlLD.mjs +95 -0
  14. package/dist/{builder-DonuxRl_.mjs → builder-Bda6LK7A.mjs} +169 -14
  15. package/dist/{circuit-breaker-CBGyz5F7.mjs → circuit-breaker-XJ53md4S.mjs} +224 -17
  16. package/dist/circuit-breaker-test-utils-DW6YC_Pe.mjs +14 -0
  17. package/dist/{client-CjF5IYQS.mjs → client-CEnNz8O7.mjs} +144 -8
  18. package/dist/{codec-BBga-FWI.mjs → codec-C6rTrpIp.mjs} +26 -3
  19. package/dist/{collection-BIhlldqK.mjs → collection-CnnP1UAv.mjs} +1 -1
  20. package/dist/compat/mod.cjs +1 -1
  21. package/dist/compat/mod.d.cts +1 -1
  22. package/dist/compat/mod.d.ts +1 -1
  23. package/dist/compat/mod.js +1 -1
  24. package/dist/compat/outgoing-jsonld.test.mjs +71 -3
  25. package/dist/compat/public-audience.test.mjs +14 -5
  26. package/dist/compat/secured-document.test.d.mts +2 -0
  27. package/dist/compat/secured-document.test.mjs +58 -0
  28. package/dist/compat/transformers.test.mjs +5 -5
  29. package/dist/compound-proof-B-9mXxFW.mjs +989 -0
  30. package/dist/{context-Zii1f5xS.d.ts → context-7NyiqIcg.d.ts} +1600 -25
  31. package/dist/{context-BJXxPElm.mjs → context-8Tu9kea0.mjs} +21 -63
  32. package/dist/{context-lxX6I7as.d.cts → context-tsYPJ2Ew.d.cts} +1600 -25
  33. package/dist/{deno-BHzKn9Ig.mjs → deno-oR5aJKpU.mjs} +1 -1
  34. package/dist/dist-DJQM4u7i.mjs +189 -0
  35. package/dist/docloader-DBoYbvYW.mjs +87 -0
  36. package/dist/{esm-yYQfPhIY.mjs → esm-BHXXx4Wx.mjs} +13 -6
  37. package/dist/federation/audience.test.d.mts +2 -0
  38. package/dist/federation/audience.test.mjs +130 -0
  39. package/dist/federation/builder.test.mjs +54 -5
  40. package/dist/federation/circuit-breaker.test.mjs +838 -7
  41. package/dist/federation/collection.test.mjs +3 -3
  42. package/dist/federation/compound-fanout.test.d.mts +2 -0
  43. package/dist/federation/compound-fanout.test.mjs +228 -0
  44. package/dist/federation/handler-compound-proof.test.d.mts +2 -0
  45. package/dist/federation/handler-compound-proof.test.mjs +384 -0
  46. package/dist/federation/handler.test.mjs +385 -15
  47. package/dist/federation/hashlink-media.test.d.mts +2 -0
  48. package/dist/federation/hashlink-media.test.mjs +422 -0
  49. package/dist/federation/idempotency.test.mjs +6 -6
  50. package/dist/federation/inbox-report.test.d.mts +2 -0
  51. package/dist/federation/inbox-report.test.mjs +475 -0
  52. package/dist/federation/inbox.test.mjs +3 -3
  53. package/dist/federation/keycache.test.mjs +215 -14
  54. package/dist/federation/kv.test.mjs +3 -3
  55. package/dist/federation/metrics.test.mjs +5 -5
  56. package/dist/federation/middleware.test.mjs +967 -35
  57. package/dist/federation/mod.cjs +18 -261
  58. package/dist/federation/mod.d.cts +5 -5
  59. package/dist/federation/mod.d.ts +5 -5
  60. package/dist/federation/mod.js +279 -1
  61. package/dist/federation/mq.test.mjs +123 -47
  62. package/dist/federation/negotiation.test.mjs +4 -4
  63. package/dist/federation/outgoing-proof.test.d.mts +2 -0
  64. package/dist/federation/outgoing-proof.test.mjs +931 -0
  65. package/dist/federation/portable-actor.test.d.mts +2 -0
  66. package/dist/federation/portable-actor.test.mjs +496 -0
  67. package/dist/federation/portable-chain.test.d.mts +2 -0
  68. package/dist/federation/portable-chain.test.mjs +370 -0
  69. package/dist/federation/portable-collection.test.d.mts +2 -0
  70. package/dist/federation/portable-collection.test.mjs +832 -0
  71. package/dist/federation/portable-delivery.test.d.mts +2 -0
  72. package/dist/federation/portable-delivery.test.mjs +746 -0
  73. package/dist/federation/portable-gateway-keys.test.d.mts +2 -0
  74. package/dist/federation/portable-gateway-keys.test.mjs +686 -0
  75. package/dist/federation/portable-inbox.test.d.mts +2 -0
  76. package/dist/federation/portable-inbox.test.mjs +1535 -0
  77. package/dist/federation/portable-parse-uri.test.d.mts +2 -0
  78. package/dist/federation/portable-parse-uri.test.mjs +348 -0
  79. package/dist/federation/portable-route-activity.test.d.mts +2 -0
  80. package/dist/federation/portable-route-activity.test.mjs +259 -0
  81. package/dist/federation/portable.test.d.mts +2 -0
  82. package/dist/federation/portable.test.mjs +1072 -0
  83. package/dist/federation/retry.test.mjs +4 -3
  84. package/dist/federation/router.test.mjs +9 -159
  85. package/dist/federation/send.test.mjs +245 -27
  86. package/dist/federation/tasks/codec.test.mjs +4 -4
  87. package/dist/federation/tasks/enqueue.test.mjs +42 -4
  88. package/dist/federation/tasks/tasks.test.mjs +7 -6
  89. package/dist/federation/temporal.test.mjs +4 -4
  90. package/dist/federation/webfinger.test.mjs +275 -12
  91. package/dist/{middleware-FrSMAYEx.cjs → federation-CkZiAcWY.cjs} +8640 -3722
  92. package/dist/http-B5JT115n.cjs +10630 -0
  93. package/dist/http-DydWCB7R.js +6527 -0
  94. package/dist/{http-CPVMUgsW.mjs → http-siciWkmx.mjs} +397 -168
  95. package/dist/key-BspPiXqn.mjs +951 -0
  96. package/dist/key-C1nv7_jD.d.ts +1125 -0
  97. package/dist/key-DYxuyd-s.d.cts +1125 -0
  98. package/dist/key-owner-evidence-APB6NpSk.mjs +108 -0
  99. package/dist/keycache-Da8A8mZa.mjs +200 -0
  100. package/dist/{kv-D6hNiMTK.d.ts → kv-B2mzK5tl.d.cts} +3 -2
  101. package/dist/{kv-gJ8LYbxX.d.cts → kv-B2mzK5tl.d.ts} +3 -2
  102. package/dist/kv-DBRWVx3Q.mjs +104 -0
  103. package/dist/{kv-cache-KyGqJqSp.mjs → kv-cache-BF1hnW65.mjs} +1 -1
  104. package/dist/{kv-cache-5bnX3-Jq.js → kv-cache-CTQr1tbn.js} +54 -16
  105. package/dist/{kv-cache-DQ29C4XL.cjs → kv-cache-DCac1nEU.cjs} +55 -19
  106. package/dist/{ld-Cj9F_5AP.mjs → ld-CzaP-hJl.mjs} +44 -12
  107. package/dist/map-local-context-conflict-DOYEEJ3u.mjs +204 -0
  108. package/dist/map-local-create-note-B0SeXJms.mjs +214 -0
  109. package/dist/{metrics-DMk-nTxI.mjs → metrics-CYg9yxBL.mjs} +3 -2
  110. package/dist/metrics-DVKYY6K1.d.cts +36 -0
  111. package/dist/metrics-DoRtI0qU.d.ts +36 -0
  112. package/dist/{middleware-Y-kpsp6S.js → middleware-CsDDXKuL.js} +5493 -1103
  113. package/dist/{middleware-CvwTUgnP.mjs → middleware-D7_LO-Vs.mjs} +3157 -272
  114. package/dist/{middleware-CEctxBN6.mjs → middleware-DWjrfpcz.mjs} +1 -1
  115. package/dist/{mod-gOlPDuT8.d.cts → mod-BojP2Bw3.d.cts} +1 -1
  116. package/dist/mod-CavhAgLw.d.cts +320 -0
  117. package/dist/mod-CtpF2BU5.d.ts +320 -0
  118. package/dist/{mod-BtEaIEcD.d.cts → mod-DEZXwV6J.d.ts} +10 -4
  119. package/dist/{mod-UMmveiO0.d.ts → mod-Dw-nPxQh.d.cts} +10 -4
  120. package/dist/{mod-DLc2Ot6f.d.ts → mod-Xj5P4s4d.d.ts} +1 -1
  121. package/dist/mod.cjs +40 -39
  122. package/dist/mod.d.cts +10 -11
  123. package/dist/mod.d.ts +10 -11
  124. package/dist/mod.js +9 -9
  125. package/dist/{mq-llHKivST.mjs → mq-Dm1Wmtm-.mjs} +6 -0
  126. package/dist/nodeinfo/client.test.mjs +139 -4
  127. package/dist/nodeinfo/handler.test.mjs +5 -5
  128. package/dist/nodeinfo/mod.cjs +1 -1
  129. package/dist/nodeinfo/mod.d.cts +1 -1
  130. package/dist/nodeinfo/mod.d.ts +1 -1
  131. package/dist/nodeinfo/mod.js +1 -1
  132. package/dist/nodeinfo/types.test.mjs +4 -4
  133. package/dist/otel/exporter.test.mjs +3 -3
  134. package/dist/otel/mod.cjs +0 -1
  135. package/dist/otel/mod.d.cts +1 -1
  136. package/dist/otel/mod.d.ts +1 -1
  137. package/dist/{outgoing-jsonld-URuqsICz.mjs → outgoing-jsonld-4IJqPYos.mjs} +12 -10
  138. package/dist/{owner-DEvZuyOE.d.cts → owner-BF0L9cMt.d.cts} +11 -0
  139. package/dist/{owner-CnngXDNJ.d.ts → owner-BSzr5-I8.d.ts} +11 -0
  140. package/dist/owner-DYgfTFHy.mjs +267 -0
  141. package/dist/portable-collection-BpsVsRov.js +670 -0
  142. package/dist/portable-collection-C74P1vtC.mjs +418 -0
  143. package/dist/portable-collection-DZd2bm7M.cjs +686 -0
  144. package/dist/portable-key-BIMLrAP4.mjs +549 -0
  145. package/dist/portable-key-id-Ca30-hOa.mjs +248 -0
  146. package/dist/proof-Dxy6ByqI.mjs +1299 -0
  147. package/dist/{public-audience-Cr5MsnMq.mjs → public-audience--klBIOk1.mjs} +15 -10
  148. package/dist/router-u5O5KCQr.mjs +156 -0
  149. package/dist/runtime/mod.cjs +1 -1
  150. package/dist/runtime/mod.js +1 -1
  151. package/dist/secured-document-CxzZZ9nL.mjs +35 -0
  152. package/dist/send-C4dDpAxm.mjs +495 -0
  153. package/dist/sig/accept.test.mjs +1 -1
  154. package/dist/sig/compound-proof-discovery.test.d.mts +2 -0
  155. package/dist/sig/compound-proof-discovery.test.mjs +331 -0
  156. package/dist/sig/compound-proof-producer.test.d.mts +2 -0
  157. package/dist/sig/compound-proof-producer.test.mjs +107 -0
  158. package/dist/sig/compound-proof-verification.test.d.mts +2 -0
  159. package/dist/sig/compound-proof-verification.test.mjs +833 -0
  160. package/dist/sig/compound-proof.test.d.mts +2 -0
  161. package/dist/sig/compound-proof.test.mjs +411 -0
  162. package/dist/sig/http.test.mjs +702 -31
  163. package/dist/sig/key-owner-evidence.test.d.mts +2 -0
  164. package/dist/sig/key-owner-evidence.test.mjs +100 -0
  165. package/dist/sig/key.test.mjs +220 -8
  166. package/dist/sig/ld.test.mjs +65 -7
  167. package/dist/sig/mitra-receive-interop.test.d.mts +2 -0
  168. package/dist/sig/mitra-receive-interop.test.mjs +260 -0
  169. package/dist/sig/mitra-send-interop.test.d.mts +2 -0
  170. package/dist/sig/mitra-send-interop.test.mjs +461 -0
  171. package/dist/sig/mod.cjs +18 -16
  172. package/dist/sig/mod.d.cts +4 -4
  173. package/dist/sig/mod.d.ts +4 -4
  174. package/dist/sig/mod.js +3 -3
  175. package/dist/sig/owner.test.mjs +108 -9
  176. package/dist/sig/portable-collection.test.d.mts +2 -0
  177. package/dist/sig/portable-collection.test.mjs +697 -0
  178. package/dist/sig/portable-interop.test.d.mts +2 -0
  179. package/dist/sig/portable-interop.test.mjs +156 -0
  180. package/dist/sig/portable-key-id.test.d.mts +2 -0
  181. package/dist/sig/portable-key-id.test.mjs +67 -0
  182. package/dist/sig/portable-key.test.d.mts +2 -0
  183. package/dist/sig/portable-key.test.mjs +1439 -0
  184. package/dist/sig/proof.test.mjs +1753 -16
  185. package/dist/sig/tootik-request-interop.test.d.mts +2 -0
  186. package/dist/sig/tootik-request-interop.test.mjs +190 -0
  187. package/dist/sig/tootik-send-interop.test.d.mts +2 -0
  188. package/dist/sig/tootik-send-interop.test.mjs +331 -0
  189. package/dist/sig/verification.test.d.mts +2 -0
  190. package/dist/sig/verification.test.mjs +310 -0
  191. package/dist/std__assert-DvMDRPes.mjs +8 -0
  192. package/dist/{testing-CO7ftO8A.mjs → tasks-IG3pHfvZ.mjs} +2 -2
  193. package/dist/{temporal-fsXO5IvD.mjs → temporal-D0KJI4NF.mjs} +3 -3
  194. package/dist/testing/context.test.d.mts +2 -0
  195. package/dist/testing/context.test.mjs +19 -0
  196. package/dist/testing/kv.test.d.mts +2 -0
  197. package/dist/testing/kv.test.mjs +101 -0
  198. package/dist/testing/mod.d.mts +1617 -48
  199. package/dist/testing/mod.mjs +6 -3
  200. package/dist/testing-t8xDeJZ5.mjs +8 -0
  201. package/dist/{transformers-DGwl-hD1.cjs → transformers-BalCrSsr.cjs} +0 -1
  202. package/dist/{types-DC1pNgJA.js → types-_S2_MeLF.js} +144 -8
  203. package/dist/{types-CPym83zc.cjs → types-poIao40f.cjs} +160 -7
  204. package/dist/utils/docloader.test.mjs +530 -8
  205. package/dist/utils/kv-cache.test.mjs +2 -2
  206. package/dist/utils/mod.cjs +1 -1
  207. package/dist/utils/mod.d.cts +1 -1
  208. package/dist/utils/mod.d.ts +1 -1
  209. package/dist/utils/mod.js +1 -1
  210. package/dist/verification-C3954hQh.mjs +5 -0
  211. package/dist/verification-Dpfcw8ml.mjs +105 -0
  212. package/dist/vocab/cjs.test.mjs +1 -1
  213. package/package.json +8 -8
  214. package/dist/assert_rejects-EgstcQy5.mjs +0 -82
  215. package/dist/docloader-e1khNUKy.mjs +0 -49
  216. package/dist/http-CsmQ-BQ4.js +0 -2483
  217. package/dist/http-VyDTd4G3.d.cts +0 -553
  218. package/dist/http-hlIjmewS.cjs +0 -2694
  219. package/dist/http-lf8Hsd91.d.ts +0 -553
  220. package/dist/key-DfPsX8hv.mjs +0 -453
  221. package/dist/keycache-_DHqz5z_.mjs +0 -97
  222. package/dist/metrics-CoUJLQhZ.d.cts +0 -276
  223. package/dist/metrics-Dc4jR-IC.d.ts +0 -276
  224. package/dist/mod-B0hW12_O.d.cts +0 -307
  225. package/dist/mod-COIAjwRS.d.ts +0 -307
  226. package/dist/owner-Br9YYzn_.mjs +0 -120
  227. package/dist/proof-B4ngoaNQ.mjs +0 -316
  228. package/dist/proof-B6E0XUXJ.js +0 -1415
  229. package/dist/proof-NN4xCQGL.cjs +0 -1562
  230. package/dist/send-CxHKUNzv.mjs +0 -239
  231. package/dist/std__assert-B2NnY9bq.mjs +0 -79
  232. package/dist/temporal-polyfill-BCdTHexd.cjs +0 -3565
  233. /package/dist/{accept-8PiolDP7.mjs → accept-CPVqki78.mjs} +0 -0
  234. /package/dist/{activity-listener-BtTSxZWA.mjs → activity-listener-C-BSbKI7.mjs} +0 -0
  235. /package/dist/{client-CAM_bQXx.d.cts → client-D-XP_Ccb.d.cts} +0 -0
  236. /package/dist/{client-CSddvgWN.d.ts → client-D-XP_Ccb.d.ts} +0 -0
  237. /package/dist/{keys-Dbyd7bhl.mjs → keys-DIJNHW-Y.mjs} +0 -0
  238. /package/dist/{kv-CXBAok3k.mjs → kv-DCHkaJ9-.mjs} +0 -0
  239. /package/dist/{negotiation-RuwrPFqi.mjs → negotiation-CCocWT_N.mjs} +0 -0
  240. /package/dist/{retry-DgFqeS5k.mjs → retry-zX5xw5e0.mjs} +0 -0
  241. /package/dist/{chunk-D5IdezsZ.js → rolldown-runtime-BC-Eo5Mj.js} +0 -0
  242. /package/dist/{chunk-Czpeue4M.cjs → rolldown-runtime-Dmm3t92W.cjs} +0 -0
  243. /package/dist/{transformers-DXze6FUB.js → transformers-DAtXl_Kc.js} +0 -0
  244. /package/dist/{types-CrtdVuDP.mjs → types-DE_LV1JB.mjs} +0 -0
@@ -1,12 +1,15 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-BHzKn9Ig.mjs";
5
- import { t as ActivityListenerSet } from "./activity-listener-BtTSxZWA.mjs";
4
+ import { i as getPortableDid, l as isPortableId, n as getCanonicalPortableId } from "./portable-key-id-Ca30-hOa.mjs";
5
+ import { n as version, t as name } from "./deno-oR5aJKpU.mjs";
6
+ import { t as ActivityListenerSet } from "./activity-listener-C-BSbKI7.mjs";
6
7
  import { getLogger } from "@logtape/logtape";
7
8
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
8
9
  import { Tombstone, getTypeId } from "@fedify/vocab";
9
10
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
11
+ import { fromCompatibleEf61Id, isGatewayUrl } from "@fedify/vocab-runtime";
12
+ import { isCompatibleEf61Iri } from "@fedify/vocab-runtime/internal/portable-dereference";
10
13
  //#region src/federation/builder.ts
11
14
  const ACTOR_ALIAS_PREFIX = "actorAlias:";
12
15
  /**
@@ -52,12 +55,14 @@ var FederationBuilderImpl = class {
52
55
  featuredTagsCallbacks;
53
56
  inboxListeners;
54
57
  outboxListeners;
58
+ inboxRequestFinishedHandler;
55
59
  inboxErrorHandler;
56
60
  outboxListenerErrorHandler;
57
61
  outboxAuthorizePredicate;
58
62
  mediaUploaderPath;
59
63
  mediaUploaderCallback;
60
64
  mediaUploaderAuthorizePredicate;
65
+ hashlinkMediaDispatcher;
61
66
  sharedInboxKeyDispatcher;
62
67
  unverifiedActivityHandler;
63
68
  outboxPermanentFailureHandler;
@@ -69,6 +74,7 @@ var FederationBuilderImpl = class {
69
74
  * Symbol registry for unique identification of unnamed symbols.
70
75
  */
71
76
  #symbolRegistry = /* @__PURE__ */ new Map();
77
+ #collectionNames = /* @__PURE__ */ new Map();
72
78
  constructor() {
73
79
  this.router = new Router();
74
80
  this.objectCallbacks = {};
@@ -85,7 +91,7 @@ var FederationBuilderImpl = class {
85
91
  * specified.
86
92
  */
87
93
  async build(options) {
88
- const { FederationImpl } = await import("./middleware-CEctxBN6.mjs");
94
+ const { FederationImpl } = await import("./middleware-DWjrfpcz.mjs");
89
95
  const f = new FederationImpl(options);
90
96
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
91
97
  f.router = this.router.clone();
@@ -96,6 +102,10 @@ var FederationBuilderImpl = class {
96
102
  f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
97
103
  f.objectCallbacks = { ...this.objectCallbacks };
98
104
  f.objectTypeIds = { ...this.objectTypeIds };
105
+ f.collectionCallbacks = { ...this.collectionCallbacks };
106
+ f.collectionTypeIds = { ...this.collectionTypeIds };
107
+ f.#symbolRegistry = new Map(this.#symbolRegistry);
108
+ f.#collectionNames = new Map(this.#collectionNames);
99
109
  f.inboxPath = this.inboxPath;
100
110
  f.outboxPath = this.outboxPath;
101
111
  f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
@@ -107,12 +117,14 @@ var FederationBuilderImpl = class {
107
117
  f.featuredTagsCallbacks = this.featuredTagsCallbacks == null ? void 0 : { ...this.featuredTagsCallbacks };
108
118
  f.inboxListeners = this.inboxListeners?.clone();
109
119
  f.outboxListeners = this.outboxListeners?.clone();
120
+ f.inboxRequestFinishedHandler = this.inboxRequestFinishedHandler;
110
121
  f.inboxErrorHandler = this.inboxErrorHandler;
111
122
  f.outboxListenerErrorHandler = this.outboxListenerErrorHandler;
112
123
  f.outboxAuthorizePredicate = this.outboxAuthorizePredicate;
113
124
  f.mediaUploaderPath = this.mediaUploaderPath;
114
125
  f.mediaUploaderCallback = this.mediaUploaderCallback;
115
126
  f.mediaUploaderAuthorizePredicate = this.mediaUploaderAuthorizePredicate;
127
+ f.hashlinkMediaDispatcher = this.hashlinkMediaDispatcher;
116
128
  f.sharedInboxKeyDispatcher = this.sharedInboxKeyDispatcher;
117
129
  f.unverifiedActivityHandler = this.unverifiedActivityHandler;
118
130
  f.outboxPermanentFailureHandler = this.outboxPermanentFailureHandler;
@@ -154,38 +166,42 @@ var FederationBuilderImpl = class {
154
166
  "federation",
155
167
  "actor"
156
168
  ]);
169
+ const portable = actor.id != null && isPortableId(actor.id);
157
170
  if (actor.id == null) logger.warn("Actor dispatcher returned an actor without an id property. Set the property with Context.getActorUri(identifier).");
158
- else if (actor.id.href != context.getActorUri(identifier).href) logger.warn("Actor dispatcher returned an actor with an id property that does not match the actor URI. Set the property with Context.getActorUri(identifier).");
171
+ else if (!portable && actor.id.href != context.getActorUri(identifier).href) logger.warn("Actor dispatcher returned an actor with an id property that does not match the actor URI. Set the property with Context.getActorUri(identifier).");
159
172
  if (actor instanceof Tombstone) return actor;
173
+ if (portable && actor.id != null) warnPortableActorGateways(actor.id, actor.gateways);
174
+ if (actor.id != null && isCompatibleEf61Iri(actor.id)) warnCompatibleActorId(actor.id, actor.gateway);
175
+ if (portable) this.#warnPortableCollectionIds(context, identifier, actor);
160
176
  if (this.followingCallbacks != null && this.followingCallbacks.dispatcher != null) {
161
177
  if (actor.followingId == null) logger.warn("You configured a following collection dispatcher, but the actor does not have a following property. Set the property with Context.getFollowingUri(identifier).");
162
- else if (actor.followingId.href != context.getFollowingUri(identifier).href) logger.warn("You configured a following collection dispatcher, but the actor's following property does not match the following collection URI. Set the property with Context.getFollowingUri(identifier).");
178
+ else if (!portable && actor.followingId.href != context.getFollowingUri(identifier).href) logger.warn("You configured a following collection dispatcher, but the actor's following property does not match the following collection URI. Set the property with Context.getFollowingUri(identifier).");
163
179
  }
164
180
  if (this.followersCallbacks != null && this.followersCallbacks.dispatcher != null) {
165
181
  if (actor.followersId == null) logger.warn("You configured a followers collection dispatcher, but the actor does not have a followers property. Set the property with Context.getFollowersUri(identifier).");
166
- else if (actor.followersId.href != context.getFollowersUri(identifier).href) logger.warn("You configured a followers collection dispatcher, but the actor's followers property does not match the followers collection URI. Set the property with Context.getFollowersUri(identifier).");
182
+ else if (!portable && actor.followersId.href != context.getFollowersUri(identifier).href) logger.warn("You configured a followers collection dispatcher, but the actor's followers property does not match the followers collection URI. Set the property with Context.getFollowersUri(identifier).");
167
183
  }
168
184
  if (this.outboxCallbacks != null && this.outboxCallbacks.dispatcher != null) {
169
185
  if (actor?.outboxId == null) logger.warn("You configured an outbox collection dispatcher, but the actor does not have an outbox property. Set the property with Context.getOutboxUri(identifier).");
170
- else if (actor.outboxId.href != context.getOutboxUri(identifier).href) logger.warn("You configured an outbox collection dispatcher, but the actor's outbox property does not match the outbox collection URI. Set the property with Context.getOutboxUri(identifier).");
186
+ else if (!portable && actor.outboxId.href != context.getOutboxUri(identifier).href) logger.warn("You configured an outbox collection dispatcher, but the actor's outbox property does not match the outbox collection URI. Set the property with Context.getOutboxUri(identifier).");
171
187
  }
172
188
  if (this.likedCallbacks != null && this.likedCallbacks.dispatcher != null) {
173
189
  if (actor?.likedId == null) logger.warn("You configured a liked collection dispatcher, but the actor does not have a liked property. Set the property with Context.getLikedUri(identifier).");
174
- else if (actor.likedId.href != context.getLikedUri(identifier).href) logger.warn("You configured a liked collection dispatcher, but the actor's liked property does not match the liked collection URI. Set the property with Context.getLikedUri(identifier).");
190
+ else if (!portable && actor.likedId.href != context.getLikedUri(identifier).href) logger.warn("You configured a liked collection dispatcher, but the actor's liked property does not match the liked collection URI. Set the property with Context.getLikedUri(identifier).");
175
191
  }
176
192
  if (this.featuredCallbacks != null && this.featuredCallbacks.dispatcher != null) {
177
193
  if (actor?.featuredId == null) logger.warn("You configured a featured collection dispatcher, but the actor does not have a featured property. Set the property with Context.getFeaturedUri(identifier).");
178
- else if (actor.featuredId.href != context.getFeaturedUri(identifier).href) logger.warn("You configured a featured collection dispatcher, but the actor's featured property does not match the featured collection URI. Set the property with Context.getFeaturedUri(identifier).");
194
+ else if (!portable && actor.featuredId.href != context.getFeaturedUri(identifier).href) logger.warn("You configured a featured collection dispatcher, but the actor's featured property does not match the featured collection URI. Set the property with Context.getFeaturedUri(identifier).");
179
195
  }
180
196
  if (this.featuredTagsCallbacks != null && this.featuredTagsCallbacks.dispatcher != null) {
181
197
  if (actor?.featuredTagsId == null) logger.warn("You configured a featured tags collection dispatcher, but the actor does not have a featuredTags property. Set the property with Context.getFeaturedTagsUri(identifier).");
182
- else if (actor.featuredTagsId.href != context.getFeaturedTagsUri(identifier).href) logger.warn("You configured a featured tags collection dispatcher, but the actor's featuredTags property does not match the featured tags collection URI. Set the property with Context.getFeaturedTagsUri(identifier).");
198
+ else if (!portable && actor.featuredTagsId.href != context.getFeaturedTagsUri(identifier).href) logger.warn("You configured a featured tags collection dispatcher, but the actor's featuredTags property does not match the featured tags collection URI. Set the property with Context.getFeaturedTagsUri(identifier).");
183
199
  }
184
200
  if (this.router.has("inbox")) {
185
201
  if (actor.inboxId == null) logger.warn("You configured inbox listeners, but the actor does not have an inbox property. Set the property with Context.getInboxUri(identifier).");
186
- else if (actor.inboxId.href != context.getInboxUri(identifier).href) logger.warn("You configured inbox listeners, but the actor's inbox property does not match the inbox URI. Set the property with Context.getInboxUri(identifier).");
202
+ else if (!portable && actor.inboxId.href != context.getInboxUri(identifier).href) logger.warn("You configured inbox listeners, but the actor's inbox property does not match the inbox URI. Set the property with Context.getInboxUri(identifier).");
187
203
  if (actor.endpoints == null || actor.endpoints.sharedInbox == null) logger.warn("You configured inbox listeners, but the actor does not have a endpoints.sharedInbox property. Set the property with Context.getInboxUri().");
188
- else if (actor.endpoints.sharedInbox.href != context.getInboxUri().href) logger.warn("You configured inbox listeners, but the actor's endpoints.sharedInbox property does not match the shared inbox URI. Set the property with Context.getInboxUri().");
204
+ else if (!portable && actor.endpoints.sharedInbox.href != context.getInboxUri().href) logger.warn("You configured inbox listeners, but the actor's endpoints.sharedInbox property does not match the shared inbox URI. Set the property with Context.getInboxUri().");
189
205
  }
190
206
  if (callbacks.keyPairsDispatcher != null) {
191
207
  if (actor.publicKeyId == null) logger.warn("You configured a key pairs dispatcher, but the actor does not have a publicKey property. Set the property with Context.getActorKeyPairs(identifier).");
@@ -229,6 +245,10 @@ var FederationBuilderImpl = class {
229
245
  callbacks.aliasMapper = mapper;
230
246
  return setters;
231
247
  },
248
+ mapPortableActorId(mapper) {
249
+ callbacks.portableActorIdMapper = mapper;
250
+ return setters;
251
+ },
232
252
  mapActorAlias: (path, identifier) => {
233
253
  if (identifier === "") throw new RouterError("Identifier cannot be empty.");
234
254
  if (this.router.has(`actorAlias:${identifier}`)) throw new RouterError(`Actor alias for "${identifier}" already set.`);
@@ -284,8 +304,8 @@ var FederationBuilderImpl = class {
284
304
  const variables = Router.variables(path);
285
305
  this.router.add(path, routeName);
286
306
  const callbacks = {
287
- dispatcher: (ctx, values) => {
288
- return this._getTracer().startActiveSpan("activitypub.dispatch_object", {
307
+ dispatcher: async (ctx, values) => {
308
+ const object = await this._getTracer().startActiveSpan("activitypub.dispatch_object", {
289
309
  kind: SpanKind.SERVER,
290
310
  attributes: {
291
311
  "fedify.object.type": cls.typeId.href,
@@ -308,6 +328,8 @@ var FederationBuilderImpl = class {
308
328
  span.end();
309
329
  }
310
330
  });
331
+ if (object instanceof Tombstone) warnMismatchedTombstoneId(ctx, cls, values, object);
332
+ return object;
311
333
  },
312
334
  parameters: variables
313
335
  };
@@ -419,6 +441,10 @@ var FederationBuilderImpl = class {
419
441
  } };
420
442
  return setters;
421
443
  }
444
+ setHashlinkMediaDispatcher(dispatcher) {
445
+ if (this.hashlinkMediaDispatcher != null) throw new RouterError("Hashlink media dispatcher already set.");
446
+ this.hashlinkMediaDispatcher = dispatcher;
447
+ }
422
448
  setFollowingDispatcher(path, dispatcher) {
423
449
  if (this.router.has("following")) throw new RouterError("Following collection dispatcher already set.");
424
450
  assertPath(path);
@@ -572,6 +598,10 @@ var FederationBuilderImpl = class {
572
598
  this.inboxErrorHandler = handler;
573
599
  return setters;
574
600
  },
601
+ onRequestFinished: (handler) => {
602
+ this.inboxRequestFinishedHandler = handler;
603
+ return setters;
604
+ },
575
605
  onUnverifiedActivity: (handler) => {
576
606
  this.unverifiedActivityHandler = handler;
577
607
  return setters;
@@ -612,6 +642,7 @@ var FederationBuilderImpl = class {
612
642
  if (this.collectionCallbacks[name] != null) throw new RouterError(`Collection dispatcher for ${strName} already set.`);
613
643
  assertPath(path);
614
644
  if (Router.variables(path).size < 1) throw new RouterError("Path for collection dispatcher must have at least one variable.");
645
+ this.#collectionNames.set(routeName, name);
615
646
  this.router.add(path, routeName);
616
647
  const callbacks = { dispatcher };
617
648
  this.collectionCallbacks[name] = callbacks;
@@ -632,6 +663,10 @@ var FederationBuilderImpl = class {
632
663
  authorize(predicate) {
633
664
  callbacks.authorizePredicate = predicate;
634
665
  return setters;
666
+ },
667
+ mapPortableOwner(mapper) {
668
+ callbacks.portableOwnerMapper = mapper;
669
+ return setters;
635
670
  }
636
671
  };
637
672
  return setters;
@@ -649,10 +684,62 @@ var FederationBuilderImpl = class {
649
684
  const routeName = this.#uniqueCollectionId(name);
650
685
  return this.router.build(`collection:${routeName}`, values) ?? this.router.build(`orderedCollection:${routeName}`, values);
651
686
  }
687
+ /** Resolves a custom collection route to its original name. */
688
+ getCollectionName(routeName) {
689
+ return this.#collectionNames.get(routeName) ?? routeName.replace(/^(collection|orderedCollection):/, "");
690
+ }
652
691
  setOutboxPermanentFailureHandler(handler) {
653
692
  this.outboxPermanentFailureHandler = handler;
654
693
  }
655
694
  /**
695
+ * Warns if a portable actor's collection properties that are portable IDs
696
+ * or compatible identifiers do not refer to the collections that
697
+ * the registered collection dispatchers serve through the FEP-ef61 gateway
698
+ * endpoint for the actor's DID. Properties with ordinary HTTP(S) URLs are
699
+ * not compared, since a portable actor may keep ordinary collections.
700
+ */
701
+ #warnPortableCollectionIds(context, identifier, actor) {
702
+ const did = actor.id == null ? null : getPortableDid(actor.id);
703
+ if (did == null) return;
704
+ const logger = getLogger([
705
+ "fedify",
706
+ "federation",
707
+ "actor"
708
+ ]);
709
+ const check = (registered, property, value, helper, build) => {
710
+ if (!registered || value == null || !isPortableId(value)) return;
711
+ const actual = getCanonicalPortableId(value);
712
+ if (actual == null) {
713
+ logger.warn("The actor's {property} property, {value}, is a malformed FEP-ef61 portable ID or compatible identifier.", {
714
+ property,
715
+ value: value.href
716
+ });
717
+ return;
718
+ }
719
+ let expected;
720
+ try {
721
+ expected = build();
722
+ } catch (error) {
723
+ if (error instanceof TypeError || error instanceof RouterError) return;
724
+ throw error;
725
+ }
726
+ if (actual === getCanonicalPortableId(expected)) return;
727
+ logger.warn("The portable actor's {property} property, {value}, does not match the portable ID of the collection that the gateway endpoint serves, {expected}. Set the property with Context.{helper}(identifier, did).", {
728
+ property,
729
+ value: value.href,
730
+ expected: expected.href,
731
+ helper
732
+ });
733
+ };
734
+ check(this.outboxCallbacks?.dispatcher != null, "outbox", actor.outboxId, "getPortableOutboxUri", () => context.getPortableOutboxUri(identifier, did));
735
+ check(this.inboxCallbacks?.dispatcher != null || this.router.has("inbox"), "inbox", actor.inboxId, "getPortableInboxUri", () => context.getPortableInboxUri(identifier, did));
736
+ check(this.followingCallbacks?.dispatcher != null, "following", actor.followingId, "getPortableFollowingUri", () => context.getPortableFollowingUri(identifier, did));
737
+ check(this.followersCallbacks?.dispatcher != null, "followers", actor.followersId, "getPortableFollowersUri", () => context.getPortableFollowersUri(identifier, did));
738
+ check(this.likedCallbacks?.dispatcher != null, "liked", actor.likedId, "getPortableLikedUri", () => context.getPortableLikedUri(identifier, did));
739
+ check(this.featuredCallbacks?.dispatcher != null, "featured", actor.featuredId, "getPortableFeaturedUri", () => context.getPortableFeaturedUri(identifier, did));
740
+ check(this.featuredTagsCallbacks?.dispatcher != null, "featuredTags", actor.featuredTagsId, "getPortableFeaturedTagsUri", () => context.getPortableFeaturedTagsUri(identifier, did));
741
+ }
742
+ /**
656
743
  * Converts a name (string or symbol) to a unique string identifier.
657
744
  * For symbols, generates and caches a UUID if not already present.
658
745
  * For strings, returns the string as-is.
@@ -673,5 +760,73 @@ var FederationBuilderImpl = class {
673
760
  function createFederationBuilder() {
674
761
  return new FederationBuilderImpl();
675
762
  }
763
+ function warnMismatchedTombstoneId(context, cls, values, tombstone) {
764
+ const logger = getLogger([
765
+ "fedify",
766
+ "federation",
767
+ "object"
768
+ ]);
769
+ if (tombstone.id == null) {
770
+ logger.warn("Object dispatcher for {class} returned a tombstone without an id property. Set the property with Context.getObjectUri().", {
771
+ class: cls.name,
772
+ values
773
+ });
774
+ return;
775
+ }
776
+ if (isPortableId(tombstone.id)) return;
777
+ const expected = context.getObjectUri(cls, values);
778
+ if (tombstone.id.href !== expected.href) logger.warn("Object dispatcher for {class} returned a tombstone with an id property {tombstoneId} that does not match the object URI {objectUri}. Set the property with Context.getObjectUri().", {
779
+ class: cls.name,
780
+ values,
781
+ tombstoneId: tombstone.id.href,
782
+ objectUri: expected.href
783
+ });
784
+ }
785
+ /**
786
+ * Warns about an FEP-ef61 portable actor whose `gateways` is empty or has
787
+ * an item that is not an HTTP(S) origin, which FEP-ef61 does not allow.
788
+ * Every item is checked, since the list and its URLs can be mutated after
789
+ * the actor is constructed.
790
+ */
791
+ function warnPortableActorGateways(actorId, gateways) {
792
+ if (gateways.length > 0 && gateways.every(isGatewayUrl)) return;
793
+ getLogger([
794
+ "fedify",
795
+ "federation",
796
+ "actor"
797
+ ]).warn("Actor dispatcher returned an FEP-ef61 portable actor, {actorId}, whose gateways property is empty or has an item that is not an HTTP(S) origin. FEP-ef61 requires a portable actor to have at least one gateway, and every gateway to be an HTTP(S) URI with an empty path, query, and fragment. Set the gateways property.", {
798
+ actorId: actorId.href,
799
+ gateways: gateways.map((g) => g.href)
800
+ });
801
+ }
802
+ /**
803
+ * Warns about an FEP-ef61 portable actor identified by a compatible identifier
804
+ * that is malformed, or is not on the actor's first gateway, where FEP-ef61
805
+ * requires publishers to construct compatible identifiers. A missing or
806
+ * invalid first gateway is reported by {@link warnPortableActorGateways}
807
+ * instead.
808
+ */
809
+ function warnCompatibleActorId(actorId, gateway) {
810
+ const logger = getLogger([
811
+ "fedify",
812
+ "federation",
813
+ "actor"
814
+ ]);
815
+ try {
816
+ fromCompatibleEf61Id(actorId);
817
+ } catch (error) {
818
+ if (!(error instanceof TypeError)) throw error;
819
+ logger.warn("Actor dispatcher returned an actor whose id property, {actorId}, is a malformed FEP-ef61 compatible identifier: {error}", {
820
+ actorId: actorId.href,
821
+ error
822
+ });
823
+ return;
824
+ }
825
+ if (gateway == null || !isGatewayUrl(gateway)) return;
826
+ if (actorId.origin !== gateway.origin) logger.warn("Actor dispatcher returned an actor whose id property, {actorId}, is an FEP-ef61 compatible identifier on another gateway than its first gateway, {gateway}. FEP-ef61 requires publishers to construct compatible identifiers with the first gateway in the actor's gateways.", {
827
+ actorId: actorId.href,
828
+ gateway: gateway.origin
829
+ });
830
+ }
676
831
  //#endregion
677
832
  export { FederationBuilderImpl as n, createFederationBuilder as r, ACTOR_ALIAS_PREFIX as t };