@fedify/fedify 2.4.0-dev.2103 → 2.4.0-dev.2115
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-CHht75pX.mjs → builder-CZcBWrBd.mjs} +29 -5
- 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-DKKH_Nr1.mjs → compound-proof-CDuP9MIX.mjs} +3 -3
- package/dist/{context-mDTxTw-S.d.cts → context-SMNOiiY6.d.cts} +93 -11
- package/dist/{context-CfJE_oQu.d.ts → context-tOiJfBoD.d.ts} +93 -11
- package/dist/{deno-CkjiYK_Z.mjs → deno-CCABdw7r.mjs} +1 -1
- package/dist/{docloader-C1hAJnWc.mjs → docloader-Bby5g2iu.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 +118 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/keycache.test.mjs +67 -1
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +184 -7
- 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/outgoing-proof.test.mjs +5 -5
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-gateway-keys.test.mjs +24 -7
- package/dist/federation/portable-inbox.test.mjs +4 -4
- package/dist/federation/portable.test.mjs +31 -4
- 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-C1dL6SiT.cjs → federation-DYr384xz.cjs} +116 -15
- package/dist/{http-Cala2Grs.cjs → http-B4mQvNcv.cjs} +140 -55
- package/dist/{http-BU-8fUrz.mjs → http-BcLnr2do.mjs} +6 -12
- package/dist/{http-xlG-jRdB.d.cts → http-BrQgkJay.d.ts} +12 -7
- package/dist/{http-tTlTeFa0.js → http-Ce6_Lf7k.js} +140 -55
- package/dist/{http-n2v6DPxu.d.ts → http-D76Py0M4.d.cts} +12 -7
- package/dist/{key-I8gLBkcf.mjs → key-CkNxztNV.mjs} +107 -16
- package/dist/{keycache-BUDHB5rY.mjs → keycache-BInaECGj.mjs} +68 -0
- package/dist/{kv-cache-Bl5EBFrU.cjs → kv-cache-Dqp_E-1g.cjs} +1 -1
- package/dist/{kv-cache-CxQu_cd4.js → kv-cache-DwzXzchj.js} +1 -1
- package/dist/{kv-cache-DJFoGRWQ.mjs → kv-cache-iFaRIcIL.mjs} +1 -1
- package/dist/{ld-wiJbqJHa.mjs → ld-CnT0f1nU.mjs} +4 -7
- package/dist/{metrics-BCAa5-kE.mjs → metrics-em_7lwhG.mjs} +1 -1
- package/dist/{middleware-FnITXhtz.mjs → middleware-BpwKvOpU.mjs} +26 -17
- package/dist/{middleware-B6IVTVL0.js → middleware-DhIBngkj.js} +108 -7
- package/dist/{middleware-6p2dYEVA.mjs → middleware-U9IuzvDO.mjs} +1 -1
- package/dist/{mod-BYvPz_T0.d.ts → mod-COWgSo2v.d.ts} +1 -1
- package/dist/{mod-Coacostr.d.ts → mod-CTh7ijx5.d.ts} +1 -1
- package/dist/{mod-xGFCHqq_.d.cts → mod-Cr79cQlc.d.cts} +1 -1
- package/dist/{mod-CVZrXSdm.d.ts → mod-Cwdt_CWU.d.ts} +1 -1
- package/dist/{mod-C8LieBzF.d.cts → mod-DMdGFMEl.d.cts} +1 -1
- package/dist/{mod-B3OzOobN.d.cts → mod-DnElMslb.d.cts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +7 -7
- package/dist/mod.d.ts +7 -7
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-BJp47LxN.mjs → owner-9LiHmOv1.mjs} +4 -4
- package/dist/{owner-DCt8W_Cv.cjs → owner-BtoMCv6Z.cjs} +1 -1
- package/dist/{owner-j5yrbXS1.js → owner-Cb3ytrlq.js} +1 -1
- package/dist/{portable-key-B5oKE_wZ.mjs → portable-key-9ck61lI0.mjs} +5 -4
- package/dist/{portable-key-id-Bva5iT3W.mjs → portable-key-id-T7lecIbt.mjs} +3 -2
- package/dist/{proof-BE4T5zF6.mjs → proof-xdPYGPaA.mjs} +32 -31
- package/dist/{send-BFITuKHw.mjs → send-Bf8rSWch.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +3 -3
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +2 -2
- package/dist/sig/portable-key.test.mjs +301 -23
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{sig-CRTRoouH.cjs → sig-Bj3fHnv0.cjs} +2 -2
- package/dist/{sig-CJHdGk9w.js → sig-DN9pOglI.js} +2 -2
- package/dist/{temporal-CyDDbE4i.mjs → temporal-tAtwv6vX.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +91 -9
- 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/package.json +7 -7
|
@@ -7,15 +7,15 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
|
7
7
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
8
8
|
import "../std__assert-DvMDRPes.mjs";
|
|
9
9
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
10
|
-
import { p as signJsonLd } from "../ld-
|
|
11
|
-
import { l as signRequest } from "../http-
|
|
10
|
+
import { p as signJsonLd } from "../ld-CnT0f1nU.mjs";
|
|
11
|
+
import { l as signRequest } from "../http-BcLnr2do.mjs";
|
|
12
12
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
13
|
-
import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-
|
|
13
|
+
import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-BpwKvOpU.mjs";
|
|
14
14
|
import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
|
|
15
|
-
import { t as KvKeyCache } from "../keycache-
|
|
15
|
+
import { t as KvKeyCache } from "../keycache-BInaECGj.mjs";
|
|
16
16
|
import { Create, CryptographicKey, Person } from "@fedify/vocab";
|
|
17
17
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
18
|
-
import { encodeMultibase, exportDidKey, parseIri } from "@fedify/vocab-runtime";
|
|
18
|
+
import { FetchError, encodeMultibase, exportDidKey, parseIri } from "@fedify/vocab-runtime";
|
|
19
19
|
import serialize from "json-canon";
|
|
20
20
|
//#region src/federation/portable-gateway-keys.test.ts
|
|
21
21
|
const did = await exportDidKey(ed25519PublicKey.publicKey);
|
|
@@ -255,8 +255,8 @@ function createLoader(responses) {
|
|
|
255
255
|
});
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
|
-
async function deliver(body, gateways, { kv = new MemoryKvStore(), httpSignature = true, actor } = {}) {
|
|
259
|
-
|
|
258
|
+
async function deliver(body, gateways, { kv = new MemoryKvStore(), httpSignature = true, actor, documentLoader } = {}) {
|
|
259
|
+
documentLoader ??= createLoader({ [compatibleActorId(gateway)]: actor ?? await actorDocument(gateways) });
|
|
260
260
|
const unsigned = new Request("https://local.example/inbox", {
|
|
261
261
|
method: "POST",
|
|
262
262
|
body: JSON.stringify(body),
|
|
@@ -332,6 +332,23 @@ test("handleInbox() requires proofs of portable actors despite gateway signature
|
|
|
332
332
|
dispatched: 1
|
|
333
333
|
});
|
|
334
334
|
});
|
|
335
|
+
test("handleInbox() fetches an unreachable gateway key once", async () => {
|
|
336
|
+
const fetched = [];
|
|
337
|
+
const documentLoader = (url) => {
|
|
338
|
+
if (url.replace(/#.*$/, "") !== compatibleActorId(gateway)) return mockDocumentLoader(url);
|
|
339
|
+
fetched.push(url);
|
|
340
|
+
return Promise.reject(new FetchError(url, "HTTP 503", new Response(null, { status: 503 })));
|
|
341
|
+
};
|
|
342
|
+
const kv = new MemoryKvStore();
|
|
343
|
+
for (let i = 0; i < 3; i++) {
|
|
344
|
+
const { status } = await deliver(await createJson(`unreachable-${i}`), [gateway], {
|
|
345
|
+
kv,
|
|
346
|
+
documentLoader
|
|
347
|
+
});
|
|
348
|
+
assertEquals(status, 401);
|
|
349
|
+
}
|
|
350
|
+
assertEquals(fetched.length, 1);
|
|
351
|
+
});
|
|
335
352
|
test("handleInbox() does not need gateway signatures for portable actors", async () => {
|
|
336
353
|
assertEquals(await deliver(await sign(await createJson("signed")), [otherGateway]), {
|
|
337
354
|
status: 202,
|
|
@@ -8,11 +8,11 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
|
|
|
8
8
|
import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
9
9
|
import "../std__assert-DvMDRPes.mjs";
|
|
10
10
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
11
|
-
import { p as signJsonLd } from "../ld-
|
|
12
|
-
import { i as signObject } from "../proof-
|
|
13
|
-
import { f as verifyRequestDetailed, l as signRequest } from "../http-
|
|
11
|
+
import { p as signJsonLd } from "../ld-CnT0f1nU.mjs";
|
|
12
|
+
import { i as signObject } from "../proof-xdPYGPaA.mjs";
|
|
13
|
+
import { f as verifyRequestDetailed, l as signRequest } from "../http-BcLnr2do.mjs";
|
|
14
14
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
15
|
-
import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-
|
|
15
|
+
import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-BpwKvOpU.mjs";
|
|
16
16
|
import { Create, CryptographicKey, Follow, Note, Person, Tombstone } from "@fedify/vocab";
|
|
17
17
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
18
18
|
import { exportDidKey, formatIri, parseIri } from "@fedify/vocab-runtime";
|
|
@@ -8,10 +8,10 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
|
8
8
|
import "../std__assert-DvMDRPes.mjs";
|
|
9
9
|
import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
|
|
10
10
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
11
|
-
import { i as signObject, s as verifyPortableObjectProof } from "../proof-
|
|
12
|
-
import { l as signRequest } from "../http-
|
|
11
|
+
import { i as signObject, s as verifyPortableObjectProof } from "../proof-xdPYGPaA.mjs";
|
|
12
|
+
import { l as signRequest } from "../http-BcLnr2do.mjs";
|
|
13
13
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
14
|
-
import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-
|
|
14
|
+
import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-BpwKvOpU.mjs";
|
|
15
15
|
import { configure, reset } from "@logtape/logtape";
|
|
16
16
|
import { Collection, Create, Note, Object as Object$1, Person, Tombstone, lookupObject } from "@fedify/vocab";
|
|
17
17
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
@@ -220,6 +220,18 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
|
|
|
220
220
|
inbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/inbox`),
|
|
221
221
|
outbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/outbox`),
|
|
222
222
|
gateways: [new URL("https://example.com/")]
|
|
223
|
+
})),
|
|
224
|
+
"tombstone": () => sign(new Tombstone({
|
|
225
|
+
id: parseIri(`ap+ef61://${did}/objects/tombstone`),
|
|
226
|
+
formerType: Note
|
|
227
|
+
})),
|
|
228
|
+
"unsigned-tombstone": () => Promise.resolve(new Tombstone({
|
|
229
|
+
id: parseIri(`ap+ef61://${did}/objects/unsigned-tombstone`),
|
|
230
|
+
formerType: Note
|
|
231
|
+
})),
|
|
232
|
+
"mismatched-tombstone": () => sign(new Tombstone({
|
|
233
|
+
id: parseIri(`ap+ef61://${did}/objects/other`),
|
|
234
|
+
formerType: Note
|
|
223
235
|
}))
|
|
224
236
|
};
|
|
225
237
|
federation.setObjectDispatcher(Object$1, "/objects/{id}", (_ctx, { id }) => objects[id]?.() ?? null);
|
|
@@ -234,7 +246,10 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
|
|
|
234
246
|
"activity": 200,
|
|
235
247
|
"actor": 200,
|
|
236
248
|
"mutated-id": 404,
|
|
237
|
-
"unsigned-actor": 500
|
|
249
|
+
"unsigned-actor": 500,
|
|
250
|
+
"tombstone": 200,
|
|
251
|
+
"unsigned-tombstone": 500,
|
|
252
|
+
"mismatched-tombstone": 404
|
|
238
253
|
})) await t.step(`${id} → ${status}`, async () => {
|
|
239
254
|
const response = await federation.fetch(gatewayRequest(`/objects/${id}`), { contextData: void 0 });
|
|
240
255
|
assertEquals(response.status, status);
|
|
@@ -245,6 +260,18 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
|
|
|
245
260
|
assertEquals(response.status, 500);
|
|
246
261
|
assertEquals(response.body, null);
|
|
247
262
|
});
|
|
263
|
+
await t.step("serves a signed tombstone with its body", async () => {
|
|
264
|
+
const response = await federation.fetch(gatewayRequest("/objects/tombstone"), { contextData: void 0 });
|
|
265
|
+
assertEquals(response.status, 200);
|
|
266
|
+
const body = await response.json();
|
|
267
|
+
assertEquals(body.type, "Tombstone");
|
|
268
|
+
assertEquals(body.id, `ap+ef61://${did}/objects/tombstone`);
|
|
269
|
+
});
|
|
270
|
+
await t.step("responds to HEAD for a tombstone without a body", async () => {
|
|
271
|
+
const response = await federation.fetch(gatewayRequest("/objects/tombstone", { method: "HEAD" }), { contextData: void 0 });
|
|
272
|
+
assertEquals(response.status, 200);
|
|
273
|
+
assertEquals(response.body, null);
|
|
274
|
+
});
|
|
248
275
|
});
|
|
249
276
|
test("Federation.fetch() authorizes portable object requests", async (t) => {
|
|
250
277
|
const federation = createTestFederation();
|
|
@@ -10,10 +10,10 @@ import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
|
|
|
10
10
|
import "../std__assert-DvMDRPes.mjs";
|
|
11
11
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
12
12
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
13
|
-
import { d as verifyRequest } from "../http-
|
|
13
|
+
import { d as verifyRequest } from "../http-BcLnr2do.mjs";
|
|
14
14
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
|
|
15
|
-
import { t as doesActorOwnKey } from "../owner-
|
|
16
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-
|
|
15
|
+
import { t as doesActorOwnKey } from "../owner-9LiHmOv1.mjs";
|
|
16
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-Bf8rSWch.mjs";
|
|
17
17
|
import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
|
|
18
18
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
19
19
|
import { FetchError, UrlError } from "@fedify/vocab-runtime";
|
|
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
|
|
5
5
|
import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-dbCShlCb.mjs";
|
|
6
6
|
import "../../testing-BWq1dCzx.mjs";
|
|
7
|
-
import { o as createFederation } from "../../middleware-
|
|
7
|
+
import { o as createFederation } from "../../middleware-BpwKvOpU.mjs";
|
|
8
8
|
import { n as ParallelMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
|
|
9
9
|
import { configure, reset } from "@logtape/logtape";
|
|
10
10
|
import { delay } from "es-toolkit";
|
|
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
|
|
5
5
|
import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-dbCShlCb.mjs";
|
|
6
6
|
import "../../testing-BWq1dCzx.mjs";
|
|
7
|
-
import { o as createFederation } from "../../middleware-
|
|
8
|
-
import { r as createFederationBuilder } from "../../builder-
|
|
7
|
+
import { o as createFederation } from "../../middleware-BpwKvOpU.mjs";
|
|
8
|
+
import { r as createFederationBuilder } from "../../builder-CZcBWrBd.mjs";
|
|
9
9
|
import { t as TaskCodec } from "../../codec-C6rTrpIp.mjs";
|
|
10
10
|
import { t as InProcessMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
|
|
11
11
|
import { W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
|
|
|
4
4
|
import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
|
|
5
5
|
import "../std__assert-DvMDRPes.mjs";
|
|
6
6
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
7
|
-
import { t as hasMalformedKnownTemporalLiteral } from "../temporal-
|
|
7
|
+
import { t as hasMalformedKnownTemporalLiteral } from "../temporal-tAtwv6vX.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 () => {
|
|
@@ -6,7 +6,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
|
6
6
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
7
7
|
import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
|
|
8
8
|
import "../std__assert-DvMDRPes.mjs";
|
|
9
|
-
import { o as createFederation, s as handleWebFinger } from "../middleware-
|
|
9
|
+
import { o as createFederation, s as handleWebFinger } from "../middleware-BpwKvOpU.mjs";
|
|
10
10
|
import { Image, Link, Person, Tombstone } from "@fedify/vocab";
|
|
11
11
|
import { createTestMeterProvider, test } from "@fedify/fixture";
|
|
12
12
|
import { parseIri } from "@fedify/vocab-runtime";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-Dmm3t92W.cjs");
|
|
3
3
|
const require_transformers = require("./transformers-BalCrSsr.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-B4mQvNcv.cjs");
|
|
5
5
|
const require_types = require("./types-Be2zbyeG.cjs");
|
|
6
|
-
const require_owner = require("./owner-
|
|
7
|
-
const require_kv_cache = require("./kv-cache-
|
|
6
|
+
const require_owner = require("./owner-BtoMCv6Z.cjs");
|
|
7
|
+
const require_kv_cache = require("./kv-cache-Dqp_E-1g.cjs");
|
|
8
8
|
let _logtape_logtape = require("@logtape/logtape");
|
|
9
9
|
let _fedify_uri_template = require("@fedify/uri-template");
|
|
10
10
|
let _fedify_vocab = require("@fedify/vocab");
|
|
@@ -342,8 +342,8 @@ var FederationBuilderImpl = class {
|
|
|
342
342
|
const variables = _fedify_uri_template.Router.variables(path);
|
|
343
343
|
this.router.add(path, routeName);
|
|
344
344
|
const callbacks = {
|
|
345
|
-
dispatcher: (ctx, values) => {
|
|
346
|
-
|
|
345
|
+
dispatcher: async (ctx, values) => {
|
|
346
|
+
const object = await this._getTracer().startActiveSpan("activitypub.dispatch_object", {
|
|
347
347
|
kind: _opentelemetry_api.SpanKind.SERVER,
|
|
348
348
|
attributes: {
|
|
349
349
|
"fedify.object.type": cls.typeId.href,
|
|
@@ -366,6 +366,8 @@ var FederationBuilderImpl = class {
|
|
|
366
366
|
span.end();
|
|
367
367
|
}
|
|
368
368
|
});
|
|
369
|
+
if (object instanceof _fedify_vocab.Tombstone) warnMismatchedTombstoneId(ctx, cls, values, object);
|
|
370
|
+
return object;
|
|
369
371
|
},
|
|
370
372
|
parameters: variables
|
|
371
373
|
};
|
|
@@ -735,6 +737,28 @@ var FederationBuilderImpl = class {
|
|
|
735
737
|
function createFederationBuilder() {
|
|
736
738
|
return new FederationBuilderImpl();
|
|
737
739
|
}
|
|
740
|
+
function warnMismatchedTombstoneId(context, cls, values, tombstone) {
|
|
741
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
742
|
+
"fedify",
|
|
743
|
+
"federation",
|
|
744
|
+
"object"
|
|
745
|
+
]);
|
|
746
|
+
if (tombstone.id == null) {
|
|
747
|
+
logger.warn("Object dispatcher for {class} returned a tombstone without an id property. Set the property with Context.getObjectUri().", {
|
|
748
|
+
class: cls.name,
|
|
749
|
+
values
|
|
750
|
+
});
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
if (tombstone.id.protocol === "ap:" || tombstone.id.protocol === "ap+ef61:") return;
|
|
754
|
+
const expected = context.getObjectUri(cls, values);
|
|
755
|
+
if (tombstone.id.href !== expected.href) logger.warn("Object dispatcher for {class} returned a tombstone with an id property {tombstoneId} that does not match the object URI {objectUri}. Set the property with Context.getObjectUri().", {
|
|
756
|
+
class: cls.name,
|
|
757
|
+
values,
|
|
758
|
+
tombstoneId: tombstone.id.href,
|
|
759
|
+
objectUri: expected.href
|
|
760
|
+
});
|
|
761
|
+
}
|
|
738
762
|
/**
|
|
739
763
|
* Warns about an FEP-ef61 portable actor identified by a compatible identifier
|
|
740
764
|
* that is malformed, or is not on the actor's first gateway, where FEP-ef61
|
|
@@ -2212,6 +2236,11 @@ async function routeActivity({ context: ctx, json, originalJson, normalizedActiv
|
|
|
2212
2236
|
//#region src/federation/keycache.ts
|
|
2213
2237
|
const Temporal$9 = require_http.Temporal;
|
|
2214
2238
|
const KEY_CACHE_GENERATION = "2";
|
|
2239
|
+
const COMPATIBLE_KEY_SEGMENT = "__compatible";
|
|
2240
|
+
const MAX_COMPATIBLE_KEY_TTL = Temporal$9.Duration.from({ hours: 1 });
|
|
2241
|
+
function isCompatibleKeyEntry(value) {
|
|
2242
|
+
return value != null && typeof value === "object" && "key" in value && "expires" in value && typeof value.expires === "number";
|
|
2243
|
+
}
|
|
2215
2244
|
var KvKeyCache = class {
|
|
2216
2245
|
kv;
|
|
2217
2246
|
prefix;
|
|
@@ -2274,6 +2303,69 @@ var KvKeyCache = class {
|
|
|
2274
2303
|
const serialized = await key.toJsonLd(this.options);
|
|
2275
2304
|
await this.kv.set(this.#entryKey(keyId), serialized, { ttl: this.keyTtl });
|
|
2276
2305
|
}
|
|
2306
|
+
/**
|
|
2307
|
+
* Returns the namespace of keys at FEP-ef61 compatible identifiers looked
|
|
2308
|
+
* up for the given purpose. Its entries carry the time they expire, which
|
|
2309
|
+
* is checked when they are read, so that an entry is never used after
|
|
2310
|
+
* the proof that vouched for its key expired, however late the underlying
|
|
2311
|
+
* store evicts it.
|
|
2312
|
+
* @param scope The purpose of the lookups.
|
|
2313
|
+
* @returns The namespace.
|
|
2314
|
+
* @internal
|
|
2315
|
+
*/
|
|
2316
|
+
compatibleKeyScope(scope) {
|
|
2317
|
+
const now = this.options.now ?? (() => Temporal$9.Now.instant());
|
|
2318
|
+
const entryKey = (keyId) => [
|
|
2319
|
+
...this.prefix,
|
|
2320
|
+
COMPATIBLE_KEY_SEGMENT,
|
|
2321
|
+
scope,
|
|
2322
|
+
keyId.href
|
|
2323
|
+
];
|
|
2324
|
+
const isExpired = (entry) => entry.expires <= now().epochMilliseconds;
|
|
2325
|
+
const keyTtl = Math.min(this.keyTtl.total("millisecond"), MAX_COMPATIBLE_KEY_TTL.total("millisecond"));
|
|
2326
|
+
const unavailableKeyTtl = this.unavailableKeyTtl.total("millisecond");
|
|
2327
|
+
return {
|
|
2328
|
+
get: async (keyId) => {
|
|
2329
|
+
const entry = await this.kv.get(entryKey(keyId));
|
|
2330
|
+
if (entry === void 0) return void 0;
|
|
2331
|
+
if (!isCompatibleKeyEntry(entry) || isExpired(entry)) {
|
|
2332
|
+
await this.kv.delete(entryKey(keyId));
|
|
2333
|
+
return;
|
|
2334
|
+
}
|
|
2335
|
+
if (entry.key === null) return null;
|
|
2336
|
+
let key;
|
|
2337
|
+
try {
|
|
2338
|
+
key = await _fedify_vocab.CryptographicKey.fromJsonLd(entry.key, this.options);
|
|
2339
|
+
} catch {
|
|
2340
|
+
try {
|
|
2341
|
+
key = await _fedify_vocab.Multikey.fromJsonLd(entry.key, this.options);
|
|
2342
|
+
} catch {
|
|
2343
|
+
await this.kv.delete(entryKey(keyId));
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
return isExpired(entry) ? void 0 : key;
|
|
2348
|
+
},
|
|
2349
|
+
set: async (keyId, key, options) => {
|
|
2350
|
+
const serialized = key == null ? null : await key.toJsonLd(this.options);
|
|
2351
|
+
const current = now();
|
|
2352
|
+
let expires = current.epochMilliseconds + (key == null ? unavailableKeyTtl : keyTtl);
|
|
2353
|
+
if (options?.expires != null) expires = Math.min(expires, options.expires.epochMilliseconds);
|
|
2354
|
+
const ttl = expires - current.epochMilliseconds;
|
|
2355
|
+
if (ttl <= 0) {
|
|
2356
|
+
await this.kv.delete(entryKey(keyId));
|
|
2357
|
+
return;
|
|
2358
|
+
}
|
|
2359
|
+
await this.kv.set(entryKey(keyId), {
|
|
2360
|
+
key: serialized,
|
|
2361
|
+
expires
|
|
2362
|
+
}, { ttl: Temporal$9.Duration.from({ milliseconds: ttl }) });
|
|
2363
|
+
},
|
|
2364
|
+
delete: async (keyId) => {
|
|
2365
|
+
await this.kv.delete(entryKey(keyId));
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
}
|
|
2277
2369
|
async getFetchError(keyId) {
|
|
2278
2370
|
const cached = await this.kv.get(this.#getFetchErrorKey(keyId));
|
|
2279
2371
|
if (cached == null || typeof cached !== "object") return void 0;
|
|
@@ -3427,6 +3519,13 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
3427
3519
|
if (!await authorizePredicate(context, values)) return await onUnauthorized(request);
|
|
3428
3520
|
}
|
|
3429
3521
|
const jsonLd = await object.toJsonLd(context);
|
|
3522
|
+
if (object instanceof _fedify_vocab.Tombstone) return new Response(request.method === "HEAD" ? null : JSON.stringify(jsonLd), {
|
|
3523
|
+
status: 410,
|
|
3524
|
+
headers: {
|
|
3525
|
+
"Content-Type": "application/activity+json",
|
|
3526
|
+
Vary: "Accept"
|
|
3527
|
+
}
|
|
3528
|
+
});
|
|
3430
3529
|
return new Response(JSON.stringify(jsonLd), { headers: {
|
|
3431
3530
|
"Content-Type": "application/activity+json",
|
|
3432
3531
|
Vary: "Accept"
|
|
@@ -3560,13 +3659,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
3560
3659
|
* @param parameters The parameters for handling the collection.
|
|
3561
3660
|
* @returns A promise that resolves to an HTTP response.
|
|
3562
3661
|
*/
|
|
3563
|
-
async function handleCollection(request, { name: name$
|
|
3564
|
-
const spanName = name$
|
|
3662
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
3663
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
3565
3664
|
tracerProvider = tracerProvider ?? _opentelemetry_api.trace.getTracerProvider();
|
|
3566
3665
|
const tracer = tracerProvider.getTracer(require_http.name, require_http.version);
|
|
3567
3666
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
3568
3667
|
const metricBase = {
|
|
3569
|
-
kind: getCollectionMetricKind(name$
|
|
3668
|
+
kind: getCollectionMetricKind(name$2),
|
|
3570
3669
|
page: cursor != null,
|
|
3571
3670
|
dispatcher: "built_in"
|
|
3572
3671
|
};
|
|
@@ -3607,7 +3706,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
3607
3706
|
span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
|
|
3608
3707
|
return await onNotFound(request);
|
|
3609
3708
|
}
|
|
3610
|
-
const items = filterCollectionItems(page.items, name$
|
|
3709
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
3611
3710
|
itemCount = items.length;
|
|
3612
3711
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
3613
3712
|
return items;
|
|
@@ -3647,7 +3746,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
3647
3746
|
} else {
|
|
3648
3747
|
const uri = new URL(baseUri);
|
|
3649
3748
|
uri.searchParams.set("cursor", cursor);
|
|
3650
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
3749
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
3651
3750
|
kind: _opentelemetry_api.SpanKind.SERVER,
|
|
3652
3751
|
attributes: {
|
|
3653
3752
|
"activitypub.collection.id": uri.href,
|
|
@@ -3663,7 +3762,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
3663
3762
|
span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
|
|
3664
3763
|
return await onNotFound(request);
|
|
3665
3764
|
}
|
|
3666
|
-
const items = filterCollectionItems(page.items, name$
|
|
3765
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
3667
3766
|
itemCount = items.length;
|
|
3668
3767
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
3669
3768
|
return {
|
|
@@ -4851,8 +4950,8 @@ var CustomCollectionHandler = class {
|
|
|
4851
4950
|
* @param CollectionPage The CollectionPage constructor.
|
|
4852
4951
|
* @param filterPredicate Optional filter predicate for items.
|
|
4853
4952
|
*/
|
|
4854
|
-
constructor(name$
|
|
4855
|
-
this.name = name$
|
|
4953
|
+
constructor(name$1, values, context, callbacks, tracerProvider = _opentelemetry_api.trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
|
|
4954
|
+
this.name = name$1;
|
|
4856
4955
|
this.values = values;
|
|
4857
4956
|
this.context = context;
|
|
4858
4957
|
this.callbacks = callbacks;
|
|
@@ -9341,7 +9440,7 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
9341
9440
|
if (actor instanceof _fedify_vocab.Tombstone && options?.tombstone !== "passthrough") return null;
|
|
9342
9441
|
return actor;
|
|
9343
9442
|
}
|
|
9344
|
-
async getObject(cls, values) {
|
|
9443
|
+
async getObject(cls, values, options) {
|
|
9345
9444
|
const callbacks = this.federation.objectCallbacks[cls.typeId.href];
|
|
9346
9445
|
if (callbacks == null) throw new Error("No object dispatcher registered.");
|
|
9347
9446
|
for (const param of callbacks.parameters) if (!(param in values)) throw new TypeError(`Missing parameter: ${param}`);
|
|
@@ -9351,13 +9450,15 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
9351
9450
|
actorDispatcherClass: this.#invokedFromObjectDispatcher.cls.name,
|
|
9352
9451
|
actorDispatcherValues: this.#invokedFromObjectDispatcher.values
|
|
9353
9452
|
});
|
|
9354
|
-
|
|
9453
|
+
const object = await callbacks.dispatcher(new RequestContextImpl({
|
|
9355
9454
|
...this,
|
|
9356
9455
|
invokedFromObjectDispatcher: {
|
|
9357
9456
|
cls,
|
|
9358
9457
|
values
|
|
9359
9458
|
}
|
|
9360
9459
|
}), values);
|
|
9460
|
+
if (object instanceof _fedify_vocab.Tombstone && !(object instanceof cls) && options?.tombstone !== "passthrough") return null;
|
|
9461
|
+
return object;
|
|
9361
9462
|
}
|
|
9362
9463
|
#signedKey = void 0;
|
|
9363
9464
|
async getSignedKey(options = {}) {
|