@fedify/fedify 2.3.9-dev.2048 → 2.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{builder-BfY2wZ4V.mjs → builder-Bal9bfuM.mjs} +10 -2
- package/dist/{client-DYDoDpMa.mjs → client-Ccbsek6u.mjs} +7 -3
- 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/{context-CAKnQy1x.d.ts → context-BWbdE_MZ.d.ts} +1 -1
- package/dist/{context-BepjCFHN.mjs → context-CxbCIptr.mjs} +2 -1
- package/dist/{context-CSIggG9_.d.cts → context-MOrCC7yl.d.cts} +1 -1
- package/dist/{deno-ayal9buz.mjs → deno-DUgFsCmM.mjs} +1 -1
- package/dist/docloader-w72ipM49.mjs +79 -0
- package/dist/federation/builder.test.mjs +38 -2
- package/dist/federation/circuit-breaker.test.mjs +1 -1
- package/dist/federation/collection.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +7 -7
- package/dist/federation/idempotency.test.mjs +3 -3
- package/dist/federation/kv.test.mjs +1 -1
- package/dist/federation/metrics.test.mjs +2 -2
- package/dist/federation/middleware.test.mjs +302 -8
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +3 -3
- package/dist/federation/mod.d.ts +3 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +98 -43
- package/dist/federation/negotiation.test.mjs +1 -1
- package/dist/federation/router.test.mjs +1 -1
- package/dist/federation/send.test.mjs +85 -4
- package/dist/federation/temporal.test.mjs +2 -2
- package/dist/federation/webfinger.test.mjs +3 -3
- package/dist/{http-B2u6PvNX.mjs → http-BNDHRNJP.mjs} +8 -4
- package/dist/{http-BPPCh0xN.js → http-BY8PpQzP.js} +6 -2
- package/dist/{http-BGP2QCbe.cjs → http-CTYio50W.cjs} +6 -2
- package/dist/{key-C9DkrWwb.mjs → key-BbuFo4CW.mjs} +2 -2
- package/dist/{kv-D6hNiMTK.d.ts → kv-CZKl1IUS.d.cts} +3 -2
- package/dist/{kv-gJ8LYbxX.d.cts → kv-CxaI4eGo.d.ts} +3 -2
- package/dist/{kv-cache-qJSjfLGm.mjs → kv-cache-CNZOaZYq.mjs} +1 -1
- package/dist/{kv-cache-C1TC_e9y.cjs → kv-cache-CrcqGkT-.cjs} +34 -8
- package/dist/{kv-cache-Cl1q1aA9.js → kv-cache-DNnjnc9t.js} +35 -9
- package/dist/{ld-DNl7KwLY.mjs → ld-BYV2Luge.mjs} +4 -4
- package/dist/{metrics-Ce55disp.mjs → metrics-QrVsKSG9.mjs} +1 -1
- package/dist/{middleware-C96wm_7x.mjs → middleware-54KSGAQA.mjs} +1 -1
- package/dist/{middleware-C_utyVa_.js → middleware-B4FNnN3W.js} +36 -11
- package/dist/{middleware-BCG2BX1n.mjs → middleware-Bj9s3J_0.mjs} +22 -19
- package/dist/{middleware-BZojifnF.cjs → middleware-Dv-L7Plm.cjs} +36 -11
- package/dist/{mod-PVR75MeU.d.cts → mod-B6PwkUMU.d.cts} +1 -1
- package/dist/{mod-DHgc4ygG.d.ts → mod-Br8yJNcE.d.ts} +3 -1
- package/dist/{mod-1TuoXkGs.d.cts → mod-Co1M3Ux0.d.cts} +3 -1
- package/dist/{mod-CFuyfw3c.d.ts → mod-LmD03uRA.d.ts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/client.test.mjs +50 -2
- package/dist/nodeinfo/handler.test.mjs +3 -3
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/nodeinfo/types.test.mjs +1 -1
- package/dist/otel/exporter.test.mjs +1 -1
- package/dist/otel/mod.d.cts +1 -1
- package/dist/otel/mod.d.ts +1 -1
- package/dist/{owner-DqqDBw-l.mjs → owner-BsBzJADO.mjs} +2 -2
- package/dist/{proof-Dz9ObvUq.js → proof-BxS2Xa8B.js} +2 -2
- package/dist/{proof-I6YcKRRq.cjs → proof-CGKQFT2M.cjs} +2 -2
- package/dist/{proof-D5vP7VIN.mjs → proof-cXVkPBIU.mjs} +3 -3
- package/dist/{send-CBtR8DQK.mjs → send-omt23uTA.mjs} +18 -4
- package/dist/sig/http.test.mjs +43 -3
- package/dist/sig/key.test.mjs +2 -2
- package/dist/sig/ld.test.mjs +5 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +2 -2
- package/dist/sig/proof.test.mjs +2 -2
- package/dist/{std__assert-BBjXFNOb.mjs → std__assert-BvGuO4xO.mjs} +2 -27
- package/dist/{temporal-B9t2tY9A.mjs → temporal-ZUAQe754.mjs} +1 -1
- package/dist/testing/mod.mjs +1 -1
- package/dist/{types-DWs-qZaY.cjs → types-DRPjmHVV.cjs} +7 -3
- package/dist/{types-sXITXcWa.js → types-miAYfiGO.js} +7 -3
- package/dist/utils/docloader.test.mjs +299 -3
- 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/vocab/cjs.test.mjs +1 -1
- package/package.json +7 -7
- package/dist/docloader-C-JrNL14.mjs +0 -53
|
@@ -3,17 +3,18 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as esm_default } from "../esm-vrlUxr60.mjs";
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
|
|
6
|
-
import "../std__assert-
|
|
6
|
+
import "../std__assert-BvGuO4xO.mjs";
|
|
7
7
|
import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
|
|
8
8
|
import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
|
|
9
9
|
import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
|
|
10
|
-
import { l as verifyRequest } from "../http-
|
|
10
|
+
import { l as verifyRequest } from "../http-BNDHRNJP.mjs";
|
|
11
11
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
|
|
12
|
-
import { t as doesActorOwnKey } from "../owner-
|
|
13
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-
|
|
12
|
+
import { t as doesActorOwnKey } from "../owner-BsBzJADO.mjs";
|
|
13
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-omt23uTA.mjs";
|
|
14
14
|
import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
|
|
15
15
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
16
16
|
import { FetchError, UrlError } from "@fedify/vocab-runtime";
|
|
17
|
+
import dns from "node:dns/promises";
|
|
17
18
|
import { AggregationTemporality, InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
18
19
|
//#region src/federation/send.test.ts
|
|
19
20
|
test("extractInboxes()", () => {
|
|
@@ -687,5 +688,85 @@ for (const signed of [false, true]) {
|
|
|
687
688
|
});
|
|
688
689
|
});
|
|
689
690
|
}
|
|
691
|
+
for (const signed of [false, true]) test({
|
|
692
|
+
name: `sendActivity() classifies DNS failures (signed: ${signed})`,
|
|
693
|
+
ignore: "Deno" in globalThis && (await Deno.permissions.query({ name: "net" })).state !== "granted",
|
|
694
|
+
async fn(t) {
|
|
695
|
+
const activity = {
|
|
696
|
+
type: "Create",
|
|
697
|
+
id: "https://example.com/activity"
|
|
698
|
+
};
|
|
699
|
+
const destination = "https://delivery.invalid/inbox";
|
|
700
|
+
const publicInbox = "https://8.8.8.8/inbox";
|
|
701
|
+
const keys = signed ? [{
|
|
702
|
+
privateKey: rsaPrivateKey2,
|
|
703
|
+
keyId: rsaPublicKey2.id
|
|
704
|
+
}] : [];
|
|
705
|
+
for (const result of [
|
|
706
|
+
"throws",
|
|
707
|
+
"empty",
|
|
708
|
+
"cname",
|
|
709
|
+
"private"
|
|
710
|
+
]) for (const redirected of [false, true]) await t.step(`${result}, redirected: ${redirected}`, async () => {
|
|
711
|
+
const [meterProvider, recorder] = createTestMeterProvider();
|
|
712
|
+
const originalLookup = dns.lookup;
|
|
713
|
+
const resolverError = /* @__PURE__ */ new Error("Resolver unavailable");
|
|
714
|
+
const lookups = [];
|
|
715
|
+
dns.lookup = ((hostname, options) => {
|
|
716
|
+
lookups.push(hostname);
|
|
717
|
+
assertEquals(hostname, "delivery.invalid");
|
|
718
|
+
assertEquals(options, { all: true });
|
|
719
|
+
if (result === "throws") return Promise.reject(resolverError);
|
|
720
|
+
return Promise.resolve(result === "empty" ? [] : [{
|
|
721
|
+
address: result === "private" ? "127.0.0.1" : "alias.invalid.",
|
|
722
|
+
family: 4
|
|
723
|
+
}]);
|
|
724
|
+
});
|
|
725
|
+
try {
|
|
726
|
+
esm_default.mockGlobal().catch(202);
|
|
727
|
+
if (redirected) esm_default.route(publicInbox, {
|
|
728
|
+
status: 307,
|
|
729
|
+
headers: { Location: destination }
|
|
730
|
+
});
|
|
731
|
+
const send = () => sendActivity({
|
|
732
|
+
activity,
|
|
733
|
+
activityType: "https://www.w3.org/ns/activitystreams#Create",
|
|
734
|
+
meterProvider,
|
|
735
|
+
keys,
|
|
736
|
+
inbox: new URL(redirected ? publicInbox : destination)
|
|
737
|
+
});
|
|
738
|
+
if (result === "private") assertEquals((await assertRejects(send, UrlError)).reason, "disallowed");
|
|
739
|
+
else {
|
|
740
|
+
const error = await assertRejects(send, FetchError);
|
|
741
|
+
assertEquals(error.url.href, destination);
|
|
742
|
+
assertInstanceOf(error.cause, UrlError);
|
|
743
|
+
assertEquals(error.cause.reason, "dns");
|
|
744
|
+
assertEquals(error.cause.cause, result === "throws" ? resolverError : void 0);
|
|
745
|
+
}
|
|
746
|
+
const expectedCount = result === "private" && !redirected ? 0 : 1;
|
|
747
|
+
const sent = recorder.getMeasurements("activitypub.delivery.sent");
|
|
748
|
+
const durations = recorder.getMeasurements("activitypub.delivery.duration");
|
|
749
|
+
assertEquals(sent.length, expectedCount);
|
|
750
|
+
assertEquals(durations.length, expectedCount);
|
|
751
|
+
if (expectedCount === 1) {
|
|
752
|
+
assertEquals(sent[0].value, 1);
|
|
753
|
+
assertEquals(sent[0].attributes, {
|
|
754
|
+
"activitypub.remote.host": redirected ? "8.8.8.8" : "delivery.invalid",
|
|
755
|
+
"activitypub.activity.type": "https://www.w3.org/ns/activitystreams#Create",
|
|
756
|
+
"activitypub.delivery.success": false
|
|
757
|
+
});
|
|
758
|
+
assertEquals(durations[0].attributes, sent[0].attributes);
|
|
759
|
+
assertGreaterOrEqual(durations[0].value, 0);
|
|
760
|
+
}
|
|
761
|
+
assertEquals(lookups, ["delivery.invalid"]);
|
|
762
|
+
assertEquals(esm_default.callHistory.calls(destination).length, 0);
|
|
763
|
+
assertEquals(esm_default.callHistory.calls().length, redirected ? 1 : 0);
|
|
764
|
+
} finally {
|
|
765
|
+
dns.lookup = originalLookup;
|
|
766
|
+
esm_default.hardReset();
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
});
|
|
690
771
|
//#endregion
|
|
691
772
|
export {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import "../std__assert-
|
|
4
|
+
import "../std__assert-BvGuO4xO.mjs";
|
|
5
5
|
import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
|
|
6
6
|
import { t as assert } from "../assert-jSdZMYam.mjs";
|
|
7
|
-
import { t as hasMalformedKnownTemporalLiteral } from "../temporal-
|
|
7
|
+
import { t as hasMalformedKnownTemporalLiteral } from "../temporal-ZUAQe754.mjs";
|
|
8
8
|
import { test } from "@fedify/fixture";
|
|
9
9
|
//#region src/federation/temporal.test.ts
|
|
10
10
|
test("hasMalformedKnownTemporalLiteral() detects expanded proof timestamps", async () => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { r as createRequestContext } from "../context-
|
|
4
|
+
import { r as createRequestContext } from "../context-CxbCIptr.mjs";
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
|
|
6
|
-
import "../std__assert-
|
|
6
|
+
import "../std__assert-BvGuO4xO.mjs";
|
|
7
7
|
import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
|
|
8
8
|
import { t as MemoryKvStore } from "../kv-CX8qfaad.mjs";
|
|
9
|
-
import { o as createFederation, s as handleWebFinger } from "../middleware-
|
|
9
|
+
import { o as createFederation, s as handleWebFinger } from "../middleware-Bj9s3J_0.mjs";
|
|
10
10
|
import { Image, Link, Person, Tombstone } from "@fedify/vocab";
|
|
11
11
|
import { createTestMeterProvider, test } from "@fedify/fixture";
|
|
12
12
|
//#region src/federation/webfinger.test.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-DUgFsCmM.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-QrVsKSG9.mjs";
|
|
6
6
|
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-Dd__NiUL.mjs";
|
|
7
|
-
import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-
|
|
7
|
+
import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-BbuFo4CW.mjs";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
9
|
import { CryptographicKey } from "@fedify/vocab";
|
|
10
10
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -718,6 +718,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
718
718
|
failure = result;
|
|
719
719
|
failureAlgorithm = algorithm;
|
|
720
720
|
};
|
|
721
|
+
let body = null;
|
|
722
|
+
let digestValid = null;
|
|
721
723
|
for (const sigName of signatureNames) {
|
|
722
724
|
if (!signatures[sigName]) {
|
|
723
725
|
setFailure(invalidSignatureResult(parseKeyId(signatureInputs[sigName]?.keyId)));
|
|
@@ -769,7 +771,9 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
769
771
|
setFailure(invalidSignatureResult(keyId));
|
|
770
772
|
continue;
|
|
771
773
|
}
|
|
772
|
-
|
|
774
|
+
body ??= await request.arrayBuffer();
|
|
775
|
+
digestValid ??= await verifyRfc9421ContentDigest(contentDigestHeader, body);
|
|
776
|
+
if (!digestValid) {
|
|
773
777
|
logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
|
|
774
778
|
setFailure(invalidSignatureResult(keyId));
|
|
775
779
|
continue;
|
|
@@ -10,7 +10,7 @@ import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } fro
|
|
|
10
10
|
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
11
11
|
//#region deno.json
|
|
12
12
|
var name = "@fedify/fedify";
|
|
13
|
-
var version = "2.3.
|
|
13
|
+
var version = "2.3.10";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region src/sig/accept.ts
|
|
16
16
|
/**
|
|
@@ -2189,6 +2189,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
2189
2189
|
failure = result;
|
|
2190
2190
|
failureAlgorithm = algorithm;
|
|
2191
2191
|
};
|
|
2192
|
+
let body = null;
|
|
2193
|
+
let digestValid = null;
|
|
2192
2194
|
for (const sigName of signatureNames) {
|
|
2193
2195
|
if (!signatures[sigName]) {
|
|
2194
2196
|
setFailure(invalidSignatureResult(parseKeyId(signatureInputs[sigName]?.keyId)));
|
|
@@ -2240,7 +2242,9 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
2240
2242
|
setFailure(invalidSignatureResult(keyId));
|
|
2241
2243
|
continue;
|
|
2242
2244
|
}
|
|
2243
|
-
|
|
2245
|
+
body ??= await request.arrayBuffer();
|
|
2246
|
+
digestValid ??= await verifyRfc9421ContentDigest(contentDigestHeader, body);
|
|
2247
|
+
if (!digestValid) {
|
|
2244
2248
|
logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
|
|
2245
2249
|
setFailure(invalidSignatureResult(keyId));
|
|
2246
2250
|
continue;
|
|
@@ -11,7 +11,7 @@ let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conve
|
|
|
11
11
|
let byte_encodings_base64 = require("byte-encodings/base64");
|
|
12
12
|
//#region deno.json
|
|
13
13
|
var name = "@fedify/fedify";
|
|
14
|
-
var version = "2.3.
|
|
14
|
+
var version = "2.3.10";
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/sig/accept.ts
|
|
17
17
|
/**
|
|
@@ -2190,6 +2190,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
2190
2190
|
failure = result;
|
|
2191
2191
|
failureAlgorithm = algorithm;
|
|
2192
2192
|
};
|
|
2193
|
+
let body = null;
|
|
2194
|
+
let digestValid = null;
|
|
2193
2195
|
for (const sigName of signatureNames) {
|
|
2194
2196
|
if (!signatures[sigName]) {
|
|
2195
2197
|
setFailure(invalidSignatureResult(parseKeyId(signatureInputs[sigName]?.keyId)));
|
|
@@ -2241,7 +2243,9 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
2241
2243
|
setFailure(invalidSignatureResult(keyId));
|
|
2242
2244
|
continue;
|
|
2243
2245
|
}
|
|
2244
|
-
|
|
2246
|
+
body ??= await request.arrayBuffer();
|
|
2247
|
+
digestValid ??= await verifyRfc9421ContentDigest(contentDigestHeader, body);
|
|
2248
|
+
if (!digestValid) {
|
|
2245
2249
|
logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
|
|
2246
2250
|
setFailure(invalidSignatureResult(keyId));
|
|
2247
2251
|
continue;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-DUgFsCmM.mjs";
|
|
5
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-QrVsKSG9.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
8
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -41,14 +41,15 @@ interface KvStore {
|
|
|
41
41
|
/**
|
|
42
42
|
* Gets the value for the given key.
|
|
43
43
|
* @param key The key to get the value for.
|
|
44
|
-
* @returns The value for the key,
|
|
44
|
+
* @returns The value for the key, including `null` if stored, or `undefined`
|
|
45
|
+
* if the key does not exist.
|
|
45
46
|
* @template T The type of the value to get.
|
|
46
47
|
*/
|
|
47
48
|
get<T = unknown>(key: KvKey): Promise<T | undefined>;
|
|
48
49
|
/**
|
|
49
50
|
* Sets the value for the given key.
|
|
50
51
|
* @param key The key to set the value for.
|
|
51
|
-
* @param value The value to set.
|
|
52
|
+
* @param value The value to set. `null` is a storable value.
|
|
52
53
|
* @param options Additional options for setting the value.
|
|
53
54
|
*/
|
|
54
55
|
set(key: KvKey, value: unknown, options?: KvStoreSetOptions): Promise<void>;
|
|
@@ -41,14 +41,15 @@ interface KvStore {
|
|
|
41
41
|
/**
|
|
42
42
|
* Gets the value for the given key.
|
|
43
43
|
* @param key The key to get the value for.
|
|
44
|
-
* @returns The value for the key,
|
|
44
|
+
* @returns The value for the key, including `null` if stored, or `undefined`
|
|
45
|
+
* if the key does not exist.
|
|
45
46
|
* @template T The type of the value to get.
|
|
46
47
|
*/
|
|
47
48
|
get<T = unknown>(key: KvKey): Promise<T | undefined>;
|
|
48
49
|
/**
|
|
49
50
|
* Sets the value for the given key.
|
|
50
51
|
* @param key The key to set the value for.
|
|
51
|
-
* @param value The value to set.
|
|
52
|
+
* @param value The value to set. `null` is a storable value.
|
|
52
53
|
* @param options Additional options for setting the value.
|
|
53
54
|
*/
|
|
54
55
|
set(key: KvKey, value: unknown, options?: KvStoreSetOptions): Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { p as recordDocumentCache } from "./metrics-
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-QrVsKSG9.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
require("./chunk-DDcVe30Y.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-CTYio50W.cjs");
|
|
5
5
|
let _logtape_logtape = require("@logtape/logtape");
|
|
6
6
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
7
7
|
let es_toolkit = require("es-toolkit");
|
|
@@ -11,10 +11,13 @@ const logger$1 = (0, _logtape_logtape.getLogger)([
|
|
|
11
11
|
"utils",
|
|
12
12
|
"docloader"
|
|
13
13
|
]);
|
|
14
|
+
const DEFAULT_MAX_REDIRECTION = 20;
|
|
14
15
|
/**
|
|
15
16
|
* Gets an authenticated {@link DocumentLoader} for the given identity.
|
|
16
17
|
* Note that an authenticated document loader intentionally does not cache
|
|
17
18
|
* the fetched documents.
|
|
19
|
+
* At most 20 HTTP redirects and alternate document links are followed in total
|
|
20
|
+
* per call. Revisiting a URL within that chain throws a {@link FetchError}.
|
|
18
21
|
* @param identity The identity to get the document loader for.
|
|
19
22
|
* The actor's key pair.
|
|
20
23
|
* @param options The options for the document loader.
|
|
@@ -24,29 +27,52 @@ const logger$1 = (0, _logtape_logtape.getLogger)([
|
|
|
24
27
|
*/
|
|
25
28
|
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
26
29
|
require_http.validateCryptoKey(identity.privateKey);
|
|
27
|
-
async function load(url, options) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
31
|
+
options?.signal?.throwIfAborted();
|
|
32
|
+
let currentUrl = new URL(url).href;
|
|
33
|
+
await validateUrl(currentUrl);
|
|
34
|
+
visited.add(currentUrl);
|
|
35
|
+
const originalRequest = (0, _fedify_vocab_runtime.createActivityPubRequest)(currentUrl, { userAgent });
|
|
36
|
+
function follow(nextUrl) {
|
|
37
|
+
options?.signal?.throwIfAborted();
|
|
38
|
+
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new _fedify_vocab_runtime.FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
39
|
+
if (visited.has(nextUrl)) throw new _fedify_vocab_runtime.FetchError(currentUrl, `Redirect loop detected: ${nextUrl}`);
|
|
40
|
+
redirected++;
|
|
41
|
+
}
|
|
42
|
+
const response = await require_http.doubleKnock(originalRequest, identity, {
|
|
30
43
|
maxRedirection,
|
|
31
44
|
specDeterminer,
|
|
32
45
|
log: (0, es_toolkit.curry)(_fedify_vocab_runtime.logRequest)(logger$1),
|
|
33
46
|
tracerProvider,
|
|
34
47
|
signal: options?.signal,
|
|
35
|
-
validateRedirect:
|
|
36
|
-
|
|
48
|
+
validateRedirect: async (nextUrl) => {
|
|
49
|
+
follow(nextUrl);
|
|
50
|
+
await validateUrl(nextUrl);
|
|
51
|
+
visited.add(nextUrl);
|
|
52
|
+
currentUrl = nextUrl;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return (0, _fedify_vocab_runtime.getRemoteDocument)(currentUrl, response, (alternateUrl) => {
|
|
56
|
+
follow(alternateUrl);
|
|
57
|
+
return load(alternateUrl, options, redirected, visited);
|
|
58
|
+
});
|
|
37
59
|
}
|
|
38
60
|
async function validateUrl(url) {
|
|
39
61
|
if (!allowPrivateAddress) try {
|
|
40
62
|
await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
|
|
41
63
|
} catch (error) {
|
|
42
|
-
if (error instanceof _fedify_vocab_runtime.UrlError) logger$1.
|
|
64
|
+
if (error instanceof _fedify_vocab_runtime.UrlError) if (error.reason === "dns") logger$1.debug("DNS lookup failed for {url}", {
|
|
65
|
+
url,
|
|
66
|
+
error
|
|
67
|
+
});
|
|
68
|
+
else logger$1.error("Disallowed private URL: {url}", {
|
|
43
69
|
url,
|
|
44
70
|
error
|
|
45
71
|
});
|
|
46
72
|
throw error;
|
|
47
73
|
}
|
|
48
74
|
}
|
|
49
|
-
return load;
|
|
75
|
+
return (url, options) => load(url, options);
|
|
50
76
|
}
|
|
51
77
|
//#endregion
|
|
52
78
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { T as recordDocumentCache, f as validateCryptoKey, t as doubleKnock } from "./http-
|
|
3
|
+
import { T as recordDocumentCache, f as validateCryptoKey, t as doubleKnock } from "./http-BY8PpQzP.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
|
-
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
5
|
+
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
7
7
|
//#region src/utils/docloader.ts
|
|
8
8
|
const logger$1 = getLogger([
|
|
@@ -10,10 +10,13 @@ const logger$1 = getLogger([
|
|
|
10
10
|
"utils",
|
|
11
11
|
"docloader"
|
|
12
12
|
]);
|
|
13
|
+
const DEFAULT_MAX_REDIRECTION = 20;
|
|
13
14
|
/**
|
|
14
15
|
* Gets an authenticated {@link DocumentLoader} for the given identity.
|
|
15
16
|
* Note that an authenticated document loader intentionally does not cache
|
|
16
17
|
* the fetched documents.
|
|
18
|
+
* At most 20 HTTP redirects and alternate document links are followed in total
|
|
19
|
+
* per call. Revisiting a URL within that chain throws a {@link FetchError}.
|
|
17
20
|
* @param identity The identity to get the document loader for.
|
|
18
21
|
* The actor's key pair.
|
|
19
22
|
* @param options The options for the document loader.
|
|
@@ -23,29 +26,52 @@ const logger$1 = getLogger([
|
|
|
23
26
|
*/
|
|
24
27
|
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
25
28
|
validateCryptoKey(identity.privateKey);
|
|
26
|
-
async function load(url, options) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
30
|
+
options?.signal?.throwIfAborted();
|
|
31
|
+
let currentUrl = new URL(url).href;
|
|
32
|
+
await validateUrl(currentUrl);
|
|
33
|
+
visited.add(currentUrl);
|
|
34
|
+
const originalRequest = createActivityPubRequest(currentUrl, { userAgent });
|
|
35
|
+
function follow(nextUrl) {
|
|
36
|
+
options?.signal?.throwIfAborted();
|
|
37
|
+
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
38
|
+
if (visited.has(nextUrl)) throw new FetchError(currentUrl, `Redirect loop detected: ${nextUrl}`);
|
|
39
|
+
redirected++;
|
|
40
|
+
}
|
|
41
|
+
const response = await doubleKnock(originalRequest, identity, {
|
|
29
42
|
maxRedirection,
|
|
30
43
|
specDeterminer,
|
|
31
44
|
log: curry(logRequest)(logger$1),
|
|
32
45
|
tracerProvider,
|
|
33
46
|
signal: options?.signal,
|
|
34
|
-
validateRedirect:
|
|
35
|
-
|
|
47
|
+
validateRedirect: async (nextUrl) => {
|
|
48
|
+
follow(nextUrl);
|
|
49
|
+
await validateUrl(nextUrl);
|
|
50
|
+
visited.add(nextUrl);
|
|
51
|
+
currentUrl = nextUrl;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return getRemoteDocument(currentUrl, response, (alternateUrl) => {
|
|
55
|
+
follow(alternateUrl);
|
|
56
|
+
return load(alternateUrl, options, redirected, visited);
|
|
57
|
+
});
|
|
36
58
|
}
|
|
37
59
|
async function validateUrl(url) {
|
|
38
60
|
if (!allowPrivateAddress) try {
|
|
39
61
|
await validatePublicUrl(url);
|
|
40
62
|
} catch (error) {
|
|
41
|
-
if (error instanceof UrlError) logger$1.
|
|
63
|
+
if (error instanceof UrlError) if (error.reason === "dns") logger$1.debug("DNS lookup failed for {url}", {
|
|
64
|
+
url,
|
|
65
|
+
error
|
|
66
|
+
});
|
|
67
|
+
else logger$1.error("Disallowed private URL: {url}", {
|
|
42
68
|
url,
|
|
43
69
|
error
|
|
44
70
|
});
|
|
45
71
|
throw error;
|
|
46
72
|
}
|
|
47
73
|
}
|
|
48
|
-
return load;
|
|
74
|
+
return (url, options) => load(url, options);
|
|
49
75
|
}
|
|
50
76
|
//#endregion
|
|
51
77
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { r as fetchKey, s as validateCryptoKey } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-DUgFsCmM.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-QrVsKSG9.mjs";
|
|
6
|
+
import { r as fetchKey, s as validateCryptoKey } from "./key-BbuFo4CW.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
9
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -206,7 +206,7 @@ function normalizeContextReference(reference, baseUrl) {
|
|
|
206
206
|
/** @internal */
|
|
207
207
|
function isInvalidUrlTypeError(error) {
|
|
208
208
|
const code = error.code;
|
|
209
|
-
return error instanceof TypeError && (code === "ERR_INVALID_URL" || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
|
|
209
|
+
return error instanceof TypeError && (code === "ERR_INVALID_URL" || error.message === "Invalid URL string." || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
|
|
210
210
|
}
|
|
211
211
|
async function applyGraphAliasContext(state, context, documentLoader, remoteContextCache, baseUrl = null, processingContexts = /* @__PURE__ */ new Set()) {
|
|
212
212
|
if (context === null) return createGraphAliasContextState();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-DUgFsCmM.mjs";
|
|
5
5
|
import { metrics } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/federation/metrics.ts
|
|
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./chunk-CRNNMoPX.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
|
|
5
|
-
import { A as recordWebFingerHandle, C as recordCollectionRequest, D as recordInboxActivity, E as recordFanoutRecipients, I as name, L as version, M as formatAcceptSignature, O as recordOutboxActivity, S as recordCollectionPageItems, _ as instrumentDocumentLoader, a as verifyRequestDetailed, b as recordCircuitBreakerStateChange, d as importJwk, f as validateCryptoKey, g as getRemoteHost, h as getFederationMetrics, i as verifyRequest, j as registerQueueDepthGauge, k as recordOutboxEnqueue, m as getDurationMs, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as isAbortError, w as recordCollectionTotalItems, x as recordCollectionDispatchDuration } from "./http-
|
|
6
|
-
import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-
|
|
7
|
-
import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
5
|
+
import { A as recordWebFingerHandle, C as recordCollectionRequest, D as recordInboxActivity, E as recordFanoutRecipients, I as name, L as version, M as formatAcceptSignature, O as recordOutboxActivity, S as recordCollectionPageItems, _ as instrumentDocumentLoader, a as verifyRequestDetailed, b as recordCircuitBreakerStateChange, d as importJwk, f as validateCryptoKey, g as getRemoteHost, h as getFederationMetrics, i as verifyRequest, j as registerQueueDepthGauge, k as recordOutboxEnqueue, m as getDurationMs, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as isAbortError, w as recordCollectionTotalItems, x as recordCollectionDispatchDuration } from "./http-BY8PpQzP.js";
|
|
6
|
+
import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-miAYfiGO.js";
|
|
7
|
+
import { _ as hasSignatureLike, b as signJsonLd, c as getKeyOwner, f as compactJsonLd, g as hasSignature, h as getNormalizationContextLoader, i as verifyObject, l as InvalidContextReferenceError, m as detachSignature, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, r as signObject, s as doesActorOwnKey, u as assertSafeJsonLd, v as isClearlyMalformedContextReference, w as wrapContextLoaderForJsonLd, x as verifyCompactJsonLd, y as isInvalidUrlTypeError } from "./proof-BxS2Xa8B.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DNnjnc9t.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, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
@@ -111,6 +111,7 @@ var FederationBuilderImpl = class {
|
|
|
111
111
|
* Symbol registry for unique identification of unnamed symbols.
|
|
112
112
|
*/
|
|
113
113
|
#symbolRegistry = /* @__PURE__ */ new Map();
|
|
114
|
+
#collectionNames = /* @__PURE__ */ new Map();
|
|
114
115
|
constructor() {
|
|
115
116
|
this.router = new Router();
|
|
116
117
|
this.objectCallbacks = {};
|
|
@@ -139,6 +140,8 @@ var FederationBuilderImpl = class {
|
|
|
139
140
|
f.objectTypeIds = { ...this.objectTypeIds };
|
|
140
141
|
f.collectionCallbacks = { ...this.collectionCallbacks };
|
|
141
142
|
f.collectionTypeIds = { ...this.collectionTypeIds };
|
|
143
|
+
f.#symbolRegistry = new Map(this.#symbolRegistry);
|
|
144
|
+
f.#collectionNames = new Map(this.#collectionNames);
|
|
142
145
|
f.inboxPath = this.inboxPath;
|
|
143
146
|
f.outboxPath = this.outboxPath;
|
|
144
147
|
f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
|
|
@@ -618,6 +621,7 @@ var FederationBuilderImpl = class {
|
|
|
618
621
|
if (this.collectionCallbacks[name] != null) throw new RouterError(`Collection dispatcher for ${strName} already set.`);
|
|
619
622
|
assertPath(path);
|
|
620
623
|
if (Router.variables(path).size < 1) throw new RouterError("Path for collection dispatcher must have at least one variable.");
|
|
624
|
+
this.#collectionNames.set(routeName, name);
|
|
621
625
|
this.router.add(path, routeName);
|
|
622
626
|
const callbacks = { dispatcher };
|
|
623
627
|
this.collectionCallbacks[name] = callbacks;
|
|
@@ -655,6 +659,10 @@ var FederationBuilderImpl = class {
|
|
|
655
659
|
const routeName = this.#uniqueCollectionId(name);
|
|
656
660
|
return this.router.build(`collection:${routeName}`, values) ?? this.router.build(`orderedCollection:${routeName}`, values);
|
|
657
661
|
}
|
|
662
|
+
/** Resolves a custom collection route to its original name. */
|
|
663
|
+
getCollectionName(routeName) {
|
|
664
|
+
return this.#collectionNames.get(routeName) ?? routeName.replace(/^(collection|orderedCollection):/, "");
|
|
665
|
+
}
|
|
658
666
|
setOutboxPermanentFailureHandler(handler) {
|
|
659
667
|
this.outboxPermanentFailureHandler = handler;
|
|
660
668
|
}
|
|
@@ -3437,6 +3445,15 @@ async function sendActivityInternal({ activity, activityId, activityType, keys,
|
|
|
3437
3445
|
if (!allowPrivateAddress) try {
|
|
3438
3446
|
await validatePublicUrl(url);
|
|
3439
3447
|
} catch (error) {
|
|
3448
|
+
if (error instanceof UrlError && error.reason === "dns") {
|
|
3449
|
+
logger.error("DNS resolution failed for URL: {url}", {
|
|
3450
|
+
url,
|
|
3451
|
+
error
|
|
3452
|
+
});
|
|
3453
|
+
const failure = new FetchError(url, error.message);
|
|
3454
|
+
failure.cause = error;
|
|
3455
|
+
throw failure;
|
|
3456
|
+
}
|
|
3440
3457
|
if (error instanceof UrlError) logger.error("Disallowed private URL: {url}", {
|
|
3441
3458
|
url,
|
|
3442
3459
|
error
|
|
@@ -3444,7 +3461,12 @@ async function sendActivityInternal({ activity, activityId, activityType, keys,
|
|
|
3444
3461
|
throw error;
|
|
3445
3462
|
}
|
|
3446
3463
|
}
|
|
3447
|
-
|
|
3464
|
+
try {
|
|
3465
|
+
await validateUrl(inbox.href);
|
|
3466
|
+
} catch (error) {
|
|
3467
|
+
if (error instanceof FetchError) federationMetrics.recordDelivery(inbox, getDurationMs(started), false, activityType);
|
|
3468
|
+
throw error;
|
|
3469
|
+
}
|
|
3448
3470
|
headers = new Headers(headers);
|
|
3449
3471
|
headers.set("Content-Type", "application/activity+json");
|
|
3450
3472
|
const request = new Request(inbox, {
|
|
@@ -5607,10 +5629,10 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5607
5629
|
onNotFound
|
|
5608
5630
|
});
|
|
5609
5631
|
case "collection": {
|
|
5610
|
-
const name = route.name
|
|
5632
|
+
const name = this.getCollectionName(route.name);
|
|
5611
5633
|
const callbacks = this.collectionCallbacks[name];
|
|
5612
5634
|
return await handleCustomCollection(request, {
|
|
5613
|
-
name,
|
|
5635
|
+
name: String(name),
|
|
5614
5636
|
context,
|
|
5615
5637
|
values: route.values,
|
|
5616
5638
|
collectionCallbacks: callbacks,
|
|
@@ -5621,10 +5643,10 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5621
5643
|
});
|
|
5622
5644
|
}
|
|
5623
5645
|
case "orderedCollection": {
|
|
5624
|
-
const name = route.name
|
|
5646
|
+
const name = this.getCollectionName(route.name);
|
|
5625
5647
|
const callbacks = this.collectionCallbacks[name];
|
|
5626
5648
|
return await handleOrderedCollection(request, {
|
|
5627
|
-
name,
|
|
5649
|
+
name: String(name),
|
|
5628
5650
|
context,
|
|
5629
5651
|
values: route.values,
|
|
5630
5652
|
collectionCallbacks: callbacks,
|
|
@@ -5867,8 +5889,10 @@ var ContextImpl = class ContextImpl {
|
|
|
5867
5889
|
const collectionRegex = new RegExp(`^(${["collection", "orderedCollection"].join("|")}):(.*)$`);
|
|
5868
5890
|
const match = route.name.match(collectionRegex);
|
|
5869
5891
|
if (match !== null) {
|
|
5870
|
-
const [, type
|
|
5892
|
+
const [, type] = match;
|
|
5893
|
+
const name = this.federation.getCollectionName(route.name);
|
|
5871
5894
|
const cls = this.federation.collectionTypeIds[name];
|
|
5895
|
+
if (cls == null) return null;
|
|
5872
5896
|
return {
|
|
5873
5897
|
type,
|
|
5874
5898
|
name,
|
|
@@ -6238,7 +6262,7 @@ var ContextImpl = class ContextImpl {
|
|
|
6238
6262
|
"inbox"
|
|
6239
6263
|
]);
|
|
6240
6264
|
const contextLoader = options.contextLoader ?? this.contextLoader;
|
|
6241
|
-
|
|
6265
|
+
let json = await activity.toJsonLd({ contextLoader });
|
|
6242
6266
|
const keyCache = new KvKeyCache(this.federation.kv, this.federation.kvPrefixes.publicKey, this);
|
|
6243
6267
|
if (await verifyObject(Activity, json, {
|
|
6244
6268
|
contextLoader,
|
|
@@ -6295,6 +6319,7 @@ var ContextImpl = class ContextImpl {
|
|
|
6295
6319
|
}
|
|
6296
6320
|
logger.debug("Successfully fetched the remote activity object {activityId}; ignore the original activity and use the fetched one, which is trustworthy.");
|
|
6297
6321
|
activity = fetched;
|
|
6322
|
+
json = await fetched.toJsonLd({ contextLoader });
|
|
6298
6323
|
} else logger.debug("Object Integrity Proofs are verified.", {
|
|
6299
6324
|
recipient,
|
|
6300
6325
|
activity: json
|