@fedify/fedify 1.10.8 → 1.10.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/{actor-stZ3L5bm.mjs → actor-DZtfiGD5.mjs} +1 -1
  2. package/dist/{actor-BtdqoffI.js → actor-q2gTvEOg.js} +187 -187
  3. package/dist/{actor-CHbT9hXW.cjs → actor-yCME0Muf.cjs} +187 -187
  4. package/dist/{authdocloader-qSZCRtME.cjs → authdocloader-C9ucnURr.cjs} +3 -3
  5. package/dist/{authdocloader-BjFtWv8Q.js → authdocloader-CjcVKv5l.js} +3 -3
  6. package/dist/{authdocloader-DiNlCuEL.mjs → authdocloader-Dxs4mL_P.mjs} +3 -3
  7. package/dist/{builder-C06p3NRV.mjs → builder-DBBCeuJN.mjs} +4 -4
  8. package/dist/{client-aAP3RFq_.mjs → client-DfSKNItx.mjs} +1 -1
  9. package/dist/compat/mod.cjs +1 -1
  10. package/dist/compat/mod.d.cts +1 -1
  11. package/dist/compat/mod.d.ts +1 -1
  12. package/dist/compat/transformers.test.mjs +3 -3
  13. package/dist/{context-BzSr5FCW.d.cts → context-CC4UrGc5.d.cts} +48 -6
  14. package/dist/{context-CyacVopT.d.ts → context-xfiK4xM5.d.ts} +48 -6
  15. package/dist/{docloader-Cms83CjK.js → docloader-D8qb26Gj.js} +12 -3
  16. package/dist/{docloader--HMTXXhM.cjs → docloader-DR98w4wL.cjs} +12 -3
  17. package/dist/{esm-CfjSLJ-h.mjs → esm-onODA711.mjs} +1 -1
  18. package/dist/federation/builder.test.mjs +3 -3
  19. package/dist/federation/collection.test.mjs +1 -1
  20. package/dist/federation/handler.test.mjs +1362 -46
  21. package/dist/federation/idempotency.test.mjs +5 -5
  22. package/dist/federation/inbox.test.mjs +3 -3
  23. package/dist/federation/keycache.test.mjs +3 -3
  24. package/dist/federation/kv.test.mjs +1 -1
  25. package/dist/federation/middleware.test.mjs +1586 -82
  26. package/dist/federation/mod.cjs +2 -2
  27. package/dist/federation/mod.d.cts +1 -1
  28. package/dist/federation/mod.d.ts +1 -1
  29. package/dist/federation/mod.js +1 -1
  30. package/dist/federation/mq.test.mjs +3 -3
  31. package/dist/federation/retry.test.mjs +2 -2
  32. package/dist/federation/router.test.mjs +2 -2
  33. package/dist/federation/send.test.mjs +8 -8
  34. package/dist/federation/temporal.test.d.mts +2 -0
  35. package/dist/federation/temporal.test.mjs +71 -0
  36. package/dist/{http-CDZB3DBW.js → http-D6Qz3p20.js} +3 -3
  37. package/dist/{http-BPQ_zPRB.mjs → http-DyCX-dN3.mjs} +2 -2
  38. package/dist/{http-Bg-OkZtX.cjs → http-mdiWJYia.cjs} +3 -3
  39. package/dist/{inbox-Cnih7u27.mjs → inbox-BZN50kyQ.mjs} +7 -4
  40. package/dist/{key-C16D-kud.mjs → key-CSH0Pfat.mjs} +2 -2
  41. package/dist/{key-DGuUMBsU.cjs → key-DPzMtgeE.cjs} +1 -1
  42. package/dist/{key-Bbf-ITpM.cjs → key-DRfL8gil.cjs} +2 -2
  43. package/dist/{key-B0qYOng3.mjs → key-DXUAJBZu.mjs} +1 -1
  44. package/dist/{key-ASS7oK8n.js → key-TRp8WTUL.js} +2 -2
  45. package/dist/{keycache-CBPbgb7d.mjs → keycache-DETDxpbh.mjs} +1 -1
  46. package/dist/{keys-Br4iedk3.mjs → keys-8FIoKqmB.mjs} +1 -1
  47. package/dist/ld-BaJmhpEa.mjs +548 -0
  48. package/dist/{lookup-CA5RreoS.cjs → lookup-B7TLaXFf.cjs} +1 -1
  49. package/dist/{lookup-CpMB-hV5.js → lookup-C6wM-gq1.js} +1 -1
  50. package/dist/{lookup-CCcDhxO2.mjs → lookup-CX2yfN-X.mjs} +1 -1
  51. package/dist/{middleware-Bi5LcEMF.mjs → middleware-BJ7otoEC.mjs} +1 -1
  52. package/dist/{middleware-Crs1EVL7.mjs → middleware-BQ6evC7E.mjs} +320 -87
  53. package/dist/{middleware-BDTuu7QY.js → middleware-BXc5M6YG.js} +408 -83
  54. package/dist/{middleware-C90kKt44.cjs → middleware-DpVqFb2x.cjs} +411 -85
  55. package/dist/{middleware-BPTDstS-.cjs → middleware-cNynSnF6.cjs} +1 -1
  56. package/dist/mod.cjs +10 -10
  57. package/dist/mod.d.cts +1 -1
  58. package/dist/mod.d.ts +1 -1
  59. package/dist/mod.js +9 -9
  60. package/dist/nodeinfo/client.test.mjs +3 -3
  61. package/dist/nodeinfo/handler.test.mjs +2 -2
  62. package/dist/nodeinfo/mod.cjs +1 -1
  63. package/dist/nodeinfo/mod.js +1 -1
  64. package/dist/nodeinfo/semver.test.mjs +1 -1
  65. package/dist/nodeinfo/types.test.mjs +1 -1
  66. package/dist/otel/exporter.test.mjs +1 -1
  67. package/dist/otel/mod.cjs +1 -1
  68. package/dist/{owner-ncOJW9jU.mjs → owner-CLGVwm9P.mjs} +3 -3
  69. package/dist/{proof-BYdxNk_7.cjs → proof-BVB37JmB.cjs} +347 -5
  70. package/dist/{proof-Bd732W1s.mjs → proof-CAOvY-AP.mjs} +2 -2
  71. package/dist/{proof-JCn_Nftz.js → proof-DxQL08gJ.js} +300 -6
  72. package/dist/runtime/authdocloader.test.mjs +6 -6
  73. package/dist/runtime/docloader.test.mjs +4 -4
  74. package/dist/runtime/key.test.mjs +3 -3
  75. package/dist/runtime/langstr.test.mjs +2 -2
  76. package/dist/runtime/link.test.mjs +2 -2
  77. package/dist/runtime/mod.cjs +3 -3
  78. package/dist/runtime/mod.js +3 -3
  79. package/dist/runtime/multibase/multibase.test.mjs +2 -2
  80. package/dist/runtime/url.test.mjs +5 -2
  81. package/dist/{send-BUUNtAjI.mjs → send-BFClgq8T.mjs} +2 -2
  82. package/dist/sig/http.test.mjs +6 -6
  83. package/dist/sig/key.test.mjs +4 -4
  84. package/dist/sig/ld.test.mjs +561 -5
  85. package/dist/sig/mod.cjs +3 -3
  86. package/dist/sig/mod.js +3 -3
  87. package/dist/sig/owner.test.mjs +6 -6
  88. package/dist/sig/proof.test.mjs +4 -4
  89. package/dist/temporal-lmewfA7Y.mjs +95 -0
  90. package/dist/testing/docloader.test.mjs +1 -1
  91. package/dist/testing/mod.d.mts +48 -6
  92. package/dist/testing/mod.mjs +1 -1
  93. package/dist/{testing-CvmsaHLW.mjs → testing-B9FmxxlI.mjs} +2 -2
  94. package/dist/{transformers-Cd6Tdn3M.cjs → transformers-KRl8YJCO.cjs} +1 -1
  95. package/dist/{types-Dy8sMtkH.js → types-B0aIcMDF.js} +1 -1
  96. package/dist/{types-BVCtDIwE.cjs → types-DPWiFqle.cjs} +1 -1
  97. package/dist/vocab/actor.test.mjs +4 -4
  98. package/dist/vocab/cjs.test.mjs +1 -1
  99. package/dist/vocab/lookup.test.mjs +5 -5
  100. package/dist/vocab/mod.cjs +3 -3
  101. package/dist/vocab/mod.js +3 -3
  102. package/dist/vocab/type.test.mjs +2 -2
  103. package/dist/vocab/vocab.test.mjs +3 -3
  104. package/dist/{vocab-DcYXFzyR.mjs → vocab-DP9A9TjH.mjs} +197 -188
  105. package/dist/webfinger/handler.test.mjs +3 -3
  106. package/dist/webfinger/lookup.test.mjs +3 -3
  107. package/dist/webfinger/mod.cjs +1 -1
  108. package/dist/webfinger/mod.js +1 -1
  109. package/dist/x/cfworkers.cjs +1 -1
  110. package/dist/x/cfworkers.test.mjs +1 -1
  111. package/dist/x/hono.cjs +1 -1
  112. package/dist/x/hono.d.cts +1 -1
  113. package/dist/x/hono.d.ts +1 -1
  114. package/dist/x/sveltekit.cjs +1 -1
  115. package/dist/x/sveltekit.d.cts +1 -1
  116. package/dist/x/sveltekit.d.ts +1 -1
  117. package/package.json +1 -1
  118. package/dist/ld-7nQ68-rS.mjs +0 -254
  119. /package/dist/{denokv-NJPMXyK0.mjs → denokv-B0ZRIDsH.mjs} +0 -0
  120. /package/dist/{otel-0v4Zy01l.mjs → otel-D00WjYJ1.mjs} +0 -0
  121. /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-Cms83CjK.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-BtdqoffI.js";
7
- import { t as lookupWebFinger } from "./lookup-CpMB-hV5.js";
8
- import { i as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-ASS7oK8n.js";
9
- import { r as verifyRequest, t as doubleKnock } from "./http-CDZB3DBW.js";
10
- import { a as doesActorOwnKey, d as signJsonLd, f as verifyJsonLd, l as detachSignature, n as signObject, o as getKeyOwner, r as verifyObject, u as hasSignature } from "./proof-JCn_Nftz.js";
11
- import { n as getNodeInfo, t as nodeInfoToJson } from "./types-Dy8sMtkH.js";
12
- import { t as getAuthenticatedDocumentLoader } from "./authdocloader-BjFtWv8Q.js";
5
+ import { d as name, f as version, i as getDocumentLoader, s as kvCache } from "./docloader-D8qb26Gj.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-q2gTvEOg.js";
7
+ import { t as lookupWebFinger } from "./lookup-C6wM-gq1.js";
8
+ import { i as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-TRp8WTUL.js";
9
+ import { r as verifyRequest, t as doubleKnock } from "./http-D6Qz3p20.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-DxQL08gJ.js";
11
+ import { n as getNodeInfo, t as nodeInfoToJson } from "./types-B0aIcMDF.js";
12
+ import { t as getAuthenticatedDocumentLoader } from "./authdocloader-CjcVKv5l.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
- await listener(inboxContextFactory(recipient, json, activity?.id?.href, getTypeId(activity).href), activity);
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$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound, onNotAcceptable }) {
1110
- const spanName = name$2.trim().replace(/\s+/g, "_");
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$2, filterPredicate)
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$2}`, {
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$2, filterPredicate),
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
- let ldSigVerified;
1387
- try {
1388
- ldSigVerified = await verifyJsonLd(json, {
1389
- contextLoader: ctx.contextLoader,
1390
- documentLoader: ctx.documentLoader,
1391
- keyCache,
1392
- tracerProvider
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
- } catch (error) {
1395
- if (error instanceof Error && error.name === "jsonld.SyntaxError") {
1396
- logger.error("Failed to parse JSON-LD:\n{error}", {
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
- ldSigVerified = false;
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
- activity = await Activity.fromJsonLd(jsonWithoutSig, ctx);
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
- activity = await Activity.fromJsonLd(jsonWithoutSig, ctx);
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$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
1637
- this.name = name$1;
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, span) {
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
- const dispatched = this.inboxListeners?.dispatchWithClass(activity);
2704
- if (dispatched == null) {
2705
- logger.error("Unsupported activity type:\n{activity}", {
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.id?.href,
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.id?.href,
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.id?.href,
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.id?.href,
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.id?.href,
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: context.toInboxContext.bind(context),
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;