@fedify/fedify 2.5.0-dev.2446 → 2.5.0-dev.2492
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/README.md +3 -0
- package/dist/{activity-listener-C-BSbKI7.mjs → activity-listener-CELFAodc.mjs} +8 -4
- package/dist/{builder-Da8b9O6v.mjs → builder-DphK9v7f.mjs} +5 -5
- package/dist/{client-D-XP_Ccb.d.ts → client-3InDZbba.d.cts} +0 -1
- package/dist/{client-D-XP_Ccb.d.cts → client-3InDZbba.d.ts} +0 -1
- package/dist/{client-CEnNz8O7.mjs → client-5SIFzW3q.mjs} +113 -64
- 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-D1djO5fa.mjs → compound-proof-cYtvlTgF.mjs} +2 -2
- package/dist/{context-8Tu9kea0.mjs → context-COHd1Rsh.mjs} +2 -0
- package/dist/{context-BdB54V-A.d.ts → context-DQJE9YfH.d.ts} +332 -6
- package/dist/{context-CQ9H8vNW.d.cts → context-DSuL3YWx.d.cts} +332 -6
- package/dist/{deno-eNpfj4oR.mjs → deno-iOAA7iRN.mjs} +1 -1
- package/dist/docloader-DCZkiTeF.mjs +136 -0
- package/dist/{exporter-DThFfe7P.mjs → exporter-DVG68ozH.mjs} +36 -30
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +6 -3
- package/dist/federation/handler-compound-proof.test.mjs +5 -5
- package/dist/federation/handler.test.mjs +22 -7
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox-actorless.test.d.mts +2 -0
- package/dist/federation/inbox-actorless.test.mjs +487 -0
- package/dist/federation/inbox-authentication.test.d.mts +2 -0
- package/dist/federation/inbox-authentication.test.mjs +116 -0
- package/dist/federation/inbox-report.test.mjs +5 -5
- package/dist/federation/inbox-view.test.d.mts +2 -0
- package/dist/federation/inbox-view.test.mjs +369 -0
- package/dist/federation/inbox.test.mjs +22 -12
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +470 -35
- package/dist/federation/mod.cjs +2 -1
- package/dist/federation/mod.d.cts +4 -4
- package/dist/federation/mod.d.ts +4 -4
- package/dist/federation/mod.js +8 -2
- package/dist/federation/mq.test.mjs +36 -1
- package/dist/federation/outgoing-proof.test.mjs +9 -6
- 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 +13 -7
- 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 +502 -93
- package/dist/federation/tasks/enqueue.test.mjs +3 -3
- package/dist/federation/tasks/tasks.test.mjs +4 -4
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{federation-BVH7drJA.cjs → federation-D0AZw_aw.cjs} +1415 -236
- package/dist/{http-BUJ5SFh6.mjs → http-BoJCMnjY.mjs} +204 -106
- package/dist/{http-DlNxxW_5.js → http-ChXUU_3c.js} +319 -123
- package/dist/{http-BfW3wyQ4.cjs → http-kv1LZw-r.cjs} +339 -125
- package/dist/inbox-BjihTKLo.mjs +312 -0
- package/dist/inbox-authentication-DflPYlLL.mjs +171 -0
- package/dist/inbox-view-D-skypg-.mjs +385 -0
- package/dist/{key-nYGY4QB9.d.cts → key-DbLNT-vA.d.ts} +1 -2
- package/dist/{key-DhsBxxZN.d.ts → key-DlHT4R6k.d.cts} +1 -2
- package/dist/{kv-cache-D_m3A241.mjs → kv-cache-Cmsyke4d.mjs} +1 -1
- package/dist/{kv-cache-7015lbrx.js → kv-cache-DQcte7ES.js} +73 -28
- package/dist/{kv-cache-kkBB0vbI.cjs → kv-cache-Ddh5sMxH.cjs} +72 -27
- package/dist/ld-CWVpo_NM.d.cts +250 -0
- package/dist/{ld-CD2CsPxq.mjs → ld-CdvcOEXQ.mjs} +52 -9
- package/dist/ld-Inagww4R.d.ts +250 -0
- package/dist/{metrics-D3LHk6Z4.mjs → metrics-CpxvUrBz.mjs} +1 -1
- package/dist/{middleware-N9eM16XE.js → middleware-BHb5toqA.js} +1413 -247
- package/dist/{middleware-CCDXvXOG.mjs → middleware-BKs2DLUF.mjs} +1 -1
- package/dist/{middleware-CzoWvrdZ.mjs → middleware-CoBLrTKX.mjs} +533 -132
- package/dist/{mod-B0dGgQsg.d.cts → mod-6TQ4UQZb.d.cts} +1 -1
- package/dist/mod-B4kBw1-8.d.ts +154 -0
- package/dist/{mod-DkhfZC1u.d.ts → mod-B7j30IQf.d.ts} +2 -9
- package/dist/mod-C1nT74IG.d.cts +154 -0
- package/dist/{mod-D0bxB8jS.d.ts → mod-CIeBgsOC.d.ts} +1 -1
- package/dist/{mod-B5-wdzmJ.d.cts → mod-YvA4Rk8J.d.cts} +2 -9
- package/dist/mod.cjs +6 -5
- package/dist/mod.d.cts +9 -9
- package/dist/mod.d.ts +9 -9
- package/dist/mod.js +6 -6
- package/dist/{mq-Dm1Wmtm-.mjs → mq-eF96QxUT.mjs} +6 -0
- package/dist/nodeinfo/client.test.mjs +337 -19
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.d.cts +1 -1
- package/dist/nodeinfo/mod.d.ts +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/otel/exporter.test.mjs +257 -1
- package/dist/otel/mod.cjs +36 -30
- package/dist/otel/mod.d.cts +13 -0
- package/dist/otel/mod.d.ts +13 -0
- package/dist/otel/mod.js +36 -30
- package/dist/{owner-C5-FVX6t.mjs → owner-DTnVpUKA.mjs} +3 -3
- package/dist/{portable-collection-Cony3_LC.mjs → portable-collection-CJeYTL61.mjs} +2 -2
- package/dist/{portable-collection-C-Z1SKDy.cjs → portable-collection-DciwBIia.cjs} +1 -1
- package/dist/{portable-collection-CC2zNAje.js → portable-collection-TmtpzD4E.js} +1 -1
- package/dist/{portable-key-DNc_flH-.mjs → portable-key-DcYok4ki.mjs} +1 -1
- package/dist/{proof-Cryb1c70.mjs → proof-GH7Poos_.mjs} +98 -10
- package/dist/{send-AF25pWaJ.mjs → send-BgGJh6pv.mjs} +174 -76
- 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 +553 -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.d.cts +3 -3
- package/dist/sig/mod.d.ts +3 -3
- 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 +45 -5
- 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-BsAeuUJj.mjs → temporal-gJINzcL4.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +288 -2
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-t8xDeJZ5.mjs → testing-Dbr21vZk.mjs} +1 -1
- package/dist/{types-_S2_MeLF.js → types-DUjZb4i6.js} +112 -63
- package/dist/{types-poIao40f.cjs → types-hKCCjii0.cjs} +111 -62
- package/dist/utils/docloader.test.mjs +344 -36
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +7 -7
- package/dist/docloader-B-0nqOB1.mjs +0 -91
- package/dist/inbox-CHvMaIFX.mjs +0 -188
- package/dist/mod-BRpER-B0.d.ts +0 -320
- package/dist/mod-xAfaLS4T.d.cts +0 -320
- package/dist/owner-BF0L9cMt.d.cts +0 -78
- package/dist/owner-BSzr5-I8.d.ts +0 -78
|
@@ -3,34 +3,37 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
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
|
+
import { i as getEmptyAuthenticationEvidence, n as deserializeAuthentication, t as createAuthenticationEvidence } from "./inbox-authentication-DflPYlLL.mjs";
|
|
6
7
|
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-
|
|
8
|
+
import { n as version, t as name } from "./deno-iOAA7iRN.mjs";
|
|
9
|
+
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-CpxvUrBz.mjs";
|
|
9
10
|
import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
10
|
-
import {
|
|
11
|
+
import { r as getVerifiedKeyOwnerEvidence } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
12
|
+
import { D as validateCryptoKey, E as importJwk, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, g as verifyCompactJsonLdDetailed, l as hasSignature, m as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike, x as exportJwk, y as wrapContextLoaderForJsonLd } from "./ld-CdvcOEXQ.mjs";
|
|
11
13
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { n as kvCache } from "./kv-cache-
|
|
16
|
-
import { d as
|
|
14
|
+
import { a as hasProofLike, d as verifyPortableObjectProof, i as getProofSigner, l as verifyObject, p as verifyPortableObjectProofWithRoot, s as signObject, t as InvalidPortableObjectIdError, u as verifyObjectDetailed } from "./proof-GH7Poos_.mjs";
|
|
15
|
+
import { c as parseRfc9421SignatureInput, f as validateMaxSignatures, l as selectRequestSignature, m as verifyRequestDetailed, o as listRequestSignatures, p as verifyRequest } from "./http-BoJCMnjY.mjs";
|
|
16
|
+
import { n as getAuthenticatedDocumentLoader } from "./docloader-DCZkiTeF.mjs";
|
|
17
|
+
import { n as kvCache } from "./kv-cache-Cmsyke4d.mjs";
|
|
18
|
+
import { d as MAX_BODY_SIZE, f as readBoundedText, t as getNodeInfo, u as BodyTooLargeError } from "./client-5SIFzW3q.mjs";
|
|
17
19
|
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
|
|
21
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
20
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DTnVpUKA.mjs";
|
|
21
|
+
import { t as verifyPortableObject } from "./portable-collection-CJeYTL61.mjs";
|
|
22
|
+
import { a as sendActivityThroughGateways, i as sendActivity, n as extractInboxes, o as getOrderingDestination, t as SendActivityError } from "./send-BgGJh6pv.mjs";
|
|
23
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-DphK9v7f.mjs";
|
|
22
24
|
import { t as CircuitBreaker } from "./circuit-breaker-XJ53md4S.mjs";
|
|
23
25
|
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-
|
|
25
|
-
import { n as routeActivity, t as actorsHaveSameOrigin } from "./inbox-
|
|
26
|
+
import { a as inspectCompoundPortableObjectApplicability, c as verifyServedPortableObjects, i as findUnsupportedCompoundProofShape, o as verifyCompoundPortableObjectProofs, r as findEmbeddedProofWithoutContext, t as containsCompoundPortableObject } from "./compound-proof-cYtvlTgF.mjs";
|
|
27
|
+
import { a as isActorlessActivityAuthenticated, i as getInboxIdempotencyKey, n as checkActorlessActivity, o as isInboxActivityProcessed, s as routeActivity, t as actorsHaveSameOrigin } from "./inbox-BjihTKLo.mjs";
|
|
28
|
+
import { c as expandDocument, d as parseSerializedVerifiedActivityView, f as restoreVerifiedActivityView, i as createReleasableLoader, l as getActorPresence, n as buildVerifiedActivityView, o as deepFreeze, r as createContextSnapshot, t as ContextSnapshotMissError } from "./inbox-view-D-skypg-.mjs";
|
|
26
29
|
import { t as KvKeyCache } from "./keycache-N2opu4-3.mjs";
|
|
27
30
|
import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
|
|
28
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
31
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-gJINzcL4.mjs";
|
|
29
32
|
import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
|
|
30
33
|
import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
|
|
31
34
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
32
35
|
import { RouterError } from "@fedify/uri-template";
|
|
33
|
-
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, isActor, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
36
|
+
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, isActor, lookupObject, lookupObserver, traverseCollection } from "@fedify/vocab";
|
|
34
37
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
35
38
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
36
39
|
import { FetchError, canonicalizePortableUri, decodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDigestMultibase, parseHashlink, parseIri, resolveDocumentLoaderTimeout, toCompatibleEf61Id } from "@fedify/vocab-runtime";
|
|
@@ -1568,13 +1571,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
1568
1571
|
* @param parameters The parameters for handling the collection.
|
|
1569
1572
|
* @returns A promise that resolves to an HTTP response.
|
|
1570
1573
|
*/
|
|
1571
|
-
async function handleCollection(request, { name: name$
|
|
1572
|
-
const spanName = name$
|
|
1574
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
1575
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
1573
1576
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1574
1577
|
const tracer = tracerProvider.getTracer(name, version);
|
|
1575
1578
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1576
1579
|
const metricBase = {
|
|
1577
|
-
kind: getCollectionMetricKind(name$
|
|
1580
|
+
kind: getCollectionMetricKind(name$1),
|
|
1578
1581
|
page: cursor != null,
|
|
1579
1582
|
dispatcher: "built_in"
|
|
1580
1583
|
};
|
|
@@ -1620,7 +1623,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1620
1623
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1621
1624
|
return await onNotFound(request);
|
|
1622
1625
|
}
|
|
1623
|
-
const items = filterCollectionItems(page.items, name$
|
|
1626
|
+
const items = filterCollectionItems(page.items, name$1, filterPredicate);
|
|
1624
1627
|
itemCount = items.length;
|
|
1625
1628
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
1626
1629
|
return items;
|
|
@@ -1662,7 +1665,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1662
1665
|
} else {
|
|
1663
1666
|
const uri = new URL(portable == null ? baseUri : pageBase);
|
|
1664
1667
|
uri.searchParams.set("cursor", cursor);
|
|
1665
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1668
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
1666
1669
|
kind: SpanKind.SERVER,
|
|
1667
1670
|
attributes: {
|
|
1668
1671
|
"activitypub.collection.id": uri.href,
|
|
@@ -1678,7 +1681,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1678
1681
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1679
1682
|
return await onNotFound(request);
|
|
1680
1683
|
}
|
|
1681
|
-
const items = filterCollectionItems(page.items, name$
|
|
1684
|
+
const items = filterCollectionItems(page.items, name$1, filterPredicate);
|
|
1682
1685
|
itemCount = items.length;
|
|
1683
1686
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
1684
1687
|
return {
|
|
@@ -2175,11 +2178,12 @@ async function handleInbox(request, options) {
|
|
|
2175
2178
|
}, async (span) => {
|
|
2176
2179
|
if (options.recipient != null) span.setAttribute("fedify.inbox.recipient", options.recipient);
|
|
2177
2180
|
const spanContext = span.spanContext();
|
|
2181
|
+
const snapshot = createContextSnapshot(options.context.contextLoader);
|
|
2178
2182
|
try {
|
|
2179
2183
|
return await withContext({
|
|
2180
2184
|
traceId: spanContext.traceId,
|
|
2181
2185
|
spanId: spanContext.spanId
|
|
2182
|
-
}, () => handleInboxInternal(request, options, span));
|
|
2186
|
+
}, () => handleInboxInternal(request, options, span, snapshot));
|
|
2183
2187
|
} catch (e) {
|
|
2184
2188
|
options.observation.hasException = true;
|
|
2185
2189
|
span.setStatus({
|
|
@@ -2188,6 +2192,7 @@ async function handleInbox(request, options) {
|
|
|
2188
2192
|
});
|
|
2189
2193
|
throw e;
|
|
2190
2194
|
} finally {
|
|
2195
|
+
snapshot.release();
|
|
2191
2196
|
options.observation.project(span);
|
|
2192
2197
|
span.end();
|
|
2193
2198
|
}
|
|
@@ -2199,9 +2204,10 @@ async function handleInbox(request, options) {
|
|
|
2199
2204
|
* @param request The HTTP request.
|
|
2200
2205
|
* @param options The parameters for handling the inbox.
|
|
2201
2206
|
* @param span The OpenTelemetry span for tracing.
|
|
2207
|
+
* @param snapshot The context snapshot of the delivery.
|
|
2202
2208
|
* @returns A promise that resolves to an HTTP response.
|
|
2203
2209
|
*/
|
|
2204
|
-
async function handleInboxInternal(request, parameters, span) {
|
|
2210
|
+
async function handleInboxInternal(request, parameters, span, snapshot) {
|
|
2205
2211
|
const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, publicKeyTtl, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, maxHttpSignatures, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider, portableInbox } = parameters;
|
|
2206
2212
|
const observation = parameters.observation;
|
|
2207
2213
|
const signatureObservation = { [verificationObservation]: observation.verification };
|
|
@@ -2315,6 +2321,8 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2315
2321
|
tracerProvider,
|
|
2316
2322
|
keyTtl: publicKeyTtl
|
|
2317
2323
|
});
|
|
2324
|
+
const standardLoader = snapshot.loader("standard");
|
|
2325
|
+
const normalizationLoader = snapshot.loader("normalization");
|
|
2318
2326
|
const jsonWithoutSig = detachSignature(json);
|
|
2319
2327
|
const hasLdSignature = hasSignature(json);
|
|
2320
2328
|
const canAttemptAlternateAuthAfterLdSignatureFailure = skipSignatureVerification || hasHttpSignatureHeaders(request) || hasObjectIntegrityProof(jsonWithoutSig);
|
|
@@ -2350,9 +2358,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2350
2358
|
let compactedJson = json;
|
|
2351
2359
|
let compactedJsonWithoutSig = jsonWithoutSig;
|
|
2352
2360
|
let ldSigVerified = false;
|
|
2361
|
+
let ldSigKey = null;
|
|
2353
2362
|
if (hasLdSignature) {
|
|
2354
2363
|
try {
|
|
2355
|
-
compactedJson = await compactJsonLd(json,
|
|
2364
|
+
compactedJson = await compactJsonLd(json, normalizationLoader);
|
|
2356
2365
|
} catch (error) {
|
|
2357
2366
|
if (isInvalidJsonLdError(error)) {
|
|
2358
2367
|
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
@@ -2388,16 +2397,18 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2388
2397
|
if (compactedJson !== json) {
|
|
2389
2398
|
compactedJsonWithoutSig = detachSignature(compactedJson);
|
|
2390
2399
|
try {
|
|
2391
|
-
|
|
2400
|
+
const ldResult = await verifyCompactJsonLdDetailed(compactedJson, {
|
|
2392
2401
|
...signatureObservation,
|
|
2393
|
-
contextLoader:
|
|
2402
|
+
contextLoader: normalizationLoader,
|
|
2394
2403
|
documentLoader: ctx.documentLoader,
|
|
2395
2404
|
keyCache,
|
|
2396
2405
|
meterProvider,
|
|
2397
2406
|
tracerProvider
|
|
2398
2407
|
});
|
|
2408
|
+
ldSigVerified = ldResult.verified;
|
|
2409
|
+
ldSigKey = ldResult.key;
|
|
2399
2410
|
} catch (error) {
|
|
2400
|
-
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig,
|
|
2411
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, normalizationLoader)) return await respondInvalidActivity(error);
|
|
2401
2412
|
if (isInvalidJsonLdError(error)) {
|
|
2402
2413
|
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
2403
2414
|
recipient,
|
|
@@ -2415,12 +2426,12 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2415
2426
|
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
2416
2427
|
if (!skipSignatureVerification) try {
|
|
2417
2428
|
await Object$1.fromJsonLd(compactedJson, {
|
|
2418
|
-
contextLoader:
|
|
2429
|
+
contextLoader: normalizationLoader,
|
|
2419
2430
|
documentLoader: ctx.documentLoader,
|
|
2420
2431
|
tracerProvider
|
|
2421
2432
|
});
|
|
2422
2433
|
} catch (parseError) {
|
|
2423
|
-
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig,
|
|
2434
|
+
if (parseError instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, normalizationLoader)) return await respondInvalidActivity(parseError);
|
|
2424
2435
|
if (isInvalidJsonLdError(parseError)) {
|
|
2425
2436
|
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
2426
2437
|
recipient,
|
|
@@ -2444,6 +2455,33 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2444
2455
|
let activity = null;
|
|
2445
2456
|
let activityVerified = false;
|
|
2446
2457
|
let proofVerified = false;
|
|
2458
|
+
let documentSigners = [];
|
|
2459
|
+
let requestSigners = [];
|
|
2460
|
+
let viewSource;
|
|
2461
|
+
const rawViewSource = {
|
|
2462
|
+
policy: "standard",
|
|
2463
|
+
source: "activity",
|
|
2464
|
+
document: jsonWithoutSig,
|
|
2465
|
+
baseUrl: null
|
|
2466
|
+
};
|
|
2467
|
+
const isActorlessCandidate = async (candidate, source) => {
|
|
2468
|
+
if (skipSignatureVerification) return false;
|
|
2469
|
+
if (inboxListeners?.dispatchWithClass(candidate)?.options.allowActorless !== true) return false;
|
|
2470
|
+
try {
|
|
2471
|
+
return getActorPresence(await expandDocument(source.document, snapshot.loader(source.policy))) === "absent";
|
|
2472
|
+
} catch {
|
|
2473
|
+
return false;
|
|
2474
|
+
}
|
|
2475
|
+
};
|
|
2476
|
+
const verifyProofs = (contextLoader = standardLoader) => verifyObjectDetailed(Activity, jsonWithoutSig, {
|
|
2477
|
+
...signatureObservation,
|
|
2478
|
+
contextLoader,
|
|
2479
|
+
documentLoader: ctx.documentLoader,
|
|
2480
|
+
keyCache,
|
|
2481
|
+
meterProvider,
|
|
2482
|
+
tracerProvider,
|
|
2483
|
+
verifyPortableObject: ctx.verifyPortableObject
|
|
2484
|
+
});
|
|
2447
2485
|
if (ldSigVerified) {
|
|
2448
2486
|
logger.debug("Linked Data Signatures are verified.", {
|
|
2449
2487
|
recipient,
|
|
@@ -2452,18 +2490,49 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2452
2490
|
try {
|
|
2453
2491
|
activity = observation.activity = await Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
2454
2492
|
...ctx,
|
|
2455
|
-
contextLoader:
|
|
2493
|
+
contextLoader: normalizationLoader
|
|
2456
2494
|
});
|
|
2457
2495
|
} catch (error) {
|
|
2458
|
-
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig,
|
|
2496
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(compactedJsonWithoutSig, normalizationLoader)) return await respondInvalidActivity(error);
|
|
2459
2497
|
if (!isPermanentActivityParseError(error)) throw error;
|
|
2460
2498
|
return await respondInvalidActivity(error);
|
|
2461
2499
|
}
|
|
2462
2500
|
activityVerified = true;
|
|
2501
|
+
viewSource = {
|
|
2502
|
+
policy: "normalization",
|
|
2503
|
+
source: "normalizedActivity",
|
|
2504
|
+
document: compactedJsonWithoutSig,
|
|
2505
|
+
baseUrl: null
|
|
2506
|
+
};
|
|
2507
|
+
if (ldSigKey?.ownerId != null) documentSigners = [{
|
|
2508
|
+
kind: "actor",
|
|
2509
|
+
id: ldSigKey.ownerId,
|
|
2510
|
+
mechanism: "linkedDataSignatures",
|
|
2511
|
+
keyId: ldSigKey.id
|
|
2512
|
+
}];
|
|
2513
|
+
if (await isActorlessCandidate(activity, viewSource)) {
|
|
2514
|
+
let result = null;
|
|
2515
|
+
try {
|
|
2516
|
+
result = await verifyProofs();
|
|
2517
|
+
} catch (error) {
|
|
2518
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
2519
|
+
logger.debug("Failed to verify the Object Integrity Proofs of the activity without an actor:\n{error}", {
|
|
2520
|
+
recipient,
|
|
2521
|
+
error
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2524
|
+
if (result?.status === "unavailable") throw result.error;
|
|
2525
|
+
if (result?.status === "verified" && result.signers.length > 0) {
|
|
2526
|
+
activity = observation.activity = result.object;
|
|
2527
|
+
documentSigners = toProofPrincipals(result.signers);
|
|
2528
|
+
viewSource = rawViewSource;
|
|
2529
|
+
proofVerified = true;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2463
2532
|
if (!skipSignatureVerification && isPortableActivity(activity)) try {
|
|
2464
2533
|
proofVerified = await verifyObject(Activity, jsonWithoutSig, {
|
|
2465
2534
|
...signatureObservation,
|
|
2466
|
-
contextLoader:
|
|
2535
|
+
contextLoader: standardLoader,
|
|
2467
2536
|
documentLoader: ctx.documentLoader,
|
|
2468
2537
|
keyCache,
|
|
2469
2538
|
meterProvider,
|
|
@@ -2481,18 +2550,11 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2481
2550
|
recipient,
|
|
2482
2551
|
json
|
|
2483
2552
|
});
|
|
2553
|
+
let proofResult;
|
|
2484
2554
|
try {
|
|
2485
|
-
|
|
2486
|
-
...signatureObservation,
|
|
2487
|
-
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
2488
|
-
documentLoader: ctx.documentLoader,
|
|
2489
|
-
keyCache,
|
|
2490
|
-
meterProvider,
|
|
2491
|
-
tracerProvider,
|
|
2492
|
-
verifyPortableObject: ctx.verifyPortableObject
|
|
2493
|
-
});
|
|
2555
|
+
proofResult = await verifyProofs();
|
|
2494
2556
|
} catch (error) {
|
|
2495
|
-
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig,
|
|
2557
|
+
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, standardLoader)) return await respondInvalidActivity(error);
|
|
2496
2558
|
if (deferredLdSignatureError != null) {
|
|
2497
2559
|
logger.debug("Object Integrity Proof fallback did not supersede a deferred Linked Data Signature failure:\n{error}", {
|
|
2498
2560
|
recipient,
|
|
@@ -2528,6 +2590,22 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2528
2590
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
2529
2591
|
});
|
|
2530
2592
|
}
|
|
2593
|
+
if (proofResult.status === "verified") if (proofResult.signers.length < 1 && await isActorlessCandidate(proofResult.object, rawViewSource)) activity = null;
|
|
2594
|
+
else {
|
|
2595
|
+
activity = proofResult.object;
|
|
2596
|
+
documentSigners = toProofPrincipals(proofResult.signers);
|
|
2597
|
+
viewSource = rawViewSource;
|
|
2598
|
+
}
|
|
2599
|
+
else if (proofResult.status === "unavailable") {
|
|
2600
|
+
let parsed = null;
|
|
2601
|
+
try {
|
|
2602
|
+
parsed = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
2603
|
+
...ctx,
|
|
2604
|
+
contextLoader: standardLoader
|
|
2605
|
+
});
|
|
2606
|
+
} catch {}
|
|
2607
|
+
if (parsed != null && await isActorlessCandidate(parsed, rawViewSource)) throw proofResult.error;
|
|
2608
|
+
}
|
|
2531
2609
|
if (activity == null) logger.debug("Object Integrity Proofs are not verified.", {
|
|
2532
2610
|
recipient,
|
|
2533
2611
|
activity: json
|
|
@@ -2657,14 +2735,28 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2657
2735
|
try {
|
|
2658
2736
|
activity = observation.activity = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
2659
2737
|
...ctx,
|
|
2660
|
-
contextLoader:
|
|
2738
|
+
contextLoader: standardLoader
|
|
2661
2739
|
});
|
|
2662
2740
|
} catch (error) {
|
|
2663
2741
|
if (!isPermanentActivityParseError(error)) throw error;
|
|
2664
2742
|
return await respondInvalidActivity(error);
|
|
2665
2743
|
}
|
|
2744
|
+
viewSource = rawViewSource;
|
|
2666
2745
|
}
|
|
2667
2746
|
observation.activity = activity;
|
|
2747
|
+
let view;
|
|
2748
|
+
try {
|
|
2749
|
+
view = await buildVerifiedActivityView(snapshot, viewSource ?? rawViewSource);
|
|
2750
|
+
} catch (error) {
|
|
2751
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
2752
|
+
return await respondInvalidActivity(error);
|
|
2753
|
+
}
|
|
2754
|
+
const actorless = !skipSignatureVerification && getActorPresence(view.expanded) === "absent" && inboxListeners?.dispatchWithClass(activity)?.options.allowActorless === true;
|
|
2755
|
+
span.setAttribute("activitypub.activity.actorless", actorless);
|
|
2756
|
+
if (actorless && httpSigKey != null) {
|
|
2757
|
+
const principal = getHttpKeyPrincipal(httpSigKey);
|
|
2758
|
+
if (principal != null) requestSigners = [principal];
|
|
2759
|
+
}
|
|
2668
2760
|
observation.stage = "policy";
|
|
2669
2761
|
observation.result = {
|
|
2670
2762
|
disposition: "rejected",
|
|
@@ -2708,7 +2800,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2708
2800
|
const rejection = await observeAttempt(signatureObservation, "objectIntegrity", async (verification) => {
|
|
2709
2801
|
const rejection = await verifyPortableActivityId(activity.id, jsonWithoutSig, {
|
|
2710
2802
|
[verificationObservation]: verification,
|
|
2711
|
-
contextLoader:
|
|
2803
|
+
contextLoader: standardLoader,
|
|
2712
2804
|
documentLoader: ctx.documentLoader,
|
|
2713
2805
|
keyCache,
|
|
2714
2806
|
meterProvider,
|
|
@@ -2746,7 +2838,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2746
2838
|
});
|
|
2747
2839
|
}
|
|
2748
2840
|
}
|
|
2749
|
-
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
2841
|
+
if (httpSigKey != null && !actorless && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
2750
2842
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
2751
2843
|
observation.authentication = {
|
|
2752
2844
|
status: "rejected",
|
|
@@ -2772,6 +2864,66 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2772
2864
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
2773
2865
|
});
|
|
2774
2866
|
}
|
|
2867
|
+
if (httpSigKey != null && !actorless && activity.actorId != null) requestSigners = [{
|
|
2868
|
+
kind: "actor",
|
|
2869
|
+
id: activity.actorId,
|
|
2870
|
+
mechanism: "httpSignatures",
|
|
2871
|
+
keyId: httpSigKey.id
|
|
2872
|
+
}];
|
|
2873
|
+
if (actorless) {
|
|
2874
|
+
const check = checkActorlessActivity(activity, {
|
|
2875
|
+
verified: true,
|
|
2876
|
+
requestSigners,
|
|
2877
|
+
documentSigners,
|
|
2878
|
+
originAuthenticated: [],
|
|
2879
|
+
expandedActivity: [],
|
|
2880
|
+
baseUrl: null
|
|
2881
|
+
});
|
|
2882
|
+
if (check.status === "noAuthenticatedPrincipal") {
|
|
2883
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
2884
|
+
observation.authentication = {
|
|
2885
|
+
status: "rejected",
|
|
2886
|
+
reason: { type: "noAuthenticatedPrincipal" }
|
|
2887
|
+
};
|
|
2888
|
+
logger.error("The activity {activityId} declares no actor, and no principal is authenticated for it.", {
|
|
2889
|
+
activity: json,
|
|
2890
|
+
recipient,
|
|
2891
|
+
activityId: activity.id?.href
|
|
2892
|
+
});
|
|
2893
|
+
span.setStatus({
|
|
2894
|
+
code: SpanStatusCode.ERROR,
|
|
2895
|
+
message: "No principal is authenticated for the activity."
|
|
2896
|
+
});
|
|
2897
|
+
return new Response("No principal is authenticated for the activity.", {
|
|
2898
|
+
status: 401,
|
|
2899
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
2900
|
+
});
|
|
2901
|
+
} else if (check.status === "activityOriginMismatch") {
|
|
2902
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
2903
|
+
observation.authentication = {
|
|
2904
|
+
status: "rejected",
|
|
2905
|
+
reason: {
|
|
2906
|
+
type: "activityOriginMismatch",
|
|
2907
|
+
activityId: new URL(activity.id.href),
|
|
2908
|
+
actorIds: check.principals.map((principal) => principal.id)
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
logger.error("The activity ({activityId}) does not have the same origin as the principals that authenticated it.", {
|
|
2912
|
+
activity: json,
|
|
2913
|
+
recipient,
|
|
2914
|
+
activityId: activity.id?.href,
|
|
2915
|
+
principals: check.principals.map((principal) => principal.id.href)
|
|
2916
|
+
});
|
|
2917
|
+
span.setStatus({
|
|
2918
|
+
code: SpanStatusCode.ERROR,
|
|
2919
|
+
message: `The activity (${activity.id?.href}) does not have the same origin as the principals that authenticated it.`
|
|
2920
|
+
});
|
|
2921
|
+
return new Response("The activity and its signers do not have the same origin.", {
|
|
2922
|
+
status: 401,
|
|
2923
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2775
2927
|
if (!skipSignatureVerification) {
|
|
2776
2928
|
const compoundJson = Array.isArray(json) ? json : jsonWithoutSig;
|
|
2777
2929
|
if (inspectCompoundPortableObjectApplicability(compoundJson, INBOX_COMPOUND_PROOF_LIMITS) !== "absent") {
|
|
@@ -2831,7 +2983,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2831
2983
|
return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
2832
2984
|
}
|
|
2833
2985
|
}
|
|
2834
|
-
if (!skipSignatureVerification && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
2986
|
+
if (!skipSignatureVerification && !actorless && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
2835
2987
|
observation.authentication = {
|
|
2836
2988
|
status: "rejected",
|
|
2837
2989
|
reason: {
|
|
@@ -2860,7 +3012,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2860
3012
|
attempts: observation.verification.attempts.filter((attempt) => attempt.status === "verified")
|
|
2861
3013
|
};
|
|
2862
3014
|
observation.stage = "dispatch";
|
|
2863
|
-
if (activity.actorId == null) {
|
|
3015
|
+
if (!actorless && activity.actorId == null) {
|
|
2864
3016
|
observation.result = {
|
|
2865
3017
|
disposition: "rejected",
|
|
2866
3018
|
reason: "missingActor"
|
|
@@ -2884,6 +3036,17 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
2884
3036
|
originalJson: json,
|
|
2885
3037
|
normalizedActivity: hasLdSignature && compactedJson !== json ? compactedJson : void 0,
|
|
2886
3038
|
ldSignatureVerified: hasLdSignature ? ldSigVerified : void 0,
|
|
3039
|
+
authentication: createAuthenticationEvidence({
|
|
3040
|
+
verified: !skipSignatureVerification,
|
|
3041
|
+
requestSigners,
|
|
3042
|
+
documentSigners,
|
|
3043
|
+
originAuthenticated: [],
|
|
3044
|
+
expandedActivity: deepFreeze(view.expanded),
|
|
3045
|
+
baseUrl: null
|
|
3046
|
+
}),
|
|
3047
|
+
verifiedView: view.view,
|
|
3048
|
+
replayable: view.replayable,
|
|
3049
|
+
actorless,
|
|
2887
3050
|
activity,
|
|
2888
3051
|
recipient,
|
|
2889
3052
|
inboxListeners,
|
|
@@ -3098,8 +3261,8 @@ var CustomCollectionHandler = class {
|
|
|
3098
3261
|
* @param CollectionPage The CollectionPage constructor.
|
|
3099
3262
|
* @param filterPredicate Optional filter predicate for items.
|
|
3100
3263
|
*/
|
|
3101
|
-
constructor(name$
|
|
3102
|
-
this.name = name$
|
|
3264
|
+
constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
|
|
3265
|
+
this.name = name$2;
|
|
3103
3266
|
this.values = values;
|
|
3104
3267
|
this.context = context;
|
|
3105
3268
|
this.callbacks = callbacks;
|
|
@@ -3608,6 +3771,42 @@ const MIN_COMPONENTS = [
|
|
|
3608
3771
|
"@authority"
|
|
3609
3772
|
];
|
|
3610
3773
|
/**
|
|
3774
|
+
* Turns the signers of verified Object Integrity Proofs into principals.
|
|
3775
|
+
*/
|
|
3776
|
+
function toProofPrincipals(signers) {
|
|
3777
|
+
return signers.map((signer) => ({
|
|
3778
|
+
kind: signer.kind,
|
|
3779
|
+
id: signer.id,
|
|
3780
|
+
mechanism: "objectIntegrityProofs",
|
|
3781
|
+
keyId: signer.keyId
|
|
3782
|
+
}));
|
|
3783
|
+
}
|
|
3784
|
+
/**
|
|
3785
|
+
* Gets the principal of an HTTP Signature key, whose owner was confirmed by
|
|
3786
|
+
* the owner's own document, or by the signed document of a portable actor,
|
|
3787
|
+
* when the key was fetched.
|
|
3788
|
+
*/
|
|
3789
|
+
function getHttpKeyPrincipal(key) {
|
|
3790
|
+
const evidence = getVerifiedKeyOwnerEvidence(key);
|
|
3791
|
+
if (evidence != null) try {
|
|
3792
|
+
return {
|
|
3793
|
+
kind: "actor",
|
|
3794
|
+
id: parseIri(evidence.ownerId),
|
|
3795
|
+
mechanism: "httpSignatures",
|
|
3796
|
+
keyId: key.id
|
|
3797
|
+
};
|
|
3798
|
+
} catch {
|
|
3799
|
+
return null;
|
|
3800
|
+
}
|
|
3801
|
+
if (key.ownerId == null || isPortableId(key.ownerId)) return null;
|
|
3802
|
+
return {
|
|
3803
|
+
kind: "actor",
|
|
3804
|
+
id: key.ownerId,
|
|
3805
|
+
mechanism: "httpSignatures",
|
|
3806
|
+
keyId: key.id
|
|
3807
|
+
};
|
|
3808
|
+
}
|
|
3809
|
+
/**
|
|
3611
3810
|
* Checks whether an HTTP Signature key is a key of an FEP-ef61 portable
|
|
3612
3811
|
* actor, i.e., its ID is a compatible identifier or an `ap:` or `ap+ef61:`
|
|
3613
3812
|
* URI, and it is owned by a portable actor, which only the portable actor's
|
|
@@ -5699,24 +5898,102 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5699
5898
|
let dispatched;
|
|
5700
5899
|
let parseInput = void 0;
|
|
5701
5900
|
let parseContextLoader = context.contextLoader;
|
|
5901
|
+
let authentication = getEmptyAuthenticationEvidence();
|
|
5902
|
+
let actorPresence = "present";
|
|
5903
|
+
if (message.verifiedView !== void 0) {
|
|
5904
|
+
const view = parseSerializedVerifiedActivityView(message.verifiedView);
|
|
5905
|
+
let restored;
|
|
5906
|
+
let restoredAuthentication = null;
|
|
5907
|
+
let failure;
|
|
5908
|
+
if (view == null) failure = /* @__PURE__ */ new TypeError("The queued activity has a malformed verified view.");
|
|
5909
|
+
else try {
|
|
5910
|
+
if (view.source === "normalizedActivity") assertSafeJsonLd(message.normalizedActivity);
|
|
5911
|
+
restored = await restoreVerifiedActivityView(view, message);
|
|
5912
|
+
} catch (error) {
|
|
5913
|
+
if (!(error instanceof ContextSnapshotMissError) && !isPermanentInboxParseError(error)) {
|
|
5914
|
+
await handleRetriableFailure(error);
|
|
5915
|
+
return;
|
|
5916
|
+
}
|
|
5917
|
+
failure = error;
|
|
5918
|
+
}
|
|
5919
|
+
if (restored != null) {
|
|
5920
|
+
const expandedActivity = deepFreeze(restored.expanded);
|
|
5921
|
+
restoredAuthentication = message.authentication === void 0 ? createAuthenticationEvidence({
|
|
5922
|
+
...getEmptyAuthenticationEvidence(),
|
|
5923
|
+
expandedActivity,
|
|
5924
|
+
baseUrl: restored.baseUrl
|
|
5925
|
+
}) : deserializeAuthentication(message.authentication, expandedActivity, restored.baseUrl);
|
|
5926
|
+
if (restoredAuthentication == null) failure = /* @__PURE__ */ new TypeError("The queued activity has malformed authentication evidence.");
|
|
5927
|
+
}
|
|
5928
|
+
if (failure != null || restored == null || restoredAuthentication == null) {
|
|
5929
|
+
await reportInboxError(failure);
|
|
5930
|
+
logger.error("Failed to replay the queued incoming activity:\n{error}", {
|
|
5931
|
+
error: failure,
|
|
5932
|
+
trial: message.attempt,
|
|
5933
|
+
activity: message.activity,
|
|
5934
|
+
recipient: message.identifier
|
|
5935
|
+
});
|
|
5936
|
+
listenerSpan.setStatus({
|
|
5937
|
+
code: SpanStatusCode.ERROR,
|
|
5938
|
+
message: String(failure)
|
|
5939
|
+
});
|
|
5940
|
+
listenerSpan.end();
|
|
5941
|
+
return;
|
|
5942
|
+
}
|
|
5943
|
+
authentication = restoredAuthentication;
|
|
5944
|
+
actorPresence = getActorPresence(restored.expanded);
|
|
5945
|
+
const policy = view.policy;
|
|
5946
|
+
const replayLoader = createReleasableLoader(restored.loader, policy === "normalization" ? getNormalizationContextLoader(context.contextLoader) : wrapContextLoaderForJsonLd(context.contextLoader), policy);
|
|
5947
|
+
parseInput = restored.document;
|
|
5948
|
+
parseContextLoader = restored.loader;
|
|
5949
|
+
try {
|
|
5950
|
+
activity = await Activity.fromJsonLd(restored.document, {
|
|
5951
|
+
...context,
|
|
5952
|
+
contextLoader: replayLoader.loader,
|
|
5953
|
+
...restored.baseUrl == null ? {} : { baseUrl: restored.baseUrl }
|
|
5954
|
+
});
|
|
5955
|
+
} catch (error) {
|
|
5956
|
+
if (isPermanentInboxParseError(error)) {
|
|
5957
|
+
await reportInboxError(error);
|
|
5958
|
+
logger.error("Failed to parse the queued incoming activity:\n{error}", {
|
|
5959
|
+
error,
|
|
5960
|
+
trial: message.attempt,
|
|
5961
|
+
activity: message.activity,
|
|
5962
|
+
recipient: message.identifier
|
|
5963
|
+
});
|
|
5964
|
+
listenerSpan.setStatus({
|
|
5965
|
+
code: SpanStatusCode.ERROR,
|
|
5966
|
+
message: String(error)
|
|
5967
|
+
});
|
|
5968
|
+
listenerSpan.end();
|
|
5969
|
+
return;
|
|
5970
|
+
}
|
|
5971
|
+
await handleRetriableFailure(error);
|
|
5972
|
+
return;
|
|
5973
|
+
} finally {
|
|
5974
|
+
replayLoader.release();
|
|
5975
|
+
}
|
|
5976
|
+
}
|
|
5702
5977
|
try {
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5978
|
+
if (activity == null) {
|
|
5979
|
+
const hasSignatureField = hasSignature(message.activity);
|
|
5980
|
+
const shouldParseFromNormalizedSignedPayload = message.ldSignatureVerified === true || message.normalizedActivity != null || message.ldSignatureVerified == null && hasSignatureField;
|
|
5981
|
+
const parseContext = hasSignatureField ? {
|
|
5982
|
+
...context,
|
|
5983
|
+
contextLoader: getNormalizationContextLoader(context.contextLoader)
|
|
5984
|
+
} : {
|
|
5985
|
+
...context,
|
|
5986
|
+
contextLoader: wrapContextLoaderForJsonLd(context.contextLoader)
|
|
5987
|
+
};
|
|
5988
|
+
parseContextLoader = parseContext.contextLoader;
|
|
5989
|
+
let normalizedActivity;
|
|
5990
|
+
if (shouldParseFromNormalizedSignedPayload) {
|
|
5991
|
+
normalizedActivity = message.normalizedActivity ?? await compactJsonLd(message.activity, context.contextLoader);
|
|
5992
|
+
assertSafeJsonLd(normalizedActivity);
|
|
5993
|
+
}
|
|
5994
|
+
parseInput = shouldParseFromNormalizedSignedPayload ? detachSignature(normalizedActivity) : hasSignatureField ? detachSignature(message.activity) : message.activity;
|
|
5995
|
+
activity = await Activity.fromJsonLd(parseInput, parseContext);
|
|
5717
5996
|
}
|
|
5718
|
-
parseInput = shouldParseFromNormalizedSignedPayload ? detachSignature(normalizedActivity) : hasSignatureField ? detachSignature(message.activity) : message.activity;
|
|
5719
|
-
activity = await Activity.fromJsonLd(parseInput, parseContext);
|
|
5720
5997
|
activityType = getTypeId(activity).href;
|
|
5721
5998
|
span.setAttribute("activitypub.activity.type", activityType);
|
|
5722
5999
|
listenerSpan.setAttribute("activitypub.activity.type", activityType);
|
|
@@ -5725,7 +6002,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5725
6002
|
span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
5726
6003
|
listenerSpan.setAttribute("activitypub.activity.id", activity.id.href);
|
|
5727
6004
|
}
|
|
5728
|
-
|
|
6005
|
+
const actorless = actorPresence === "absent" && !this.skipSignatureVerification && authentication.verified && this.inboxListeners?.dispatchWithClass(activity)?.options.allowActorless === true && isActorlessActivityAuthenticated(activity, authentication);
|
|
6006
|
+
if (activity.actorId == null && !actorless) {
|
|
5729
6007
|
logger.error("Missing actor in queued incoming activity.", {
|
|
5730
6008
|
activityId: activity.id?.href,
|
|
5731
6009
|
activity: message.activity,
|
|
@@ -5739,7 +6017,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5739
6017
|
listenerSpan.end();
|
|
5740
6018
|
return;
|
|
5741
6019
|
}
|
|
5742
|
-
if (!this.skipSignatureVerification && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
6020
|
+
if (!this.skipSignatureVerification && !actorless && activity.id != null && !actorsHaveSameOrigin(activity)) {
|
|
5743
6021
|
logger.error("The queued activity ({activityId}) and its actors do not have the same origin.", {
|
|
5744
6022
|
activityId: activity.id.href,
|
|
5745
6023
|
actorIds: activity.actorIds.map((actor) => actor.href),
|
|
@@ -5754,22 +6032,18 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5754
6032
|
listenerSpan.end();
|
|
5755
6033
|
return;
|
|
5756
6034
|
}
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
5770
|
-
listenerSpan.end();
|
|
5771
|
-
return;
|
|
5772
|
-
}
|
|
6035
|
+
const parsedActivity = activity;
|
|
6036
|
+
const parsedActivityType = activityType;
|
|
6037
|
+
cacheKey = await getInboxIdempotencyKey(this.idempotencyStrategy, () => context.toInboxContext(message.identifier, message.activity, parsedActivity.id?.href, parsedActivityType, { authentication }), activity, context.origin, message.identifier, this.kvPrefixes.activityIdempotence);
|
|
6038
|
+
if (await isInboxActivityProcessed(this.kv, cacheKey, activity, context.origin, this.kvPrefixes.activityIdempotence)) {
|
|
6039
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
6040
|
+
activityId: activity.id?.href,
|
|
6041
|
+
activity: message.activity,
|
|
6042
|
+
recipient: message.identifier
|
|
6043
|
+
});
|
|
6044
|
+
recordInboxActivity(this.meterProvider, "rejected", activityType);
|
|
6045
|
+
listenerSpan.end();
|
|
6046
|
+
return;
|
|
5773
6047
|
}
|
|
5774
6048
|
dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
5775
6049
|
} catch (error) {
|
|
@@ -5828,7 +6102,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5828
6102
|
try {
|
|
5829
6103
|
const started = performance.now();
|
|
5830
6104
|
try {
|
|
5831
|
-
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, activityType), activity);
|
|
6105
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, activityType, { authentication }), activity);
|
|
5832
6106
|
} finally {
|
|
5833
6107
|
this.metrics.recordInboxProcessingDuration(activityType, getDurationMs(started));
|
|
5834
6108
|
}
|
|
@@ -6230,7 +6504,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
6230
6504
|
onNotAcceptable ??= notAcceptable;
|
|
6231
6505
|
onUnauthorized ??= unauthorized;
|
|
6232
6506
|
const url = new URL(request.url);
|
|
6233
|
-
const route = this.router.route(url.pathname);
|
|
6507
|
+
const route = this.router.route(url.pathname, { allowUnencodedColon: true });
|
|
6234
6508
|
if (route == null) {
|
|
6235
6509
|
const media = this.hashlinkMediaDispatcher == null ? null : parseHashlinkGatewayRequest(url);
|
|
6236
6510
|
if (media != null) return await this.#fetchHashlinkMedia(request, media, {
|
|
@@ -7135,7 +7409,7 @@ var ContextImpl = class ContextImpl {
|
|
|
7135
7409
|
invokedFromActorKeyPairsDispatcher: this.invokedFromActorKeyPairsDispatcher
|
|
7136
7410
|
});
|
|
7137
7411
|
}
|
|
7138
|
-
toInboxContext(recipient, activity, activityId, activityType) {
|
|
7412
|
+
toInboxContext(recipient, activity, activityId, activityType, metadata) {
|
|
7139
7413
|
return new InboxContextImpl(recipient, activity, activityId, activityType, {
|
|
7140
7414
|
url: this.url,
|
|
7141
7415
|
federation: this.federation,
|
|
@@ -7143,7 +7417,7 @@ var ContextImpl = class ContextImpl {
|
|
|
7143
7417
|
documentLoader: this.documentLoader,
|
|
7144
7418
|
contextLoader: this.contextLoader,
|
|
7145
7419
|
invokedFromActorKeyPairsDispatcher: this.invokedFromActorKeyPairsDispatcher
|
|
7146
|
-
});
|
|
7420
|
+
}, metadata?.authentication);
|
|
7147
7421
|
}
|
|
7148
7422
|
toOutboxContext(identifier, activity, activityId, activityType) {
|
|
7149
7423
|
return new OutboxContextImpl(identifier, activity, activityId, activityType, {
|
|
@@ -7758,12 +8032,20 @@ var ContextImpl = class ContextImpl {
|
|
|
7758
8032
|
});
|
|
7759
8033
|
}
|
|
7760
8034
|
async routeActivityInternal(recipient, activity, options = {}, span) {
|
|
8035
|
+
const snapshot = createContextSnapshot(options.contextLoader ?? this.contextLoader);
|
|
8036
|
+
try {
|
|
8037
|
+
return await this.#routeActivityWithSnapshot(recipient, activity, options, span, snapshot);
|
|
8038
|
+
} finally {
|
|
8039
|
+
snapshot.release();
|
|
8040
|
+
}
|
|
8041
|
+
}
|
|
8042
|
+
async #routeActivityWithSnapshot(recipient, activity, options, span, snapshot) {
|
|
7761
8043
|
const logger = getLogger([
|
|
7762
8044
|
"fedify",
|
|
7763
8045
|
"federation",
|
|
7764
8046
|
"inbox"
|
|
7765
8047
|
]);
|
|
7766
|
-
const contextLoader =
|
|
8048
|
+
const contextLoader = snapshot.loader("standard");
|
|
7767
8049
|
let json = await activity.toJsonLd({ contextLoader });
|
|
7768
8050
|
const keyCache = new KvKeyCache(this.federation.kv, this.federation.kvPrefixes.publicKey, {
|
|
7769
8051
|
documentLoader: this.documentLoader,
|
|
@@ -7771,13 +8053,19 @@ var ContextImpl = class ContextImpl {
|
|
|
7771
8053
|
tracerProvider: this.tracerProvider,
|
|
7772
8054
|
keyTtl: this.federation.publicKeyTtl
|
|
7773
8055
|
});
|
|
7774
|
-
|
|
8056
|
+
let documentSigners = [];
|
|
8057
|
+
let originAuthenticated = [];
|
|
8058
|
+
let viewSource;
|
|
8059
|
+
let fetchedView;
|
|
8060
|
+
const document = detachSignature(json);
|
|
8061
|
+
const verified = await verifyObjectDetailed(Activity, document, {
|
|
7775
8062
|
contextLoader,
|
|
7776
8063
|
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
7777
8064
|
meterProvider: this.meterProvider,
|
|
7778
8065
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
7779
8066
|
keyCache
|
|
7780
|
-
})
|
|
8067
|
+
});
|
|
8068
|
+
if (verified.status !== "verified") {
|
|
7781
8069
|
logger.debug("Object Integrity Proofs are not verified.", {
|
|
7782
8070
|
recipient,
|
|
7783
8071
|
activity: json
|
|
@@ -7789,8 +8077,29 @@ var ContextImpl = class ContextImpl {
|
|
|
7789
8077
|
});
|
|
7790
8078
|
return false;
|
|
7791
8079
|
}
|
|
7792
|
-
|
|
7793
|
-
|
|
8080
|
+
let candidate;
|
|
8081
|
+
let candidateView;
|
|
8082
|
+
const verifications = /* @__PURE__ */ new WeakMap();
|
|
8083
|
+
const fetched = await this.lookupObject(activity.id, {
|
|
8084
|
+
...options,
|
|
8085
|
+
contextLoader,
|
|
8086
|
+
verifyPortableObject: async (document, verifierOptions) => {
|
|
8087
|
+
const result = await this.verifyPortableObject(document, verifierOptions);
|
|
8088
|
+
if (document != null && typeof document === "object") verifications.set(document, result);
|
|
8089
|
+
return result;
|
|
8090
|
+
},
|
|
8091
|
+
[lookupObserver]: { accept: async (accepted) => {
|
|
8092
|
+
candidate = accepted;
|
|
8093
|
+
candidateView = await buildVerifiedActivityView(createContextSnapshot(accepted.contextLoader), {
|
|
8094
|
+
policy: "standard",
|
|
8095
|
+
source: "activity",
|
|
8096
|
+
document: detachSignature(accepted.document),
|
|
8097
|
+
baseUrl: accepted.baseUrl
|
|
8098
|
+
});
|
|
8099
|
+
return true;
|
|
8100
|
+
} }
|
|
8101
|
+
});
|
|
8102
|
+
if (fetched == null || candidate == null || candidateView == null) {
|
|
7794
8103
|
logger.debug("Failed to fetch the remote activity object {activityId}.", {
|
|
7795
8104
|
recipient,
|
|
7796
8105
|
activity: json,
|
|
@@ -7826,11 +8135,50 @@ var ContextImpl = class ContextImpl {
|
|
|
7826
8135
|
}
|
|
7827
8136
|
logger.debug("Successfully fetched the remote activity object {activityId}; ignore the original activity and use the fetched one, which is trustworthy.");
|
|
7828
8137
|
activity = fetched;
|
|
7829
|
-
json =
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
8138
|
+
json = candidate.document;
|
|
8139
|
+
fetchedView = candidateView;
|
|
8140
|
+
viewSource = {
|
|
8141
|
+
policy: "standard",
|
|
8142
|
+
source: "activity",
|
|
8143
|
+
document: detachSignature(candidate.document),
|
|
8144
|
+
baseUrl: candidate.baseUrl
|
|
8145
|
+
};
|
|
8146
|
+
if (isPortableId(fetched.id)) {
|
|
8147
|
+
const result = verifications.get(candidate.document);
|
|
8148
|
+
if (result?.verified === true && result.method === "proof") documentSigners = result.keys.flatMap((key) => {
|
|
8149
|
+
const signer = getProofSigner(key);
|
|
8150
|
+
return signer == null ? [] : [{
|
|
8151
|
+
kind: signer.kind,
|
|
8152
|
+
id: signer.id,
|
|
8153
|
+
mechanism: "objectIntegrityProofs",
|
|
8154
|
+
keyId: signer.keyId
|
|
8155
|
+
}];
|
|
8156
|
+
});
|
|
8157
|
+
} else originAuthenticated = fetched.actorIds.map((actorId) => ({
|
|
8158
|
+
kind: "actor",
|
|
8159
|
+
id: actorId,
|
|
8160
|
+
mechanism: "origin",
|
|
8161
|
+
keyId: null
|
|
8162
|
+
}));
|
|
8163
|
+
} else {
|
|
8164
|
+
logger.debug("Object Integrity Proofs are verified.", {
|
|
8165
|
+
recipient,
|
|
8166
|
+
activity: json
|
|
8167
|
+
});
|
|
8168
|
+
activity = verified.object;
|
|
8169
|
+
documentSigners = verified.signers.map((signer) => ({
|
|
8170
|
+
kind: signer.kind,
|
|
8171
|
+
id: signer.id,
|
|
8172
|
+
mechanism: "objectIntegrityProofs",
|
|
8173
|
+
keyId: signer.keyId
|
|
8174
|
+
}));
|
|
8175
|
+
viewSource = {
|
|
8176
|
+
policy: "standard",
|
|
8177
|
+
source: "activity",
|
|
8178
|
+
document,
|
|
8179
|
+
baseUrl: null
|
|
8180
|
+
};
|
|
8181
|
+
}
|
|
7834
8182
|
if (activity.actorId == null) {
|
|
7835
8183
|
logger.debug("Activity is missing an actor; unable to verify.", {
|
|
7836
8184
|
recipient,
|
|
@@ -7845,10 +8193,21 @@ var ContextImpl = class ContextImpl {
|
|
|
7845
8193
|
});
|
|
7846
8194
|
return false;
|
|
7847
8195
|
}
|
|
8196
|
+
const view = fetchedView ?? await buildVerifiedActivityView(snapshot, viewSource);
|
|
7848
8197
|
const routeResult = await routeActivity({
|
|
7849
8198
|
context: this,
|
|
7850
8199
|
json,
|
|
7851
8200
|
ldSignatureVerified: false,
|
|
8201
|
+
authentication: createAuthenticationEvidence({
|
|
8202
|
+
verified: true,
|
|
8203
|
+
requestSigners: [],
|
|
8204
|
+
documentSigners,
|
|
8205
|
+
originAuthenticated,
|
|
8206
|
+
expandedActivity: deepFreeze(view.expanded),
|
|
8207
|
+
baseUrl: viewSource.baseUrl
|
|
8208
|
+
}),
|
|
8209
|
+
verifiedView: view.view,
|
|
8210
|
+
replayable: view.replayable,
|
|
7852
8211
|
activity,
|
|
7853
8212
|
recipient,
|
|
7854
8213
|
inboxListeners: this.federation.inboxListeners,
|
|
@@ -7964,52 +8323,92 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
7964
8323
|
if (object instanceof Tombstone && !(object instanceof cls) && options?.tombstone !== "passthrough") return null;
|
|
7965
8324
|
return object;
|
|
7966
8325
|
}
|
|
7967
|
-
#signedKey =
|
|
8326
|
+
#signedKey = null;
|
|
8327
|
+
#signedKeyOwner = null;
|
|
8328
|
+
#signatureChecks = /* @__PURE__ */ new WeakMap();
|
|
8329
|
+
#getSignatureCheck(documentLoader, contextLoader) {
|
|
8330
|
+
let checks = this.#signatureChecks.get(documentLoader);
|
|
8331
|
+
if (checks == null) {
|
|
8332
|
+
checks = /* @__PURE__ */ new WeakMap();
|
|
8333
|
+
this.#signatureChecks.set(documentLoader, checks);
|
|
8334
|
+
}
|
|
8335
|
+
let check = checks.get(contextLoader);
|
|
8336
|
+
if (check == null) {
|
|
8337
|
+
check = {};
|
|
8338
|
+
checks.set(contextLoader, check);
|
|
8339
|
+
}
|
|
8340
|
+
return check;
|
|
8341
|
+
}
|
|
7968
8342
|
async getSignedKey(options = {}) {
|
|
7969
8343
|
if (this.#signedKey != null) return this.#signedKey;
|
|
7970
|
-
const
|
|
7971
|
-
|
|
7972
|
-
|
|
8344
|
+
const documentLoader = options.documentLoader ?? this.documentLoader;
|
|
8345
|
+
const contextLoader = options.contextLoader ?? this.contextLoader;
|
|
8346
|
+
const check = this.#getSignatureCheck(documentLoader, contextLoader);
|
|
8347
|
+
if (check.key != null) return check.key;
|
|
8348
|
+
const keyCache = documentLoader === this.documentLoader && contextLoader === this.contextLoader ? new KvKeyCache(this.federation.kv, this.federation.kvPrefixes.publicKey, {
|
|
8349
|
+
documentLoader,
|
|
8350
|
+
contextLoader,
|
|
7973
8351
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
7974
8352
|
keyTtl: this.federation.publicKeyTtl
|
|
7975
|
-
});
|
|
7976
|
-
|
|
8353
|
+
}) : void 0;
|
|
8354
|
+
const promise = verifyRequest(this.request, {
|
|
7977
8355
|
...this,
|
|
7978
|
-
contextLoader
|
|
7979
|
-
documentLoader
|
|
8356
|
+
contextLoader,
|
|
8357
|
+
documentLoader,
|
|
7980
8358
|
timeWindow: this.federation.signatureTimeWindow,
|
|
7981
8359
|
maxSignatures: this.federation.maxHttpSignatures,
|
|
8360
|
+
keyCache,
|
|
7982
8361
|
meterProvider: this.meterProvider,
|
|
7983
|
-
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
7984
|
-
|
|
8362
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
8363
|
+
}).then((key) => {
|
|
8364
|
+
if (key != null) this.#signedKey ??= key;
|
|
8365
|
+
return key;
|
|
8366
|
+
}).catch((error) => {
|
|
8367
|
+
if (check.key === promise) check.key = void 0;
|
|
8368
|
+
throw error;
|
|
7985
8369
|
});
|
|
8370
|
+
check.key = promise;
|
|
8371
|
+
return await promise;
|
|
7986
8372
|
}
|
|
7987
|
-
#signedKeyOwner = void 0;
|
|
7988
8373
|
async getSignedKeyOwner(options = {}) {
|
|
7989
8374
|
if (this.#signedKeyOwner != null) return this.#signedKeyOwner;
|
|
7990
|
-
const
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8375
|
+
const normalizedOptions = {
|
|
8376
|
+
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
8377
|
+
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
8378
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
8379
|
+
};
|
|
8380
|
+
const check = this.#getSignatureCheck(normalizedOptions.documentLoader, normalizedOptions.contextLoader);
|
|
8381
|
+
if (check.owner != null) return check.owner;
|
|
8382
|
+
const promise = this.getSignedKey(normalizedOptions).then(async (key) => {
|
|
8383
|
+
if (key == null) {
|
|
8384
|
+
if (check.owner === promise) check.owner = void 0;
|
|
8385
|
+
return null;
|
|
8386
|
+
}
|
|
8387
|
+
try {
|
|
8388
|
+
const owner = await getKeyOwner(key, normalizedOptions);
|
|
8389
|
+
if (owner != null) this.#signedKeyOwner ??= owner;
|
|
8390
|
+
return owner;
|
|
8391
|
+
} catch (error) {
|
|
8392
|
+
if (error instanceof FetchError) {
|
|
8393
|
+
getLogger([
|
|
8394
|
+
"fedify",
|
|
8395
|
+
"federation",
|
|
8396
|
+
"actor"
|
|
8397
|
+
]).warn("Failed to fetch the key owner {keyOwner} of {keyId} while verifying the request signature; treating the request as unauthenticated: {error}", {
|
|
8398
|
+
keyId: key.id?.href,
|
|
8399
|
+
keyOwner: error.url.href,
|
|
8400
|
+
error
|
|
8401
|
+
});
|
|
8402
|
+
return null;
|
|
8403
|
+
}
|
|
8404
|
+
throw error;
|
|
8010
8405
|
}
|
|
8406
|
+
}).catch((error) => {
|
|
8407
|
+
if (check.owner === promise) check.owner = void 0;
|
|
8011
8408
|
throw error;
|
|
8012
|
-
}
|
|
8409
|
+
});
|
|
8410
|
+
check.owner = promise;
|
|
8411
|
+
return await promise;
|
|
8013
8412
|
}
|
|
8014
8413
|
async isSignedByAudience(object, options = {}) {
|
|
8015
8414
|
return await isInAudience(object, null) || await isInAudience(object, await this.getSignedKeyOwner(options), options);
|
|
@@ -8199,12 +8598,14 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
8199
8598
|
activity;
|
|
8200
8599
|
activityId;
|
|
8201
8600
|
activityType;
|
|
8202
|
-
|
|
8601
|
+
authentication;
|
|
8602
|
+
constructor(recipient, activity, activityId, activityType, options, authentication) {
|
|
8203
8603
|
super(options);
|
|
8204
8604
|
this.recipient = recipient;
|
|
8205
8605
|
this.activity = activity;
|
|
8206
8606
|
this.activityId = activityId;
|
|
8207
8607
|
this.activityType = activityType;
|
|
8608
|
+
this.authentication = authentication ?? getEmptyAuthenticationEvidence();
|
|
8208
8609
|
}
|
|
8209
8610
|
clone(data) {
|
|
8210
8611
|
return new InboxContextImpl(this.recipient, this.activity, this.activityId, this.activityType, {
|
|
@@ -8214,7 +8615,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
8214
8615
|
documentLoader: this.documentLoader,
|
|
8215
8616
|
contextLoader: this.contextLoader,
|
|
8216
8617
|
invokedFromActorKeyPairsDispatcher: this.invokedFromActorKeyPairsDispatcher
|
|
8217
|
-
});
|
|
8618
|
+
}, this.authentication);
|
|
8218
8619
|
}
|
|
8219
8620
|
forwardActivity(forwarder, recipients, options) {
|
|
8220
8621
|
return forwardActivity(this, "inbox", forwarder, recipients, options).then(() => void 0);
|