@fedify/fedify 2.4.0-dev.2073 → 2.4.0-dev.2084

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 (68) hide show
  1. package/dist/{builder-CVHpPAjK.mjs → builder-BGlpUocK.mjs} +2 -2
  2. package/dist/compat/transformers.test.mjs +1 -1
  3. package/dist/{compound-proof-B5Skp-vE.mjs → compound-proof-B6Aj2kGY.mjs} +1 -1
  4. package/dist/{deno-LYTbBhYV.mjs → deno-Dn-py9Zy.mjs} +1 -1
  5. package/dist/{docloader-C0SWQylk.mjs → docloader-BUq5bYJr.mjs} +2 -2
  6. package/dist/federation/builder.test.mjs +1 -1
  7. package/dist/federation/compound-fanout.test.mjs +3 -3
  8. package/dist/federation/handler-compound-proof.test.mjs +137 -10
  9. package/dist/federation/handler.test.mjs +5 -5
  10. package/dist/federation/hashlink-media.test.mjs +2 -2
  11. package/dist/federation/idempotency.test.mjs +2 -2
  12. package/dist/federation/metrics.test.mjs +1 -1
  13. package/dist/federation/middleware.test.mjs +7 -7
  14. package/dist/federation/mod.cjs +1 -1
  15. package/dist/federation/mod.js +1 -1
  16. package/dist/federation/outgoing-proof.test.mjs +5 -5
  17. package/dist/federation/portable-gateway-keys.test.mjs +3 -3
  18. package/dist/federation/portable-inbox.test.mjs +401 -6
  19. package/dist/federation/portable.test.mjs +3 -3
  20. package/dist/federation/send.test.mjs +3 -3
  21. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  22. package/dist/federation/tasks/tasks.test.mjs +2 -2
  23. package/dist/federation/temporal.test.mjs +1 -1
  24. package/dist/federation/webfinger.test.mjs +1 -1
  25. package/dist/{federation-B1aeTKKN.cjs → federation-BLGx8JUH.cjs} +126 -22
  26. package/dist/{http-vfTpzGEq.js → http-4PCCvhsU.js} +1 -1
  27. package/dist/{http-C7qHlv-b.mjs → http-B0VRNipE.mjs} +4 -4
  28. package/dist/{http-DGk8XI38.cjs → http-B5q1CHtL.cjs} +1 -1
  29. package/dist/{key-BYXnTGro.mjs → key-BJrp524f.mjs} +2 -2
  30. package/dist/{kv-cache-DCJuwdnB.js → kv-cache-1KUmAPH7.js} +1 -1
  31. package/dist/{kv-cache-DEH5jyND.mjs → kv-cache-C4C3LyYW.mjs} +1 -1
  32. package/dist/{kv-cache-DvqkKNIj.cjs → kv-cache-Dhhhrryv.cjs} +1 -1
  33. package/dist/{ld-DT3e2hOv.mjs → ld-BmFz5NLA.mjs} +3 -3
  34. package/dist/{metrics-DvlvYpq_.mjs → metrics-Beod6tzO.mjs} +1 -1
  35. package/dist/{middleware-BJcez_E3.mjs → middleware-B7CNsyqt.mjs} +1 -1
  36. package/dist/{middleware-CpyCNOW_.mjs → middleware-BKeQYPm0.mjs} +136 -32
  37. package/dist/{middleware-CCbyUF4c.js → middleware-D_9pNYe9.js} +126 -22
  38. package/dist/mod.cjs +5 -5
  39. package/dist/mod.js +5 -5
  40. package/dist/nodeinfo/handler.test.mjs +1 -1
  41. package/dist/{owner-DCIH7Iq0.cjs → owner-BQFZtFV4.cjs} +1 -1
  42. package/dist/{owner-CDsVeZI7.mjs → owner-CsKVgMzk.mjs} +3 -3
  43. package/dist/{owner-DfGz0cXm.js → owner-_pbbgLJK.js} +1 -1
  44. package/dist/{portable-key-DCyKGCQd.mjs → portable-key-B4R-CiIV.mjs} +2 -2
  45. package/dist/{proof-CxsVG6vM.mjs → proof-ozG4HfcQ.mjs} +4 -4
  46. package/dist/{send-BZJ7NsVV.mjs → send-ClPt8nYu.mjs} +3 -3
  47. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  48. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  49. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  50. package/dist/sig/compound-proof.test.mjs +2 -2
  51. package/dist/sig/http.test.mjs +2 -2
  52. package/dist/sig/key.test.mjs +1 -1
  53. package/dist/sig/ld.test.mjs +2 -2
  54. package/dist/sig/mod.cjs +3 -3
  55. package/dist/sig/mod.js +3 -3
  56. package/dist/sig/owner.test.mjs +1 -1
  57. package/dist/sig/portable-collection.test.mjs +2 -2
  58. package/dist/sig/portable-key.test.mjs +3 -3
  59. package/dist/sig/proof.test.mjs +3 -3
  60. package/dist/{sig-Cs9_ecdh.js → sig-DhdomAN0.js} +2 -2
  61. package/dist/{sig-C6TnADze.cjs → sig-k3C8sF7g.cjs} +2 -2
  62. package/dist/{temporal-CLzSfIOV.mjs → temporal-Ba0EAZAI.mjs} +1 -1
  63. package/dist/testing/kv.test.mjs +1 -1
  64. package/dist/utils/docloader.test.mjs +2 -2
  65. package/dist/utils/kv-cache.test.mjs +1 -1
  66. package/dist/utils/mod.cjs +1 -1
  67. package/dist/utils/mod.js +1 -1
  68. package/package.json +7 -7
@@ -1,27 +1,27 @@
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-LYTbBhYV.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-DvlvYpq_.mjs";
4
+ import { n as version, t as name } from "./deno-Dn-py9Zy.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-Beod6tzO.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
7
- import { d as hasPortableActor, f as isCompatibleKeyId, m as isPortableUri, o as importJwk, s as validateCryptoKey, t as exportJwk, u as getGatewayKeyBase } from "./key-BYXnTGro.mjs";
7
+ import { d as hasPortableActor, f as isCompatibleKeyId, l as getCanonicalPortableId, m as isPortableUri, o as importJwk, s as validateCryptoKey, t as exportJwk, u as getGatewayKeyBase } from "./key-BJrp524f.mjs";
8
8
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
9
- 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-DT3e2hOv.mjs";
10
- import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-CxsVG6vM.mjs";
11
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-C7qHlv-b.mjs";
12
- import { t as getAuthenticatedDocumentLoader } from "./docloader-C0SWQylk.mjs";
13
- import { n as kvCache } from "./kv-cache-DEH5jyND.mjs";
9
+ 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-BmFz5NLA.mjs";
10
+ import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-ozG4HfcQ.mjs";
11
+ import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-B0VRNipE.mjs";
12
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-BUq5bYJr.mjs";
13
+ import { n as kvCache } from "./kv-cache-C4C3LyYW.mjs";
14
14
  import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-DpnpgjyX.mjs";
15
15
  import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
16
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CDsVeZI7.mjs";
17
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-BZJ7NsVV.mjs";
18
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-CVHpPAjK.mjs";
16
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CsKVgMzk.mjs";
17
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-ClPt8nYu.mjs";
18
+ import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BGlpUocK.mjs";
19
19
  import { t as CircuitBreaker } from "./circuit-breaker-C5NqoLBJ.mjs";
20
20
  import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
21
- import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-B5Skp-vE.mjs";
21
+ import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-B6Aj2kGY.mjs";
22
22
  import { t as KvKeyCache } from "./keycache-BUDHB5rY.mjs";
23
23
  import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
24
- import { t as hasMalformedKnownTemporalLiteral } from "./temporal-CLzSfIOV.mjs";
24
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-Ba0EAZAI.mjs";
25
25
  import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
26
26
  import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
27
27
  import { getLogger, withContext } from "@logtape/logtape";
@@ -858,13 +858,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
858
858
  * @param parameters The parameters for handling the collection.
859
859
  * @returns A promise that resolves to an HTTP response.
860
860
  */
861
- async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
862
- const spanName = name$2.trim().replace(/\s+/g, "_");
861
+ async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
862
+ const spanName = name$1.trim().replace(/\s+/g, "_");
863
863
  tracerProvider = tracerProvider ?? trace.getTracerProvider();
864
864
  const tracer = tracerProvider.getTracer(name, version);
865
865
  const cursor = new URL(request.url).searchParams.get("cursor");
866
866
  const metricBase = {
867
- kind: getCollectionMetricKind(name$2),
867
+ kind: getCollectionMetricKind(name$1),
868
868
  page: cursor != null,
869
869
  dispatcher: "built_in"
870
870
  };
@@ -905,7 +905,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
905
905
  span.setStatus({ code: SpanStatusCode.ERROR });
906
906
  return await onNotFound(request);
907
907
  }
908
- const items = filterCollectionItems(page.items, name$2, filterPredicate);
908
+ const items = filterCollectionItems(page.items, name$1, filterPredicate);
909
909
  itemCount = items.length;
910
910
  span.setAttribute("fedify.collection.items", itemCount);
911
911
  return items;
@@ -945,7 +945,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
945
945
  } else {
946
946
  const uri = new URL(baseUri);
947
947
  uri.searchParams.set("cursor", cursor);
948
- const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
948
+ const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
949
949
  kind: SpanKind.SERVER,
950
950
  attributes: {
951
951
  "activitypub.collection.id": uri.href,
@@ -961,7 +961,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
961
961
  span.setStatus({ code: SpanStatusCode.ERROR });
962
962
  return await onNotFound(request);
963
963
  }
964
- const items = filterCollectionItems(page.items, name$2, filterPredicate);
964
+ const items = filterCollectionItems(page.items, name$1, filterPredicate);
965
965
  itemCount = items.length;
966
966
  span.setAttribute("fedify.collection.items", itemCount);
967
967
  return {
@@ -1891,8 +1891,9 @@ async function handleInboxInternal(request, parameters, span) {
1891
1891
  });
1892
1892
  }
1893
1893
  if (!skipSignatureVerification) {
1894
- if (inspectCompoundPortableObjectApplicability(json, INBOX_COMPOUND_PROOF_LIMITS) !== "absent") {
1895
- const compoundProof = await verifyCompoundPortableObjectProofs(json, INBOX_COMPOUND_PROOF_LIMITS, {
1894
+ const compoundJson = Array.isArray(json) ? json : jsonWithoutSig;
1895
+ if (inspectCompoundPortableObjectApplicability(compoundJson, INBOX_COMPOUND_PROOF_LIMITS) !== "absent") {
1896
+ const compoundProof = await verifyCompoundPortableObjectProofs(compoundJson, INBOX_COMPOUND_PROOF_LIMITS, {
1896
1897
  documentLoader: ctx.documentLoader,
1897
1898
  keyCache,
1898
1899
  meterProvider,
@@ -2108,8 +2109,8 @@ var CustomCollectionHandler = class {
2108
2109
  * @param CollectionPage The CollectionPage constructor.
2109
2110
  * @param filterPredicate Optional filter predicate for items.
2110
2111
  */
2111
- constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
2112
- this.name = name$1;
2112
+ constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
2113
+ this.name = name$2;
2113
2114
  this.values = values;
2114
2115
  this.context = context;
2115
2116
  this.callbacks = callbacks;
@@ -2669,6 +2670,7 @@ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, loc
2669
2670
  return {
2670
2671
  status: "accepted",
2671
2672
  recipient: {
2673
+ actorId: id,
2672
2674
  inboxId,
2673
2675
  canonicalInboxId,
2674
2676
  gateways
@@ -2702,8 +2704,11 @@ function canonicalize(iri) {
2702
2704
  * Forwarding is therefore best effort. Without {@link KvStore.cas}, nothing is
2703
2705
  * forwarded.
2704
2706
  *
2705
- * Forwarded requests are not signed with HTTP Signatures; the receiving
2706
- * gateways authenticate the activity by its own proof.
2707
+ * Forwarded requests are signed with HTTP Signatures by the RSA key among
2708
+ * {@link ForwardPortableInboxActivityParameters.getKeys}, if any, so that
2709
+ * servers requiring HTTP Signatures accept them, and are sent unsigned
2710
+ * otherwise. Either way, the receiving gateways authenticate the activity by
2711
+ * its own proof.
2707
2712
  * @param parameters The parameters.
2708
2713
  * @returns The target inbox URLs that the activity was handed off to.
2709
2714
  */
@@ -2775,20 +2780,59 @@ function getForwardingTargets(recipient, excludedOrigins) {
2775
2780
  }
2776
2781
  return targets;
2777
2782
  }
2778
- async function forwardImmediately({ activity, activityId, activityType, allowPrivateAddress, options, meterProvider, tracerProvider }, inboxes) {
2783
+ /**
2784
+ * Resolves the key that signs forwarded requests: the first RSASSA-PKCS1-v1_5
2785
+ * key, as {@link sendActivity} signs requests only with such a key. Since
2786
+ * the targets have already been claimed, the activity is forwarded unsigned
2787
+ * rather than not at all if the key cannot be resolved or used.
2788
+ */
2789
+ async function resolveForwardingKey({ getKeys, activityId }) {
2790
+ if (getKeys == null) return null;
2791
+ const logger = getLogger([
2792
+ "fedify",
2793
+ "federation",
2794
+ "inbox"
2795
+ ]);
2796
+ let key;
2797
+ try {
2798
+ key = (await getKeys()).find((k) => k.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5");
2799
+ } catch (error) {
2800
+ logger.error("Failed to get the gateway keys to sign forwarded requests with; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
2801
+ activityId: activityId.href,
2802
+ error
2803
+ });
2804
+ return null;
2805
+ }
2806
+ if (key == null) return null;
2807
+ try {
2808
+ validateCryptoKey(key.privateKey, "private");
2809
+ } catch (error) {
2810
+ if (!(error instanceof TypeError)) throw error;
2811
+ logger.warn("The gateway key {keyId} cannot sign forwarded requests; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
2812
+ keyId: key.keyId.href,
2813
+ activityId: activityId.href,
2814
+ error
2815
+ });
2816
+ return null;
2817
+ }
2818
+ return key;
2819
+ }
2820
+ async function forwardImmediately(parameters, inboxes) {
2821
+ const { activity, activityId, activityType, allowPrivateAddress, specDeterminer, options, meterProvider, tracerProvider } = parameters;
2779
2822
  const logger = getLogger([
2780
2823
  "fedify",
2781
2824
  "federation",
2782
2825
  "inbox"
2783
2826
  ]);
2784
2827
  const deadline = (options ?? resolvePortableInboxForwardingOptions()).deadline.total("millisecond");
2785
- const sends = inboxes.map((inbox) => sendActivity({
2828
+ const forwarding = resolveForwardingKey(parameters).then((key) => Promise.all(inboxes.map((inbox) => sendActivity({
2786
2829
  activity,
2787
2830
  activityId: activityId.href,
2788
2831
  activityType,
2789
- keys: [],
2832
+ keys: key == null ? [] : [key],
2790
2833
  inbox,
2791
2834
  allowPrivateAddress,
2835
+ specDeterminer,
2792
2836
  meterProvider,
2793
2837
  tracerProvider
2794
2838
  }).catch((error) => {
@@ -2797,9 +2841,9 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
2797
2841
  inbox: inbox.href,
2798
2842
  error
2799
2843
  });
2800
- }));
2844
+ }))));
2801
2845
  let timer;
2802
- const timedOut = await Promise.race([Promise.all(sends).then(() => false), new Promise((resolve) => {
2846
+ const timedOut = await Promise.race([forwarding.then(() => false), new Promise((resolve) => {
2803
2847
  timer = setTimeout(() => resolve(true), deadline);
2804
2848
  })]);
2805
2849
  clearTimeout(timer);
@@ -2808,12 +2852,27 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
2808
2852
  deadline
2809
2853
  });
2810
2854
  }
2811
- async function enqueueForwarding({ activity, activityId, activityType, baseUrl, startQueue, meterProvider }, outboxQueue, inboxes) {
2855
+ async function enqueueForwarding(parameters, outboxQueue, inboxes) {
2856
+ const { activity, activityId, activityType, baseUrl, startQueue, meterProvider } = parameters;
2812
2857
  const logger = getLogger([
2813
2858
  "fedify",
2814
2859
  "federation",
2815
2860
  "inbox"
2816
2861
  ]);
2862
+ const key = await resolveForwardingKey(parameters);
2863
+ const keys = [];
2864
+ if (key != null) try {
2865
+ keys.push({
2866
+ keyId: key.keyId.href,
2867
+ privateKey: await exportJwk(key.privateKey)
2868
+ });
2869
+ } catch (error) {
2870
+ logger.error("Failed to export the gateway key {keyId}; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
2871
+ keyId: key.keyId.href,
2872
+ activityId: activityId.href,
2873
+ error
2874
+ });
2875
+ }
2817
2876
  startQueue?.();
2818
2877
  const started = (/* @__PURE__ */ new Date()).toISOString();
2819
2878
  const traceContext = {};
@@ -2823,7 +2882,7 @@ async function enqueueForwarding({ activity, activityId, activityType, baseUrl,
2823
2882
  type: "outbox",
2824
2883
  id: crypto.randomUUID(),
2825
2884
  baseUrl,
2826
- keys: [],
2885
+ keys,
2827
2886
  activity,
2828
2887
  activityId: activityId.href,
2829
2888
  activityType,
@@ -5324,6 +5383,8 @@ var FederationImpl = class extends FederationBuilderImpl {
5324
5383
  outboxQueue: this.outboxQueue,
5325
5384
  startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
5326
5385
  allowPrivateAddress: this.allowPrivateAddress,
5386
+ getKeys: () => this.#getPortableGatewayKeyPairs(context, identifier, recipient),
5387
+ specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, this.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
5327
5388
  options: this.portableInboxForwarding,
5328
5389
  meterProvider: this.meterProvider,
5329
5390
  tracerProvider: this.tracerProvider
@@ -5332,6 +5393,49 @@ var FederationImpl = class extends FederationBuilderImpl {
5332
5393
  }
5333
5394
  });
5334
5395
  }
5396
+ /**
5397
+ * Gets this server's gateway key pairs for the portable actor that owns
5398
+ * a portable inbox, which sign the activities forwarded from the inbox.
5399
+ * @param context The context.
5400
+ * @param identifier The identifier of the portable actor.
5401
+ * @param recipient The portable inbox.
5402
+ * @returns The key pairs, or an empty array if the actor has no gateway
5403
+ * keys on this server.
5404
+ */
5405
+ async #getPortableGatewayKeyPairs(context, identifier, recipient) {
5406
+ const logger = getLogger([
5407
+ "fedify",
5408
+ "federation",
5409
+ "inbox"
5410
+ ]);
5411
+ if (this.actorCallbacks?.keyPairsDispatcher == null || this.actorCallbacks.portableActorIdMapper == null) {
5412
+ logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as gateway keys need both a key pairs dispatcher and a portable actor ID mapper.", { inbox: recipient.canonicalInboxId });
5413
+ return [];
5414
+ }
5415
+ const actorId = getCanonicalPortableId(recipient.actorId);
5416
+ if (actorId == null) return [];
5417
+ const keyPairs = await context.getActorKeyPairs(identifier);
5418
+ for (const { cryptographicKey } of keyPairs) {
5419
+ const owner = cryptographicKey.ownerId;
5420
+ const canonicalOwner = owner == null ? null : getCanonicalPortableId(owner);
5421
+ if (canonicalOwner === actorId) continue;
5422
+ if (canonicalOwner == null) logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are not the gateway keys of a portable actor.", {
5423
+ inbox: recipient.canonicalInboxId,
5424
+ identifier
5425
+ });
5426
+ else logger.warn("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are the gateway keys of {owner}, not of the recipient {actorId}.", {
5427
+ inbox: recipient.canonicalInboxId,
5428
+ identifier,
5429
+ owner: canonicalOwner,
5430
+ actorId
5431
+ });
5432
+ return [];
5433
+ }
5434
+ return keyPairs.map(({ keyId, privateKey }) => ({
5435
+ keyId,
5436
+ privateKey
5437
+ }));
5438
+ }
5335
5439
  async #fetchHashlinkMedia(request, media, { onNotFound, contextData, span, metricState }) {
5336
5440
  metricState.endpoint = "hashlink_media";
5337
5441
  metricState.routeTemplate = HASHLINK_MEDIA_ROUTE_TEMPLATE;
@@ -2,10 +2,10 @@ import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { t as __exportAll } from "./rolldown-runtime-BC-Eo5Mj.js";
4
4
  import { r as getDefaultActivityTransformers } from "./transformers-DAtXl_Kc.js";
5
- import { $ as recordCollectionPageItems, C as hasSignature, D as signJsonLd, E as isInvalidUrlTypeError, H as hasPortableActor, J as getRemoteHost, K as getDurationMs, L as importJwk, M as exportJwk, O as verifyCompactJsonLd, Q as recordCollectionDispatchDuration, R as validateCryptoKey, S as getNormalizationContextLoader, T as isClearlyMalformedContextReference, U as isCompatibleKeyId, V as getGatewayKeyBase, W as isPortableUri, X as isAbortError, Y as instrumentDocumentLoader, Z as recordCircuitBreakerStateChange, _ as assertSafeJsonLd, a as verifyRequestDetailed, at as recordOutboxActivity, c as hasProofLike, ct as registerQueueDepthGauge, d as verifyObject, et as recordCollectionRequest, f as verifyPortableObjectProof, g as InvalidContextReferenceError, ht as version, i as verifyRequest, it as recordInboxActivity, j as wrapContextLoaderForJsonLd, l as signObject, lt as normalizeOutgoingActivityJsonLd, mt as name, n as parseRfc9421SignatureInput, ot as recordOutboxEnqueue, p as verifyPortableObjectProofPolicy, q as getFederationMetrics, rt as recordFanoutRecipients, st as recordWebFingerHandle, t as doubleKnock, tt as recordCollectionTotalItems, u as verifyMapLocalProof, ut as formatAcceptSignature, w as hasSignatureLike, x as detachSignature, y as compactJsonLd } from "./http-vfTpzGEq.js";
5
+ import { $ as recordCollectionPageItems, B as getCanonicalPortableId, C as hasSignature, D as signJsonLd, E as isInvalidUrlTypeError, H as hasPortableActor, J as getRemoteHost, K as getDurationMs, L as importJwk, M as exportJwk, O as verifyCompactJsonLd, Q as recordCollectionDispatchDuration, R as validateCryptoKey, S as getNormalizationContextLoader, T as isClearlyMalformedContextReference, U as isCompatibleKeyId, V as getGatewayKeyBase, W as isPortableUri, X as isAbortError, Y as instrumentDocumentLoader, Z as recordCircuitBreakerStateChange, _ as assertSafeJsonLd, a as verifyRequestDetailed, at as recordOutboxActivity, c as hasProofLike, ct as registerQueueDepthGauge, d as verifyObject, et as recordCollectionRequest, f as verifyPortableObjectProof, g as InvalidContextReferenceError, ht as version, i as verifyRequest, it as recordInboxActivity, j as wrapContextLoaderForJsonLd, l as signObject, lt as normalizeOutgoingActivityJsonLd, mt as name, n as parseRfc9421SignatureInput, ot as recordOutboxEnqueue, p as verifyPortableObjectProofPolicy, q as getFederationMetrics, rt as recordFanoutRecipients, st as recordWebFingerHandle, t as doubleKnock, tt as recordCollectionTotalItems, u as verifyMapLocalProof, ut as formatAcceptSignature, w as hasSignatureLike, x as detachSignature, y as compactJsonLd } from "./http-4PCCvhsU.js";
6
6
  import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-C_cNlNVK.js";
7
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DfGz0cXm.js";
8
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DCJuwdnB.js";
7
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-_pbbgLJK.js";
8
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-1KUmAPH7.js";
9
9
  import { getLogger, withContext } from "@logtape/logtape";
10
10
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
11
11
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
@@ -2633,13 +2633,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
2633
2633
  * @param parameters The parameters for handling the collection.
2634
2634
  * @returns A promise that resolves to an HTTP response.
2635
2635
  */
2636
- async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
2637
- const spanName = name$2.trim().replace(/\s+/g, "_");
2636
+ async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
2637
+ const spanName = name$1.trim().replace(/\s+/g, "_");
2638
2638
  tracerProvider = tracerProvider ?? trace.getTracerProvider();
2639
2639
  const tracer = tracerProvider.getTracer(name, version);
2640
2640
  const cursor = new URL(request.url).searchParams.get("cursor");
2641
2641
  const metricBase = {
2642
- kind: getCollectionMetricKind(name$2),
2642
+ kind: getCollectionMetricKind(name$1),
2643
2643
  page: cursor != null,
2644
2644
  dispatcher: "built_in"
2645
2645
  };
@@ -2680,7 +2680,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
2680
2680
  span.setStatus({ code: SpanStatusCode.ERROR });
2681
2681
  return await onNotFound(request);
2682
2682
  }
2683
- const items = filterCollectionItems(page.items, name$2, filterPredicate);
2683
+ const items = filterCollectionItems(page.items, name$1, filterPredicate);
2684
2684
  itemCount = items.length;
2685
2685
  span.setAttribute("fedify.collection.items", itemCount);
2686
2686
  return items;
@@ -2720,7 +2720,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
2720
2720
  } else {
2721
2721
  const uri = new URL(baseUri);
2722
2722
  uri.searchParams.set("cursor", cursor);
2723
- const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
2723
+ const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
2724
2724
  kind: SpanKind.SERVER,
2725
2725
  attributes: {
2726
2726
  "activitypub.collection.id": uri.href,
@@ -2736,7 +2736,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
2736
2736
  span.setStatus({ code: SpanStatusCode.ERROR });
2737
2737
  return await onNotFound(request);
2738
2738
  }
2739
- const items = filterCollectionItems(page.items, name$2, filterPredicate);
2739
+ const items = filterCollectionItems(page.items, name$1, filterPredicate);
2740
2740
  itemCount = items.length;
2741
2741
  span.setAttribute("fedify.collection.items", itemCount);
2742
2742
  return {
@@ -3666,8 +3666,9 @@ async function handleInboxInternal(request, parameters, span) {
3666
3666
  });
3667
3667
  }
3668
3668
  if (!skipSignatureVerification) {
3669
- if (inspectCompoundPortableObjectApplicability(json, INBOX_COMPOUND_PROOF_LIMITS) !== "absent") {
3670
- const compoundProof = await verifyCompoundPortableObjectProofs(json, INBOX_COMPOUND_PROOF_LIMITS, {
3669
+ const compoundJson = Array.isArray(json) ? json : jsonWithoutSig;
3670
+ if (inspectCompoundPortableObjectApplicability(compoundJson, INBOX_COMPOUND_PROOF_LIMITS) !== "absent") {
3671
+ const compoundProof = await verifyCompoundPortableObjectProofs(compoundJson, INBOX_COMPOUND_PROOF_LIMITS, {
3671
3672
  documentLoader: ctx.documentLoader,
3672
3673
  keyCache,
3673
3674
  meterProvider,
@@ -3883,8 +3884,8 @@ var CustomCollectionHandler = class {
3883
3884
  * @param CollectionPage The CollectionPage constructor.
3884
3885
  * @param filterPredicate Optional filter predicate for items.
3885
3886
  */
3886
- constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
3887
- this.name = name$1;
3887
+ constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
3888
+ this.name = name$2;
3888
3889
  this.values = values;
3889
3890
  this.context = context;
3890
3891
  this.callbacks = callbacks;
@@ -4964,6 +4965,7 @@ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, loc
4964
4965
  return {
4965
4966
  status: "accepted",
4966
4967
  recipient: {
4968
+ actorId: id,
4967
4969
  inboxId,
4968
4970
  canonicalInboxId,
4969
4971
  gateways
@@ -4997,8 +4999,11 @@ function canonicalize(iri) {
4997
4999
  * Forwarding is therefore best effort. Without {@link KvStore.cas}, nothing is
4998
5000
  * forwarded.
4999
5001
  *
5000
- * Forwarded requests are not signed with HTTP Signatures; the receiving
5001
- * gateways authenticate the activity by its own proof.
5002
+ * Forwarded requests are signed with HTTP Signatures by the RSA key among
5003
+ * {@link ForwardPortableInboxActivityParameters.getKeys}, if any, so that
5004
+ * servers requiring HTTP Signatures accept them, and are sent unsigned
5005
+ * otherwise. Either way, the receiving gateways authenticate the activity by
5006
+ * its own proof.
5002
5007
  * @param parameters The parameters.
5003
5008
  * @returns The target inbox URLs that the activity was handed off to.
5004
5009
  */
@@ -5070,20 +5075,59 @@ function getForwardingTargets(recipient, excludedOrigins) {
5070
5075
  }
5071
5076
  return targets;
5072
5077
  }
5073
- async function forwardImmediately({ activity, activityId, activityType, allowPrivateAddress, options, meterProvider, tracerProvider }, inboxes) {
5078
+ /**
5079
+ * Resolves the key that signs forwarded requests: the first RSASSA-PKCS1-v1_5
5080
+ * key, as {@link sendActivity} signs requests only with such a key. Since
5081
+ * the targets have already been claimed, the activity is forwarded unsigned
5082
+ * rather than not at all if the key cannot be resolved or used.
5083
+ */
5084
+ async function resolveForwardingKey({ getKeys, activityId }) {
5085
+ if (getKeys == null) return null;
5086
+ const logger = getLogger([
5087
+ "fedify",
5088
+ "federation",
5089
+ "inbox"
5090
+ ]);
5091
+ let key;
5092
+ try {
5093
+ key = (await getKeys()).find((k) => k.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5");
5094
+ } catch (error) {
5095
+ logger.error("Failed to get the gateway keys to sign forwarded requests with; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
5096
+ activityId: activityId.href,
5097
+ error
5098
+ });
5099
+ return null;
5100
+ }
5101
+ if (key == null) return null;
5102
+ try {
5103
+ validateCryptoKey(key.privateKey, "private");
5104
+ } catch (error) {
5105
+ if (!(error instanceof TypeError)) throw error;
5106
+ logger.warn("The gateway key {keyId} cannot sign forwarded requests; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
5107
+ keyId: key.keyId.href,
5108
+ activityId: activityId.href,
5109
+ error
5110
+ });
5111
+ return null;
5112
+ }
5113
+ return key;
5114
+ }
5115
+ async function forwardImmediately(parameters, inboxes) {
5116
+ const { activity, activityId, activityType, allowPrivateAddress, specDeterminer, options, meterProvider, tracerProvider } = parameters;
5074
5117
  const logger = getLogger([
5075
5118
  "fedify",
5076
5119
  "federation",
5077
5120
  "inbox"
5078
5121
  ]);
5079
5122
  const deadline = (options ?? resolvePortableInboxForwardingOptions()).deadline.total("millisecond");
5080
- const sends = inboxes.map((inbox) => sendActivity({
5123
+ const forwarding = resolveForwardingKey(parameters).then((key) => Promise.all(inboxes.map((inbox) => sendActivity({
5081
5124
  activity,
5082
5125
  activityId: activityId.href,
5083
5126
  activityType,
5084
- keys: [],
5127
+ keys: key == null ? [] : [key],
5085
5128
  inbox,
5086
5129
  allowPrivateAddress,
5130
+ specDeterminer,
5087
5131
  meterProvider,
5088
5132
  tracerProvider
5089
5133
  }).catch((error) => {
@@ -5092,9 +5136,9 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
5092
5136
  inbox: inbox.href,
5093
5137
  error
5094
5138
  });
5095
- }));
5139
+ }))));
5096
5140
  let timer;
5097
- const timedOut = await Promise.race([Promise.all(sends).then(() => false), new Promise((resolve) => {
5141
+ const timedOut = await Promise.race([forwarding.then(() => false), new Promise((resolve) => {
5098
5142
  timer = setTimeout(() => resolve(true), deadline);
5099
5143
  })]);
5100
5144
  clearTimeout(timer);
@@ -5103,12 +5147,27 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
5103
5147
  deadline
5104
5148
  });
5105
5149
  }
5106
- async function enqueueForwarding({ activity, activityId, activityType, baseUrl, startQueue, meterProvider }, outboxQueue, inboxes) {
5150
+ async function enqueueForwarding(parameters, outboxQueue, inboxes) {
5151
+ const { activity, activityId, activityType, baseUrl, startQueue, meterProvider } = parameters;
5107
5152
  const logger = getLogger([
5108
5153
  "fedify",
5109
5154
  "federation",
5110
5155
  "inbox"
5111
5156
  ]);
5157
+ const key = await resolveForwardingKey(parameters);
5158
+ const keys = [];
5159
+ if (key != null) try {
5160
+ keys.push({
5161
+ keyId: key.keyId.href,
5162
+ privateKey: await exportJwk(key.privateKey)
5163
+ });
5164
+ } catch (error) {
5165
+ logger.error("Failed to export the gateway key {keyId}; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
5166
+ keyId: key.keyId.href,
5167
+ activityId: activityId.href,
5168
+ error
5169
+ });
5170
+ }
5112
5171
  startQueue?.();
5113
5172
  const started = (/* @__PURE__ */ new Date()).toISOString();
5114
5173
  const traceContext = {};
@@ -5118,7 +5177,7 @@ async function enqueueForwarding({ activity, activityId, activityType, baseUrl,
5118
5177
  type: "outbox",
5119
5178
  id: crypto.randomUUID(),
5120
5179
  baseUrl,
5121
- keys: [],
5180
+ keys,
5122
5181
  activity,
5123
5182
  activityId: activityId.href,
5124
5183
  activityType,
@@ -7798,6 +7857,8 @@ var FederationImpl = class extends FederationBuilderImpl {
7798
7857
  outboxQueue: this.outboxQueue,
7799
7858
  startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
7800
7859
  allowPrivateAddress: this.allowPrivateAddress,
7860
+ getKeys: () => this.#getPortableGatewayKeyPairs(context, identifier, recipient),
7861
+ specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, this.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
7801
7862
  options: this.portableInboxForwarding,
7802
7863
  meterProvider: this.meterProvider,
7803
7864
  tracerProvider: this.tracerProvider
@@ -7806,6 +7867,49 @@ var FederationImpl = class extends FederationBuilderImpl {
7806
7867
  }
7807
7868
  });
7808
7869
  }
7870
+ /**
7871
+ * Gets this server's gateway key pairs for the portable actor that owns
7872
+ * a portable inbox, which sign the activities forwarded from the inbox.
7873
+ * @param context The context.
7874
+ * @param identifier The identifier of the portable actor.
7875
+ * @param recipient The portable inbox.
7876
+ * @returns The key pairs, or an empty array if the actor has no gateway
7877
+ * keys on this server.
7878
+ */
7879
+ async #getPortableGatewayKeyPairs(context, identifier, recipient) {
7880
+ const logger = getLogger([
7881
+ "fedify",
7882
+ "federation",
7883
+ "inbox"
7884
+ ]);
7885
+ if (this.actorCallbacks?.keyPairsDispatcher == null || this.actorCallbacks.portableActorIdMapper == null) {
7886
+ logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as gateway keys need both a key pairs dispatcher and a portable actor ID mapper.", { inbox: recipient.canonicalInboxId });
7887
+ return [];
7888
+ }
7889
+ const actorId = getCanonicalPortableId(recipient.actorId);
7890
+ if (actorId == null) return [];
7891
+ const keyPairs = await context.getActorKeyPairs(identifier);
7892
+ for (const { cryptographicKey } of keyPairs) {
7893
+ const owner = cryptographicKey.ownerId;
7894
+ const canonicalOwner = owner == null ? null : getCanonicalPortableId(owner);
7895
+ if (canonicalOwner === actorId) continue;
7896
+ if (canonicalOwner == null) logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are not the gateway keys of a portable actor.", {
7897
+ inbox: recipient.canonicalInboxId,
7898
+ identifier
7899
+ });
7900
+ else logger.warn("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are the gateway keys of {owner}, not of the recipient {actorId}.", {
7901
+ inbox: recipient.canonicalInboxId,
7902
+ identifier,
7903
+ owner: canonicalOwner,
7904
+ actorId
7905
+ });
7906
+ return [];
7907
+ }
7908
+ return keyPairs.map(({ keyId, privateKey }) => ({
7909
+ keyId,
7910
+ privateKey
7911
+ }));
7912
+ }
7809
7913
  async #fetchHashlinkMedia(request, media, { onNotFound, contextData, span, metricState }) {
7810
7914
  metricState.endpoint = "hashlink_media";
7811
7915
  metricState.routeTemplate = HASHLINK_MEDIA_ROUTE_TEMPLATE;
package/dist/mod.cjs CHANGED
@@ -3,14 +3,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("./rolldown-runtime-Dmm3t92W.cjs");
4
4
  const require_transformers = require("./transformers-BalCrSsr.cjs");
5
5
  require("./compat/mod.cjs");
6
- const require_http = require("./http-DGk8XI38.cjs");
7
- const require_federation = require("./federation-B1aeTKKN.cjs");
6
+ const require_http = require("./http-B5q1CHtL.cjs");
7
+ const require_federation = require("./federation-BLGx8JUH.cjs");
8
8
  const require_types = require("./types-Be2zbyeG.cjs");
9
- const require_owner = require("./owner-DCIH7Iq0.cjs");
10
- const require_kv_cache = require("./kv-cache-DvqkKNIj.cjs");
9
+ const require_owner = require("./owner-BQFZtFV4.cjs");
10
+ const require_kv_cache = require("./kv-cache-Dhhhrryv.cjs");
11
11
  require("./nodeinfo/mod.cjs");
12
12
  require("./runtime/mod.cjs");
13
- const require_sig = require("./sig-C6TnADze.cjs");
13
+ const require_sig = require("./sig-k3C8sF7g.cjs");
14
14
  require("./utils/mod.cjs");
15
15
  //#endregion
16
16
  exports.CircuitBreaker = require_federation.CircuitBreaker;
package/dist/mod.js CHANGED
@@ -3,15 +3,15 @@ import { URLPattern } from "urlpattern-polyfill";
3
3
  import "./rolldown-runtime-BC-Eo5Mj.js";
4
4
  import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-DAtXl_Kc.js";
5
5
  import "./compat/mod.js";
6
- import { A as verifySignature, D as signJsonLd, F as fetchKeyDetailed, I as generateCryptoKeyPair, L as importJwk, M as exportJwk, P as fetchKey, a as verifyRequestDetailed, b as createSignature, c as hasProofLike, d as verifyObject, dt as fulfillAcceptSignature, f as verifyPortableObjectProof, ft as parseAcceptSignature, h as verifyProof, i as verifyRequest, k as verifyJsonLd, l as signObject, pt as validateAcceptSignature, r as signRequest, s as createProof, ut as formatAcceptSignature, v as attachSignature, w as hasSignatureLike, x as detachSignature } from "./http-vfTpzGEq.js";
7
- import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "./middleware-CCbyUF4c.js";
6
+ import { A as verifySignature, D as signJsonLd, F as fetchKeyDetailed, I as generateCryptoKeyPair, L as importJwk, M as exportJwk, P as fetchKey, a as verifyRequestDetailed, b as createSignature, c as hasProofLike, d as verifyObject, dt as fulfillAcceptSignature, f as verifyPortableObjectProof, ft as parseAcceptSignature, h as verifyProof, i as verifyRequest, k as verifyJsonLd, l as signObject, pt as validateAcceptSignature, r as signRequest, s as createProof, ut as formatAcceptSignature, v as attachSignature, w as hasSignatureLike, x as detachSignature } from "./http-4PCCvhsU.js";
7
+ import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "./middleware-D_9pNYe9.js";
8
8
  import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-C_cNlNVK.js";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DfGz0cXm.js";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DCJuwdnB.js";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-_pbbgLJK.js";
10
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-1KUmAPH7.js";
11
11
  import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue, Router, RouterError } from "./federation/mod.js";
12
12
  import "./nodeinfo/mod.js";
13
13
  import "./runtime/mod.js";
14
- import { t as verifyPortableObject } from "./sig-Cs9_ecdh.js";
14
+ import { t as verifyPortableObject } from "./sig-DhdomAN0.js";
15
15
  import "./utils/mod.js";
16
16
  export * from "@fedify/vocab-runtime";
17
17
  //#endregion
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-DlZhxdFT.mjs";
5
5
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
- import { S as handleNodeInfoJrd, o as createFederation, x as handleNodeInfo } from "../middleware-CpyCNOW_.mjs";
8
+ import { S as handleNodeInfoJrd, o as createFederation, x as handleNodeInfo } from "../middleware-BKeQYPm0.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/nodeinfo/handler.test.ts
11
11
  test("handleNodeInfo()", async () => {
@@ -1,5 +1,5 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
- const require_http = require("./http-DGk8XI38.cjs");
2
+ const require_http = require("./http-B5q1CHtL.cjs");
3
3
  let _logtape_logtape = require("@logtape/logtape");
4
4
  let _fedify_vocab = require("@fedify/vocab");
5
5
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -1,9 +1,9 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-LYTbBhYV.mjs";
5
- import { c as verifyKeyOwnership, f as isCompatibleKeyId, h as isSamePublicKey$1, l as getCanonicalPortableId, n as fetchActorDocument, t as exportJwk } from "./key-BYXnTGro.mjs";
6
- import { t as fetchPortableGatewayKey } from "./portable-key-DCyKGCQd.mjs";
4
+ import { n as version, t as name } from "./deno-Dn-py9Zy.mjs";
5
+ import { c as verifyKeyOwnership, f as isCompatibleKeyId, h as isSamePublicKey$1, l as getCanonicalPortableId, n as fetchActorDocument, t as exportJwk } from "./key-BJrp524f.mjs";
6
+ import { t as fetchPortableGatewayKey } from "./portable-key-B4R-CiIV.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
9
9
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";