@fedify/fedify 2.3.0-dev.1145 → 2.3.0-dev.1150
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-ShiR1K6b.mjs → builder-Bjm1Jq9n.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/{context-DI2gRbyN.d.cts → context-CRXCkTM6.d.cts} +48 -6
- package/dist/{context-DCtsSHDv.d.ts → context-MgCh7YGu.d.ts} +48 -6
- package/dist/{deno-h0TWFuEz.mjs → deno-CKFE6Uya.mjs} +1 -1
- package/dist/{docloader-BdDN0Aqx.mjs → docloader-B-ZE1cZf.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +1363 -44
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +1667 -163
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/send.test.mjs +8 -8
- package/dist/federation/temporal.test.d.mts +2 -0
- package/dist/federation/temporal.test.mjs +71 -0
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{getMachineId-bsd-etIyxDet.mjs → getMachineId-bsd-BY01PL1n.mjs} +1 -1
- package/dist/{getMachineId-darwin-D23zTf4g.mjs → getMachineId-darwin-Dr1gkBkp.mjs} +1 -1
- package/dist/{getMachineId-win-Dpap6v5i.mjs → getMachineId-win-QEYwcJiy.mjs} +1 -1
- package/dist/{http-7kAB7PVx.cjs → http-DQYEA7AZ.cjs} +1 -1
- package/dist/{http-B2hxA7dO.js → http-WbS1gKzr.js} +1 -1
- package/dist/{http-QzW9IWfs.mjs → http-vHCgbhTg.mjs} +3 -3
- package/dist/{key-Dh2OK1XQ.mjs → key-N0zP_oJA.mjs} +2 -2
- package/dist/{kv-cache-b22dNkjt.js → kv-cache-DM2O-Yjy.js} +1 -1
- package/dist/{kv-cache-DCPp-MT0.cjs → kv-cache-Dsg_bi4N.cjs} +1 -1
- package/dist/{kv-cache-EZRIPZXD.mjs → kv-cache-GXXZEemD.mjs} +1 -1
- package/dist/{ld-eZbar1rr.mjs → ld-BwKhquPx.mjs} +302 -6
- package/dist/{metrics-E0hAHtLZ.mjs → metrics-7Vy9FvEw.mjs} +1 -1
- package/dist/{middleware-BrGIM_Ra.js → middleware-BscgvU-m.js} +428 -99
- package/dist/{middleware-BUl1BH4x.cjs → middleware-D_iXrYHJ.cjs} +429 -99
- package/dist/{middleware-mToCR2tG.mjs → middleware-Db1_qAFG.mjs} +1 -1
- package/dist/{middleware-CyJDCmNg.mjs → middleware-ZuUcO0t1.mjs} +348 -108
- package/dist/{mod-CI9fduEi.d.cts → mod-C7HOzGqH.d.cts} +1 -1
- package/dist/{mod-CkRiJHGA.d.ts → mod-CpQHB3Ys.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +2 -2
- package/dist/mod.d.ts +2 -2
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-ByO_Fw6U.mjs → owner-FD0H_vpj.mjs} +2 -2
- package/dist/{proof-jVqClF49.cjs → proof-CYK8T8IS.cjs} +353 -3
- package/dist/{proof-BkRyFchv.js → proof-I3EokKN-.js} +300 -4
- package/dist/{proof-CSo0S8OK.mjs → proof-V_lafPmA.mjs} +3 -3
- package/dist/{send-jzrTV1FU.mjs → send-Cc2_10tF.mjs} +3 -3
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +558 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +1 -1
- package/dist/temporal-BkmBfs__.mjs +95 -0
- package/dist/testing/mod.d.mts +48 -6
- 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
- /package/dist/{execAsync-DCBrgFiV.mjs → execAsync-Dxb7rNf3.mjs} +0 -0
- /package/dist/{getMachineId-linux-ObI47Hql.mjs → getMachineId-linux-Bbhofx-s.mjs} +0 -0
- /package/dist/{getMachineId-unsupported-Ddu-PFeh.mjs → getMachineId-unsupported-dIOte2Ct.mjs} +0 -0
- /package/dist/{retry-v_sGLH1d.mjs → retry-_VvV0h9f.mjs} +0 -0
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { Temporal } from "@js-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, d as recordInboxActivity, h as recordWebFingerHandle, i as getRemoteHost, m as recordOutboxEnqueue, n as getDurationMs, o as isAbortError, p as recordOutboxActivity, r as getFederationMetrics, u as recordFanoutRecipients } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-CKFE6Uya.mjs";
|
|
5
|
+
import { a as instrumentDocumentLoader, d as recordInboxActivity, h as recordWebFingerHandle, i as getRemoteHost, m as recordOutboxEnqueue, n as getDurationMs, o as isAbortError, p as recordOutboxActivity, r as getFederationMetrics, u as recordFanoutRecipients } from "./metrics-7Vy9FvEw.mjs";
|
|
6
6
|
import { t as formatAcceptSignature } from "./accept-CceiKpCy.mjs";
|
|
7
|
-
import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-
|
|
8
|
-
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-
|
|
9
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
10
|
-
import { n as kvCache } from "./kv-cache-
|
|
11
|
-
import { a as
|
|
12
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
7
|
+
import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-N0zP_oJA.mjs";
|
|
8
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-vHCgbhTg.mjs";
|
|
9
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-B-ZE1cZf.mjs";
|
|
10
|
+
import { n as kvCache } from "./kv-cache-GXXZEemD.mjs";
|
|
11
|
+
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-BwKhquPx.mjs";
|
|
12
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-FD0H_vpj.mjs";
|
|
13
13
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-BgFLCJQ_.mjs";
|
|
14
|
-
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-
|
|
14
|
+
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-V_lafPmA.mjs";
|
|
15
15
|
import { t as getNodeInfo } from "./client-B_A6mfn3.mjs";
|
|
16
16
|
import { t as nodeInfoToJson } from "./types-BFowWFTT.mjs";
|
|
17
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
17
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-Bjm1Jq9n.mjs";
|
|
18
18
|
import { t as buildCollectionSynchronizationHeader } from "./collection-CA3V5zyK.mjs";
|
|
19
19
|
import { t as KvKeyCache } from "./keycache-BYMd8q7F.mjs";
|
|
20
20
|
import { t as acceptsJsonLd } from "./negotiation-CDW-_gUU.mjs";
|
|
21
|
-
import { t as
|
|
22
|
-
import {
|
|
21
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-BkmBfs__.mjs";
|
|
22
|
+
import { t as createExponentialBackoffPolicy } from "./retry-_VvV0h9f.mjs";
|
|
23
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-Cc2_10tF.mjs";
|
|
23
24
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
24
25
|
import { RouterError } from "@fedify/uri-template";
|
|
25
26
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
@@ -155,7 +156,7 @@ function handleNodeInfoJrd(_request, context) {
|
|
|
155
156
|
}
|
|
156
157
|
//#endregion
|
|
157
158
|
//#region src/federation/inbox.ts
|
|
158
|
-
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, meterProvider, tracerProvider, idempotencyStrategy }) {
|
|
159
|
+
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, meterProvider, tracerProvider, idempotencyStrategy }) {
|
|
159
160
|
const logger = getLogger([
|
|
160
161
|
"fedify",
|
|
161
162
|
"federation",
|
|
@@ -214,7 +215,9 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
214
215
|
type: "inbox",
|
|
215
216
|
id: crypto.randomUUID(),
|
|
216
217
|
baseUrl: ctx.origin,
|
|
217
|
-
activity: json,
|
|
218
|
+
activity: originalJson ?? json,
|
|
219
|
+
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
220
|
+
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
218
221
|
identifier: recipient,
|
|
219
222
|
attempt: 0,
|
|
220
223
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -268,7 +271,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
268
271
|
const activityType = getTypeId(activity).href;
|
|
269
272
|
const started = performance.now();
|
|
270
273
|
try {
|
|
271
|
-
|
|
274
|
+
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
275
|
+
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity.id?.href, activityType), activity);
|
|
272
276
|
} finally {
|
|
273
277
|
getFederationMetrics(meterProvider).recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
274
278
|
}
|
|
@@ -310,6 +314,33 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
310
314
|
}
|
|
311
315
|
//#endregion
|
|
312
316
|
//#region src/federation/handler.ts
|
|
317
|
+
const rawInboxContextFactorySymbol = Symbol("fedify.rawInboxContextFactory");
|
|
318
|
+
function isRemoteContextLoadingFailure$1(error) {
|
|
319
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
320
|
+
}
|
|
321
|
+
function isPermanentRemoteContextError$1(error) {
|
|
322
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
323
|
+
const details = error.details;
|
|
324
|
+
if (details?.code === "invalid remote context") return true;
|
|
325
|
+
return isRemoteContextLoadingFailure$1(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
|
|
326
|
+
}
|
|
327
|
+
function isInvalidJsonLdError(error) {
|
|
328
|
+
if (!(error instanceof Error)) return false;
|
|
329
|
+
const name = error.name;
|
|
330
|
+
return name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
|
|
331
|
+
}
|
|
332
|
+
function isValidationTypeError(error) {
|
|
333
|
+
return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || isInvalidUrlTypeError(error));
|
|
334
|
+
}
|
|
335
|
+
function isPermanentActivityParseError(error) {
|
|
336
|
+
return isInvalidJsonLdError(error) || isValidationTypeError(error);
|
|
337
|
+
}
|
|
338
|
+
function hasHttpSignatureHeaders(request) {
|
|
339
|
+
return request.headers.has("Signature") || request.headers.has("Signature-Input");
|
|
340
|
+
}
|
|
341
|
+
function hasObjectIntegrityProof(json) {
|
|
342
|
+
return typeof json === "object" && json != null && "proof" in json;
|
|
343
|
+
}
|
|
313
344
|
/**
|
|
314
345
|
* Handles an actor request.
|
|
315
346
|
* @template TContextData The context data to pass to the context.
|
|
@@ -381,8 +412,8 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
381
412
|
* @param parameters The parameters for handling the collection.
|
|
382
413
|
* @returns A promise that resolves to an HTTP response.
|
|
383
414
|
*/
|
|
384
|
-
async function handleCollection(request, { name: name$
|
|
385
|
-
const spanName = name$
|
|
415
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound }) {
|
|
416
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
386
417
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
387
418
|
const tracer = tracerProvider.getTracer(name, version);
|
|
388
419
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
@@ -424,7 +455,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
424
455
|
collection = new OrderedCollection({
|
|
425
456
|
id: baseUri,
|
|
426
457
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
427
|
-
items: filterCollectionItems(itemsOrResponse, name$
|
|
458
|
+
items: filterCollectionItems(itemsOrResponse, name$1, filterPredicate)
|
|
428
459
|
});
|
|
429
460
|
} else {
|
|
430
461
|
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
@@ -445,7 +476,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
445
476
|
} else {
|
|
446
477
|
const uri = new URL(baseUri);
|
|
447
478
|
uri.searchParams.set("cursor", cursor);
|
|
448
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
479
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
449
480
|
kind: SpanKind.SERVER,
|
|
450
481
|
attributes: {
|
|
451
482
|
"activitypub.collection.id": uri.href,
|
|
@@ -489,7 +520,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
489
520
|
id: uri,
|
|
490
521
|
prev,
|
|
491
522
|
next,
|
|
492
|
-
items: filterCollectionItems(items, name$
|
|
523
|
+
items: filterCollectionItems(items, name$1, filterPredicate),
|
|
493
524
|
partOf
|
|
494
525
|
});
|
|
495
526
|
}
|
|
@@ -836,29 +867,105 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
836
867
|
});
|
|
837
868
|
}
|
|
838
869
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
870
|
+
const jsonWithoutSig = detachSignature(json);
|
|
871
|
+
const hasLdSignature = hasSignature(json);
|
|
872
|
+
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
873
|
+
let deferredLdSignatureError = void 0;
|
|
874
|
+
const respondInvalidActivity = async (error) => {
|
|
875
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
876
|
+
recipient,
|
|
877
|
+
activity: json,
|
|
878
|
+
error
|
|
847
879
|
});
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
880
|
+
try {
|
|
881
|
+
await inboxErrorHandler?.(ctx, error);
|
|
882
|
+
} catch (error) {
|
|
883
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
884
|
+
error,
|
|
885
|
+
activity: json,
|
|
886
|
+
recipient
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
span.setStatus({
|
|
890
|
+
code: SpanStatusCode.ERROR,
|
|
891
|
+
message: `Failed to parse activity:\n${error}`
|
|
892
|
+
});
|
|
893
|
+
return new Response("Invalid activity.", {
|
|
894
|
+
status: 400,
|
|
895
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
896
|
+
});
|
|
897
|
+
};
|
|
898
|
+
let compactedJson = json;
|
|
899
|
+
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
900
|
+
let ldSigVerified = false;
|
|
901
|
+
if (hasLdSignature) {
|
|
902
|
+
try {
|
|
903
|
+
compactedJson = await compactJsonLd(json, ctx.contextLoader);
|
|
904
|
+
} catch (error) {
|
|
905
|
+
if (isInvalidJsonLdError(error)) {
|
|
906
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
907
|
+
recipient,
|
|
908
|
+
error
|
|
909
|
+
});
|
|
910
|
+
return new Response("Invalid JSON-LD.", {
|
|
911
|
+
status: 400,
|
|
912
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
916
|
+
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
917
|
+
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
851
918
|
recipient,
|
|
852
919
|
error
|
|
853
920
|
});
|
|
854
|
-
return new Response("Invalid JSON-LD.", {
|
|
855
|
-
status: 400,
|
|
856
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
857
|
-
});
|
|
858
921
|
}
|
|
859
|
-
|
|
922
|
+
if (compactedJson !== json) {
|
|
923
|
+
compactedJsonWithoutSig = detachSignature(compactedJson);
|
|
924
|
+
try {
|
|
925
|
+
ldSigVerified = await verifyCompactJsonLd(compactedJson, {
|
|
926
|
+
contextLoader: ctx.contextLoader,
|
|
927
|
+
documentLoader: ctx.documentLoader,
|
|
928
|
+
keyCache,
|
|
929
|
+
meterProvider,
|
|
930
|
+
tracerProvider
|
|
931
|
+
});
|
|
932
|
+
} catch (error) {
|
|
933
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
934
|
+
if (isInvalidJsonLdError(error)) {
|
|
935
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
936
|
+
recipient,
|
|
937
|
+
error
|
|
938
|
+
});
|
|
939
|
+
return new Response("Invalid JSON-LD.", {
|
|
940
|
+
status: 400,
|
|
941
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
945
|
+
if (!skipSignatureVerification) try {
|
|
946
|
+
await Object$1.fromJsonLd(compactedJson, {
|
|
947
|
+
contextLoader: getNormalizationContextLoader(ctx.contextLoader),
|
|
948
|
+
documentLoader: ctx.documentLoader,
|
|
949
|
+
tracerProvider
|
|
950
|
+
});
|
|
951
|
+
} catch (parseError) {
|
|
952
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(parseError);
|
|
953
|
+
if (isInvalidJsonLdError(parseError)) {
|
|
954
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
955
|
+
recipient,
|
|
956
|
+
error: parseError
|
|
957
|
+
});
|
|
958
|
+
return new Response("Invalid JSON-LD.", {
|
|
959
|
+
status: 400,
|
|
960
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
deferredLdSignatureError = parseError;
|
|
964
|
+
}
|
|
965
|
+
ldSigVerified = false;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
860
968
|
}
|
|
861
|
-
const jsonWithoutSig = detachSignature(json);
|
|
862
969
|
let activity = null;
|
|
863
970
|
let activityVerified = false;
|
|
864
971
|
if (ldSigVerified) {
|
|
@@ -866,7 +973,16 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
866
973
|
recipient,
|
|
867
974
|
json
|
|
868
975
|
});
|
|
869
|
-
|
|
976
|
+
try {
|
|
977
|
+
activity = await Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
978
|
+
...ctx,
|
|
979
|
+
contextLoader: getNormalizationContextLoader(ctx.contextLoader)
|
|
980
|
+
});
|
|
981
|
+
} catch (error) {
|
|
982
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
983
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
984
|
+
return await respondInvalidActivity(error);
|
|
985
|
+
}
|
|
870
986
|
activityVerified = true;
|
|
871
987
|
} else {
|
|
872
988
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
@@ -875,13 +991,22 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
875
991
|
});
|
|
876
992
|
try {
|
|
877
993
|
activity = await verifyObject(Activity, jsonWithoutSig, {
|
|
878
|
-
contextLoader: ctx.contextLoader,
|
|
994
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
879
995
|
documentLoader: ctx.documentLoader,
|
|
880
996
|
keyCache,
|
|
881
997
|
meterProvider,
|
|
882
998
|
tracerProvider
|
|
883
999
|
});
|
|
884
1000
|
} catch (error) {
|
|
1001
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1002
|
+
if (deferredLdSignatureError != null) {
|
|
1003
|
+
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
1004
|
+
recipient,
|
|
1005
|
+
error
|
|
1006
|
+
});
|
|
1007
|
+
activity = null;
|
|
1008
|
+
}
|
|
1009
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
885
1010
|
logger.error("Failed to parse activity:\n{error}", {
|
|
886
1011
|
recipient,
|
|
887
1012
|
activity: json,
|
|
@@ -930,6 +1055,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
930
1055
|
tracerProvider
|
|
931
1056
|
});
|
|
932
1057
|
if (verification.verified === false) {
|
|
1058
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
933
1059
|
const reason = verification.reason;
|
|
934
1060
|
const remoteHost = "keyId" in reason && reason.keyId != null ? getRemoteHost(reason.keyId) : void 0;
|
|
935
1061
|
getFederationMetrics(parameters.meterProvider).recordSignatureVerificationFailure(reason.type, remoteHost);
|
|
@@ -1007,7 +1133,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1007
1133
|
}
|
|
1008
1134
|
httpSigKey = verification.key;
|
|
1009
1135
|
}
|
|
1010
|
-
|
|
1136
|
+
try {
|
|
1137
|
+
activity = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
1138
|
+
...ctx,
|
|
1139
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1140
|
+
});
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1143
|
+
return await respondInvalidActivity(error);
|
|
1144
|
+
}
|
|
1011
1145
|
}
|
|
1012
1146
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1013
1147
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
@@ -1019,6 +1153,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1019
1153
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1020
1154
|
});
|
|
1021
1155
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1156
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1022
1157
|
getFederationMetrics(parameters.meterProvider).recordSignatureVerificationFailure("actorKeyMismatch", httpSigKey.id == null ? void 0 : getRemoteHost(httpSigKey.id));
|
|
1023
1158
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1024
1159
|
activity: json,
|
|
@@ -1045,10 +1180,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1045
1180
|
const routeResult = await routeActivity({
|
|
1046
1181
|
context: ctx,
|
|
1047
1182
|
json,
|
|
1183
|
+
originalJson: json,
|
|
1184
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
1185
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1048
1186
|
activity,
|
|
1049
1187
|
recipient,
|
|
1050
1188
|
inboxListeners,
|
|
1051
1189
|
inboxContextFactory,
|
|
1190
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1052
1191
|
inboxErrorHandler,
|
|
1053
1192
|
kv,
|
|
1054
1193
|
kvPrefixes,
|
|
@@ -1175,8 +1314,8 @@ var CustomCollectionHandler = class {
|
|
|
1175
1314
|
* @param CollectionPage The CollectionPage constructor.
|
|
1176
1315
|
* @param filterPredicate Optional filter predicate for items.
|
|
1177
1316
|
*/
|
|
1178
|
-
constructor(name$
|
|
1179
|
-
this.name = name$
|
|
1317
|
+
constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1318
|
+
this.name = name$2;
|
|
1180
1319
|
this.values = values;
|
|
1181
1320
|
this.context = context;
|
|
1182
1321
|
this.callbacks = callbacks;
|
|
@@ -1773,6 +1912,18 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
1773
1912
|
}
|
|
1774
1913
|
//#endregion
|
|
1775
1914
|
//#region src/federation/middleware.ts
|
|
1915
|
+
function isRemoteContextLoadingFailure(error) {
|
|
1916
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
1917
|
+
}
|
|
1918
|
+
function isPermanentRemoteContextError(error) {
|
|
1919
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
1920
|
+
const details = error.details;
|
|
1921
|
+
if (details?.code === "invalid remote context") return true;
|
|
1922
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
|
|
1923
|
+
}
|
|
1924
|
+
function isPermanentInboxParseError(error) {
|
|
1925
|
+
return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || isInvalidUrlTypeError(error));
|
|
1926
|
+
}
|
|
1776
1927
|
/**
|
|
1777
1928
|
* Create a new {@link Federation} instance.
|
|
1778
1929
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2275,78 +2426,37 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2275
2426
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2276
2427
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2277
2428
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
const cacheKey = activity.id == null ? null : [
|
|
2284
|
-
...this.kvPrefixes.activityIdempotence,
|
|
2285
|
-
context.origin,
|
|
2286
|
-
activity.id.href
|
|
2287
|
-
];
|
|
2288
|
-
if (cacheKey != null) {
|
|
2289
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
2290
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
2291
|
-
activityId: activity.id?.href,
|
|
2292
|
-
activity: message.activity,
|
|
2293
|
-
recipient: message.identifier
|
|
2294
|
-
});
|
|
2295
|
-
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
2296
|
-
return;
|
|
2297
|
-
}
|
|
2298
|
-
}
|
|
2299
|
-
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
|
|
2300
|
-
const dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
2301
|
-
if (dispatched == null) {
|
|
2302
|
-
logger.error("Unsupported activity type:\n{activity}", {
|
|
2303
|
-
activityId: activity.id?.href,
|
|
2304
|
-
activity: message.activity,
|
|
2305
|
-
recipient: message.identifier,
|
|
2306
|
-
trial: message.attempt
|
|
2307
|
-
});
|
|
2308
|
-
span.setStatus({
|
|
2309
|
-
code: SpanStatusCode.ERROR,
|
|
2310
|
-
message: `Unsupported activity type: ${activityType}`
|
|
2311
|
-
});
|
|
2312
|
-
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
2313
|
-
span.end();
|
|
2314
|
-
return;
|
|
2315
|
-
}
|
|
2316
|
-
const { class: cls, listener } = dispatched;
|
|
2317
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2318
|
-
try {
|
|
2319
|
-
const started = performance.now();
|
|
2320
|
-
try {
|
|
2321
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, activityType), activity);
|
|
2322
|
-
} finally {
|
|
2323
|
-
getFederationMetrics(this.meterProvider).recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
2324
|
-
}
|
|
2325
|
-
recordInboxActivity(this.meterProvider, "processed", activityType);
|
|
2326
|
-
} catch (error) {
|
|
2429
|
+
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (listenerSpan) => {
|
|
2430
|
+
let activity = null;
|
|
2431
|
+
let cacheKey = null;
|
|
2432
|
+
let activityType;
|
|
2433
|
+
const reportInboxError = async (error) => {
|
|
2327
2434
|
try {
|
|
2328
2435
|
await this.inboxErrorHandler?.(context, error);
|
|
2329
2436
|
} catch (error) {
|
|
2330
2437
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2331
2438
|
error,
|
|
2332
2439
|
trial: message.attempt,
|
|
2333
|
-
activityId: activity
|
|
2440
|
+
activityId: activity?.id?.href,
|
|
2334
2441
|
activity: message.activity,
|
|
2335
2442
|
recipient: message.identifier
|
|
2336
2443
|
});
|
|
2337
2444
|
}
|
|
2445
|
+
};
|
|
2446
|
+
const handleRetriableFailure = async (error) => {
|
|
2447
|
+
await reportInboxError(error);
|
|
2338
2448
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2339
2449
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2340
2450
|
error,
|
|
2341
|
-
activityId: activity
|
|
2451
|
+
activityId: activity?.id?.href,
|
|
2342
2452
|
activity: message.activity,
|
|
2343
2453
|
recipient: message.identifier
|
|
2344
2454
|
});
|
|
2345
|
-
|
|
2455
|
+
listenerSpan.setStatus({
|
|
2346
2456
|
code: SpanStatusCode.ERROR,
|
|
2347
2457
|
message: String(error)
|
|
2348
2458
|
});
|
|
2349
|
-
|
|
2459
|
+
listenerSpan.end();
|
|
2350
2460
|
throw error;
|
|
2351
2461
|
}
|
|
2352
2462
|
const delay = this.inboxRetryPolicy({
|
|
@@ -2357,20 +2467,27 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2357
2467
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2358
2468
|
error,
|
|
2359
2469
|
attempt: message.attempt,
|
|
2360
|
-
activityId: activity
|
|
2470
|
+
activityId: activity?.id?.href,
|
|
2361
2471
|
activity: message.activity,
|
|
2362
2472
|
recipient: message.identifier
|
|
2363
2473
|
});
|
|
2474
|
+
if (this.inboxQueue == null) {
|
|
2475
|
+
listenerSpan.setStatus({
|
|
2476
|
+
code: SpanStatusCode.ERROR,
|
|
2477
|
+
message: String(error)
|
|
2478
|
+
});
|
|
2479
|
+
listenerSpan.end();
|
|
2480
|
+
throw error;
|
|
2481
|
+
}
|
|
2364
2482
|
const retryMessage = {
|
|
2365
2483
|
...message,
|
|
2366
2484
|
attempt: message.attempt + 1
|
|
2367
2485
|
};
|
|
2368
|
-
|
|
2369
|
-
if (
|
|
2370
|
-
await inboxQueue.enqueue(retryMessage, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2486
|
+
await this.inboxQueue.enqueue(retryMessage, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2487
|
+
if (activityType != null) {
|
|
2371
2488
|
getFederationMetrics(this.meterProvider).recordQueueTaskEnqueued({
|
|
2372
2489
|
role: "inbox",
|
|
2373
|
-
queue: inboxQueue,
|
|
2490
|
+
queue: this.inboxQueue,
|
|
2374
2491
|
activityType
|
|
2375
2492
|
}, retryMessage.attempt);
|
|
2376
2493
|
recordInboxActivity(this.meterProvider, "retried", activityType);
|
|
@@ -2378,26 +2495,137 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2378
2495
|
} else {
|
|
2379
2496
|
logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2380
2497
|
error,
|
|
2381
|
-
activityId: activity
|
|
2498
|
+
activityId: activity?.id?.href,
|
|
2382
2499
|
activity: message.activity,
|
|
2383
2500
|
recipient: message.identifier
|
|
2384
2501
|
});
|
|
2385
|
-
recordInboxActivity(this.meterProvider, "abandoned", activityType);
|
|
2502
|
+
if (activityType != null) recordInboxActivity(this.meterProvider, "abandoned", activityType);
|
|
2386
2503
|
}
|
|
2387
|
-
|
|
2504
|
+
listenerSpan.setStatus({
|
|
2388
2505
|
code: SpanStatusCode.ERROR,
|
|
2389
2506
|
message: String(error)
|
|
2390
2507
|
});
|
|
2391
|
-
|
|
2508
|
+
listenerSpan.end();
|
|
2509
|
+
};
|
|
2510
|
+
let dispatched;
|
|
2511
|
+
let parseInput = void 0;
|
|
2512
|
+
let parseContextLoader = context.contextLoader;
|
|
2513
|
+
try {
|
|
2514
|
+
const hasSignatureField = hasSignature(message.activity);
|
|
2515
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
2516
|
+
const parseContext = hasSignatureField ? {
|
|
2517
|
+
...context,
|
|
2518
|
+
contextLoader: getNormalizationContextLoader(context.contextLoader)
|
|
2519
|
+
} : {
|
|
2520
|
+
...context,
|
|
2521
|
+
contextLoader: wrapContextLoaderForJsonLd(context.contextLoader)
|
|
2522
|
+
};
|
|
2523
|
+
parseContextLoader = parseContext.contextLoader;
|
|
2524
|
+
let normalizedActivity;
|
|
2525
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
2526
|
+
normalizedActivity = message.normalizedActivity ?? await compactJsonLd(message.activity, context.contextLoader);
|
|
2527
|
+
assertSafeJsonLd(normalizedActivity);
|
|
2528
|
+
}
|
|
2529
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? detachSignature(normalizedActivity) : hasSignatureField ? detachSignature(message.activity) : message.activity;
|
|
2530
|
+
activity = await Activity.fromJsonLd(parseInput, parseContext);
|
|
2531
|
+
activityType = getTypeId(activity).href;
|
|
2532
|
+
span.setAttribute("activitypub.activity.type", activityType);
|
|
2533
|
+
listenerSpan.setAttribute("activitypub.activity.type", activityType);
|
|
2534
|
+
onActivityType?.(activityType);
|
|
2535
|
+
if (activity.id != null) {
|
|
2536
|
+
span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2537
|
+
listenerSpan.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2538
|
+
}
|
|
2539
|
+
cacheKey = activity.id == null ? null : [
|
|
2540
|
+
...this.kvPrefixes.activityIdempotence,
|
|
2541
|
+
context.origin,
|
|
2542
|
+
activity.id.href
|
|
2543
|
+
];
|
|
2544
|
+
if (cacheKey != null) {
|
|
2545
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
2546
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
2547
|
+
activityId: activity.id?.href,
|
|
2548
|
+
activity: message.activity,
|
|
2549
|
+
recipient: message.identifier
|
|
2550
|
+
});
|
|
2551
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
2552
|
+
listenerSpan.end();
|
|
2553
|
+
return;
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
2557
|
+
} catch (error) {
|
|
2558
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
2559
|
+
await reportInboxError(error);
|
|
2560
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
2561
|
+
error,
|
|
2562
|
+
trial: message.attempt,
|
|
2563
|
+
activityId: null,
|
|
2564
|
+
activity: message.activity,
|
|
2565
|
+
recipient: message.identifier
|
|
2566
|
+
});
|
|
2567
|
+
listenerSpan.setStatus({
|
|
2568
|
+
code: SpanStatusCode.ERROR,
|
|
2569
|
+
message: String(error)
|
|
2570
|
+
});
|
|
2571
|
+
listenerSpan.end();
|
|
2572
|
+
return;
|
|
2573
|
+
}
|
|
2574
|
+
if (isPermanentInboxParseError(error)) {
|
|
2575
|
+
await reportInboxError(error);
|
|
2576
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
2577
|
+
error,
|
|
2578
|
+
trial: message.attempt,
|
|
2579
|
+
activityId: activity?.id?.href,
|
|
2580
|
+
activity: message.activity,
|
|
2581
|
+
recipient: message.identifier
|
|
2582
|
+
});
|
|
2583
|
+
listenerSpan.setStatus({
|
|
2584
|
+
code: SpanStatusCode.ERROR,
|
|
2585
|
+
message: String(error)
|
|
2586
|
+
});
|
|
2587
|
+
listenerSpan.end();
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
await handleRetriableFailure(error);
|
|
2591
|
+
return;
|
|
2592
|
+
}
|
|
2593
|
+
if (dispatched == null) {
|
|
2594
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
2595
|
+
activityId: activity.id?.href,
|
|
2596
|
+
activity: message.activity,
|
|
2597
|
+
recipient: message.identifier,
|
|
2598
|
+
trial: message.attempt
|
|
2599
|
+
});
|
|
2600
|
+
listenerSpan.setStatus({
|
|
2601
|
+
code: SpanStatusCode.ERROR,
|
|
2602
|
+
message: `Unsupported activity type: ${activityType}`
|
|
2603
|
+
});
|
|
2604
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
2605
|
+
listenerSpan.end();
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2608
|
+
const { class: cls, listener } = dispatched;
|
|
2609
|
+
listenerSpan.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2610
|
+
try {
|
|
2611
|
+
const started = performance.now();
|
|
2612
|
+
try {
|
|
2613
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, activityType), activity);
|
|
2614
|
+
} finally {
|
|
2615
|
+
getFederationMetrics(this.meterProvider).recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
2616
|
+
}
|
|
2617
|
+
recordInboxActivity(this.meterProvider, "processed", activityType);
|
|
2618
|
+
} catch (error) {
|
|
2619
|
+
await handleRetriableFailure(error);
|
|
2392
2620
|
return;
|
|
2393
2621
|
}
|
|
2394
2622
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2395
2623
|
logger.info("Activity {activityId} has been processed.", {
|
|
2396
|
-
activityId: activity
|
|
2624
|
+
activityId: activity?.id?.href,
|
|
2397
2625
|
activity: message.activity,
|
|
2398
2626
|
recipient: message.identifier
|
|
2399
2627
|
});
|
|
2400
|
-
|
|
2628
|
+
listenerSpan.end();
|
|
2401
2629
|
});
|
|
2402
2630
|
}
|
|
2403
2631
|
startQueue(contextData, options = {}) {
|
|
@@ -2778,16 +3006,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2778
3006
|
onNotFound
|
|
2779
3007
|
});
|
|
2780
3008
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
|
|
2781
|
-
case "sharedInbox":
|
|
3009
|
+
case "sharedInbox": {
|
|
2782
3010
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
2783
3011
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2784
3012
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2785
3013
|
}
|
|
2786
3014
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3015
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3016
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
2787
3017
|
return await handleInbox(request, {
|
|
2788
3018
|
recipient: route.values.identifier ?? null,
|
|
2789
3019
|
context,
|
|
2790
|
-
inboxContextFactory
|
|
3020
|
+
inboxContextFactory,
|
|
2791
3021
|
kv: this.kv,
|
|
2792
3022
|
kvPrefixes: this.kvPrefixes,
|
|
2793
3023
|
queue: this.inboxQueue,
|
|
@@ -2803,6 +3033,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2803
3033
|
tracerProvider: this.tracerProvider,
|
|
2804
3034
|
idempotencyStrategy: this.idempotencyStrategy
|
|
2805
3035
|
});
|
|
3036
|
+
}
|
|
2806
3037
|
case "following": return await handleCollection(request, {
|
|
2807
3038
|
name: "following",
|
|
2808
3039
|
identifier: route.values.identifier,
|
|
@@ -3536,6 +3767,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3536
3767
|
const routeResult = await routeActivity({
|
|
3537
3768
|
context: this,
|
|
3538
3769
|
json,
|
|
3770
|
+
ldSignatureVerified: false,
|
|
3539
3771
|
activity,
|
|
3540
3772
|
recipient,
|
|
3541
3773
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -3824,6 +4056,14 @@ async function forwardActivityInternal(ctx, loggerCategory, forwarder, recipient
|
|
|
3824
4056
|
}
|
|
3825
4057
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
3826
4058
|
recipient;
|
|
4059
|
+
/**
|
|
4060
|
+
* The original received activity payload.
|
|
4061
|
+
*
|
|
4062
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4063
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4064
|
+
* third-party signatures/proofs remain intact.
|
|
4065
|
+
* @internal
|
|
4066
|
+
*/
|
|
3827
4067
|
activity;
|
|
3828
4068
|
activityId;
|
|
3829
4069
|
activityType;
|