@fedify/fedify 2.4.0-dev.2169 → 2.4.0-dev.2193

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 (103) hide show
  1. package/dist/{builder-B2d_Pt0j.mjs → builder-0onlMY4u.mjs} +26 -6
  2. package/dist/{circuit-breaker-C5NqoLBJ.mjs → circuit-breaker-XJ53md4S.mjs} +16 -11
  3. package/dist/compat/mod.d.cts +1 -1
  4. package/dist/compat/mod.d.ts +1 -1
  5. package/dist/compat/transformers.test.mjs +1 -1
  6. package/dist/{compound-proof-D28gMFqP.mjs → compound-proof-B-Fk6Slo.mjs} +3 -3
  7. package/dist/{context-BykNUf04.d.ts → context-9T--NSo4.d.ts} +55 -1
  8. package/dist/{context-L0Fnib9j.d.cts → context-CDcAgm4l.d.cts} +55 -1
  9. package/dist/{deno-DU8dvnWk.mjs → deno-DB_Sh0LK.mjs} +1 -1
  10. package/dist/{docloader-CghLH7Zi.mjs → docloader-DpWYYY6a.mjs} +25 -17
  11. package/dist/federation/builder.test.mjs +1 -1
  12. package/dist/federation/circuit-breaker.test.mjs +50 -1
  13. package/dist/federation/compound-fanout.test.mjs +3 -3
  14. package/dist/federation/handler-compound-proof.test.mjs +52 -3
  15. package/dist/federation/handler.test.mjs +5 -5
  16. package/dist/federation/hashlink-media.test.mjs +2 -2
  17. package/dist/federation/idempotency.test.mjs +2 -2
  18. package/dist/federation/keycache.test.mjs +1 -1
  19. package/dist/federation/metrics.test.mjs +1 -1
  20. package/dist/federation/middleware.test.mjs +182 -13
  21. package/dist/federation/mod.cjs +1 -1
  22. package/dist/federation/mod.d.cts +2 -2
  23. package/dist/federation/mod.d.ts +2 -2
  24. package/dist/federation/mod.js +1 -1
  25. package/dist/federation/outgoing-proof.test.mjs +5 -5
  26. package/dist/federation/portable-actor.test.mjs +3 -3
  27. package/dist/federation/portable-chain.test.mjs +3 -3
  28. package/dist/federation/portable-collection.test.mjs +4 -4
  29. package/dist/federation/portable-gateway-keys.test.mjs +6 -6
  30. package/dist/federation/portable-inbox.test.mjs +35 -5
  31. package/dist/federation/portable-parse-uri.test.mjs +1 -1
  32. package/dist/federation/portable-route-activity.test.d.mts +2 -0
  33. package/dist/federation/portable-route-activity.test.mjs +259 -0
  34. package/dist/federation/portable.test.mjs +49 -5
  35. package/dist/federation/send.test.mjs +3 -3
  36. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  37. package/dist/federation/tasks/tasks.test.mjs +2 -2
  38. package/dist/federation/temporal.test.mjs +1 -1
  39. package/dist/federation/webfinger.test.mjs +1 -1
  40. package/dist/{federation-DrNgkLfJ.cjs → federation-BsGo0EH2.cjs} +76 -35
  41. package/dist/{http-5CJBdU8n.cjs → http-BEivI0TS.cjs} +279 -87
  42. package/dist/{http-BGpexPO7.js → http-BGmxtpo2.js} +263 -89
  43. package/dist/{http-Cok5-vIC.d.ts → http-BrwKINQn.d.cts} +29 -1
  44. package/dist/{http-DC1cqAQ2.d.cts → http-DGx0KOws.d.ts} +29 -1
  45. package/dist/{http-Bd6rZlJX.mjs → http-DQf9Mw4V.mjs} +180 -92
  46. package/dist/{key-gIhVZO3p.mjs → key-DA3Yx8p2.mjs} +4 -4
  47. package/dist/{key-owner-evidence-Bo3yaeL5.mjs → key-owner-evidence-APB6NpSk.mjs} +1 -1
  48. package/dist/{keycache-PiOM9pM0.mjs → keycache-Da8A8mZa.mjs} +1 -1
  49. package/dist/{kv-cache-YRi_g8GB.cjs → kv-cache-1hafSoqH.cjs} +23 -15
  50. package/dist/{kv-cache-iR55fqlk.js → kv-cache-DduYhpee.js} +24 -16
  51. package/dist/{kv-cache-D0qjSeWY.mjs → kv-cache-OFBvrKh3.mjs} +1 -1
  52. package/dist/{ld-BsTkRrwF.mjs → ld-C15yzuY6.mjs} +3 -3
  53. package/dist/{metrics-jUDFfVgi.mjs → metrics-B1H23mlq.mjs} +1 -1
  54. package/dist/{middleware-Dq-OCmb6.mjs → middleware-BZQnf0nI.mjs} +1 -1
  55. package/dist/{middleware-Coqgp-K0.mjs → middleware-BqqycC0P.mjs} +52 -36
  56. package/dist/{middleware-DlxMxVp5.js → middleware-ClaUFaLb.js} +77 -36
  57. package/dist/{mod-DK0y9fd-.d.ts → mod-B3OBLj5g.d.ts} +1 -1
  58. package/dist/{mod-B5z_q9TH.d.ts → mod-C5Mwx5ty.d.ts} +5 -1
  59. package/dist/{mod-CPPqkyV_.d.cts → mod-Cy9VNHVw.d.ts} +14 -3
  60. package/dist/{mod-BLOXGs6m.d.cts → mod-D58KCqUg.d.cts} +1 -1
  61. package/dist/{mod--jv6vyrP.d.ts → mod-DoTWIc7F.d.cts} +14 -3
  62. package/dist/{mod-BA_F2x53.d.cts → mod-Dp3Ij7sw.d.cts} +5 -1
  63. package/dist/mod.cjs +4 -4
  64. package/dist/mod.d.cts +5 -5
  65. package/dist/mod.d.ts +5 -5
  66. package/dist/mod.js +4 -4
  67. package/dist/nodeinfo/handler.test.mjs +1 -1
  68. package/dist/{owner-D3GoetXS.mjs → owner-BVpZBM-V.mjs} +5 -5
  69. package/dist/{portable-collection-CnlCamup.cjs → portable-collection-BFSShzwh.cjs} +1 -1
  70. package/dist/{portable-collection-Bkdh_WpL.js → portable-collection-D535cSz_.js} +1 -1
  71. package/dist/{portable-collection-C60_acmx.mjs → portable-collection-Dn2GdZdI.mjs} +2 -2
  72. package/dist/{portable-key-DyF5AnZo.mjs → portable-key-Bmwmq7Y6.mjs} +2 -2
  73. package/dist/{portable-key-id-Bg259c4Z.mjs → portable-key-id-Ca30-hOa.mjs} +45 -1
  74. package/dist/{proof-CQAYqWdj.mjs → proof-DrJWKeOl.mjs} +49 -7
  75. package/dist/{send-DjkQrxt5.mjs → send-CT3a-0Vd.mjs} +3 -3
  76. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  77. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  78. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  79. package/dist/sig/compound-proof.test.mjs +2 -2
  80. package/dist/sig/http.test.mjs +495 -23
  81. package/dist/sig/key-owner-evidence.test.mjs +2 -2
  82. package/dist/sig/key.test.mjs +1 -1
  83. package/dist/sig/ld.test.mjs +2 -2
  84. package/dist/sig/mod.cjs +2 -2
  85. package/dist/sig/mod.d.cts +2 -2
  86. package/dist/sig/mod.d.ts +2 -2
  87. package/dist/sig/mod.js +2 -2
  88. package/dist/sig/owner.test.mjs +1 -1
  89. package/dist/sig/portable-collection.test.mjs +1 -1
  90. package/dist/sig/portable-key-id.test.d.mts +2 -0
  91. package/dist/sig/portable-key-id.test.mjs +67 -0
  92. package/dist/sig/portable-key.test.mjs +7 -7
  93. package/dist/sig/proof.test.mjs +141 -7
  94. package/dist/{temporal-oRKP803M.mjs → temporal-DNqluyEc.mjs} +1 -1
  95. package/dist/testing/kv.test.mjs +1 -1
  96. package/dist/testing/mod.d.mts +52 -0
  97. package/dist/utils/docloader.test.mjs +93 -2
  98. package/dist/utils/kv-cache.test.mjs +1 -1
  99. package/dist/utils/mod.cjs +1 -1
  100. package/dist/utils/mod.d.cts +1 -1
  101. package/dist/utils/mod.d.ts +1 -1
  102. package/dist/utils/mod.js +1 -1
  103. package/package.json +7 -7
@@ -1,29 +1,29 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-DU8dvnWk.mjs";
5
- import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-jUDFfVgi.mjs";
4
+ import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
5
+ import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-B1H23mlq.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
7
- import { a as hasPortableActor, c as isPortableId, l as isPortableKeyId, n as getGatewayKeyBase, o as isCompatibleKeyId, r as getPortableDid, t as getCanonicalPortableId, u as isPortableUri } from "./portable-key-id-Bg259c4Z.mjs";
8
- import { c as validateCryptoKey, n as exportJwk, s as importJwk } from "./key-gIhVZO3p.mjs";
7
+ import { d as isPortableUri, f as isSameObjectId, i as getPortableDid, l as isPortableId, n as getCanonicalPortableId, o as hasPortableActor, r as getGatewayKeyBase, s as isCompatibleKeyId, t as getAuthenticationOrigin, u as isPortableKeyId } from "./portable-key-id-Ca30-hOa.mjs";
8
+ import { c as validateCryptoKey, n as exportJwk, s as importJwk } from "./key-DA3Yx8p2.mjs";
9
9
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
10
- import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-BsTkRrwF.mjs";
11
- import { a as signObject, c as verifyPortableObjectProof, i as hasProofLike, s as verifyObject, t as InvalidPortableObjectIdError, u as verifyPortableObjectProofWithRoot } from "./proof-CQAYqWdj.mjs";
12
- import { a as listRequestSignatures, c as selectRequestSignature, d as verifyRequest, f as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-Bd6rZlJX.mjs";
13
- import { t as getAuthenticatedDocumentLoader } from "./docloader-CghLH7Zi.mjs";
14
- import { n as kvCache } from "./kv-cache-D0qjSeWY.mjs";
10
+ import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-C15yzuY6.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof, i as hasProofLike, s as verifyObject, t as InvalidPortableObjectIdError, u as verifyPortableObjectProofWithRoot } from "./proof-DrJWKeOl.mjs";
12
+ import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-DQf9Mw4V.mjs";
13
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-DpWYYY6a.mjs";
14
+ import { n as kvCache } from "./kv-cache-OFBvrKh3.mjs";
15
15
  import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-CEnNz8O7.mjs";
16
16
  import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
17
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-D3GoetXS.mjs";
18
- import { t as verifyPortableObject } from "./portable-collection-C60_acmx.mjs";
19
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-DjkQrxt5.mjs";
20
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-B2d_Pt0j.mjs";
21
- import { t as CircuitBreaker } from "./circuit-breaker-C5NqoLBJ.mjs";
17
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-BVpZBM-V.mjs";
18
+ import { t as verifyPortableObject } from "./portable-collection-Dn2GdZdI.mjs";
19
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CT3a-0Vd.mjs";
20
+ import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-0onlMY4u.mjs";
21
+ import { t as CircuitBreaker } from "./circuit-breaker-XJ53md4S.mjs";
22
22
  import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
23
- import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, s as verifyServedPortableObjects, t as containsCompoundPortableObject } from "./compound-proof-D28gMFqP.mjs";
24
- import { t as KvKeyCache } from "./keycache-PiOM9pM0.mjs";
23
+ import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, s as verifyServedPortableObjects, t as containsCompoundPortableObject } from "./compound-proof-B-Fk6Slo.mjs";
24
+ import { t as KvKeyCache } from "./keycache-Da8A8mZa.mjs";
25
25
  import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
26
- import { t as hasMalformedKnownTemporalLiteral } from "./temporal-oRKP803M.mjs";
26
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-DNqluyEc.mjs";
27
27
  import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
28
28
  import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
29
29
  import { getLogger, withContext } from "@logtape/logtape";
@@ -32,7 +32,7 @@ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey,
32
32
  import { lookupWebFinger } from "@fedify/webfinger";
33
33
  import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
34
34
  import { uniq } from "es-toolkit";
35
- import { FetchError, canonicalizePortableUri, decodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDigestMultibase, parseHashlink, parseIri, toCompatibleEf61Id } from "@fedify/vocab-runtime";
35
+ import { FetchError, canonicalizePortableUri, decodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDigestMultibase, parseHashlink, parseIri, resolveDocumentLoaderTimeout, toCompatibleEf61Id } from "@fedify/vocab-runtime";
36
36
  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";
37
37
  import { isCompatibleEf61Iri } from "@fedify/vocab-runtime/internal/portable-dereference";
38
38
  import jsonld from "@fedify/vocab-runtime/jsonld";
@@ -1127,7 +1127,7 @@ function isInvalidJsonLdError(error) {
1127
1127
  return name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
1128
1128
  }
1129
1129
  function isValidationTypeError(error) {
1130
- return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:)/.test(error.message) || isInvalidUrlTypeError(error));
1130
+ return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:|Invalid FEP-ef61 gateway:)/.test(error.message) || isInvalidUrlTypeError(error));
1131
1131
  }
1132
1132
  function isPermanentActivityParseError(error) {
1133
1133
  return isInvalidJsonLdError(error) || isValidationTypeError(error);
@@ -1270,7 +1270,11 @@ async function handlePortableObject(request, { values, context, objectDispatcher
1270
1270
  return await onNotFound(request);
1271
1271
  }
1272
1272
  if (tombstone || result.reason.type !== "unsecuredCollection" && result.reason.type !== "unsupportedObjectType") {
1273
- logger.error("Refusing to serve the portable object {portableId}, as it does not satisfy the FEP-ef61 proof policy: {reason}. Portable actors, activities, objects, and tombstones need an Object Integrity Proof made with a key of the DID in their ID.", {
1273
+ if (result.reason.type === "invalidGateways") logger.error("Refusing to serve the portable actor {portableId}, as its gateways property is missing, empty, or has an item that is not an HTTP(S) origin. FEP-ef61 requires a portable actor to list at least one gateway where it can be retrieved.", {
1274
+ portableId: canonicalId,
1275
+ reason: result.reason.type
1276
+ });
1277
+ else logger.error("Refusing to serve the portable object {portableId}, as it does not satisfy the FEP-ef61 proof policy: {reason}. Portable actors, activities, objects, and tombstones need an Object Integrity Proof made with a key of the DID in their ID.", {
1274
1278
  portableId: canonicalId,
1275
1279
  reason: result.reason.type
1276
1280
  });
@@ -1389,13 +1393,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
1389
1393
  * @param parameters The parameters for handling the collection.
1390
1394
  * @returns A promise that resolves to an HTTP response.
1391
1395
  */
1392
- async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
1393
- const spanName = name$1.trim().replace(/\s+/g, "_");
1396
+ async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
1397
+ const spanName = name$2.trim().replace(/\s+/g, "_");
1394
1398
  tracerProvider = tracerProvider ?? trace.getTracerProvider();
1395
1399
  const tracer = tracerProvider.getTracer(name, version);
1396
1400
  const cursor = new URL(request.url).searchParams.get("cursor");
1397
1401
  const metricBase = {
1398
- kind: getCollectionMetricKind(name$1),
1402
+ kind: getCollectionMetricKind(name$2),
1399
1403
  page: cursor != null,
1400
1404
  dispatcher: "built_in"
1401
1405
  };
@@ -1441,7 +1445,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
1441
1445
  span.setStatus({ code: SpanStatusCode.ERROR });
1442
1446
  return await onNotFound(request);
1443
1447
  }
1444
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
1448
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
1445
1449
  itemCount = items.length;
1446
1450
  span.setAttribute("fedify.collection.items", itemCount);
1447
1451
  return items;
@@ -1483,7 +1487,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
1483
1487
  } else {
1484
1488
  const uri = new URL(portable == null ? baseUri : pageBase);
1485
1489
  uri.searchParams.set("cursor", cursor);
1486
- const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
1490
+ const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
1487
1491
  kind: SpanKind.SERVER,
1488
1492
  attributes: {
1489
1493
  "activitypub.collection.id": uri.href,
@@ -1499,7 +1503,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
1499
1503
  span.setStatus({ code: SpanStatusCode.ERROR });
1500
1504
  return await onNotFound(request);
1501
1505
  }
1502
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
1506
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
1503
1507
  itemCount = items.length;
1504
1508
  span.setAttribute("fedify.collection.items", itemCount);
1505
1509
  return {
@@ -2007,7 +2011,7 @@ async function handleInbox(request, options) {
2007
2011
  * @returns A promise that resolves to an HTTP response.
2008
2012
  */
2009
2013
  async function handleInboxInternal(request, parameters, span) {
2010
- const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, publicKeyTtl, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider, portableInbox } = parameters;
2014
+ const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, publicKeyTtl, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, maxHttpSignatures, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider, portableInbox } = parameters;
2011
2015
  const logger = getLogger([
2012
2016
  "fedify",
2013
2017
  "federation",
@@ -2293,6 +2297,7 @@ async function handleInboxInternal(request, parameters, span) {
2293
2297
  contextLoader: ctx.contextLoader,
2294
2298
  documentLoader: ctx.documentLoader,
2295
2299
  timeWindow: signatureTimeWindow,
2300
+ maxSignatures: maxHttpSignatures,
2296
2301
  keyCache,
2297
2302
  meterProvider,
2298
2303
  tracerProvider
@@ -2515,7 +2520,7 @@ async function handleInboxInternal(request, parameters, span) {
2515
2520
  inbox: portableInbox.recipient.canonicalInboxId
2516
2521
  });
2517
2522
  else try {
2518
- await portableInbox.forward(json, activity.id, getTypeId(activity).href, listRequestSignatures(request).map((signature) => ({
2523
+ await portableInbox.forward(json, activity.id, getTypeId(activity).href, listRequestSignatures(request, maxHttpSignatures).map((signature) => ({
2519
2524
  keyId: signature.keyId,
2520
2525
  coversDelivery: coversDelivery(signature),
2521
2526
  verify: async () => {
@@ -2689,8 +2694,8 @@ var CustomCollectionHandler = class {
2689
2694
  * @param CollectionPage The CollectionPage constructor.
2690
2695
  * @param filterPredicate Optional filter predicate for items.
2691
2696
  */
2692
- constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
2693
- this.name = name$2;
2697
+ constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
2698
+ this.name = name$1;
2694
2699
  this.values = values;
2695
2700
  this.context = context;
2696
2701
  this.callbacks = callbacks;
@@ -4069,7 +4074,7 @@ function isPermanentRemoteContextError(error) {
4069
4074
  return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
4070
4075
  }
4071
4076
  function isPermanentInboxParseError(error) {
4072
- return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:)/.test(error.message) || isInvalidUrlTypeError(error));
4077
+ return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:|Invalid FEP-ef61 gateway:)/.test(error.message) || isInvalidUrlTypeError(error));
4073
4078
  }
4074
4079
  function hasLinkedDataSignatureJsonLdProcessingError(error) {
4075
4080
  if (error.message.startsWith("Maximum deep iterations exceeded")) return true;
@@ -4086,6 +4091,8 @@ function isLinkedDataSignatureJsonLdProcessingError(error) {
4086
4091
  * @returns A new {@link Federation} instance.
4087
4092
  * @throws {TypeError} If benchmark mode and `meterProvider` are both
4088
4093
  * specified.
4094
+ * @throws {RangeError} If {@link FederationOptions.maxHttpSignatures} is not
4095
+ * a positive integer or `Infinity`.
4089
4096
  * @since 0.10.0
4090
4097
  */
4091
4098
  function createFederation(options) {
@@ -4112,6 +4119,7 @@ var FederationImpl = class extends FederationBuilderImpl {
4112
4119
  onOutboxError;
4113
4120
  permanentFailureStatusCodes;
4114
4121
  signatureTimeWindow;
4122
+ maxHttpSignatures;
4115
4123
  skipSignatureVerification;
4116
4124
  outboxRetryPolicy;
4117
4125
  inboxRetryPolicy;
@@ -4140,6 +4148,7 @@ var FederationImpl = class extends FederationBuilderImpl {
4140
4148
  const hasCustomLoaderFactory = options.documentLoaderFactory != null || options.contextLoaderFactory != null;
4141
4149
  const allowPrivateAddress = options.allowPrivateAddress ?? (benchmarkMode && !hasCustomLoaderFactory ? true : false);
4142
4150
  const signatureTimeWindow = options.signatureTimeWindow ?? (benchmarkMode ? false : { hours: 1 });
4151
+ if (options.maxHttpSignatures !== void 0) validateMaxSignatures(options.maxHttpSignatures, "maxHttpSignatures");
4143
4152
  if (benchmarkMode && options.meterProvider != null) throw new TypeError("benchmarkMode requires Fedify to own the meterProvider; OpenTelemetry metric readers cannot be added after a MeterProvider is constructed.");
4144
4153
  if (benchmarkMode) {
4145
4154
  const relaxations = getBenchmarkRelaxations(allowPrivateAddress, signatureTimeWindow);
@@ -4232,13 +4241,15 @@ var FederationImpl = class extends FederationBuilderImpl {
4232
4241
  }
4233
4242
  const { userAgent } = options;
4234
4243
  this.allowPrivateAddress = allowPrivateAddress;
4244
+ const documentLoaderTimeout = resolveDocumentLoaderTimeout(options.documentLoaderTimeout == null ? options.documentLoaderTimeout : Temporal.Duration.from(options.documentLoaderTimeout).total("millisecond"));
4235
4245
  const userDocumentLoaderFactory = options.documentLoaderFactory;
4236
4246
  const userContextLoaderFactory = options.contextLoaderFactory;
4237
4247
  const userAuthFactory = options.authenticatedDocumentLoaderFactory;
4238
4248
  const builtinDocumentLoaderFactory = (opts) => kvCache({
4239
4249
  loader: getDocumentLoader({
4240
4250
  allowPrivateAddress: opts?.allowPrivateAddress ?? allowPrivateAddress,
4241
- userAgent: opts?.userAgent ?? userAgent
4251
+ userAgent: opts?.userAgent ?? userAgent,
4252
+ timeout: opts?.timeout !== void 0 ? opts.timeout : documentLoaderTimeout
4242
4253
  }),
4243
4254
  kv: options.kv,
4244
4255
  prefix: this.kvPrefixes.remoteDocument,
@@ -4248,7 +4259,8 @@ var FederationImpl = class extends FederationBuilderImpl {
4248
4259
  const builtinContextLoaderFactory = (opts) => kvCache({
4249
4260
  loader: getDocumentLoader({
4250
4261
  allowPrivateAddress: opts?.allowPrivateAddress ?? allowPrivateAddress,
4251
- userAgent: opts?.userAgent ?? userAgent
4262
+ userAgent: opts?.userAgent ?? userAgent,
4263
+ timeout: opts?.timeout !== void 0 ? opts.timeout : documentLoaderTimeout
4252
4264
  }),
4253
4265
  kv: options.kv,
4254
4266
  prefix: this.kvPrefixes.remoteDocument,
@@ -4269,6 +4281,7 @@ var FederationImpl = class extends FederationBuilderImpl {
4269
4281
  this.authenticatedDocumentLoaderFactory = (identity, factoryOpts) => instrumentDocumentLoader(userAuthFactory != null ? userAuthFactory(identity, factoryOpts) : getAuthenticatedDocumentLoader(identity, {
4270
4282
  allowPrivateAddress: factoryOpts?.allowPrivateAddress ?? allowPrivateAddress,
4271
4283
  userAgent: factoryOpts?.userAgent ?? userAgent,
4284
+ timeout: factoryOpts?.timeout !== void 0 ? factoryOpts.timeout : documentLoaderTimeout,
4272
4285
  specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, options.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
4273
4286
  tracerProvider: this.tracerProvider
4274
4287
  }), {
@@ -4280,6 +4293,7 @@ var FederationImpl = class extends FederationBuilderImpl {
4280
4293
  this.onOutboxError = options.onOutboxError;
4281
4294
  this.permanentFailureStatusCodes = options.permanentFailureStatusCodes ?? [404, 410];
4282
4295
  this.signatureTimeWindow = signatureTimeWindow;
4296
+ this.maxHttpSignatures = options.maxHttpSignatures ?? 3;
4283
4297
  this.skipSignatureVerification = options.skipSignatureVerification ?? false;
4284
4298
  this.inboxChallengePolicy = options.inboxChallengePolicy;
4285
4299
  this.outboxRetryPolicy = options.outboxRetryPolicy ?? createExponentialBackoffPolicy();
@@ -5905,6 +5919,7 @@ var FederationImpl = class extends FederationBuilderImpl {
5905
5919
  unverifiedActivityHandler: this.unverifiedActivityHandler,
5906
5920
  onNotFound,
5907
5921
  signatureTimeWindow: this.signatureTimeWindow,
5922
+ maxHttpSignatures: this.maxHttpSignatures,
5908
5923
  skipSignatureVerification: this.skipSignatureVerification,
5909
5924
  inboxChallengePolicy: this.inboxChallengePolicy,
5910
5925
  meterProvider: this.meterProvider,
@@ -6893,7 +6908,7 @@ var ContextImpl = class ContextImpl {
6893
6908
  activity: await fetched.toJsonLd({ contextLoader })
6894
6909
  });
6895
6910
  return false;
6896
- } else if (fetched.id?.href !== activity.id.href) {
6911
+ } else if (fetched.id == null || !isSameObjectId(fetched.id, activity.id)) {
6897
6912
  logger.debug("Fetched activity object has a different ID; failed to verify.", {
6898
6913
  recipient,
6899
6914
  activity: await fetched.toJsonLd({ contextLoader })
@@ -6906,8 +6921,8 @@ var ContextImpl = class ContextImpl {
6906
6921
  });
6907
6922
  return false;
6908
6923
  }
6909
- const activityId = fetched.id;
6910
- if (!fetched.actorIds.every((actor) => actor.origin === activityId.origin)) {
6924
+ const activityOrigin = getAuthenticationOrigin(fetched.id);
6925
+ if (activityOrigin == null || !fetched.actorIds.every((actor) => getAuthenticationOrigin(actor) === activityOrigin)) {
6911
6926
  logger.debug("Fetched activity object has actors from different origins; unable to verify.", {
6912
6927
  recipient,
6913
6928
  activity: await fetched.toJsonLd({ contextLoader })
@@ -7043,6 +7058,7 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
7043
7058
  contextLoader: options.contextLoader ?? this.contextLoader,
7044
7059
  documentLoader: options.documentLoader ?? this.documentLoader,
7045
7060
  timeWindow: this.federation.signatureTimeWindow,
7061
+ maxSignatures: this.federation.maxHttpSignatures,
7046
7062
  meterProvider: this.meterProvider,
7047
7063
  tracerProvider: options.tracerProvider ?? this.tracerProvider
7048
7064
  });