@fedify/fedify 2.0.17 → 2.0.19
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-Dgk0oJse.mjs → builder-DpMJ796G.mjs} +3 -3
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{context-BzRJ49gL.d.cts → context-CJZHWLmz.d.cts} +48 -6
- package/dist/{context-CdJ9wAQa.d.ts → context-DnsFj3yK.d.ts} +48 -6
- package/dist/{deno-Cb0U4mYY.mjs → deno-OvlgTe2z.mjs} +1 -1
- package/dist/{docloader-BtgBOjR2.mjs → docloader-LahMFnq1.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +1358 -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 +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/send.test.mjs +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-CkpjqreM.mjs → http-BGqCzFFW.mjs} +2 -2
- package/dist/{http-C8fyMUjD.cjs → http-B_rBGJzj.cjs} +1 -1
- package/dist/{http-DOir4i5c.js → http-GMhBzdUg.js} +1 -1
- package/dist/{inbox-VNZAN2rq.mjs → inbox-B0rurFqy.mjs} +7 -4
- package/dist/{key-jLdTQH2f.mjs → key-v_BpXvjh.mjs} +1 -1
- package/dist/{kv-cache-D7YHL8kZ.cjs → kv-cache-B-QyKmN6.cjs} +1 -1
- package/dist/{kv-cache-BT1ZahAh.js → kv-cache-DIgdPeX1.js} +1 -1
- package/dist/ld-DHdnBuQl.mjs +550 -0
- package/dist/{middleware-Bua1eJKj.mjs → middleware-B0dEe1fJ.mjs} +309 -76
- package/dist/{middleware-ChZir5hz.mjs → middleware-D-GLLKcV.mjs} +1 -1
- package/dist/{middleware-BIaxjP-q.cjs → middleware-DQE7csTG.cjs} +399 -73
- package/dist/{middleware-o4he3VG2.js → middleware-DwMR-UJ5.js} +396 -71
- package/dist/{middleware-BmYsY7pr.cjs → middleware-zX2hBOnb.cjs} +1 -1
- package/dist/{mod-CKkpvznG.d.cts → mod-43DJyETz.d.cts} +1 -1
- package/dist/{mod-Kzr52ns8.d.ts → mod-COgmn-UO.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +2 -2
- package/dist/mod.d.ts +2 -2
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-9JLKNjOK.mjs → owner-B8gYOXYm.mjs} +2 -2
- package/dist/{proof-Bds_rOyf.js → proof-D2j9J3Sr.js} +298 -4
- package/dist/{proof-CVNf-KlO.mjs → proof-DSGV862v.mjs} +2 -2
- package/dist/{proof-DWK4MOe5.cjs → proof-RC4Q3Ozn.cjs} +345 -3
- package/dist/{send-j6vHPA3l.mjs → send-myUWQlOg.mjs} +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +558 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +1 -1
- package/dist/temporal-D4MiakbY.mjs +95 -0
- package/dist/testing/mod.d.mts +48 -6
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
- package/dist/ld-C48i1Mdp.mjs +0 -256
- /package/dist/{retry-Ddbq3AcK.mjs → retry-B_E3V_Dx.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-B_rBGJzj.cjs");
|
|
6
|
+
const require_proof = require("./proof-RC4Q3Ozn.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-B-QyKmN6.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);
|
|
@@ -330,7 +335,7 @@ var FederationBuilderImpl = class {
|
|
|
330
335
|
this.collectionTypeIds = {};
|
|
331
336
|
}
|
|
332
337
|
async build(options) {
|
|
333
|
-
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-
|
|
338
|
+
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-zX2hBOnb.cjs"));
|
|
334
339
|
const f = new FederationImpl(options);
|
|
335
340
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
336
341
|
f.router = this.router.clone();
|
|
@@ -959,7 +964,123 @@ function acceptsJsonLd(request) {
|
|
|
959
964
|
return types.includes("application/activity+json") || types.includes("application/ld+json") || types.includes("application/json");
|
|
960
965
|
}
|
|
961
966
|
//#endregion
|
|
967
|
+
//#region src/federation/temporal.ts
|
|
968
|
+
function isPlainObject(value) {
|
|
969
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
970
|
+
}
|
|
971
|
+
function normalizeDateTimeLiteral(value) {
|
|
972
|
+
return value.substring(19).match(/[Z+-]/) ? value : value + "Z";
|
|
973
|
+
}
|
|
974
|
+
function isMalformedDateTimeLiteral(value) {
|
|
975
|
+
if (typeof value !== "string") return false;
|
|
976
|
+
try {
|
|
977
|
+
Temporal.Instant.from(normalizeDateTimeLiteral(value));
|
|
978
|
+
return false;
|
|
979
|
+
} catch {
|
|
980
|
+
return true;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function isMalformedDurationLiteral(value) {
|
|
984
|
+
if (typeof value !== "string") return false;
|
|
985
|
+
try {
|
|
986
|
+
Temporal.Duration.from(value);
|
|
987
|
+
return false;
|
|
988
|
+
} catch {
|
|
989
|
+
return true;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
const TEMPORAL_DATE_TIME_IRIS = new Set([
|
|
993
|
+
"https://www.w3.org/ns/activitystreams#deleted",
|
|
994
|
+
"https://www.w3.org/ns/activitystreams#endTime",
|
|
995
|
+
"https://www.w3.org/ns/activitystreams#published",
|
|
996
|
+
"https://www.w3.org/ns/activitystreams#startTime",
|
|
997
|
+
"https://www.w3.org/ns/activitystreams#updated",
|
|
998
|
+
"http://purl.org/dc/terms/created",
|
|
999
|
+
"https://w3id.org/security#created"
|
|
1000
|
+
]);
|
|
1001
|
+
const TEMPORAL_DURATION_IRIS = new Set(["https://www.w3.org/ns/activitystreams#duration"]);
|
|
1002
|
+
const QUESTION_CLOSED_IRI = "https://www.w3.org/ns/activitystreams#closed";
|
|
1003
|
+
const XSD_DATE_TIME_IRI = "http://www.w3.org/2001/XMLSchema#dateTime";
|
|
1004
|
+
function hasMalformedExpandedDateTimeLiteral(value) {
|
|
1005
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDateTimeLiteral);
|
|
1006
|
+
return isPlainObject(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1007
|
+
}
|
|
1008
|
+
function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
1009
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedQuestionClosedLiteral);
|
|
1010
|
+
if (!isPlainObject(value) || !("@value" in value)) return false;
|
|
1011
|
+
const literal = value["@value"];
|
|
1012
|
+
if (typeof literal === "boolean") return false;
|
|
1013
|
+
if (typeof literal !== "string") return false;
|
|
1014
|
+
if (value["@type"] !== XSD_DATE_TIME_IRI) return false;
|
|
1015
|
+
if (new Date(literal).toString() === "Invalid Date") return false;
|
|
1016
|
+
return isMalformedDateTimeLiteral(literal);
|
|
1017
|
+
}
|
|
1018
|
+
function hasMalformedExpandedDurationLiteral(value) {
|
|
1019
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDurationLiteral);
|
|
1020
|
+
return isPlainObject(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1021
|
+
}
|
|
1022
|
+
function hasMalformedKnownTemporalLiteralInternal(value, visited) {
|
|
1023
|
+
if (Array.isArray(value)) return value.some((item) => hasMalformedKnownTemporalLiteralInternal(item, visited));
|
|
1024
|
+
if (!isPlainObject(value)) return false;
|
|
1025
|
+
if (visited.has(value)) return false;
|
|
1026
|
+
visited.add(value);
|
|
1027
|
+
if ("@value" in value) return false;
|
|
1028
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1029
|
+
if (TEMPORAL_DATE_TIME_IRIS.has(key)) {
|
|
1030
|
+
if (hasMalformedExpandedDateTimeLiteral(child)) return true;
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
if (key === QUESTION_CLOSED_IRI) {
|
|
1034
|
+
if (hasMalformedExpandedQuestionClosedLiteral(child)) return true;
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
if (TEMPORAL_DURATION_IRIS.has(key)) {
|
|
1038
|
+
if (hasMalformedExpandedDurationLiteral(child)) return true;
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
if (hasMalformedKnownTemporalLiteralInternal(child, visited)) return true;
|
|
1042
|
+
}
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
async function hasMalformedKnownTemporalLiteral(value, contextLoader) {
|
|
1046
|
+
try {
|
|
1047
|
+
return hasMalformedKnownTemporalLiteralInternal(await _fedify_vocab_runtime_jsonld.default.expand(value, {
|
|
1048
|
+
documentLoader: require_proof.getNormalizationContextLoader(contextLoader),
|
|
1049
|
+
keepFreeFloatingNodes: true
|
|
1050
|
+
}), /* @__PURE__ */ new Set());
|
|
1051
|
+
} catch {
|
|
1052
|
+
return false;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
//#endregion
|
|
962
1056
|
//#region src/federation/handler.ts
|
|
1057
|
+
const rawInboxContextFactorySymbol = Symbol("fedify.rawInboxContextFactory");
|
|
1058
|
+
function isRemoteContextLoadingFailure$1(error) {
|
|
1059
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
1060
|
+
}
|
|
1061
|
+
function isPermanentRemoteContextError$1(error) {
|
|
1062
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
1063
|
+
const details = error.details;
|
|
1064
|
+
if (details?.code === "invalid remote context") return true;
|
|
1065
|
+
return isRemoteContextLoadingFailure$1(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
1066
|
+
}
|
|
1067
|
+
function isInvalidJsonLdError(error) {
|
|
1068
|
+
if (!(error instanceof Error)) return false;
|
|
1069
|
+
const name = error.name;
|
|
1070
|
+
return name === "UnsafeJsonLdError" || error instanceof require_proof.InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
|
|
1071
|
+
}
|
|
1072
|
+
function isValidationTypeError(error) {
|
|
1073
|
+
return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || require_proof.isInvalidUrlTypeError(error));
|
|
1074
|
+
}
|
|
1075
|
+
function isPermanentActivityParseError(error) {
|
|
1076
|
+
return isInvalidJsonLdError(error) || isValidationTypeError(error);
|
|
1077
|
+
}
|
|
1078
|
+
function hasHttpSignatureHeaders(request) {
|
|
1079
|
+
return request.headers.has("Signature") || request.headers.has("Signature-Input");
|
|
1080
|
+
}
|
|
1081
|
+
function hasObjectIntegrityProof(json) {
|
|
1082
|
+
return typeof json === "object" && json != null && "proof" in json;
|
|
1083
|
+
}
|
|
963
1084
|
/**
|
|
964
1085
|
* Handles an actor request.
|
|
965
1086
|
* @template TContextData The context data to pass to the context.
|
|
@@ -1279,35 +1400,120 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1279
1400
|
});
|
|
1280
1401
|
}
|
|
1281
1402
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1403
|
+
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1404
|
+
const hasLdSignature = require_proof.hasSignature(json);
|
|
1405
|
+
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
1406
|
+
let deferredLdSignatureError = void 0;
|
|
1407
|
+
const respondInvalidActivity = async (error) => {
|
|
1408
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
1409
|
+
recipient,
|
|
1410
|
+
activity: json,
|
|
1411
|
+
error
|
|
1289
1412
|
});
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1413
|
+
try {
|
|
1414
|
+
await inboxErrorHandler?.(ctx, error);
|
|
1415
|
+
} catch (error) {
|
|
1416
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1417
|
+
error,
|
|
1418
|
+
activity: json,
|
|
1419
|
+
recipient
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
span.setStatus({
|
|
1423
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
1424
|
+
message: `Failed to parse activity:\n${error}`
|
|
1425
|
+
});
|
|
1426
|
+
return new Response("Invalid activity.", {
|
|
1427
|
+
status: 400,
|
|
1428
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1429
|
+
});
|
|
1430
|
+
};
|
|
1431
|
+
let compactedJson = json;
|
|
1432
|
+
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
1433
|
+
let ldSigVerified = false;
|
|
1434
|
+
if (hasLdSignature) {
|
|
1435
|
+
try {
|
|
1436
|
+
compactedJson = await require_proof.compactJsonLd(json, ctx.contextLoader);
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
if (isInvalidJsonLdError(error)) {
|
|
1439
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1440
|
+
recipient,
|
|
1441
|
+
error
|
|
1442
|
+
});
|
|
1443
|
+
return new Response("Invalid JSON-LD.", {
|
|
1444
|
+
status: 400,
|
|
1445
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1449
|
+
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
1450
|
+
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
1293
1451
|
recipient,
|
|
1294
1452
|
error
|
|
1295
1453
|
});
|
|
1296
|
-
return new Response("Invalid JSON-LD.", {
|
|
1297
|
-
status: 400,
|
|
1298
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1299
|
-
});
|
|
1300
1454
|
}
|
|
1301
|
-
|
|
1455
|
+
if (compactedJson !== json) {
|
|
1456
|
+
compactedJsonWithoutSig = require_proof.detachSignature(compactedJson);
|
|
1457
|
+
try {
|
|
1458
|
+
ldSigVerified = await require_proof.verifyCompactJsonLd(compactedJson, {
|
|
1459
|
+
contextLoader: ctx.contextLoader,
|
|
1460
|
+
documentLoader: ctx.documentLoader,
|
|
1461
|
+
keyCache,
|
|
1462
|
+
tracerProvider
|
|
1463
|
+
});
|
|
1464
|
+
} catch (error) {
|
|
1465
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1466
|
+
if (isInvalidJsonLdError(error)) {
|
|
1467
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1468
|
+
recipient,
|
|
1469
|
+
error
|
|
1470
|
+
});
|
|
1471
|
+
return new Response("Invalid JSON-LD.", {
|
|
1472
|
+
status: 400,
|
|
1473
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1477
|
+
if (!skipSignatureVerification) try {
|
|
1478
|
+
await _fedify_vocab.Object.fromJsonLd(compactedJson, {
|
|
1479
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader),
|
|
1480
|
+
documentLoader: ctx.documentLoader,
|
|
1481
|
+
tracerProvider
|
|
1482
|
+
});
|
|
1483
|
+
} catch (parseError) {
|
|
1484
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(parseError);
|
|
1485
|
+
if (isInvalidJsonLdError(parseError)) {
|
|
1486
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1487
|
+
recipient,
|
|
1488
|
+
error: parseError
|
|
1489
|
+
});
|
|
1490
|
+
return new Response("Invalid JSON-LD.", {
|
|
1491
|
+
status: 400,
|
|
1492
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1495
|
+
deferredLdSignatureError = parseError;
|
|
1496
|
+
}
|
|
1497
|
+
ldSigVerified = false;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1302
1500
|
}
|
|
1303
|
-
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1304
1501
|
let activity = null;
|
|
1305
1502
|
if (ldSigVerified) {
|
|
1306
1503
|
logger.debug("Linked Data Signatures are verified.", {
|
|
1307
1504
|
recipient,
|
|
1308
1505
|
json
|
|
1309
1506
|
});
|
|
1310
|
-
|
|
1507
|
+
try {
|
|
1508
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
1509
|
+
...ctx,
|
|
1510
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader)
|
|
1511
|
+
});
|
|
1512
|
+
} catch (error) {
|
|
1513
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1514
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1515
|
+
return await respondInvalidActivity(error);
|
|
1516
|
+
}
|
|
1311
1517
|
} else {
|
|
1312
1518
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
1313
1519
|
recipient,
|
|
@@ -1315,12 +1521,21 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1315
1521
|
});
|
|
1316
1522
|
try {
|
|
1317
1523
|
activity = await require_proof.verifyObject(_fedify_vocab.Activity, jsonWithoutSig, {
|
|
1318
|
-
contextLoader: ctx.contextLoader,
|
|
1524
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1319
1525
|
documentLoader: ctx.documentLoader,
|
|
1320
1526
|
keyCache,
|
|
1321
1527
|
tracerProvider
|
|
1322
1528
|
});
|
|
1323
1529
|
} catch (error) {
|
|
1530
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1531
|
+
if (deferredLdSignatureError != null) {
|
|
1532
|
+
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
1533
|
+
recipient,
|
|
1534
|
+
error
|
|
1535
|
+
});
|
|
1536
|
+
activity = null;
|
|
1537
|
+
}
|
|
1538
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1324
1539
|
logger.error("Failed to parse activity:\n{error}", {
|
|
1325
1540
|
recipient,
|
|
1326
1541
|
activity: json,
|
|
@@ -1364,6 +1579,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1364
1579
|
tracerProvider
|
|
1365
1580
|
});
|
|
1366
1581
|
if (key == null) {
|
|
1582
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1367
1583
|
logger.error("Failed to verify the request's HTTP Signatures.", { recipient });
|
|
1368
1584
|
span.setStatus({
|
|
1369
1585
|
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
@@ -1376,7 +1592,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1376
1592
|
} else logger.debug("HTTP Signatures are verified.", { recipient });
|
|
1377
1593
|
httpSigKey = key;
|
|
1378
1594
|
}
|
|
1379
|
-
|
|
1595
|
+
try {
|
|
1596
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(jsonWithoutSig, {
|
|
1597
|
+
...ctx,
|
|
1598
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1599
|
+
});
|
|
1600
|
+
} catch (error) {
|
|
1601
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1602
|
+
return await respondInvalidActivity(error);
|
|
1603
|
+
}
|
|
1380
1604
|
}
|
|
1381
1605
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1382
1606
|
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
@@ -1388,6 +1612,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1388
1612
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1389
1613
|
});
|
|
1390
1614
|
if (httpSigKey != null && !await require_proof.doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1615
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1391
1616
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1392
1617
|
activity: json,
|
|
1393
1618
|
recipient,
|
|
@@ -1406,10 +1631,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1406
1631
|
const routeResult = await routeActivity({
|
|
1407
1632
|
context: ctx,
|
|
1408
1633
|
json,
|
|
1634
|
+
originalJson: json,
|
|
1635
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
1636
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1409
1637
|
activity,
|
|
1410
1638
|
recipient,
|
|
1411
1639
|
inboxListeners,
|
|
1412
1640
|
inboxContextFactory,
|
|
1641
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1413
1642
|
inboxErrorHandler,
|
|
1414
1643
|
kv,
|
|
1415
1644
|
kvPrefixes,
|
|
@@ -2250,6 +2479,18 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2250
2479
|
}
|
|
2251
2480
|
//#endregion
|
|
2252
2481
|
//#region src/federation/middleware.ts
|
|
2482
|
+
function isRemoteContextLoadingFailure(error) {
|
|
2483
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
2484
|
+
}
|
|
2485
|
+
function isPermanentRemoteContextError(error) {
|
|
2486
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
2487
|
+
const details = error.details;
|
|
2488
|
+
if (details?.code === "invalid remote context") return true;
|
|
2489
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
2490
|
+
}
|
|
2491
|
+
function isPermanentInboxParseError(error) {
|
|
2492
|
+
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));
|
|
2493
|
+
}
|
|
2253
2494
|
/**
|
|
2254
2495
|
* Create a new {@link Federation} instance.
|
|
2255
2496
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2627,7 +2868,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2627
2868
|
}
|
|
2628
2869
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
2629
2870
|
}
|
|
2630
|
-
async #listenInboxMessage(ctxData, message,
|
|
2871
|
+
async #listenInboxMessage(ctxData, message, _span) {
|
|
2631
2872
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
2632
2873
|
"fedify",
|
|
2633
2874
|
"federation",
|
|
@@ -2640,60 +2881,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2640
2881
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2641
2882
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2642
2883
|
}
|
|
2643
|
-
const activity = await _fedify_vocab.Activity.fromJsonLd(message.activity, context);
|
|
2644
|
-
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
2645
|
-
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2646
|
-
const cacheKey = activity.id == null ? null : [
|
|
2647
|
-
...this.kvPrefixes.activityIdempotence,
|
|
2648
|
-
context.origin,
|
|
2649
|
-
activity.id.href
|
|
2650
|
-
];
|
|
2651
|
-
if (cacheKey != null) {
|
|
2652
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
2653
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
2654
|
-
activityId: activity.id?.href,
|
|
2655
|
-
activity: message.activity,
|
|
2656
|
-
recipient: message.identifier
|
|
2657
|
-
});
|
|
2658
|
-
return;
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
2884
|
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: _opentelemetry_api.SpanKind.INTERNAL }, async (span) => {
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
activityId: activity.id?.href,
|
|
2666
|
-
activity: message.activity,
|
|
2667
|
-
recipient: message.identifier,
|
|
2668
|
-
trial: message.attempt
|
|
2669
|
-
});
|
|
2670
|
-
span.setStatus({
|
|
2671
|
-
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
2672
|
-
message: `Unsupported activity type: ${(0, _fedify_vocab.getTypeId)(activity).href}`
|
|
2673
|
-
});
|
|
2674
|
-
span.end();
|
|
2675
|
-
return;
|
|
2676
|
-
}
|
|
2677
|
-
const { class: cls, listener } = dispatched;
|
|
2678
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2679
|
-
try {
|
|
2680
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
2681
|
-
} catch (error) {
|
|
2885
|
+
let activity = null;
|
|
2886
|
+
let cacheKey = null;
|
|
2887
|
+
const reportInboxError = async (error) => {
|
|
2682
2888
|
try {
|
|
2683
2889
|
await this.inboxErrorHandler?.(context, error);
|
|
2684
2890
|
} catch (error) {
|
|
2685
2891
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2686
2892
|
error,
|
|
2687
2893
|
trial: message.attempt,
|
|
2688
|
-
activityId: activity
|
|
2894
|
+
activityId: activity?.id?.href,
|
|
2689
2895
|
activity: message.activity,
|
|
2690
2896
|
recipient: message.identifier
|
|
2691
2897
|
});
|
|
2692
2898
|
}
|
|
2899
|
+
};
|
|
2900
|
+
const handleRetriableFailure = async (error) => {
|
|
2901
|
+
await reportInboxError(error);
|
|
2693
2902
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2694
2903
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2695
2904
|
error,
|
|
2696
|
-
activityId: activity
|
|
2905
|
+
activityId: activity?.id?.href,
|
|
2697
2906
|
activity: message.activity,
|
|
2698
2907
|
recipient: message.identifier
|
|
2699
2908
|
});
|
|
@@ -2712,17 +2921,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2712
2921
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2713
2922
|
error,
|
|
2714
2923
|
attempt: message.attempt,
|
|
2715
|
-
activityId: activity
|
|
2924
|
+
activityId: activity?.id?.href,
|
|
2716
2925
|
activity: message.activity,
|
|
2717
2926
|
recipient: message.identifier
|
|
2718
2927
|
});
|
|
2928
|
+
if (this.inboxQueue == null) {
|
|
2929
|
+
span.setStatus({
|
|
2930
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
2931
|
+
message: String(error)
|
|
2932
|
+
});
|
|
2933
|
+
span.end();
|
|
2934
|
+
throw error;
|
|
2935
|
+
}
|
|
2719
2936
|
await this.inboxQueue?.enqueue({
|
|
2720
2937
|
...message,
|
|
2721
2938
|
attempt: message.attempt + 1
|
|
2722
2939
|
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2723
2940
|
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2724
2941
|
error,
|
|
2725
|
-
activityId: activity
|
|
2942
|
+
activityId: activity?.id?.href,
|
|
2726
2943
|
activity: message.activity,
|
|
2727
2944
|
recipient: message.identifier
|
|
2728
2945
|
});
|
|
@@ -2731,11 +2948,108 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2731
2948
|
message: String(error)
|
|
2732
2949
|
});
|
|
2733
2950
|
span.end();
|
|
2951
|
+
};
|
|
2952
|
+
let dispatched;
|
|
2953
|
+
let parseInput = void 0;
|
|
2954
|
+
let parseContextLoader = context.contextLoader;
|
|
2955
|
+
try {
|
|
2956
|
+
const hasSignatureField = require_proof.hasSignature(message.activity);
|
|
2957
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
2958
|
+
const parseContext = hasSignatureField ? {
|
|
2959
|
+
...context,
|
|
2960
|
+
contextLoader: require_proof.getNormalizationContextLoader(context.contextLoader)
|
|
2961
|
+
} : {
|
|
2962
|
+
...context,
|
|
2963
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(context.contextLoader)
|
|
2964
|
+
};
|
|
2965
|
+
parseContextLoader = parseContext.contextLoader;
|
|
2966
|
+
let normalizedActivity;
|
|
2967
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
2968
|
+
normalizedActivity = message.normalizedActivity ?? await require_proof.compactJsonLd(message.activity, context.contextLoader);
|
|
2969
|
+
require_proof.assertSafeJsonLd(normalizedActivity);
|
|
2970
|
+
}
|
|
2971
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? require_proof.detachSignature(normalizedActivity) : hasSignatureField ? require_proof.detachSignature(message.activity) : message.activity;
|
|
2972
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(parseInput, parseContext);
|
|
2973
|
+
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
2974
|
+
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2975
|
+
cacheKey = activity.id == null ? null : [
|
|
2976
|
+
...this.kvPrefixes.activityIdempotence,
|
|
2977
|
+
context.origin,
|
|
2978
|
+
activity.id.href
|
|
2979
|
+
];
|
|
2980
|
+
if (cacheKey != null) {
|
|
2981
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
2982
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
2983
|
+
activityId: activity.id?.href,
|
|
2984
|
+
activity: message.activity,
|
|
2985
|
+
recipient: message.identifier
|
|
2986
|
+
});
|
|
2987
|
+
span.end();
|
|
2988
|
+
return;
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
2992
|
+
} catch (error) {
|
|
2993
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
2994
|
+
await reportInboxError(error);
|
|
2995
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
2996
|
+
error,
|
|
2997
|
+
trial: message.attempt,
|
|
2998
|
+
activityId: null,
|
|
2999
|
+
activity: message.activity,
|
|
3000
|
+
recipient: message.identifier
|
|
3001
|
+
});
|
|
3002
|
+
span.setStatus({
|
|
3003
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3004
|
+
message: String(error)
|
|
3005
|
+
});
|
|
3006
|
+
span.end();
|
|
3007
|
+
return;
|
|
3008
|
+
}
|
|
3009
|
+
if (isPermanentInboxParseError(error)) {
|
|
3010
|
+
await reportInboxError(error);
|
|
3011
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3012
|
+
error,
|
|
3013
|
+
trial: message.attempt,
|
|
3014
|
+
activityId: activity?.id?.href,
|
|
3015
|
+
activity: message.activity,
|
|
3016
|
+
recipient: message.identifier
|
|
3017
|
+
});
|
|
3018
|
+
span.setStatus({
|
|
3019
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3020
|
+
message: String(error)
|
|
3021
|
+
});
|
|
3022
|
+
span.end();
|
|
3023
|
+
return;
|
|
3024
|
+
}
|
|
3025
|
+
await handleRetriableFailure(error);
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
3028
|
+
if (dispatched == null) {
|
|
3029
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
3030
|
+
activityId: activity.id?.href,
|
|
3031
|
+
activity: message.activity,
|
|
3032
|
+
recipient: message.identifier,
|
|
3033
|
+
trial: message.attempt
|
|
3034
|
+
});
|
|
3035
|
+
span.setStatus({
|
|
3036
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3037
|
+
message: `Unsupported activity type: ${(0, _fedify_vocab.getTypeId)(activity).href}`
|
|
3038
|
+
});
|
|
3039
|
+
span.end();
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
const { class: cls, listener } = dispatched;
|
|
3043
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3044
|
+
try {
|
|
3045
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
3046
|
+
} catch (error) {
|
|
3047
|
+
await handleRetriableFailure(error);
|
|
2734
3048
|
return;
|
|
2735
3049
|
}
|
|
2736
3050
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2737
3051
|
logger.info("Activity {activityId} has been processed.", {
|
|
2738
|
-
activityId: activity
|
|
3052
|
+
activityId: activity?.id?.href,
|
|
2739
3053
|
activity: message.activity,
|
|
2740
3054
|
recipient: message.identifier
|
|
2741
3055
|
});
|
|
@@ -3081,16 +3395,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3081
3395
|
onNotFound
|
|
3082
3396
|
});
|
|
3083
3397
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
|
|
3084
|
-
case "sharedInbox":
|
|
3398
|
+
case "sharedInbox": {
|
|
3085
3399
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3086
3400
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3087
3401
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3088
3402
|
}
|
|
3089
3403
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3404
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3405
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
3090
3406
|
return await handleInbox(request, {
|
|
3091
3407
|
recipient: route.values.identifier ?? null,
|
|
3092
3408
|
context,
|
|
3093
|
-
inboxContextFactory
|
|
3409
|
+
inboxContextFactory,
|
|
3094
3410
|
kv: this.kv,
|
|
3095
3411
|
kvPrefixes: this.kvPrefixes,
|
|
3096
3412
|
queue: this.inboxQueue,
|
|
@@ -3103,6 +3419,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3103
3419
|
tracerProvider: this.tracerProvider,
|
|
3104
3420
|
idempotencyStrategy: this.idempotencyStrategy
|
|
3105
3421
|
});
|
|
3422
|
+
}
|
|
3106
3423
|
case "following": return await handleCollection(request, {
|
|
3107
3424
|
name: "following",
|
|
3108
3425
|
identifier: route.values.identifier,
|
|
@@ -3778,6 +4095,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3778
4095
|
const routeResult = await routeActivity({
|
|
3779
4096
|
context: this,
|
|
3780
4097
|
json,
|
|
4098
|
+
ldSignatureVerified: false,
|
|
3781
4099
|
activity,
|
|
3782
4100
|
recipient,
|
|
3783
4101
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -3876,6 +4194,14 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
3876
4194
|
};
|
|
3877
4195
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
3878
4196
|
recipient;
|
|
4197
|
+
/**
|
|
4198
|
+
* The original received activity payload.
|
|
4199
|
+
*
|
|
4200
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4201
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4202
|
+
* third-party signatures/proofs remain intact.
|
|
4203
|
+
* @internal
|
|
4204
|
+
*/
|
|
3879
4205
|
activity;
|
|
3880
4206
|
activityId;
|
|
3881
4207
|
activityType;
|