@fedify/fedify 2.4.0-dev.2071 → 2.4.0-dev.2077
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.
- package/dist/{builder-DVQ0yhKJ.mjs → builder-i3jxVe9m.mjs} +2 -2
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-KmXDfWFp.mjs → compound-proof-Cayy-ECj.mjs} +1 -1
- package/dist/{context-DsB9kF6q.d.ts → context-BSywYspi.d.ts} +109 -1
- package/dist/{context-DijrgHDe.d.cts → context-CZjZYXFC.d.cts} +109 -1
- package/dist/{context-DG5QeQ8W.mjs → context-DlZhxdFT.mjs} +2 -1
- package/dist/{deno-B-NtYZVW.mjs → deno-Djkzd-G_.mjs} +1 -1
- package/dist/{docloader-C6yOVoaF.mjs → docloader-dA0RswUV.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +138 -11
- package/dist/federation/handler.test.mjs +6 -6
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +8 -8
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +3 -3
- package/dist/federation/mod.d.ts +3 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- package/dist/federation/portable-gateway-keys.test.mjs +4 -4
- package/dist/federation/portable-inbox.test.d.mts +2 -0
- package/dist/federation/portable-inbox.test.mjs +546 -0
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +2 -2
- package/dist/federation/tasks/tasks.test.mjs +3 -3
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{federation-CUiHc7dP.cjs → federation-CFd0Jhhv.cjs} +463 -82
- package/dist/{http-DKWi8RjI.mjs → http-CCJ97Jql.mjs} +4 -4
- package/dist/{http-CuLWIJdf.cjs → http-Dvy_IwRa.cjs} +1 -1
- package/dist/{http-BoWBwC0g.js → http-aqh3yFdM.js} +1 -1
- package/dist/{key-lfcx_NaE.mjs → key-IxTTC8Yf.mjs} +2 -2
- package/dist/{kv-cache-DE8kSNQU.cjs → kv-cache-BP69NV0P.cjs} +1 -1
- package/dist/{kv-cache-d8EjO29d.mjs → kv-cache-Bwwbh-xR.mjs} +1 -1
- package/dist/{kv-cache-BdnmnAVc.js → kv-cache-Y6SDRSX6.js} +1 -1
- package/dist/{ld-jyjdrWjG.mjs → ld-l0B9nREb.mjs} +3 -3
- package/dist/{metrics-B5Rei-HC.mjs → metrics-D1p6hv4z.mjs} +1 -1
- package/dist/{middleware-CdVnCDXD.mjs → middleware-BDjCUHMS.mjs} +1 -1
- package/dist/{middleware-CPx4ZWwt.mjs → middleware-BMgzqBtr.mjs} +418 -42
- package/dist/{middleware-CAObohey.js → middleware-SSfryVzY.js} +412 -32
- package/dist/{mod-DMkflQdF.d.ts → mod-B2h2KY0q.d.ts} +1 -1
- package/dist/{mod-DTAaBwiY.d.cts → mod-JzkaEXsi.d.cts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/{owner-BXufwAzm.cjs → owner-BpOxL5PG.cjs} +1 -1
- package/dist/{owner-ByqNQVaa.mjs → owner-DGbYmXqU.mjs} +3 -3
- package/dist/{owner-1TFakcTF.js → owner-jH1z_YfD.js} +1 -1
- package/dist/{portable-key-Cw_ow5vn.mjs → portable-key-CCwJGSsU.mjs} +2 -2
- package/dist/{proof-B6gwdhN5.mjs → proof-CVL7JnZd.mjs} +4 -4
- package/dist/{send-DsK7xevO.mjs → send-Ejy1jOz9.mjs} +8 -4
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +3 -3
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +2 -2
- package/dist/sig/portable-key.test.mjs +3 -3
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{sig-BR_Z6mpY.js → sig-Dpy1B1Ad.js} +2 -2
- package/dist/{sig-TTn9wYrE.cjs → sig-xoqy3ATq.cjs} +2 -2
- package/dist/{temporal-Bw5jtrBY.mjs → temporal-DNJ1cNpr.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +108 -0
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-By1YYsIK.mjs → testing-CO_cEvQc.mjs} +1 -1
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- 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-
|
|
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-
|
|
4
|
+
import { n as version, t as name } from "./deno-Djkzd-G_.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-D1p6hv4z.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-
|
|
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-IxTTC8Yf.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-
|
|
10
|
-
import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-
|
|
11
|
-
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-
|
|
12
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
13
|
-
import { n as kvCache } from "./kv-cache-
|
|
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-l0B9nREb.mjs";
|
|
10
|
+
import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-CVL7JnZd.mjs";
|
|
11
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-CCJ97Jql.mjs";
|
|
12
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-dA0RswUV.mjs";
|
|
13
|
+
import { n as kvCache } from "./kv-cache-Bwwbh-xR.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-
|
|
17
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-
|
|
18
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
16
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DGbYmXqU.mjs";
|
|
17
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-Ejy1jOz9.mjs";
|
|
18
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-i3jxVe9m.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-
|
|
21
|
+
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-Cayy-ECj.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-
|
|
24
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-DNJ1cNpr.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";
|
|
@@ -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 });
|
|
@@ -1891,8 +1891,9 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1891
1891
|
});
|
|
1892
1892
|
}
|
|
1893
1893
|
if (!skipSignatureVerification) {
|
|
1894
|
-
|
|
1895
|
-
|
|
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,
|
|
@@ -1942,6 +1943,19 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1942
1943
|
tracerProvider,
|
|
1943
1944
|
idempotencyStrategy: parameters.idempotencyStrategy
|
|
1944
1945
|
});
|
|
1946
|
+
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.", {
|
|
1947
|
+
activityId: activity.id.href,
|
|
1948
|
+
inbox: portableInbox.recipient.canonicalInboxId
|
|
1949
|
+
});
|
|
1950
|
+
else try {
|
|
1951
|
+
await portableInbox.forward(json, activity.id, getTypeId(activity).href);
|
|
1952
|
+
} catch (error) {
|
|
1953
|
+
logger.error("Failed to forward activity {activityId} to the other gateways of the portable inbox {inbox}:\n{error}", {
|
|
1954
|
+
activityId: activity.id.href,
|
|
1955
|
+
inbox: portableInbox.recipient.canonicalInboxId,
|
|
1956
|
+
error
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1945
1959
|
if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
|
|
1946
1960
|
status: 202,
|
|
1947
1961
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
@@ -1967,6 +1981,12 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1967
1981
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1968
1982
|
});
|
|
1969
1983
|
}
|
|
1984
|
+
const PORTABLE_INBOX_FORWARDABLE_RESULTS = /* @__PURE__ */ new Set([
|
|
1985
|
+
"success",
|
|
1986
|
+
"enqueued",
|
|
1987
|
+
"alreadyProcessed",
|
|
1988
|
+
"unsupportedActivity"
|
|
1989
|
+
]);
|
|
1970
1990
|
/**
|
|
1971
1991
|
* Handles a custom collection request.
|
|
1972
1992
|
* @template TItem The type of items in the collection.
|
|
@@ -2584,6 +2604,251 @@ function isPortableGatewayKey(key) {
|
|
|
2584
2604
|
return key?.id != null && isCompatibleKeyId(key.id) && key.ownerId != null && isPortableUri(key.ownerId);
|
|
2585
2605
|
}
|
|
2586
2606
|
//#endregion
|
|
2607
|
+
//#region src/federation/portable-inbox.ts
|
|
2608
|
+
const MAX_TIMEOUT_MS = 2 ** 31 - 1;
|
|
2609
|
+
/**
|
|
2610
|
+
* Fills in the defaults of {@link PortableInboxForwardingOptions} and
|
|
2611
|
+
* validates them.
|
|
2612
|
+
* @param options The options.
|
|
2613
|
+
* @returns The resolved options.
|
|
2614
|
+
* @throws {RangeError} If `maxTargets` is not a non-negative integer, if `ttl`
|
|
2615
|
+
* is not positive, if `deadline` is negative or longer
|
|
2616
|
+
* than 2,147,483,647 milliseconds (about 24.8 days), or
|
|
2617
|
+
* if either duration has calendar units, i.e., weeks,
|
|
2618
|
+
* months, or years, whose length depends on the date.
|
|
2619
|
+
*/
|
|
2620
|
+
function resolvePortableInboxForwardingOptions(options = {}) {
|
|
2621
|
+
const maxTargets = options.maxTargets ?? 10;
|
|
2622
|
+
if (!Number.isInteger(maxTargets) || maxTargets < 0) throw new RangeError("portableInboxForwarding.maxTargets must be a non-negative integer.");
|
|
2623
|
+
const ttl = Temporal.Duration.from(options.ttl ?? { days: 30 });
|
|
2624
|
+
if (ttl.total("millisecond") <= 0) throw new RangeError("portableInboxForwarding.ttl must be positive.");
|
|
2625
|
+
const deadline = Temporal.Duration.from(options.deadline ?? { seconds: 10 });
|
|
2626
|
+
const deadlineMs = deadline.total("millisecond");
|
|
2627
|
+
if (deadlineMs < 0 || deadlineMs > MAX_TIMEOUT_MS) throw new RangeError(`portableInboxForwarding.deadline must be between 0 and ${MAX_TIMEOUT_MS} milliseconds.`);
|
|
2628
|
+
return {
|
|
2629
|
+
maxTargets,
|
|
2630
|
+
ttl,
|
|
2631
|
+
deadline
|
|
2632
|
+
};
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Decides whether this server accepts a delivery to a portable inbox on behalf
|
|
2636
|
+
* of the given actor, which the actor dispatcher returned for the identifier
|
|
2637
|
+
* in the requested inbox path.
|
|
2638
|
+
*
|
|
2639
|
+
* The actor document comes from the application, so it is trusted as is and
|
|
2640
|
+
* its proof is not verified here.
|
|
2641
|
+
* @param actor The actor the actor dispatcher returned.
|
|
2642
|
+
* @param options The requested DID, the canonical form of the requested inbox
|
|
2643
|
+
* ID, and the origin of this server.
|
|
2644
|
+
* @returns The resolution.
|
|
2645
|
+
*/
|
|
2646
|
+
function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, localOrigin }) {
|
|
2647
|
+
if (actor == null) return {
|
|
2648
|
+
status: "rejected",
|
|
2649
|
+
reason: "notFound"
|
|
2650
|
+
};
|
|
2651
|
+
const id = actor.id;
|
|
2652
|
+
if (id == null || id.protocol !== "ap:" && id.protocol !== "ap+ef61:") return {
|
|
2653
|
+
status: "rejected",
|
|
2654
|
+
reason: "notPortable"
|
|
2655
|
+
};
|
|
2656
|
+
if (!isSameAuthority(id, authority)) return {
|
|
2657
|
+
status: "rejected",
|
|
2658
|
+
reason: "authorityMismatch"
|
|
2659
|
+
};
|
|
2660
|
+
const inboxId = actor.inboxId;
|
|
2661
|
+
if (inboxId == null || canonicalize(inboxId) !== canonicalInboxId) return {
|
|
2662
|
+
status: "rejected",
|
|
2663
|
+
reason: "inboxMismatch"
|
|
2664
|
+
};
|
|
2665
|
+
const gateways = actor.gateways;
|
|
2666
|
+
if (!gateways.some((g) => isGatewayUrl(g) && g.origin === localOrigin)) return {
|
|
2667
|
+
status: "rejected",
|
|
2668
|
+
reason: "notGateway"
|
|
2669
|
+
};
|
|
2670
|
+
return {
|
|
2671
|
+
status: "accepted",
|
|
2672
|
+
recipient: {
|
|
2673
|
+
inboxId,
|
|
2674
|
+
canonicalInboxId,
|
|
2675
|
+
gateways
|
|
2676
|
+
}
|
|
2677
|
+
};
|
|
2678
|
+
}
|
|
2679
|
+
function isSameAuthority(id, authority) {
|
|
2680
|
+
try {
|
|
2681
|
+
return getFe34Origin(id) === authority;
|
|
2682
|
+
} catch (error) {
|
|
2683
|
+
if (error instanceof TypeError) return false;
|
|
2684
|
+
throw error;
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
function canonicalize(iri) {
|
|
2688
|
+
try {
|
|
2689
|
+
return canonicalizePortableUri(typeof iri === "string" ? iri : formatIri(iri));
|
|
2690
|
+
} catch (error) {
|
|
2691
|
+
if (error instanceof TypeError) return null;
|
|
2692
|
+
throw error;
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Forwards an activity received in a portable inbox to the inboxes of the same
|
|
2697
|
+
* portable actor on its other gateways, as FEP-ef61 recommends.
|
|
2698
|
+
*
|
|
2699
|
+
* FEP-ef61 forbids forwarding an activity from an inbox more than once, so
|
|
2700
|
+
* each target gateway is claimed with an atomic compare-and-swap before the
|
|
2701
|
+
* activity is handed off, and a claim is never released, even if the hand-off
|
|
2702
|
+
* fails, since a failed hand-off does not prove that nothing was delivered.
|
|
2703
|
+
* Forwarding is therefore best effort. Without {@link KvStore.cas}, nothing is
|
|
2704
|
+
* forwarded.
|
|
2705
|
+
*
|
|
2706
|
+
* Forwarded requests are not signed with HTTP Signatures; the receiving
|
|
2707
|
+
* gateways authenticate the activity by its own proof.
|
|
2708
|
+
* @param parameters The parameters.
|
|
2709
|
+
* @returns The target inbox URLs that the activity was handed off to.
|
|
2710
|
+
*/
|
|
2711
|
+
async function forwardPortableInboxActivity(parameters) {
|
|
2712
|
+
const logger = getLogger([
|
|
2713
|
+
"fedify",
|
|
2714
|
+
"federation",
|
|
2715
|
+
"inbox"
|
|
2716
|
+
]);
|
|
2717
|
+
const { recipient, activityId, excludedOrigins, kv, kvPrefix, outboxQueue } = parameters;
|
|
2718
|
+
const { maxTargets, ttl } = parameters.options ?? resolvePortableInboxForwardingOptions();
|
|
2719
|
+
if (kv.cas == null || maxTargets < 1) return [];
|
|
2720
|
+
const canonicalActivityId = canonicalize(activityId) ?? activityId.href;
|
|
2721
|
+
const targets = getForwardingTargets(recipient, excludedOrigins);
|
|
2722
|
+
if (targets.length > maxTargets) {
|
|
2723
|
+
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.", {
|
|
2724
|
+
inbox: recipient.canonicalInboxId,
|
|
2725
|
+
activityId: activityId.href,
|
|
2726
|
+
max: maxTargets
|
|
2727
|
+
});
|
|
2728
|
+
targets.length = maxTargets;
|
|
2729
|
+
}
|
|
2730
|
+
const claimed = [];
|
|
2731
|
+
for (const { gateway, inbox } of targets) {
|
|
2732
|
+
const key = [
|
|
2733
|
+
...kvPrefix,
|
|
2734
|
+
recipient.canonicalInboxId,
|
|
2735
|
+
canonicalActivityId,
|
|
2736
|
+
gateway
|
|
2737
|
+
];
|
|
2738
|
+
if (await kv.cas(key, void 0, true, { ttl })) claimed.push(inbox);
|
|
2739
|
+
}
|
|
2740
|
+
if (claimed.length < 1) return [];
|
|
2741
|
+
logger.debug("Forwarding activity {activityId} from the portable inbox {inbox} to other gateways:\n{targets}", {
|
|
2742
|
+
activityId: activityId.href,
|
|
2743
|
+
inbox: recipient.canonicalInboxId,
|
|
2744
|
+
targets: claimed.map((t) => t.href)
|
|
2745
|
+
});
|
|
2746
|
+
if (outboxQueue == null) await forwardImmediately(parameters, claimed);
|
|
2747
|
+
else await enqueueForwarding(parameters, outboxQueue, claimed);
|
|
2748
|
+
return claimed;
|
|
2749
|
+
}
|
|
2750
|
+
function getForwardingTargets(recipient, excludedOrigins) {
|
|
2751
|
+
const logger = getLogger([
|
|
2752
|
+
"fedify",
|
|
2753
|
+
"federation",
|
|
2754
|
+
"inbox"
|
|
2755
|
+
]);
|
|
2756
|
+
const seen = new Set(excludedOrigins);
|
|
2757
|
+
const targets = [];
|
|
2758
|
+
for (const gateway of recipient.gateways) {
|
|
2759
|
+
if (!isGatewayUrl(gateway) || seen.has(gateway.origin)) continue;
|
|
2760
|
+
seen.add(gateway.origin);
|
|
2761
|
+
let inbox;
|
|
2762
|
+
try {
|
|
2763
|
+
inbox = toCompatibleEf61Id(recipient.inboxId, gateway.origin);
|
|
2764
|
+
} catch (error) {
|
|
2765
|
+
if (!(error instanceof TypeError)) throw error;
|
|
2766
|
+
logger.warn("Cannot forward to the gateway {gateway}, as the portable inbox {inbox} cannot be represented as its compatible identifier.", {
|
|
2767
|
+
gateway: gateway.origin,
|
|
2768
|
+
inbox: recipient.canonicalInboxId
|
|
2769
|
+
});
|
|
2770
|
+
continue;
|
|
2771
|
+
}
|
|
2772
|
+
targets.push({
|
|
2773
|
+
gateway: gateway.origin,
|
|
2774
|
+
inbox
|
|
2775
|
+
});
|
|
2776
|
+
}
|
|
2777
|
+
return targets;
|
|
2778
|
+
}
|
|
2779
|
+
async function forwardImmediately({ activity, activityId, activityType, allowPrivateAddress, options, meterProvider, tracerProvider }, inboxes) {
|
|
2780
|
+
const logger = getLogger([
|
|
2781
|
+
"fedify",
|
|
2782
|
+
"federation",
|
|
2783
|
+
"inbox"
|
|
2784
|
+
]);
|
|
2785
|
+
const deadline = (options ?? resolvePortableInboxForwardingOptions()).deadline.total("millisecond");
|
|
2786
|
+
const sends = inboxes.map((inbox) => sendActivity({
|
|
2787
|
+
activity,
|
|
2788
|
+
activityId: activityId.href,
|
|
2789
|
+
activityType,
|
|
2790
|
+
keys: [],
|
|
2791
|
+
inbox,
|
|
2792
|
+
allowPrivateAddress,
|
|
2793
|
+
meterProvider,
|
|
2794
|
+
tracerProvider
|
|
2795
|
+
}).catch((error) => {
|
|
2796
|
+
logger.error("Failed to forward activity {activityId} to {inbox}; it will not be forwarded to the inbox again:\n{error}", {
|
|
2797
|
+
activityId: activityId.href,
|
|
2798
|
+
inbox: inbox.href,
|
|
2799
|
+
error
|
|
2800
|
+
});
|
|
2801
|
+
}));
|
|
2802
|
+
let timer;
|
|
2803
|
+
const timedOut = await Promise.race([Promise.all(sends).then(() => false), new Promise((resolve) => {
|
|
2804
|
+
timer = setTimeout(() => resolve(true), deadline);
|
|
2805
|
+
})]);
|
|
2806
|
+
clearTimeout(timer);
|
|
2807
|
+
if (timedOut) logger.warn("Forwarding activity {activityId} to other gateways did not finish in {deadline} ms; responding to the delivery without waiting for it.", {
|
|
2808
|
+
activityId: activityId.href,
|
|
2809
|
+
deadline
|
|
2810
|
+
});
|
|
2811
|
+
}
|
|
2812
|
+
async function enqueueForwarding({ activity, activityId, activityType, baseUrl, startQueue, meterProvider }, outboxQueue, inboxes) {
|
|
2813
|
+
const logger = getLogger([
|
|
2814
|
+
"fedify",
|
|
2815
|
+
"federation",
|
|
2816
|
+
"inbox"
|
|
2817
|
+
]);
|
|
2818
|
+
startQueue?.();
|
|
2819
|
+
const started = (/* @__PURE__ */ new Date()).toISOString();
|
|
2820
|
+
const traceContext = {};
|
|
2821
|
+
propagation.inject(context.active(), traceContext);
|
|
2822
|
+
await Promise.all(inboxes.map(async (inbox) => {
|
|
2823
|
+
const message = {
|
|
2824
|
+
type: "outbox",
|
|
2825
|
+
id: crypto.randomUUID(),
|
|
2826
|
+
baseUrl,
|
|
2827
|
+
keys: [],
|
|
2828
|
+
activity,
|
|
2829
|
+
activityId: activityId.href,
|
|
2830
|
+
activityType,
|
|
2831
|
+
inbox: inbox.href,
|
|
2832
|
+
sharedInbox: false,
|
|
2833
|
+
started,
|
|
2834
|
+
attempt: 0,
|
|
2835
|
+
headers: {},
|
|
2836
|
+
traceContext
|
|
2837
|
+
};
|
|
2838
|
+
try {
|
|
2839
|
+
await outboxQueue.enqueue(message);
|
|
2840
|
+
} catch (error) {
|
|
2841
|
+
logger.error("Failed to enqueue activity {activityId} to forward to {inbox}; it will not be forwarded to the inbox again:\n{error}", {
|
|
2842
|
+
activityId: activityId.href,
|
|
2843
|
+
inbox: inbox.href,
|
|
2844
|
+
error
|
|
2845
|
+
});
|
|
2846
|
+
return;
|
|
2847
|
+
}
|
|
2848
|
+
recordOutboxEnqueue(meterProvider, outboxQueue, message);
|
|
2849
|
+
}));
|
|
2850
|
+
}
|
|
2851
|
+
//#endregion
|
|
2587
2852
|
//#region src/federation/outgoing-proof.ts
|
|
2588
2853
|
function isPortableUrl(url) {
|
|
2589
2854
|
return url.protocol === "ap:" || url.protocol === "ap+ef61:";
|
|
@@ -3304,6 +3569,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3304
3569
|
kvPrefixes;
|
|
3305
3570
|
publicKeyTtl;
|
|
3306
3571
|
httpMessageSignaturesSpecTtl;
|
|
3572
|
+
portableInboxForwarding;
|
|
3307
3573
|
inboxQueue;
|
|
3308
3574
|
outboxQueue;
|
|
3309
3575
|
fanoutQueue;
|
|
@@ -3336,6 +3602,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3336
3602
|
benchmarkMetricReader;
|
|
3337
3603
|
benchmarkTriggerOptions;
|
|
3338
3604
|
#mediaUploaderNoAuthWarned = false;
|
|
3605
|
+
#portableInboxForwardingWarned = false;
|
|
3339
3606
|
#queueDepthGaugeSourceId = `fedify-${(++nextQueueDepthGaugeSourceId).toString(36)}`;
|
|
3340
3607
|
#queueDepthGaugeEntries = [];
|
|
3341
3608
|
#queueDepthGaugeMeterProvider;
|
|
@@ -3367,10 +3634,12 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3367
3634
|
acceptSignatureNonce: ["_fedify", "acceptSignatureNonce"],
|
|
3368
3635
|
circuitBreaker: ["_fedify", "circuit"],
|
|
3369
3636
|
taskDeduplication: ["_fedify", "taskDeduplication"],
|
|
3637
|
+
portableInboxForwarding: ["_fedify", "portableInboxForwarding"],
|
|
3370
3638
|
...options.kvPrefixes ?? {}
|
|
3371
3639
|
};
|
|
3372
3640
|
this.publicKeyTtl = Temporal.Duration.from(options.publicKeyTtl ?? { days: 30 });
|
|
3373
3641
|
this.httpMessageSignaturesSpecTtl = Temporal.Duration.from(options.httpMessageSignaturesSpecTtl ?? { days: 90 });
|
|
3642
|
+
this.portableInboxForwarding = resolvePortableInboxForwardingOptions(options.portableInboxForwarding);
|
|
3374
3643
|
if (options.queue == null) {
|
|
3375
3644
|
this.inboxQueue = void 0;
|
|
3376
3645
|
this.outboxQueue = void 0;
|
|
@@ -4040,8 +4309,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4040
4309
|
]);
|
|
4041
4310
|
const baseUrl = new URL(message.baseUrl);
|
|
4042
4311
|
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) {
|
|
4312
|
+
if (message.identifier != null && this.actorCallbacks?.keyPairsDispatcher != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: await context.getDocumentLoader({ identifier: message.identifier }) });
|
|
4313
|
+
else if (message.identifier == null && this.sharedInboxKeyDispatcher != null) {
|
|
4045
4314
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
4046
4315
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
4047
4316
|
}
|
|
@@ -4634,6 +4903,15 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4634
4903
|
span,
|
|
4635
4904
|
metricState
|
|
4636
4905
|
});
|
|
4906
|
+
if (request.method === "POST") {
|
|
4907
|
+
const portable = parsePortableGatewayRequest(url);
|
|
4908
|
+
if (portable != null) return await this.#fetchPortableInbox(request, portable, {
|
|
4909
|
+
onNotFound,
|
|
4910
|
+
contextData,
|
|
4911
|
+
span,
|
|
4912
|
+
metricState
|
|
4913
|
+
});
|
|
4914
|
+
}
|
|
4637
4915
|
const portable = request.method === "GET" || request.method === "HEAD" ? parsePortableGatewayRequest(url) : null;
|
|
4638
4916
|
if (portable != null) return await discardBodyForHead(request, await this.#fetchPortableObject(request, portable, {
|
|
4639
4917
|
onNotFound,
|
|
@@ -4785,35 +5063,17 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4785
5063
|
onNotFound
|
|
4786
5064
|
});
|
|
4787
5065
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
|
|
4788
|
-
case "sharedInbox":
|
|
5066
|
+
case "sharedInbox":
|
|
4789
5067
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
4790
5068
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
4791
5069
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
4792
5070
|
}
|
|
4793
|
-
|
|
4794
|
-
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
4795
|
-
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
4796
|
-
return await handleInbox(request, {
|
|
5071
|
+
return await this.#handleInbox(request, {
|
|
4797
5072
|
recipient: route.values.identifier ?? null,
|
|
4798
5073
|
context,
|
|
4799
|
-
|
|
4800
|
-
|
|
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
|
|
5074
|
+
contextData,
|
|
5075
|
+
onNotFound
|
|
4815
5076
|
});
|
|
4816
|
-
}
|
|
4817
5077
|
case "following": return await handleCollection(request, {
|
|
4818
5078
|
name: "following",
|
|
4819
5079
|
identifier: route.values.identifier,
|
|
@@ -4966,6 +5226,113 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
4966
5226
|
onNotFound
|
|
4967
5227
|
});
|
|
4968
5228
|
}
|
|
5229
|
+
async #handleInbox(request, { recipient, context, contextData, onNotFound, portableInbox }) {
|
|
5230
|
+
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
5231
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
5232
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
5233
|
+
return await handleInbox(request, {
|
|
5234
|
+
recipient,
|
|
5235
|
+
context,
|
|
5236
|
+
inboxContextFactory,
|
|
5237
|
+
kv: this.kv,
|
|
5238
|
+
kvPrefixes: this.kvPrefixes,
|
|
5239
|
+
publicKeyTtl: this.publicKeyTtl,
|
|
5240
|
+
queue: this.inboxQueue,
|
|
5241
|
+
actorDispatcher: this.actorCallbacks?.dispatcher,
|
|
5242
|
+
inboxListeners: this.inboxListeners,
|
|
5243
|
+
inboxErrorHandler: this.inboxErrorHandler,
|
|
5244
|
+
unverifiedActivityHandler: this.unverifiedActivityHandler,
|
|
5245
|
+
onNotFound,
|
|
5246
|
+
signatureTimeWindow: this.signatureTimeWindow,
|
|
5247
|
+
skipSignatureVerification: this.skipSignatureVerification,
|
|
5248
|
+
inboxChallengePolicy: this.inboxChallengePolicy,
|
|
5249
|
+
meterProvider: this.meterProvider,
|
|
5250
|
+
tracerProvider: this.tracerProvider,
|
|
5251
|
+
idempotencyStrategy: this.idempotencyStrategy,
|
|
5252
|
+
portableInbox
|
|
5253
|
+
});
|
|
5254
|
+
}
|
|
5255
|
+
async #fetchPortableInbox(request, portable, { onNotFound, contextData, span, metricState }) {
|
|
5256
|
+
const logger = getLogger([
|
|
5257
|
+
"fedify",
|
|
5258
|
+
"federation",
|
|
5259
|
+
"inbox"
|
|
5260
|
+
]);
|
|
5261
|
+
if (portable.type === "malformed") {
|
|
5262
|
+
metricState.endpoint = "not_found";
|
|
5263
|
+
logger.debug("Malformed FEP-ef61 gateway inbox request {url}: {error}", {
|
|
5264
|
+
url: request.url,
|
|
5265
|
+
error: portable.error
|
|
5266
|
+
});
|
|
5267
|
+
return new Response("Malformed portable inbox ID.", {
|
|
5268
|
+
status: 400,
|
|
5269
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
5270
|
+
});
|
|
5271
|
+
}
|
|
5272
|
+
const route = this.router.route(portable.path);
|
|
5273
|
+
if (route == null || route.name !== "inbox") {
|
|
5274
|
+
metricState.endpoint = "not_found";
|
|
5275
|
+
return await onNotFound(request);
|
|
5276
|
+
}
|
|
5277
|
+
metricState.routeTemplate = PORTABLE_GATEWAY_ROUTE_PREFIX + route.template;
|
|
5278
|
+
metricState.endpoint = "inbox";
|
|
5279
|
+
span.updateName(`${request.method} ${metricState.routeTemplate}`);
|
|
5280
|
+
const identifier = route.values.identifier;
|
|
5281
|
+
let context = this.#createContext(request, contextData);
|
|
5282
|
+
const actor = this.actorCallbacks?.dispatcher == null ? null : await this.actorCallbacks.dispatcher(context, identifier);
|
|
5283
|
+
const localOrigin = context.canonicalOrigin;
|
|
5284
|
+
const resolution = resolvePortableInboxRecipient(actor == null || actor instanceof Tombstone ? null : actor, {
|
|
5285
|
+
authority: portable.portableRequest.authority,
|
|
5286
|
+
canonicalInboxId: portable.canonicalId,
|
|
5287
|
+
localOrigin
|
|
5288
|
+
});
|
|
5289
|
+
if (resolution.status === "rejected") {
|
|
5290
|
+
logger.debug("Not accepting a delivery to the portable inbox {inbox} on behalf of the actor {identifier}: {reason}.", {
|
|
5291
|
+
inbox: portable.canonicalId,
|
|
5292
|
+
identifier,
|
|
5293
|
+
reason: resolution.reason
|
|
5294
|
+
});
|
|
5295
|
+
return await onNotFound(request);
|
|
5296
|
+
}
|
|
5297
|
+
const { recipient } = resolution;
|
|
5298
|
+
if (this.actorCallbacks?.keyPairsDispatcher != null) context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier }) });
|
|
5299
|
+
const excludedOrigins = [localOrigin, new URL(request.url).origin];
|
|
5300
|
+
return await this.#handleInbox(request, {
|
|
5301
|
+
recipient: identifier,
|
|
5302
|
+
context,
|
|
5303
|
+
contextData,
|
|
5304
|
+
onNotFound,
|
|
5305
|
+
portableInbox: {
|
|
5306
|
+
recipient,
|
|
5307
|
+
forward: async (activity, activityId, activityType) => {
|
|
5308
|
+
if (this.portableInboxForwarding.maxTargets < 1) return;
|
|
5309
|
+
if (this.kv.cas == null) {
|
|
5310
|
+
if (!this.#portableInboxForwardingWarned) {
|
|
5311
|
+
this.#portableInboxForwardingWarned = true;
|
|
5312
|
+
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.");
|
|
5313
|
+
}
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5316
|
+
await forwardPortableInboxActivity({
|
|
5317
|
+
recipient,
|
|
5318
|
+
activity,
|
|
5319
|
+
activityId,
|
|
5320
|
+
activityType,
|
|
5321
|
+
excludedOrigins,
|
|
5322
|
+
baseUrl: context.origin,
|
|
5323
|
+
kv: this.kv,
|
|
5324
|
+
kvPrefix: this.kvPrefixes.portableInboxForwarding,
|
|
5325
|
+
outboxQueue: this.outboxQueue,
|
|
5326
|
+
startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
|
|
5327
|
+
allowPrivateAddress: this.allowPrivateAddress,
|
|
5328
|
+
options: this.portableInboxForwarding,
|
|
5329
|
+
meterProvider: this.meterProvider,
|
|
5330
|
+
tracerProvider: this.tracerProvider
|
|
5331
|
+
});
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
});
|
|
5335
|
+
}
|
|
4969
5336
|
async #fetchHashlinkMedia(request, media, { onNotFound, contextData, span, metricState }) {
|
|
4970
5337
|
metricState.endpoint = "hashlink_media";
|
|
4971
5338
|
metricState.routeTemplate = HASHLINK_MEDIA_ROUTE_TEMPLATE;
|
|
@@ -5196,6 +5563,12 @@ var ContextImpl = class ContextImpl {
|
|
|
5196
5563
|
if (path == null) throw new RouterError("No inbox path registered.");
|
|
5197
5564
|
return new URL(path, this.canonicalOrigin);
|
|
5198
5565
|
}
|
|
5566
|
+
getPortableInboxUri(identifier, authority) {
|
|
5567
|
+
const path = this.federation.router.build("inbox", { identifier });
|
|
5568
|
+
if (path == null) throw new RouterError("No inbox path registered.");
|
|
5569
|
+
if (authority == null) throw new TypeError("The authority of a portable ID is required outside an FEP-ef61 gateway request.");
|
|
5570
|
+
return buildPortableUri(authority, path);
|
|
5571
|
+
}
|
|
5199
5572
|
getFollowingUri(identifier) {
|
|
5200
5573
|
const path = this.federation.router.build("following", { identifier });
|
|
5201
5574
|
if (path == null) throw new RouterError("No following collection path registered.");
|
|
@@ -5798,6 +6171,9 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
5798
6171
|
getPortableObjectUri(cls, values, authority) {
|
|
5799
6172
|
return super.getPortableObjectUri(cls, values, authority ?? this.portableRequest?.authority);
|
|
5800
6173
|
}
|
|
6174
|
+
getPortableInboxUri(identifier, authority) {
|
|
6175
|
+
return super.getPortableInboxUri(identifier, authority ?? this.portableRequest?.authority);
|
|
6176
|
+
}
|
|
5801
6177
|
async getActor(identifier, options) {
|
|
5802
6178
|
if (this.federation.actorCallbacks == null || this.federation.actorCallbacks.dispatcher == null) throw new Error("No actor dispatcher registered.");
|
|
5803
6179
|
if (this.#invokedFromActorDispatcher != null) getLogger([
|
|
@@ -6188,4 +6564,4 @@ function getRequestId(request) {
|
|
|
6188
6564
|
return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
6189
6565
|
}
|
|
6190
6566
|
//#endregion
|
|
6191
|
-
export {
|
|
6567
|
+
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 };
|