@fedify/fedify 2.2.3-dev.1098 → 2.2.4
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-mqtih91o.mjs → builder-Dg2hGWk5.mjs} +2 -2
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{context-BPMgyX7m.d.ts → context-BU-1O90h.d.ts} +48 -6
- package/dist/{context-DwkhwUX9.d.cts → context-DVA8wHZ0.d.cts} +48 -6
- package/dist/{deno-CziVFvS6.mjs → deno-_3m2phl-.mjs} +1 -1
- package/dist/{docloader-fI9DeYyB.mjs → docloader-Cq_3E56G.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +1363 -43
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/middleware.test.mjs +1584 -80
- 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-D8qsXrUS.js → http-BauEA3uU.js} +1 -1
- package/dist/{http-BDCGf4Ac.mjs → http-C6206Ne5.mjs} +2 -2
- package/dist/{http-kPc328Pc.cjs → http-CzvQu1wC.cjs} +1 -1
- package/dist/{key-D3TgMhcs.mjs → key-ckqyhgo3.mjs} +1 -1
- package/dist/{kv-cache-zxW74Wfd.cjs → kv-cache-10y07lRd.cjs} +1 -1
- package/dist/{kv-cache-D_eVhctK.js → kv-cache-DLwx2oCr.js} +1 -1
- package/dist/ld-B3BrUVFK.mjs +573 -0
- package/dist/{middleware-2gmMVy8b.mjs → middleware-Bn8hcuAb.mjs} +314 -78
- package/dist/{middleware-BuOXw_hM.cjs → middleware-CBNvWoWG.cjs} +1 -1
- package/dist/{middleware-xR9KxICq.cjs → middleware-Cppn0oGi.cjs} +399 -73
- package/dist/{middleware-gXlDLkok.js → middleware-DkSEt8CX.js} +396 -71
- package/dist/{middleware-CfaiRKQ9.mjs → middleware-_5uCEul-.mjs} +1 -1
- package/dist/{mod-CNAHY39V.d.ts → mod-BVt6iTmH.d.ts} +1 -1
- package/dist/{mod-Bi6WOdti.d.cts → mod-q-NFLW6B.d.cts} +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-DBSV2TSl.mjs → owner-BIrHaRRj.mjs} +2 -2
- package/dist/{proof-tz91vdtN.mjs → proof-B9P5A7RZ.mjs} +2 -2
- package/dist/{proof-CZDkoeWG.cjs → proof-Bxo0UtfN.cjs} +351 -3
- package/dist/{proof-z93OkIov.js → proof-erB_wSQi.js} +298 -4
- package/dist/{send-CNjG31rJ.mjs → send-7FY-qDY3.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-CuaJdDfw.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 +5 -5
- package/dist/ld-D_u8mdpv.mjs +0 -279
- /package/dist/{retry-bMXBL97A.mjs → retry-v_sGLH1d.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-CzvQu1wC.cjs");
|
|
6
|
+
const require_proof = require("./proof-Bxo0UtfN.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-10y07lRd.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/activity-listener.ts
|
|
@@ -210,7 +212,7 @@ var FederationBuilderImpl = class {
|
|
|
210
212
|
this.collectionTypeIds = {};
|
|
211
213
|
}
|
|
212
214
|
async build(options) {
|
|
213
|
-
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-
|
|
215
|
+
const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-CBNvWoWG.cjs"));
|
|
214
216
|
const f = new FederationImpl(options);
|
|
215
217
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
216
218
|
f.router = this.router.clone();
|
|
@@ -770,7 +772,7 @@ async function buildCollectionSynchronizationHeader(collectionId, actorIds) {
|
|
|
770
772
|
}
|
|
771
773
|
//#endregion
|
|
772
774
|
//#region src/federation/inbox.ts
|
|
773
|
-
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
775
|
+
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
774
776
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
775
777
|
"fedify",
|
|
776
778
|
"federation",
|
|
@@ -827,7 +829,9 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
827
829
|
type: "inbox",
|
|
828
830
|
id: crypto.randomUUID(),
|
|
829
831
|
baseUrl: ctx.origin,
|
|
830
|
-
activity: json,
|
|
832
|
+
activity: originalJson ?? json,
|
|
833
|
+
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
834
|
+
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
831
835
|
identifier: recipient,
|
|
832
836
|
attempt: 0,
|
|
833
837
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -871,7 +875,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
871
875
|
const { class: cls, listener } = dispatched;
|
|
872
876
|
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
873
877
|
try {
|
|
874
|
-
|
|
878
|
+
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
879
|
+
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity?.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
875
880
|
} catch (error) {
|
|
876
881
|
try {
|
|
877
882
|
await inboxErrorHandler?.(ctx, error);
|
|
@@ -1062,7 +1067,123 @@ function acceptsJsonLd(request) {
|
|
|
1062
1067
|
return types.includes("application/activity+json") || types.includes("application/ld+json") || types.includes("application/json");
|
|
1063
1068
|
}
|
|
1064
1069
|
//#endregion
|
|
1070
|
+
//#region src/federation/temporal.ts
|
|
1071
|
+
function isPlainObject(value) {
|
|
1072
|
+
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
1073
|
+
}
|
|
1074
|
+
function normalizeDateTimeLiteral(value) {
|
|
1075
|
+
return value.substring(19).match(/[Z+-]/) ? value : value + "Z";
|
|
1076
|
+
}
|
|
1077
|
+
function isMalformedDateTimeLiteral(value) {
|
|
1078
|
+
if (typeof value !== "string") return false;
|
|
1079
|
+
try {
|
|
1080
|
+
Temporal.Instant.from(normalizeDateTimeLiteral(value));
|
|
1081
|
+
return false;
|
|
1082
|
+
} catch {
|
|
1083
|
+
return true;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
function isMalformedDurationLiteral(value) {
|
|
1087
|
+
if (typeof value !== "string") return false;
|
|
1088
|
+
try {
|
|
1089
|
+
Temporal.Duration.from(value);
|
|
1090
|
+
return false;
|
|
1091
|
+
} catch {
|
|
1092
|
+
return true;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
const TEMPORAL_DATE_TIME_IRIS = new Set([
|
|
1096
|
+
"https://www.w3.org/ns/activitystreams#deleted",
|
|
1097
|
+
"https://www.w3.org/ns/activitystreams#endTime",
|
|
1098
|
+
"https://www.w3.org/ns/activitystreams#published",
|
|
1099
|
+
"https://www.w3.org/ns/activitystreams#startTime",
|
|
1100
|
+
"https://www.w3.org/ns/activitystreams#updated",
|
|
1101
|
+
"http://purl.org/dc/terms/created",
|
|
1102
|
+
"https://w3id.org/security#created"
|
|
1103
|
+
]);
|
|
1104
|
+
const TEMPORAL_DURATION_IRIS = new Set(["https://www.w3.org/ns/activitystreams#duration"]);
|
|
1105
|
+
const QUESTION_CLOSED_IRI = "https://www.w3.org/ns/activitystreams#closed";
|
|
1106
|
+
const XSD_DATE_TIME_IRI = "http://www.w3.org/2001/XMLSchema#dateTime";
|
|
1107
|
+
function hasMalformedExpandedDateTimeLiteral(value) {
|
|
1108
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDateTimeLiteral);
|
|
1109
|
+
return isPlainObject(value) && "@value" in value && isMalformedDateTimeLiteral(value["@value"]);
|
|
1110
|
+
}
|
|
1111
|
+
function hasMalformedExpandedQuestionClosedLiteral(value) {
|
|
1112
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedQuestionClosedLiteral);
|
|
1113
|
+
if (!isPlainObject(value) || !("@value" in value)) return false;
|
|
1114
|
+
const literal = value["@value"];
|
|
1115
|
+
if (typeof literal === "boolean") return false;
|
|
1116
|
+
if (typeof literal !== "string") return false;
|
|
1117
|
+
if (value["@type"] !== XSD_DATE_TIME_IRI) return false;
|
|
1118
|
+
if (new Date(literal).toString() === "Invalid Date") return false;
|
|
1119
|
+
return isMalformedDateTimeLiteral(literal);
|
|
1120
|
+
}
|
|
1121
|
+
function hasMalformedExpandedDurationLiteral(value) {
|
|
1122
|
+
if (Array.isArray(value)) return value.some(hasMalformedExpandedDurationLiteral);
|
|
1123
|
+
return isPlainObject(value) && "@value" in value && isMalformedDurationLiteral(value["@value"]);
|
|
1124
|
+
}
|
|
1125
|
+
function hasMalformedKnownTemporalLiteralInternal(value, visited) {
|
|
1126
|
+
if (Array.isArray(value)) return value.some((item) => hasMalformedKnownTemporalLiteralInternal(item, visited));
|
|
1127
|
+
if (!isPlainObject(value)) return false;
|
|
1128
|
+
if (visited.has(value)) return false;
|
|
1129
|
+
visited.add(value);
|
|
1130
|
+
if ("@value" in value) return false;
|
|
1131
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1132
|
+
if (TEMPORAL_DATE_TIME_IRIS.has(key)) {
|
|
1133
|
+
if (hasMalformedExpandedDateTimeLiteral(child)) return true;
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
if (key === QUESTION_CLOSED_IRI) {
|
|
1137
|
+
if (hasMalformedExpandedQuestionClosedLiteral(child)) return true;
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
if (TEMPORAL_DURATION_IRIS.has(key)) {
|
|
1141
|
+
if (hasMalformedExpandedDurationLiteral(child)) return true;
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (hasMalformedKnownTemporalLiteralInternal(child, visited)) return true;
|
|
1145
|
+
}
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1148
|
+
async function hasMalformedKnownTemporalLiteral(value, contextLoader) {
|
|
1149
|
+
try {
|
|
1150
|
+
return hasMalformedKnownTemporalLiteralInternal(await _fedify_vocab_runtime_jsonld.default.expand(value, {
|
|
1151
|
+
documentLoader: require_proof.getNormalizationContextLoader(contextLoader),
|
|
1152
|
+
keepFreeFloatingNodes: true
|
|
1153
|
+
}), /* @__PURE__ */ new Set());
|
|
1154
|
+
} catch {
|
|
1155
|
+
return false;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
//#endregion
|
|
1065
1159
|
//#region src/federation/handler.ts
|
|
1160
|
+
const rawInboxContextFactorySymbol = Symbol("fedify.rawInboxContextFactory");
|
|
1161
|
+
function isRemoteContextLoadingFailure$1(error) {
|
|
1162
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
1163
|
+
}
|
|
1164
|
+
function isPermanentRemoteContextError$1(error) {
|
|
1165
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
1166
|
+
const details = error.details;
|
|
1167
|
+
if (details?.code === "invalid remote context") return true;
|
|
1168
|
+
return isRemoteContextLoadingFailure$1(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
1169
|
+
}
|
|
1170
|
+
function isInvalidJsonLdError(error) {
|
|
1171
|
+
if (!(error instanceof Error)) return false;
|
|
1172
|
+
const name = error.name;
|
|
1173
|
+
return name === "UnsafeJsonLdError" || error instanceof require_proof.InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
|
|
1174
|
+
}
|
|
1175
|
+
function isValidationTypeError(error) {
|
|
1176
|
+
return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || require_proof.isInvalidUrlTypeError(error));
|
|
1177
|
+
}
|
|
1178
|
+
function isPermanentActivityParseError(error) {
|
|
1179
|
+
return isInvalidJsonLdError(error) || isValidationTypeError(error);
|
|
1180
|
+
}
|
|
1181
|
+
function hasHttpSignatureHeaders(request) {
|
|
1182
|
+
return request.headers.has("Signature") || request.headers.has("Signature-Input");
|
|
1183
|
+
}
|
|
1184
|
+
function hasObjectIntegrityProof(json) {
|
|
1185
|
+
return typeof json === "object" && json != null && "proof" in json;
|
|
1186
|
+
}
|
|
1066
1187
|
/**
|
|
1067
1188
|
* Handles an actor request.
|
|
1068
1189
|
* @template TContextData The context data to pass to the context.
|
|
@@ -1589,28 +1710,104 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1589
1710
|
});
|
|
1590
1711
|
}
|
|
1591
1712
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1713
|
+
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1714
|
+
const hasLdSignature = require_proof.hasSignature(json);
|
|
1715
|
+
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
1716
|
+
let deferredLdSignatureError = void 0;
|
|
1717
|
+
const respondInvalidActivity = async (error) => {
|
|
1718
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
1719
|
+
recipient,
|
|
1720
|
+
activity: json,
|
|
1721
|
+
error
|
|
1599
1722
|
});
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1723
|
+
try {
|
|
1724
|
+
await inboxErrorHandler?.(ctx, error);
|
|
1725
|
+
} catch (error) {
|
|
1726
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1727
|
+
error,
|
|
1728
|
+
activity: json,
|
|
1729
|
+
recipient
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
span.setStatus({
|
|
1733
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
1734
|
+
message: `Failed to parse activity:\n${error}`
|
|
1735
|
+
});
|
|
1736
|
+
return new Response("Invalid activity.", {
|
|
1737
|
+
status: 400,
|
|
1738
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1739
|
+
});
|
|
1740
|
+
};
|
|
1741
|
+
let compactedJson = json;
|
|
1742
|
+
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
1743
|
+
let ldSigVerified = false;
|
|
1744
|
+
if (hasLdSignature) {
|
|
1745
|
+
try {
|
|
1746
|
+
compactedJson = await require_proof.compactJsonLd(json, ctx.contextLoader);
|
|
1747
|
+
} catch (error) {
|
|
1748
|
+
if (isInvalidJsonLdError(error)) {
|
|
1749
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1750
|
+
recipient,
|
|
1751
|
+
error
|
|
1752
|
+
});
|
|
1753
|
+
return new Response("Invalid JSON-LD.", {
|
|
1754
|
+
status: 400,
|
|
1755
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1759
|
+
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
1760
|
+
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
1603
1761
|
recipient,
|
|
1604
1762
|
error
|
|
1605
1763
|
});
|
|
1606
|
-
return new Response("Invalid JSON-LD.", {
|
|
1607
|
-
status: 400,
|
|
1608
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1609
|
-
});
|
|
1610
1764
|
}
|
|
1611
|
-
|
|
1765
|
+
if (compactedJson !== json) {
|
|
1766
|
+
compactedJsonWithoutSig = require_proof.detachSignature(compactedJson);
|
|
1767
|
+
try {
|
|
1768
|
+
ldSigVerified = await require_proof.verifyCompactJsonLd(compactedJson, {
|
|
1769
|
+
contextLoader: ctx.contextLoader,
|
|
1770
|
+
documentLoader: ctx.documentLoader,
|
|
1771
|
+
keyCache,
|
|
1772
|
+
tracerProvider
|
|
1773
|
+
});
|
|
1774
|
+
} catch (error) {
|
|
1775
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1776
|
+
if (isInvalidJsonLdError(error)) {
|
|
1777
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1778
|
+
recipient,
|
|
1779
|
+
error
|
|
1780
|
+
});
|
|
1781
|
+
return new Response("Invalid JSON-LD.", {
|
|
1782
|
+
status: 400,
|
|
1783
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
1787
|
+
if (!skipSignatureVerification) try {
|
|
1788
|
+
await _fedify_vocab.Object.fromJsonLd(compactedJson, {
|
|
1789
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader),
|
|
1790
|
+
documentLoader: ctx.documentLoader,
|
|
1791
|
+
tracerProvider
|
|
1792
|
+
});
|
|
1793
|
+
} catch (parseError) {
|
|
1794
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(parseError);
|
|
1795
|
+
if (isInvalidJsonLdError(parseError)) {
|
|
1796
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1797
|
+
recipient,
|
|
1798
|
+
error: parseError
|
|
1799
|
+
});
|
|
1800
|
+
return new Response("Invalid JSON-LD.", {
|
|
1801
|
+
status: 400,
|
|
1802
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1805
|
+
deferredLdSignatureError = parseError;
|
|
1806
|
+
}
|
|
1807
|
+
ldSigVerified = false;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1612
1810
|
}
|
|
1613
|
-
const jsonWithoutSig = require_proof.detachSignature(json);
|
|
1614
1811
|
let activity = null;
|
|
1615
1812
|
let activityVerified = false;
|
|
1616
1813
|
if (ldSigVerified) {
|
|
@@ -1618,7 +1815,16 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1618
1815
|
recipient,
|
|
1619
1816
|
json
|
|
1620
1817
|
});
|
|
1621
|
-
|
|
1818
|
+
try {
|
|
1819
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
1820
|
+
...ctx,
|
|
1821
|
+
contextLoader: require_proof.getNormalizationContextLoader(ctx.contextLoader)
|
|
1822
|
+
});
|
|
1823
|
+
} catch (error) {
|
|
1824
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1825
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1826
|
+
return await respondInvalidActivity(error);
|
|
1827
|
+
}
|
|
1622
1828
|
activityVerified = true;
|
|
1623
1829
|
} else {
|
|
1624
1830
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
@@ -1627,12 +1833,21 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1627
1833
|
});
|
|
1628
1834
|
try {
|
|
1629
1835
|
activity = await require_proof.verifyObject(_fedify_vocab.Activity, jsonWithoutSig, {
|
|
1630
|
-
contextLoader: ctx.contextLoader,
|
|
1836
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1631
1837
|
documentLoader: ctx.documentLoader,
|
|
1632
1838
|
keyCache,
|
|
1633
1839
|
tracerProvider
|
|
1634
1840
|
});
|
|
1635
1841
|
} catch (error) {
|
|
1842
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
1843
|
+
if (deferredLdSignatureError != null) {
|
|
1844
|
+
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
1845
|
+
recipient,
|
|
1846
|
+
error
|
|
1847
|
+
});
|
|
1848
|
+
activity = null;
|
|
1849
|
+
}
|
|
1850
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1636
1851
|
logger.error("Failed to parse activity:\n{error}", {
|
|
1637
1852
|
recipient,
|
|
1638
1853
|
activity: json,
|
|
@@ -1680,6 +1895,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1680
1895
|
tracerProvider
|
|
1681
1896
|
});
|
|
1682
1897
|
if (verification.verified === false) {
|
|
1898
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1683
1899
|
const reason = verification.reason;
|
|
1684
1900
|
logger.error("Failed to verify the request's HTTP Signatures.", {
|
|
1685
1901
|
recipient,
|
|
@@ -1755,7 +1971,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1755
1971
|
}
|
|
1756
1972
|
httpSigKey = verification.key;
|
|
1757
1973
|
}
|
|
1758
|
-
|
|
1974
|
+
try {
|
|
1975
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(jsonWithoutSig, {
|
|
1976
|
+
...ctx,
|
|
1977
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1978
|
+
});
|
|
1979
|
+
} catch (error) {
|
|
1980
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1981
|
+
return await respondInvalidActivity(error);
|
|
1982
|
+
}
|
|
1759
1983
|
}
|
|
1760
1984
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1761
1985
|
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
@@ -1767,6 +1991,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1767
1991
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1768
1992
|
});
|
|
1769
1993
|
if (httpSigKey != null && !await require_proof.doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1994
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1770
1995
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1771
1996
|
activity: json,
|
|
1772
1997
|
recipient,
|
|
@@ -1791,10 +2016,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1791
2016
|
const routeResult = await routeActivity({
|
|
1792
2017
|
context: ctx,
|
|
1793
2018
|
json,
|
|
2019
|
+
originalJson: json,
|
|
2020
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
2021
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1794
2022
|
activity,
|
|
1795
2023
|
recipient,
|
|
1796
2024
|
inboxListeners,
|
|
1797
2025
|
inboxContextFactory,
|
|
2026
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1798
2027
|
inboxErrorHandler,
|
|
1799
2028
|
kv,
|
|
1800
2029
|
kvPrefixes,
|
|
@@ -2710,6 +2939,18 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
2710
2939
|
}
|
|
2711
2940
|
//#endregion
|
|
2712
2941
|
//#region src/federation/middleware.ts
|
|
2942
|
+
function isRemoteContextLoadingFailure(error) {
|
|
2943
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
2944
|
+
}
|
|
2945
|
+
function isPermanentRemoteContextError(error) {
|
|
2946
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
2947
|
+
const details = error.details;
|
|
2948
|
+
if (details?.code === "invalid remote context") return true;
|
|
2949
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_proof.isClearlyMalformedContextReference(details.url);
|
|
2950
|
+
}
|
|
2951
|
+
function isPermanentInboxParseError(error) {
|
|
2952
|
+
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));
|
|
2953
|
+
}
|
|
2713
2954
|
/**
|
|
2714
2955
|
* Create a new {@link Federation} instance.
|
|
2715
2956
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -3091,7 +3332,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3091
3332
|
}
|
|
3092
3333
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
3093
3334
|
}
|
|
3094
|
-
async #listenInboxMessage(ctxData, message,
|
|
3335
|
+
async #listenInboxMessage(ctxData, message, _span) {
|
|
3095
3336
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
3096
3337
|
"fedify",
|
|
3097
3338
|
"federation",
|
|
@@ -3104,60 +3345,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3104
3345
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3105
3346
|
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3106
3347
|
}
|
|
3107
|
-
const activity = await _fedify_vocab.Activity.fromJsonLd(message.activity, context);
|
|
3108
|
-
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
3109
|
-
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
3110
|
-
const cacheKey = activity.id == null ? null : [
|
|
3111
|
-
...this.kvPrefixes.activityIdempotence,
|
|
3112
|
-
context.origin,
|
|
3113
|
-
activity.id.href
|
|
3114
|
-
];
|
|
3115
|
-
if (cacheKey != null) {
|
|
3116
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
3117
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
3118
|
-
activityId: activity.id?.href,
|
|
3119
|
-
activity: message.activity,
|
|
3120
|
-
recipient: message.identifier
|
|
3121
|
-
});
|
|
3122
|
-
return;
|
|
3123
|
-
}
|
|
3124
|
-
}
|
|
3125
3348
|
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: _opentelemetry_api.SpanKind.INTERNAL }, async (span) => {
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
activityId: activity.id?.href,
|
|
3130
|
-
activity: message.activity,
|
|
3131
|
-
recipient: message.identifier,
|
|
3132
|
-
trial: message.attempt
|
|
3133
|
-
});
|
|
3134
|
-
span.setStatus({
|
|
3135
|
-
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3136
|
-
message: `Unsupported activity type: ${(0, _fedify_vocab.getTypeId)(activity).href}`
|
|
3137
|
-
});
|
|
3138
|
-
span.end();
|
|
3139
|
-
return;
|
|
3140
|
-
}
|
|
3141
|
-
const { class: cls, listener } = dispatched;
|
|
3142
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3143
|
-
try {
|
|
3144
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
3145
|
-
} catch (error) {
|
|
3349
|
+
let activity = null;
|
|
3350
|
+
let cacheKey = null;
|
|
3351
|
+
const reportInboxError = async (error) => {
|
|
3146
3352
|
try {
|
|
3147
3353
|
await this.inboxErrorHandler?.(context, error);
|
|
3148
3354
|
} catch (error) {
|
|
3149
3355
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
3150
3356
|
error,
|
|
3151
3357
|
trial: message.attempt,
|
|
3152
|
-
activityId: activity
|
|
3358
|
+
activityId: activity?.id?.href,
|
|
3153
3359
|
activity: message.activity,
|
|
3154
3360
|
recipient: message.identifier
|
|
3155
3361
|
});
|
|
3156
3362
|
}
|
|
3363
|
+
};
|
|
3364
|
+
const handleRetriableFailure = async (error) => {
|
|
3365
|
+
await reportInboxError(error);
|
|
3157
3366
|
if (this.inboxQueue?.nativeRetrial) {
|
|
3158
3367
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
3159
3368
|
error,
|
|
3160
|
-
activityId: activity
|
|
3369
|
+
activityId: activity?.id?.href,
|
|
3161
3370
|
activity: message.activity,
|
|
3162
3371
|
recipient: message.identifier
|
|
3163
3372
|
});
|
|
@@ -3176,17 +3385,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3176
3385
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
3177
3386
|
error,
|
|
3178
3387
|
attempt: message.attempt,
|
|
3179
|
-
activityId: activity
|
|
3388
|
+
activityId: activity?.id?.href,
|
|
3180
3389
|
activity: message.activity,
|
|
3181
3390
|
recipient: message.identifier
|
|
3182
3391
|
});
|
|
3392
|
+
if (this.inboxQueue == null) {
|
|
3393
|
+
span.setStatus({
|
|
3394
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3395
|
+
message: String(error)
|
|
3396
|
+
});
|
|
3397
|
+
span.end();
|
|
3398
|
+
throw error;
|
|
3399
|
+
}
|
|
3183
3400
|
await this.inboxQueue?.enqueue({
|
|
3184
3401
|
...message,
|
|
3185
3402
|
attempt: message.attempt + 1
|
|
3186
3403
|
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
3187
3404
|
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
3188
3405
|
error,
|
|
3189
|
-
activityId: activity
|
|
3406
|
+
activityId: activity?.id?.href,
|
|
3190
3407
|
activity: message.activity,
|
|
3191
3408
|
recipient: message.identifier
|
|
3192
3409
|
});
|
|
@@ -3195,11 +3412,108 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3195
3412
|
message: String(error)
|
|
3196
3413
|
});
|
|
3197
3414
|
span.end();
|
|
3415
|
+
};
|
|
3416
|
+
let dispatched;
|
|
3417
|
+
let parseInput = void 0;
|
|
3418
|
+
let parseContextLoader = context.contextLoader;
|
|
3419
|
+
try {
|
|
3420
|
+
const hasSignatureField = require_proof.hasSignature(message.activity);
|
|
3421
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
3422
|
+
const parseContext = hasSignatureField ? {
|
|
3423
|
+
...context,
|
|
3424
|
+
contextLoader: require_proof.getNormalizationContextLoader(context.contextLoader)
|
|
3425
|
+
} : {
|
|
3426
|
+
...context,
|
|
3427
|
+
contextLoader: require_proof.wrapContextLoaderForJsonLd(context.contextLoader)
|
|
3428
|
+
};
|
|
3429
|
+
parseContextLoader = parseContext.contextLoader;
|
|
3430
|
+
let normalizedActivity;
|
|
3431
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
3432
|
+
normalizedActivity = message.normalizedActivity ?? await require_proof.compactJsonLd(message.activity, context.contextLoader);
|
|
3433
|
+
require_proof.assertSafeJsonLd(normalizedActivity);
|
|
3434
|
+
}
|
|
3435
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? require_proof.detachSignature(normalizedActivity) : hasSignatureField ? require_proof.detachSignature(message.activity) : message.activity;
|
|
3436
|
+
activity = await _fedify_vocab.Activity.fromJsonLd(parseInput, parseContext);
|
|
3437
|
+
span.setAttribute("activitypub.activity.type", (0, _fedify_vocab.getTypeId)(activity).href);
|
|
3438
|
+
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
3439
|
+
cacheKey = activity.id == null ? null : [
|
|
3440
|
+
...this.kvPrefixes.activityIdempotence,
|
|
3441
|
+
context.origin,
|
|
3442
|
+
activity.id.href
|
|
3443
|
+
];
|
|
3444
|
+
if (cacheKey != null) {
|
|
3445
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
3446
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
3447
|
+
activityId: activity.id?.href,
|
|
3448
|
+
activity: message.activity,
|
|
3449
|
+
recipient: message.identifier
|
|
3450
|
+
});
|
|
3451
|
+
span.end();
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
3456
|
+
} catch (error) {
|
|
3457
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
3458
|
+
await reportInboxError(error);
|
|
3459
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3460
|
+
error,
|
|
3461
|
+
trial: message.attempt,
|
|
3462
|
+
activityId: null,
|
|
3463
|
+
activity: message.activity,
|
|
3464
|
+
recipient: message.identifier
|
|
3465
|
+
});
|
|
3466
|
+
span.setStatus({
|
|
3467
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3468
|
+
message: String(error)
|
|
3469
|
+
});
|
|
3470
|
+
span.end();
|
|
3471
|
+
return;
|
|
3472
|
+
}
|
|
3473
|
+
if (isPermanentInboxParseError(error)) {
|
|
3474
|
+
await reportInboxError(error);
|
|
3475
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3476
|
+
error,
|
|
3477
|
+
trial: message.attempt,
|
|
3478
|
+
activityId: activity?.id?.href,
|
|
3479
|
+
activity: message.activity,
|
|
3480
|
+
recipient: message.identifier
|
|
3481
|
+
});
|
|
3482
|
+
span.setStatus({
|
|
3483
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3484
|
+
message: String(error)
|
|
3485
|
+
});
|
|
3486
|
+
span.end();
|
|
3487
|
+
return;
|
|
3488
|
+
}
|
|
3489
|
+
await handleRetriableFailure(error);
|
|
3490
|
+
return;
|
|
3491
|
+
}
|
|
3492
|
+
if (dispatched == null) {
|
|
3493
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
3494
|
+
activityId: activity.id?.href,
|
|
3495
|
+
activity: message.activity,
|
|
3496
|
+
recipient: message.identifier,
|
|
3497
|
+
trial: message.attempt
|
|
3498
|
+
});
|
|
3499
|
+
span.setStatus({
|
|
3500
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
3501
|
+
message: `Unsupported activity type: ${(0, _fedify_vocab.getTypeId)(activity).href}`
|
|
3502
|
+
});
|
|
3503
|
+
span.end();
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3506
|
+
const { class: cls, listener } = dispatched;
|
|
3507
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3508
|
+
try {
|
|
3509
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, (0, _fedify_vocab.getTypeId)(activity).href), activity);
|
|
3510
|
+
} catch (error) {
|
|
3511
|
+
await handleRetriableFailure(error);
|
|
3198
3512
|
return;
|
|
3199
3513
|
}
|
|
3200
3514
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
3201
3515
|
logger.info("Activity {activityId} has been processed.", {
|
|
3202
|
-
activityId: activity
|
|
3516
|
+
activityId: activity?.id?.href,
|
|
3203
3517
|
activity: message.activity,
|
|
3204
3518
|
recipient: message.identifier
|
|
3205
3519
|
});
|
|
@@ -3569,16 +3883,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3569
3883
|
onNotFound
|
|
3570
3884
|
});
|
|
3571
3885
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier }) });
|
|
3572
|
-
case "sharedInbox":
|
|
3886
|
+
case "sharedInbox": {
|
|
3573
3887
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3574
3888
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3575
3889
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3576
3890
|
}
|
|
3577
3891
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3892
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3893
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
3578
3894
|
return await handleInbox(request, {
|
|
3579
3895
|
recipient: route.values.identifier ?? null,
|
|
3580
3896
|
context,
|
|
3581
|
-
inboxContextFactory
|
|
3897
|
+
inboxContextFactory,
|
|
3582
3898
|
kv: this.kv,
|
|
3583
3899
|
kvPrefixes: this.kvPrefixes,
|
|
3584
3900
|
queue: this.inboxQueue,
|
|
@@ -3593,6 +3909,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3593
3909
|
tracerProvider: this.tracerProvider,
|
|
3594
3910
|
idempotencyStrategy: this.idempotencyStrategy
|
|
3595
3911
|
});
|
|
3912
|
+
}
|
|
3596
3913
|
case "following": return await handleCollection(request, {
|
|
3597
3914
|
name: "following",
|
|
3598
3915
|
identifier: route.values.identifier,
|
|
@@ -4293,6 +4610,7 @@ var ContextImpl = class ContextImpl {
|
|
|
4293
4610
|
const routeResult = await routeActivity({
|
|
4294
4611
|
context: this,
|
|
4295
4612
|
json,
|
|
4613
|
+
ldSignatureVerified: false,
|
|
4296
4614
|
activity,
|
|
4297
4615
|
recipient,
|
|
4298
4616
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -4573,6 +4891,14 @@ async function forwardActivityInternal(ctx, loggerCategory, forwarder, recipient
|
|
|
4573
4891
|
}
|
|
4574
4892
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
4575
4893
|
recipient;
|
|
4894
|
+
/**
|
|
4895
|
+
* The original received activity payload.
|
|
4896
|
+
*
|
|
4897
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4898
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4899
|
+
* third-party signatures/proofs remain intact.
|
|
4900
|
+
* @internal
|
|
4901
|
+
*/
|
|
4576
4902
|
activity;
|
|
4577
4903
|
activityId;
|
|
4578
4904
|
activityType;
|