@fedify/fedify 1.10.9 → 1.10.10
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/{actor-z4bjwAPy.mjs → actor-DZtfiGD5.mjs} +1 -1
- package/dist/{actor-CMBXPdjk.js → actor-q2gTvEOg.js} +187 -187
- package/dist/{actor-DSmY7of0.cjs → actor-yCME0Muf.cjs} +187 -187
- package/dist/{authdocloader-YXazGK4I.cjs → authdocloader-C9ucnURr.cjs} +3 -3
- package/dist/{authdocloader-B4QKchy5.js → authdocloader-CjcVKv5l.js} +3 -3
- package/dist/{authdocloader-C7iVUcxr.mjs → authdocloader-Dxs4mL_P.mjs} +3 -3
- package/dist/{builder-C3PFAtTV.mjs → builder-DBBCeuJN.mjs} +4 -4
- package/dist/{client-C-xdpu6M.mjs → client-DfSKNItx.mjs} +1 -1
- package/dist/compat/mod.cjs +1 -1
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +3 -3
- package/dist/{context-BzSr5FCW.d.cts → context-CC4UrGc5.d.cts} +48 -6
- package/dist/{context-CyacVopT.d.ts → context-xfiK4xM5.d.ts} +48 -6
- package/dist/{docloader-DXUkyjIx.js → docloader-D8qb26Gj.js} +1 -1
- package/dist/{docloader-9cG6ESUw.cjs → docloader-DR98w4wL.cjs} +1 -1
- package/dist/{esm-Bfj-SwEx.mjs → esm-onODA711.mjs} +1 -1
- package/dist/federation/builder.test.mjs +3 -3
- package/dist/federation/collection.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +1362 -46
- package/dist/federation/idempotency.test.mjs +5 -5
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +3 -3
- package/dist/federation/kv.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +1586 -82
- package/dist/federation/mod.cjs +2 -2
- package/dist/federation/mod.d.cts +1 -1
- package/dist/federation/mod.d.ts +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +3 -3
- package/dist/federation/retry.test.mjs +2 -2
- package/dist/federation/router.test.mjs +2 -2
- 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/{http-CuloN7xQ.js → http-D6Qz3p20.js} +3 -3
- package/dist/{http-D5CDiVKf.mjs → http-DyCX-dN3.mjs} +2 -2
- package/dist/{http-LjaXmp2m.cjs → http-mdiWJYia.cjs} +3 -3
- package/dist/{inbox-D0Mzd940.mjs → inbox-BZN50kyQ.mjs} +7 -4
- package/dist/{key-Dnc1ekhA.mjs → key-CSH0Pfat.mjs} +2 -2
- package/dist/{key-CXkrXfz6.cjs → key-DPzMtgeE.cjs} +1 -1
- package/dist/{key-B22mXs2u.cjs → key-DRfL8gil.cjs} +2 -2
- package/dist/{key-B5QN42gR.mjs → key-DXUAJBZu.mjs} +1 -1
- package/dist/{key-D1PkkNK-.js → key-TRp8WTUL.js} +2 -2
- package/dist/{keycache-DwDRFAp7.mjs → keycache-DETDxpbh.mjs} +1 -1
- package/dist/{keys-C4Ms2Cy-.mjs → keys-8FIoKqmB.mjs} +1 -1
- package/dist/ld-BaJmhpEa.mjs +548 -0
- package/dist/{lookup-D0d32cZH.cjs → lookup-B7TLaXFf.cjs} +1 -1
- package/dist/{lookup-B8rOR_1a.js → lookup-C6wM-gq1.js} +1 -1
- package/dist/{lookup-Br7I7sqm.mjs → lookup-CX2yfN-X.mjs} +1 -1
- package/dist/{middleware-BlsPkr2X.mjs → middleware-BJ7otoEC.mjs} +1 -1
- package/dist/{middleware-BbgpZrsX.mjs → middleware-BQ6evC7E.mjs} +320 -87
- package/dist/{middleware-CYNQWJ-D.js → middleware-BXc5M6YG.js} +408 -83
- package/dist/{middleware-0yq2uipZ.cjs → middleware-DpVqFb2x.cjs} +411 -85
- package/dist/{middleware-BRXIidLb.cjs → middleware-cNynSnF6.cjs} +1 -1
- package/dist/mod.cjs +10 -10
- package/dist/mod.d.cts +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.js +9 -9
- package/dist/nodeinfo/client.test.mjs +3 -3
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/nodeinfo/semver.test.mjs +1 -1
- package/dist/nodeinfo/types.test.mjs +1 -1
- package/dist/otel/exporter.test.mjs +1 -1
- package/dist/otel/mod.cjs +1 -1
- package/dist/{owner-D32qC-wF.mjs → owner-CLGVwm9P.mjs} +3 -3
- package/dist/{proof-DE2Z0_uv.cjs → proof-BVB37JmB.cjs} +347 -5
- package/dist/{proof-B67QOiuS.mjs → proof-CAOvY-AP.mjs} +2 -2
- package/dist/{proof-u5ivh_eA.js → proof-DxQL08gJ.js} +300 -6
- package/dist/runtime/authdocloader.test.mjs +6 -6
- package/dist/runtime/docloader.test.mjs +4 -4
- package/dist/runtime/key.test.mjs +3 -3
- package/dist/runtime/langstr.test.mjs +2 -2
- package/dist/runtime/link.test.mjs +2 -2
- package/dist/runtime/mod.cjs +3 -3
- package/dist/runtime/mod.js +3 -3
- package/dist/runtime/multibase/multibase.test.mjs +2 -2
- package/dist/runtime/url.test.mjs +2 -2
- package/dist/{send-7RGxOhrY.mjs → send-BFClgq8T.mjs} +2 -2
- package/dist/sig/http.test.mjs +6 -6
- package/dist/sig/key.test.mjs +4 -4
- package/dist/sig/ld.test.mjs +561 -5
- package/dist/sig/mod.cjs +3 -3
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +4 -4
- package/dist/temporal-lmewfA7Y.mjs +95 -0
- package/dist/testing/docloader.test.mjs +1 -1
- package/dist/testing/mod.d.mts +48 -6
- package/dist/testing/mod.mjs +1 -1
- package/dist/{testing-zWgaXBJW.mjs → testing-B9FmxxlI.mjs} +2 -2
- package/dist/{transformers-BdbEtUZU.cjs → transformers-KRl8YJCO.cjs} +1 -1
- package/dist/{types-6_pWuZfK.js → types-B0aIcMDF.js} +1 -1
- package/dist/{types-ec4G8nGs.cjs → types-DPWiFqle.cjs} +1 -1
- package/dist/vocab/actor.test.mjs +4 -4
- package/dist/vocab/cjs.test.mjs +1 -1
- package/dist/vocab/lookup.test.mjs +5 -5
- package/dist/vocab/mod.cjs +3 -3
- package/dist/vocab/mod.js +3 -3
- package/dist/vocab/type.test.mjs +2 -2
- package/dist/vocab/vocab.test.mjs +3 -3
- package/dist/{vocab-C60RNInZ.mjs → vocab-DP9A9TjH.mjs} +186 -186
- package/dist/webfinger/handler.test.mjs +3 -3
- package/dist/webfinger/lookup.test.mjs +3 -3
- package/dist/webfinger/mod.cjs +1 -1
- package/dist/webfinger/mod.js +1 -1
- package/dist/x/cfworkers.cjs +1 -1
- package/dist/x/cfworkers.test.mjs +1 -1
- package/dist/x/hono.cjs +1 -1
- package/dist/x/hono.d.cts +1 -1
- package/dist/x/hono.d.ts +1 -1
- package/dist/x/sveltekit.cjs +1 -1
- package/dist/x/sveltekit.d.cts +1 -1
- package/dist/x/sveltekit.d.ts +1 -1
- package/package.json +1 -1
- package/dist/ld-BJ8BZLC8.mjs +0 -254
- /package/dist/{denokv-NJPMXyK0.mjs → denokv-B0ZRIDsH.mjs} +0 -0
- /package/dist/{otel-0v4Zy01l.mjs → otel-D00WjYJ1.mjs} +0 -0
- /package/dist/{retry-Ddbq3AcK.mjs → retry-B_E3V_Dx.mjs} +0 -0
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
|
-
const require_docloader = require("./docloader-
|
|
4
|
-
const require_transformers = require("./transformers-
|
|
5
|
-
const require_actor = require("./actor-
|
|
6
|
-
const require_lookup = require("./lookup-
|
|
7
|
-
const require_key = require("./key-
|
|
8
|
-
const require_http = require("./http-
|
|
9
|
-
const require_proof = require("./proof-
|
|
10
|
-
const require_types = require("./types-
|
|
11
|
-
const require_authdocloader = require("./authdocloader-
|
|
3
|
+
const require_docloader = require("./docloader-DR98w4wL.cjs");
|
|
4
|
+
const require_transformers = require("./transformers-KRl8YJCO.cjs");
|
|
5
|
+
const require_actor = require("./actor-yCME0Muf.cjs");
|
|
6
|
+
const require_lookup = require("./lookup-B7TLaXFf.cjs");
|
|
7
|
+
const require_key = require("./key-DRfL8gil.cjs");
|
|
8
|
+
const require_http = require("./http-mdiWJYia.cjs");
|
|
9
|
+
const require_proof = require("./proof-BVB37JmB.cjs");
|
|
10
|
+
const require_types = require("./types-DPWiFqle.cjs");
|
|
11
|
+
const require_authdocloader = require("./authdocloader-C9ucnURr.cjs");
|
|
12
12
|
const require_vocab_mod = require("./vocab/mod.cjs");
|
|
13
13
|
let _logtape_logtape = require("@logtape/logtape");
|
|
14
14
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
15
|
+
let jsonld = require("jsonld");
|
|
16
|
+
jsonld = require_docloader.__toESM(jsonld);
|
|
15
17
|
let byte_encodings_hex = require("byte-encodings/hex");
|
|
16
18
|
let es_toolkit = require("es-toolkit");
|
|
17
19
|
let uri_template_router = require("uri-template-router");
|
|
@@ -53,7 +55,7 @@ var InboxListenerSet = class InboxListenerSet {
|
|
|
53
55
|
}
|
|
54
56
|
};
|
|
55
57
|
let warnedAboutDefaultIdempotency = false;
|
|
56
|
-
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
58
|
+
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
57
59
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
58
60
|
"fedify",
|
|
59
61
|
"federation",
|
|
@@ -114,7 +116,9 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
114
116
|
type: "inbox",
|
|
115
117
|
id: crypto.randomUUID(),
|
|
116
118
|
baseUrl: ctx.origin,
|
|
117
|
-
activity: json,
|
|
119
|
+
activity: originalJson ?? json,
|
|
120
|
+
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
121
|
+
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
118
122
|
identifier: recipient,
|
|
119
123
|
attempt: 0,
|
|
120
124
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -158,7 +162,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
158
162
|
const { class: cls, listener } = dispatched;
|
|
159
163
|
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
160
164
|
try {
|
|
161
|
-
|
|
165
|
+
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
166
|
+
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity?.id?.href, require_actor.getTypeId(activity).href), activity);
|
|
162
167
|
} catch (error) {
|
|
163
168
|
try {
|
|
164
169
|
await inboxErrorHandler?.(ctx, error);
|
|
@@ -335,7 +340,7 @@ var FederationBuilderImpl = class {
|
|
|
335
340
|
this.collectionTypeIds = {};
|
|
336
341
|
}
|
|
337
342
|
async build(options) {
|
|
338
|
-
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-
|
|
343
|
+
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-cNynSnF6.cjs"));
|
|
339
344
|
const f = new FederationImpl(options);
|
|
340
345
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
341
346
|
f.router = this.router.clone();
|
|
@@ -998,7 +1003,123 @@ function preferredMediaTypes(accept) {
|
|
|
998
1003
|
return parseAccept(accept === void 0 ? "*/*" : accept ?? "").filter(isQuality).sort(compareSpecs).map(getFullType);
|
|
999
1004
|
}
|
|
1000
1005
|
//#endregion
|
|
1006
|
+
//#region src/federation/temporal.ts
|
|
1007
|
+
function isPlainObject(value) {
|
|
1008
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
1009
|
+
}
|
|
1010
|
+
function normalizeDateTimeLiteral(value) {
|
|
1011
|
+
return value.substring(19).match(/[Z+-]/) ? value : value + "Z";
|
|
1012
|
+
}
|
|
1013
|
+
function isMalformedDateTimeLiteral(value) {
|
|
1014
|
+
if (typeof value !== "string") return false;
|
|
1015
|
+
try {
|
|
1016
|
+
Temporal.Instant.from(normalizeDateTimeLiteral(value));
|
|
1017
|
+
return false;
|
|
1018
|
+
} catch {
|
|
1019
|
+
return true;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
function isMalformedDurationLiteral(value) {
|
|
1023
|
+
if (typeof value !== "string") return false;
|
|
1024
|
+
try {
|
|
1025
|
+
Temporal.Duration.from(value);
|
|
1026
|
+
return false;
|
|
1027
|
+
} catch {
|
|
1028
|
+
return true;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
const TEMPORAL_DATE_TIME_IRIS = new Set([
|
|
1032
|
+
"https://www.w3.org/ns/activitystreams#deleted",
|
|
1033
|
+
"https://www.w3.org/ns/activitystreams#endTime",
|
|
1034
|
+
"https://www.w3.org/ns/activitystreams#published",
|
|
1035
|
+
"https://www.w3.org/ns/activitystreams#startTime",
|
|
1036
|
+
"https://www.w3.org/ns/activitystreams#updated",
|
|
1037
|
+
"http://purl.org/dc/terms/created",
|
|
1038
|
+
"https://w3id.org/security#created"
|
|
1039
|
+
]);
|
|
1040
|
+
const TEMPORAL_DURATION_IRIS = new Set(["https://www.w3.org/ns/activitystreams#duration"]);
|
|
1041
|
+
const QUESTION_CLOSED_IRI = "https://www.w3.org/ns/activitystreams#closed";
|
|
1042
|
+
const XSD_DATE_TIME_IRI = "http://www.w3.org/2001/XMLSchema#dateTime";
|
|
1043
|
+
function hasMalformedExpandedDateTimeLiteral(value) {
|
|
1044
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDateTimeLiteral);
|
|
1045
|
+
return isPlainObject(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1046
|
+
}
|
|
1047
|
+
function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
1048
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedQuestionClosedLiteral);
|
|
1049
|
+
if (!isPlainObject(value) || !("@value" in value)) return false;
|
|
1050
|
+
const literal = value["@value"];
|
|
1051
|
+
if (typeof literal === "boolean") return false;
|
|
1052
|
+
if (typeof literal !== "string") return false;
|
|
1053
|
+
if (value["@type"] !== XSD_DATE_TIME_IRI) return false;
|
|
1054
|
+
if (new Date(literal).toString() === "Invalid Date") return false;
|
|
1055
|
+
return isMalformedDateTimeLiteral(literal);
|
|
1056
|
+
}
|
|
1057
|
+
function hasMalformedExpandedDurationLiteral(value) {
|
|
1058
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDurationLiteral);
|
|
1059
|
+
return isPlainObject(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1060
|
+
}
|
|
1061
|
+
function hasMalformedKnownTemporalLiteralInternal(value, visited) {
|
|
1062
|
+
if (Array.isArray(value)) return value.some((item) => hasMalformedKnownTemporalLiteralInternal(item, visited));
|
|
1063
|
+
if (!isPlainObject(value)) return false;
|
|
1064
|
+
if (visited.has(value)) return false;
|
|
1065
|
+
visited.add(value);
|
|
1066
|
+
if ("@value" in value) return false;
|
|
1067
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1068
|
+
if (TEMPORAL_DATE_TIME_IRIS.has(key)) {
|
|
1069
|
+
if (hasMalformedExpandedDateTimeLiteral(child)) return true;
|
|
1070
|
+
continue;
|
|
1071
|
+
}
|
|
1072
|
+
if (key === QUESTION_CLOSED_IRI) {
|
|
1073
|
+
if (hasMalformedExpandedQuestionClosedLiteral(child)) return true;
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
if (TEMPORAL_DURATION_IRIS.has(key)) {
|
|
1077
|
+
if (hasMalformedExpandedDurationLiteral(child)) return true;
|
|
1078
|
+
continue;
|
|
1079
|
+
}
|
|
1080
|
+
if (hasMalformedKnownTemporalLiteralInternal(child, visited)) return true;
|
|
1081
|
+
}
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
1084
|
+
async function hasMalformedKnownTemporalLiteral(value, contextLoader) {
|
|
1085
|
+
try {
|
|
1086
|
+
return hasMalformedKnownTemporalLiteralInternal(await jsonld.default.expand(value, {
|
|
1087
|
+
documentLoader: require_proof.getNormalizationContextLoader(contextLoader),
|
|
1088
|
+
keepFreeFloatingNodes: true
|
|
1089
|
+
}), /* @__PURE__ */ new Set());
|
|
1090
|
+
} catch {
|
|
1091
|
+
return false;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
//#endregion
|
|
1001
1095
|
//#region src/federation/handler.ts
|
|
1096
|
+
const rawInboxContextFactorySymbol = Symbol("fedify.rawInboxContextFactory");
|
|
1097
|
+
function isRemoteContextLoadingFailure$1(error) {
|
|
1098
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
1099
|
+
}
|
|
1100
|
+
function isPermanentRemoteContextError$1(error) {
|
|
1101
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
1102
|
+
const details = error.details;
|
|
1103
|
+
if (details?.code === "invalid remote context") return true;
|
|
1104
|
+
return isRemoteContextLoadingFailure$1(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
1105
|
+
}
|
|
1106
|
+
function isInvalidJsonLdError(error) {
|
|
1107
|
+
if (!(error instanceof Error)) return false;
|
|
1108
|
+
const name = error.name;
|
|
1109
|
+
return name === "UnsafeJsonLdError" || error instanceof require_proof.InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
|
|
1110
|
+
}
|
|
1111
|
+
function isValidationTypeError(error) {
|
|
1112
|
+
return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || require_proof.isInvalidUrlTypeError(error));
|
|
1113
|
+
}
|
|
1114
|
+
function isPermanentActivityParseError(error) {
|
|
1115
|
+
return isInvalidJsonLdError(error) || isValidationTypeError(error);
|
|
1116
|
+
}
|
|
1117
|
+
function hasHttpSignatureHeaders(request) {
|
|
1118
|
+
return request.headers.has("Signature") || request.headers.has("Signature-Input");
|
|
1119
|
+
}
|
|
1120
|
+
function hasObjectIntegrityProof(json) {
|
|
1121
|
+
return typeof json === "object" && json != null && "proof" in json;
|
|
1122
|
+
}
|
|
1002
1123
|
function acceptsJsonLd(request) {
|
|
1003
1124
|
const accept = request.headers.get("Accept");
|
|
1004
1125
|
const types = accept ? preferredMediaTypes(accept) : ["*/*"];
|
|
@@ -1105,8 +1226,8 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
1105
1226
|
* @param parameters The parameters for handling the collection.
|
|
1106
1227
|
* @returns A promise that resolves to an HTTP response.
|
|
1107
1228
|
*/
|
|
1108
|
-
async function handleCollection(request, { name: name$
|
|
1109
|
-
const spanName = name$
|
|
1229
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound, onNotAcceptable }) {
|
|
1230
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
1110
1231
|
tracerProvider = tracerProvider ?? _opentelemetry_api.trace.getTracerProvider();
|
|
1111
1232
|
const tracer = tracerProvider.getTracer(require_docloader.name, require_docloader.version);
|
|
1112
1233
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
@@ -1148,7 +1269,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1148
1269
|
collection = new require_actor.OrderedCollection({
|
|
1149
1270
|
id: baseUri,
|
|
1150
1271
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
1151
|
-
items: filterCollectionItems(itemsOrResponse, name$
|
|
1272
|
+
items: filterCollectionItems(itemsOrResponse, name$1, filterPredicate)
|
|
1152
1273
|
});
|
|
1153
1274
|
} else {
|
|
1154
1275
|
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
@@ -1169,7 +1290,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1169
1290
|
} else {
|
|
1170
1291
|
const uri = new URL(baseUri);
|
|
1171
1292
|
uri.searchParams.set("cursor", cursor);
|
|
1172
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1293
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
1173
1294
|
kind: _opentelemetry_api.SpanKind.SERVER,
|
|
1174
1295
|
attributes: {
|
|
1175
1296
|
"activitypub.collection.id": uri.href,
|
|
@@ -1213,7 +1334,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1213
1334
|
id: uri,
|
|
1214
1335
|
prev,
|
|
1215
1336
|
next,
|
|
1216
|
-
items: filterCollectionItems(items, name$
|
|
1337
|
+
items: filterCollectionItems(items, name$1, filterPredicate),
|
|
1217
1338
|
partOf
|
|
1218
1339
|
});
|
|
1219
1340
|
}
|
|
@@ -1382,35 +1503,120 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1382
1503
|
});
|
|
1383
1504
|
}
|
|
1384
1505
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1506
|
+
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1507
|
+
const hasLdSignature = require_proof.hasSignature(json);
|
|
1508
|
+
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
1509
|
+
let deferredLdSignatureError = void 0;
|
|
1510
|
+
const respondInvalidActivity = async (error) => {
|
|
1511
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
1512
|
+
recipient,
|
|
1513
|
+
activity: json,
|
|
1514
|
+
error
|
|
1392
1515
|
});
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1516
|
+
try {
|
|
1517
|
+
await inboxErrorHandler?.(ctx, error);
|
|
1518
|
+
} catch (error) {
|
|
1519
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1520
|
+
error,
|
|
1521
|
+
activity: json,
|
|
1522
|
+
recipient
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
span.setStatus({
|
|
1526
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
1527
|
+
message: `Failed to parse activity:\n${error}`
|
|
1528
|
+
});
|
|
1529
|
+
return new Response("Invalid activity.", {
|
|
1530
|
+
status: 400,
|
|
1531
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1532
|
+
});
|
|
1533
|
+
};
|
|
1534
|
+
let compactedJson = json;
|
|
1535
|
+
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
1536
|
+
let ldSigVerified = false;
|
|
1537
|
+
if (hasLdSignature) {
|
|
1538
|
+
try {
|
|
1539
|
+
compactedJson = await require_proof.compactJsonLd(json, ctx.contextLoader);
|
|
1540
|
+
} catch (error) {
|
|
1541
|
+
if (isInvalidJsonLdError(error)) {
|
|
1542
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1543
|
+
recipient,
|
|
1544
|
+
error
|
|
1545
|
+
});
|
|
1546
|
+
return new Response("Invalid JSON-LD.", {
|
|
1547
|
+
status: 400,
|
|
1548
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1552
|
+
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
1553
|
+
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
1396
1554
|
recipient,
|
|
1397
1555
|
error
|
|
1398
1556
|
});
|
|
1399
|
-
return new Response("Invalid JSON-LD.", {
|
|
1400
|
-
status: 400,
|
|
1401
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1402
|
-
});
|
|
1403
1557
|
}
|
|
1404
|
-
|
|
1558
|
+
if (compactedJson !== json) {
|
|
1559
|
+
compactedJsonWithoutSig = require_proof.detachSignature(compactedJson);
|
|
1560
|
+
try {
|
|
1561
|
+
ldSigVerified = await require_proof.verifyCompactJsonLd(compactedJson, {
|
|
1562
|
+
contextLoader: ctx.contextLoader,
|
|
1563
|
+
documentLoader: ctx.documentLoader,
|
|
1564
|
+
keyCache,
|
|
1565
|
+
tracerProvider
|
|
1566
|
+
});
|
|
1567
|
+
} catch (error) {
|
|
1568
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1569
|
+
if (isInvalidJsonLdError(error)) {
|
|
1570
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1571
|
+
recipient,
|
|
1572
|
+
error
|
|
1573
|
+
});
|
|
1574
|
+
return new Response("Invalid JSON-LD.", {
|
|
1575
|
+
status: 400,
|
|
1576
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1580
|
+
if (!skipSignatureVerification) try {
|
|
1581
|
+
await require_actor.Object.fromJsonLd(compactedJson, {
|
|
1582
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader),
|
|
1583
|
+
documentLoader: ctx.documentLoader,
|
|
1584
|
+
tracerProvider
|
|
1585
|
+
});
|
|
1586
|
+
} catch (parseError) {
|
|
1587
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(parseError);
|
|
1588
|
+
if (isInvalidJsonLdError(parseError)) {
|
|
1589
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1590
|
+
recipient,
|
|
1591
|
+
error: parseError
|
|
1592
|
+
});
|
|
1593
|
+
return new Response("Invalid JSON-LD.", {
|
|
1594
|
+
status: 400,
|
|
1595
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
deferredLdSignatureError = parseError;
|
|
1599
|
+
}
|
|
1600
|
+
ldSigVerified = false;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1405
1603
|
}
|
|
1406
|
-
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1407
1604
|
let activity = null;
|
|
1408
1605
|
if (ldSigVerified) {
|
|
1409
1606
|
logger.debug("Linked Data Signatures are verified.", {
|
|
1410
1607
|
recipient,
|
|
1411
1608
|
json
|
|
1412
1609
|
});
|
|
1413
|
-
|
|
1610
|
+
try {
|
|
1611
|
+
activity = await require_actor.Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
1612
|
+
...ctx,
|
|
1613
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader)
|
|
1614
|
+
});
|
|
1615
|
+
} catch (error) {
|
|
1616
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1617
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1618
|
+
return await respondInvalidActivity(error);
|
|
1619
|
+
}
|
|
1414
1620
|
} else {
|
|
1415
1621
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
1416
1622
|
recipient,
|
|
@@ -1418,12 +1624,21 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1418
1624
|
});
|
|
1419
1625
|
try {
|
|
1420
1626
|
activity = await require_proof.verifyObject(require_actor.Activity, jsonWithoutSig, {
|
|
1421
|
-
contextLoader: ctx.contextLoader,
|
|
1627
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1422
1628
|
documentLoader: ctx.documentLoader,
|
|
1423
1629
|
keyCache,
|
|
1424
1630
|
tracerProvider
|
|
1425
1631
|
});
|
|
1426
1632
|
} catch (error) {
|
|
1633
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1634
|
+
if (deferredLdSignatureError != null) {
|
|
1635
|
+
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
1636
|
+
recipient,
|
|
1637
|
+
error
|
|
1638
|
+
});
|
|
1639
|
+
activity = null;
|
|
1640
|
+
}
|
|
1641
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1427
1642
|
logger.error("Failed to parse activity:\n{error}", {
|
|
1428
1643
|
recipient,
|
|
1429
1644
|
activity: json,
|
|
@@ -1467,6 +1682,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1467
1682
|
tracerProvider
|
|
1468
1683
|
});
|
|
1469
1684
|
if (key == null) {
|
|
1685
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1470
1686
|
logger.error("Failed to verify the request's HTTP Signatures.", { recipient });
|
|
1471
1687
|
span.setStatus({
|
|
1472
1688
|
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
@@ -1479,7 +1695,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1479
1695
|
} else logger.debug("HTTP Signatures are verified.", { recipient });
|
|
1480
1696
|
httpSigKey = key;
|
|
1481
1697
|
}
|
|
1482
|
-
|
|
1698
|
+
try {
|
|
1699
|
+
activity = await require_actor.Activity.fromJsonLd(jsonWithoutSig, {
|
|
1700
|
+
...ctx,
|
|
1701
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1702
|
+
});
|
|
1703
|
+
} catch (error) {
|
|
1704
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1705
|
+
return await respondInvalidActivity(error);
|
|
1706
|
+
}
|
|
1483
1707
|
}
|
|
1484
1708
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1485
1709
|
span.setAttribute("activitypub.activity.type", require_actor.getTypeId(activity).href);
|
|
@@ -1491,6 +1715,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1491
1715
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1492
1716
|
});
|
|
1493
1717
|
if (httpSigKey != null && !await require_proof.doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1718
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1494
1719
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1495
1720
|
activity: json,
|
|
1496
1721
|
recipient,
|
|
@@ -1509,10 +1734,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1509
1734
|
const routeResult = await routeActivity({
|
|
1510
1735
|
context: ctx,
|
|
1511
1736
|
json,
|
|
1737
|
+
originalJson: json,
|
|
1738
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
1739
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1512
1740
|
activity,
|
|
1513
1741
|
recipient,
|
|
1514
1742
|
inboxListeners,
|
|
1515
1743
|
inboxContextFactory,
|
|
1744
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1516
1745
|
inboxErrorHandler,
|
|
1517
1746
|
kv,
|
|
1518
1747
|
kvPrefixes,
|
|
@@ -1632,8 +1861,8 @@ var CustomCollectionHandler = class {
|
|
|
1632
1861
|
* @param CollectionPage The CollectionPage constructor.
|
|
1633
1862
|
* @param filterPredicate Optional filter predicate for items.
|
|
1634
1863
|
*/
|
|
1635
|
-
constructor(name$
|
|
1636
|
-
this.name = name$
|
|
1864
|
+
constructor(name$2, values, context, callbacks, tracerProvider = _opentelemetry_api.trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1865
|
+
this.name = name$2;
|
|
1637
1866
|
this.values = values;
|
|
1638
1867
|
this.context = context;
|
|
1639
1868
|
this.callbacks = callbacks;
|
|
@@ -2329,6 +2558,18 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2329
2558
|
}
|
|
2330
2559
|
//#endregion
|
|
2331
2560
|
//#region src/federation/middleware.ts
|
|
2561
|
+
function isRemoteContextLoadingFailure(error) {
|
|
2562
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
2563
|
+
}
|
|
2564
|
+
function isPermanentRemoteContextError(error) {
|
|
2565
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
2566
|
+
const details = error.details;
|
|
2567
|
+
if (details?.code === "invalid remote context") return true;
|
|
2568
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
2569
|
+
}
|
|
2570
|
+
function isPermanentInboxParseError(error) {
|
|
2571
|
+
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));
|
|
2572
|
+
}
|
|
2332
2573
|
/**
|
|
2333
2574
|
* Create a new {@link Federation} instance.
|
|
2334
2575
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2660,7 +2901,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2660
2901
|
}
|
|
2661
2902
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
2662
2903
|
}
|
|
2663
|
-
async #listenInboxMessage(ctxData, message,
|
|
2904
|
+
async #listenInboxMessage(ctxData, message, _span) {
|
|
2664
2905
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
2665
2906
|
"fedify",
|
|
2666
2907
|
"federation",
|
|
@@ -2673,60 +2914,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2673
2914
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2674
2915
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity || "handle" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2675
2916
|
}
|
|
2676
|
-
const activity = await require_actor.Activity.fromJsonLd(message.activity, context);
|
|
2677
|
-
span.setAttribute("activitypub.activity.type", require_actor.getTypeId(activity).href);
|
|
2678
|
-
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2679
|
-
const cacheKey = activity.id == null ? null : [
|
|
2680
|
-
...this.kvPrefixes.activityIdempotence,
|
|
2681
|
-
context.origin,
|
|
2682
|
-
activity.id.href
|
|
2683
|
-
];
|
|
2684
|
-
if (cacheKey != null) {
|
|
2685
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
2686
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
2687
|
-
activityId: activity.id?.href,
|
|
2688
|
-
activity: message.activity,
|
|
2689
|
-
recipient: message.identifier
|
|
2690
|
-
});
|
|
2691
|
-
return;
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
2917
|
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: _opentelemetry_api.SpanKind.INTERNAL }, async (span) => {
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
activityId: activity.id?.href,
|
|
2699
|
-
activity: message.activity,
|
|
2700
|
-
recipient: message.identifier,
|
|
2701
|
-
trial: message.attempt
|
|
2702
|
-
});
|
|
2703
|
-
span.setStatus({
|
|
2704
|
-
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
2705
|
-
message: `Unsupported activity type: ${require_actor.getTypeId(activity).href}`
|
|
2706
|
-
});
|
|
2707
|
-
span.end();
|
|
2708
|
-
return;
|
|
2709
|
-
}
|
|
2710
|
-
const { class: cls, listener } = dispatched;
|
|
2711
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2712
|
-
try {
|
|
2713
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, require_actor.getTypeId(activity).href), activity);
|
|
2714
|
-
} catch (error) {
|
|
2918
|
+
let activity = null;
|
|
2919
|
+
let cacheKey = null;
|
|
2920
|
+
const reportInboxError = async (error) => {
|
|
2715
2921
|
try {
|
|
2716
2922
|
await this.inboxErrorHandler?.(context, error);
|
|
2717
2923
|
} catch (error) {
|
|
2718
2924
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2719
2925
|
error,
|
|
2720
2926
|
trial: message.attempt,
|
|
2721
|
-
activityId: activity
|
|
2927
|
+
activityId: activity?.id?.href,
|
|
2722
2928
|
activity: message.activity,
|
|
2723
2929
|
recipient: message.identifier
|
|
2724
2930
|
});
|
|
2725
2931
|
}
|
|
2932
|
+
};
|
|
2933
|
+
const handleRetriableFailure = async (error) => {
|
|
2934
|
+
await reportInboxError(error);
|
|
2726
2935
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2727
2936
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2728
2937
|
error,
|
|
2729
|
-
activityId: activity
|
|
2938
|
+
activityId: activity?.id?.href,
|
|
2730
2939
|
activity: message.activity,
|
|
2731
2940
|
recipient: message.identifier
|
|
2732
2941
|
});
|
|
@@ -2745,17 +2954,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2745
2954
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2746
2955
|
error,
|
|
2747
2956
|
attempt: message.attempt,
|
|
2748
|
-
activityId: activity
|
|
2957
|
+
activityId: activity?.id?.href,
|
|
2749
2958
|
activity: message.activity,
|
|
2750
2959
|
recipient: message.identifier
|
|
2751
2960
|
});
|
|
2961
|
+
if (this.inboxQueue == null) {
|
|
2962
|
+
span.setStatus({
|
|
2963
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
2964
|
+
message: String(error)
|
|
2965
|
+
});
|
|
2966
|
+
span.end();
|
|
2967
|
+
throw error;
|
|
2968
|
+
}
|
|
2752
2969
|
await this.inboxQueue?.enqueue({
|
|
2753
2970
|
...message,
|
|
2754
2971
|
attempt: message.attempt + 1
|
|
2755
2972
|
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2756
2973
|
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2757
2974
|
error,
|
|
2758
|
-
activityId: activity
|
|
2975
|
+
activityId: activity?.id?.href,
|
|
2759
2976
|
activity: message.activity,
|
|
2760
2977
|
recipient: message.identifier
|
|
2761
2978
|
});
|
|
@@ -2764,11 +2981,108 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2764
2981
|
message: String(error)
|
|
2765
2982
|
});
|
|
2766
2983
|
span.end();
|
|
2984
|
+
};
|
|
2985
|
+
let dispatched;
|
|
2986
|
+
let parseInput = void 0;
|
|
2987
|
+
let parseContextLoader = context.contextLoader;
|
|
2988
|
+
try {
|
|
2989
|
+
const hasSignatureField = require_proof.hasSignature(message.activity);
|
|
2990
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
2991
|
+
const parseContext = hasSignatureField ? {
|
|
2992
|
+
...context,
|
|
2993
|
+
contextLoader: require_proof.getNormalizationContextLoader(context.contextLoader)
|
|
2994
|
+
} : {
|
|
2995
|
+
...context,
|
|
2996
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(context.contextLoader)
|
|
2997
|
+
};
|
|
2998
|
+
parseContextLoader = parseContext.contextLoader;
|
|
2999
|
+
let normalizedActivity;
|
|
3000
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
3001
|
+
normalizedActivity = message.normalizedActivity ?? await require_proof.compactJsonLd(message.activity, context.contextLoader);
|
|
3002
|
+
require_proof.assertSafeJsonLd(normalizedActivity);
|
|
3003
|
+
}
|
|
3004
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? require_proof.detachSignature(normalizedActivity) : hasSignatureField ? require_proof.detachSignature(message.activity) : message.activity;
|
|
3005
|
+
activity = await require_actor.Activity.fromJsonLd(parseInput, parseContext);
|
|
3006
|
+
span.setAttribute("activitypub.activity.type", require_actor.getTypeId(activity).href);
|
|
3007
|
+
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
3008
|
+
cacheKey = activity.id == null ? null : [
|
|
3009
|
+
...this.kvPrefixes.activityIdempotence,
|
|
3010
|
+
context.origin,
|
|
3011
|
+
activity.id.href
|
|
3012
|
+
];
|
|
3013
|
+
if (cacheKey != null) {
|
|
3014
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
3015
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
3016
|
+
activityId: activity.id?.href,
|
|
3017
|
+
activity: message.activity,
|
|
3018
|
+
recipient: message.identifier
|
|
3019
|
+
});
|
|
3020
|
+
span.end();
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
3025
|
+
} catch (error) {
|
|
3026
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
3027
|
+
await reportInboxError(error);
|
|
3028
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3029
|
+
error,
|
|
3030
|
+
trial: message.attempt,
|
|
3031
|
+
activityId: null,
|
|
3032
|
+
activity: message.activity,
|
|
3033
|
+
recipient: message.identifier
|
|
3034
|
+
});
|
|
3035
|
+
span.setStatus({
|
|
3036
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3037
|
+
message: String(error)
|
|
3038
|
+
});
|
|
3039
|
+
span.end();
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
if (isPermanentInboxParseError(error)) {
|
|
3043
|
+
await reportInboxError(error);
|
|
3044
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3045
|
+
error,
|
|
3046
|
+
trial: message.attempt,
|
|
3047
|
+
activityId: activity?.id?.href,
|
|
3048
|
+
activity: message.activity,
|
|
3049
|
+
recipient: message.identifier
|
|
3050
|
+
});
|
|
3051
|
+
span.setStatus({
|
|
3052
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3053
|
+
message: String(error)
|
|
3054
|
+
});
|
|
3055
|
+
span.end();
|
|
3056
|
+
return;
|
|
3057
|
+
}
|
|
3058
|
+
await handleRetriableFailure(error);
|
|
3059
|
+
return;
|
|
3060
|
+
}
|
|
3061
|
+
if (dispatched == null) {
|
|
3062
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
3063
|
+
activityId: activity.id?.href,
|
|
3064
|
+
activity: message.activity,
|
|
3065
|
+
recipient: message.identifier,
|
|
3066
|
+
trial: message.attempt
|
|
3067
|
+
});
|
|
3068
|
+
span.setStatus({
|
|
3069
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3070
|
+
message: `Unsupported activity type: ${require_actor.getTypeId(activity).href}`
|
|
3071
|
+
});
|
|
3072
|
+
span.end();
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
const { class: cls, listener } = dispatched;
|
|
3076
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3077
|
+
try {
|
|
3078
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, require_actor.getTypeId(activity).href), activity);
|
|
3079
|
+
} catch (error) {
|
|
3080
|
+
await handleRetriableFailure(error);
|
|
2767
3081
|
return;
|
|
2768
3082
|
}
|
|
2769
3083
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2770
3084
|
logger.info("Activity {activityId} has been processed.", {
|
|
2771
|
-
activityId: activity
|
|
3085
|
+
activityId: activity?.id?.href,
|
|
2772
3086
|
activity: message.activity,
|
|
2773
3087
|
recipient: message.identifier
|
|
2774
3088
|
});
|
|
@@ -3090,16 +3404,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3090
3404
|
onNotAcceptable
|
|
3091
3405
|
});
|
|
3092
3406
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier ?? route.values.handle }) });
|
|
3093
|
-
case "sharedInbox":
|
|
3407
|
+
case "sharedInbox": {
|
|
3094
3408
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3095
3409
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3096
3410
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity || "handle" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3097
3411
|
}
|
|
3098
3412
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3413
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3414
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
3099
3415
|
return await handleInbox(request, {
|
|
3100
3416
|
recipient: route.values.identifier ?? route.values.handle ?? null,
|
|
3101
3417
|
context,
|
|
3102
|
-
inboxContextFactory
|
|
3418
|
+
inboxContextFactory,
|
|
3103
3419
|
kv: this.kv,
|
|
3104
3420
|
kvPrefixes: this.kvPrefixes,
|
|
3105
3421
|
queue: this.inboxQueue,
|
|
@@ -3112,6 +3428,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3112
3428
|
tracerProvider: this.tracerProvider,
|
|
3113
3429
|
idempotencyStrategy: this.idempotencyStrategy
|
|
3114
3430
|
});
|
|
3431
|
+
}
|
|
3115
3432
|
case "following": return await handleCollection(request, {
|
|
3116
3433
|
name: "following",
|
|
3117
3434
|
identifier: route.values.identifier ?? route.values.handle,
|
|
@@ -3862,6 +4179,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3862
4179
|
const routeResult = await routeActivity({
|
|
3863
4180
|
context: this,
|
|
3864
4181
|
json,
|
|
4182
|
+
ldSignatureVerified: false,
|
|
3865
4183
|
activity,
|
|
3866
4184
|
recipient,
|
|
3867
4185
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -3960,6 +4278,14 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
3960
4278
|
};
|
|
3961
4279
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
3962
4280
|
recipient;
|
|
4281
|
+
/**
|
|
4282
|
+
* The original received activity payload.
|
|
4283
|
+
*
|
|
4284
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4285
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4286
|
+
* third-party signatures/proofs remain intact.
|
|
4287
|
+
* @internal
|
|
4288
|
+
*/
|
|
3963
4289
|
activity;
|
|
3964
4290
|
activityId;
|
|
3965
4291
|
activityType;
|