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

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 (83) hide show
  1. package/dist/{builder-DVQ0yhKJ.mjs → builder-CVHpPAjK.mjs} +2 -2
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{compound-proof-KmXDfWFp.mjs → compound-proof-B5Skp-vE.mjs} +1 -1
  6. package/dist/{context-DsB9kF6q.d.ts → context-BSywYspi.d.ts} +109 -1
  7. package/dist/{context-DijrgHDe.d.cts → context-CZjZYXFC.d.cts} +109 -1
  8. package/dist/{context-DG5QeQ8W.mjs → context-DlZhxdFT.mjs} +2 -1
  9. package/dist/{deno-B-NtYZVW.mjs → deno-LYTbBhYV.mjs} +1 -1
  10. package/dist/{docloader-C6yOVoaF.mjs → docloader-C0SWQylk.mjs} +2 -2
  11. package/dist/federation/builder.test.mjs +1 -1
  12. package/dist/federation/compound-fanout.test.mjs +3 -3
  13. package/dist/federation/handler-compound-proof.test.mjs +4 -4
  14. package/dist/federation/handler.test.mjs +6 -6
  15. package/dist/federation/hashlink-media.test.mjs +2 -2
  16. package/dist/federation/idempotency.test.mjs +2 -2
  17. package/dist/federation/metrics.test.mjs +1 -1
  18. package/dist/federation/middleware.test.mjs +8 -8
  19. package/dist/federation/mod.cjs +1 -1
  20. package/dist/federation/mod.d.cts +3 -3
  21. package/dist/federation/mod.d.ts +3 -3
  22. package/dist/federation/mod.js +1 -1
  23. package/dist/federation/outgoing-proof.test.mjs +5 -5
  24. package/dist/federation/portable-gateway-keys.test.mjs +4 -4
  25. package/dist/federation/portable-inbox.test.d.mts +2 -0
  26. package/dist/federation/portable-inbox.test.mjs +546 -0
  27. package/dist/federation/portable.test.mjs +3 -3
  28. package/dist/federation/send.test.mjs +3 -3
  29. package/dist/federation/tasks/enqueue.test.mjs +2 -2
  30. package/dist/federation/tasks/tasks.test.mjs +3 -3
  31. package/dist/federation/temporal.test.mjs +1 -1
  32. package/dist/federation/webfinger.test.mjs +2 -2
  33. package/dist/{federation-CUiHc7dP.cjs → federation-B1aeTKKN.cjs} +468 -88
  34. package/dist/{http-DKWi8RjI.mjs → http-C7qHlv-b.mjs} +4 -4
  35. package/dist/{http-CuLWIJdf.cjs → http-DGk8XI38.cjs} +1 -1
  36. package/dist/{http-BoWBwC0g.js → http-vfTpzGEq.js} +1 -1
  37. package/dist/{key-lfcx_NaE.mjs → key-BYXnTGro.mjs} +2 -2
  38. package/dist/{kv-cache-BdnmnAVc.js → kv-cache-DCJuwdnB.js} +1 -1
  39. package/dist/{kv-cache-d8EjO29d.mjs → kv-cache-DEH5jyND.mjs} +1 -1
  40. package/dist/{kv-cache-DE8kSNQU.cjs → kv-cache-DvqkKNIj.cjs} +1 -1
  41. package/dist/{ld-jyjdrWjG.mjs → ld-DT3e2hOv.mjs} +3 -3
  42. package/dist/{metrics-B5Rei-HC.mjs → metrics-DvlvYpq_.mjs} +1 -1
  43. package/dist/{middleware-CdVnCDXD.mjs → middleware-BJcez_E3.mjs} +1 -1
  44. package/dist/{middleware-CAObohey.js → middleware-CCbyUF4c.js} +417 -38
  45. package/dist/{middleware-CPx4ZWwt.mjs → middleware-CpyCNOW_.mjs} +423 -48
  46. package/dist/{mod-DMkflQdF.d.ts → mod-B2h2KY0q.d.ts} +1 -1
  47. package/dist/{mod-DTAaBwiY.d.cts → mod-JzkaEXsi.d.cts} +1 -1
  48. package/dist/mod.cjs +5 -5
  49. package/dist/mod.d.cts +4 -4
  50. package/dist/mod.d.ts +4 -4
  51. package/dist/mod.js +5 -5
  52. package/dist/nodeinfo/handler.test.mjs +2 -2
  53. package/dist/{owner-ByqNQVaa.mjs → owner-CDsVeZI7.mjs} +3 -3
  54. package/dist/{owner-BXufwAzm.cjs → owner-DCIH7Iq0.cjs} +1 -1
  55. package/dist/{owner-1TFakcTF.js → owner-DfGz0cXm.js} +1 -1
  56. package/dist/{portable-key-Cw_ow5vn.mjs → portable-key-DCyKGCQd.mjs} +2 -2
  57. package/dist/{proof-B6gwdhN5.mjs → proof-CxsVG6vM.mjs} +4 -4
  58. package/dist/{send-DsK7xevO.mjs → send-BZJ7NsVV.mjs} +8 -4
  59. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  60. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  61. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  62. package/dist/sig/compound-proof.test.mjs +2 -2
  63. package/dist/sig/http.test.mjs +2 -2
  64. package/dist/sig/key.test.mjs +1 -1
  65. package/dist/sig/ld.test.mjs +2 -2
  66. package/dist/sig/mod.cjs +3 -3
  67. package/dist/sig/mod.js +3 -3
  68. package/dist/sig/owner.test.mjs +1 -1
  69. package/dist/sig/portable-collection.test.mjs +2 -2
  70. package/dist/sig/portable-key.test.mjs +3 -3
  71. package/dist/sig/proof.test.mjs +3 -3
  72. package/dist/{sig-TTn9wYrE.cjs → sig-C6TnADze.cjs} +2 -2
  73. package/dist/{sig-BR_Z6mpY.js → sig-Cs9_ecdh.js} +2 -2
  74. package/dist/{temporal-Bw5jtrBY.mjs → temporal-CLzSfIOV.mjs} +1 -1
  75. package/dist/testing/kv.test.mjs +1 -1
  76. package/dist/testing/mod.d.mts +108 -0
  77. package/dist/testing/mod.mjs +2 -2
  78. package/dist/{testing-By1YYsIK.mjs → testing-CO_cEvQc.mjs} +1 -1
  79. package/dist/utils/docloader.test.mjs +2 -2
  80. package/dist/utils/kv-cache.test.mjs +1 -1
  81. package/dist/utils/mod.cjs +1 -1
  82. package/dist/utils/mod.js +1 -1
  83. package/package.json +6 -6
@@ -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-B-NtYZVW.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-B5Rei-HC.mjs";
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";
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-lfcx_NaE.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";
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-jyjdrWjG.mjs";
10
- import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-B6gwdhN5.mjs";
11
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-DKWi8RjI.mjs";
12
- import { t as getAuthenticatedDocumentLoader } from "./docloader-C6yOVoaF.mjs";
13
- import { n as kvCache } from "./kv-cache-d8EjO29d.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";
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-ByqNQVaa.mjs";
17
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-DsK7xevO.mjs";
18
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-DVQ0yhKJ.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";
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-KmXDfWFp.mjs";
21
+ import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-B5Skp-vE.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-Bw5jtrBY.mjs";
24
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-CLzSfIOV.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$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
862
- const spanName = name$1.trim().replace(/\s+/g, "_");
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, "_");
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$1),
867
+ kind: getCollectionMetricKind(name$2),
868
868
  page: cursor != null,
869
869
  dispatcher: "built_in"
870
870
  };
@@ -905,7 +905,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
905
905
  span.setStatus({ code: SpanStatusCode.ERROR });
906
906
  return await onNotFound(request);
907
907
  }
908
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
908
+ const items = filterCollectionItems(page.items, name$2, 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$1, 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$1}`, {
948
+ const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
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$1, identifier, uriGetter,
961
961
  span.setStatus({ code: SpanStatusCode.ERROR });
962
962
  return await onNotFound(request);
963
963
  }
964
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
964
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
965
965
  itemCount = items.length;
966
966
  span.setAttribute("fedify.collection.items", itemCount);
967
967
  return {
@@ -1467,7 +1467,7 @@ async function handleInbox(request, options) {
1467
1467
  * @returns A promise that resolves to an HTTP response.
1468
1468
  */
1469
1469
  async function handleInboxInternal(request, parameters, span) {
1470
- const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, publicKeyTtl, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider } = parameters;
1470
+ const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, publicKeyTtl, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider, portableInbox } = parameters;
1471
1471
  const logger = getLogger([
1472
1472
  "fedify",
1473
1473
  "federation",
@@ -1480,7 +1480,7 @@ async function handleInboxInternal(request, parameters, span) {
1480
1480
  message: "Actor dispatcher is not set."
1481
1481
  });
1482
1482
  return await onNotFound(request);
1483
- } else if (recipient != null) {
1483
+ } else if (recipient != null && portableInbox == null) {
1484
1484
  const actor = await actorDispatcher(ctx, recipient);
1485
1485
  if (actor == null || actor instanceof Tombstone) {
1486
1486
  logger.error("Actor {recipient} not found.", { recipient });
@@ -1942,6 +1942,19 @@ async function handleInboxInternal(request, parameters, span) {
1942
1942
  tracerProvider,
1943
1943
  idempotencyStrategy: parameters.idempotencyStrategy
1944
1944
  });
1945
+ if (portableInbox != null && activity.id != null && PORTABLE_INBOX_FORWARDABLE_RESULTS.has(routeResult)) if (skipSignatureVerification || !(ldSigVerified || proofVerified)) logger.debug("Not forwarding activity {activityId} to the other gateways of the portable inbox {inbox}, as it is not authenticated by its own proof.", {
1946
+ activityId: activity.id.href,
1947
+ inbox: portableInbox.recipient.canonicalInboxId
1948
+ });
1949
+ else try {
1950
+ await portableInbox.forward(json, activity.id, getTypeId(activity).href);
1951
+ } catch (error) {
1952
+ logger.error("Failed to forward activity {activityId} to the other gateways of the portable inbox {inbox}:\n{error}", {
1953
+ activityId: activity.id.href,
1954
+ inbox: portableInbox.recipient.canonicalInboxId,
1955
+ error
1956
+ });
1957
+ }
1945
1958
  if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
1946
1959
  status: 202,
1947
1960
  headers: { "Content-Type": "text/plain; charset=utf-8" }
@@ -1967,6 +1980,12 @@ async function handleInboxInternal(request, parameters, span) {
1967
1980
  headers: { "Content-Type": "text/plain; charset=utf-8" }
1968
1981
  });
1969
1982
  }
1983
+ const PORTABLE_INBOX_FORWARDABLE_RESULTS = /* @__PURE__ */ new Set([
1984
+ "success",
1985
+ "enqueued",
1986
+ "alreadyProcessed",
1987
+ "unsupportedActivity"
1988
+ ]);
1970
1989
  /**
1971
1990
  * Handles a custom collection request.
1972
1991
  * @template TItem The type of items in the collection.
@@ -2089,8 +2108,8 @@ var CustomCollectionHandler = class {
2089
2108
  * @param CollectionPage The CollectionPage constructor.
2090
2109
  * @param filterPredicate Optional filter predicate for items.
2091
2110
  */
2092
- constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
2093
- this.name = name$2;
2111
+ constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
2112
+ this.name = name$1;
2094
2113
  this.values = values;
2095
2114
  this.context = context;
2096
2115
  this.callbacks = callbacks;
@@ -2584,6 +2603,251 @@ function isPortableGatewayKey(key) {
2584
2603
  return key?.id != null && isCompatibleKeyId(key.id) && key.ownerId != null && isPortableUri(key.ownerId);
2585
2604
  }
2586
2605
  //#endregion
2606
+ //#region src/federation/portable-inbox.ts
2607
+ const MAX_TIMEOUT_MS = 2 ** 31 - 1;
2608
+ /**
2609
+ * Fills in the defaults of {@link PortableInboxForwardingOptions} and
2610
+ * validates them.
2611
+ * @param options The options.
2612
+ * @returns The resolved options.
2613
+ * @throws {RangeError} If `maxTargets` is not a non-negative integer, if `ttl`
2614
+ * is not positive, if `deadline` is negative or longer
2615
+ * than 2,147,483,647 milliseconds (about 24.8 days), or
2616
+ * if either duration has calendar units, i.e., weeks,
2617
+ * months, or years, whose length depends on the date.
2618
+ */
2619
+ function resolvePortableInboxForwardingOptions(options = {}) {
2620
+ const maxTargets = options.maxTargets ?? 10;
2621
+ if (!Number.isInteger(maxTargets) || maxTargets < 0) throw new RangeError("portableInboxForwarding.maxTargets must be a non-negative integer.");
2622
+ const ttl = Temporal.Duration.from(options.ttl ?? { days: 30 });
2623
+ if (ttl.total("millisecond") <= 0) throw new RangeError("portableInboxForwarding.ttl must be positive.");
2624
+ const deadline = Temporal.Duration.from(options.deadline ?? { seconds: 10 });
2625
+ const deadlineMs = deadline.total("millisecond");
2626
+ if (deadlineMs < 0 || deadlineMs > MAX_TIMEOUT_MS) throw new RangeError(`portableInboxForwarding.deadline must be between 0 and ${MAX_TIMEOUT_MS} milliseconds.`);
2627
+ return {
2628
+ maxTargets,
2629
+ ttl,
2630
+ deadline
2631
+ };
2632
+ }
2633
+ /**
2634
+ * Decides whether this server accepts a delivery to a portable inbox on behalf
2635
+ * of the given actor, which the actor dispatcher returned for the identifier
2636
+ * in the requested inbox path.
2637
+ *
2638
+ * The actor document comes from the application, so it is trusted as is and
2639
+ * its proof is not verified here.
2640
+ * @param actor The actor the actor dispatcher returned.
2641
+ * @param options The requested DID, the canonical form of the requested inbox
2642
+ * ID, and the origin of this server.
2643
+ * @returns The resolution.
2644
+ */
2645
+ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, localOrigin }) {
2646
+ if (actor == null) return {
2647
+ status: "rejected",
2648
+ reason: "notFound"
2649
+ };
2650
+ const id = actor.id;
2651
+ if (id == null || id.protocol !== "ap:" && id.protocol !== "ap+ef61:") return {
2652
+ status: "rejected",
2653
+ reason: "notPortable"
2654
+ };
2655
+ if (!isSameAuthority(id, authority)) return {
2656
+ status: "rejected",
2657
+ reason: "authorityMismatch"
2658
+ };
2659
+ const inboxId = actor.inboxId;
2660
+ if (inboxId == null || canonicalize(inboxId) !== canonicalInboxId) return {
2661
+ status: "rejected",
2662
+ reason: "inboxMismatch"
2663
+ };
2664
+ const gateways = actor.gateways;
2665
+ if (!gateways.some((g) => isGatewayUrl(g) && g.origin === localOrigin)) return {
2666
+ status: "rejected",
2667
+ reason: "notGateway"
2668
+ };
2669
+ return {
2670
+ status: "accepted",
2671
+ recipient: {
2672
+ inboxId,
2673
+ canonicalInboxId,
2674
+ gateways
2675
+ }
2676
+ };
2677
+ }
2678
+ function isSameAuthority(id, authority) {
2679
+ try {
2680
+ return getFe34Origin(id) === authority;
2681
+ } catch (error) {
2682
+ if (error instanceof TypeError) return false;
2683
+ throw error;
2684
+ }
2685
+ }
2686
+ function canonicalize(iri) {
2687
+ try {
2688
+ return canonicalizePortableUri(typeof iri === "string" ? iri : formatIri(iri));
2689
+ } catch (error) {
2690
+ if (error instanceof TypeError) return null;
2691
+ throw error;
2692
+ }
2693
+ }
2694
+ /**
2695
+ * Forwards an activity received in a portable inbox to the inboxes of the same
2696
+ * portable actor on its other gateways, as FEP-ef61 recommends.
2697
+ *
2698
+ * FEP-ef61 forbids forwarding an activity from an inbox more than once, so
2699
+ * each target gateway is claimed with an atomic compare-and-swap before the
2700
+ * activity is handed off, and a claim is never released, even if the hand-off
2701
+ * fails, since a failed hand-off does not prove that nothing was delivered.
2702
+ * Forwarding is therefore best effort. Without {@link KvStore.cas}, nothing is
2703
+ * forwarded.
2704
+ *
2705
+ * Forwarded requests are not signed with HTTP Signatures; the receiving
2706
+ * gateways authenticate the activity by its own proof.
2707
+ * @param parameters The parameters.
2708
+ * @returns The target inbox URLs that the activity was handed off to.
2709
+ */
2710
+ async function forwardPortableInboxActivity(parameters) {
2711
+ const logger = getLogger([
2712
+ "fedify",
2713
+ "federation",
2714
+ "inbox"
2715
+ ]);
2716
+ const { recipient, activityId, excludedOrigins, kv, kvPrefix, outboxQueue } = parameters;
2717
+ const { maxTargets, ttl } = parameters.options ?? resolvePortableInboxForwardingOptions();
2718
+ if (kv.cas == null || maxTargets < 1) return [];
2719
+ const canonicalActivityId = canonicalize(activityId) ?? activityId.href;
2720
+ const targets = getForwardingTargets(recipient, excludedOrigins);
2721
+ if (targets.length > maxTargets) {
2722
+ logger.warn("The portable actor that owns the inbox {inbox} has more than {max} other gateways; the activity {activityId} is forwarded only to the first {max} of them.", {
2723
+ inbox: recipient.canonicalInboxId,
2724
+ activityId: activityId.href,
2725
+ max: maxTargets
2726
+ });
2727
+ targets.length = maxTargets;
2728
+ }
2729
+ const claimed = [];
2730
+ for (const { gateway, inbox } of targets) {
2731
+ const key = [
2732
+ ...kvPrefix,
2733
+ recipient.canonicalInboxId,
2734
+ canonicalActivityId,
2735
+ gateway
2736
+ ];
2737
+ if (await kv.cas(key, void 0, true, { ttl })) claimed.push(inbox);
2738
+ }
2739
+ if (claimed.length < 1) return [];
2740
+ logger.debug("Forwarding activity {activityId} from the portable inbox {inbox} to other gateways:\n{targets}", {
2741
+ activityId: activityId.href,
2742
+ inbox: recipient.canonicalInboxId,
2743
+ targets: claimed.map((t) => t.href)
2744
+ });
2745
+ if (outboxQueue == null) await forwardImmediately(parameters, claimed);
2746
+ else await enqueueForwarding(parameters, outboxQueue, claimed);
2747
+ return claimed;
2748
+ }
2749
+ function getForwardingTargets(recipient, excludedOrigins) {
2750
+ const logger = getLogger([
2751
+ "fedify",
2752
+ "federation",
2753
+ "inbox"
2754
+ ]);
2755
+ const seen = new Set(excludedOrigins);
2756
+ const targets = [];
2757
+ for (const gateway of recipient.gateways) {
2758
+ if (!isGatewayUrl(gateway) || seen.has(gateway.origin)) continue;
2759
+ seen.add(gateway.origin);
2760
+ let inbox;
2761
+ try {
2762
+ inbox = toCompatibleEf61Id(recipient.inboxId, gateway.origin);
2763
+ } catch (error) {
2764
+ if (!(error instanceof TypeError)) throw error;
2765
+ logger.warn("Cannot forward to the gateway {gateway}, as the portable inbox {inbox} cannot be represented as its compatible identifier.", {
2766
+ gateway: gateway.origin,
2767
+ inbox: recipient.canonicalInboxId
2768
+ });
2769
+ continue;
2770
+ }
2771
+ targets.push({
2772
+ gateway: gateway.origin,
2773
+ inbox
2774
+ });
2775
+ }
2776
+ return targets;
2777
+ }
2778
+ async function forwardImmediately({ activity, activityId, activityType, allowPrivateAddress, options, meterProvider, tracerProvider }, inboxes) {
2779
+ const logger = getLogger([
2780
+ "fedify",
2781
+ "federation",
2782
+ "inbox"
2783
+ ]);
2784
+ const deadline = (options ?? resolvePortableInboxForwardingOptions()).deadline.total("millisecond");
2785
+ const sends = inboxes.map((inbox) => sendActivity({
2786
+ activity,
2787
+ activityId: activityId.href,
2788
+ activityType,
2789
+ keys: [],
2790
+ inbox,
2791
+ allowPrivateAddress,
2792
+ meterProvider,
2793
+ tracerProvider
2794
+ }).catch((error) => {
2795
+ logger.error("Failed to forward activity {activityId} to {inbox}; it will not be forwarded to the inbox again:\n{error}", {
2796
+ activityId: activityId.href,
2797
+ inbox: inbox.href,
2798
+ error
2799
+ });
2800
+ }));
2801
+ let timer;
2802
+ const timedOut = await Promise.race([Promise.all(sends).then(() => false), new Promise((resolve) => {
2803
+ timer = setTimeout(() => resolve(true), deadline);
2804
+ })]);
2805
+ clearTimeout(timer);
2806
+ if (timedOut) logger.warn("Forwarding activity {activityId} to other gateways did not finish in {deadline} ms; responding to the delivery without waiting for it.", {
2807
+ activityId: activityId.href,
2808
+ deadline
2809
+ });
2810
+ }
2811
+ async function enqueueForwarding({ activity, activityId, activityType, baseUrl, startQueue, meterProvider }, outboxQueue, inboxes) {
2812
+ const logger = getLogger([
2813
+ "fedify",
2814
+ "federation",
2815
+ "inbox"
2816
+ ]);
2817
+ startQueue?.();
2818
+ const started = (/* @__PURE__ */ new Date()).toISOString();
2819
+ const traceContext = {};
2820
+ propagation.inject(context.active(), traceContext);
2821
+ await Promise.all(inboxes.map(async (inbox) => {
2822
+ const message = {
2823
+ type: "outbox",
2824
+ id: crypto.randomUUID(),
2825
+ baseUrl,
2826
+ keys: [],
2827
+ activity,
2828
+ activityId: activityId.href,
2829
+ activityType,
2830
+ inbox: inbox.href,
2831
+ sharedInbox: false,
2832
+ started,
2833
+ attempt: 0,
2834
+ headers: {},
2835
+ traceContext
2836
+ };
2837
+ try {
2838
+ await outboxQueue.enqueue(message);
2839
+ } catch (error) {
2840
+ logger.error("Failed to enqueue activity {activityId} to forward to {inbox}; it will not be forwarded to the inbox again:\n{error}", {
2841
+ activityId: activityId.href,
2842
+ inbox: inbox.href,
2843
+ error
2844
+ });
2845
+ return;
2846
+ }
2847
+ recordOutboxEnqueue(meterProvider, outboxQueue, message);
2848
+ }));
2849
+ }
2850
+ //#endregion
2587
2851
  //#region src/federation/outgoing-proof.ts
2588
2852
  function isPortableUrl(url) {
2589
2853
  return url.protocol === "ap:" || url.protocol === "ap+ef61:";
@@ -3304,6 +3568,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3304
3568
  kvPrefixes;
3305
3569
  publicKeyTtl;
3306
3570
  httpMessageSignaturesSpecTtl;
3571
+ portableInboxForwarding;
3307
3572
  inboxQueue;
3308
3573
  outboxQueue;
3309
3574
  fanoutQueue;
@@ -3336,6 +3601,7 @@ var FederationImpl = class extends FederationBuilderImpl {
3336
3601
  benchmarkMetricReader;
3337
3602
  benchmarkTriggerOptions;
3338
3603
  #mediaUploaderNoAuthWarned = false;
3604
+ #portableInboxForwardingWarned = false;
3339
3605
  #queueDepthGaugeSourceId = `fedify-${(++nextQueueDepthGaugeSourceId).toString(36)}`;
3340
3606
  #queueDepthGaugeEntries = [];
3341
3607
  #queueDepthGaugeMeterProvider;
@@ -3367,10 +3633,12 @@ var FederationImpl = class extends FederationBuilderImpl {
3367
3633
  acceptSignatureNonce: ["_fedify", "acceptSignatureNonce"],
3368
3634
  circuitBreaker: ["_fedify", "circuit"],
3369
3635
  taskDeduplication: ["_fedify", "taskDeduplication"],
3636
+ portableInboxForwarding: ["_fedify", "portableInboxForwarding"],
3370
3637
  ...options.kvPrefixes ?? {}
3371
3638
  };
3372
3639
  this.publicKeyTtl = Temporal.Duration.from(options.publicKeyTtl ?? { days: 30 });
3373
3640
  this.httpMessageSignaturesSpecTtl = Temporal.Duration.from(options.httpMessageSignaturesSpecTtl ?? { days: 90 });
3641
+ this.portableInboxForwarding = resolvePortableInboxForwardingOptions(options.portableInboxForwarding);
3374
3642
  if (options.queue == null) {
3375
3643
  this.inboxQueue = void 0;
3376
3644
  this.outboxQueue = void 0;
@@ -4040,8 +4308,8 @@ var FederationImpl = class extends FederationBuilderImpl {
4040
4308
  ]);
4041
4309
  const baseUrl = new URL(message.baseUrl);
4042
4310
  let context = this.#createContext(baseUrl, ctxData);
4043
- if (message.identifier != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: await context.getDocumentLoader({ identifier: message.identifier }) });
4044
- else if (this.sharedInboxKeyDispatcher != null) {
4311
+ if (message.identifier != null && this.actorCallbacks?.keyPairsDispatcher != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: await context.getDocumentLoader({ identifier: message.identifier }) });
4312
+ else if (message.identifier == null && this.sharedInboxKeyDispatcher != null) {
4045
4313
  const identity = await this.sharedInboxKeyDispatcher(context);
4046
4314
  if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
4047
4315
  }
@@ -4634,6 +4902,15 @@ var FederationImpl = class extends FederationBuilderImpl {
4634
4902
  span,
4635
4903
  metricState
4636
4904
  });
4905
+ if (request.method === "POST") {
4906
+ const portable = parsePortableGatewayRequest(url);
4907
+ if (portable != null) return await this.#fetchPortableInbox(request, portable, {
4908
+ onNotFound,
4909
+ contextData,
4910
+ span,
4911
+ metricState
4912
+ });
4913
+ }
4637
4914
  const portable = request.method === "GET" || request.method === "HEAD" ? parsePortableGatewayRequest(url) : null;
4638
4915
  if (portable != null) return await discardBodyForHead(request, await this.#fetchPortableObject(request, portable, {
4639
4916
  onNotFound,
@@ -4785,35 +5062,17 @@ var FederationImpl = class extends FederationBuilderImpl {
4785
5062
  onNotFound
4786
5063
  });
4787
5064
  context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
4788
- case "sharedInbox": {
5065
+ case "sharedInbox":
4789
5066
  if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
4790
5067
  const identity = await this.sharedInboxKeyDispatcher(context);
4791
5068
  if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
4792
5069
  }
4793
- if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
4794
- const inboxContextFactory = context.toInboxContext.bind(context);
4795
- inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
4796
- return await handleInbox(request, {
5070
+ return await this.#handleInbox(request, {
4797
5071
  recipient: route.values.identifier ?? null,
4798
5072
  context,
4799
- inboxContextFactory,
4800
- kv: this.kv,
4801
- kvPrefixes: this.kvPrefixes,
4802
- publicKeyTtl: this.publicKeyTtl,
4803
- queue: this.inboxQueue,
4804
- actorDispatcher: this.actorCallbacks?.dispatcher,
4805
- inboxListeners: this.inboxListeners,
4806
- inboxErrorHandler: this.inboxErrorHandler,
4807
- unverifiedActivityHandler: this.unverifiedActivityHandler,
4808
- onNotFound,
4809
- signatureTimeWindow: this.signatureTimeWindow,
4810
- skipSignatureVerification: this.skipSignatureVerification,
4811
- inboxChallengePolicy: this.inboxChallengePolicy,
4812
- meterProvider: this.meterProvider,
4813
- tracerProvider: this.tracerProvider,
4814
- idempotencyStrategy: this.idempotencyStrategy
5073
+ contextData,
5074
+ onNotFound
4815
5075
  });
4816
- }
4817
5076
  case "following": return await handleCollection(request, {
4818
5077
  name: "following",
4819
5078
  identifier: route.values.identifier,
@@ -4966,6 +5225,113 @@ var FederationImpl = class extends FederationBuilderImpl {
4966
5225
  onNotFound
4967
5226
  });
4968
5227
  }
5228
+ async #handleInbox(request, { recipient, context, contextData, onNotFound, portableInbox }) {
5229
+ if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
5230
+ const inboxContextFactory = context.toInboxContext.bind(context);
5231
+ inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
5232
+ return await handleInbox(request, {
5233
+ recipient,
5234
+ context,
5235
+ inboxContextFactory,
5236
+ kv: this.kv,
5237
+ kvPrefixes: this.kvPrefixes,
5238
+ publicKeyTtl: this.publicKeyTtl,
5239
+ queue: this.inboxQueue,
5240
+ actorDispatcher: this.actorCallbacks?.dispatcher,
5241
+ inboxListeners: this.inboxListeners,
5242
+ inboxErrorHandler: this.inboxErrorHandler,
5243
+ unverifiedActivityHandler: this.unverifiedActivityHandler,
5244
+ onNotFound,
5245
+ signatureTimeWindow: this.signatureTimeWindow,
5246
+ skipSignatureVerification: this.skipSignatureVerification,
5247
+ inboxChallengePolicy: this.inboxChallengePolicy,
5248
+ meterProvider: this.meterProvider,
5249
+ tracerProvider: this.tracerProvider,
5250
+ idempotencyStrategy: this.idempotencyStrategy,
5251
+ portableInbox
5252
+ });
5253
+ }
5254
+ async #fetchPortableInbox(request, portable, { onNotFound, contextData, span, metricState }) {
5255
+ const logger = getLogger([
5256
+ "fedify",
5257
+ "federation",
5258
+ "inbox"
5259
+ ]);
5260
+ if (portable.type === "malformed") {
5261
+ metricState.endpoint = "not_found";
5262
+ logger.debug("Malformed FEP-ef61 gateway inbox request {url}: {error}", {
5263
+ url: request.url,
5264
+ error: portable.error
5265
+ });
5266
+ return new Response("Malformed portable inbox ID.", {
5267
+ status: 400,
5268
+ headers: { "Content-Type": "text/plain; charset=utf-8" }
5269
+ });
5270
+ }
5271
+ const route = this.router.route(portable.path);
5272
+ if (route == null || route.name !== "inbox") {
5273
+ metricState.endpoint = "not_found";
5274
+ return await onNotFound(request);
5275
+ }
5276
+ metricState.routeTemplate = PORTABLE_GATEWAY_ROUTE_PREFIX + route.template;
5277
+ metricState.endpoint = "inbox";
5278
+ span.updateName(`${request.method} ${metricState.routeTemplate}`);
5279
+ const identifier = route.values.identifier;
5280
+ let context = this.#createContext(request, contextData);
5281
+ const actor = this.actorCallbacks?.dispatcher == null ? null : await this.actorCallbacks.dispatcher(context, identifier);
5282
+ const localOrigin = context.canonicalOrigin;
5283
+ const resolution = resolvePortableInboxRecipient(actor == null || actor instanceof Tombstone ? null : actor, {
5284
+ authority: portable.portableRequest.authority,
5285
+ canonicalInboxId: portable.canonicalId,
5286
+ localOrigin
5287
+ });
5288
+ if (resolution.status === "rejected") {
5289
+ logger.debug("Not accepting a delivery to the portable inbox {inbox} on behalf of the actor {identifier}: {reason}.", {
5290
+ inbox: portable.canonicalId,
5291
+ identifier,
5292
+ reason: resolution.reason
5293
+ });
5294
+ return await onNotFound(request);
5295
+ }
5296
+ const { recipient } = resolution;
5297
+ if (this.actorCallbacks?.keyPairsDispatcher != null) context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier }) });
5298
+ const excludedOrigins = [localOrigin, new URL(request.url).origin];
5299
+ return await this.#handleInbox(request, {
5300
+ recipient: identifier,
5301
+ context,
5302
+ contextData,
5303
+ onNotFound,
5304
+ portableInbox: {
5305
+ recipient,
5306
+ forward: async (activity, activityId, activityType) => {
5307
+ if (this.portableInboxForwarding.maxTargets < 1) return;
5308
+ if (this.kv.cas == null) {
5309
+ if (!this.#portableInboxForwardingWarned) {
5310
+ this.#portableInboxForwardingWarned = true;
5311
+ logger.warn("Activities delivered to FEP-ef61 portable inboxes are not forwarded to the other gateways, as the key–value store does not support compare-and-swap (KvStore.cas()), which is needed to forward each activity at most once.");
5312
+ }
5313
+ return;
5314
+ }
5315
+ await forwardPortableInboxActivity({
5316
+ recipient,
5317
+ activity,
5318
+ activityId,
5319
+ activityType,
5320
+ excludedOrigins,
5321
+ baseUrl: context.origin,
5322
+ kv: this.kv,
5323
+ kvPrefix: this.kvPrefixes.portableInboxForwarding,
5324
+ outboxQueue: this.outboxQueue,
5325
+ startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
5326
+ allowPrivateAddress: this.allowPrivateAddress,
5327
+ options: this.portableInboxForwarding,
5328
+ meterProvider: this.meterProvider,
5329
+ tracerProvider: this.tracerProvider
5330
+ });
5331
+ }
5332
+ }
5333
+ });
5334
+ }
4969
5335
  async #fetchHashlinkMedia(request, media, { onNotFound, contextData, span, metricState }) {
4970
5336
  metricState.endpoint = "hashlink_media";
4971
5337
  metricState.routeTemplate = HASHLINK_MEDIA_ROUTE_TEMPLATE;
@@ -5196,6 +5562,12 @@ var ContextImpl = class ContextImpl {
5196
5562
  if (path == null) throw new RouterError("No inbox path registered.");
5197
5563
  return new URL(path, this.canonicalOrigin);
5198
5564
  }
5565
+ getPortableInboxUri(identifier, authority) {
5566
+ const path = this.federation.router.build("inbox", { identifier });
5567
+ if (path == null) throw new RouterError("No inbox path registered.");
5568
+ if (authority == null) throw new TypeError("The authority of a portable ID is required outside an FEP-ef61 gateway request.");
5569
+ return buildPortableUri(authority, path);
5570
+ }
5199
5571
  getFollowingUri(identifier) {
5200
5572
  const path = this.federation.router.build("following", { identifier });
5201
5573
  if (path == null) throw new RouterError("No following collection path registered.");
@@ -5798,6 +6170,9 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
5798
6170
  getPortableObjectUri(cls, values, authority) {
5799
6171
  return super.getPortableObjectUri(cls, values, authority ?? this.portableRequest?.authority);
5800
6172
  }
6173
+ getPortableInboxUri(identifier, authority) {
6174
+ return super.getPortableInboxUri(identifier, authority ?? this.portableRequest?.authority);
6175
+ }
5801
6176
  async getActor(identifier, options) {
5802
6177
  if (this.federation.actorCallbacks == null || this.federation.actorCallbacks.dispatcher == null) throw new Error("No actor dispatcher registered.");
5803
6178
  if (this.#invokedFromActorDispatcher != null) getLogger([
@@ -6188,4 +6563,4 @@ function getRequestId(request) {
6188
6563
  return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
6189
6564
  }
6190
6565
  //#endregion
6191
- export { autoIdAssigner as S, parseHashlinkGatewayRequest as _, OutboxContextImpl as a, handleNodeInfoJrd as b, handleActor as c, handleInbox as d, handleObject as f, PORTABLE_OBJECT_CONTENT_TYPE as g, respondWithObjectIfAcceptable as h, KvSpecDeterminer as i, handleCollection as l, respondWithObject as m, FederationImpl as n, createFederation as o, handleOutbox as p, InboxContextImpl as r, handleWebFinger as s, ContextImpl as t, handleCustomCollection as u, handleBenchmarkTrigger as v, actorDehydrator as x, handleNodeInfo as y };
6566
+ export { actorDehydrator as C, handleNodeInfoJrd as S, respondWithObjectIfAcceptable as _, OutboxContextImpl as a, handleBenchmarkTrigger as b, forwardPortableInboxActivity as c, handleCollection as d, handleCustomCollection as f, respondWithObject as g, handleOutbox as h, KvSpecDeterminer as i, resolvePortableInboxForwardingOptions as l, handleObject as m, FederationImpl as n, createFederation as o, handleInbox as p, InboxContextImpl as r, handleWebFinger as s, ContextImpl as t, handleActor as u, PORTABLE_OBJECT_CONTENT_TYPE as v, autoIdAssigner as w, handleNodeInfo as x, parseHashlinkGatewayRequest as y };
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { Ut as WebFingerLinksDispatcher, _t as ActorDispatcher, gt as ActorAliasMapper, u as RequestContext, vt as ActorHandleMapper } from "./context-DsB9kF6q.js";
2
+ import { Wt as WebFingerLinksDispatcher, _t as ActorAliasMapper, u as RequestContext, vt as ActorDispatcher, yt as ActorHandleMapper } from "./context-BSywYspi.js";
3
3
  import { RouterError, RouterOptions, RouterRouteResult } from "@fedify/uri-template";
4
4
  import { MeterProvider, Span, Tracer } from "@opentelemetry/api";
5
5
 
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { Ut as WebFingerLinksDispatcher, _t as ActorDispatcher, gt as ActorAliasMapper, u as RequestContext, vt as ActorHandleMapper } from "./context-DijrgHDe.cjs";
2
+ import { Wt as WebFingerLinksDispatcher, _t as ActorAliasMapper, u as RequestContext, vt as ActorDispatcher, yt as ActorHandleMapper } from "./context-CZjZYXFC.cjs";
3
3
  import { MeterProvider, Span, Tracer } from "@opentelemetry/api";
4
4
  import { RouterError, RouterOptions, RouterRouteResult } from "@fedify/uri-template";
5
5
 
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-CuLWIJdf.cjs");
7
- const require_federation = require("./federation-CUiHc7dP.cjs");
6
+ const require_http = require("./http-DGk8XI38.cjs");
7
+ const require_federation = require("./federation-B1aeTKKN.cjs");
8
8
  const require_types = require("./types-Be2zbyeG.cjs");
9
- const require_owner = require("./owner-BXufwAzm.cjs");
10
- const require_kv_cache = require("./kv-cache-DE8kSNQU.cjs");
9
+ const require_owner = require("./owner-DCIH7Iq0.cjs");
10
+ const require_kv_cache = require("./kv-cache-DvqkKNIj.cjs");
11
11
  require("./nodeinfo/mod.cjs");
12
12
  require("./runtime/mod.cjs");
13
- const require_sig = require("./sig-TTn9wYrE.cjs");
13
+ const require_sig = require("./sig-C6TnADze.cjs");
14
14
  require("./utils/mod.cjs");
15
15
  //#endregion
16
16
  exports.CircuitBreaker = require_federation.CircuitBreaker;