@fedify/fedify 2.4.0-dev.2256 → 2.4.0-dev.2259
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-DvSQqk2l.mjs → builder-CBNa1Uw2.mjs} +8 -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-5bg_j_ye.mjs → compound-proof-CMPv4UK0.mjs} +20 -3
- package/dist/{context-CtI307_A.d.ts → context-7NyiqIcg.d.ts} +111 -2
- package/dist/{context-B6X-t8gI.d.cts → context-tsYPJ2Ew.d.cts} +111 -2
- package/dist/{deno-AmcRMq5z.mjs → deno-C8XaXmPB.mjs} +1 -1
- package/dist/{docloader-CIP_SG39.mjs → docloader-CpdFLwAg.mjs} +2 -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 +3 -3
- package/dist/federation/handler.test.mjs +76 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox-report.test.d.mts +2 -0
- package/dist/federation/inbox-report.test.mjs +475 -0
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +7 -7
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +4 -3
- package/dist/federation/mod.d.ts +4 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- 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 +67 -6
- 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-BDzIgqOd.cjs → federation-D6giSGUT.cjs} +524 -118
- package/dist/{http-DkqWu-sm.mjs → http-BqSbUEiQ.mjs} +141 -98
- package/dist/{http-1fZ83jj7.cjs → http-Cki-npuA.cjs} +447 -110
- package/dist/{http-BGb3QioZ.js → http-OMtKlbx1.js} +430 -111
- package/dist/{http-BrwKINQn.d.cts → key-C1nv7_jD.d.ts} +638 -229
- package/dist/{http-DGx0KOws.d.ts → key-DYxuyd-s.d.cts} +638 -229
- package/dist/{key-CEsu7oaD.mjs → key-DecAtABm.mjs} +30 -3
- package/dist/{kv-cache-CJS4mImS.mjs → kv-cache-CWWlMv-s.mjs} +1 -1
- package/dist/{kv-cache-BEWuZSB4.cjs → kv-cache-D73yVcE5.cjs} +1 -1
- package/dist/{kv-cache-CGhEgt98.js → kv-cache-J0v3UbUn.js} +1 -1
- package/dist/{ld-Cf4CPWN_.mjs → ld-UsN-TIPh.mjs} +40 -5
- package/dist/{metrics-CocsZP0E.mjs → metrics-DWCn4VXX.mjs} +2 -1
- package/dist/{middleware-BfYke3YQ.js → middleware-BqzfIlUO.js} +524 -118
- package/dist/{middleware-Dxn0E9ES.mjs → middleware-CkjwiEBd.mjs} +512 -127
- package/dist/{middleware-Cne_jMZo.mjs → middleware-DHn2q0L1.mjs} +1 -1
- package/dist/{mod-C7_2j7VT.d.cts → mod-BojP2Bw3.d.cts} +1 -1
- package/dist/{mod-BlLwewYe.d.ts → mod-CavhAgLw.d.cts} +5 -255
- package/dist/{mod-VHYh1lTK.d.cts → mod-CtpF2BU5.d.ts} +5 -255
- package/dist/{mod-B8MI1mpi.d.ts → mod-DEZXwV6J.d.ts} +1 -1
- package/dist/{mod-DFL6IxYQ.d.cts → mod-Dw-nPxQh.d.cts} +1 -1
- package/dist/{mod-BhTaDR5H.d.ts → mod-Xj5P4s4d.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +7 -7
- package/dist/mod.d.ts +7 -7
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-DSJ7nFgy.mjs → owner-CEBn81LD.mjs} +3 -3
- package/dist/{portable-collection-r-mHg1PV.cjs → portable-collection-DqTUBKY7.cjs} +1 -1
- package/dist/{portable-collection-BuBV6xTo.js → portable-collection-ZkUNjtb7.js} +1 -1
- package/dist/{portable-collection-qskqXJrH.mjs → portable-collection-qFSYw4TG.mjs} +2 -2
- package/dist/{portable-key-woGH_1nn.mjs → portable-key-LlMkP-vz.mjs} +1 -1
- package/dist/{proof-8WiH_-Gq.mjs → proof-BHRf_jMG.mjs} +133 -16
- package/dist/{send-JKzZBgPU.mjs → send-DjG8DDU_.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 +19 -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 +2 -2
- 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 +2 -2
- package/dist/sig/mod.d.ts +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 +6 -6
- package/dist/sig/proof.test.mjs +76 -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.d.mts +2 -0
- package/dist/sig/verification.test.mjs +310 -0
- package/dist/{temporal-CT3fRaMH.mjs → temporal-BRFH_dte.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +315 -28
- package/dist/utils/docloader.test.mjs +2 -2
- 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/dist/verification-C3954hQh.mjs +5 -0
- package/dist/verification-Dpfcw8ml.mjs +105 -0
- package/package.json +7 -7
|
@@ -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 instrumentDocumentLoader, A as hasSignature, At as
|
|
5
|
+
import { $ as instrumentDocumentLoader, A as hasSignature, At as isPortableUri, C as InvalidContextReferenceError, Ct as getGatewayKeyBase, Dt as isCompatibleKeyId, E as compactJsonLd, Et as hasPortableActor, F as verifyCompactJsonLd, G as validateCryptoKey, M as isClearlyMalformedContextReference, N as isInvalidUrlTypeError, Nt as name, O as detachSignature, Ot as isPortableId, P as signJsonLd, Pt as version, Q as getRemoteHost, R as wrapContextLoaderForJsonLd, S as normalizeOutgoingActivityJsonLd, St as getCanonicalPortableId, Tt as getRawCanonicalPortableId, W as importJwk, X as getDurationMs, Z as getFederationMetrics, _ as verifyObject, at as recordCollectionTotalItems, b as verifyPortableObjectProofWithRoot, bt as verificationObservation, c as verifyRequestDetailed, ct as recordInboxActivity, d as InvalidPortableObjectIdError, dt as recordWebFingerHandle, et as isAbortError, f as classifyFep2277CoreType, ft as registerQueueDepthGauge, g as verifyMapLocalProof, h as signObject, i as selectRequestSignature, it as recordCollectionRequest, j as hasSignatureLike, jt as isSameObjectId, k as getNormalizationContextLoader, kt as isPortableKeyId, lt as recordOutboxActivity, m as hasProofLike, mt as formatAcceptSignature, n as listRequestSignatures, nt as recordCollectionDispatchDuration, o as validateMaxSignatures, pt as preloadedOnlyDocumentLoader, q as MAX_PORTABLE_KEY_TTL, r as parseRfc9421SignatureInput, rt as recordCollectionPageItems, s as verifyRequest, st as recordFanoutRecipients, t as doubleKnock, tt as recordCircuitBreakerStateChange, ut as recordOutboxEnqueue, v as verifyPortableObjectProof, vt as observeAttempt, w as assertSafeJsonLd, wt as getPortableDid, xt as getAuthenticationOrigin, y as verifyPortableObjectProofPolicy, yt as snapshotKey, z as exportJwk } from "./http-OMtKlbx1.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-ZkUNjtb7.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-J0v3UbUn.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";
|
|
@@ -100,6 +100,7 @@ var FederationBuilderImpl = class {
|
|
|
100
100
|
featuredTagsCallbacks;
|
|
101
101
|
inboxListeners;
|
|
102
102
|
outboxListeners;
|
|
103
|
+
inboxRequestFinishedHandler;
|
|
103
104
|
inboxErrorHandler;
|
|
104
105
|
outboxListenerErrorHandler;
|
|
105
106
|
outboxAuthorizePredicate;
|
|
@@ -161,6 +162,7 @@ var FederationBuilderImpl = class {
|
|
|
161
162
|
f.featuredTagsCallbacks = this.featuredTagsCallbacks == null ? void 0 : { ...this.featuredTagsCallbacks };
|
|
162
163
|
f.inboxListeners = this.inboxListeners?.clone();
|
|
163
164
|
f.outboxListeners = this.outboxListeners?.clone();
|
|
165
|
+
f.inboxRequestFinishedHandler = this.inboxRequestFinishedHandler;
|
|
164
166
|
f.inboxErrorHandler = this.inboxErrorHandler;
|
|
165
167
|
f.outboxListenerErrorHandler = this.outboxListenerErrorHandler;
|
|
166
168
|
f.outboxAuthorizePredicate = this.outboxAuthorizePredicate;
|
|
@@ -641,6 +643,10 @@ var FederationBuilderImpl = class {
|
|
|
641
643
|
this.inboxErrorHandler = handler;
|
|
642
644
|
return setters;
|
|
643
645
|
},
|
|
646
|
+
onRequestFinished: (handler) => {
|
|
647
|
+
this.inboxRequestFinishedHandler = handler;
|
|
648
|
+
return setters;
|
|
649
|
+
},
|
|
644
650
|
onUnverifiedActivity: (handler) => {
|
|
645
651
|
this.unverifiedActivityHandler = handler;
|
|
646
652
|
return setters;
|
|
@@ -1446,6 +1452,111 @@ async function buildCollectionSynchronizationHeader(collectionId, actorIds) {
|
|
|
1446
1452
|
return `collectionId="${collectionId}", url="${url}", digest="${encodeHex(await digest(actorIds))}"`;
|
|
1447
1453
|
}
|
|
1448
1454
|
//#endregion
|
|
1455
|
+
//#region src/federation/inbox-observation.ts
|
|
1456
|
+
/** Internal state owned by the ingress boundary, never serialized into queues. */
|
|
1457
|
+
var InboxObservation = class {
|
|
1458
|
+
inbox;
|
|
1459
|
+
payload = { status: "unavailable" };
|
|
1460
|
+
activity = null;
|
|
1461
|
+
authentication = { status: "notDetermined" };
|
|
1462
|
+
hasException = false;
|
|
1463
|
+
stage = "prepare";
|
|
1464
|
+
result = {
|
|
1465
|
+
disposition: "rejected",
|
|
1466
|
+
reason: "recipientNotFound"
|
|
1467
|
+
};
|
|
1468
|
+
verification = {
|
|
1469
|
+
attempts: [],
|
|
1470
|
+
subject: {
|
|
1471
|
+
id: null,
|
|
1472
|
+
pointer: ""
|
|
1473
|
+
},
|
|
1474
|
+
parsedObject: (object) => {
|
|
1475
|
+
if (object instanceof Activity) {
|
|
1476
|
+
this.activity = object;
|
|
1477
|
+
this.verification.subject.id = object.id == null ? null : new URL(object.id.href);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
constructor(inbox) {
|
|
1482
|
+
this.inbox = inbox;
|
|
1483
|
+
}
|
|
1484
|
+
/** Run an ingress operation and project telemetry; fetch owns completion. */
|
|
1485
|
+
async run(operation, span) {
|
|
1486
|
+
let response;
|
|
1487
|
+
let outcome;
|
|
1488
|
+
let threw = false;
|
|
1489
|
+
let originalError;
|
|
1490
|
+
try {
|
|
1491
|
+
response = await operation();
|
|
1492
|
+
outcome = {
|
|
1493
|
+
type: "response",
|
|
1494
|
+
status: response.status,
|
|
1495
|
+
...this.result
|
|
1496
|
+
};
|
|
1497
|
+
} catch (error) {
|
|
1498
|
+
threw = true;
|
|
1499
|
+
this.hasException = true;
|
|
1500
|
+
originalError = error;
|
|
1501
|
+
outcome = {
|
|
1502
|
+
type: "exception",
|
|
1503
|
+
stage: this.stage,
|
|
1504
|
+
error
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
if (span != null) this.project(span, outcome);
|
|
1508
|
+
if (threw) throw originalError;
|
|
1509
|
+
return response;
|
|
1510
|
+
}
|
|
1511
|
+
/** Complete standalone handler calls that have no enclosing fetch boundary. */
|
|
1512
|
+
async runAndFinish(getContext, handler, operation) {
|
|
1513
|
+
let response;
|
|
1514
|
+
try {
|
|
1515
|
+
response = await this.run(operation);
|
|
1516
|
+
} catch (error) {
|
|
1517
|
+
await this.finish(getContext(), handler, {
|
|
1518
|
+
type: "exception",
|
|
1519
|
+
stage: this.stage,
|
|
1520
|
+
error
|
|
1521
|
+
});
|
|
1522
|
+
throw error;
|
|
1523
|
+
}
|
|
1524
|
+
await this.finish(getContext(), handler, {
|
|
1525
|
+
type: "response",
|
|
1526
|
+
status: response.status,
|
|
1527
|
+
...this.result
|
|
1528
|
+
});
|
|
1529
|
+
return response;
|
|
1530
|
+
}
|
|
1531
|
+
project(span, outcome) {
|
|
1532
|
+
span.setAttribute("activitypub.authentication.status", this.authentication.status);
|
|
1533
|
+
if (this.authentication.status === "rejected") span.setAttribute("activitypub.verification.failure_reason", this.authentication.reason.type);
|
|
1534
|
+
span.setAttribute("activitypub.inbox.disposition", outcome?.type === "exception" || this.hasException ? "exception" : this.result.disposition);
|
|
1535
|
+
}
|
|
1536
|
+
async finish(context, handler, outcome) {
|
|
1537
|
+
if (handler == null) return;
|
|
1538
|
+
const report = {
|
|
1539
|
+
inbox: this.inbox,
|
|
1540
|
+
payload: this.payload,
|
|
1541
|
+
activity: this.activity,
|
|
1542
|
+
attempts: this.verification.attempts,
|
|
1543
|
+
authentication: this.authentication,
|
|
1544
|
+
outcome
|
|
1545
|
+
};
|
|
1546
|
+
try {
|
|
1547
|
+
await handler(context, report);
|
|
1548
|
+
} catch (error) {
|
|
1549
|
+
try {
|
|
1550
|
+
getLogger([
|
|
1551
|
+
"fedify",
|
|
1552
|
+
"federation",
|
|
1553
|
+
"inbox"
|
|
1554
|
+
]).error("An unexpected error occurred in inbox request finished handler:\n{error}", { error });
|
|
1555
|
+
} catch {}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
//#endregion
|
|
1449
1560
|
//#region src/sig/compound-proof.ts
|
|
1450
1561
|
const textEncoder = new TextEncoder();
|
|
1451
1562
|
/**
|
|
@@ -1934,7 +2045,23 @@ async function verifyDiscoveredProofDocuments(discovered, options) {
|
|
|
1934
2045
|
verified: false,
|
|
1935
2046
|
reason: { type: "missingContext" }
|
|
1936
2047
|
});
|
|
1937
|
-
const
|
|
2048
|
+
const inherited = options[verificationObservation];
|
|
2049
|
+
let subjectId = null;
|
|
2050
|
+
if (inherited != null && document.id != null) try {
|
|
2051
|
+
subjectId = parseIri(document.id);
|
|
2052
|
+
} catch {}
|
|
2053
|
+
const key = await observeAttempt({ [verificationObservation]: inherited == null ? void 0 : {
|
|
2054
|
+
...inherited,
|
|
2055
|
+
attempt: void 0,
|
|
2056
|
+
check: void 0,
|
|
2057
|
+
subject: {
|
|
2058
|
+
id: subjectId,
|
|
2059
|
+
pointer: document.path
|
|
2060
|
+
}
|
|
2061
|
+
} }, "objectIntegrity", (observation) => verifyMapLocalProof(document.securedDocument, {
|
|
2062
|
+
...options,
|
|
2063
|
+
[verificationObservation]: inherited == null ? void 0 : observation
|
|
2064
|
+
}), (key) => key != null);
|
|
1938
2065
|
return key == null ? Object.freeze({
|
|
1939
2066
|
...metadata,
|
|
1940
2067
|
verified: false,
|
|
@@ -4573,13 +4700,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
4573
4700
|
* @param parameters The parameters for handling the collection.
|
|
4574
4701
|
* @returns A promise that resolves to an HTTP response.
|
|
4575
4702
|
*/
|
|
4576
|
-
async function handleCollection(request, { name: name$
|
|
4577
|
-
const spanName = name$
|
|
4703
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
4704
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
4578
4705
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
4579
4706
|
const tracer = tracerProvider.getTracer(name, version);
|
|
4580
4707
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
4581
4708
|
const metricBase = {
|
|
4582
|
-
kind: getCollectionMetricKind(name$
|
|
4709
|
+
kind: getCollectionMetricKind(name$2),
|
|
4583
4710
|
page: cursor != null,
|
|
4584
4711
|
dispatcher: "built_in"
|
|
4585
4712
|
};
|
|
@@ -4625,7 +4752,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
4625
4752
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
4626
4753
|
return await onNotFound(request);
|
|
4627
4754
|
}
|
|
4628
|
-
const items = filterCollectionItems(page.items, name$
|
|
4755
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
4629
4756
|
itemCount = items.length;
|
|
4630
4757
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
4631
4758
|
return items;
|
|
@@ -4667,7 +4794,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
4667
4794
|
} else {
|
|
4668
4795
|
const uri = new URL(portable == null ? baseUri : pageBase);
|
|
4669
4796
|
uri.searchParams.set("cursor", cursor);
|
|
4670
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
4797
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
4671
4798
|
kind: SpanKind.SERVER,
|
|
4672
4799
|
attributes: {
|
|
4673
4800
|
"activitypub.collection.id": uri.href,
|
|
@@ -4683,7 +4810,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
4683
4810
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
4684
4811
|
return await onNotFound(request);
|
|
4685
4812
|
}
|
|
4686
|
-
const items = filterCollectionItems(page.items, name$
|
|
4813
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
4687
4814
|
itemCount = items.length;
|
|
4688
4815
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
4689
4816
|
return {
|
|
@@ -5164,6 +5291,16 @@ async function handleMediaUpload(request, { identifier, context: ctx, mediaUploa
|
|
|
5164
5291
|
* @returns A promise that resolves to an HTTP response.
|
|
5165
5292
|
*/
|
|
5166
5293
|
async function handleInbox(request, options) {
|
|
5294
|
+
if (options.observation == null) {
|
|
5295
|
+
const observation = new InboxObservation({
|
|
5296
|
+
kind: options.portableInbox != null ? "portable" : options.recipient == null ? "shared" : "personal",
|
|
5297
|
+
recipient: options.recipient
|
|
5298
|
+
});
|
|
5299
|
+
return await observation.runAndFinish(() => options.context, options.inboxRequestFinishedHandler, () => handleInbox(request, {
|
|
5300
|
+
...options,
|
|
5301
|
+
observation
|
|
5302
|
+
}));
|
|
5303
|
+
}
|
|
5167
5304
|
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("activitypub.inbox", {
|
|
5168
5305
|
kind: options.queue == null ? SpanKind.SERVER : SpanKind.PRODUCER,
|
|
5169
5306
|
attributes: { "activitypub.shared_inbox": options.recipient == null }
|
|
@@ -5172,12 +5309,14 @@ async function handleInbox(request, options) {
|
|
|
5172
5309
|
try {
|
|
5173
5310
|
return await handleInboxInternal(request, options, span);
|
|
5174
5311
|
} catch (e) {
|
|
5312
|
+
options.observation.hasException = true;
|
|
5175
5313
|
span.setStatus({
|
|
5176
5314
|
code: SpanStatusCode.ERROR,
|
|
5177
5315
|
message: String(e)
|
|
5178
5316
|
});
|
|
5179
5317
|
throw e;
|
|
5180
5318
|
} finally {
|
|
5319
|
+
options.observation.project(span);
|
|
5181
5320
|
span.end();
|
|
5182
5321
|
}
|
|
5183
5322
|
});
|
|
@@ -5192,6 +5331,8 @@ async function handleInbox(request, options) {
|
|
|
5192
5331
|
*/
|
|
5193
5332
|
async function handleInboxInternal(request, parameters, span) {
|
|
5194
5333
|
const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, publicKeyTtl, queue, actorDispatcher, inboxListeners, inboxErrorHandler, unverifiedActivityHandler, onNotFound, signatureTimeWindow, maxHttpSignatures, skipSignatureVerification, inboxChallengePolicy, meterProvider, tracerProvider, portableInbox } = parameters;
|
|
5334
|
+
const observation = parameters.observation;
|
|
5335
|
+
const signatureObservation = { [verificationObservation]: observation.verification };
|
|
5195
5336
|
const logger = getLogger([
|
|
5196
5337
|
"fedify",
|
|
5197
5338
|
"federation",
|
|
@@ -5216,6 +5357,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5216
5357
|
}
|
|
5217
5358
|
}
|
|
5218
5359
|
if (request.bodyUsed) {
|
|
5360
|
+
observation.result = {
|
|
5361
|
+
disposition: "failed",
|
|
5362
|
+
reason: "bodyUnavailable"
|
|
5363
|
+
};
|
|
5219
5364
|
logger.error("Request body has already been read.", { recipient });
|
|
5220
5365
|
span.setStatus({
|
|
5221
5366
|
code: SpanStatusCode.ERROR,
|
|
@@ -5226,6 +5371,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5226
5371
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
5227
5372
|
});
|
|
5228
5373
|
} else if (request.body?.locked) {
|
|
5374
|
+
observation.result = {
|
|
5375
|
+
disposition: "failed",
|
|
5376
|
+
reason: "bodyUnavailable"
|
|
5377
|
+
};
|
|
5229
5378
|
logger.error("Request body is locked.", { recipient });
|
|
5230
5379
|
span.setStatus({
|
|
5231
5380
|
code: SpanStatusCode.ERROR,
|
|
@@ -5236,11 +5385,20 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5236
5385
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
5237
5386
|
});
|
|
5238
5387
|
}
|
|
5388
|
+
observation.stage = "parse";
|
|
5389
|
+
observation.result = {
|
|
5390
|
+
disposition: "rejected",
|
|
5391
|
+
reason: "invalidJson"
|
|
5392
|
+
};
|
|
5239
5393
|
let json;
|
|
5240
5394
|
try {
|
|
5241
5395
|
json = JSON.parse(await readBoundedText(request.clone(), MAX_BODY_SIZE, request.url));
|
|
5242
5396
|
} catch (error) {
|
|
5243
5397
|
if (error instanceof BodyTooLargeError) {
|
|
5398
|
+
observation.result = {
|
|
5399
|
+
disposition: "rejected",
|
|
5400
|
+
reason: "bodyTooLarge"
|
|
5401
|
+
};
|
|
5244
5402
|
request.body?.cancel(error).catch(() => {});
|
|
5245
5403
|
span.setStatus({
|
|
5246
5404
|
code: SpanStatusCode.ERROR,
|
|
@@ -5270,6 +5428,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5270
5428
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
5271
5429
|
});
|
|
5272
5430
|
}
|
|
5431
|
+
observation.payload = {
|
|
5432
|
+
status: "parsed",
|
|
5433
|
+
value: structuredClone(json)
|
|
5434
|
+
};
|
|
5435
|
+
observation.result = {
|
|
5436
|
+
disposition: "rejected",
|
|
5437
|
+
reason: "invalidActivity"
|
|
5438
|
+
};
|
|
5439
|
+
observation.stage = "verify";
|
|
5273
5440
|
const keyCache = new KvKeyCache(kv, kvPrefixes.publicKey, {
|
|
5274
5441
|
documentLoader: ctx.documentLoader,
|
|
5275
5442
|
contextLoader: ctx.contextLoader,
|
|
@@ -5299,6 +5466,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5299
5466
|
code: SpanStatusCode.ERROR,
|
|
5300
5467
|
message: `Failed to parse activity:\n${error}`
|
|
5301
5468
|
});
|
|
5469
|
+
observation.result = {
|
|
5470
|
+
disposition: "rejected",
|
|
5471
|
+
reason: "invalidActivity"
|
|
5472
|
+
};
|
|
5302
5473
|
return new Response("Invalid activity.", {
|
|
5303
5474
|
status: 400,
|
|
5304
5475
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
@@ -5316,11 +5487,25 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5316
5487
|
recipient,
|
|
5317
5488
|
error
|
|
5318
5489
|
});
|
|
5490
|
+
observation.result = {
|
|
5491
|
+
disposition: "rejected",
|
|
5492
|
+
reason: "invalidJsonLd"
|
|
5493
|
+
};
|
|
5319
5494
|
return new Response("Invalid JSON-LD.", {
|
|
5320
5495
|
status: 400,
|
|
5321
5496
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
5322
5497
|
});
|
|
5323
5498
|
}
|
|
5499
|
+
observation.verification.attempts.push({
|
|
5500
|
+
mechanism: "linkedData",
|
|
5501
|
+
subject: {
|
|
5502
|
+
id: null,
|
|
5503
|
+
pointer: ""
|
|
5504
|
+
},
|
|
5505
|
+
checks: [],
|
|
5506
|
+
status: "error",
|
|
5507
|
+
error
|
|
5508
|
+
});
|
|
5324
5509
|
if (!canAttemptAlternateAuthAfterLdSignatureFailure) throw error;
|
|
5325
5510
|
if (!skipSignatureVerification) deferredLdSignatureError = error;
|
|
5326
5511
|
logger.debug("Failed to normalize JSON-LD for Linked Data Signatures; deferring to another authentication path only if it verifies:\n{error}", {
|
|
@@ -5332,6 +5517,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5332
5517
|
compactedJsonWithoutSig = detachSignature(compactedJson);
|
|
5333
5518
|
try {
|
|
5334
5519
|
ldSigVerified = await verifyCompactJsonLd(compactedJson, {
|
|
5520
|
+
...signatureObservation,
|
|
5335
5521
|
contextLoader: ctx.contextLoader,
|
|
5336
5522
|
documentLoader: ctx.documentLoader,
|
|
5337
5523
|
keyCache,
|
|
@@ -5345,6 +5531,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5345
5531
|
recipient,
|
|
5346
5532
|
error
|
|
5347
5533
|
});
|
|
5534
|
+
observation.result = {
|
|
5535
|
+
disposition: "rejected",
|
|
5536
|
+
reason: "invalidJsonLd"
|
|
5537
|
+
};
|
|
5348
5538
|
return new Response("Invalid JSON-LD.", {
|
|
5349
5539
|
status: 400,
|
|
5350
5540
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
@@ -5364,6 +5554,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5364
5554
|
recipient,
|
|
5365
5555
|
error: parseError
|
|
5366
5556
|
});
|
|
5557
|
+
observation.result = {
|
|
5558
|
+
disposition: "rejected",
|
|
5559
|
+
reason: "invalidJsonLd"
|
|
5560
|
+
};
|
|
5367
5561
|
return new Response("Invalid JSON-LD.", {
|
|
5368
5562
|
status: 400,
|
|
5369
5563
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
@@ -5384,7 +5578,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5384
5578
|
json
|
|
5385
5579
|
});
|
|
5386
5580
|
try {
|
|
5387
|
-
activity = await Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
5581
|
+
activity = observation.activity = await Activity.fromJsonLd(compactedJsonWithoutSig, {
|
|
5388
5582
|
...ctx,
|
|
5389
5583
|
contextLoader: getNormalizationContextLoader(ctx.contextLoader)
|
|
5390
5584
|
});
|
|
@@ -5396,6 +5590,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5396
5590
|
activityVerified = true;
|
|
5397
5591
|
if (!skipSignatureVerification && isPortableActivity(activity)) try {
|
|
5398
5592
|
proofVerified = await verifyObject(Activity, jsonWithoutSig, {
|
|
5593
|
+
...signatureObservation,
|
|
5399
5594
|
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
5400
5595
|
documentLoader: ctx.documentLoader,
|
|
5401
5596
|
keyCache,
|
|
@@ -5416,6 +5611,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5416
5611
|
});
|
|
5417
5612
|
try {
|
|
5418
5613
|
activity = await verifyObject(Activity, jsonWithoutSig, {
|
|
5614
|
+
...signatureObservation,
|
|
5419
5615
|
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
5420
5616
|
documentLoader: ctx.documentLoader,
|
|
5421
5617
|
keyCache,
|
|
@@ -5451,6 +5647,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5451
5647
|
code: SpanStatusCode.ERROR,
|
|
5452
5648
|
message: `Failed to parse activity:\n${error}`
|
|
5453
5649
|
});
|
|
5650
|
+
observation.result = {
|
|
5651
|
+
disposition: "rejected",
|
|
5652
|
+
reason: "invalidActivity"
|
|
5653
|
+
};
|
|
5454
5654
|
return new Response("Invalid activity.", {
|
|
5455
5655
|
status: 400,
|
|
5456
5656
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
@@ -5474,6 +5674,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5474
5674
|
if (activity == null) {
|
|
5475
5675
|
if (!skipSignatureVerification) {
|
|
5476
5676
|
const verification = await verifyRequestDetailed(request, {
|
|
5677
|
+
...signatureObservation,
|
|
5477
5678
|
contextLoader: ctx.contextLoader,
|
|
5478
5679
|
documentLoader: ctx.documentLoader,
|
|
5479
5680
|
timeWindow: signatureTimeWindow,
|
|
@@ -5484,6 +5685,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5484
5685
|
});
|
|
5485
5686
|
if (verification.verified === false) {
|
|
5486
5687
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
5688
|
+
observation.authentication = {
|
|
5689
|
+
status: "rejected",
|
|
5690
|
+
reason: { type: "verificationFailed" }
|
|
5691
|
+
};
|
|
5692
|
+
observation.result = {
|
|
5693
|
+
disposition: "rejected",
|
|
5694
|
+
reason: "authentication"
|
|
5695
|
+
};
|
|
5487
5696
|
const reason = verification.reason;
|
|
5488
5697
|
const remoteHost = "keyId" in reason && reason.keyId != null ? getRemoteHost(reason.keyId) : void 0;
|
|
5489
5698
|
getFederationMetrics(parameters.meterProvider).recordSignatureVerificationFailure(reason.type, remoteHost);
|
|
@@ -5498,7 +5707,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5498
5707
|
});
|
|
5499
5708
|
if (unverifiedActivityHandler == null) return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
5500
5709
|
try {
|
|
5501
|
-
activity = await Activity.fromJsonLd(jsonWithoutSig, ctx);
|
|
5710
|
+
activity = observation.activity = await Activity.fromJsonLd(jsonWithoutSig, ctx);
|
|
5502
5711
|
} catch (error) {
|
|
5503
5712
|
logger.error("Failed to parse activity:\n{error}", {
|
|
5504
5713
|
recipient,
|
|
@@ -5514,6 +5723,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5514
5723
|
recipient
|
|
5515
5724
|
});
|
|
5516
5725
|
}
|
|
5726
|
+
observation.result = {
|
|
5727
|
+
disposition: "rejected",
|
|
5728
|
+
reason: "invalidActivity"
|
|
5729
|
+
};
|
|
5517
5730
|
return new Response("Invalid activity.", {
|
|
5518
5731
|
status: 400,
|
|
5519
5732
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
@@ -5536,6 +5749,11 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5536
5749
|
try {
|
|
5537
5750
|
response = await unverifiedActivityHandler(ctx, activity, reason);
|
|
5538
5751
|
} catch (error) {
|
|
5752
|
+
observation.result = {
|
|
5753
|
+
disposition: "failed",
|
|
5754
|
+
reason: "listenerError",
|
|
5755
|
+
error
|
|
5756
|
+
};
|
|
5539
5757
|
logger.error("An unexpected error occurred in unverified activity handler:\n{error}", {
|
|
5540
5758
|
error,
|
|
5541
5759
|
activity: json,
|
|
@@ -5552,7 +5770,10 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5552
5770
|
}
|
|
5553
5771
|
return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
5554
5772
|
}
|
|
5555
|
-
if (response instanceof Response)
|
|
5773
|
+
if (response instanceof Response) {
|
|
5774
|
+
observation.result = { disposition: "customResponse" };
|
|
5775
|
+
return response;
|
|
5776
|
+
}
|
|
5556
5777
|
return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
5557
5778
|
} else {
|
|
5558
5779
|
if (inboxChallengePolicy?.enabled && inboxChallengePolicy.requestNonce) pendingNonceLabel = verification.signatureLabel;
|
|
@@ -5562,7 +5783,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5562
5783
|
httpSigKey = verification.key;
|
|
5563
5784
|
}
|
|
5564
5785
|
try {
|
|
5565
|
-
activity = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
5786
|
+
activity = observation.activity = await Activity.fromJsonLd(jsonWithoutSig, {
|
|
5566
5787
|
...ctx,
|
|
5567
5788
|
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader)
|
|
5568
5789
|
});
|
|
@@ -5571,6 +5792,12 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5571
5792
|
return await respondInvalidActivity(error);
|
|
5572
5793
|
}
|
|
5573
5794
|
}
|
|
5795
|
+
observation.activity = activity;
|
|
5796
|
+
observation.stage = "policy";
|
|
5797
|
+
observation.result = {
|
|
5798
|
+
disposition: "rejected",
|
|
5799
|
+
reason: "authentication"
|
|
5800
|
+
};
|
|
5574
5801
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
5575
5802
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
5576
5803
|
span.addEvent("activitypub.activity.received", {
|
|
@@ -5582,6 +5809,13 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5582
5809
|
});
|
|
5583
5810
|
if (!skipSignatureVerification && !proofVerified && (isPortableActivity(activity) || isPortableActorKey(httpSigKey))) {
|
|
5584
5811
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
5812
|
+
observation.authentication = {
|
|
5813
|
+
status: "rejected",
|
|
5814
|
+
reason: {
|
|
5815
|
+
type: "proofPolicy",
|
|
5816
|
+
policy: "portableActor"
|
|
5817
|
+
}
|
|
5818
|
+
};
|
|
5585
5819
|
logger.error("The activity {activityId} of the portable actor {actorId} is not authenticated by a valid Object Integrity Proof.", {
|
|
5586
5820
|
activity: json,
|
|
5587
5821
|
recipient,
|
|
@@ -5599,20 +5833,36 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5599
5833
|
});
|
|
5600
5834
|
}
|
|
5601
5835
|
if (!skipSignatureVerification && activity.id != null && isPortableId(activity.id)) {
|
|
5602
|
-
const rejection = await
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5836
|
+
const rejection = await observeAttempt(signatureObservation, "objectIntegrity", async (verification) => {
|
|
5837
|
+
const rejection = await verifyPortableActivityId(activity.id, jsonWithoutSig, {
|
|
5838
|
+
[verificationObservation]: verification,
|
|
5839
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
5840
|
+
documentLoader: ctx.documentLoader,
|
|
5841
|
+
keyCache,
|
|
5842
|
+
meterProvider,
|
|
5843
|
+
tracerProvider
|
|
5844
|
+
});
|
|
5845
|
+
if (rejection != null) verification.attempt.reason = {
|
|
5846
|
+
type: "proofPolicy",
|
|
5847
|
+
reason: rejection
|
|
5848
|
+
};
|
|
5849
|
+
return rejection;
|
|
5850
|
+
}, (value) => value == null);
|
|
5609
5851
|
if (rejection != null) {
|
|
5610
5852
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
5853
|
+
observation.authentication = {
|
|
5854
|
+
status: "rejected",
|
|
5855
|
+
reason: {
|
|
5856
|
+
type: "proofPolicy",
|
|
5857
|
+
policy: "portableActivity",
|
|
5858
|
+
detail: rejection
|
|
5859
|
+
}
|
|
5860
|
+
};
|
|
5611
5861
|
logger.error("The portable activity {activityId} is not authenticated by an Object Integrity Proof of its own DID: {reason}", {
|
|
5612
5862
|
activity: json,
|
|
5613
5863
|
recipient,
|
|
5614
5864
|
activityId: activity.id.href,
|
|
5615
|
-
reason: rejection
|
|
5865
|
+
reason: rejection.type
|
|
5616
5866
|
});
|
|
5617
5867
|
span.setStatus({
|
|
5618
5868
|
code: SpanStatusCode.ERROR,
|
|
@@ -5626,6 +5876,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5626
5876
|
}
|
|
5627
5877
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
5628
5878
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
5879
|
+
observation.authentication = {
|
|
5880
|
+
status: "rejected",
|
|
5881
|
+
reason: {
|
|
5882
|
+
type: "actorKeyMismatch",
|
|
5883
|
+
key: snapshotKey(httpSigKey),
|
|
5884
|
+
actorIds: activity.actorIds.map((id) => new URL(id.href))
|
|
5885
|
+
}
|
|
5886
|
+
};
|
|
5629
5887
|
getFederationMetrics(parameters.meterProvider).recordSignatureVerificationFailure("actorKeyMismatch", httpSigKey.id == null ? void 0 : getRemoteHost(httpSigKey.id));
|
|
5630
5888
|
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
5631
5889
|
activity: json,
|
|
@@ -5645,13 +5903,35 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5645
5903
|
if (!skipSignatureVerification) {
|
|
5646
5904
|
const compoundJson = Array.isArray(json) ? json : jsonWithoutSig;
|
|
5647
5905
|
if (inspectCompoundPortableObjectApplicability(compoundJson, INBOX_COMPOUND_PROOF_LIMITS) !== "absent") {
|
|
5648
|
-
const compoundProof = await
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5906
|
+
const compoundProof = await observeAttempt(signatureObservation, "objectIntegrity", async (verification) => {
|
|
5907
|
+
const result = await verifyCompoundPortableObjectProofs(compoundJson, INBOX_COMPOUND_PROOF_LIMITS, {
|
|
5908
|
+
[verificationObservation]: verification,
|
|
5909
|
+
documentLoader: ctx.documentLoader,
|
|
5910
|
+
keyCache,
|
|
5911
|
+
meterProvider,
|
|
5912
|
+
tracerProvider
|
|
5913
|
+
});
|
|
5914
|
+
if (result.status === "unsupported") verification.attempt.reason = {
|
|
5915
|
+
type: "proofPolicy",
|
|
5916
|
+
reason: result.reason
|
|
5917
|
+
};
|
|
5918
|
+
else if (!result.verified) {
|
|
5919
|
+
const failed = result.portableObjects.find((object) => !object.verified);
|
|
5920
|
+
verification.attempt.reason = {
|
|
5921
|
+
type: "proofPolicy",
|
|
5922
|
+
reason: failed?.verified === false ? failed.reason : { type: "invalidProof" }
|
|
5923
|
+
};
|
|
5924
|
+
}
|
|
5925
|
+
return result;
|
|
5926
|
+
}, (result) => result.status === "ok" && result.verified);
|
|
5654
5927
|
if (compoundProof.status !== "ok" || !compoundProof.verified) {
|
|
5928
|
+
observation.authentication = {
|
|
5929
|
+
status: "rejected",
|
|
5930
|
+
reason: {
|
|
5931
|
+
type: "proofPolicy",
|
|
5932
|
+
policy: "compound"
|
|
5933
|
+
}
|
|
5934
|
+
};
|
|
5655
5935
|
logger.error("Failed to verify compound portable Object Integrity Proofs.", {
|
|
5656
5936
|
recipient,
|
|
5657
5937
|
activity: json,
|
|
@@ -5670,11 +5950,20 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5670
5950
|
}
|
|
5671
5951
|
if (pendingNonceLabel != null) {
|
|
5672
5952
|
if (!await verifySignatureNonce(request, kv, kvPrefixes.acceptSignatureNonce, pendingNonceLabel)) {
|
|
5953
|
+
observation.authentication = {
|
|
5954
|
+
status: "rejected",
|
|
5955
|
+
reason: { type: "invalidNonce" }
|
|
5956
|
+
};
|
|
5673
5957
|
getFederationMetrics(parameters.meterProvider).recordSignatureVerificationFailure("invalidNonce", httpSigKey?.id == null ? void 0 : getRemoteHost(httpSigKey.id));
|
|
5674
5958
|
logger.error("Signature nonce verification failed (missing, expired, or replayed).", { recipient });
|
|
5675
5959
|
return await getFailedSignatureResponse(inboxChallengePolicy, kv, kvPrefixes);
|
|
5676
5960
|
}
|
|
5677
5961
|
}
|
|
5962
|
+
observation.authentication = skipSignatureVerification ? { status: "skipped" } : {
|
|
5963
|
+
status: "verified",
|
|
5964
|
+
attempts: observation.verification.attempts.filter((attempt) => attempt.status === "verified")
|
|
5965
|
+
};
|
|
5966
|
+
observation.stage = "dispatch";
|
|
5678
5967
|
const routeResult = await routeActivity({
|
|
5679
5968
|
context: ctx,
|
|
5680
5969
|
json,
|
|
@@ -5686,7 +5975,14 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5686
5975
|
inboxListeners,
|
|
5687
5976
|
inboxContextFactory,
|
|
5688
5977
|
listenerInboxContextFactory: ldSigVerified ? inboxContextFactory[rawInboxContextFactorySymbol] : void 0,
|
|
5689
|
-
inboxErrorHandler,
|
|
5978
|
+
inboxErrorHandler: async (context, error) => {
|
|
5979
|
+
observation.result = {
|
|
5980
|
+
disposition: "failed",
|
|
5981
|
+
reason: "listenerError",
|
|
5982
|
+
error
|
|
5983
|
+
};
|
|
5984
|
+
await inboxErrorHandler?.(context, error);
|
|
5985
|
+
},
|
|
5690
5986
|
kv,
|
|
5691
5987
|
kvPrefixes,
|
|
5692
5988
|
queue,
|
|
@@ -5722,30 +6018,44 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
5722
6018
|
error
|
|
5723
6019
|
});
|
|
5724
6020
|
}
|
|
5725
|
-
if (routeResult === "alreadyProcessed")
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
})
|
|
5741
|
-
|
|
6021
|
+
if (routeResult === "alreadyProcessed") {
|
|
6022
|
+
observation.result = { disposition: "duplicate" };
|
|
6023
|
+
return new Response(`Activity <${activity.id}> has already been processed.`, {
|
|
6024
|
+
status: 202,
|
|
6025
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6026
|
+
});
|
|
6027
|
+
} else if (routeResult === "missingActor") {
|
|
6028
|
+
observation.result = {
|
|
6029
|
+
disposition: "rejected",
|
|
6030
|
+
reason: "missingActor"
|
|
6031
|
+
};
|
|
6032
|
+
return new Response("Missing actor.", {
|
|
6033
|
+
status: 400,
|
|
6034
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6035
|
+
});
|
|
6036
|
+
} else if (routeResult === "enqueued") {
|
|
6037
|
+
observation.result = { disposition: "enqueued" };
|
|
6038
|
+
return new Response("Activity is enqueued.", {
|
|
6039
|
+
status: 202,
|
|
6040
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6041
|
+
});
|
|
6042
|
+
} else if (routeResult === "unsupportedActivity") {
|
|
6043
|
+
observation.result = { disposition: "unhandled" };
|
|
6044
|
+
return new Response("", {
|
|
6045
|
+
status: 202,
|
|
6046
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6047
|
+
});
|
|
6048
|
+
} else if (routeResult === "error") return new Response("Internal server error.", {
|
|
5742
6049
|
status: 500,
|
|
5743
6050
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
5744
6051
|
});
|
|
5745
|
-
else
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
6052
|
+
else {
|
|
6053
|
+
observation.result = { disposition: "processed" };
|
|
6054
|
+
return new Response("", {
|
|
6055
|
+
status: 202,
|
|
6056
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
6057
|
+
});
|
|
6058
|
+
}
|
|
5749
6059
|
}
|
|
5750
6060
|
const PORTABLE_INBOX_FORWARDABLE_RESULTS = /* @__PURE__ */ new Set([
|
|
5751
6061
|
"success",
|
|
@@ -5874,8 +6184,8 @@ var CustomCollectionHandler = class {
|
|
|
5874
6184
|
* @param CollectionPage The CollectionPage constructor.
|
|
5875
6185
|
* @param filterPredicate Optional filter predicate for items.
|
|
5876
6186
|
*/
|
|
5877
|
-
constructor(name$
|
|
5878
|
-
this.name = name$
|
|
6187
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
|
|
6188
|
+
this.name = name$1;
|
|
5879
6189
|
this.values = values;
|
|
5880
6190
|
this.context = context;
|
|
5881
6191
|
this.callbacks = callbacks;
|
|
@@ -6411,19 +6721,19 @@ function isPortableActivity(activity) {
|
|
|
6411
6721
|
*/
|
|
6412
6722
|
async function verifyPortableActivityId(activityId, jsonLd, options) {
|
|
6413
6723
|
const expectedId = getCanonicalPortableId(activityId);
|
|
6414
|
-
if (expectedId == null) return
|
|
6724
|
+
if (expectedId == null) return { type: "invalidObjectId" };
|
|
6415
6725
|
let verification;
|
|
6416
6726
|
try {
|
|
6417
6727
|
verification = await verifyPortableObjectProofWithRoot(jsonLd, options);
|
|
6418
6728
|
} catch (error) {
|
|
6419
|
-
if (error instanceof InvalidPortableObjectIdError) return
|
|
6729
|
+
if (error instanceof InvalidPortableObjectIdError) return { type: "invalidObjectId" };
|
|
6420
6730
|
if (!isPermanentActivityParseError(error)) throw error;
|
|
6421
|
-
return "
|
|
6731
|
+
return { type: "invalidDocument" };
|
|
6422
6732
|
}
|
|
6423
6733
|
const { result, root } = verification;
|
|
6424
|
-
if (!result.verified) return result.reason
|
|
6734
|
+
if (!result.verified) return result.reason;
|
|
6425
6735
|
const rootId = root?.["@id"];
|
|
6426
|
-
if (typeof rootId !== "string" || getCanonicalPortableId(parseIri(rootId)) !== expectedId) return
|
|
6736
|
+
if (typeof rootId !== "string" || getCanonicalPortableId(parseIri(rootId)) !== expectedId) return { type: "subjectMismatch" };
|
|
6427
6737
|
return null;
|
|
6428
6738
|
}
|
|
6429
6739
|
//#endregion
|
|
@@ -9312,7 +9622,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9312
9622
|
return await withContext({
|
|
9313
9623
|
traceId: spanCtx.traceId,
|
|
9314
9624
|
spanId: spanCtx.spanId
|
|
9315
|
-
}, async () => {
|
|
9625
|
+
}, () => this.#observeInboxFetch(metricState, async () => {
|
|
9316
9626
|
const logger = getLogger([
|
|
9317
9627
|
"fedify",
|
|
9318
9628
|
"federation",
|
|
@@ -9327,8 +9637,14 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9327
9637
|
tracer,
|
|
9328
9638
|
metricState
|
|
9329
9639
|
});
|
|
9640
|
+
if (metricState.inboxCompletion != null) metricState.inboxCompletion.observation.stage = "respond";
|
|
9330
9641
|
if (metricState.endpoint !== "hashlink_media" && acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
|
|
9331
9642
|
} catch (error) {
|
|
9643
|
+
metricState.inboxCompletion?.observation.project(span, {
|
|
9644
|
+
type: "exception",
|
|
9645
|
+
stage: metricState.inboxCompletion.observation.stage,
|
|
9646
|
+
error
|
|
9647
|
+
});
|
|
9332
9648
|
this.metrics.recordHttpServerRequest(request.method, metricState.endpoint ?? "error", getDurationMs(metricStart), { routeTemplate: metricState.routeTemplate });
|
|
9333
9649
|
span.setStatus({
|
|
9334
9650
|
code: SpanStatusCode.ERROR,
|
|
@@ -9367,7 +9683,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9367
9683
|
else if (response.status >= 400) logger.warn(logTpl, values);
|
|
9368
9684
|
else logger.info(logTpl, values);
|
|
9369
9685
|
return response;
|
|
9370
|
-
});
|
|
9686
|
+
}));
|
|
9371
9687
|
});
|
|
9372
9688
|
});
|
|
9373
9689
|
}
|
|
@@ -9409,8 +9725,17 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9409
9725
|
metricState.routeTemplate = route.template;
|
|
9410
9726
|
metricState.endpoint = getEndpointCategory(route.name);
|
|
9411
9727
|
span.updateName(`${request.method} ${route.template}`);
|
|
9412
|
-
let context = this.#createContext(request, contextData);
|
|
9413
9728
|
const routeName = route.name.replace(/:.*$/, "");
|
|
9729
|
+
let context;
|
|
9730
|
+
try {
|
|
9731
|
+
context = this.#createContext(request, contextData);
|
|
9732
|
+
} catch (error) {
|
|
9733
|
+
if (request.method !== "POST" || routeName !== "inbox" && routeName !== "sharedInbox") throw error;
|
|
9734
|
+
return await this.#reportInboxPreparationError(request, contextData, {
|
|
9735
|
+
kind: routeName === "inbox" ? "personal" : "shared",
|
|
9736
|
+
recipient: route.values.identifier ?? null
|
|
9737
|
+
}, error, span, metricState);
|
|
9738
|
+
}
|
|
9414
9739
|
switch (routeName) {
|
|
9415
9740
|
case "webfinger": return await handleWebFinger(request, {
|
|
9416
9741
|
context,
|
|
@@ -9469,6 +9794,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9469
9794
|
});
|
|
9470
9795
|
return response;
|
|
9471
9796
|
}
|
|
9797
|
+
if (request.method === "POST" && (routeName === "inbox" || routeName === "sharedInbox")) {
|
|
9798
|
+
const recipient = route.values.identifier ?? null;
|
|
9799
|
+
const observation = new InboxObservation({
|
|
9800
|
+
kind: routeName === "inbox" ? "personal" : "shared",
|
|
9801
|
+
recipient
|
|
9802
|
+
});
|
|
9803
|
+
this.#setInboxCompletion(metricState, observation, () => context);
|
|
9804
|
+
return await observation.run(async () => {
|
|
9805
|
+
if (routeName === "inbox") context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: recipient }) });
|
|
9806
|
+
else if (this.sharedInboxKeyDispatcher != null) {
|
|
9807
|
+
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
9808
|
+
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
9809
|
+
}
|
|
9810
|
+
return await this.#handleInbox(request, {
|
|
9811
|
+
recipient,
|
|
9812
|
+
context,
|
|
9813
|
+
contextData,
|
|
9814
|
+
onNotFound,
|
|
9815
|
+
observation
|
|
9816
|
+
});
|
|
9817
|
+
}, span);
|
|
9818
|
+
}
|
|
9472
9819
|
switch (routeName) {
|
|
9473
9820
|
case "actor":
|
|
9474
9821
|
case "actorAlias": {
|
|
@@ -9544,9 +9891,9 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9544
9891
|
onUnauthorized,
|
|
9545
9892
|
onNotFound
|
|
9546
9893
|
});
|
|
9547
|
-
|
|
9894
|
+
throw new Error("Unreachable inbox delivery.");
|
|
9548
9895
|
case "sharedInbox":
|
|
9549
|
-
if (
|
|
9896
|
+
if (this.sharedInboxKeyDispatcher != null) {
|
|
9550
9897
|
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
9551
9898
|
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
9552
9899
|
}
|
|
@@ -9839,7 +10186,49 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9839
10186
|
}
|
|
9840
10187
|
return await onNotFound(request);
|
|
9841
10188
|
}
|
|
9842
|
-
|
|
10189
|
+
#setInboxCompletion(metricState, observation, getContext) {
|
|
10190
|
+
const handler = this.inboxRequestFinishedHandler;
|
|
10191
|
+
metricState.inboxCompletion = {
|
|
10192
|
+
observation,
|
|
10193
|
+
finish: (outcome) => observation.finish(getContext(), handler, outcome)
|
|
10194
|
+
};
|
|
10195
|
+
}
|
|
10196
|
+
async #observeInboxFetch(metricState, operation) {
|
|
10197
|
+
let response;
|
|
10198
|
+
try {
|
|
10199
|
+
response = await operation();
|
|
10200
|
+
} catch (error) {
|
|
10201
|
+
const completion = metricState.inboxCompletion;
|
|
10202
|
+
if (completion != null) await completion.finish({
|
|
10203
|
+
type: "exception",
|
|
10204
|
+
stage: completion.observation.stage,
|
|
10205
|
+
error
|
|
10206
|
+
});
|
|
10207
|
+
throw error;
|
|
10208
|
+
}
|
|
10209
|
+
const completion = metricState.inboxCompletion;
|
|
10210
|
+
if (completion != null) await completion.finish({
|
|
10211
|
+
type: "response",
|
|
10212
|
+
status: response.status,
|
|
10213
|
+
...completion.observation.result
|
|
10214
|
+
});
|
|
10215
|
+
return response;
|
|
10216
|
+
}
|
|
10217
|
+
async #reportInboxPreparationError(request, contextData, inbox, error, span, metricState) {
|
|
10218
|
+
const unavailableLoader = () => Promise.reject(error);
|
|
10219
|
+
const context = new RequestContextImpl({
|
|
10220
|
+
url: new URL(request.url),
|
|
10221
|
+
request,
|
|
10222
|
+
federation: this,
|
|
10223
|
+
data: contextData,
|
|
10224
|
+
documentLoader: unavailableLoader,
|
|
10225
|
+
contextLoader: unavailableLoader
|
|
10226
|
+
});
|
|
10227
|
+
const observation = new InboxObservation(inbox);
|
|
10228
|
+
this.#setInboxCompletion(metricState, observation, () => context);
|
|
10229
|
+
return await observation.run(() => Promise.reject(error), span);
|
|
10230
|
+
}
|
|
10231
|
+
async #handleInbox(request, { recipient, context, contextData, onNotFound, portableInbox, observation }) {
|
|
9843
10232
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
9844
10233
|
const inboxContextFactory = context.toInboxContext.bind(context);
|
|
9845
10234
|
inboxContextFactory[rawInboxContextFactorySymbol] = context.toInboxContext.bind(context);
|
|
@@ -9863,7 +10252,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9863
10252
|
meterProvider: this.meterProvider,
|
|
9864
10253
|
tracerProvider: this.tracerProvider,
|
|
9865
10254
|
idempotencyStrategy: this.idempotencyStrategy,
|
|
9866
|
-
portableInbox
|
|
10255
|
+
portableInbox,
|
|
10256
|
+
observation
|
|
9867
10257
|
});
|
|
9868
10258
|
}
|
|
9869
10259
|
async #fetchPortableInbox(request, portable, { onNotFound, contextData, span, metricState }) {
|
|
@@ -9892,63 +10282,79 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
9892
10282
|
metricState.endpoint = "inbox";
|
|
9893
10283
|
span.updateName(`${request.method} ${metricState.routeTemplate}`);
|
|
9894
10284
|
const identifier = route.values.identifier;
|
|
9895
|
-
let context
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
10285
|
+
let context;
|
|
10286
|
+
try {
|
|
10287
|
+
context = this.#createContext(request, contextData);
|
|
10288
|
+
} catch (error) {
|
|
10289
|
+
return await this.#reportInboxPreparationError(request, contextData, {
|
|
10290
|
+
kind: "portable",
|
|
10291
|
+
recipient: identifier
|
|
10292
|
+
}, error, span, metricState);
|
|
10293
|
+
}
|
|
10294
|
+
const observation = new InboxObservation({
|
|
10295
|
+
kind: "portable",
|
|
10296
|
+
recipient: identifier
|
|
10297
|
+
});
|
|
10298
|
+
this.#setInboxCompletion(metricState, observation, () => context);
|
|
10299
|
+
return await observation.run(async () => {
|
|
10300
|
+
const actor = this.actorCallbacks?.dispatcher == null ? null : await this.actorCallbacks.dispatcher(context, identifier);
|
|
10301
|
+
const localOrigin = context.canonicalOrigin;
|
|
10302
|
+
const resolution = resolvePortableInboxRecipient(actor == null || actor instanceof Tombstone ? null : actor, {
|
|
10303
|
+
authority: portable.portableRequest.authority,
|
|
10304
|
+
canonicalInboxId: portable.canonicalId,
|
|
10305
|
+
localOrigin
|
|
10306
|
+
});
|
|
10307
|
+
if (resolution.status === "rejected") {
|
|
10308
|
+
logger.debug("Not accepting a delivery to the portable inbox {inbox} on behalf of the actor {identifier}: {reason}.", {
|
|
10309
|
+
inbox: portable.canonicalId,
|
|
10310
|
+
identifier,
|
|
10311
|
+
reason: resolution.reason
|
|
10312
|
+
});
|
|
10313
|
+
return await onNotFound(request);
|
|
10314
|
+
}
|
|
10315
|
+
const { recipient } = resolution;
|
|
10316
|
+
if (this.actorCallbacks?.keyPairsDispatcher != null) context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier }) });
|
|
10317
|
+
const excludedOrigins = [localOrigin, new URL(request.url).origin];
|
|
10318
|
+
return await this.#handleInbox(request, {
|
|
10319
|
+
recipient: identifier,
|
|
10320
|
+
observation,
|
|
10321
|
+
context,
|
|
10322
|
+
contextData,
|
|
10323
|
+
onNotFound,
|
|
10324
|
+
portableInbox: {
|
|
10325
|
+
recipient,
|
|
10326
|
+
forward: async (activity, activityId, activityType, signatures) => {
|
|
10327
|
+
if (this.portableInboxForwarding.maxTargets < 1) return;
|
|
10328
|
+
if (this.kv.cas == null) {
|
|
10329
|
+
if (!this.#portableInboxForwardingWarned) {
|
|
10330
|
+
this.#portableInboxForwardingWarned = true;
|
|
10331
|
+
logger.warn("Activities delivered to FEP-ef61 portable inboxes are not forwarded to the other gateways, as the key–value store does not support compare-and-swap (KvStore.cas()), which is needed to forward each activity at most once.");
|
|
10332
|
+
}
|
|
10333
|
+
return;
|
|
9927
10334
|
}
|
|
9928
|
-
|
|
10335
|
+
await forwardPortableInboxActivity({
|
|
10336
|
+
recipient,
|
|
10337
|
+
activity,
|
|
10338
|
+
activityId,
|
|
10339
|
+
activityType,
|
|
10340
|
+
excludedOrigins,
|
|
10341
|
+
baseUrl: context.origin,
|
|
10342
|
+
kv: this.kv,
|
|
10343
|
+
kvPrefix: this.kvPrefixes.portableInboxForwarding,
|
|
10344
|
+
outboxQueue: this.outboxQueue,
|
|
10345
|
+
startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
|
|
10346
|
+
allowPrivateAddress: this.allowPrivateAddress,
|
|
10347
|
+
getKeys: () => this.#getPortableGatewayKeyPairs(context, identifier, recipient),
|
|
10348
|
+
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, this.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
|
|
10349
|
+
signatures,
|
|
10350
|
+
options: this.portableInboxForwarding,
|
|
10351
|
+
meterProvider: this.meterProvider,
|
|
10352
|
+
tracerProvider: this.tracerProvider
|
|
10353
|
+
});
|
|
9929
10354
|
}
|
|
9930
|
-
await forwardPortableInboxActivity({
|
|
9931
|
-
recipient,
|
|
9932
|
-
activity,
|
|
9933
|
-
activityId,
|
|
9934
|
-
activityType,
|
|
9935
|
-
excludedOrigins,
|
|
9936
|
-
baseUrl: context.origin,
|
|
9937
|
-
kv: this.kv,
|
|
9938
|
-
kvPrefix: this.kvPrefixes.portableInboxForwarding,
|
|
9939
|
-
outboxQueue: this.outboxQueue,
|
|
9940
|
-
startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
|
|
9941
|
-
allowPrivateAddress: this.allowPrivateAddress,
|
|
9942
|
-
getKeys: () => this.#getPortableGatewayKeyPairs(context, identifier, recipient),
|
|
9943
|
-
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, this.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
|
|
9944
|
-
signatures,
|
|
9945
|
-
options: this.portableInboxForwarding,
|
|
9946
|
-
meterProvider: this.meterProvider,
|
|
9947
|
-
tracerProvider: this.tracerProvider
|
|
9948
|
-
});
|
|
9949
10355
|
}
|
|
9950
|
-
}
|
|
9951
|
-
});
|
|
10356
|
+
});
|
|
10357
|
+
}, span);
|
|
9952
10358
|
}
|
|
9953
10359
|
/**
|
|
9954
10360
|
* Gets this server's gateway key pairs for the portable actor that owns
|