@fedify/fedify 1.10.9 → 1.10.11
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-DSmY7of0.cjs → actor--xTQfY8h.cjs} +187 -187
- package/dist/{actor-CMBXPdjk.js → actor-B7XRaa54.js} +187 -187
- package/dist/{actor-z4bjwAPy.mjs → actor-CTpwJ1pI.mjs} +1 -1
- package/dist/{authdocloader-C7iVUcxr.mjs → authdocloader-DJ-h-WMy.mjs} +3 -3
- package/dist/{authdocloader-YXazGK4I.cjs → authdocloader-DMkkNwRc.cjs} +3 -3
- package/dist/{authdocloader-B4QKchy5.js → authdocloader-_h7VKnUP.js} +3 -3
- package/dist/{builder-C3PFAtTV.mjs → builder-Dx_LGmTI.mjs} +4 -4
- package/dist/{client-C-xdpu6M.mjs → client-DDy3-85E.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-Ca6-eCr_.js} +121 -13
- package/dist/{docloader-9cG6ESUw.cjs → docloader-CvMstYam.cjs} +121 -13
- package/dist/{esm-Bfj-SwEx.mjs → esm-CzaH6D4W.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-LjaXmp2m.cjs → http-B3o3SOXX.cjs} +3 -3
- package/dist/{http-CuloN7xQ.js → http-Bku28NB8.js} +3 -3
- package/dist/{http-D5CDiVKf.mjs → http-CiqAQGRx.mjs} +2 -2
- package/dist/{inbox-D0Mzd940.mjs → inbox-D3RCgSiJ.mjs} +7 -4
- package/dist/{key-B22mXs2u.cjs → key-BbdUjmdf.cjs} +2 -2
- package/dist/{key-B5QN42gR.mjs → key-C15RK-kf.mjs} +1 -1
- package/dist/{key-D1PkkNK-.js → key-CJU1QxP2.js} +2 -2
- package/dist/{key-CXkrXfz6.cjs → key-ClgfrNJf.cjs} +1 -1
- package/dist/{key-Dnc1ekhA.mjs → key-LJoRzwG2.mjs} +2 -2
- package/dist/{keycache-DwDRFAp7.mjs → keycache-BCuiTm4y.mjs} +1 -1
- package/dist/{keys-C4Ms2Cy-.mjs → keys-wZip1i2J.mjs} +1 -1
- package/dist/ld-BO_vEkla.mjs +548 -0
- package/dist/{lookup-D0d32cZH.cjs → lookup-Cs7LHObN.cjs} +1 -1
- package/dist/{lookup-B8rOR_1a.js → lookup-DRzvxZ-l.js} +1 -1
- package/dist/{lookup-Br7I7sqm.mjs → lookup-FvsTNqW8.mjs} +1 -1
- package/dist/{middleware-BlsPkr2X.mjs → middleware-Cdb7LDeG.mjs} +1 -1
- package/dist/{middleware-BbgpZrsX.mjs → middleware-CzjJsU2k.mjs} +320 -87
- package/dist/{middleware-0yq2uipZ.cjs → middleware-Dn5HfxXi.cjs} +411 -85
- package/dist/{middleware-CYNQWJ-D.js → middleware-DoM0y4tG.js} +408 -83
- package/dist/{middleware-BRXIidLb.cjs → middleware-SfuiAsBu.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-BRgVUFTA.mjs} +3 -3
- package/dist/{proof-u5ivh_eA.js → proof-BL5RXXp2.js} +300 -6
- package/dist/{proof-DE2Z0_uv.cjs → proof-BPEkbKl1.cjs} +347 -5
- package/dist/{proof-B67QOiuS.mjs → proof-De_2gCxi.mjs} +2 -2
- 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 +53 -2
- package/dist/{send-7RGxOhrY.mjs → send-C7irF8CJ.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-CtvhWksK.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-DskvUSfh.mjs} +2 -2
- package/dist/{transformers-BdbEtUZU.cjs → transformers-BbJsnOaL.cjs} +1 -1
- package/dist/{types-6_pWuZfK.js → types-B-GUdtNR.js} +1 -1
- package/dist/{types-ec4G8nGs.cjs → types-BWNGBD9D.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-C0yDmtpE.mjs} +306 -198
- 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
|
@@ -2,17 +2,18 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./rolldown-runtime-C7fyD9f2.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-BV4OeK9o.js";
|
|
5
|
-
import { d as name, f as version, i as getDocumentLoader, s as kvCache } from "./docloader-
|
|
6
|
-
import { G as Multikey, Tt as getTypeId, V as Link, X as OrderedCollectionPage, Y as OrderedCollection, _ as CollectionPage, g as Collection, q as Object$1, s as Activity, y as CryptographicKey } from "./actor-
|
|
7
|
-
import { t as lookupWebFinger } from "./lookup-
|
|
8
|
-
import { i as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-
|
|
9
|
-
import { r as verifyRequest, t as doubleKnock } from "./http-
|
|
10
|
-
import { a as doesActorOwnKey,
|
|
11
|
-
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-
|
|
12
|
-
import { t as getAuthenticatedDocumentLoader } from "./authdocloader-
|
|
5
|
+
import { d as name, f as version, i as getDocumentLoader, s as kvCache } from "./docloader-Ca6-eCr_.js";
|
|
6
|
+
import { G as Multikey, Tt as getTypeId, V as Link, X as OrderedCollectionPage, Y as OrderedCollection, _ as CollectionPage, g as Collection, q as Object$1, s as Activity, y as CryptographicKey } from "./actor-B7XRaa54.js";
|
|
7
|
+
import { t as lookupWebFinger } from "./lookup-DRzvxZ-l.js";
|
|
8
|
+
import { i as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-CJU1QxP2.js";
|
|
9
|
+
import { r as verifyRequest, t as doubleKnock } from "./http-Bku28NB8.js";
|
|
10
|
+
import { _ as signJsonLd, a as doesActorOwnKey, c as assertSafeJsonLd, f as detachSignature, g as isInvalidUrlTypeError, h as isClearlyMalformedContextReference, m as hasSignature, n as signObject, o as getKeyOwner, p as getNormalizationContextLoader, r as verifyObject, s as InvalidContextReferenceError, u as compactJsonLd, v as verifyCompactJsonLd, x as wrapContextLoaderForJsonLd } from "./proof-BL5RXXp2.js";
|
|
11
|
+
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-B-GUdtNR.js";
|
|
12
|
+
import { t as getAuthenticatedDocumentLoader } from "./authdocloader-_h7VKnUP.js";
|
|
13
13
|
import { lookupObject, traverseCollection } from "./vocab/mod.js";
|
|
14
14
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
15
15
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
16
|
+
import jsonld from "jsonld";
|
|
16
17
|
import { encodeHex } from "byte-encodings/hex";
|
|
17
18
|
import { cloneDeep } from "es-toolkit";
|
|
18
19
|
import { Router } from "uri-template-router";
|
|
@@ -54,7 +55,7 @@ var InboxListenerSet = class InboxListenerSet {
|
|
|
54
55
|
}
|
|
55
56
|
};
|
|
56
57
|
let warnedAboutDefaultIdempotency = false;
|
|
57
|
-
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 }) {
|
|
58
59
|
const logger = getLogger([
|
|
59
60
|
"fedify",
|
|
60
61
|
"federation",
|
|
@@ -115,7 +116,9 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
115
116
|
type: "inbox",
|
|
116
117
|
id: crypto.randomUUID(),
|
|
117
118
|
baseUrl: ctx.origin,
|
|
118
|
-
activity: json,
|
|
119
|
+
activity: originalJson ?? json,
|
|
120
|
+
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
121
|
+
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
119
122
|
identifier: recipient,
|
|
120
123
|
attempt: 0,
|
|
121
124
|
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -159,7 +162,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
159
162
|
const { class: cls, listener } = dispatched;
|
|
160
163
|
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
161
164
|
try {
|
|
162
|
-
|
|
165
|
+
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
166
|
+
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity?.id?.href, getTypeId(activity).href), activity);
|
|
163
167
|
} catch (error) {
|
|
164
168
|
try {
|
|
165
169
|
await inboxErrorHandler?.(ctx, error);
|
|
@@ -999,7 +1003,123 @@ function preferredMediaTypes(accept) {
|
|
|
999
1003
|
return parseAccept(accept === void 0 ? "*/*" : accept ?? "").filter(isQuality).sort(compareSpecs).map(getFullType);
|
|
1000
1004
|
}
|
|
1001
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.expand(value, {
|
|
1087
|
+
documentLoader: getNormalizationContextLoader(contextLoader),
|
|
1088
|
+
keepFreeFloatingNodes: true
|
|
1089
|
+
}), /* @__PURE__ */ new Set());
|
|
1090
|
+
} catch {
|
|
1091
|
+
return false;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
//#endregion
|
|
1002
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) && 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 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) || 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
|
+
}
|
|
1003
1123
|
function acceptsJsonLd(request) {
|
|
1004
1124
|
const accept = request.headers.get("Accept");
|
|
1005
1125
|
const types = accept ? preferredMediaTypes(accept) : ["*/*"];
|
|
@@ -1106,8 +1226,8 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
1106
1226
|
* @param parameters The parameters for handling the collection.
|
|
1107
1227
|
* @returns A promise that resolves to an HTTP response.
|
|
1108
1228
|
*/
|
|
1109
|
-
async function handleCollection(request, { name: name$
|
|
1110
|
-
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, "_");
|
|
1111
1231
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1112
1232
|
const tracer = tracerProvider.getTracer(name, version);
|
|
1113
1233
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
@@ -1149,7 +1269,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1149
1269
|
collection = new OrderedCollection({
|
|
1150
1270
|
id: baseUri,
|
|
1151
1271
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
1152
|
-
items: filterCollectionItems(itemsOrResponse, name$
|
|
1272
|
+
items: filterCollectionItems(itemsOrResponse, name$1, filterPredicate)
|
|
1153
1273
|
});
|
|
1154
1274
|
} else {
|
|
1155
1275
|
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
@@ -1170,7 +1290,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1170
1290
|
} else {
|
|
1171
1291
|
const uri = new URL(baseUri);
|
|
1172
1292
|
uri.searchParams.set("cursor", cursor);
|
|
1173
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1293
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
1174
1294
|
kind: SpanKind.SERVER,
|
|
1175
1295
|
attributes: {
|
|
1176
1296
|
"activitypub.collection.id": uri.href,
|
|
@@ -1214,7 +1334,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1214
1334
|
id: uri,
|
|
1215
1335
|
prev,
|
|
1216
1336
|
next,
|
|
1217
|
-
items: filterCollectionItems(items, name$
|
|
1337
|
+
items: filterCollectionItems(items, name$1, filterPredicate),
|
|
1218
1338
|
partOf
|
|
1219
1339
|
});
|
|
1220
1340
|
}
|
|
@@ -1383,35 +1503,120 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1383
1503
|
});
|
|
1384
1504
|
}
|
|
1385
1505
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, ctx);
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1506
|
+
const jsonWithoutSig = detachSignature(json);
|
|
1507
|
+
const hasLdSignature = 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
|
|
1393
1515
|
});
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
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: 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 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}", {
|
|
1397
1554
|
recipient,
|
|
1398
1555
|
error
|
|
1399
1556
|
});
|
|
1400
|
-
return new Response("Invalid JSON-LD.", {
|
|
1401
|
-
status: 400,
|
|
1402
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1403
|
-
});
|
|
1404
1557
|
}
|
|
1405
|
-
|
|
1558
|
+
if (compactedJson !== json) {
|
|
1559
|
+
compactedJsonWithoutSig = detachSignature(compactedJson);
|
|
1560
|
+
try {
|
|
1561
|
+
ldSigVerified = await 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 Object$1.fromJsonLd(compactedJson, {
|
|
1582
|
+
contextLoader: 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
|
+
}
|
|
1406
1603
|
}
|
|
1407
|
-
const jsonWithoutSig = detachSignature(json);
|
|
1408
1604
|
let activity = null;
|
|
1409
1605
|
if (ldSigVerified) {
|
|
1410
1606
|
logger.debug("Linked Data Signatures are verified.", {
|
|
1411
1607
|
recipient,
|
|
1412
1608
|
json
|
|
1413
1609
|
});
|
|
1414
|
-
|
|
1610
|
+
try {
|
|
1611
|
+
activity = await Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
1612
|
+
...ctx,
|
|
1613
|
+
contextLoader: 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
|
+
}
|
|
1415
1620
|
} else {
|
|
1416
1621
|
logger.debug("Linked Data Signatures are not verified.", {
|
|
1417
1622
|
recipient,
|
|
@@ -1419,12 +1624,21 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1419
1624
|
});
|
|
1420
1625
|
try {
|
|
1421
1626
|
activity = await verifyObject(Activity, jsonWithoutSig, {
|
|
1422
|
-
contextLoader: ctx.contextLoader,
|
|
1627
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1423
1628
|
documentLoader: ctx.documentLoader,
|
|
1424
1629
|
keyCache,
|
|
1425
1630
|
tracerProvider
|
|
1426
1631
|
});
|
|
1427
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;
|
|
1428
1642
|
logger.error("Failed to parse activity:\n{error}", {
|
|
1429
1643
|
recipient,
|
|
1430
1644
|
activity: json,
|
|
@@ -1468,6 +1682,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1468
1682
|
tracerProvider
|
|
1469
1683
|
});
|
|
1470
1684
|
if (key == null) {
|
|
1685
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1471
1686
|
logger.error("Failed to verify the request's HTTP Signatures.", { recipient });
|
|
1472
1687
|
span.setStatus({
|
|
1473
1688
|
code: SpanStatusCode.ERROR,
|
|
@@ -1480,7 +1695,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1480
1695
|
} else logger.debug("HTTP Signatures are verified.", { recipient });
|
|
1481
1696
|
httpSigKey = key;
|
|
1482
1697
|
}
|
|
1483
|
-
|
|
1698
|
+
try {
|
|
1699
|
+
activity = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
1700
|
+
...ctx,
|
|
1701
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
1702
|
+
});
|
|
1703
|
+
} catch (error) {
|
|
1704
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
1705
|
+
return await respondInvalidActivity(error);
|
|
1706
|
+
}
|
|
1484
1707
|
}
|
|
1485
1708
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1486
1709
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
@@ -1492,6 +1715,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1492
1715
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1493
1716
|
});
|
|
1494
1717
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1718
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1495
1719
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1496
1720
|
activity: json,
|
|
1497
1721
|
recipient,
|
|
@@ -1510,10 +1734,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1510
1734
|
const routeResult = await routeActivity({
|
|
1511
1735
|
context: ctx,
|
|
1512
1736
|
json,
|
|
1737
|
+
originalJson: json,
|
|
1738
|
+
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
1739
|
+
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
1513
1740
|
activity,
|
|
1514
1741
|
recipient,
|
|
1515
1742
|
inboxListeners,
|
|
1516
1743
|
inboxContextFactory,
|
|
1744
|
+
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
1517
1745
|
inboxErrorHandler,
|
|
1518
1746
|
kv,
|
|
1519
1747
|
kvPrefixes,
|
|
@@ -1633,8 +1861,8 @@ var CustomCollectionHandler = class {
|
|
|
1633
1861
|
* @param CollectionPage The CollectionPage constructor.
|
|
1634
1862
|
* @param filterPredicate Optional filter predicate for items.
|
|
1635
1863
|
*/
|
|
1636
|
-
constructor(name$
|
|
1637
|
-
this.name = name$
|
|
1864
|
+
constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1865
|
+
this.name = name$2;
|
|
1638
1866
|
this.values = values;
|
|
1639
1867
|
this.context = context;
|
|
1640
1868
|
this.callbacks = callbacks;
|
|
@@ -2337,6 +2565,18 @@ var middleware_exports = /* @__PURE__ */ __exportAll({
|
|
|
2337
2565
|
KvSpecDeterminer: () => KvSpecDeterminer,
|
|
2338
2566
|
createFederation: () => createFederation
|
|
2339
2567
|
});
|
|
2568
|
+
function isRemoteContextLoadingFailure(error) {
|
|
2569
|
+
return error instanceof Error && typeof error.details === "object" && error.details != null && error.details.code === "loading remote context failed";
|
|
2570
|
+
}
|
|
2571
|
+
function isPermanentRemoteContextError(error) {
|
|
2572
|
+
if (!(error instanceof Error) || error.name !== "jsonld.InvalidUrl") return false;
|
|
2573
|
+
const details = error.details;
|
|
2574
|
+
if (details?.code === "invalid remote context") return true;
|
|
2575
|
+
return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
|
|
2576
|
+
}
|
|
2577
|
+
function isPermanentInboxParseError(error) {
|
|
2578
|
+
return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:)/.test(error.message) || isInvalidUrlTypeError(error));
|
|
2579
|
+
}
|
|
2340
2580
|
/**
|
|
2341
2581
|
* Create a new {@link Federation} instance.
|
|
2342
2582
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2668,7 +2908,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2668
2908
|
}
|
|
2669
2909
|
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
2670
2910
|
}
|
|
2671
|
-
async #listenInboxMessage(ctxData, message,
|
|
2911
|
+
async #listenInboxMessage(ctxData, message, _span) {
|
|
2672
2912
|
const logger = getLogger([
|
|
2673
2913
|
"fedify",
|
|
2674
2914
|
"federation",
|
|
@@ -2681,60 +2921,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2681
2921
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2682
2922
|
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) });
|
|
2683
2923
|
}
|
|
2684
|
-
const activity = await Activity.fromJsonLd(message.activity, context);
|
|
2685
|
-
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
2686
|
-
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2687
|
-
const cacheKey = activity.id == null ? null : [
|
|
2688
|
-
...this.kvPrefixes.activityIdempotence,
|
|
2689
|
-
context.origin,
|
|
2690
|
-
activity.id.href
|
|
2691
|
-
];
|
|
2692
|
-
if (cacheKey != null) {
|
|
2693
|
-
if (await this.kv.get(cacheKey) === true) {
|
|
2694
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
2695
|
-
activityId: activity.id?.href,
|
|
2696
|
-
activity: message.activity,
|
|
2697
|
-
recipient: message.identifier
|
|
2698
|
-
});
|
|
2699
|
-
return;
|
|
2700
|
-
}
|
|
2701
|
-
}
|
|
2702
2924
|
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
activityId: activity.id?.href,
|
|
2707
|
-
activity: message.activity,
|
|
2708
|
-
recipient: message.identifier,
|
|
2709
|
-
trial: message.attempt
|
|
2710
|
-
});
|
|
2711
|
-
span.setStatus({
|
|
2712
|
-
code: SpanStatusCode.ERROR,
|
|
2713
|
-
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
2714
|
-
});
|
|
2715
|
-
span.end();
|
|
2716
|
-
return;
|
|
2717
|
-
}
|
|
2718
|
-
const { class: cls, listener } = dispatched;
|
|
2719
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2720
|
-
try {
|
|
2721
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, getTypeId(activity).href), activity);
|
|
2722
|
-
} catch (error) {
|
|
2925
|
+
let activity = null;
|
|
2926
|
+
let cacheKey = null;
|
|
2927
|
+
const reportInboxError = async (error) => {
|
|
2723
2928
|
try {
|
|
2724
2929
|
await this.inboxErrorHandler?.(context, error);
|
|
2725
2930
|
} catch (error) {
|
|
2726
2931
|
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2727
2932
|
error,
|
|
2728
2933
|
trial: message.attempt,
|
|
2729
|
-
activityId: activity
|
|
2934
|
+
activityId: activity?.id?.href,
|
|
2730
2935
|
activity: message.activity,
|
|
2731
2936
|
recipient: message.identifier
|
|
2732
2937
|
});
|
|
2733
2938
|
}
|
|
2939
|
+
};
|
|
2940
|
+
const handleRetriableFailure = async (error) => {
|
|
2941
|
+
await reportInboxError(error);
|
|
2734
2942
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2735
2943
|
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2736
2944
|
error,
|
|
2737
|
-
activityId: activity
|
|
2945
|
+
activityId: activity?.id?.href,
|
|
2738
2946
|
activity: message.activity,
|
|
2739
2947
|
recipient: message.identifier
|
|
2740
2948
|
});
|
|
@@ -2753,17 +2961,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2753
2961
|
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2754
2962
|
error,
|
|
2755
2963
|
attempt: message.attempt,
|
|
2756
|
-
activityId: activity
|
|
2964
|
+
activityId: activity?.id?.href,
|
|
2757
2965
|
activity: message.activity,
|
|
2758
2966
|
recipient: message.identifier
|
|
2759
2967
|
});
|
|
2968
|
+
if (this.inboxQueue == null) {
|
|
2969
|
+
span.setStatus({
|
|
2970
|
+
code: SpanStatusCode.ERROR,
|
|
2971
|
+
message: String(error)
|
|
2972
|
+
});
|
|
2973
|
+
span.end();
|
|
2974
|
+
throw error;
|
|
2975
|
+
}
|
|
2760
2976
|
await this.inboxQueue?.enqueue({
|
|
2761
2977
|
...message,
|
|
2762
2978
|
attempt: message.attempt + 1
|
|
2763
2979
|
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2764
2980
|
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2765
2981
|
error,
|
|
2766
|
-
activityId: activity
|
|
2982
|
+
activityId: activity?.id?.href,
|
|
2767
2983
|
activity: message.activity,
|
|
2768
2984
|
recipient: message.identifier
|
|
2769
2985
|
});
|
|
@@ -2772,11 +2988,108 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2772
2988
|
message: String(error)
|
|
2773
2989
|
});
|
|
2774
2990
|
span.end();
|
|
2991
|
+
};
|
|
2992
|
+
let dispatched;
|
|
2993
|
+
let parseInput = void 0;
|
|
2994
|
+
let parseContextLoader = context.contextLoader;
|
|
2995
|
+
try {
|
|
2996
|
+
const hasSignatureField = hasSignature(message.activity);
|
|
2997
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
2998
|
+
const parseContext = hasSignatureField ? {
|
|
2999
|
+
...context,
|
|
3000
|
+
contextLoader: getNormalizationContextLoader(context.contextLoader)
|
|
3001
|
+
} : {
|
|
3002
|
+
...context,
|
|
3003
|
+
contextLoader: wrapContextLoaderForJsonLd(context.contextLoader)
|
|
3004
|
+
};
|
|
3005
|
+
parseContextLoader = parseContext.contextLoader;
|
|
3006
|
+
let normalizedActivity;
|
|
3007
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
3008
|
+
normalizedActivity = message.normalizedActivity ?? await compactJsonLd(message.activity, context.contextLoader);
|
|
3009
|
+
assertSafeJsonLd(normalizedActivity);
|
|
3010
|
+
}
|
|
3011
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? detachSignature(normalizedActivity) : hasSignatureField ? detachSignature(message.activity) : message.activity;
|
|
3012
|
+
activity = await Activity.fromJsonLd(parseInput, parseContext);
|
|
3013
|
+
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
3014
|
+
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
3015
|
+
cacheKey = activity.id == null ? null : [
|
|
3016
|
+
...this.kvPrefixes.activityIdempotence,
|
|
3017
|
+
context.origin,
|
|
3018
|
+
activity.id.href
|
|
3019
|
+
];
|
|
3020
|
+
if (cacheKey != null) {
|
|
3021
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
3022
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
3023
|
+
activityId: activity.id?.href,
|
|
3024
|
+
activity: message.activity,
|
|
3025
|
+
recipient: message.identifier
|
|
3026
|
+
});
|
|
3027
|
+
span.end();
|
|
3028
|
+
return;
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
3032
|
+
} catch (error) {
|
|
3033
|
+
if (activity == null && error instanceof RangeError && await hasMalformedKnownTemporalLiteral(parseInput, parseContextLoader)) {
|
|
3034
|
+
await reportInboxError(error);
|
|
3035
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3036
|
+
error,
|
|
3037
|
+
trial: message.attempt,
|
|
3038
|
+
activityId: null,
|
|
3039
|
+
activity: message.activity,
|
|
3040
|
+
recipient: message.identifier
|
|
3041
|
+
});
|
|
3042
|
+
span.setStatus({
|
|
3043
|
+
code: SpanStatusCode.ERROR,
|
|
3044
|
+
message: String(error)
|
|
3045
|
+
});
|
|
3046
|
+
span.end();
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
3049
|
+
if (isPermanentInboxParseError(error)) {
|
|
3050
|
+
await reportInboxError(error);
|
|
3051
|
+
logger.error("Failed to parse the queued incoming activity {activityId}:\n{error}", {
|
|
3052
|
+
error,
|
|
3053
|
+
trial: message.attempt,
|
|
3054
|
+
activityId: activity?.id?.href,
|
|
3055
|
+
activity: message.activity,
|
|
3056
|
+
recipient: message.identifier
|
|
3057
|
+
});
|
|
3058
|
+
span.setStatus({
|
|
3059
|
+
code: SpanStatusCode.ERROR,
|
|
3060
|
+
message: String(error)
|
|
3061
|
+
});
|
|
3062
|
+
span.end();
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
await handleRetriableFailure(error);
|
|
3066
|
+
return;
|
|
3067
|
+
}
|
|
3068
|
+
if (dispatched == null) {
|
|
3069
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
3070
|
+
activityId: activity.id?.href,
|
|
3071
|
+
activity: message.activity,
|
|
3072
|
+
recipient: message.identifier,
|
|
3073
|
+
trial: message.attempt
|
|
3074
|
+
});
|
|
3075
|
+
span.setStatus({
|
|
3076
|
+
code: SpanStatusCode.ERROR,
|
|
3077
|
+
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
3078
|
+
});
|
|
3079
|
+
span.end();
|
|
3080
|
+
return;
|
|
3081
|
+
}
|
|
3082
|
+
const { class: cls, listener } = dispatched;
|
|
3083
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
3084
|
+
try {
|
|
3085
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, getTypeId(activity).href), activity);
|
|
3086
|
+
} catch (error) {
|
|
3087
|
+
await handleRetriableFailure(error);
|
|
2775
3088
|
return;
|
|
2776
3089
|
}
|
|
2777
3090
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2778
3091
|
logger.info("Activity {activityId} has been processed.", {
|
|
2779
|
-
activityId: activity
|
|
3092
|
+
activityId: activity?.id?.href,
|
|
2780
3093
|
activity: message.activity,
|
|
2781
3094
|
recipient: message.identifier
|
|
2782
3095
|
});
|
|
@@ -3098,16 +3411,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3098
3411
|
onNotAcceptable
|
|
3099
3412
|
});
|
|
3100
3413
|
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier ?? route.values.handle }) });
|
|
3101
|
-
case "sharedInbox":
|
|
3414
|
+
case "sharedInbox": {
|
|
3102
3415
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3103
3416
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3104
3417
|
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) });
|
|
3105
3418
|
}
|
|
3106
3419
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3420
|
+
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
3421
|
+
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
3107
3422
|
return await handleInbox(request, {
|
|
3108
3423
|
recipient: route.values.identifier ?? route.values.handle ?? null,
|
|
3109
3424
|
context,
|
|
3110
|
-
inboxContextFactory
|
|
3425
|
+
inboxContextFactory,
|
|
3111
3426
|
kv: this.kv,
|
|
3112
3427
|
kvPrefixes: this.kvPrefixes,
|
|
3113
3428
|
queue: this.inboxQueue,
|
|
@@ -3120,6 +3435,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3120
3435
|
tracerProvider: this.tracerProvider,
|
|
3121
3436
|
idempotencyStrategy: this.idempotencyStrategy
|
|
3122
3437
|
});
|
|
3438
|
+
}
|
|
3123
3439
|
case "following": return await handleCollection(request, {
|
|
3124
3440
|
name: "following",
|
|
3125
3441
|
identifier: route.values.identifier ?? route.values.handle,
|
|
@@ -3870,6 +4186,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3870
4186
|
const routeResult = await routeActivity({
|
|
3871
4187
|
context: this,
|
|
3872
4188
|
json,
|
|
4189
|
+
ldSignatureVerified: false,
|
|
3873
4190
|
activity,
|
|
3874
4191
|
recipient,
|
|
3875
4192
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -3968,6 +4285,14 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
3968
4285
|
};
|
|
3969
4286
|
var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
3970
4287
|
recipient;
|
|
4288
|
+
/**
|
|
4289
|
+
* The original received activity payload.
|
|
4290
|
+
*
|
|
4291
|
+
* Fedify may normalize a Linked Data Signature payload internally for safe
|
|
4292
|
+
* parsing, but forwarding must keep the sender's payload unchanged so
|
|
4293
|
+
* third-party signatures/proofs remain intact.
|
|
4294
|
+
* @internal
|
|
4295
|
+
*/
|
|
3971
4296
|
activity;
|
|
3972
4297
|
activityId;
|
|
3973
4298
|
activityType;
|