@fedify/fedify 2.1.23 → 2.1.24

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 (98) hide show
  1. package/dist/{assert_instance_of-C4Ri6VuN.mjs → assert-BhQd8QHP.mjs} +19 -1
  2. package/dist/{builder-BlCsjkrX.mjs → builder-BatYe9a2.mjs} +3 -3
  3. package/dist/{client-CZWLyLmp.mjs → client-DNiBssfx.mjs} +78 -4
  4. package/dist/compat/mod.d.cts +1 -1
  5. package/dist/compat/mod.d.ts +1 -1
  6. package/dist/compat/transformers.test.mjs +3 -4
  7. package/dist/{context-_l9t359k.d.ts → context-BgU5UWTx.d.ts} +4 -3
  8. package/dist/{context-o22vjzS2.d.cts → context-D4s0Wk3N.d.cts} +4 -3
  9. package/dist/{deno-B_Gwkjh7.mjs → deno-BXkm_rws.mjs} +1 -1
  10. package/dist/{docloader-B-IG1dVk.mjs → docloader-DdEK2tXP.mjs} +2 -2
  11. package/dist/federation/builder.test.mjs +2 -2
  12. package/dist/federation/collection.test.mjs +1 -1
  13. package/dist/federation/handler.test.mjs +127 -9
  14. package/dist/federation/idempotency.test.mjs +4 -4
  15. package/dist/federation/inbox.test.mjs +1 -1
  16. package/dist/federation/keycache.test.mjs +44 -10
  17. package/dist/federation/kv.test.mjs +1 -1
  18. package/dist/federation/middleware.test.mjs +99 -11
  19. package/dist/federation/mod.cjs +1 -1
  20. package/dist/federation/mod.d.cts +2 -2
  21. package/dist/federation/mod.d.ts +2 -2
  22. package/dist/federation/mod.js +1 -1
  23. package/dist/federation/mq.test.mjs +1 -1
  24. package/dist/federation/negotiation.test.mjs +2 -2
  25. package/dist/federation/retry.test.mjs +1 -1
  26. package/dist/federation/router.test.mjs +1 -1
  27. package/dist/federation/send.test.mjs +138 -6
  28. package/dist/federation/temporal.test.mjs +2 -2
  29. package/dist/federation/webfinger.test.mjs +2 -2
  30. package/dist/{http-Yoq0YGz7.cjs → http-7FmLhLDv.cjs} +166 -6
  31. package/dist/{http-88deUx3Y.js → http-Chr54tTL.js} +155 -7
  32. package/dist/{http-BDZeS5om.d.ts → http-Dl00HXr4.d.ts} +1 -1
  33. package/dist/{http-C87EWkO0.d.cts → http-DqZhyEso.d.cts} +1 -1
  34. package/dist/{http-DIh9_s_-.mjs → http-UyebnM2c.mjs} +3 -3
  35. package/dist/{inbox-BxCHIWPD.mjs → inbox-ByQ2iD14.mjs} +1 -1
  36. package/dist/{key-DywPPmb0.mjs → key-A8SuFznD.mjs} +154 -6
  37. package/dist/{keycache-CCSwkQcY.mjs → keycache-CaO7wyQA.mjs} +12 -4
  38. package/dist/{kv-cache-HA011rBG.cjs → kv-cache-DJhBDA9T.cjs} +1 -1
  39. package/dist/{kv-cache-rHQOc5rE.js → kv-cache-J6hmiAEd.js} +1 -1
  40. package/dist/{ld-Ch6FVq7X.mjs → ld-BSvHU-S0.mjs} +2 -2
  41. package/dist/{middleware-itcr4fAv.cjs → middleware-Bddj287b.cjs} +1 -1
  42. package/dist/{middleware-CUNIlYzF.cjs → middleware-CCYqHlzn.cjs} +90 -14
  43. package/dist/{middleware-CYsQG25-.js → middleware-Do50b12a.js} +90 -14
  44. package/dist/{middleware-DABFg_Xy.mjs → middleware-DvxNTKpl.mjs} +1 -1
  45. package/dist/{middleware-D2O8b03q.mjs → middleware-Dy18K1xP.mjs} +31 -20
  46. package/dist/{mod-CjiK2zrW.d.ts → mod-BLDHhuW0.d.ts} +1 -1
  47. package/dist/{mod-0dF0OeGw.d.cts → mod-Bx80LUTA.d.cts} +1 -1
  48. package/dist/{mod-BTWFtZwa.d.ts → mod-CMK_S-eX.d.ts} +1 -1
  49. package/dist/{mod-Bv1elC-b.d.ts → mod-DcAiY74j.d.ts} +1 -1
  50. package/dist/{mod-D5YlzzP3.d.cts → mod-DiuFTYUt.d.cts} +1 -1
  51. package/dist/{mod-dxOnKp2Y.d.cts → mod-DniKVJ_C.d.cts} +1 -1
  52. package/dist/mod.cjs +5 -5
  53. package/dist/mod.d.cts +6 -6
  54. package/dist/mod.d.ts +6 -6
  55. package/dist/mod.js +5 -5
  56. package/dist/nodeinfo/client.test.mjs +28 -1
  57. package/dist/nodeinfo/handler.test.mjs +2 -2
  58. package/dist/nodeinfo/mod.cjs +1 -1
  59. package/dist/nodeinfo/mod.js +1 -1
  60. package/dist/nodeinfo/types.test.mjs +1 -1
  61. package/dist/otel/exporter.test.mjs +1 -1
  62. package/dist/{owner-DEvZuyOE.d.cts → owner-B3hNQCG8.d.cts} +11 -0
  63. package/dist/owner-CaaCVHsG.mjs +175 -0
  64. package/dist/{owner-CnngXDNJ.d.ts → owner-CiBPcC6F.d.ts} +11 -0
  65. package/dist/{proof-K3inAqnp.js → proof-BrOQrPQf.js} +112 -58
  66. package/dist/{proof-CEn2R6W9.cjs → proof-CaCUMcvk.cjs} +112 -58
  67. package/dist/{proof-Dt5GV-xi.mjs → proof-_AyA4r7z.mjs} +2 -2
  68. package/dist/{send-CqaJDT2z.mjs → send-B1CRgb14.mjs} +64 -6
  69. package/dist/sig/accept.test.mjs +1 -1
  70. package/dist/sig/http.test.mjs +4 -4
  71. package/dist/sig/key.test.mjs +170 -3
  72. package/dist/sig/ld.test.mjs +56 -4
  73. package/dist/sig/mod.cjs +2 -2
  74. package/dist/sig/mod.d.cts +3 -3
  75. package/dist/sig/mod.d.ts +3 -3
  76. package/dist/sig/mod.js +2 -2
  77. package/dist/sig/owner.test.mjs +105 -6
  78. package/dist/sig/proof.test.mjs +72 -3
  79. package/dist/{temporal-G_GDghC-.mjs → temporal-Pmk5ouB1.mjs} +1 -1
  80. package/dist/{types-m8u9L86X.cjs → types-DWs-qZaY.cjs} +94 -2
  81. package/dist/{types-DTONwNqL.js → types-sXITXcWa.js} +78 -4
  82. package/dist/utils/docloader.test.mjs +28 -4
  83. package/dist/utils/kv-cache.test.mjs +1 -1
  84. package/dist/utils/mod.cjs +1 -1
  85. package/dist/utils/mod.d.cts +1 -1
  86. package/dist/utils/mod.d.ts +1 -1
  87. package/dist/utils/mod.js +1 -1
  88. package/package.json +6 -6
  89. package/dist/assert-ddO5KLpe.mjs +0 -23
  90. package/dist/owner-Cygg-fHW.mjs +0 -120
  91. /package/dist/{accept-Dd__NiUL.mjs → accept-BavzedPB.mjs} +0 -0
  92. /package/dist/{collection-BD6-SZ6O.mjs → collection-ChgDTHLz.mjs} +0 -0
  93. /package/dist/{keys-BAK-tUlf.mjs → keys-CtZLJq76.mjs} +0 -0
  94. /package/dist/{kv-tL2TOE9X.mjs → kv-BrZHNugx.mjs} +0 -0
  95. /package/dist/{kv-cache-FsT1ljhs.mjs → kv-cache-DqEKe5E0.mjs} +0 -0
  96. /package/dist/{negotiation-DnsfFF8I.mjs → negotiation-BehA2uul.mjs} +0 -0
  97. /package/dist/{retry-CJL0poaU.mjs → retry-B_E3V_Dx.mjs} +0 -0
  98. /package/dist/{types-DCP0WLdt.mjs → types-C37hquWI.mjs} +0 -0
@@ -2,10 +2,10 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  const require_chunk = require("./chunk-DDcVe30Y.cjs");
4
4
  const require_transformers = require("./transformers-NeAONrAq.cjs");
5
- const require_http = require("./http-Yoq0YGz7.cjs");
6
- const require_proof = require("./proof-CEn2R6W9.cjs");
7
- const require_types = require("./types-m8u9L86X.cjs");
8
- const require_kv_cache = require("./kv-cache-HA011rBG.cjs");
5
+ const require_http = require("./http-7FmLhLDv.cjs");
6
+ const require_types = require("./types-DWs-qZaY.cjs");
7
+ const require_proof = require("./proof-CaCUMcvk.cjs");
8
+ const require_kv_cache = require("./kv-cache-DJhBDA9T.cjs");
9
9
  let _logtape_logtape = require("@logtape/logtape");
10
10
  let _fedify_vocab = require("@fedify/vocab");
11
11
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -336,7 +336,7 @@ var FederationBuilderImpl = class {
336
336
  this.collectionTypeIds = {};
337
337
  }
338
338
  async build(options) {
339
- const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-itcr4fAv.cjs"));
339
+ const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-Bddj287b.cjs"));
340
340
  const f = new FederationImpl(options);
341
341
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
342
342
  f.router = this.router.clone();
@@ -862,6 +862,7 @@ async function buildCollectionSynchronizationHeader(collectionId, actorIds) {
862
862
  }
863
863
  //#endregion
864
864
  //#region src/federation/keycache.ts
865
+ const KEY_CACHE_GENERATION = "2";
865
866
  var KvKeyCache = class {
866
867
  kv;
867
868
  prefix;
@@ -882,13 +883,20 @@ var KvKeyCache = class {
882
883
  keyId.href
883
884
  ];
884
885
  }
886
+ #entryKey(keyId) {
887
+ return [
888
+ ...this.prefix,
889
+ KEY_CACHE_GENERATION,
890
+ keyId.href
891
+ ];
892
+ }
885
893
  async get(keyId) {
886
894
  const negativeExpiration = this.nullKeys.get(keyId.href);
887
895
  if (negativeExpiration != null) {
888
896
  if (Temporal.Now.instant().until(negativeExpiration).sign >= 0) return null;
889
897
  this.nullKeys.delete(keyId.href);
890
898
  }
891
- const serialized = await this.kv.get([...this.prefix, keyId.href]);
899
+ const serialized = await this.kv.get(this.#entryKey(keyId));
892
900
  if (serialized === void 0) return void 0;
893
901
  if (serialized === null) {
894
902
  this.nullKeys.set(keyId.href, Temporal.Now.instant().add(this.unavailableKeyTtl));
@@ -900,7 +908,7 @@ var KvKeyCache = class {
900
908
  try {
901
909
  return await _fedify_vocab.Multikey.fromJsonLd(serialized, this.options);
902
910
  } catch {
903
- await this.kv.delete([...this.prefix, keyId.href]);
911
+ await this.kv.delete(this.#entryKey(keyId));
904
912
  return;
905
913
  }
906
914
  }
@@ -908,12 +916,12 @@ var KvKeyCache = class {
908
916
  async set(keyId, key) {
909
917
  if (key == null) {
910
918
  this.nullKeys.set(keyId.href, Temporal.Now.instant().add(this.unavailableKeyTtl));
911
- await this.kv.set([...this.prefix, keyId.href], null, { ttl: this.unavailableKeyTtl });
919
+ await this.kv.set(this.#entryKey(keyId), null, { ttl: this.unavailableKeyTtl });
912
920
  return;
913
921
  }
914
922
  this.nullKeys.delete(keyId.href);
915
923
  const serialized = await key.toJsonLd(this.options);
916
- await this.kv.set([...this.prefix, keyId.href], serialized);
924
+ await this.kv.set(this.#entryKey(keyId), serialized);
917
925
  }
918
926
  async getFetchError(keyId) {
919
927
  const cached = await this.kv.get(this.#getFetchErrorKey(keyId));
@@ -1427,8 +1435,16 @@ async function handleInboxInternal(request, parameters, span) {
1427
1435
  }
1428
1436
  let json;
1429
1437
  try {
1430
- json = await request.clone().json();
1438
+ json = JSON.parse(await require_types.readBoundedText(request.clone(), require_types.MAX_BODY_SIZE, request.url));
1431
1439
  } catch (error) {
1440
+ if (error instanceof require_types.BodyTooLargeError) {
1441
+ request.body?.cancel(error).catch(() => {});
1442
+ span.setStatus({
1443
+ code: _opentelemetry_api.SpanStatusCode.ERROR,
1444
+ message: String(error)
1445
+ });
1446
+ return new Response("Inbox body too large.", { status: 413 });
1447
+ }
1432
1448
  logger.error("Failed to parse JSON:\n{error}", {
1433
1449
  recipient,
1434
1450
  error
@@ -2445,18 +2461,31 @@ async function readLimitedResponseBody(response, maxBytes) {
2445
2461
  if (truncated) result += "… (truncated)";
2446
2462
  return result;
2447
2463
  }
2448
- async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }, span) {
2464
+ async function sendActivityInternal({ activity, activityId, keys, inbox, allowPrivateAddress, headers, specDeterminer, tracerProvider }, span) {
2449
2465
  const logger = (0, _logtape_logtape.getLogger)([
2450
2466
  "fedify",
2451
2467
  "federation",
2452
2468
  "outbox"
2453
2469
  ]);
2470
+ async function validateUrl(url) {
2471
+ if (!allowPrivateAddress) try {
2472
+ await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
2473
+ } catch (error) {
2474
+ if (error instanceof _fedify_vocab_runtime.UrlError) logger.error("Disallowed private URL: {url}", {
2475
+ url,
2476
+ error
2477
+ });
2478
+ throw error;
2479
+ }
2480
+ }
2481
+ await validateUrl(inbox.href);
2454
2482
  headers = new Headers(headers);
2455
2483
  headers.set("Content-Type", "application/activity+json");
2456
2484
  const request = new Request(inbox, {
2457
2485
  method: "POST",
2458
2486
  headers,
2459
- body: JSON.stringify(activity)
2487
+ body: JSON.stringify(activity),
2488
+ redirect: "manual"
2460
2489
  });
2461
2490
  let rsaKey = null;
2462
2491
  for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
@@ -2472,9 +2501,10 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2472
2501
  });
2473
2502
  let response;
2474
2503
  try {
2475
- response = rsaKey == null ? await fetch(request) : await require_http.doubleKnock(request, rsaKey, {
2504
+ response = rsaKey == null ? await fetchWithValidatedRedirects(request, validateUrl) : await require_http.doubleKnock(request, rsaKey, {
2476
2505
  tracerProvider,
2477
- specDeterminer
2506
+ specDeterminer,
2507
+ validateRedirect: validateUrl
2478
2508
  });
2479
2509
  } catch (error) {
2480
2510
  logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
@@ -2506,6 +2536,49 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2506
2536
  "activitypub.activity.id": activityId ?? ""
2507
2537
  });
2508
2538
  }
2539
+ async function fetchWithValidatedRedirects(request, validateUrl) {
2540
+ let body = await request.clone().text();
2541
+ for (let redirects = 0;; redirects++) {
2542
+ const response = await fetch(request, { redirect: "manual" });
2543
+ const location = response.headers.get("Location");
2544
+ if (![
2545
+ 301,
2546
+ 302,
2547
+ 303,
2548
+ 307,
2549
+ 308
2550
+ ].includes(response.status) || location == null) return response;
2551
+ await response.body?.cancel();
2552
+ if (redirects >= 20) throw new TypeError("Too many redirects");
2553
+ const url = new URL(location, request.url);
2554
+ await validateUrl(url.href);
2555
+ const headers = new Headers(request.headers);
2556
+ if (url.origin !== new URL(request.url).origin) {
2557
+ headers.delete("Authorization");
2558
+ headers.delete("Proxy-Authorization");
2559
+ headers.delete("Cookie");
2560
+ headers.delete("Host");
2561
+ }
2562
+ let method = request.method;
2563
+ if ((response.status === 301 || response.status === 302) && method === "POST" || response.status === 303 && method !== "GET" && method !== "HEAD") {
2564
+ method = "GET";
2565
+ body = void 0;
2566
+ for (const name of [
2567
+ "Content-Encoding",
2568
+ "Content-Language",
2569
+ "Content-Length",
2570
+ "Content-Location",
2571
+ "Content-Type"
2572
+ ]) headers.delete(name);
2573
+ }
2574
+ request = new Request(url, {
2575
+ method,
2576
+ headers,
2577
+ body,
2578
+ redirect: "manual"
2579
+ });
2580
+ }
2581
+ }
2509
2582
  /**
2510
2583
  * An error that is thrown when an activity fails to send to a remote inbox.
2511
2584
  * It contains structured information about the failure, including the HTTP
@@ -3007,6 +3080,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3007
3080
  }
3008
3081
  try {
3009
3082
  await sendActivity({
3083
+ allowPrivateAddress: this.allowPrivateAddress,
3010
3084
  keys,
3011
3085
  activity: message.activity,
3012
3086
  activityId: message.activityId,
@@ -3398,6 +3472,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3398
3472
  });
3399
3473
  const promises = [];
3400
3474
  for (const inbox in inboxes) promises.push(sendActivity({
3475
+ allowPrivateAddress: this.allowPrivateAddress,
3401
3476
  keys,
3402
3477
  activity: jsonLd,
3403
3478
  activityId: activity.id?.href,
@@ -4556,6 +4631,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
4556
4631
  else logger.debug("Forwarding activity immediately without queue since queue is not set.");
4557
4632
  const promises = [];
4558
4633
  for (const inbox in inboxes) promises.push(sendActivity({
4634
+ allowPrivateAddress: this.federation.allowPrivateAddress,
4559
4635
  keys,
4560
4636
  activity: this.activity,
4561
4637
  activityId: this.activityId,
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { t as __exportAll } from "./chunk-CRNNMoPX.js";
4
4
  import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
5
- import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-88deUx3Y.js";
6
- import { _ as signJsonLd, a as doesActorOwnKey, c as assertSafeJsonLd, f as detachSignature, g as isInvalidUrlTypeError, h as isClearlyMalformedContextReference, m as hasSignature, n as signObject, o as getKeyOwner, p as getNormalizationContextLoader, r as verifyObject, s as InvalidContextReferenceError, u as compactJsonLd, v as verifyCompactJsonLd, x as wrapContextLoaderForJsonLd } from "./proof-K3inAqnp.js";
7
- import { n as getNodeInfo, t as nodeInfoToJson } from "./types-DTONwNqL.js";
8
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-rHQOc5rE.js";
5
+ import { a as verifyRequestDetailed, d as importJwk, f as validateCryptoKey, i as verifyRequest, m as formatAcceptSignature, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as name, y as version } from "./http-Chr54tTL.js";
6
+ import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-sXITXcWa.js";
7
+ import { _ as signJsonLd, a as doesActorOwnKey, c as assertSafeJsonLd, f as detachSignature, g as isInvalidUrlTypeError, h as isClearlyMalformedContextReference, m as hasSignature, n as signObject, o as getKeyOwner, p as getNormalizationContextLoader, r as verifyObject, s as InvalidContextReferenceError, u as compactJsonLd, v as verifyCompactJsonLd, x as wrapContextLoaderForJsonLd } from "./proof-BrOQrPQf.js";
8
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-J6hmiAEd.js";
9
9
  import { getLogger, withContext } from "@logtape/logtape";
10
10
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
11
11
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -13,7 +13,7 @@ import { cloneDeep, uniq } from "es-toolkit";
13
13
  import { Router } from "uri-template-router";
14
14
  import { parseTemplate } from "url-template";
15
15
  import { encodeHex } from "byte-encodings/hex";
16
- import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
16
+ import { FetchError, UrlError, getDocumentLoader, validatePublicUrl } from "@fedify/vocab-runtime";
17
17
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
18
18
  import jsonld from "@fedify/vocab-runtime/jsonld";
19
19
  import { lookupWebFinger } from "@fedify/webfinger";
@@ -861,6 +861,7 @@ async function buildCollectionSynchronizationHeader(collectionId, actorIds) {
861
861
  }
862
862
  //#endregion
863
863
  //#region src/federation/keycache.ts
864
+ const KEY_CACHE_GENERATION = "2";
864
865
  var KvKeyCache = class {
865
866
  kv;
866
867
  prefix;
@@ -881,13 +882,20 @@ var KvKeyCache = class {
881
882
  keyId.href
882
883
  ];
883
884
  }
885
+ #entryKey(keyId) {
886
+ return [
887
+ ...this.prefix,
888
+ KEY_CACHE_GENERATION,
889
+ keyId.href
890
+ ];
891
+ }
884
892
  async get(keyId) {
885
893
  const negativeExpiration = this.nullKeys.get(keyId.href);
886
894
  if (negativeExpiration != null) {
887
895
  if (Temporal.Now.instant().until(negativeExpiration).sign >= 0) return null;
888
896
  this.nullKeys.delete(keyId.href);
889
897
  }
890
- const serialized = await this.kv.get([...this.prefix, keyId.href]);
898
+ const serialized = await this.kv.get(this.#entryKey(keyId));
891
899
  if (serialized === void 0) return void 0;
892
900
  if (serialized === null) {
893
901
  this.nullKeys.set(keyId.href, Temporal.Now.instant().add(this.unavailableKeyTtl));
@@ -899,7 +907,7 @@ var KvKeyCache = class {
899
907
  try {
900
908
  return await Multikey.fromJsonLd(serialized, this.options);
901
909
  } catch {
902
- await this.kv.delete([...this.prefix, keyId.href]);
910
+ await this.kv.delete(this.#entryKey(keyId));
903
911
  return;
904
912
  }
905
913
  }
@@ -907,12 +915,12 @@ var KvKeyCache = class {
907
915
  async set(keyId, key) {
908
916
  if (key == null) {
909
917
  this.nullKeys.set(keyId.href, Temporal.Now.instant().add(this.unavailableKeyTtl));
910
- await this.kv.set([...this.prefix, keyId.href], null, { ttl: this.unavailableKeyTtl });
918
+ await this.kv.set(this.#entryKey(keyId), null, { ttl: this.unavailableKeyTtl });
911
919
  return;
912
920
  }
913
921
  this.nullKeys.delete(keyId.href);
914
922
  const serialized = await key.toJsonLd(this.options);
915
- await this.kv.set([...this.prefix, keyId.href], serialized);
923
+ await this.kv.set(this.#entryKey(keyId), serialized);
916
924
  }
917
925
  async getFetchError(keyId) {
918
926
  const cached = await this.kv.get(this.#getFetchErrorKey(keyId));
@@ -1426,8 +1434,16 @@ async function handleInboxInternal(request, parameters, span) {
1426
1434
  }
1427
1435
  let json;
1428
1436
  try {
1429
- json = await request.clone().json();
1437
+ json = JSON.parse(await readBoundedText(request.clone(), MAX_BODY_SIZE, request.url));
1430
1438
  } catch (error) {
1439
+ if (error instanceof BodyTooLargeError) {
1440
+ request.body?.cancel(error).catch(() => {});
1441
+ span.setStatus({
1442
+ code: SpanStatusCode.ERROR,
1443
+ message: String(error)
1444
+ });
1445
+ return new Response("Inbox body too large.", { status: 413 });
1446
+ }
1431
1447
  logger.error("Failed to parse JSON:\n{error}", {
1432
1448
  recipient,
1433
1449
  error
@@ -2444,18 +2460,31 @@ async function readLimitedResponseBody(response, maxBytes) {
2444
2460
  if (truncated) result += "… (truncated)";
2445
2461
  return result;
2446
2462
  }
2447
- async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }, span) {
2463
+ async function sendActivityInternal({ activity, activityId, keys, inbox, allowPrivateAddress, headers, specDeterminer, tracerProvider }, span) {
2448
2464
  const logger = getLogger([
2449
2465
  "fedify",
2450
2466
  "federation",
2451
2467
  "outbox"
2452
2468
  ]);
2469
+ async function validateUrl(url) {
2470
+ if (!allowPrivateAddress) try {
2471
+ await validatePublicUrl(url);
2472
+ } catch (error) {
2473
+ if (error instanceof UrlError) logger.error("Disallowed private URL: {url}", {
2474
+ url,
2475
+ error
2476
+ });
2477
+ throw error;
2478
+ }
2479
+ }
2480
+ await validateUrl(inbox.href);
2453
2481
  headers = new Headers(headers);
2454
2482
  headers.set("Content-Type", "application/activity+json");
2455
2483
  const request = new Request(inbox, {
2456
2484
  method: "POST",
2457
2485
  headers,
2458
- body: JSON.stringify(activity)
2486
+ body: JSON.stringify(activity),
2487
+ redirect: "manual"
2459
2488
  });
2460
2489
  let rsaKey = null;
2461
2490
  for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
@@ -2471,9 +2500,10 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2471
2500
  });
2472
2501
  let response;
2473
2502
  try {
2474
- response = rsaKey == null ? await fetch(request) : await doubleKnock(request, rsaKey, {
2503
+ response = rsaKey == null ? await fetchWithValidatedRedirects(request, validateUrl) : await doubleKnock(request, rsaKey, {
2475
2504
  tracerProvider,
2476
- specDeterminer
2505
+ specDeterminer,
2506
+ validateRedirect: validateUrl
2477
2507
  });
2478
2508
  } catch (error) {
2479
2509
  logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
@@ -2505,6 +2535,49 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
2505
2535
  "activitypub.activity.id": activityId ?? ""
2506
2536
  });
2507
2537
  }
2538
+ async function fetchWithValidatedRedirects(request, validateUrl) {
2539
+ let body = await request.clone().text();
2540
+ for (let redirects = 0;; redirects++) {
2541
+ const response = await fetch(request, { redirect: "manual" });
2542
+ const location = response.headers.get("Location");
2543
+ if (![
2544
+ 301,
2545
+ 302,
2546
+ 303,
2547
+ 307,
2548
+ 308
2549
+ ].includes(response.status) || location == null) return response;
2550
+ await response.body?.cancel();
2551
+ if (redirects >= 20) throw new TypeError("Too many redirects");
2552
+ const url = new URL(location, request.url);
2553
+ await validateUrl(url.href);
2554
+ const headers = new Headers(request.headers);
2555
+ if (url.origin !== new URL(request.url).origin) {
2556
+ headers.delete("Authorization");
2557
+ headers.delete("Proxy-Authorization");
2558
+ headers.delete("Cookie");
2559
+ headers.delete("Host");
2560
+ }
2561
+ let method = request.method;
2562
+ if ((response.status === 301 || response.status === 302) && method === "POST" || response.status === 303 && method !== "GET" && method !== "HEAD") {
2563
+ method = "GET";
2564
+ body = void 0;
2565
+ for (const name of [
2566
+ "Content-Encoding",
2567
+ "Content-Language",
2568
+ "Content-Length",
2569
+ "Content-Location",
2570
+ "Content-Type"
2571
+ ]) headers.delete(name);
2572
+ }
2573
+ request = new Request(url, {
2574
+ method,
2575
+ headers,
2576
+ body,
2577
+ redirect: "manual"
2578
+ });
2579
+ }
2580
+ }
2508
2581
  /**
2509
2582
  * An error that is thrown when an activity fails to send to a remote inbox.
2510
2583
  * It contains structured information about the failure, including the HTTP
@@ -3013,6 +3086,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3013
3086
  }
3014
3087
  try {
3015
3088
  await sendActivity({
3089
+ allowPrivateAddress: this.allowPrivateAddress,
3016
3090
  keys,
3017
3091
  activity: message.activity,
3018
3092
  activityId: message.activityId,
@@ -3404,6 +3478,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3404
3478
  });
3405
3479
  const promises = [];
3406
3480
  for (const inbox in inboxes) promises.push(sendActivity({
3481
+ allowPrivateAddress: this.allowPrivateAddress,
3407
3482
  keys,
3408
3483
  activity: jsonLd,
3409
3484
  activityId: activity.id?.href,
@@ -4562,6 +4637,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
4562
4637
  else logger.debug("Forwarding activity immediately without queue since queue is not set.");
4563
4638
  const promises = [];
4564
4639
  for (const inbox in inboxes) promises.push(sendActivity({
4640
+ allowPrivateAddress: this.federation.allowPrivateAddress,
4565
4641
  keys,
4566
4642
  activity: this.activity,
4567
4643
  activityId: this.activityId,
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as FederationImpl } from "./middleware-D2O8b03q.mjs";
4
+ import { n as FederationImpl } from "./middleware-Dy18K1xP.mjs";
5
5
  export { FederationImpl };
@@ -2,25 +2,25 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { n as RouterError } from "./router-CrMLXoOr.mjs";
5
- import { n as version, t as name } from "./deno-B_Gwkjh7.mjs";
6
- import { t as formatAcceptSignature } from "./accept-Dd__NiUL.mjs";
7
- import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-DywPPmb0.mjs";
8
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-DIh9_s_-.mjs";
9
- import { t as getAuthenticatedDocumentLoader } from "./docloader-B-IG1dVk.mjs";
10
- import { n as kvCache } from "./kv-cache-FsT1ljhs.mjs";
11
- import { a as compactJsonLd, c as getNormalizationContextLoader, d as isInvalidUrlTypeError, f as signJsonLd, g as wrapContextLoaderForJsonLd, l as hasSignature, p as verifyCompactJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as isClearlyMalformedContextReference } from "./ld-Ch6FVq7X.mjs";
12
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-Cygg-fHW.mjs";
13
- import { n as signObject, r as verifyObject } from "./proof-Dt5GV-xi.mjs";
14
- import { t as getNodeInfo } from "./client-CZWLyLmp.mjs";
15
- import { t as nodeInfoToJson } from "./types-DCP0WLdt.mjs";
16
- import { n as routeActivity } from "./inbox-BxCHIWPD.mjs";
17
- import { t as FederationBuilderImpl } from "./builder-BlCsjkrX.mjs";
18
- import { t as buildCollectionSynchronizationHeader } from "./collection-BD6-SZ6O.mjs";
19
- import { t as KvKeyCache } from "./keycache-CCSwkQcY.mjs";
20
- import { t as acceptsJsonLd } from "./negotiation-DnsfFF8I.mjs";
21
- import { t as hasMalformedKnownTemporalLiteral } from "./temporal-G_GDghC-.mjs";
22
- import { t as createExponentialBackoffPolicy } from "./retry-CJL0poaU.mjs";
23
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CqaJDT2z.mjs";
5
+ import { n as version, t as name } from "./deno-BXkm_rws.mjs";
6
+ import { t as formatAcceptSignature } from "./accept-BavzedPB.mjs";
7
+ import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-A8SuFznD.mjs";
8
+ import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-UyebnM2c.mjs";
9
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-DdEK2tXP.mjs";
10
+ import { n as kvCache } from "./kv-cache-DqEKe5E0.mjs";
11
+ import { a as compactJsonLd, c as getNormalizationContextLoader, d as isInvalidUrlTypeError, f as signJsonLd, g as wrapContextLoaderForJsonLd, l as hasSignature, p as verifyCompactJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as isClearlyMalformedContextReference } from "./ld-BSvHU-S0.mjs";
12
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CaaCVHsG.mjs";
13
+ import { n as signObject, r as verifyObject } from "./proof-_AyA4r7z.mjs";
14
+ import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-DNiBssfx.mjs";
15
+ import { t as nodeInfoToJson } from "./types-C37hquWI.mjs";
16
+ import { n as routeActivity } from "./inbox-ByQ2iD14.mjs";
17
+ import { t as FederationBuilderImpl } from "./builder-BatYe9a2.mjs";
18
+ import { t as buildCollectionSynchronizationHeader } from "./collection-ChgDTHLz.mjs";
19
+ import { t as KvKeyCache } from "./keycache-CaO7wyQA.mjs";
20
+ import { t as acceptsJsonLd } from "./negotiation-BehA2uul.mjs";
21
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-Pmk5ouB1.mjs";
22
+ import { t as createExponentialBackoffPolicy } from "./retry-B_E3V_Dx.mjs";
23
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-B1CRgb14.mjs";
24
24
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
25
25
  import { lookupWebFinger } from "@fedify/webfinger";
26
26
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -476,8 +476,16 @@ async function handleInboxInternal(request, parameters, span) {
476
476
  }
477
477
  let json;
478
478
  try {
479
- json = await request.clone().json();
479
+ json = JSON.parse(await readBoundedText(request.clone(), MAX_BODY_SIZE, request.url));
480
480
  } catch (error) {
481
+ if (error instanceof BodyTooLargeError) {
482
+ request.body?.cancel(error).catch(() => {});
483
+ span.setStatus({
484
+ code: SpanStatusCode.ERROR,
485
+ message: String(error)
486
+ });
487
+ return new Response("Inbox body too large.", { status: 413 });
488
+ }
481
489
  logger.error("Failed to parse JSON:\n{error}", {
482
490
  recipient,
483
491
  error
@@ -1806,6 +1814,7 @@ var FederationImpl = class extends FederationBuilderImpl {
1806
1814
  }
1807
1815
  try {
1808
1816
  await sendActivity({
1817
+ allowPrivateAddress: this.allowPrivateAddress,
1809
1818
  keys,
1810
1819
  activity: message.activity,
1811
1820
  activityId: message.activityId,
@@ -2197,6 +2206,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2197
2206
  });
2198
2207
  const promises = [];
2199
2208
  for (const inbox in inboxes) promises.push(sendActivity({
2209
+ allowPrivateAddress: this.allowPrivateAddress,
2200
2210
  keys,
2201
2211
  activity: jsonLd,
2202
2212
  activityId: activity.id?.href,
@@ -3355,6 +3365,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
3355
3365
  else logger.debug("Forwarding activity immediately without queue since queue is not set.");
3356
3366
  const promises = [];
3357
3367
  for (const inbox in inboxes) promises.push(sendActivity({
3368
+ allowPrivateAddress: this.federation.allowPrivateAddress,
3358
3369
  keys,
3359
3370
  activity: this.activity,
3360
3371
  activityId: this.activityId,
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { S as KeyCache } from "./http-BDZeS5om.js";
2
+ import { S as KeyCache } from "./http-Dl00HXr4.js";
3
3
  import { CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1 } from "@fedify/vocab";
4
4
  import { TracerProvider } from "@opentelemetry/api";
5
5
  import { DocumentLoader } from "@fedify/vocab-runtime";
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { Q as ActorHandleMapper, X as ActorAliasMapper, Z as ActorDispatcher, _t as WebFingerLinksDispatcher, s as RequestContext } from "./context-o22vjzS2.cjs";
2
+ import { Q as ActorHandleMapper, X as ActorAliasMapper, Z as ActorDispatcher, _t as WebFingerLinksDispatcher, s as RequestContext } from "./context-D4s0Wk3N.cjs";
3
3
  import { Span, Tracer } from "@opentelemetry/api";
4
4
 
5
5
  //#region src/federation/webfinger.d.ts
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { n as HttpMessageSignaturesSpecDeterminer } from "./http-BDZeS5om.js";
2
+ import { n as HttpMessageSignaturesSpecDeterminer } from "./http-Dl00HXr4.js";
3
3
  import { n as KvStore, t as KvKey } from "./kv-D6hNiMTK.js";
4
4
  import { TracerProvider } from "@opentelemetry/api";
5
5
  import { DocumentLoader, DocumentLoaderFactoryOptions } from "@fedify/vocab-runtime";
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { Q as ActorHandleMapper, X as ActorAliasMapper, Z as ActorDispatcher, _t as WebFingerLinksDispatcher, s as RequestContext } from "./context-_l9t359k.js";
2
+ import { Q as ActorHandleMapper, X as ActorAliasMapper, Z as ActorDispatcher, _t as WebFingerLinksDispatcher, s as RequestContext } from "./context-BgU5UWTx.js";
3
3
  import { Span, Tracer } from "@opentelemetry/api";
4
4
 
5
5
  //#region src/federation/webfinger.d.ts
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { S as KeyCache } from "./http-C87EWkO0.cjs";
2
+ import { S as KeyCache } from "./http-DqZhyEso.cjs";
3
3
  import { CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1 } from "@fedify/vocab";
4
4
  import { DocumentLoader } from "@fedify/vocab-runtime";
5
5
  import { TracerProvider } from "@opentelemetry/api";
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { n as HttpMessageSignaturesSpecDeterminer } from "./http-C87EWkO0.cjs";
2
+ import { n as HttpMessageSignaturesSpecDeterminer } from "./http-DqZhyEso.cjs";
3
3
  import { n as KvStore, t as KvKey } from "./kv-gJ8LYbxX.cjs";
4
4
  import { DocumentLoader, DocumentLoaderFactoryOptions } from "@fedify/vocab-runtime";
5
5
  import { TracerProvider } from "@opentelemetry/api";
package/dist/mod.cjs CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("./chunk-DDcVe30Y.cjs");
5
5
  const require_transformers = require("./transformers-NeAONrAq.cjs");
6
6
  require("./compat/mod.cjs");
7
- const require_http = require("./http-Yoq0YGz7.cjs");
8
- const require_middleware = require("./middleware-CUNIlYzF.cjs");
9
- const require_proof = require("./proof-CEn2R6W9.cjs");
10
- const require_types = require("./types-m8u9L86X.cjs");
11
- const require_kv_cache = require("./kv-cache-HA011rBG.cjs");
7
+ const require_http = require("./http-7FmLhLDv.cjs");
8
+ const require_middleware = require("./middleware-CCYqHlzn.cjs");
9
+ const require_types = require("./types-DWs-qZaY.cjs");
10
+ const require_proof = require("./proof-CaCUMcvk.cjs");
11
+ const require_kv_cache = require("./kv-cache-DJhBDA9T.cjs");
12
12
  const require_federation_mod = require("./federation/mod.cjs");
13
13
  require("./nodeinfo/mod.cjs");
14
14
  require("./runtime/mod.cjs");
package/dist/mod.d.cts CHANGED
@@ -1,13 +1,13 @@
1
1
  /// <reference lib="esnext.temporal" />
2
2
  import { a as InboundService, c as OutboundService, d as Software, f as Usage, i as parseNodeInfo, l as Protocol, n as ParseNodeInfoOptions, o as JsonValue, p as nodeInfoToJson, r as getNodeInfo, s as NodeInfo, t as GetNodeInfoOptions, u as Services } from "./client-CAM_bQXx.cjs";
3
- import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "./http-C87EWkO0.cjs";
4
- import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "./owner-DEvZuyOE.cjs";
5
- import { $ as ActorKeyPairsDispatcher, A as createFederation, B as RouterRouteResult, C as InboxChallengePolicy, Ct as ActivityTransformer, D as FederationKvPrefixes, E as Rfc6570Expression, F as Message, G as InProcessMessageQueueOptions, H as respondWithObject, I as createFederationBuilder, J as MessageQueueListenOptions, K as MessageQueue, L as Router, M as RetryContext, N as RetryPolicy, O as FederationOrigin, P as createExponentialBackoffPolicy, Q as ActorHandleMapper, R as RouterError, S as IdempotencyStrategy, St as digest, T as ObjectCallbackSetters, U as respondWithObjectIfAcceptable, V as RespondWithObjectOptions, W as InProcessMessageQueue, X as ActorAliasMapper, Y as ParallelMessageQueue, Z as ActorDispatcher, _ as FederationBuilder, _t as WebFingerLinksDispatcher, a as InboxContext, at as CustomCollectionCursor, b as FederationStartQueueOptions, bt as PageItems, c as RouteActivityOptions, ct as InboxListener, d as ActorCallbackSetters, dt as ObjectDispatcher, et as AuthorizePredicate, f as CollectionCallbackSetters, ft as OutboxErrorHandler, g as Federation, gt as UnverifiedActivityReason, h as Federatable, ht as UnverifiedActivityHandler, i as GetSignedKeyOptions, it as CustomCollectionCounter, j as CreateExponentialBackoffPolicyOptions, k as FederationQueueOptions, l as SendActivityOptions, lt as NodeInfoDispatcher, m as CustomCollectionCallbackSetters, mt as SharedInboxKeyDispatcher, n as Context, nt as CollectionCursor, o as ParseUriResult, ot as CustomCollectionDispatcher, p as ConstructorWithTypeId, pt as OutboxPermanentFailureHandler, q as MessageQueueEnqueueOptions, r as ForwardActivityOptions, rt as CollectionDispatcher, s as RequestContext, st as InboxErrorHandler, t as ActorKeyPair, tt as CollectionCounter, u as SendActivityOptionsForCollection, ut as ObjectAuthorizePredicate, v as FederationFetchOptions, vt as SendActivityError, w as InboxListenerSetters, x as IdempotencyKeyCallback, xt as buildCollectionSynchronizationHeader, y as FederationOptions, yt as SenderKeyPair, z as RouterOptions } from "./context-o22vjzS2.cjs";
3
+ import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "./http-DqZhyEso.cjs";
4
+ import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "./owner-B3hNQCG8.cjs";
5
+ import { $ as ActorKeyPairsDispatcher, A as createFederation, B as RouterRouteResult, C as InboxChallengePolicy, Ct as ActivityTransformer, D as FederationKvPrefixes, E as Rfc6570Expression, F as Message, G as InProcessMessageQueueOptions, H as respondWithObject, I as createFederationBuilder, J as MessageQueueListenOptions, K as MessageQueue, L as Router, M as RetryContext, N as RetryPolicy, O as FederationOrigin, P as createExponentialBackoffPolicy, Q as ActorHandleMapper, R as RouterError, S as IdempotencyStrategy, St as digest, T as ObjectCallbackSetters, U as respondWithObjectIfAcceptable, V as RespondWithObjectOptions, W as InProcessMessageQueue, X as ActorAliasMapper, Y as ParallelMessageQueue, Z as ActorDispatcher, _ as FederationBuilder, _t as WebFingerLinksDispatcher, a as InboxContext, at as CustomCollectionCursor, b as FederationStartQueueOptions, bt as PageItems, c as RouteActivityOptions, ct as InboxListener, d as ActorCallbackSetters, dt as ObjectDispatcher, et as AuthorizePredicate, f as CollectionCallbackSetters, ft as OutboxErrorHandler, g as Federation, gt as UnverifiedActivityReason, h as Federatable, ht as UnverifiedActivityHandler, i as GetSignedKeyOptions, it as CustomCollectionCounter, j as CreateExponentialBackoffPolicyOptions, k as FederationQueueOptions, l as SendActivityOptions, lt as NodeInfoDispatcher, m as CustomCollectionCallbackSetters, mt as SharedInboxKeyDispatcher, n as Context, nt as CollectionCursor, o as ParseUriResult, ot as CustomCollectionDispatcher, p as ConstructorWithTypeId, pt as OutboxPermanentFailureHandler, q as MessageQueueEnqueueOptions, r as ForwardActivityOptions, rt as CollectionDispatcher, s as RequestContext, st as InboxErrorHandler, t as ActorKeyPair, tt as CollectionCounter, u as SendActivityOptionsForCollection, ut as ObjectAuthorizePredicate, v as FederationFetchOptions, vt as SendActivityError, w as InboxListenerSetters, x as IdempotencyKeyCallback, xt as buildCollectionSynchronizationHeader, y as FederationOptions, yt as SenderKeyPair, z as RouterOptions } from "./context-D4s0Wk3N.cjs";
6
6
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "./kv-gJ8LYbxX.cjs";
7
7
  import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "./compat/mod.cjs";
8
- import { n as handleWebFinger, t as WebFingerHandlerParameters } from "./mod-0dF0OeGw.cjs";
9
- import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "./mod-D5YlzzP3.cjs";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-dxOnKp2Y.cjs";
8
+ import { n as handleWebFinger, t as WebFingerHandlerParameters } from "./mod-Bx80LUTA.cjs";
9
+ import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "./mod-DiuFTYUt.cjs";
10
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-DniKVJ_C.cjs";
11
11
  export * from "@fedify/vocab-runtime";
12
12
 
13
13
  //#region src/mod.d.ts