@fedify/fedify 2.1.12 → 2.1.14
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-D9hlyCx5.mjs → builder-BBifZZ5G.mjs} +3 -3
- package/dist/{chunk-nlSIicah.js → chunk-CRNNMoPX.js} +2 -2
- package/dist/{client-z-8dc-e1.d.cts → client-CAM_bQXx.d.cts} +1 -0
- package/dist/{client-AtlibPOU.d.ts → client-CSddvgWN.d.ts} +1 -2
- package/dist/compat/mod.d.cts +2 -1
- package/dist/compat/mod.d.ts +2 -3
- package/dist/compat/mod.js +3 -3
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{context-C0fssarc.d.ts → context-_l9t359k.d.ts} +53 -12
- package/dist/{context-LmrZPwti.d.cts → context-o22vjzS2.d.cts} +53 -10
- package/dist/{deno-Ddb3P7G7.mjs → deno-bqnW1QlD.mjs} +1 -1
- package/dist/{docloader-CK8tewt1.mjs → docloader-D-Fu0kBF.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +1361 -41
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +1588 -84
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +4 -3
- package/dist/federation/mod.d.ts +4 -5
- package/dist/federation/mod.js +2 -2
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/send.test.mjs +3 -3
- 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/{http-CrGuipxe.d.cts → http-BDZeS5om.d.ts} +2 -1
- package/dist/{http-aQzN9Ayi.d.ts → http-C87EWkO0.d.cts} +2 -3
- package/dist/{http-CmDErAnD.cjs → http-CEXtUHix.cjs} +57 -9
- package/dist/{http-qKyJKSnF.js → http-Cw1EorUA.js} +58 -10
- package/dist/{http-DRDpStn2.mjs → http-DvhFwy2E.mjs} +58 -10
- package/dist/{inbox-DTuPJEma.mjs → inbox-7b3VYnec.mjs} +7 -4
- package/dist/{key-WSedbAA-.mjs → key-B3OBz6A_.mjs} +1 -1
- package/dist/{kv-CbLNp3zQ.d.cts → kv-D6hNiMTK.d.ts} +1 -0
- package/dist/{kv-cache-9cdQDeT0.cjs → kv-cache-BIapFiSV.cjs} +2 -2
- package/dist/{kv-cache-DNNRFY8u.js → kv-cache-C6nynGhh.js} +2 -2
- package/dist/{kv-cache-B01V7s3h.mjs → kv-cache-FsT1ljhs.mjs} +1 -1
- package/dist/{kv-GFYnFoOl.d.ts → kv-gJ8LYbxX.d.cts} +1 -3
- package/dist/ld-DTxYKZTT.mjs +550 -0
- package/dist/{middleware-UThUK30x.js → middleware-0vceVN10.js} +407 -82
- package/dist/{middleware-DFcgN1cH.cjs → middleware-BcbU5lKS.cjs} +406 -80
- package/dist/{middleware-8P6Z15Wq.cjs → middleware-DUT--Qen.cjs} +1 -1
- package/dist/{middleware-DDsnRvFC.mjs → middleware-DmT9t0BJ.mjs} +317 -84
- package/dist/{middleware-C2c1rlmE.mjs → middleware-Li_g_vqz.mjs} +1 -1
- package/dist/{mod-CnwZoDzx.d.ts → mod-0dF0OeGw.d.cts} +2 -3
- package/dist/{mod-B505FZBC.d.cts → mod-BTWFtZwa.d.ts} +4 -3
- package/dist/{mod-Cgpc49fA.d.cts → mod-Bv1elC-b.d.ts} +2 -1
- package/dist/{mod-DoJBjjnO.d.cts → mod-CjiK2zrW.d.ts} +3 -2
- package/dist/{mod-DvxszxXC.d.ts → mod-D5YlzzP3.d.cts} +3 -4
- package/dist/{mod-D7PAuO6k.d.ts → mod-dxOnKp2Y.d.cts} +4 -5
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +9 -8
- package/dist/mod.d.ts +9 -10
- package/dist/mod.js +9 -9
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/nodeinfo/mod.d.cts +2 -1
- package/dist/nodeinfo/mod.d.ts +2 -3
- package/dist/nodeinfo/mod.js +3 -3
- package/dist/otel/mod.d.cts +2 -1
- package/dist/otel/mod.d.ts +2 -3
- package/dist/otel/mod.js +2 -2
- package/dist/{owner-CptqhsOy.d.cts → owner-CnngXDNJ.d.ts} +2 -1
- package/dist/{owner-74ARJ5TL.d.ts → owner-DEvZuyOE.d.cts} +2 -3
- package/dist/{owner-BceqCVOs.mjs → owner-DzcnuWYo.mjs} +2 -2
- package/dist/{proof-4NUQlbQV.js → proof-CtTT8A7y.js} +299 -5
- package/dist/{proof-BojC8L94.mjs → proof-DmVGi7mI.mjs} +2 -2
- package/dist/{proof-kuTIVfyZ.cjs → proof-JEoW3ODq.cjs} +345 -3
- package/dist/runtime/mod.d.cts +1 -0
- package/dist/runtime/mod.d.ts +1 -2
- package/dist/runtime/mod.js +3 -3
- package/dist/{send-Buz5Gy8x.mjs → send-5ulOKVCW.mjs} +2 -2
- package/dist/sig/http.test.mjs +120 -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.d.cts +4 -3
- package/dist/sig/mod.d.ts +4 -5
- package/dist/sig/mod.js +4 -4
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +1 -1
- package/dist/temporal-CmJkd-25.mjs +95 -0
- package/dist/testing/mod.d.mts +48 -6
- package/dist/{transformers-ve6e2xcg.js → transformers-BGMIq1cs.js} +2 -2
- package/dist/{types-hvL8ElAs.js → types-CAY3OdLq.js} +2 -2
- 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.d.cts +2 -1
- package/dist/utils/mod.d.ts +2 -3
- package/dist/utils/mod.js +3 -3
- package/dist/vocab/mod.d.cts +1 -0
- package/dist/vocab/mod.d.ts +1 -2
- package/dist/vocab/mod.js +2 -2
- package/package.json +7 -7
- package/dist/ld-OBpaLfHR.mjs +0 -256
- /package/dist/{retry-B_E3V_Dx.mjs → retry-CJL0poaU.mjs} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
-
import "urlpattern-polyfill";
|
|
3
|
-
import { t as __exportAll } from "./chunk-
|
|
4
|
-
import { r as getDefaultActivityTransformers } from "./transformers-
|
|
5
|
-
import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-
|
|
6
|
-
import { a as doesActorOwnKey,
|
|
7
|
-
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
2
|
+
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
+
import { t as __exportAll } from "./chunk-CRNNMoPX.js";
|
|
4
|
+
import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
|
|
5
|
+
import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-Cw1EorUA.js";
|
|
6
|
+
import { _ as signJsonLd, a as doesActorOwnKey, c as assertSafeJsonLd, f as detachSignature, g as isInvalidUrlTypeError, h as isClearlyMalformedContextReference, m as hasSignature, n as signObject, o as getKeyOwner, p as getNormalizationContextLoader, r as verifyObject, s as InvalidContextReferenceError, u as compactJsonLd, v as verifyCompactJsonLd, x as wrapContextLoaderForJsonLd } from "./proof-CtTT8A7y.js";
|
|
7
|
+
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-CAY3OdLq.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-C6nynGhh.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
10
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
11
11
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
@@ -15,6 +15,7 @@ import { parseTemplate } from "url-template";
|
|
|
15
15
|
import { encodeHex } from "byte-encodings/hex";
|
|
16
16
|
import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
17
17
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
18
|
+
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
18
19
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
19
20
|
import { domainToASCII } from "node:url";
|
|
20
21
|
//#region src/federation/inbox.ts
|
|
@@ -51,7 +52,7 @@ var InboxListenerSet = class InboxListenerSet {
|
|
|
51
52
|
return this.dispatchWithClass(activity)?.listener ?? null;
|
|
52
53
|
}
|
|
53
54
|
};
|
|
54
|
-
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
55
|
+
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
55
56
|
const logger = getLogger([
|
|
56
57
|
"fedify",
|
|
57
58
|
"federation",
|
|
@@ -108,7 +109,9 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
108
109
|
type: "inbox",
|
|
109
110
|
id: crypto.randomUUID(),
|
|
110
111
|
baseUrl: ctx.origin,
|
|
111
|
-
activity: json,
|
|
112
|
+
activity: originalJson ?? json,
|
|
113
|
+
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
114
|
+
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
112
115
|
identifier: recipient,
|
|
113
116
|
attempt: 0,
|
|
114
117
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -152,7 +155,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
152
155
|
const { class: cls, listener } = dispatched;
|
|
153
156
|
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
154
157
|
try {
|
|
155
|
-
|
|
158
|
+
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
159
|
+
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity?.id?.href, getTypeId(activity).href), activity);
|
|
156
160
|
} catch (error) {
|
|
157
161
|
try {
|
|
158
162
|
await inboxErrorHandler?.(ctx, error);
|
|
@@ -1009,7 +1013,123 @@ function acceptsJsonLd(request) {
|
|
|
1009
1013
|
return types.includes("application/activity+json") || types.includes("application/ld+json") || types.includes("application/json");
|
|
1010
1014
|
}
|
|
1011
1015
|
//#endregion
|
|
1016
|
+
//#region src/federation/temporal.ts
|
|
1017
|
+
function isPlainObject(value) {
|
|
1018
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
1019
|
+
}
|
|
1020
|
+
function normalizeDateTimeLiteral(value) {
|
|
1021
|
+
return value.substring(19).match(/[Z+-]/) ? value : value + "Z";
|
|
1022
|
+
}
|
|
1023
|
+
function isMalformedDateTimeLiteral(value) {
|
|
1024
|
+
if (typeof value !== "string") return false;
|
|
1025
|
+
try {
|
|
1026
|
+
Temporal.Instant.from(normalizeDateTimeLiteral(value));
|
|
1027
|
+
return false;
|
|
1028
|
+
} catch {
|
|
1029
|
+
return true;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
function isMalformedDurationLiteral(value) {
|
|
1033
|
+
if (typeof value !== "string") return false;
|
|
1034
|
+
try {
|
|
1035
|
+
Temporal.Duration.from(value);
|
|
1036
|
+
return false;
|
|
1037
|
+
} catch {
|
|
1038
|
+
return true;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
const TEMPORAL_DATE_TIME_IRIS = new Set([
|
|
1042
|
+
"https://www.w3.org/ns/activitystreams#deleted",
|
|
1043
|
+
"https://www.w3.org/ns/activitystreams#endTime",
|
|
1044
|
+
"https://www.w3.org/ns/activitystreams#published",
|
|
1045
|
+
"https://www.w3.org/ns/activitystreams#startTime",
|
|
1046
|
+
"https://www.w3.org/ns/activitystreams#updated",
|
|
1047
|
+
"http://purl.org/dc/terms/created",
|
|
1048
|
+
"https://w3id.org/security#created"
|
|
1049
|
+
]);
|
|
1050
|
+
const TEMPORAL_DURATION_IRIS = new Set(["https://www.w3.org/ns/activitystreams#duration"]);
|
|
1051
|
+
const QUESTION_CLOSED_IRI = "https://www.w3.org/ns/activitystreams#closed";
|
|
1052
|
+
const XSD_DATE_TIME_IRI = "http://www.w3.org/2001/XMLSchema#dateTime";
|
|
1053
|
+
function hasMalformedExpandedDateTimeLiteral(value) {
|
|
1054
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDateTimeLiteral);
|
|
1055
|
+
return isPlainObject(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1056
|
+
}
|
|
1057
|
+
function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
1058
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedQuestionClosedLiteral);
|
|
1059
|
+
if (!isPlainObject(value) || !("@value" in value)) return false;
|
|
1060
|
+
const literal = value["@value"];
|
|
1061
|
+
if (typeof literal === "boolean") return false;
|
|
1062
|
+
if (typeof literal !== "string") return false;
|
|
1063
|
+
if (value["@type"] !== XSD_DATE_TIME_IRI) return false;
|
|
1064
|
+
if (new Date(literal).toString() === "Invalid Date") return false;
|
|
1065
|
+
return isMalformedDateTimeLiteral(literal);
|
|
1066
|
+
}
|
|
1067
|
+
function hasMalformedExpandedDurationLiteral(value) {
|
|
1068
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDurationLiteral);
|
|
1069
|
+
return isPlainObject(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1070
|
+
}
|
|
1071
|
+
function hasMalformedKnownTemporalLiteralInternal(value, visited) {
|
|
1072
|
+
if (Array.isArray(value)) return value.some((item) => hasMalformedKnownTemporalLiteralInternal(item, visited));
|
|
1073
|
+
if (!isPlainObject(value)) return false;
|
|
1074
|
+
if (visited.has(value)) return false;
|
|
1075
|
+
visited.add(value);
|
|
1076
|
+
if ("@value" in value) return false;
|
|
1077
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1078
|
+
if (TEMPORAL_DATE_TIME_IRIS.has(key)) {
|
|
1079
|
+
if (hasMalformedExpandedDateTimeLiteral(child)) return true;
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
if (key === QUESTION_CLOSED_IRI) {
|
|
1083
|
+
if (hasMalformedExpandedQuestionClosedLiteral(child)) return true;
|
|
1084
|
+
continue;
|
|
1085
|
+
}
|
|
1086
|
+
if (TEMPORAL_DURATION_IRIS.has(key)) {
|
|
1087
|
+
if (hasMalformedExpandedDurationLiteral(child)) return true;
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
if (hasMalformedKnownTemporalLiteralInternal(child, visited)) return true;
|
|
1091
|
+
}
|
|
1092
|
+
return false;
|
|
1093
|
+
}
|
|
1094
|
+
async function hasMalformedKnownTemporalLiteral(value, contextLoader) {
|
|
1095
|
+
try {
|
|
1096
|
+
return hasMalformedKnownTemporalLiteralInternal(await jsonld.expand(value, {
|
|
1097
|
+
documentLoader: getNormalizationContextLoader(contextLoader),
|
|
1098
|
+
keepFreeFloatingNodes: true
|
|
1099
|
+
}), /* @__PURE__ */ new Set());
|
|
1100
|
+
} catch {
|
|
1101
|
+
return false;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
//#endregion
|
|
1012
1105
|
//#region src/federation/handler.ts
|
|
1106
|
+
const rawInboxContextFactorySymbol = Symbol("fedify.rawInboxContextFactory");
|
|
1107
|
+
function isRemoteContextLoadingFailure$1(error) {
|
|
1108
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
1109
|
+
}
|
|
1110
|
+
function isPermanentRemoteContextError$1(error) {
|
|
1111
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
1112
|
+
const details = error.details;
|
|
1113
|
+
if (details?.code === "invalid remote context") return true;
|
|
1114
|
+
return isRemoteContextLoadingFailure$1(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
|
|
1115
|
+
}
|
|
1116
|
+
function isInvalidJsonLdError(error) {
|
|
1117
|
+
if (!(error instanceof Error)) return false;
|
|
1118
|
+
const name = error.name;
|
|
1119
|
+
return name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
|
|
1120
|
+
}
|
|
1121
|
+
function isValidationTypeError(error) {
|
|
1122
|
+
return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || isInvalidUrlTypeError(error));
|
|
1123
|
+
}
|
|
1124
|
+
function isPermanentActivityParseError(error) {
|
|
1125
|
+
return isInvalidJsonLdError(error) || isValidationTypeError(error);
|
|
1126
|
+
}
|
|
1127
|
+
function hasHttpSignatureHeaders(request) {
|
|
1128
|
+
return request.headers.has("Signature") || request.headers.has("Signature-Input");
|
|
1129
|
+
}
|
|
1130
|
+
function hasObjectIntegrityProof(json) {
|
|
1131
|
+
return typeof json === "object" && json != null && "proof" in json;
|
|
1132
|
+
}
|
|
1013
1133
|
/**
|
|
1014
1134
|
* Handles an actor request.
|
|
1015
1135
|
* @template TContextData The context data to pass to the context.
|
|
@@ -1071,8 +1191,8 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
1071
1191
|
* @param parameters The parameters for handling the collection.
|
|
1072
1192
|
* @returns A promise that resolves to an HTTP response.
|
|
1073
1193
|
*/
|
|
1074
|
-
async function handleCollection(request, { name: name$
|
|
1075
|
-
const spanName = name$
|
|
1194
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound }) {
|
|
1195
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
1076
1196
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1077
1197
|
const tracer = tracerProvider.getTracer(name, version);
|
|
1078
1198
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
@@ -1114,7 +1234,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1114
1234
|
collection = new OrderedCollection({
|
|
1115
1235
|
id: baseUri,
|
|
1116
1236
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
1117
|
-
items: filterCollectionItems(itemsOrResponse, name$
|
|
1237
|
+
items: filterCollectionItems(itemsOrResponse, name$1, filterPredicate)
|
|
1118
1238
|
});
|
|
1119
1239
|
} else {
|
|
1120
1240
|
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
@@ -1135,7 +1255,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1135
1255
|
} else {
|
|
1136
1256
|
const uri = new URL(baseUri);
|
|
1137
1257
|
uri.searchParams.set("cursor", cursor);
|
|
1138
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1258
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
1139
1259
|
kind: SpanKind.SERVER,
|
|
1140
1260
|
attributes: {
|
|
1141
1261
|
"activitypub.collection.id": uri.href,
|
|
@@ -1179,7 +1299,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1179
1299
|
id: uri,
|
|
1180
1300
|
prev,
|
|
1181
1301
|
next,
|
|
1182
|
-
items: filterCollectionItems(items, name$
|
|
1302
|
+
items: filterCollectionItems(items, name$1, filterPredicate),
|
|
1183
1303
|
partOf
|
|
1184
1304
|
});
|
|
1185
1305
|
}
|
|
@@ -1329,28 +1449,104 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1329
1449
|
});
|
|
1330
1450
|
}
|
|
1331
1451
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1452
|
+
const jsonWithoutSig = detachSignature(json);
|
|
1453
|
+
const hasLdSignature = hasSignature(json);
|
|
1454
|
+
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
1455
|
+
let deferredLdSignatureError = void 0;
|
|
1456
|
+
const respondInvalidActivity = async (error) => {
|
|
1457
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
1458
|
+
recipient,
|
|
1459
|
+
activity: json,
|
|
1460
|
+
error
|
|
1339
1461
|
});
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1462
|
+
try {
|
|
1463
|
+
await inboxErrorHandler?.(ctx, error);
|
|
1464
|
+
} catch (error) {
|
|
1465
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1466
|
+
error,
|
|
1467
|
+
activity: json,
|
|
1468
|
+
recipient
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
span.setStatus({
|
|
1472
|
+
code: SpanStatusCode.ERROR,
|
|
1473
|
+
message: `Failed to parse activity:\n${error}`
|
|
1474
|
+
});
|
|
1475
|
+
return new Response("Invalid activity.", {
|
|
1476
|
+
status: 400,
|
|
1477
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1478
|
+
});
|
|
1479
|
+
};
|
|
1480
|
+
let compactedJson = json;
|
|
1481
|
+
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
1482
|
+
let ldSigVerified = false;
|
|
1483
|
+
if (hasLdSignature) {
|
|
1484
|
+
try {
|
|
1485
|
+
compactedJson = await compactJsonLd(json, ctx.contextLoader);
|
|
1486
|
+
} catch (error) {
|
|
1487
|
+
if (isInvalidJsonLdError(error)) {
|
|
1488
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1489
|
+
recipient,
|
|
1490
|
+
error
|
|
1491
|
+
});
|
|
1492
|
+
return new Response("Invalid JSON-LD.", {
|
|
1493
|
+
status: 400,
|
|
1494
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1498
|
+
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
1499
|
+
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
1343
1500
|
recipient,
|
|
1344
1501
|
error
|
|
1345
1502
|
});
|
|
1346
|
-
return new Response("Invalid JSON-LD.", {
|
|
1347
|
-
status: 400,
|
|
1348
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1349
|
-
});
|
|
1350
1503
|
}
|
|
1351
|
-
|
|
1504
|
+
if (compactedJson !== json) {
|
|
1505
|
+
compactedJsonWithoutSig = detachSignature(compactedJson);
|
|
1506
|
+
try {
|
|
1507
|
+
ldSigVerified = await verifyCompactJsonLd(compactedJson, {
|
|
1508
|
+
contextLoader: ctx.contextLoader,
|
|
1509
|
+
documentLoader: ctx.documentLoader,
|
|
1510
|
+
keyCache,
|
|
1511
|
+
tracerProvider
|
|
1512
|
+
});
|
|
1513
|
+
} catch (error) {
|
|
1514
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1515
|
+
if (isInvalidJsonLdError(error)) {
|
|
1516
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1517
|
+
recipient,
|
|
1518
|
+
error
|
|
1519
|
+
});
|
|
1520
|
+
return new Response("Invalid JSON-LD.", {
|
|
1521
|
+
status: 400,
|
|
1522
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1526
|
+
if (!skipSignatureVerification) try {
|
|
1527
|
+
await Object$1.fromJsonLd(compactedJson, {
|
|
1528
|
+
contextLoader: getNormalizationContextLoader(ctx.contextLoader),
|
|
1529
|
+
documentLoader: ctx.documentLoader,
|
|
1530
|
+
tracerProvider
|
|
1531
|
+
});
|
|
1532
|
+
} catch (parseError) {
|
|
1533
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(parseError);
|
|
1534
|
+
if (isInvalidJsonLdError(parseError)) {
|
|
1535
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1536
|
+
recipient,
|
|
1537
|
+
error: parseError
|
|
1538
|
+
});
|
|
1539
|
+
return new Response("Invalid JSON-LD.", {
|
|
1540
|
+
status: 400,
|
|
1541
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
deferredLdSignatureError = parseError;
|
|
1545
|
+
}
|
|
1546
|
+
ldSigVerified = false;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1352
1549
|
}
|
|
1353
|
-
const jsonWithoutSig = detachSignature(json);
|
|
1354
1550
|
let activity = null;
|
|
1355
1551
|
let activityVerified = false;
|
|
1356
1552
|
if (ldSigVerified) {
|
|
@@ -1358,7 +1554,16 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1358
1554
|
recipient,
|
|
1359
1555
|
json
|
|
1360
1556
|
});
|
|
1361
|
-
|
|
1557
|
+
try {
|
|
1558
|
+
activity = await Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
1559
|
+
...ctx,
|
|
1560
|
+
contextLoader: getNormalizationContextLoader(ctx.contextLoader)
|
|
1561
|
+
});
|
|
1562
|
+
} catch (error) {
|
|
1563
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1564
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1565
|
+
return await respondInvalidActivity(error);
|
|
1566
|
+
}
|
|
1362
1567
|
activityVerified = true;
|
|
1363
1568
|
} else {
|
|
1364
1569
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
@@ -1367,12 +1572,21 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1367
1572
|
});
|
|
1368
1573
|
try {
|
|
1369
1574
|
activity = await verifyObject(Activity, jsonWithoutSig, {
|
|
1370
|
-
contextLoader: ctx.contextLoader,
|
|
1575
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1371
1576
|
documentLoader: ctx.documentLoader,
|
|
1372
1577
|
keyCache,
|
|
1373
1578
|
tracerProvider
|
|
1374
1579
|
});
|
|
1375
1580
|
} catch (error) {
|
|
1581
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1582
|
+
if (deferredLdSignatureError != null) {
|
|
1583
|
+
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
1584
|
+
recipient,
|
|
1585
|
+
error
|
|
1586
|
+
});
|
|
1587
|
+
activity = null;
|
|
1588
|
+
}
|
|
1589
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1376
1590
|
logger.error("Failed to parse activity:\n{error}", {
|
|
1377
1591
|
recipient,
|
|
1378
1592
|
activity: json,
|
|
@@ -1420,6 +1634,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1420
1634
|
tracerProvider
|
|
1421
1635
|
});
|
|
1422
1636
|
if (verification.verified === false) {
|
|
1637
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1423
1638
|
const reason = verification.reason;
|
|
1424
1639
|
logger.error("Failed to verify the request's HTTP Signatures.", {
|
|
1425
1640
|
recipient,
|
|
@@ -1495,7 +1710,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1495
1710
|
}
|
|
1496
1711
|
httpSigKey = verification.key;
|
|
1497
1712
|
}
|
|
1498
|
-
|
|
1713
|
+
try {
|
|
1714
|
+
activity = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
1715
|
+
...ctx,
|
|
1716
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1717
|
+
});
|
|
1718
|
+
} catch (error) {
|
|
1719
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1720
|
+
return await respondInvalidActivity(error);
|
|
1721
|
+
}
|
|
1499
1722
|
}
|
|
1500
1723
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1501
1724
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
@@ -1507,6 +1730,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1507
1730
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1508
1731
|
});
|
|
1509
1732
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1733
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1510
1734
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1511
1735
|
activity: json,
|
|
1512
1736
|
recipient,
|
|
@@ -1531,10 +1755,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1531
1755
|
const routeResult = await routeActivity({
|
|
1532
1756
|
context: ctx,
|
|
1533
1757
|
json,
|
|
1758
|
+
originalJson: json,
|
|
1759
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
1760
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1534
1761
|
activity,
|
|
1535
1762
|
recipient,
|
|
1536
1763
|
inboxListeners,
|
|
1537
1764
|
inboxContextFactory,
|
|
1765
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1538
1766
|
inboxErrorHandler,
|
|
1539
1767
|
kv,
|
|
1540
1768
|
kvPrefixes,
|
|
@@ -1652,8 +1880,8 @@ var CustomCollectionHandler = class {
|
|
|
1652
1880
|
* @param CollectionPage The CollectionPage constructor.
|
|
1653
1881
|
* @param filterPredicate Optional filter predicate for items.
|
|
1654
1882
|
*/
|
|
1655
|
-
constructor(name$
|
|
1656
|
-
this.name = name$
|
|
1883
|
+
constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1884
|
+
this.name = name$2;
|
|
1657
1885
|
this.values = values;
|
|
1658
1886
|
this.context = context;
|
|
1659
1887
|
this.callbacks = callbacks;
|
|
@@ -2452,6 +2680,18 @@ var middleware_exports = /* @__PURE__ */ __exportAll({
|
|
|
2452
2680
|
KvSpecDeterminer: () => KvSpecDeterminer,
|
|
2453
2681
|
createFederation: () => createFederation
|
|
2454
2682
|
});
|
|
2683
|
+
function isRemoteContextLoadingFailure(error) {
|
|
2684
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
2685
|
+
}
|
|
2686
|
+
function isPermanentRemoteContextError(error) {
|
|
2687
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
2688
|
+
const details = error.details;
|
|
2689
|
+
if (details?.code === "invalid remote context") return true;
|
|
2690
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
|
|
2691
|
+
}
|
|
2692
|
+
function isPermanentInboxParseError(error) {
|
|
2693
|
+
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));
|
|
2694
|
+
}
|
|
2455
2695
|
/**
|
|
2456
2696
|
* Create a new {@link Federation} instance.
|
|
2457
2697
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2832,7 +3072,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2832
3072
|
}
|
|
2833
3073
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
2834
3074
|
}
|
|
2835
|
-
async #listenInboxMessage(ctxData, message,
|
|
3075
|
+
async #listenInboxMessage(ctxData, message, _span) {
|
|
2836
3076
|
const logger = getLogger([
|
|
2837
3077
|
"fedify",
|
|
2838
3078
|
"federation",
|
|
@@ -2845,60 +3085,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2845
3085
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2846
3086
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2847
3087
|
}
|
|
2848
|
-
const activity = await Activity.fromJsonLd(message.activity, context);
|
|
2849
|
-
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
2850
|
-
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2851
|
-
const cacheKey = activity.id == null ? null : [
|
|
2852
|
-
...this.kvPrefixes.activityIdempotence,
|
|
2853
|
-
context.origin,
|
|
2854
|
-
activity.id.href
|
|
2855
|
-
];
|
|
2856
|
-
if (cacheKey != null) {
|
|
2857
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
2858
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
2859
|
-
activityId: activity.id?.href,
|
|
2860
|
-
activity: message.activity,
|
|
2861
|
-
recipient: message.identifier
|
|
2862
|
-
});
|
|
2863
|
-
return;
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
3088
|
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
activityId: activity.id?.href,
|
|
2871
|
-
activity: message.activity,
|
|
2872
|
-
recipient: message.identifier,
|
|
2873
|
-
trial: message.attempt
|
|
2874
|
-
});
|
|
2875
|
-
span.setStatus({
|
|
2876
|
-
code: SpanStatusCode.ERROR,
|
|
2877
|
-
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
2878
|
-
});
|
|
2879
|
-
span.end();
|
|
2880
|
-
return;
|
|
2881
|
-
}
|
|
2882
|
-
const { class: cls, listener } = dispatched;
|
|
2883
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2884
|
-
try {
|
|
2885
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, getTypeId(activity).href), activity);
|
|
2886
|
-
} catch (error) {
|
|
3089
|
+
let activity = null;
|
|
3090
|
+
let cacheKey = null;
|
|
3091
|
+
const reportInboxError = async (error) => {
|
|
2887
3092
|
try {
|
|
2888
3093
|
await this.inboxErrorHandler?.(context, error);
|
|
2889
3094
|
} catch (error) {
|
|
2890
3095
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2891
3096
|
error,
|
|
2892
3097
|
trial: message.attempt,
|
|
2893
|
-
activityId: activity
|
|
3098
|
+
activityId: activity?.id?.href,
|
|
2894
3099
|
activity: message.activity,
|
|
2895
3100
|
recipient: message.identifier
|
|
2896
3101
|
});
|
|
2897
3102
|
}
|
|
3103
|
+
};
|
|
3104
|
+
const handleRetriableFailure = async (error) => {
|
|
3105
|
+
await reportInboxError(error);
|
|
2898
3106
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2899
3107
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2900
3108
|
error,
|
|
2901
|
-
activityId: activity
|
|
3109
|
+
activityId: activity?.id?.href,
|
|
2902
3110
|
activity: message.activity,
|
|
2903
3111
|
recipient: message.identifier
|
|
2904
3112
|
});
|
|
@@ -2917,17 +3125,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2917
3125
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2918
3126
|
error,
|
|
2919
3127
|
attempt: message.attempt,
|
|
2920
|
-
activityId: activity
|
|
3128
|
+
activityId: activity?.id?.href,
|
|
2921
3129
|
activity: message.activity,
|
|
2922
3130
|
recipient: message.identifier
|
|
2923
3131
|
});
|
|
3132
|
+
if (this.inboxQueue == null) {
|
|
3133
|
+
span.setStatus({
|
|
3134
|
+
code: SpanStatusCode.ERROR,
|
|
3135
|
+
message: String(error)
|
|
3136
|
+
});
|
|
3137
|
+
span.end();
|
|
3138
|
+
throw error;
|
|
3139
|
+
}
|
|
2924
3140
|
await this.inboxQueue?.enqueue({
|
|
2925
3141
|
...message,
|
|
2926
3142
|
attempt: message.attempt + 1
|
|
2927
3143
|
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2928
3144
|
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2929
3145
|
error,
|
|
2930
|
-
activityId: activity
|
|
3146
|
+
activityId: activity?.id?.href,
|
|
2931
3147
|
activity: message.activity,
|
|
2932
3148
|
recipient: message.identifier
|
|
2933
3149
|
});
|
|
@@ -2936,11 +3152,108 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2936
3152
|
message: String(error)
|
|
2937
3153
|
});
|
|
2938
3154
|
span.end();
|
|
3155
|
+
};
|
|
3156
|
+
let dispatched;
|
|
3157
|
+
let parseInput = void 0;
|
|
3158
|
+
let parseContextLoader = context.contextLoader;
|
|
3159
|
+
try {
|
|
3160
|
+
const hasSignatureField = hasSignature(message.activity);
|
|
3161
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
3162
|
+
const parseContext = hasSignatureField ? {
|
|
3163
|
+
...context,
|
|
3164
|
+
contextLoader: getNormalizationContextLoader(context.contextLoader)
|
|
3165
|
+
} : {
|
|
3166
|
+
...context,
|
|
3167
|
+
contextLoader: wrapContextLoaderForJsonLd(context.contextLoader)
|
|
3168
|
+
};
|
|
3169
|
+
parseContextLoader = parseContext.contextLoader;
|
|
3170
|
+
let normalizedActivity;
|
|
3171
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
3172
|
+
normalizedActivity = message.normalizedActivity ?? await compactJsonLd(message.activity, context.contextLoader);
|
|
3173
|
+
assertSafeJsonLd(normalizedActivity);
|
|
3174
|
+
}
|
|
3175
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? detachSignature(normalizedActivity) : hasSignatureField ? detachSignature(message.activity) : message.activity;
|
|
3176
|
+
activity = await Activity.fromJsonLd(parseInput, parseContext);
|
|
3177
|
+
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
3178
|
+
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
3179
|
+
cacheKey = activity.id == null ? null : [
|
|
3180
|
+
...this.kvPrefixes.activityIdempotence,
|
|
3181
|
+
context.origin,
|
|
3182
|
+
activity.id.href
|
|
3183
|
+
];
|
|
3184
|
+
if (cacheKey != null) {
|
|
3185
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
3186
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
3187
|
+
activityId: activity.id?.href,
|
|
3188
|
+
activity: message.activity,
|
|
3189
|
+
recipient: message.identifier
|
|
3190
|
+
});
|
|
3191
|
+
span.end();
|
|
3192
|
+
return;
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
3196
|
+
} catch (error) {
|
|
3197
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
3198
|
+
await reportInboxError(error);
|
|
3199
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3200
|
+
error,
|
|
3201
|
+
trial: message.attempt,
|
|
3202
|
+
activityId: null,
|
|
3203
|
+
activity: message.activity,
|
|
3204
|
+
recipient: message.identifier
|
|
3205
|
+
});
|
|
3206
|
+
span.setStatus({
|
|
3207
|
+
code: SpanStatusCode.ERROR,
|
|
3208
|
+
message: String(error)
|
|
3209
|
+
});
|
|
3210
|
+
span.end();
|
|
3211
|
+
return;
|
|
3212
|
+
}
|
|
3213
|
+
if (isPermanentInboxParseError(error)) {
|
|
3214
|
+
await reportInboxError(error);
|
|
3215
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3216
|
+
error,
|
|
3217
|
+
trial: message.attempt,
|
|
3218
|
+
activityId: activity?.id?.href,
|
|
3219
|
+
activity: message.activity,
|
|
3220
|
+
recipient: message.identifier
|
|
3221
|
+
});
|
|
3222
|
+
span.setStatus({
|
|
3223
|
+
code: SpanStatusCode.ERROR,
|
|
3224
|
+
message: String(error)
|
|
3225
|
+
});
|
|
3226
|
+
span.end();
|
|
3227
|
+
return;
|
|
3228
|
+
}
|
|
3229
|
+
await handleRetriableFailure(error);
|
|
3230
|
+
return;
|
|
3231
|
+
}
|
|
3232
|
+
if (dispatched == null) {
|
|
3233
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
3234
|
+
activityId: activity.id?.href,
|
|
3235
|
+
activity: message.activity,
|
|
3236
|
+
recipient: message.identifier,
|
|
3237
|
+
trial: message.attempt
|
|
3238
|
+
});
|
|
3239
|
+
span.setStatus({
|
|
3240
|
+
code: SpanStatusCode.ERROR,
|
|
3241
|
+
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
3242
|
+
});
|
|
3243
|
+
span.end();
|
|
3244
|
+
return;
|
|
3245
|
+
}
|
|
3246
|
+
const { class: cls, listener } = dispatched;
|
|
3247
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3248
|
+
try {
|
|
3249
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, getTypeId(activity).href), activity);
|
|
3250
|
+
} catch (error) {
|
|
3251
|
+
await handleRetriableFailure(error);
|
|
2939
3252
|
return;
|
|
2940
3253
|
}
|
|
2941
3254
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2942
3255
|
logger.info("Activity {activityId} has been processed.", {
|
|
2943
|
-
activityId: activity
|
|
3256
|
+
activityId: activity?.id?.href,
|
|
2944
3257
|
activity: message.activity,
|
|
2945
3258
|
recipient: message.identifier
|
|
2946
3259
|
});
|
|
@@ -3286,16 +3599,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3286
3599
|
onNotFound
|
|
3287
3600
|
});
|
|
3288
3601
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
|
|
3289
|
-
case "sharedInbox":
|
|
3602
|
+
case "sharedInbox": {
|
|
3290
3603
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3291
3604
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3292
3605
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3293
3606
|
}
|
|
3294
3607
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3608
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3609
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
3295
3610
|
return await handleInbox(request, {
|
|
3296
3611
|
recipient: route.values.identifier ?? null,
|
|
3297
3612
|
context,
|
|
3298
|
-
inboxContextFactory
|
|
3613
|
+
inboxContextFactory,
|
|
3299
3614
|
kv: this.kv,
|
|
3300
3615
|
kvPrefixes: this.kvPrefixes,
|
|
3301
3616
|
queue: this.inboxQueue,
|
|
@@ -3310,6 +3625,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3310
3625
|
tracerProvider: this.tracerProvider,
|
|
3311
3626
|
idempotencyStrategy: this.idempotencyStrategy
|
|
3312
3627
|
});
|
|
3628
|
+
}
|
|
3313
3629
|
case "following": return await handleCollection(request, {
|
|
3314
3630
|
name: "following",
|
|
3315
3631
|
identifier: route.values.identifier,
|
|
@@ -3985,6 +4301,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3985
4301
|
const routeResult = await routeActivity({
|
|
3986
4302
|
context: this,
|
|
3987
4303
|
json,
|
|
4304
|
+
ldSignatureVerified: false,
|
|
3988
4305
|
activity,
|
|
3989
4306
|
recipient,
|
|
3990
4307
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -4099,6 +4416,14 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
4099
4416
|
};
|
|
4100
4417
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
4101
4418
|
recipient;
|
|
4419
|
+
/**
|
|
4420
|
+
* The original received activity payload.
|
|
4421
|
+
*
|
|
4422
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4423
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4424
|
+
* third-party signatures/proofs remain intact.
|
|
4425
|
+
* @internal
|
|
4426
|
+
*/
|
|
4102
4427
|
activity;
|
|
4103
4428
|
activityId;
|
|
4104
4429
|
activityType;
|