@fedify/fedify 2.5.0-dev.2378 → 2.5.0-dev.2424
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-J1K0IJj6.mjs → builder-crKu0U3j.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/{compound-proof-DtmVrMV7.mjs → compound-proof-D5pMfQau.mjs} +2 -2
- package/dist/{context-C2-UDo2c.d.ts → context-2wLkQrjb.d.ts} +11 -0
- package/dist/{context-BjD_CTxh.d.cts → context-DPocjp1l.d.cts} +11 -0
- package/dist/{deno-Ci6tSK9-.mjs → deno-Dgtb5dvg.mjs} +1 -1
- package/dist/{docloader-DZ9h6KJS.mjs → docloader-C8QI5jg2.mjs} +4 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +5 -5
- package/dist/federation/handler.test.mjs +258 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox-report.test.mjs +30 -5
- package/dist/federation/inbox.test.mjs +43 -0
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +254 -11
- 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/outgoing-proof.test.mjs +4 -4
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.mjs +3 -3
- package/dist/federation/portable-collection.test.mjs +4 -4
- package/dist/federation/portable-delivery.test.mjs +2 -2
- package/dist/federation/portable-gateway-keys.test.mjs +4 -4
- package/dist/federation/portable-inbox.test.mjs +4 -4
- package/dist/federation/portable-parse-uri.test.mjs +1 -1
- package/dist/federation/portable-route-activity.test.mjs +2 -2
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{federation-lzy7M3hT.cjs → federation-XZF9Yna_.cjs} +133 -21
- package/dist/{http-CFyizTHa.mjs → http-CO8l72H1.mjs} +4 -4
- package/dist/{http-Cmz7x6Iw.js → http-CRRQ6LBq.js} +1 -1
- package/dist/{http-D1RPHoq3.cjs → http-DZpLusNJ.cjs} +1 -1
- package/dist/inbox-q6uJubdj.mjs +188 -0
- package/dist/{kv-cache-rOQX3I3c.mjs → kv-cache-C-20uhXH.mjs} +1 -1
- package/dist/{kv-cache-C0-HuvwP.js → kv-cache-D5EHCk1_.js} +3 -1
- package/dist/{kv-cache-Jym5nP3J.cjs → kv-cache-DB0oTO06.cjs} +3 -1
- package/dist/{ld-DJ--ZUpr.mjs → ld-DqV2dhgT.mjs} +2 -2
- package/dist/{metrics-Dwgav7s_.mjs → metrics--5oGNIHa.mjs} +1 -1
- package/dist/{middleware-BbBsa5iR.mjs → middleware-BahtLJeT.mjs} +115 -180
- package/dist/{middleware-CJWxuUy5.mjs → middleware-Cna-mkwy.mjs} +1 -1
- package/dist/{middleware-CqgRIsWM.js → middleware-Mn7MeLDZ.js} +133 -21
- package/dist/{mod-BBPd4M_0.d.cts → mod-DKGoPoQC.d.cts} +1 -1
- package/dist/{mod-CUYBGKof.d.ts → mod-Dm-7RdhR.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +2 -2
- package/dist/mod.d.ts +2 -2
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-Btd7SwMj.mjs → owner-Cb6Kalag.mjs} +3 -3
- package/dist/{portable-collection-DwQT28O2.js → portable-collection-BweSVeOo.js} +1 -1
- package/dist/{portable-collection-BvWxS1sL.cjs → portable-collection-C3FBNHhB.cjs} +1 -1
- package/dist/{portable-collection-gb9V8XEO.mjs → portable-collection-DatZLGgt.mjs} +2 -2
- package/dist/{portable-key-Cwti99nP.mjs → portable-key-C2jzDc2S.mjs} +1 -1
- package/dist/{proof-Bwzv6mXZ.mjs → proof-BpQd-cat.mjs} +3 -3
- package/dist/{send-BrQYUSb4.mjs → send-CrgC-GYC.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.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 +1 -1
- package/dist/sig/mitra-receive-interop.test.mjs +4 -4
- package/dist/sig/mitra-send-interop.test.mjs +3 -3
- 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/portable-collection.test.mjs +1 -1
- package/dist/sig/portable-interop.test.mjs +3 -3
- package/dist/sig/portable-key.test.mjs +5 -5
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/sig/tootik-request-interop.test.mjs +4 -4
- package/dist/sig/tootik-send-interop.test.mjs +3 -3
- package/dist/sig/verification.test.mjs +3 -3
- package/dist/{temporal-BRaCTxVe.mjs → temporal-BjBxALiF.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +11 -0
- package/dist/utils/docloader.test.mjs +112 -37
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
|
@@ -4,27 +4,28 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { d as isPortableUri, f as isSameObjectId, i as getPortableDid, l as isPortableId, n as getCanonicalPortableId, o as hasPortableActor, r as getGatewayKeyBase, s as isCompatibleKeyId, t as getAuthenticationOrigin, u as isPortableKeyId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
5
5
|
import { n as isPubliclyAddressedNode, t as isInAudience } from "./audience-CHQ-FlLD.mjs";
|
|
6
6
|
import { a as verificationObservation, r as snapshotKey, t as observeAttempt } from "./verification-Dpfcw8ml.mjs";
|
|
7
|
-
import { n as version, t as name } from "./deno-
|
|
8
|
-
import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics
|
|
7
|
+
import { n as version, t as name } from "./deno-Dgtb5dvg.mjs";
|
|
8
|
+
import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics--5oGNIHa.mjs";
|
|
9
9
|
import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
10
|
-
import { T as validateCryptoKey, _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike, w as importJwk, y as exportJwk } from "./ld-
|
|
10
|
+
import { T as validateCryptoKey, _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike, w as importJwk, y as exportJwk } from "./ld-DqV2dhgT.mjs";
|
|
11
11
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
|
|
12
|
-
import { c as verifyObject, d as verifyPortableObjectProofWithRoot, i as hasProofLike, l as verifyPortableObjectProof, o as signObject, t as InvalidPortableObjectIdError } from "./proof-
|
|
13
|
-
import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-
|
|
14
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
15
|
-
import { n as kvCache } from "./kv-cache-
|
|
12
|
+
import { c as verifyObject, d as verifyPortableObjectProofWithRoot, i as hasProofLike, l as verifyPortableObjectProof, o as signObject, t as InvalidPortableObjectIdError } from "./proof-BpQd-cat.mjs";
|
|
13
|
+
import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-CO8l72H1.mjs";
|
|
14
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-C8QI5jg2.mjs";
|
|
15
|
+
import { n as kvCache } from "./kv-cache-C-20uhXH.mjs";
|
|
16
16
|
import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-CEnNz8O7.mjs";
|
|
17
17
|
import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
|
|
18
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
19
|
-
import { t as verifyPortableObject } from "./portable-collection-
|
|
20
|
-
import { a as getOrderingDestination, i as sendActivityThroughGateways, n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-
|
|
21
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
18
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-Cb6Kalag.mjs";
|
|
19
|
+
import { t as verifyPortableObject } from "./portable-collection-DatZLGgt.mjs";
|
|
20
|
+
import { a as getOrderingDestination, i as sendActivityThroughGateways, n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CrgC-GYC.mjs";
|
|
21
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-crKu0U3j.mjs";
|
|
22
22
|
import { t as CircuitBreaker } from "./circuit-breaker-XJ53md4S.mjs";
|
|
23
23
|
import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
|
|
24
|
-
import { a as inspectCompoundPortableObjectApplicability, c as verifyServedPortableObjects, i as findUnsupportedCompoundProofShape, o as verifyCompoundPortableObjectProofs, r as findEmbeddedProofWithoutContext, t as containsCompoundPortableObject } from "./compound-proof-
|
|
24
|
+
import { a as inspectCompoundPortableObjectApplicability, c as verifyServedPortableObjects, i as findUnsupportedCompoundProofShape, o as verifyCompoundPortableObjectProofs, r as findEmbeddedProofWithoutContext, t as containsCompoundPortableObject } from "./compound-proof-D5pMfQau.mjs";
|
|
25
|
+
import { n as routeActivity, t as actorsHaveSameOrigin } from "./inbox-q6uJubdj.mjs";
|
|
25
26
|
import { t as KvKeyCache } from "./keycache-D-MNltOk.mjs";
|
|
26
27
|
import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
|
|
27
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
28
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-BjBxALiF.mjs";
|
|
28
29
|
import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
|
|
29
30
|
import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
|
|
30
31
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
@@ -638,164 +639,6 @@ function visitJsonMaps(json, visit) {
|
|
|
638
639
|
}
|
|
639
640
|
}
|
|
640
641
|
//#endregion
|
|
641
|
-
//#region src/federation/inbox.ts
|
|
642
|
-
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, meterProvider, tracerProvider, idempotencyStrategy }) {
|
|
643
|
-
const logger = getLogger([
|
|
644
|
-
"fedify",
|
|
645
|
-
"federation",
|
|
646
|
-
"inbox"
|
|
647
|
-
]);
|
|
648
|
-
let cacheKey = null;
|
|
649
|
-
if (activity.id != null) {
|
|
650
|
-
const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
|
|
651
|
-
const strategy = idempotencyStrategy ?? "per-inbox";
|
|
652
|
-
let keyString;
|
|
653
|
-
if (typeof strategy === "function") keyString = await strategy(inboxContext, activity);
|
|
654
|
-
else switch (strategy) {
|
|
655
|
-
case "global":
|
|
656
|
-
keyString = activity.id.href;
|
|
657
|
-
break;
|
|
658
|
-
case "per-origin":
|
|
659
|
-
keyString = `${ctx.origin}\n${activity.id.href}`;
|
|
660
|
-
break;
|
|
661
|
-
case "per-inbox":
|
|
662
|
-
keyString = `${ctx.origin}\n${activity.id.href}\n${recipient == null ? "sharedInbox" : `inbox\n${recipient}`}`;
|
|
663
|
-
break;
|
|
664
|
-
default: keyString = `${ctx.origin}\n${activity.id.href}`;
|
|
665
|
-
}
|
|
666
|
-
if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
|
|
667
|
-
}
|
|
668
|
-
if (cacheKey != null) {
|
|
669
|
-
if (await kv.get(cacheKey) === true) {
|
|
670
|
-
logger.debug("Activity {activityId} has already been processed.", {
|
|
671
|
-
activityId: activity.id?.href,
|
|
672
|
-
activity: json,
|
|
673
|
-
recipient
|
|
674
|
-
});
|
|
675
|
-
span.setStatus({
|
|
676
|
-
code: SpanStatusCode.UNSET,
|
|
677
|
-
message: `Activity ${activity.id?.href} has already been processed.`
|
|
678
|
-
});
|
|
679
|
-
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
680
|
-
return "alreadyProcessed";
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
if (activity.actorId == null) {
|
|
684
|
-
logger.error("Missing actor.", { activity: json });
|
|
685
|
-
span.setStatus({
|
|
686
|
-
code: SpanStatusCode.ERROR,
|
|
687
|
-
message: "Missing actor."
|
|
688
|
-
});
|
|
689
|
-
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
690
|
-
return "missingActor";
|
|
691
|
-
}
|
|
692
|
-
span.setAttribute("activitypub.actor.id", activity.actorId.href);
|
|
693
|
-
if (queue != null) {
|
|
694
|
-
const carrier = {};
|
|
695
|
-
propagation.inject(context.active(), carrier);
|
|
696
|
-
try {
|
|
697
|
-
await queue.enqueue({
|
|
698
|
-
type: "inbox",
|
|
699
|
-
id: crypto.randomUUID(),
|
|
700
|
-
baseUrl: ctx.origin,
|
|
701
|
-
activity: originalJson ?? json,
|
|
702
|
-
...normalizedActivity == null ? {} : { normalizedActivity },
|
|
703
|
-
...ldSignatureVerified == null ? {} : { ldSignatureVerified },
|
|
704
|
-
identifier: recipient,
|
|
705
|
-
attempt: 0,
|
|
706
|
-
started: (/* @__PURE__ */ new Date()).toISOString(),
|
|
707
|
-
traceContext: carrier
|
|
708
|
-
});
|
|
709
|
-
} catch (error) {
|
|
710
|
-
logger.error("Failed to enqueue the incoming activity {activityId}:\n{error}", {
|
|
711
|
-
error,
|
|
712
|
-
activityId: activity.id?.href,
|
|
713
|
-
activity: json,
|
|
714
|
-
recipient
|
|
715
|
-
});
|
|
716
|
-
span.setStatus({
|
|
717
|
-
code: SpanStatusCode.ERROR,
|
|
718
|
-
message: `Failed to enqueue the incoming activity ${activity.id?.href}.`
|
|
719
|
-
});
|
|
720
|
-
throw error;
|
|
721
|
-
}
|
|
722
|
-
getFederationMetrics(meterProvider).recordQueueTaskEnqueued({
|
|
723
|
-
role: "inbox",
|
|
724
|
-
queue,
|
|
725
|
-
activityType: getTypeId(activity).href
|
|
726
|
-
}, 0);
|
|
727
|
-
recordInboxActivity(meterProvider, "queued", getTypeId(activity).href);
|
|
728
|
-
logger.info("Activity {activityId} is enqueued.", {
|
|
729
|
-
activityId: activity.id?.href,
|
|
730
|
-
activity: json,
|
|
731
|
-
recipient
|
|
732
|
-
});
|
|
733
|
-
return "enqueued";
|
|
734
|
-
}
|
|
735
|
-
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
736
|
-
return await tracerProvider.getTracer(name, version).startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
|
|
737
|
-
const dispatched = inboxListeners?.dispatchWithClass(activity);
|
|
738
|
-
if (dispatched == null) {
|
|
739
|
-
logger.error("Unsupported activity type:\n{activity}", {
|
|
740
|
-
activity: json,
|
|
741
|
-
recipient
|
|
742
|
-
});
|
|
743
|
-
span.setStatus({
|
|
744
|
-
code: SpanStatusCode.UNSET,
|
|
745
|
-
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
746
|
-
});
|
|
747
|
-
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
748
|
-
span.end();
|
|
749
|
-
return "unsupportedActivity";
|
|
750
|
-
}
|
|
751
|
-
const { class: cls, listener } = dispatched;
|
|
752
|
-
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
753
|
-
try {
|
|
754
|
-
const activityType = getTypeId(activity).href;
|
|
755
|
-
const started = performance.now();
|
|
756
|
-
try {
|
|
757
|
-
const contextFactory = listenerInboxContextFactory ?? inboxContextFactory;
|
|
758
|
-
await listener(contextFactory(recipient, contextFactory === inboxContextFactory ? json : originalJson ?? json, activity.id?.href, activityType), activity);
|
|
759
|
-
} finally {
|
|
760
|
-
getFederationMetrics(meterProvider).recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
761
|
-
}
|
|
762
|
-
} catch (error) {
|
|
763
|
-
try {
|
|
764
|
-
await inboxErrorHandler?.(ctx, error);
|
|
765
|
-
} catch (error) {
|
|
766
|
-
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
767
|
-
error,
|
|
768
|
-
activityId: activity.id?.href,
|
|
769
|
-
activity: json,
|
|
770
|
-
recipient
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
logger.error("Failed to process the incoming activity {activityId}:\n{error}", {
|
|
774
|
-
error,
|
|
775
|
-
activityId: activity.id?.href,
|
|
776
|
-
activity: json,
|
|
777
|
-
recipient
|
|
778
|
-
});
|
|
779
|
-
span.setStatus({
|
|
780
|
-
code: SpanStatusCode.ERROR,
|
|
781
|
-
message: String(error)
|
|
782
|
-
});
|
|
783
|
-
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
784
|
-
span.end();
|
|
785
|
-
return "error";
|
|
786
|
-
}
|
|
787
|
-
recordInboxActivity(meterProvider, "processed", getTypeId(activity).href);
|
|
788
|
-
if (cacheKey != null) await kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
789
|
-
logger.info("Activity {activityId} has been processed.", {
|
|
790
|
-
activityId: activity.id?.href,
|
|
791
|
-
activity: json,
|
|
792
|
-
recipient
|
|
793
|
-
});
|
|
794
|
-
span.end();
|
|
795
|
-
return "success";
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
//#endregion
|
|
799
642
|
//#region src/federation/portable.ts
|
|
800
643
|
/**
|
|
801
644
|
* The media type that FEP-ef61 gateways must use for portable objects.
|
|
@@ -1725,13 +1568,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
1725
1568
|
* @param parameters The parameters for handling the collection.
|
|
1726
1569
|
* @returns A promise that resolves to an HTTP response.
|
|
1727
1570
|
*/
|
|
1728
|
-
async function handleCollection(request, { name: name$
|
|
1729
|
-
const spanName = name$
|
|
1571
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
1572
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
1730
1573
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1731
1574
|
const tracer = tracerProvider.getTracer(name, version);
|
|
1732
1575
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1733
1576
|
const metricBase = {
|
|
1734
|
-
kind: getCollectionMetricKind(name$
|
|
1577
|
+
kind: getCollectionMetricKind(name$2),
|
|
1735
1578
|
page: cursor != null,
|
|
1736
1579
|
dispatcher: "built_in"
|
|
1737
1580
|
};
|
|
@@ -1777,7 +1620,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
1777
1620
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1778
1621
|
return await onNotFound(request);
|
|
1779
1622
|
}
|
|
1780
|
-
const items = filterCollectionItems(page.items, name$
|
|
1623
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
1781
1624
|
itemCount = items.length;
|
|
1782
1625
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
1783
1626
|
return items;
|
|
@@ -1819,7 +1662,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
1819
1662
|
} else {
|
|
1820
1663
|
const uri = new URL(portable == null ? baseUri : pageBase);
|
|
1821
1664
|
uri.searchParams.set("cursor", cursor);
|
|
1822
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1665
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
1823
1666
|
kind: SpanKind.SERVER,
|
|
1824
1667
|
attributes: {
|
|
1825
1668
|
"activitypub.collection.id": uri.href,
|
|
@@ -1835,7 +1678,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
1835
1678
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1836
1679
|
return await onNotFound(request);
|
|
1837
1680
|
}
|
|
1838
|
-
const items = filterCollectionItems(page.items, name$
|
|
1681
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
1839
1682
|
itemCount = items.length;
|
|
1840
1683
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
1841
1684
|
return {
|
|
@@ -2988,11 +2831,53 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2988
2831
|
return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
2989
2832
|
}
|
|
2990
2833
|
}
|
|
2834
|
+
if (!skipSignatureVerification && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
2835
|
+
observation.authentication = {
|
|
2836
|
+
status: "rejected",
|
|
2837
|
+
reason: {
|
|
2838
|
+
type: "activityOriginMismatch",
|
|
2839
|
+
activityId: new URL(activity.id.href),
|
|
2840
|
+
actorIds: activity.actorIds.map((id) => new URL(id.href))
|
|
2841
|
+
}
|
|
2842
|
+
};
|
|
2843
|
+
logger.error("The activity ({activityId}) and its actors do not have the same origin.", {
|
|
2844
|
+
activity: json,
|
|
2845
|
+
recipient,
|
|
2846
|
+
activityId: activity.id.href,
|
|
2847
|
+
actorIds: activity.actorIds.map((actor) => actor.href)
|
|
2848
|
+
});
|
|
2849
|
+
span.setStatus({
|
|
2850
|
+
code: SpanStatusCode.ERROR,
|
|
2851
|
+
message: `The activity (${activity.id.href}) and its actors do not have the same origin.`
|
|
2852
|
+
});
|
|
2853
|
+
return new Response("The activity and its actors do not have the same origin.", {
|
|
2854
|
+
status: 401,
|
|
2855
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
2856
|
+
});
|
|
2857
|
+
}
|
|
2991
2858
|
observation.authentication = skipSignatureVerification ? { status: "skipped" } : {
|
|
2992
2859
|
status: "verified",
|
|
2993
2860
|
attempts: observation.verification.attempts.filter((attempt) => attempt.status === "verified")
|
|
2994
2861
|
};
|
|
2995
2862
|
observation.stage = "dispatch";
|
|
2863
|
+
if (activity.actorId == null) {
|
|
2864
|
+
observation.result = {
|
|
2865
|
+
disposition: "rejected",
|
|
2866
|
+
reason: "missingActor"
|
|
2867
|
+
};
|
|
2868
|
+
logger.error("Missing actor.", {
|
|
2869
|
+
activity: json,
|
|
2870
|
+
recipient
|
|
2871
|
+
});
|
|
2872
|
+
span.setStatus({
|
|
2873
|
+
code: SpanStatusCode.ERROR,
|
|
2874
|
+
message: "Missing actor."
|
|
2875
|
+
});
|
|
2876
|
+
return new Response("Missing actor.", {
|
|
2877
|
+
status: 400,
|
|
2878
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2996
2881
|
const routeResult = await routeActivity({
|
|
2997
2882
|
context: ctx,
|
|
2998
2883
|
json,
|
|
@@ -3213,8 +3098,8 @@ var CustomCollectionHandler = class {
|
|
|
3213
3098
|
* @param CollectionPage The CollectionPage constructor.
|
|
3214
3099
|
* @param filterPredicate Optional filter predicate for items.
|
|
3215
3100
|
*/
|
|
3216
|
-
constructor(name$
|
|
3217
|
-
this.name = name$
|
|
3101
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
|
|
3102
|
+
this.name = name$1;
|
|
3218
3103
|
this.values = values;
|
|
3219
3104
|
this.context = context;
|
|
3220
3105
|
this.callbacks = callbacks;
|
|
@@ -5840,6 +5725,35 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5840
5725
|
span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
5841
5726
|
listenerSpan.setAttribute("activitypub.activity.id", activity.id.href);
|
|
5842
5727
|
}
|
|
5728
|
+
if (activity.actorId == null) {
|
|
5729
|
+
logger.error("Missing actor in queued incoming activity.", {
|
|
5730
|
+
activityId: activity.id?.href,
|
|
5731
|
+
activity: message.activity,
|
|
5732
|
+
recipient: message.identifier
|
|
5733
|
+
});
|
|
5734
|
+
listenerSpan.setStatus({
|
|
5735
|
+
code: SpanStatusCode.ERROR,
|
|
5736
|
+
message: "Missing actor."
|
|
5737
|
+
});
|
|
5738
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
5739
|
+
listenerSpan.end();
|
|
5740
|
+
return;
|
|
5741
|
+
}
|
|
5742
|
+
if (!this.skipSignatureVerification && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
5743
|
+
logger.error("The queued activity ({activityId}) and its actors do not have the same origin.", {
|
|
5744
|
+
activityId: activity.id.href,
|
|
5745
|
+
actorIds: activity.actorIds.map((actor) => actor.href),
|
|
5746
|
+
activity: message.activity,
|
|
5747
|
+
recipient: message.identifier
|
|
5748
|
+
});
|
|
5749
|
+
listenerSpan.setStatus({
|
|
5750
|
+
code: SpanStatusCode.ERROR,
|
|
5751
|
+
message: `The activity (${activity.id.href}) and its actors do not have the same origin.`
|
|
5752
|
+
});
|
|
5753
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
5754
|
+
listenerSpan.end();
|
|
5755
|
+
return;
|
|
5756
|
+
}
|
|
5843
5757
|
cacheKey = activity.id == null ? null : [
|
|
5844
5758
|
...this.kvPrefixes.activityIdempotence,
|
|
5845
5759
|
context.origin,
|
|
@@ -7916,6 +7830,20 @@ var ContextImpl = class ContextImpl {
|
|
|
7916
7830
|
recipient,
|
|
7917
7831
|
activity: json
|
|
7918
7832
|
});
|
|
7833
|
+
if (activity.actorId == null) {
|
|
7834
|
+
logger.debug("Activity is missing an actor; unable to verify.", {
|
|
7835
|
+
recipient,
|
|
7836
|
+
activity: json
|
|
7837
|
+
});
|
|
7838
|
+
return false;
|
|
7839
|
+
}
|
|
7840
|
+
if (activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
7841
|
+
logger.debug("Activity has actors from different origins; unable to verify.", {
|
|
7842
|
+
recipient,
|
|
7843
|
+
activity: json
|
|
7844
|
+
});
|
|
7845
|
+
return false;
|
|
7846
|
+
}
|
|
7919
7847
|
const routeResult = await routeActivity({
|
|
7920
7848
|
context: this,
|
|
7921
7849
|
json,
|
|
@@ -8038,6 +7966,12 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
8038
7966
|
#signedKey = void 0;
|
|
8039
7967
|
async getSignedKey(options = {}) {
|
|
8040
7968
|
if (this.#signedKey != null) return this.#signedKey;
|
|
7969
|
+
const keyCache = new KvKeyCache(this.federation.kv, this.federation.kvPrefixes.publicKey, {
|
|
7970
|
+
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
7971
|
+
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
7972
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
7973
|
+
keyTtl: this.federation.publicKeyTtl
|
|
7974
|
+
});
|
|
8041
7975
|
return this.#signedKey = await verifyRequest(this.request, {
|
|
8042
7976
|
...this,
|
|
8043
7977
|
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
@@ -8045,7 +7979,8 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
8045
7979
|
timeWindow: this.federation.signatureTimeWindow,
|
|
8046
7980
|
maxSignatures: this.federation.maxHttpSignatures,
|
|
8047
7981
|
meterProvider: this.meterProvider,
|
|
8048
|
-
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
7982
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
7983
|
+
keyCache
|
|
8049
7984
|
});
|
|
8050
7985
|
}
|
|
8051
7986
|
#signedKeyOwner = void 0;
|
|
@@ -2,10 +2,10 @@ import { Temporal } from "temporal-polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./rolldown-runtime-BC-Eo5Mj.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-DAtXl_Kc.js";
|
|
5
|
-
import { $ as getFederationMetrics, A as detachSignature, At as isPortableId, B as wrapContextLoaderForJsonLd, Ct as getAuthenticationOrigin, Dt as getRawCanonicalPortableId, E as assertSafeJsonLd, Et as getPortableDid, F as isInvalidUrlTypeError, Ft as name, I as signJsonLd, It as version, K as importJwk, L as verifyCompactJsonLd, M as hasSignature, Mt as isPortableUri, N as hasSignatureLike, Nt as isSameObjectId, O as compactJsonLd, Ot as hasPortableActor, P as isClearlyMalformedContextReference, Q as getDurationMs, S as verifyPreparedPortableObjectProofPolicy, St as verificationObservation, T as InvalidContextReferenceError, Tt as getGatewayKeyBase, V as exportJwk, Y as MAX_PORTABLE_KEY_TTL, _ as verifyMapLocalProof, at as recordCollectionPageItems, b as verifyPortableObjectProofPolicy, bt as observeAttempt, c as verifyRequestDetailed, d as InvalidPortableObjectIdError, dt as recordOutboxActivity, et as getRemoteHost, f as classifyFep2277CoreType, ft as recordOutboxEnqueue, g as signObject, gt as formatAcceptSignature, h as preparePortableObjectProofPolicy, ht as preloadedOnlyDocumentLoader, i as selectRequestSignature, it as recordCollectionDispatchDuration, j as getNormalizationContextLoader, jt as isPortableKeyId, kt as isCompatibleKeyId, lt as recordFanoutRecipients, m as hasProofLike, mt as registerQueueDepthGauge, n as listRequestSignatures, nt as isAbortError, o as validateMaxSignatures, ot as recordCollectionRequest, pt as recordWebFingerHandle, q as validateCryptoKey, r as parseRfc9421SignatureInput, rt as recordCircuitBreakerStateChange, s as verifyRequest, st as recordCollectionTotalItems, t as doubleKnock, tt as instrumentDocumentLoader, ut as recordInboxActivity, v as verifyObject, w as normalizeOutgoingActivityJsonLd, wt as getCanonicalPortableId, x as verifyPortableObjectProofWithRoot, xt as snapshotKey, y as verifyPortableObjectProof } from "./http-
|
|
5
|
+
import { $ as getFederationMetrics, A as detachSignature, At as isPortableId, B as wrapContextLoaderForJsonLd, Ct as getAuthenticationOrigin, Dt as getRawCanonicalPortableId, E as assertSafeJsonLd, Et as getPortableDid, F as isInvalidUrlTypeError, Ft as name, I as signJsonLd, It as version, K as importJwk, L as verifyCompactJsonLd, M as hasSignature, Mt as isPortableUri, N as hasSignatureLike, Nt as isSameObjectId, O as compactJsonLd, Ot as hasPortableActor, P as isClearlyMalformedContextReference, Q as getDurationMs, S as verifyPreparedPortableObjectProofPolicy, St as verificationObservation, T as InvalidContextReferenceError, Tt as getGatewayKeyBase, V as exportJwk, Y as MAX_PORTABLE_KEY_TTL, _ as verifyMapLocalProof, at as recordCollectionPageItems, b as verifyPortableObjectProofPolicy, bt as observeAttempt, c as verifyRequestDetailed, d as InvalidPortableObjectIdError, dt as recordOutboxActivity, et as getRemoteHost, f as classifyFep2277CoreType, ft as recordOutboxEnqueue, g as signObject, gt as formatAcceptSignature, h as preparePortableObjectProofPolicy, ht as preloadedOnlyDocumentLoader, i as selectRequestSignature, it as recordCollectionDispatchDuration, j as getNormalizationContextLoader, jt as isPortableKeyId, kt as isCompatibleKeyId, lt as recordFanoutRecipients, m as hasProofLike, mt as registerQueueDepthGauge, n as listRequestSignatures, nt as isAbortError, o as validateMaxSignatures, ot as recordCollectionRequest, pt as recordWebFingerHandle, q as validateCryptoKey, r as parseRfc9421SignatureInput, rt as recordCircuitBreakerStateChange, s as verifyRequest, st as recordCollectionTotalItems, t as doubleKnock, tt as instrumentDocumentLoader, ut as recordInboxActivity, v as verifyObject, w as normalizeOutgoingActivityJsonLd, wt as getCanonicalPortableId, x as verifyPortableObjectProofWithRoot, xt as snapshotKey, y as verifyPortableObjectProof } from "./http-CRRQ6LBq.js";
|
|
6
6
|
import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-_S2_MeLF.js";
|
|
7
|
-
import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "./portable-collection-
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
7
|
+
import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "./portable-collection-BweSVeOo.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-D5EHCk1_.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
10
|
import { Router, RouterError, assertPath } from "@fedify/uri-template";
|
|
11
11
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, PUBLIC_COLLECTION, Tombstone, getTypeId, isActor, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
@@ -2805,12 +2805,41 @@ async function isInAudience(object, actor, options = {}) {
|
|
|
2805
2805
|
}
|
|
2806
2806
|
//#endregion
|
|
2807
2807
|
//#region src/federation/inbox.ts
|
|
2808
|
+
/**
|
|
2809
|
+
* Checks whether an activity's ID and all of its actor IDs have the same
|
|
2810
|
+
* [FEP-fe34] origin. Activities without an ID have no origin to authenticate.
|
|
2811
|
+
*
|
|
2812
|
+
* Origins are compared by `getAuthenticationOrigin()`, so a portable activity
|
|
2813
|
+
* and its portable actors, including compatible identifiers on any gateway,
|
|
2814
|
+
* are compared by their DIDs. An ID that has no supported origin, such as an
|
|
2815
|
+
* opaque URN, never matches.
|
|
2816
|
+
*
|
|
2817
|
+
* The caller is responsible for rejecting a missing primary actor ID before
|
|
2818
|
+
* relying on this check.
|
|
2819
|
+
*
|
|
2820
|
+
* [FEP-fe34]: https://w3id.org/fep/fe34
|
|
2821
|
+
* @internal
|
|
2822
|
+
*/
|
|
2823
|
+
function actorsHaveSameOrigin(activity) {
|
|
2824
|
+
if (activity.id == null) return true;
|
|
2825
|
+
const origin = getAuthenticationOrigin(activity.id);
|
|
2826
|
+
return origin != null && activity.actorIds.every((actor) => getAuthenticationOrigin(actor) === origin);
|
|
2827
|
+
}
|
|
2808
2828
|
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, meterProvider, tracerProvider, idempotencyStrategy }) {
|
|
2809
2829
|
const logger = getLogger([
|
|
2810
2830
|
"fedify",
|
|
2811
2831
|
"federation",
|
|
2812
2832
|
"inbox"
|
|
2813
2833
|
]);
|
|
2834
|
+
if (activity.actorId == null) {
|
|
2835
|
+
logger.error("Missing actor.", { activity: json });
|
|
2836
|
+
span.setStatus({
|
|
2837
|
+
code: SpanStatusCode.ERROR,
|
|
2838
|
+
message: "Missing actor."
|
|
2839
|
+
});
|
|
2840
|
+
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
2841
|
+
return "missingActor";
|
|
2842
|
+
}
|
|
2814
2843
|
let cacheKey = null;
|
|
2815
2844
|
if (activity.id != null) {
|
|
2816
2845
|
const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
|
|
@@ -2846,15 +2875,6 @@ async function routeActivity({ context: ctx, json, originalJson, normalizedActiv
|
|
|
2846
2875
|
return "alreadyProcessed";
|
|
2847
2876
|
}
|
|
2848
2877
|
}
|
|
2849
|
-
if (activity.actorId == null) {
|
|
2850
|
-
logger.error("Missing actor.", { activity: json });
|
|
2851
|
-
span.setStatus({
|
|
2852
|
-
code: SpanStatusCode.ERROR,
|
|
2853
|
-
message: "Missing actor."
|
|
2854
|
-
});
|
|
2855
|
-
recordInboxActivity(meterProvider, "rejected", getTypeId(activity).href);
|
|
2856
|
-
return "missingActor";
|
|
2857
|
-
}
|
|
2858
2878
|
span.setAttribute("activitypub.actor.id", activity.actorId.href);
|
|
2859
2879
|
if (queue != null) {
|
|
2860
2880
|
const carrier = {};
|
|
@@ -4772,13 +4792,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
4772
4792
|
* @param parameters The parameters for handling the collection.
|
|
4773
4793
|
* @returns A promise that resolves to an HTTP response.
|
|
4774
4794
|
*/
|
|
4775
|
-
async function handleCollection(request, { name: name$
|
|
4776
|
-
const spanName = name$
|
|
4795
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
4796
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
4777
4797
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
4778
4798
|
const tracer = tracerProvider.getTracer(name, version);
|
|
4779
4799
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
4780
4800
|
const metricBase = {
|
|
4781
|
-
kind: getCollectionMetricKind(name$
|
|
4801
|
+
kind: getCollectionMetricKind(name$2),
|
|
4782
4802
|
page: cursor != null,
|
|
4783
4803
|
dispatcher: "built_in"
|
|
4784
4804
|
};
|
|
@@ -4824,7 +4844,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
4824
4844
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
4825
4845
|
return await onNotFound(request);
|
|
4826
4846
|
}
|
|
4827
|
-
const items = filterCollectionItems(page.items, name$
|
|
4847
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
4828
4848
|
itemCount = items.length;
|
|
4829
4849
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
4830
4850
|
return items;
|
|
@@ -4866,7 +4886,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
4866
4886
|
} else {
|
|
4867
4887
|
const uri = new URL(portable == null ? baseUri : pageBase);
|
|
4868
4888
|
uri.searchParams.set("cursor", cursor);
|
|
4869
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
4889
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
4870
4890
|
kind: SpanKind.SERVER,
|
|
4871
4891
|
attributes: {
|
|
4872
4892
|
"activitypub.collection.id": uri.href,
|
|
@@ -4882,7 +4902,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
4882
4902
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
4883
4903
|
return await onNotFound(request);
|
|
4884
4904
|
}
|
|
4885
|
-
const items = filterCollectionItems(page.items, name$
|
|
4905
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
4886
4906
|
itemCount = items.length;
|
|
4887
4907
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
4888
4908
|
return {
|
|
@@ -6035,11 +6055,53 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
6035
6055
|
return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
6036
6056
|
}
|
|
6037
6057
|
}
|
|
6058
|
+
if (!skipSignatureVerification && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
6059
|
+
observation.authentication = {
|
|
6060
|
+
status: "rejected",
|
|
6061
|
+
reason: {
|
|
6062
|
+
type: "activityOriginMismatch",
|
|
6063
|
+
activityId: new URL(activity.id.href),
|
|
6064
|
+
actorIds: activity.actorIds.map((id) => new URL(id.href))
|
|
6065
|
+
}
|
|
6066
|
+
};
|
|
6067
|
+
logger.error("The activity ({activityId}) and its actors do not have the same origin.", {
|
|
6068
|
+
activity: json,
|
|
6069
|
+
recipient,
|
|
6070
|
+
activityId: activity.id.href,
|
|
6071
|
+
actorIds: activity.actorIds.map((actor) => actor.href)
|
|
6072
|
+
});
|
|
6073
|
+
span.setStatus({
|
|
6074
|
+
code: SpanStatusCode.ERROR,
|
|
6075
|
+
message: `The activity (${activity.id.href}) and its actors do not have the same origin.`
|
|
6076
|
+
});
|
|
6077
|
+
return new Response("The activity and its actors do not have the same origin.", {
|
|
6078
|
+
status: 401,
|
|
6079
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6080
|
+
});
|
|
6081
|
+
}
|
|
6038
6082
|
observation.authentication = skipSignatureVerification ? { status: "skipped" } : {
|
|
6039
6083
|
status: "verified",
|
|
6040
6084
|
attempts: observation.verification.attempts.filter((attempt) => attempt.status === "verified")
|
|
6041
6085
|
};
|
|
6042
6086
|
observation.stage = "dispatch";
|
|
6087
|
+
if (activity.actorId == null) {
|
|
6088
|
+
observation.result = {
|
|
6089
|
+
disposition: "rejected",
|
|
6090
|
+
reason: "missingActor"
|
|
6091
|
+
};
|
|
6092
|
+
logger.error("Missing actor.", {
|
|
6093
|
+
activity: json,
|
|
6094
|
+
recipient
|
|
6095
|
+
});
|
|
6096
|
+
span.setStatus({
|
|
6097
|
+
code: SpanStatusCode.ERROR,
|
|
6098
|
+
message: "Missing actor."
|
|
6099
|
+
});
|
|
6100
|
+
return new Response("Missing actor.", {
|
|
6101
|
+
status: 400,
|
|
6102
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6103
|
+
});
|
|
6104
|
+
}
|
|
6043
6105
|
const routeResult = await routeActivity({
|
|
6044
6106
|
context: ctx,
|
|
6045
6107
|
json,
|
|
@@ -6260,8 +6322,8 @@ var CustomCollectionHandler = class {
|
|
|
6260
6322
|
* @param CollectionPage The CollectionPage constructor.
|
|
6261
6323
|
* @param filterPredicate Optional filter predicate for items.
|
|
6262
6324
|
*/
|
|
6263
|
-
constructor(name$
|
|
6264
|
-
this.name = name$
|
|
6325
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
|
|
6326
|
+
this.name = name$1;
|
|
6265
6327
|
this.values = values;
|
|
6266
6328
|
this.context = context;
|
|
6267
6329
|
this.callbacks = callbacks;
|
|
@@ -9296,6 +9358,35 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9296
9358
|
span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
9297
9359
|
listenerSpan.setAttribute("activitypub.activity.id", activity.id.href);
|
|
9298
9360
|
}
|
|
9361
|
+
if (activity.actorId == null) {
|
|
9362
|
+
logger.error("Missing actor in queued incoming activity.", {
|
|
9363
|
+
activityId: activity.id?.href,
|
|
9364
|
+
activity: message.activity,
|
|
9365
|
+
recipient: message.identifier
|
|
9366
|
+
});
|
|
9367
|
+
listenerSpan.setStatus({
|
|
9368
|
+
code: SpanStatusCode.ERROR,
|
|
9369
|
+
message: "Missing actor."
|
|
9370
|
+
});
|
|
9371
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
9372
|
+
listenerSpan.end();
|
|
9373
|
+
return;
|
|
9374
|
+
}
|
|
9375
|
+
if (!this.skipSignatureVerification && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
9376
|
+
logger.error("The queued activity ({activityId}) and its actors do not have the same origin.", {
|
|
9377
|
+
activityId: activity.id.href,
|
|
9378
|
+
actorIds: activity.actorIds.map((actor) => actor.href),
|
|
9379
|
+
activity: message.activity,
|
|
9380
|
+
recipient: message.identifier
|
|
9381
|
+
});
|
|
9382
|
+
listenerSpan.setStatus({
|
|
9383
|
+
code: SpanStatusCode.ERROR,
|
|
9384
|
+
message: `The activity (${activity.id.href}) and its actors do not have the same origin.`
|
|
9385
|
+
});
|
|
9386
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
9387
|
+
listenerSpan.end();
|
|
9388
|
+
return;
|
|
9389
|
+
}
|
|
9299
9390
|
cacheKey = activity.id == null ? null : [
|
|
9300
9391
|
...this.kvPrefixes.activityIdempotence,
|
|
9301
9392
|
context.origin,
|
|
@@ -11372,6 +11463,20 @@ var ContextImpl = class ContextImpl {
|
|
|
11372
11463
|
recipient,
|
|
11373
11464
|
activity: json
|
|
11374
11465
|
});
|
|
11466
|
+
if (activity.actorId == null) {
|
|
11467
|
+
logger.debug("Activity is missing an actor; unable to verify.", {
|
|
11468
|
+
recipient,
|
|
11469
|
+
activity: json
|
|
11470
|
+
});
|
|
11471
|
+
return false;
|
|
11472
|
+
}
|
|
11473
|
+
if (activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
11474
|
+
logger.debug("Activity has actors from different origins; unable to verify.", {
|
|
11475
|
+
recipient,
|
|
11476
|
+
activity: json
|
|
11477
|
+
});
|
|
11478
|
+
return false;
|
|
11479
|
+
}
|
|
11375
11480
|
const routeResult = await routeActivity({
|
|
11376
11481
|
context: this,
|
|
11377
11482
|
json,
|
|
@@ -11494,6 +11599,12 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
11494
11599
|
#signedKey = void 0;
|
|
11495
11600
|
async getSignedKey(options = {}) {
|
|
11496
11601
|
if (this.#signedKey != null) return this.#signedKey;
|
|
11602
|
+
const keyCache = new KvKeyCache(this.federation.kv, this.federation.kvPrefixes.publicKey, {
|
|
11603
|
+
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
11604
|
+
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
11605
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
11606
|
+
keyTtl: this.federation.publicKeyTtl
|
|
11607
|
+
});
|
|
11497
11608
|
return this.#signedKey = await verifyRequest(this.request, {
|
|
11498
11609
|
...this,
|
|
11499
11610
|
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
@@ -11501,7 +11612,8 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
11501
11612
|
timeWindow: this.federation.signatureTimeWindow,
|
|
11502
11613
|
maxSignatures: this.federation.maxHttpSignatures,
|
|
11503
11614
|
meterProvider: this.meterProvider,
|
|
11504
|
-
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
11615
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
11616
|
+
keyCache
|
|
11505
11617
|
});
|
|
11506
11618
|
}
|
|
11507
11619
|
#signedKeyOwner = void 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { Jt as WebFingerLinksDispatcher, St as ActorHandleMapper, bt as ActorAliasMapper, p as RequestContext, xt as ActorDispatcher } from "./context-
|
|
2
|
+
import { Jt as WebFingerLinksDispatcher, St as ActorHandleMapper, bt as ActorAliasMapper, p as RequestContext, xt as ActorDispatcher } from "./context-DPocjp1l.cjs";
|
|
3
3
|
import { MeterProvider, Span, Tracer } from "@opentelemetry/api";
|
|
4
4
|
import { RouterError, RouterOptions, RouterRouteResult } from "@fedify/uri-template";
|
|
5
5
|
|