@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
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
|
-
require("./chunk-DDcVe30Y.cjs");
|
|
3
|
+
const require_chunk = require("./chunk-DDcVe30Y.cjs");
|
|
4
4
|
const require_transformers = require("./transformers-NeAONrAq.cjs");
|
|
5
|
-
const require_http = require("./http-
|
|
6
|
-
const require_proof = require("./proof-
|
|
5
|
+
const require_http = require("./http-CEXtUHix.cjs");
|
|
6
|
+
const require_proof = require("./proof-JEoW3ODq.cjs");
|
|
7
7
|
const require_types = require("./types-KC4QAoxe.cjs");
|
|
8
|
-
const require_kv_cache = require("./kv-cache-
|
|
8
|
+
const require_kv_cache = require("./kv-cache-BIapFiSV.cjs");
|
|
9
9
|
let _logtape_logtape = require("@logtape/logtape");
|
|
10
10
|
let _fedify_vocab = require("@fedify/vocab");
|
|
11
11
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
@@ -15,6 +15,8 @@ let url_template = require("url-template");
|
|
|
15
15
|
let byte_encodings_hex = require("byte-encodings/hex");
|
|
16
16
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
17
17
|
let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
18
|
+
let _fedify_vocab_runtime_jsonld = require("@fedify/vocab-runtime/jsonld");
|
|
19
|
+
_fedify_vocab_runtime_jsonld = require_chunk.__toESM(_fedify_vocab_runtime_jsonld);
|
|
18
20
|
let _fedify_webfinger = require("@fedify/webfinger");
|
|
19
21
|
let node_url = require("node:url");
|
|
20
22
|
//#region src/federation/inbox.ts
|
|
@@ -51,7 +53,7 @@ var InboxListenerSet = class InboxListenerSet {
|
|
|
51
53
|
return this.dispatchWithClass(activity)?.listener ?? null;
|
|
52
54
|
}
|
|
53
55
|
};
|
|
54
|
-
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
56
|
+
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
55
57
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
56
58
|
"fedify",
|
|
57
59
|
"federation",
|
|
@@ -108,7 +110,9 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
108
110
|
type: "inbox",
|
|
109
111
|
id: crypto.randomUUID(),
|
|
110
112
|
baseUrl: ctx.origin,
|
|
111
|
-
activity: json,
|
|
113
|
+
activity: originalJson ?? json,
|
|
114
|
+
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
115
|
+
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
112
116
|
identifier: recipient,
|
|
113
117
|
attempt: 0,
|
|
114
118
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -152,7 +156,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
152
156
|
const { class: cls, listener } = dispatched;
|
|
153
157
|
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
154
158
|
try {
|
|
155
|
-
|
|
159
|
+
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
160
|
+
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity?.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
156
161
|
} catch (error) {
|
|
157
162
|
try {
|
|
158
163
|
await inboxErrorHandler?.(ctx, error);
|
|
@@ -331,7 +336,7 @@ var FederationBuilderImpl = class {
|
|
|
331
336
|
this.collectionTypeIds = {};
|
|
332
337
|
}
|
|
333
338
|
async build(options) {
|
|
334
|
-
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-
|
|
339
|
+
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-DUT--Qen.cjs"));
|
|
335
340
|
const f = new FederationImpl(options);
|
|
336
341
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
337
342
|
f.router = this.router.clone();
|
|
@@ -1009,7 +1014,123 @@ function acceptsJsonLd(request) {
|
|
|
1009
1014
|
return types.includes("application/activity+json") || types.includes("application/ld+json") || types.includes("application/json");
|
|
1010
1015
|
}
|
|
1011
1016
|
//#endregion
|
|
1017
|
+
//#region src/federation/temporal.ts
|
|
1018
|
+
function isPlainObject(value) {
|
|
1019
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
1020
|
+
}
|
|
1021
|
+
function normalizeDateTimeLiteral(value) {
|
|
1022
|
+
return value.substring(19).match(/[Z+-]/) ? value : value + "Z";
|
|
1023
|
+
}
|
|
1024
|
+
function isMalformedDateTimeLiteral(value) {
|
|
1025
|
+
if (typeof value !== "string") return false;
|
|
1026
|
+
try {
|
|
1027
|
+
Temporal.Instant.from(normalizeDateTimeLiteral(value));
|
|
1028
|
+
return false;
|
|
1029
|
+
} catch {
|
|
1030
|
+
return true;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
function isMalformedDurationLiteral(value) {
|
|
1034
|
+
if (typeof value !== "string") return false;
|
|
1035
|
+
try {
|
|
1036
|
+
Temporal.Duration.from(value);
|
|
1037
|
+
return false;
|
|
1038
|
+
} catch {
|
|
1039
|
+
return true;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
const TEMPORAL_DATE_TIME_IRIS = new Set([
|
|
1043
|
+
"https://www.w3.org/ns/activitystreams#deleted",
|
|
1044
|
+
"https://www.w3.org/ns/activitystreams#endTime",
|
|
1045
|
+
"https://www.w3.org/ns/activitystreams#published",
|
|
1046
|
+
"https://www.w3.org/ns/activitystreams#startTime",
|
|
1047
|
+
"https://www.w3.org/ns/activitystreams#updated",
|
|
1048
|
+
"http://purl.org/dc/terms/created",
|
|
1049
|
+
"https://w3id.org/security#created"
|
|
1050
|
+
]);
|
|
1051
|
+
const TEMPORAL_DURATION_IRIS = new Set(["https://www.w3.org/ns/activitystreams#duration"]);
|
|
1052
|
+
const QUESTION_CLOSED_IRI = "https://www.w3.org/ns/activitystreams#closed";
|
|
1053
|
+
const XSD_DATE_TIME_IRI = "http://www.w3.org/2001/XMLSchema#dateTime";
|
|
1054
|
+
function hasMalformedExpandedDateTimeLiteral(value) {
|
|
1055
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDateTimeLiteral);
|
|
1056
|
+
return isPlainObject(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1057
|
+
}
|
|
1058
|
+
function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
1059
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedQuestionClosedLiteral);
|
|
1060
|
+
if (!isPlainObject(value) || !("@value" in value)) return false;
|
|
1061
|
+
const literal = value["@value"];
|
|
1062
|
+
if (typeof literal === "boolean") return false;
|
|
1063
|
+
if (typeof literal !== "string") return false;
|
|
1064
|
+
if (value["@type"] !== XSD_DATE_TIME_IRI) return false;
|
|
1065
|
+
if (new Date(literal).toString() === "Invalid Date") return false;
|
|
1066
|
+
return isMalformedDateTimeLiteral(literal);
|
|
1067
|
+
}
|
|
1068
|
+
function hasMalformedExpandedDurationLiteral(value) {
|
|
1069
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDurationLiteral);
|
|
1070
|
+
return isPlainObject(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1071
|
+
}
|
|
1072
|
+
function hasMalformedKnownTemporalLiteralInternal(value, visited) {
|
|
1073
|
+
if (Array.isArray(value)) return value.some((item) => hasMalformedKnownTemporalLiteralInternal(item, visited));
|
|
1074
|
+
if (!isPlainObject(value)) return false;
|
|
1075
|
+
if (visited.has(value)) return false;
|
|
1076
|
+
visited.add(value);
|
|
1077
|
+
if ("@value" in value) return false;
|
|
1078
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1079
|
+
if (TEMPORAL_DATE_TIME_IRIS.has(key)) {
|
|
1080
|
+
if (hasMalformedExpandedDateTimeLiteral(child)) return true;
|
|
1081
|
+
continue;
|
|
1082
|
+
}
|
|
1083
|
+
if (key === QUESTION_CLOSED_IRI) {
|
|
1084
|
+
if (hasMalformedExpandedQuestionClosedLiteral(child)) return true;
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
if (TEMPORAL_DURATION_IRIS.has(key)) {
|
|
1088
|
+
if (hasMalformedExpandedDurationLiteral(child)) return true;
|
|
1089
|
+
continue;
|
|
1090
|
+
}
|
|
1091
|
+
if (hasMalformedKnownTemporalLiteralInternal(child, visited)) return true;
|
|
1092
|
+
}
|
|
1093
|
+
return false;
|
|
1094
|
+
}
|
|
1095
|
+
async function hasMalformedKnownTemporalLiteral(value, contextLoader) {
|
|
1096
|
+
try {
|
|
1097
|
+
return hasMalformedKnownTemporalLiteralInternal(await _fedify_vocab_runtime_jsonld.default.expand(value, {
|
|
1098
|
+
documentLoader: require_proof.getNormalizationContextLoader(contextLoader),
|
|
1099
|
+
keepFreeFloatingNodes: true
|
|
1100
|
+
}), /* @__PURE__ */ new Set());
|
|
1101
|
+
} catch {
|
|
1102
|
+
return false;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
//#endregion
|
|
1012
1106
|
//#region src/federation/handler.ts
|
|
1107
|
+
const rawInboxContextFactorySymbol = Symbol("fedify.rawInboxContextFactory");
|
|
1108
|
+
function isRemoteContextLoadingFailure$1(error) {
|
|
1109
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
1110
|
+
}
|
|
1111
|
+
function isPermanentRemoteContextError$1(error) {
|
|
1112
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
1113
|
+
const details = error.details;
|
|
1114
|
+
if (details?.code === "invalid remote context") return true;
|
|
1115
|
+
return isRemoteContextLoadingFailure$1(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
1116
|
+
}
|
|
1117
|
+
function isInvalidJsonLdError(error) {
|
|
1118
|
+
if (!(error instanceof Error)) return false;
|
|
1119
|
+
const name = error.name;
|
|
1120
|
+
return name === "UnsafeJsonLdError" || error instanceof require_proof.InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
|
|
1121
|
+
}
|
|
1122
|
+
function isValidationTypeError(error) {
|
|
1123
|
+
return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || require_proof.isInvalidUrlTypeError(error));
|
|
1124
|
+
}
|
|
1125
|
+
function isPermanentActivityParseError(error) {
|
|
1126
|
+
return isInvalidJsonLdError(error) || isValidationTypeError(error);
|
|
1127
|
+
}
|
|
1128
|
+
function hasHttpSignatureHeaders(request) {
|
|
1129
|
+
return request.headers.has("Signature") || request.headers.has("Signature-Input");
|
|
1130
|
+
}
|
|
1131
|
+
function hasObjectIntegrityProof(json) {
|
|
1132
|
+
return typeof json === "object" && json != null && "proof" in json;
|
|
1133
|
+
}
|
|
1013
1134
|
/**
|
|
1014
1135
|
* Handles an actor request.
|
|
1015
1136
|
* @template TContextData The context data to pass to the context.
|
|
@@ -1071,8 +1192,8 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
1071
1192
|
* @param parameters The parameters for handling the collection.
|
|
1072
1193
|
* @returns A promise that resolves to an HTTP response.
|
|
1073
1194
|
*/
|
|
1074
|
-
async function handleCollection(request, { name: name$
|
|
1075
|
-
const spanName = name$
|
|
1195
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound }) {
|
|
1196
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
1076
1197
|
tracerProvider = tracerProvider ?? _opentelemetry_api.trace.getTracerProvider();
|
|
1077
1198
|
const tracer = tracerProvider.getTracer(require_http.name, require_http.version);
|
|
1078
1199
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
@@ -1114,7 +1235,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1114
1235
|
collection = new _fedify_vocab.OrderedCollection({
|
|
1115
1236
|
id: baseUri,
|
|
1116
1237
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
1117
|
-
items: filterCollectionItems(itemsOrResponse, name$
|
|
1238
|
+
items: filterCollectionItems(itemsOrResponse, name$1, filterPredicate)
|
|
1118
1239
|
});
|
|
1119
1240
|
} else {
|
|
1120
1241
|
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
@@ -1135,7 +1256,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1135
1256
|
} else {
|
|
1136
1257
|
const uri = new URL(baseUri);
|
|
1137
1258
|
uri.searchParams.set("cursor", cursor);
|
|
1138
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1259
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
1139
1260
|
kind: _opentelemetry_api.SpanKind.SERVER,
|
|
1140
1261
|
attributes: {
|
|
1141
1262
|
"activitypub.collection.id": uri.href,
|
|
@@ -1179,7 +1300,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1179
1300
|
id: uri,
|
|
1180
1301
|
prev,
|
|
1181
1302
|
next,
|
|
1182
|
-
items: filterCollectionItems(items, name$
|
|
1303
|
+
items: filterCollectionItems(items, name$1, filterPredicate),
|
|
1183
1304
|
partOf
|
|
1184
1305
|
});
|
|
1185
1306
|
}
|
|
@@ -1329,28 +1450,104 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1329
1450
|
});
|
|
1330
1451
|
}
|
|
1331
1452
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1453
|
+
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1454
|
+
const hasLdSignature = require_proof.hasSignature(json);
|
|
1455
|
+
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
1456
|
+
let deferredLdSignatureError = void 0;
|
|
1457
|
+
const respondInvalidActivity = async (error) => {
|
|
1458
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
1459
|
+
recipient,
|
|
1460
|
+
activity: json,
|
|
1461
|
+
error
|
|
1339
1462
|
});
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1463
|
+
try {
|
|
1464
|
+
await inboxErrorHandler?.(ctx, error);
|
|
1465
|
+
} catch (error) {
|
|
1466
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1467
|
+
error,
|
|
1468
|
+
activity: json,
|
|
1469
|
+
recipient
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
span.setStatus({
|
|
1473
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
1474
|
+
message: `Failed to parse activity:\n${error}`
|
|
1475
|
+
});
|
|
1476
|
+
return new Response("Invalid activity.", {
|
|
1477
|
+
status: 400,
|
|
1478
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1479
|
+
});
|
|
1480
|
+
};
|
|
1481
|
+
let compactedJson = json;
|
|
1482
|
+
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
1483
|
+
let ldSigVerified = false;
|
|
1484
|
+
if (hasLdSignature) {
|
|
1485
|
+
try {
|
|
1486
|
+
compactedJson = await require_proof.compactJsonLd(json, ctx.contextLoader);
|
|
1487
|
+
} catch (error) {
|
|
1488
|
+
if (isInvalidJsonLdError(error)) {
|
|
1489
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1490
|
+
recipient,
|
|
1491
|
+
error
|
|
1492
|
+
});
|
|
1493
|
+
return new Response("Invalid JSON-LD.", {
|
|
1494
|
+
status: 400,
|
|
1495
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1499
|
+
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
1500
|
+
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
1343
1501
|
recipient,
|
|
1344
1502
|
error
|
|
1345
1503
|
});
|
|
1346
|
-
return new Response("Invalid JSON-LD.", {
|
|
1347
|
-
status: 400,
|
|
1348
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1349
|
-
});
|
|
1350
1504
|
}
|
|
1351
|
-
|
|
1505
|
+
if (compactedJson !== json) {
|
|
1506
|
+
compactedJsonWithoutSig = require_proof.detachSignature(compactedJson);
|
|
1507
|
+
try {
|
|
1508
|
+
ldSigVerified = await require_proof.verifyCompactJsonLd(compactedJson, {
|
|
1509
|
+
contextLoader: ctx.contextLoader,
|
|
1510
|
+
documentLoader: ctx.documentLoader,
|
|
1511
|
+
keyCache,
|
|
1512
|
+
tracerProvider
|
|
1513
|
+
});
|
|
1514
|
+
} catch (error) {
|
|
1515
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1516
|
+
if (isInvalidJsonLdError(error)) {
|
|
1517
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1518
|
+
recipient,
|
|
1519
|
+
error
|
|
1520
|
+
});
|
|
1521
|
+
return new Response("Invalid JSON-LD.", {
|
|
1522
|
+
status: 400,
|
|
1523
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1527
|
+
if (!skipSignatureVerification) try {
|
|
1528
|
+
await _fedify_vocab.Object.fromJsonLd(compactedJson, {
|
|
1529
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader),
|
|
1530
|
+
documentLoader: ctx.documentLoader,
|
|
1531
|
+
tracerProvider
|
|
1532
|
+
});
|
|
1533
|
+
} catch (parseError) {
|
|
1534
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(parseError);
|
|
1535
|
+
if (isInvalidJsonLdError(parseError)) {
|
|
1536
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1537
|
+
recipient,
|
|
1538
|
+
error: parseError
|
|
1539
|
+
});
|
|
1540
|
+
return new Response("Invalid JSON-LD.", {
|
|
1541
|
+
status: 400,
|
|
1542
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
deferredLdSignatureError = parseError;
|
|
1546
|
+
}
|
|
1547
|
+
ldSigVerified = false;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1352
1550
|
}
|
|
1353
|
-
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1354
1551
|
let activity = null;
|
|
1355
1552
|
let activityVerified = false;
|
|
1356
1553
|
if (ldSigVerified) {
|
|
@@ -1358,7 +1555,16 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1358
1555
|
recipient,
|
|
1359
1556
|
json
|
|
1360
1557
|
});
|
|
1361
|
-
|
|
1558
|
+
try {
|
|
1559
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
1560
|
+
...ctx,
|
|
1561
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader)
|
|
1562
|
+
});
|
|
1563
|
+
} catch (error) {
|
|
1564
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1565
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1566
|
+
return await respondInvalidActivity(error);
|
|
1567
|
+
}
|
|
1362
1568
|
activityVerified = true;
|
|
1363
1569
|
} else {
|
|
1364
1570
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
@@ -1367,12 +1573,21 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1367
1573
|
});
|
|
1368
1574
|
try {
|
|
1369
1575
|
activity = await require_proof.verifyObject(_fedify_vocab.Activity, jsonWithoutSig, {
|
|
1370
|
-
contextLoader: ctx.contextLoader,
|
|
1576
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1371
1577
|
documentLoader: ctx.documentLoader,
|
|
1372
1578
|
keyCache,
|
|
1373
1579
|
tracerProvider
|
|
1374
1580
|
});
|
|
1375
1581
|
} catch (error) {
|
|
1582
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1583
|
+
if (deferredLdSignatureError != null) {
|
|
1584
|
+
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
1585
|
+
recipient,
|
|
1586
|
+
error
|
|
1587
|
+
});
|
|
1588
|
+
activity = null;
|
|
1589
|
+
}
|
|
1590
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1376
1591
|
logger.error("Failed to parse activity:\n{error}", {
|
|
1377
1592
|
recipient,
|
|
1378
1593
|
activity: json,
|
|
@@ -1420,6 +1635,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1420
1635
|
tracerProvider
|
|
1421
1636
|
});
|
|
1422
1637
|
if (verification.verified === false) {
|
|
1638
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1423
1639
|
const reason = verification.reason;
|
|
1424
1640
|
logger.error("Failed to verify the request's HTTP Signatures.", {
|
|
1425
1641
|
recipient,
|
|
@@ -1495,7 +1711,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1495
1711
|
}
|
|
1496
1712
|
httpSigKey = verification.key;
|
|
1497
1713
|
}
|
|
1498
|
-
|
|
1714
|
+
try {
|
|
1715
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(jsonWithoutSig, {
|
|
1716
|
+
...ctx,
|
|
1717
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1718
|
+
});
|
|
1719
|
+
} catch (error) {
|
|
1720
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1721
|
+
return await respondInvalidActivity(error);
|
|
1722
|
+
}
|
|
1499
1723
|
}
|
|
1500
1724
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1501
1725
|
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
@@ -1507,6 +1731,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1507
1731
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1508
1732
|
});
|
|
1509
1733
|
if (httpSigKey != null && !await require_proof.doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1734
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1510
1735
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1511
1736
|
activity: json,
|
|
1512
1737
|
recipient,
|
|
@@ -1531,10 +1756,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1531
1756
|
const routeResult = await routeActivity({
|
|
1532
1757
|
context: ctx,
|
|
1533
1758
|
json,
|
|
1759
|
+
originalJson: json,
|
|
1760
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
1761
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1534
1762
|
activity,
|
|
1535
1763
|
recipient,
|
|
1536
1764
|
inboxListeners,
|
|
1537
1765
|
inboxContextFactory,
|
|
1766
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1538
1767
|
inboxErrorHandler,
|
|
1539
1768
|
kv,
|
|
1540
1769
|
kvPrefixes,
|
|
@@ -1652,8 +1881,8 @@ var CustomCollectionHandler = class {
|
|
|
1652
1881
|
* @param CollectionPage The CollectionPage constructor.
|
|
1653
1882
|
* @param filterPredicate Optional filter predicate for items.
|
|
1654
1883
|
*/
|
|
1655
|
-
constructor(name$
|
|
1656
|
-
this.name = name$
|
|
1884
|
+
constructor(name$2, values, context, callbacks, tracerProvider = _opentelemetry_api.trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1885
|
+
this.name = name$2;
|
|
1657
1886
|
this.values = values;
|
|
1658
1887
|
this.context = context;
|
|
1659
1888
|
this.callbacks = callbacks;
|
|
@@ -2445,6 +2674,18 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2445
2674
|
}
|
|
2446
2675
|
//#endregion
|
|
2447
2676
|
//#region src/federation/middleware.ts
|
|
2677
|
+
function isRemoteContextLoadingFailure(error) {
|
|
2678
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
2679
|
+
}
|
|
2680
|
+
function isPermanentRemoteContextError(error) {
|
|
2681
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
2682
|
+
const details = error.details;
|
|
2683
|
+
if (details?.code === "invalid remote context") return true;
|
|
2684
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
2685
|
+
}
|
|
2686
|
+
function isPermanentInboxParseError(error) {
|
|
2687
|
+
return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof require_proof.InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || require_proof.isInvalidUrlTypeError(error));
|
|
2688
|
+
}
|
|
2448
2689
|
/**
|
|
2449
2690
|
* Create a new {@link Federation} instance.
|
|
2450
2691
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2825,7 +3066,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2825
3066
|
}
|
|
2826
3067
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
2827
3068
|
}
|
|
2828
|
-
async #listenInboxMessage(ctxData, message,
|
|
3069
|
+
async #listenInboxMessage(ctxData, message, _span) {
|
|
2829
3070
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
2830
3071
|
"fedify",
|
|
2831
3072
|
"federation",
|
|
@@ -2838,60 +3079,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2838
3079
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2839
3080
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2840
3081
|
}
|
|
2841
|
-
const activity = await _fedify_vocab.Activity.fromJsonLd(message.activity, context);
|
|
2842
|
-
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
2843
|
-
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2844
|
-
const cacheKey = activity.id == null ? null : [
|
|
2845
|
-
...this.kvPrefixes.activityIdempotence,
|
|
2846
|
-
context.origin,
|
|
2847
|
-
activity.id.href
|
|
2848
|
-
];
|
|
2849
|
-
if (cacheKey != null) {
|
|
2850
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
2851
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
2852
|
-
activityId: activity.id?.href,
|
|
2853
|
-
activity: message.activity,
|
|
2854
|
-
recipient: message.identifier
|
|
2855
|
-
});
|
|
2856
|
-
return;
|
|
2857
|
-
}
|
|
2858
|
-
}
|
|
2859
3082
|
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: _opentelemetry_api.SpanKind.INTERNAL }, async (span) => {
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
activityId: activity.id?.href,
|
|
2864
|
-
activity: message.activity,
|
|
2865
|
-
recipient: message.identifier,
|
|
2866
|
-
trial: message.attempt
|
|
2867
|
-
});
|
|
2868
|
-
span.setStatus({
|
|
2869
|
-
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
2870
|
-
message: `Unsupported activity type: ${(0, _fedify_vocab.getTypeId)(activity).href}`
|
|
2871
|
-
});
|
|
2872
|
-
span.end();
|
|
2873
|
-
return;
|
|
2874
|
-
}
|
|
2875
|
-
const { class: cls, listener } = dispatched;
|
|
2876
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2877
|
-
try {
|
|
2878
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
2879
|
-
} catch (error) {
|
|
3083
|
+
let activity = null;
|
|
3084
|
+
let cacheKey = null;
|
|
3085
|
+
const reportInboxError = async (error) => {
|
|
2880
3086
|
try {
|
|
2881
3087
|
await this.inboxErrorHandler?.(context, error);
|
|
2882
3088
|
} catch (error) {
|
|
2883
3089
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2884
3090
|
error,
|
|
2885
3091
|
trial: message.attempt,
|
|
2886
|
-
activityId: activity
|
|
3092
|
+
activityId: activity?.id?.href,
|
|
2887
3093
|
activity: message.activity,
|
|
2888
3094
|
recipient: message.identifier
|
|
2889
3095
|
});
|
|
2890
3096
|
}
|
|
3097
|
+
};
|
|
3098
|
+
const handleRetriableFailure = async (error) => {
|
|
3099
|
+
await reportInboxError(error);
|
|
2891
3100
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2892
3101
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2893
3102
|
error,
|
|
2894
|
-
activityId: activity
|
|
3103
|
+
activityId: activity?.id?.href,
|
|
2895
3104
|
activity: message.activity,
|
|
2896
3105
|
recipient: message.identifier
|
|
2897
3106
|
});
|
|
@@ -2910,17 +3119,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2910
3119
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2911
3120
|
error,
|
|
2912
3121
|
attempt: message.attempt,
|
|
2913
|
-
activityId: activity
|
|
3122
|
+
activityId: activity?.id?.href,
|
|
2914
3123
|
activity: message.activity,
|
|
2915
3124
|
recipient: message.identifier
|
|
2916
3125
|
});
|
|
3126
|
+
if (this.inboxQueue == null) {
|
|
3127
|
+
span.setStatus({
|
|
3128
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3129
|
+
message: String(error)
|
|
3130
|
+
});
|
|
3131
|
+
span.end();
|
|
3132
|
+
throw error;
|
|
3133
|
+
}
|
|
2917
3134
|
await this.inboxQueue?.enqueue({
|
|
2918
3135
|
...message,
|
|
2919
3136
|
attempt: message.attempt + 1
|
|
2920
3137
|
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2921
3138
|
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2922
3139
|
error,
|
|
2923
|
-
activityId: activity
|
|
3140
|
+
activityId: activity?.id?.href,
|
|
2924
3141
|
activity: message.activity,
|
|
2925
3142
|
recipient: message.identifier
|
|
2926
3143
|
});
|
|
@@ -2929,11 +3146,108 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2929
3146
|
message: String(error)
|
|
2930
3147
|
});
|
|
2931
3148
|
span.end();
|
|
3149
|
+
};
|
|
3150
|
+
let dispatched;
|
|
3151
|
+
let parseInput = void 0;
|
|
3152
|
+
let parseContextLoader = context.contextLoader;
|
|
3153
|
+
try {
|
|
3154
|
+
const hasSignatureField = require_proof.hasSignature(message.activity);
|
|
3155
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
3156
|
+
const parseContext = hasSignatureField ? {
|
|
3157
|
+
...context,
|
|
3158
|
+
contextLoader: require_proof.getNormalizationContextLoader(context.contextLoader)
|
|
3159
|
+
} : {
|
|
3160
|
+
...context,
|
|
3161
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(context.contextLoader)
|
|
3162
|
+
};
|
|
3163
|
+
parseContextLoader = parseContext.contextLoader;
|
|
3164
|
+
let normalizedActivity;
|
|
3165
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
3166
|
+
normalizedActivity = message.normalizedActivity ?? await require_proof.compactJsonLd(message.activity, context.contextLoader);
|
|
3167
|
+
require_proof.assertSafeJsonLd(normalizedActivity);
|
|
3168
|
+
}
|
|
3169
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? require_proof.detachSignature(normalizedActivity) : hasSignatureField ? require_proof.detachSignature(message.activity) : message.activity;
|
|
3170
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(parseInput, parseContext);
|
|
3171
|
+
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
3172
|
+
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
3173
|
+
cacheKey = activity.id == null ? null : [
|
|
3174
|
+
...this.kvPrefixes.activityIdempotence,
|
|
3175
|
+
context.origin,
|
|
3176
|
+
activity.id.href
|
|
3177
|
+
];
|
|
3178
|
+
if (cacheKey != null) {
|
|
3179
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
3180
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
3181
|
+
activityId: activity.id?.href,
|
|
3182
|
+
activity: message.activity,
|
|
3183
|
+
recipient: message.identifier
|
|
3184
|
+
});
|
|
3185
|
+
span.end();
|
|
3186
|
+
return;
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
3190
|
+
} catch (error) {
|
|
3191
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
3192
|
+
await reportInboxError(error);
|
|
3193
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3194
|
+
error,
|
|
3195
|
+
trial: message.attempt,
|
|
3196
|
+
activityId: null,
|
|
3197
|
+
activity: message.activity,
|
|
3198
|
+
recipient: message.identifier
|
|
3199
|
+
});
|
|
3200
|
+
span.setStatus({
|
|
3201
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3202
|
+
message: String(error)
|
|
3203
|
+
});
|
|
3204
|
+
span.end();
|
|
3205
|
+
return;
|
|
3206
|
+
}
|
|
3207
|
+
if (isPermanentInboxParseError(error)) {
|
|
3208
|
+
await reportInboxError(error);
|
|
3209
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3210
|
+
error,
|
|
3211
|
+
trial: message.attempt,
|
|
3212
|
+
activityId: activity?.id?.href,
|
|
3213
|
+
activity: message.activity,
|
|
3214
|
+
recipient: message.identifier
|
|
3215
|
+
});
|
|
3216
|
+
span.setStatus({
|
|
3217
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3218
|
+
message: String(error)
|
|
3219
|
+
});
|
|
3220
|
+
span.end();
|
|
3221
|
+
return;
|
|
3222
|
+
}
|
|
3223
|
+
await handleRetriableFailure(error);
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3226
|
+
if (dispatched == null) {
|
|
3227
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
3228
|
+
activityId: activity.id?.href,
|
|
3229
|
+
activity: message.activity,
|
|
3230
|
+
recipient: message.identifier,
|
|
3231
|
+
trial: message.attempt
|
|
3232
|
+
});
|
|
3233
|
+
span.setStatus({
|
|
3234
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3235
|
+
message: `Unsupported activity type: ${(0, _fedify_vocab.getTypeId)(activity).href}`
|
|
3236
|
+
});
|
|
3237
|
+
span.end();
|
|
3238
|
+
return;
|
|
3239
|
+
}
|
|
3240
|
+
const { class: cls, listener } = dispatched;
|
|
3241
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3242
|
+
try {
|
|
3243
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
3244
|
+
} catch (error) {
|
|
3245
|
+
await handleRetriableFailure(error);
|
|
2932
3246
|
return;
|
|
2933
3247
|
}
|
|
2934
3248
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2935
3249
|
logger.info("Activity {activityId} has been processed.", {
|
|
2936
|
-
activityId: activity
|
|
3250
|
+
activityId: activity?.id?.href,
|
|
2937
3251
|
activity: message.activity,
|
|
2938
3252
|
recipient: message.identifier
|
|
2939
3253
|
});
|
|
@@ -3279,16 +3593,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3279
3593
|
onNotFound
|
|
3280
3594
|
});
|
|
3281
3595
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
|
|
3282
|
-
case "sharedInbox":
|
|
3596
|
+
case "sharedInbox": {
|
|
3283
3597
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3284
3598
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3285
3599
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3286
3600
|
}
|
|
3287
3601
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3602
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3603
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
3288
3604
|
return await handleInbox(request, {
|
|
3289
3605
|
recipient: route.values.identifier ?? null,
|
|
3290
3606
|
context,
|
|
3291
|
-
inboxContextFactory
|
|
3607
|
+
inboxContextFactory,
|
|
3292
3608
|
kv: this.kv,
|
|
3293
3609
|
kvPrefixes: this.kvPrefixes,
|
|
3294
3610
|
queue: this.inboxQueue,
|
|
@@ -3303,6 +3619,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3303
3619
|
tracerProvider: this.tracerProvider,
|
|
3304
3620
|
idempotencyStrategy: this.idempotencyStrategy
|
|
3305
3621
|
});
|
|
3622
|
+
}
|
|
3306
3623
|
case "following": return await handleCollection(request, {
|
|
3307
3624
|
name: "following",
|
|
3308
3625
|
identifier: route.values.identifier,
|
|
@@ -3978,6 +4295,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3978
4295
|
const routeResult = await routeActivity({
|
|
3979
4296
|
context: this,
|
|
3980
4297
|
json,
|
|
4298
|
+
ldSignatureVerified: false,
|
|
3981
4299
|
activity,
|
|
3982
4300
|
recipient,
|
|
3983
4301
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -4092,6 +4410,14 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
4092
4410
|
};
|
|
4093
4411
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
4094
4412
|
recipient;
|
|
4413
|
+
/**
|
|
4414
|
+
* The original received activity payload.
|
|
4415
|
+
*
|
|
4416
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4417
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4418
|
+
* third-party signatures/proofs remain intact.
|
|
4419
|
+
* @internal
|
|
4420
|
+
*/
|
|
4095
4421
|
activity;
|
|
4096
4422
|
activityId;
|
|
4097
4423
|
activityType;
|