@fedify/fedify 2.4.0-dev.2054 → 2.4.0-dev.2056

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.
Files changed (75) hide show
  1. package/dist/{builder-C86Z3BKs.mjs → builder-D_XU_Fw2.mjs} +8 -2
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{compound-proof-BcZqTCwy.mjs → compound-proof-CwTySDnn.mjs} +1 -1
  6. package/dist/{context-BJPHhBmD.d.ts → context-D_gg4M0n.d.ts} +102 -1
  7. package/dist/{context-Bh_mJfbD.d.cts → context-b36TpPoG.d.cts} +102 -1
  8. package/dist/{deno-Bz6KTcon.mjs → deno-BtpLWN2L.mjs} +1 -1
  9. package/dist/{docloader-DS54zLD1.mjs → docloader-CJADEtqb.mjs} +2 -2
  10. package/dist/federation/builder.test.mjs +1 -1
  11. package/dist/federation/compound-fanout.test.mjs +3 -3
  12. package/dist/federation/handler-compound-proof.test.mjs +3 -3
  13. package/dist/federation/handler.test.mjs +5 -5
  14. package/dist/federation/hashlink-media.test.d.mts +2 -0
  15. package/dist/federation/hashlink-media.test.mjs +422 -0
  16. package/dist/federation/idempotency.test.mjs +2 -2
  17. package/dist/federation/metrics.test.mjs +1 -1
  18. package/dist/federation/middleware.test.mjs +7 -7
  19. package/dist/federation/mod.cjs +1 -1
  20. package/dist/federation/mod.d.cts +3 -3
  21. package/dist/federation/mod.d.ts +3 -3
  22. package/dist/federation/mod.js +1 -1
  23. package/dist/federation/outgoing-proof.test.mjs +5 -5
  24. package/dist/federation/portable.test.mjs +3 -3
  25. package/dist/federation/router.test.mjs +2 -152
  26. package/dist/federation/send.test.mjs +3 -3
  27. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  28. package/dist/federation/tasks/tasks.test.mjs +2 -2
  29. package/dist/federation/temporal.test.mjs +1 -1
  30. package/dist/federation/webfinger.test.mjs +1 -1
  31. package/dist/{federation-su1OEWsM.cjs → federation-DDwszIrk.cjs} +139 -21
  32. package/dist/{http-Ty805y3A.mjs → http-CotELN-4.mjs} +3 -3
  33. package/dist/{http-LmUsMjK_.cjs → http-DW5mt8FG.cjs} +1 -1
  34. package/dist/{http-C3WGK1dL.js → http-iLCx9vk-.js} +1 -1
  35. package/dist/{key-BMc-2eW0.mjs → key-DrCNkH3Y.mjs} +2 -2
  36. package/dist/{kv-cache-CuaZnk6r.cjs → kv-cache-LOyq_Ty6.cjs} +1 -1
  37. package/dist/{kv-cache-BhPPtHg7.mjs → kv-cache-a1ghEA4h.mjs} +1 -1
  38. package/dist/{kv-cache-BcHCmrC8.js → kv-cache-bXLDSaRu.js} +1 -1
  39. package/dist/{ld-OpXWt-80.mjs → ld-BPG92sC0.mjs} +3 -3
  40. package/dist/{metrics-CTAe8lYz.mjs → metrics-DxVi0UJD.mjs} +1 -1
  41. package/dist/{middleware-_CMav1o7.js → middleware-1nes8_U-.js} +140 -22
  42. package/dist/{middleware-C-JLcqy7.mjs → middleware-BIPftTly.mjs} +1 -1
  43. package/dist/{middleware-BtwW3G41.mjs → middleware-DohUu-Tz.mjs} +145 -33
  44. package/dist/{mod-DU8aVzQJ.d.cts → mod-Bfenkg_c.d.cts} +1 -1
  45. package/dist/{mod-BofpDIcU.d.ts → mod-BhMvsgdF.d.ts} +1 -1
  46. package/dist/mod.cjs +4 -4
  47. package/dist/mod.d.cts +4 -4
  48. package/dist/mod.d.ts +4 -4
  49. package/dist/mod.js +4 -4
  50. package/dist/nodeinfo/handler.test.mjs +1 -1
  51. package/dist/{owner-RxB_eQpU.mjs → owner-BN7Mqjso.mjs} +2 -2
  52. package/dist/{owner-Bcm4pLXw.cjs → owner-C2ER4VD7.cjs} +1 -1
  53. package/dist/{owner-B-TLr-1I.js → owner-SBgt2USF.js} +1 -1
  54. package/dist/{proof-CVf2XbEa.mjs → proof-BigVZwkl.mjs} +4 -4
  55. package/dist/router-u5O5KCQr.mjs +156 -0
  56. package/dist/{send-DF9KzhJH.mjs → send-CvatEhyY.mjs} +3 -3
  57. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  58. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  59. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  60. package/dist/sig/compound-proof.test.mjs +2 -2
  61. package/dist/sig/http.test.mjs +2 -2
  62. package/dist/sig/key.test.mjs +1 -1
  63. package/dist/sig/ld.test.mjs +2 -2
  64. package/dist/sig/mod.cjs +2 -2
  65. package/dist/sig/mod.js +2 -2
  66. package/dist/sig/owner.test.mjs +1 -1
  67. package/dist/sig/proof.test.mjs +3 -3
  68. package/dist/{temporal-B6U3fEUW.mjs → temporal-DV5jeBbR.mjs} +1 -1
  69. package/dist/testing/kv.test.mjs +1 -1
  70. package/dist/testing/mod.d.mts +101 -0
  71. package/dist/utils/docloader.test.mjs +2 -2
  72. package/dist/utils/kv-cache.test.mjs +1 -1
  73. package/dist/utils/mod.cjs +1 -1
  74. package/dist/utils/mod.js +1 -1
  75. package/package.json +6 -6
@@ -0,0 +1,422 @@
1
+ import "temporal-polyfill";
2
+ import "urlpattern-polyfill";
3
+ globalThis.addEventListener = () => {};
4
+ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
+ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
+ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
+ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
8
+ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
9
+ import "../std__assert-DvMDRPes.mjs";
10
+ import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
11
+ import { t as assert } from "../assert-D1Eafmd_.mjs";
12
+ import { r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
13
+ import { _ as parseHashlinkGatewayRequest, o as createFederation } from "../middleware-DohUu-Tz.mjs";
14
+ import { r as createFederationBuilder } from "../builder-D_XU_Fw2.mjs";
15
+ import { n as RouterError } from "../router-u5O5KCQr.mjs";
16
+ import { Note } from "@fedify/vocab";
17
+ import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
18
+ import { computeDigestMultibase, encodeMultibase, exportDidKey } from "@fedify/vocab-runtime";
19
+ //#region src/federation/hashlink-media.test.ts
20
+ const textDecoder = new TextDecoder();
21
+ const FEP_DIGEST = "zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n";
22
+ const mediaBytes = new TextEncoder().encode("Hello, portable world!");
23
+ const mediaDigest = await computeDigestMultibase(mediaBytes);
24
+ const mediaSha256 = new Uint8Array(await crypto.subtle.digest("SHA-256", mediaBytes));
25
+ const ffDigest = (/* @__PURE__ */ new Uint8Array(32)).fill(255);
26
+ const ffMultihash = new Uint8Array([
27
+ 18,
28
+ 32,
29
+ ...ffDigest
30
+ ]);
31
+ const ffBase64 = textDecoder.decode(encodeMultibase("base64", ffMultihash));
32
+ const ffBase58 = textDecoder.decode(encodeMultibase("base58btc", ffMultihash));
33
+ function mediaUrl(hashlink) {
34
+ return `https://example.com/.well-known/apgateway/${hashlink}`;
35
+ }
36
+ function parse(url) {
37
+ return parseHashlinkGatewayRequest(new URL(url));
38
+ }
39
+ function assertMedia(url) {
40
+ const result = parse(url);
41
+ assert(result != null, `${url} should be a hashlink media request`);
42
+ if (result.type !== "media") throw new Error(`${url} should not be malformed: ${result.error}`);
43
+ return result.media;
44
+ }
45
+ function assertMalformed(url) {
46
+ const result = parse(url);
47
+ assert(result != null, `${url} should be a hashlink media request`);
48
+ assertEquals(result.type, "malformed", url);
49
+ if (result.type === "malformed") assertInstanceOf(result.error, TypeError);
50
+ }
51
+ function createTestFederation() {
52
+ return createFederation({
53
+ kv: new MemoryKvStore(),
54
+ documentLoaderFactory: () => mockDocumentLoader,
55
+ contextLoaderFactory: () => mockDocumentLoader
56
+ });
57
+ }
58
+ test("parseHashlinkGatewayRequest()", async (t) => {
59
+ await t.step("parses a hashlink", () => {
60
+ const media = assertMedia(mediaUrl(`hl:${mediaDigest}`));
61
+ assertEquals(media.hashlink, `hl:${mediaDigest}`);
62
+ assertEquals(media.digestMultibase, mediaDigest);
63
+ assertEquals(media.algorithm, "sha2-256");
64
+ assertEquals(media.digest, mediaSha256);
65
+ assertEquals(media.multihash, new Uint8Array([
66
+ 18,
67
+ 32,
68
+ ...mediaSha256
69
+ ]));
70
+ assert(Object.isFrozen(media));
71
+ });
72
+ await t.step("parses the example of FEP-ef61", () => {
73
+ const media = assertMedia(mediaUrl(`hl:${FEP_DIGEST}`));
74
+ assertEquals(media.digestMultibase, FEP_DIGEST);
75
+ assertEquals(media.digest.length, 32);
76
+ });
77
+ await t.step("normalizes the scheme and percent-encoding", () => {
78
+ for (const hashlink of [`HL:${mediaDigest}`, `hl%3a${mediaDigest}`]) {
79
+ const media = assertMedia(mediaUrl(hashlink));
80
+ assertEquals(media.hashlink, `hl:${mediaDigest}`);
81
+ assertEquals(media.digestMultibase, mediaDigest);
82
+ }
83
+ });
84
+ await t.step("accepts slashes in a base64 digest", () => {
85
+ assert(ffBase64.includes("/"));
86
+ for (const hashlink of [`hl:${ffBase64}`, `hl:${ffBase64.replaceAll("/", "%2F")}`]) {
87
+ const media = assertMedia(mediaUrl(hashlink));
88
+ assertEquals(media.digestMultibase, ffBase64);
89
+ assertEquals(media.digest, ffDigest);
90
+ assertEquals(media.multihash, ffMultihash);
91
+ }
92
+ });
93
+ await t.step("keeps the requested multibase encoding", () => {
94
+ const base58 = assertMedia(mediaUrl(`hl:${ffBase58}`));
95
+ const base64 = assertMedia(mediaUrl(`hl:${ffBase64}`));
96
+ assertEquals(base58.digestMultibase, ffBase58);
97
+ assertEquals(base64.digestMultibase, ffBase64);
98
+ assertEquals(base58.digest, base64.digest);
99
+ assertEquals(base58.multihash, base64.multihash);
100
+ });
101
+ await t.step("ignores the query", () => {
102
+ assertEquals(assertMedia(mediaUrl(`hl:${mediaDigest}?v=1`)).digestMultibase, mediaDigest);
103
+ });
104
+ await t.step("returns fresh digest bytes", () => {
105
+ const a = assertMedia(mediaUrl(`hl:${mediaDigest}`));
106
+ const b = assertMedia(mediaUrl(`hl:${mediaDigest}`));
107
+ a.digest.fill(0);
108
+ a.multihash.fill(0);
109
+ assertEquals(b.digest, mediaSha256);
110
+ });
111
+ await t.step("ignores other URLs", async () => {
112
+ const did = await exportDidKey(ed25519PublicKey.publicKey);
113
+ for (const url of [
114
+ "https://example.com/.well-known/apgateway",
115
+ "https://example.com/.well-known/apgateway/",
116
+ `https://example.com/.well-known/apgateway/${did}/notes/1`,
117
+ `https://example.com/.WELL-KNOWN/apgateway/hl:${mediaDigest}`,
118
+ `https://example.com/.well-known/apgateway-media/hl:${mediaDigest}`,
119
+ `https://example.com/hl:${mediaDigest}`,
120
+ `https://example.com/.well-known/apgateway/x/hl:${mediaDigest}`,
121
+ `https://example.com/.well-known/apgateway/hlx${mediaDigest}`
122
+ ]) assertStrictEquals(parse(url), null, url);
123
+ });
124
+ await t.step("recognizes malformed hashlinks", () => {
125
+ const sha512 = textDecoder.decode(encodeMultibase("base58btc", new Uint8Array([
126
+ 19,
127
+ 64,
128
+ .../* @__PURE__ */ new Uint8Array(64)
129
+ ])));
130
+ const short = textDecoder.decode(encodeMultibase("base58btc", new Uint8Array([
131
+ 18,
132
+ 16,
133
+ .../* @__PURE__ */ new Uint8Array(16)
134
+ ])));
135
+ for (const hashlink of [
136
+ "hl:",
137
+ "hl:z",
138
+ "hl:zInvalid0OIl",
139
+ `hl:${sha512}`,
140
+ `hl:${short}`,
141
+ `hl:${mediaDigest}:zCwPSdabLuj3jue1qYujzunnKwpL4myKdyeqySyFhnzZ8qdfW3bb6W8dVdRu`,
142
+ `hl:${mediaDigest}/`,
143
+ `hl:${mediaDigest}/extra`,
144
+ `hl:${mediaDigest}%E0%A4%A`,
145
+ `hl:${mediaDigest}%0A`
146
+ ]) assertMalformed(mediaUrl(hashlink));
147
+ });
148
+ });
149
+ test("Federation.fetch() serves hashlink media", async (t) => {
150
+ await t.step("passes the parsed hashlink to the dispatcher", async () => {
151
+ const federation = createTestFederation();
152
+ const calls = [];
153
+ federation.setHashlinkMediaDispatcher((ctx, media) => {
154
+ calls.push([ctx, media]);
155
+ return new Response(mediaBytes, { headers: { "Content-Type": "text/plain" } });
156
+ });
157
+ const response = await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}?download=1`)), { contextData: void 0 });
158
+ assertEquals(response.status, 200);
159
+ assertEquals(response.headers.get("Content-Type"), "text/plain");
160
+ assertEquals(new Uint8Array(await response.arrayBuffer()), mediaBytes);
161
+ assertEquals(calls.length, 1);
162
+ const [ctx, media] = calls[0];
163
+ assertEquals(ctx.request.url, mediaUrl(`hl:${mediaDigest}?download=1`));
164
+ assertEquals(ctx.url.href, mediaUrl(`hl:${mediaDigest}?download=1`));
165
+ assertEquals(media.hashlink, `hl:${mediaDigest}`);
166
+ assertEquals(media.digestMultibase, mediaDigest);
167
+ assertEquals(media.algorithm, "sha2-256");
168
+ assertEquals(media.digest, mediaSha256);
169
+ });
170
+ await t.step("sends the response of the dispatcher as is", async () => {
171
+ const federation = createTestFederation();
172
+ let pulled = 0;
173
+ let dispatched;
174
+ federation.setHashlinkMediaDispatcher(() => {
175
+ const body = new ReadableStream({ pull(controller) {
176
+ pulled++;
177
+ controller.enqueue(mediaBytes.subarray(0, 4));
178
+ } }, { highWaterMark: 0 });
179
+ dispatched = new Response(body, {
180
+ status: 206,
181
+ statusText: "Partial Content",
182
+ headers: {
183
+ "Content-Type": "image/png",
184
+ "Content-Range": "bytes 0-3/22",
185
+ "Cache-Control": "public, max-age=31536000, immutable",
186
+ "Content-Disposition": "attachment",
187
+ ETag: `"${mediaDigest}"`,
188
+ "Accept-Ranges": "bytes"
189
+ }
190
+ });
191
+ return dispatched;
192
+ });
193
+ const response = await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { headers: { Range: "bytes=0-3" } }), { contextData: void 0 });
194
+ assertStrictEquals(response, dispatched);
195
+ assertEquals(pulled, 0);
196
+ assertEquals(response.status, 206);
197
+ assertEquals(response.statusText, "Partial Content");
198
+ assertEquals(response.headers.get("Content-Range"), "bytes 0-3/22");
199
+ assertEquals(response.headers.get("Cache-Control"), "public, max-age=31536000, immutable");
200
+ assertEquals(response.headers.get("Content-Disposition"), "attachment");
201
+ assertEquals(response.headers.get("ETag"), `"${mediaDigest}"`);
202
+ const reader = response.body.getReader();
203
+ assertEquals((await reader.read()).value, mediaBytes.subarray(0, 4));
204
+ await reader.cancel();
205
+ });
206
+ await t.step("does not touch the Vary header", async () => {
207
+ const federation = createTestFederation();
208
+ federation.setHashlinkMediaDispatcher(() => new Response(mediaBytes, { headers: { Vary: "Accept-Encoding" } }));
209
+ assertEquals((await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { headers: { Accept: "application/activity+json" } }), { contextData: void 0 })).headers.get("Vary"), "Accept-Encoding");
210
+ });
211
+ await t.step("sends responses with immutable headers", async () => {
212
+ const federation = createTestFederation();
213
+ federation.setHashlinkMediaDispatcher(() => Response.redirect("https://cdn.example/media.png", 302));
214
+ const response = await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { headers: { Accept: "application/activity+json" } }), { contextData: void 0 });
215
+ assertEquals(response.status, 302);
216
+ assertEquals(response.headers.get("Location"), "https://cdn.example/media.png");
217
+ });
218
+ await t.step("responds with 404 if the dispatcher returns null", async () => {
219
+ const federation = createTestFederation();
220
+ federation.setHashlinkMediaDispatcher(() => null);
221
+ assertEquals((await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`)), { contextData: void 0 })).status, 404);
222
+ const custom = await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`)), {
223
+ contextData: void 0,
224
+ onNotFound: () => new Response("Nope.", { status: 404 })
225
+ });
226
+ assertEquals(custom.status, 404);
227
+ assertEquals(await custom.text(), "Nope.");
228
+ });
229
+ await t.step("responds with 400 to malformed hashlinks", async () => {
230
+ const federation = createTestFederation();
231
+ let called = false;
232
+ federation.setHashlinkMediaDispatcher(() => {
233
+ called = true;
234
+ return new Response(mediaBytes);
235
+ });
236
+ for (const hashlink of [
237
+ "hl:zInvalid",
238
+ `hl:${mediaDigest}/`,
239
+ `hl:${mediaDigest}:z123`
240
+ ]) {
241
+ const response = await federation.fetch(new Request(mediaUrl(hashlink)), { contextData: void 0 });
242
+ assertEquals(response.status, 400, hashlink);
243
+ assertEquals(response.headers.get("Content-Type"), "text/plain; charset=utf-8");
244
+ }
245
+ assertFalse(called);
246
+ });
247
+ await t.step("responds with 405 to other methods", async () => {
248
+ const federation = createTestFederation();
249
+ let called = false;
250
+ federation.setHashlinkMediaDispatcher(() => {
251
+ called = true;
252
+ return new Response(mediaBytes);
253
+ });
254
+ for (const hashlink of [`hl:${mediaDigest}`, "hl:zInvalid"]) {
255
+ const response = await federation.fetch(new Request(mediaUrl(hashlink), {
256
+ method: "POST",
257
+ body: mediaBytes
258
+ }), { contextData: void 0 });
259
+ assertEquals(response.status, 405);
260
+ assertEquals(response.headers.get("Allow"), "GET, HEAD");
261
+ }
262
+ assertFalse(called);
263
+ });
264
+ await t.step("responds to HEAD requests without bodies", async () => {
265
+ const federation = createTestFederation();
266
+ let cancelled = false;
267
+ let method;
268
+ federation.setHashlinkMediaDispatcher((ctx) => {
269
+ method = ctx.request.method;
270
+ const body = new ReadableStream({
271
+ start(controller) {
272
+ controller.enqueue(mediaBytes);
273
+ },
274
+ cancel() {
275
+ cancelled = true;
276
+ }
277
+ });
278
+ return new Response(body, { headers: {
279
+ "Content-Type": "image/png",
280
+ "Content-Length": mediaBytes.length.toString()
281
+ } });
282
+ });
283
+ const response = await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { method: "HEAD" }), { contextData: void 0 });
284
+ assertEquals(method, "HEAD");
285
+ assertEquals(response.status, 200);
286
+ assertStrictEquals(response.body, null);
287
+ assert(cancelled);
288
+ assertEquals(response.headers.get("Content-Type"), "image/png");
289
+ assertEquals(response.headers.get("Content-Length"), mediaBytes.length.toString());
290
+ const malformed = await federation.fetch(new Request(mediaUrl("hl:zInvalid"), { method: "HEAD" }), { contextData: void 0 });
291
+ assertEquals(malformed.status, 400);
292
+ assertStrictEquals(malformed.body, null);
293
+ });
294
+ await t.step("does not wait for cancelling a cloned body", async () => {
295
+ const federation = createTestFederation();
296
+ const cached = new Response(mediaBytes, { headers: { "Content-Type": "image/png" } });
297
+ federation.setHashlinkMediaDispatcher(() => cached.clone());
298
+ let timer;
299
+ const response = await Promise.race([federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { method: "HEAD" }), { contextData: void 0 }), new Promise((resolve) => {
300
+ timer = setTimeout(() => resolve(null), 1e3);
301
+ })]);
302
+ clearTimeout(timer);
303
+ assert(response != null, "the HEAD response should not hang");
304
+ assertEquals(response.status, 200);
305
+ assertStrictEquals(response.body, null);
306
+ assertEquals(response.headers.get("Content-Type"), "image/png");
307
+ await cached.body.cancel();
308
+ });
309
+ await t.step("returns onNotFound responses as is", async () => {
310
+ const federation = createTestFederation();
311
+ federation.setHashlinkMediaDispatcher(() => null);
312
+ const notFound = new Response("", { status: 404 });
313
+ for (const method of ["GET", "HEAD"]) assertStrictEquals(await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { method }), {
314
+ contextData: void 0,
315
+ onNotFound: () => notFound
316
+ }), notFound, method);
317
+ });
318
+ await t.step("propagates errors thrown by the dispatcher", async () => {
319
+ const federation = createTestFederation();
320
+ const error = /* @__PURE__ */ new Error("Storage is down.");
321
+ federation.setHashlinkMediaDispatcher(() => {
322
+ throw error;
323
+ });
324
+ let thrown;
325
+ try {
326
+ await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`)), { contextData: void 0 });
327
+ } catch (e) {
328
+ thrown = e;
329
+ }
330
+ assertStrictEquals(thrown, error);
331
+ });
332
+ await t.step("records metrics", async () => {
333
+ const [meterProvider, recorder] = createTestMeterProvider();
334
+ const federation = createFederation({
335
+ kv: new MemoryKvStore(),
336
+ documentLoaderFactory: () => mockDocumentLoader,
337
+ contextLoaderFactory: () => mockDocumentLoader,
338
+ meterProvider
339
+ });
340
+ federation.setHashlinkMediaDispatcher(() => new Response(mediaBytes));
341
+ await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`)), { contextData: void 0 });
342
+ await federation.fetch(new Request(mediaUrl("hl:zInvalid")), { contextData: void 0 });
343
+ const counts = recorder.getMeasurements("fedify.http.server.request.count");
344
+ assertEquals(counts.length, 2);
345
+ for (const [count, status] of [[counts[0], 200], [counts[1], 400]]) {
346
+ assertEquals(count.attributes["fedify.endpoint"], "hashlink_media");
347
+ assertEquals(count.attributes["http.response.status_code"], status);
348
+ assertEquals(count.attributes["fedify.route.template"], "/.well-known/apgateway/hl:{digestMultibase}");
349
+ }
350
+ });
351
+ });
352
+ test("Federation.fetch() routes hashlink media apart from other routes", async (t) => {
353
+ const did = await exportDidKey(ed25519PublicKey.publicKey);
354
+ await t.step("responds with 404 without a dispatcher", async () => {
355
+ const federation = createTestFederation();
356
+ for (const method of ["GET", "POST"]) assertEquals((await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { method }), { contextData: void 0 })).status, 404, method);
357
+ assertEquals((await federation.fetch(new Request(mediaUrl("hl:zInvalid")), { contextData: void 0 })).status, 404);
358
+ });
359
+ await t.step("keeps portable objects apart from media", async () => {
360
+ const federation = createTestFederation();
361
+ const objectCalls = [];
362
+ let mediaCalled = false;
363
+ federation.setObjectDispatcher(Note, "/notes/{id}", (_ctx, values) => {
364
+ objectCalls.push(values);
365
+ return null;
366
+ });
367
+ federation.setHashlinkMediaDispatcher(() => {
368
+ mediaCalled = true;
369
+ return null;
370
+ });
371
+ assertEquals((await federation.fetch(new Request(`https://example.com/.well-known/apgateway/${did}/notes/1`, { headers: { Accept: "application/activity+json" } }), { contextData: void 0 })).status, 404);
372
+ assertEquals(objectCalls, [{ id: "1" }]);
373
+ assertFalse(mediaCalled);
374
+ await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { headers: { Accept: "application/activity+json" } }), { contextData: void 0 });
375
+ assert(mediaCalled);
376
+ assertEquals(objectCalls.length, 1);
377
+ });
378
+ await t.step("lets application routes shadow the gateway", async () => {
379
+ const federation = createTestFederation();
380
+ const objectCalls = [];
381
+ let mediaCalled = false;
382
+ federation.setObjectDispatcher(Note, "/.well-known/apgateway/{+id}", (_ctx, values) => {
383
+ objectCalls.push(values);
384
+ return null;
385
+ });
386
+ federation.setHashlinkMediaDispatcher(() => {
387
+ mediaCalled = true;
388
+ return new Response(mediaBytes);
389
+ });
390
+ assertEquals((await federation.fetch(new Request(mediaUrl(`hl:${mediaDigest}`), { headers: { Accept: "application/activity+json" } }), { contextData: void 0 })).status, 404);
391
+ assertEquals(objectCalls, [{ id: `hl:${mediaDigest}` }]);
392
+ assertFalse(mediaCalled);
393
+ });
394
+ await t.step("keeps unrelated paths not found", async () => {
395
+ const federation = createTestFederation();
396
+ let mediaCalled = false;
397
+ federation.setHashlinkMediaDispatcher(() => {
398
+ mediaCalled = true;
399
+ return new Response(mediaBytes);
400
+ });
401
+ for (const url of [
402
+ `https://example.com/hl:${mediaDigest}`,
403
+ "https://example.com/.well-known/apgateway",
404
+ `https://example.com/.well-known/apgateway-media/hl:${mediaDigest}`
405
+ ]) assertEquals((await federation.fetch(new Request(url), { contextData: void 0 })).status, 404, url);
406
+ assertFalse(mediaCalled);
407
+ });
408
+ });
409
+ test("FederationBuilder.setHashlinkMediaDispatcher()", async () => {
410
+ const builder = createFederationBuilder();
411
+ builder.setHashlinkMediaDispatcher(() => new Response(mediaBytes));
412
+ assertThrows(() => builder.setHashlinkMediaDispatcher(() => null), RouterError, "Hashlink media dispatcher already set.");
413
+ const response = await (await builder.build({
414
+ kv: new MemoryKvStore(),
415
+ documentLoaderFactory: () => mockDocumentLoader,
416
+ contextLoaderFactory: () => mockDocumentLoader
417
+ })).fetch(new Request(mediaUrl(`hl:${mediaDigest}`)), { contextData: void 0 });
418
+ assertEquals(response.status, 200);
419
+ assertEquals(new Uint8Array(await response.arrayBuffer()), mediaBytes);
420
+ });
421
+ //#endregion
422
+ export {};
@@ -5,8 +5,8 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import "../std__assert-DvMDRPes.mjs";
7
7
  import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
8
- import { o as createFederation } from "../middleware-BtwW3G41.mjs";
9
- import { r as signObject } from "../proof-CVf2XbEa.mjs";
8
+ import { o as createFederation } from "../middleware-DohUu-Tz.mjs";
9
+ import { r as signObject } from "../proof-BigVZwkl.mjs";
10
10
  import { Create, Follow, Person } from "@fedify/vocab";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/federation/idempotency.test.ts
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
5
5
  import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
7
- import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-CTAe8lYz.mjs";
7
+ import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-DxVi0UJD.mjs";
8
8
  import { createTestMeterProvider, test } from "@fedify/fixture";
9
9
  import { FetchError } from "@fedify/vocab-runtime";
10
10
  import { DataPointType, MeterProvider, MetricReader } from "@opentelemetry/sdk-metrics";
@@ -16,14 +16,14 @@ import "../std__assert-DvMDRPes.mjs";
16
16
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
17
17
  import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
18
18
  import { t as assert } from "../assert-D1Eafmd_.mjs";
19
- import { g as recordInboxActivity } from "../metrics-CTAe8lYz.mjs";
20
- import { l as verifyRequest, s as signRequest } from "../http-Ty805y3A.mjs";
19
+ import { g as recordInboxActivity } from "../metrics-DxVi0UJD.mjs";
20
+ import { l as verifyRequest, s as signRequest } from "../http-CotELN-4.mjs";
21
21
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
22
- import { t as getAuthenticatedDocumentLoader } from "../docloader-DS54zLD1.mjs";
23
- import { _ as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-BtwW3G41.mjs";
24
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-OpXWt-80.mjs";
25
- import { t as doesActorOwnKey } from "../owner-RxB_eQpU.mjs";
26
- import { a as verifyObject, r as signObject } from "../proof-CVf2XbEa.mjs";
22
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-CJADEtqb.mjs";
23
+ import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl, v as handleBenchmarkTrigger } from "../middleware-DohUu-Tz.mjs";
24
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-BPG92sC0.mjs";
25
+ import { t as doesActorOwnKey } from "../owner-BN7Mqjso.mjs";
26
+ import { a as verifyObject, r as signObject } from "../proof-BigVZwkl.mjs";
27
27
  import { t as CircuitBreaker } from "../circuit-breaker-C5NqoLBJ.mjs";
28
28
  import { t as TaskCodec } from "../codec-C6rTrpIp.mjs";
29
29
  import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-DW6YC_Pe.mjs";
@@ -1,6 +1,6 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_federation = require("../federation-su1OEWsM.cjs");
3
+ const require_federation = require("../federation-DDwszIrk.cjs");
4
4
  exports.CircuitBreaker = require_federation.CircuitBreaker;
5
5
  exports.InProcessMessageQueue = require_federation.InProcessMessageQueue;
6
6
  exports.MemoryKvStore = require_federation.MemoryKvStore;
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as MessageQueue, A as ObjectCallbackSetters, At as NodeInfoDispatcher, B as TaskDefinitionOptions, Bt as WebFingerLinksDispatcher, C as FederationOptions, Ct as CollectionDispatcher, D as InboxChallengePolicy, Dt as InboxErrorHandler, E as IdempotencyStrategy, Et as CustomCollectionDispatcher, F as FederationQueueOptions, Ft as OutboxListenerErrorHandler, G as RetryContext, Gt as digest, H as TaskHandler, Ht as SenderKeyPair, I as createFederation, It as OutboxPermanentFailureHandler, J as RespondWithObjectOptions, K as RetryPolicy, L as Message, Lt as SharedInboxKeyDispatcher, M as Rfc6570Expression, Mt as ObjectDispatcher, N as FederationKvPrefixes, Nt as OutboxErrorHandler, O as InboxListenerSetters, Ot as InboxListener, P as FederationOrigin, Pt as OutboxListener, Q as InProcessMessageQueueOptions, R as createFederationBuilder, Rt as UnverifiedActivityHandler, S as FederationFetchOptions, St as CollectionCursor, T as IdempotencyKeyCallback, Tt as CustomCollectionCursor, U as TaskRegistry, Ut as PageItems, V as TaskEnqueueOptions, Vt as SendActivityError, W as CreateExponentialBackoffPolicyOptions, Wt as buildCollectionSynchronizationHeader, X as respondWithObjectIfAcceptable, Y as respondWithObject, Z as InProcessMessageQueue, _ as CustomCollectionCallbackSetters, _t as ActorDispatcher, a as GetSignedKeyOptions, at as CircuitBreakerActivityDrop, b as FederationBenchmarkOptions, bt as AuthorizePredicate, c as ParseUriResult, ct as CircuitBreakerFailurePolicy, d as RouteActivityOptions, dt as CircuitBreakerState, et as MessageQueueDepth, f as SendActivityOptions, ft as CircuitBreakerStateChange, g as ConstructorWithTypeId, gt as ActorAliasMapper, h as CollectionCallbackSetters, ht as parseCircuitBreakerKvState, i as GetActorOptions, it as CircuitBreaker, j as OutboxListenerSetters, jt as ObjectAuthorizePredicate, k as MediaUploaderSetters, kt as MediaUploaderCallback, l as PortableRequest, lt as CircuitBreakerKvState, m as ActorCallbackSetters, mt as normalizeCircuitBreakerOptions, n as Context, nt as MessageQueueListenOptions, o as InboxContext, ot as CircuitBreakerBeforeSendDecision, p as SendActivityOptionsForCollection, pt as NormalizedCircuitBreakerOptions, q as createExponentialBackoffPolicy, r as ForwardActivityOptions, rt as ParallelMessageQueue, s as OutboxContext, st as CircuitBreakerCreateOptions, t as ActorKeyPair, tt as MessageQueueEnqueueOptions, u as RequestContext, ut as CircuitBreakerOptions, v as Federatable, vt as ActorHandleMapper, w as FederationStartQueueOptions, wt as CustomCollectionCounter, x as FederationBuilder, xt as CollectionCounter, y as Federation, yt as ActorKeyPairsDispatcher, z as TaskDefinition, zt as UnverifiedActivityReason } from "../context-Bh_mJfbD.cjs";
2
+ import { $ as MessageQueue, A as ObjectCallbackSetters, At as InboxListener, B as TaskDefinitionOptions, Bt as UnverifiedActivityHandler, C as FederationOptions, Ct as CollectionDispatcher, D as InboxChallengePolicy, Dt as HashlinkMediaDispatcher, E as IdempotencyStrategy, Et as CustomCollectionDispatcher, F as FederationQueueOptions, Ft as OutboxErrorHandler, G as RetryContext, Gt as PageItems, H as TaskHandler, Ht as WebFingerLinksDispatcher, I as createFederation, It as OutboxListener, J as RespondWithObjectOptions, K as RetryPolicy, Kt as buildCollectionSynchronizationHeader, L as Message, Lt as OutboxListenerErrorHandler, M as Rfc6570Expression, Mt as NodeInfoDispatcher, N as FederationKvPrefixes, Nt as ObjectAuthorizePredicate, O as InboxListenerSetters, Ot as HashlinkMediaRequest, P as FederationOrigin, Pt as ObjectDispatcher, Q as InProcessMessageQueueOptions, R as createFederationBuilder, Rt as OutboxPermanentFailureHandler, S as FederationFetchOptions, St as CollectionCursor, T as IdempotencyKeyCallback, Tt as CustomCollectionCursor, U as TaskRegistry, Ut as SendActivityError, V as TaskEnqueueOptions, Vt as UnverifiedActivityReason, W as CreateExponentialBackoffPolicyOptions, Wt as SenderKeyPair, X as respondWithObjectIfAcceptable, Y as respondWithObject, Z as InProcessMessageQueue, _ as CustomCollectionCallbackSetters, _t as ActorDispatcher, a as GetSignedKeyOptions, at as CircuitBreakerActivityDrop, b as FederationBenchmarkOptions, bt as AuthorizePredicate, c as ParseUriResult, ct as CircuitBreakerFailurePolicy, d as RouteActivityOptions, dt as CircuitBreakerState, et as MessageQueueDepth, f as SendActivityOptions, ft as CircuitBreakerStateChange, g as ConstructorWithTypeId, gt as ActorAliasMapper, h as CollectionCallbackSetters, ht as parseCircuitBreakerKvState, i as GetActorOptions, it as CircuitBreaker, j as OutboxListenerSetters, jt as MediaUploaderCallback, k as MediaUploaderSetters, kt as InboxErrorHandler, l as PortableRequest, lt as CircuitBreakerKvState, m as ActorCallbackSetters, mt as normalizeCircuitBreakerOptions, n as Context, nt as MessageQueueListenOptions, o as InboxContext, ot as CircuitBreakerBeforeSendDecision, p as SendActivityOptionsForCollection, pt as NormalizedCircuitBreakerOptions, q as createExponentialBackoffPolicy, qt as digest, r as ForwardActivityOptions, rt as ParallelMessageQueue, s as OutboxContext, st as CircuitBreakerCreateOptions, t as ActorKeyPair, tt as MessageQueueEnqueueOptions, u as RequestContext, ut as CircuitBreakerOptions, v as Federatable, vt as ActorHandleMapper, w as FederationStartQueueOptions, wt as CustomCollectionCounter, x as FederationBuilder, xt as CollectionCounter, y as Federation, yt as ActorKeyPairsDispatcher, z as TaskDefinition, zt as SharedInboxKeyDispatcher } from "../context-b36TpPoG.cjs";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-BhNbN8Ed.cjs";
4
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-DU8aVzQJ.cjs";
5
- export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
4
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-Bfenkg_c.cjs";
5
+ export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, HashlinkMediaDispatcher, HashlinkMediaRequest, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as MessageQueue, A as ObjectCallbackSetters, At as NodeInfoDispatcher, B as TaskDefinitionOptions, Bt as WebFingerLinksDispatcher, C as FederationOptions, Ct as CollectionDispatcher, D as InboxChallengePolicy, Dt as InboxErrorHandler, E as IdempotencyStrategy, Et as CustomCollectionDispatcher, F as FederationQueueOptions, Ft as OutboxListenerErrorHandler, G as RetryContext, Gt as digest, H as TaskHandler, Ht as SenderKeyPair, I as createFederation, It as OutboxPermanentFailureHandler, J as RespondWithObjectOptions, K as RetryPolicy, L as Message, Lt as SharedInboxKeyDispatcher, M as Rfc6570Expression, Mt as ObjectDispatcher, N as FederationKvPrefixes, Nt as OutboxErrorHandler, O as InboxListenerSetters, Ot as InboxListener, P as FederationOrigin, Pt as OutboxListener, Q as InProcessMessageQueueOptions, R as createFederationBuilder, Rt as UnverifiedActivityHandler, S as FederationFetchOptions, St as CollectionCursor, T as IdempotencyKeyCallback, Tt as CustomCollectionCursor, U as TaskRegistry, Ut as PageItems, V as TaskEnqueueOptions, Vt as SendActivityError, W as CreateExponentialBackoffPolicyOptions, Wt as buildCollectionSynchronizationHeader, X as respondWithObjectIfAcceptable, Y as respondWithObject, Z as InProcessMessageQueue, _ as CustomCollectionCallbackSetters, _t as ActorDispatcher, a as GetSignedKeyOptions, at as CircuitBreakerActivityDrop, b as FederationBenchmarkOptions, bt as AuthorizePredicate, c as ParseUriResult, ct as CircuitBreakerFailurePolicy, d as RouteActivityOptions, dt as CircuitBreakerState, et as MessageQueueDepth, f as SendActivityOptions, ft as CircuitBreakerStateChange, g as ConstructorWithTypeId, gt as ActorAliasMapper, h as CollectionCallbackSetters, ht as parseCircuitBreakerKvState, i as GetActorOptions, it as CircuitBreaker, j as OutboxListenerSetters, jt as ObjectAuthorizePredicate, k as MediaUploaderSetters, kt as MediaUploaderCallback, l as PortableRequest, lt as CircuitBreakerKvState, m as ActorCallbackSetters, mt as normalizeCircuitBreakerOptions, n as Context, nt as MessageQueueListenOptions, o as InboxContext, ot as CircuitBreakerBeforeSendDecision, p as SendActivityOptionsForCollection, pt as NormalizedCircuitBreakerOptions, q as createExponentialBackoffPolicy, r as ForwardActivityOptions, rt as ParallelMessageQueue, s as OutboxContext, st as CircuitBreakerCreateOptions, t as ActorKeyPair, tt as MessageQueueEnqueueOptions, u as RequestContext, ut as CircuitBreakerOptions, v as Federatable, vt as ActorHandleMapper, w as FederationStartQueueOptions, wt as CustomCollectionCounter, x as FederationBuilder, xt as CollectionCounter, y as Federation, yt as ActorKeyPairsDispatcher, z as TaskDefinition, zt as UnverifiedActivityReason } from "../context-BJPHhBmD.js";
2
+ import { $ as MessageQueue, A as ObjectCallbackSetters, At as InboxListener, B as TaskDefinitionOptions, Bt as UnverifiedActivityHandler, C as FederationOptions, Ct as CollectionDispatcher, D as InboxChallengePolicy, Dt as HashlinkMediaDispatcher, E as IdempotencyStrategy, Et as CustomCollectionDispatcher, F as FederationQueueOptions, Ft as OutboxErrorHandler, G as RetryContext, Gt as PageItems, H as TaskHandler, Ht as WebFingerLinksDispatcher, I as createFederation, It as OutboxListener, J as RespondWithObjectOptions, K as RetryPolicy, Kt as buildCollectionSynchronizationHeader, L as Message, Lt as OutboxListenerErrorHandler, M as Rfc6570Expression, Mt as NodeInfoDispatcher, N as FederationKvPrefixes, Nt as ObjectAuthorizePredicate, O as InboxListenerSetters, Ot as HashlinkMediaRequest, P as FederationOrigin, Pt as ObjectDispatcher, Q as InProcessMessageQueueOptions, R as createFederationBuilder, Rt as OutboxPermanentFailureHandler, S as FederationFetchOptions, St as CollectionCursor, T as IdempotencyKeyCallback, Tt as CustomCollectionCursor, U as TaskRegistry, Ut as SendActivityError, V as TaskEnqueueOptions, Vt as UnverifiedActivityReason, W as CreateExponentialBackoffPolicyOptions, Wt as SenderKeyPair, X as respondWithObjectIfAcceptable, Y as respondWithObject, Z as InProcessMessageQueue, _ as CustomCollectionCallbackSetters, _t as ActorDispatcher, a as GetSignedKeyOptions, at as CircuitBreakerActivityDrop, b as FederationBenchmarkOptions, bt as AuthorizePredicate, c as ParseUriResult, ct as CircuitBreakerFailurePolicy, d as RouteActivityOptions, dt as CircuitBreakerState, et as MessageQueueDepth, f as SendActivityOptions, ft as CircuitBreakerStateChange, g as ConstructorWithTypeId, gt as ActorAliasMapper, h as CollectionCallbackSetters, ht as parseCircuitBreakerKvState, i as GetActorOptions, it as CircuitBreaker, j as OutboxListenerSetters, jt as MediaUploaderCallback, k as MediaUploaderSetters, kt as InboxErrorHandler, l as PortableRequest, lt as CircuitBreakerKvState, m as ActorCallbackSetters, mt as normalizeCircuitBreakerOptions, n as Context, nt as MessageQueueListenOptions, o as InboxContext, ot as CircuitBreakerBeforeSendDecision, p as SendActivityOptionsForCollection, pt as NormalizedCircuitBreakerOptions, q as createExponentialBackoffPolicy, qt as digest, r as ForwardActivityOptions, rt as ParallelMessageQueue, s as OutboxContext, st as CircuitBreakerCreateOptions, t as ActorKeyPair, tt as MessageQueueEnqueueOptions, u as RequestContext, ut as CircuitBreakerOptions, v as Federatable, vt as ActorHandleMapper, w as FederationStartQueueOptions, wt as CustomCollectionCounter, x as FederationBuilder, xt as CollectionCounter, y as Federation, yt as ActorKeyPairsDispatcher, z as TaskDefinition, zt as SharedInboxKeyDispatcher } from "../context-D_gg4M0n.js";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-BhNbN8Ed.js";
4
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-BofpDIcU.js";
5
- export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
4
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-BhMvsgdF.js";
5
+ export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, HashlinkMediaDispatcher, HashlinkMediaRequest, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-_CMav1o7.js";
3
+ import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-1nes8_U-.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Router as Router$1, RouterError as RouterError$1, assertPath, isPath } from "@fedify/uri-template";
6
6
  import { isEqual } from "es-toolkit";
@@ -7,12 +7,12 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
8
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { t as exportJwk } from "../key-BMc-2eW0.mjs";
10
+ import { t as exportJwk } from "../key-DrCNkH3Y.mjs";
11
11
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
12
- import { n as FederationImpl, o as createFederation } from "../middleware-BtwW3G41.mjs";
13
- import { s as detachSignature } from "../ld-OpXWt-80.mjs";
14
- import { r as signObject } from "../proof-CVf2XbEa.mjs";
15
- import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-BcZqTCwy.mjs";
12
+ import { n as FederationImpl, o as createFederation } from "../middleware-DohUu-Tz.mjs";
13
+ import { s as detachSignature } from "../ld-BPG92sC0.mjs";
14
+ import { r as signObject } from "../proof-BigVZwkl.mjs";
15
+ import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-CwTySDnn.mjs";
16
16
  import { Create, Note, Person } from "@fedify/vocab";
17
17
  import { mockDocumentLoader, test } from "@fedify/fixture";
18
18
  import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
@@ -7,10 +7,10 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
7
7
  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
- import { s as signRequest } from "../http-Ty805y3A.mjs";
10
+ import { s as signRequest } from "../http-CotELN-4.mjs";
11
11
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
12
- import { g as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-BtwW3G41.mjs";
13
- import { o as verifyPortableObjectProof, r as signObject } from "../proof-CVf2XbEa.mjs";
12
+ import { g as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DohUu-Tz.mjs";
13
+ import { o as verifyPortableObjectProof, r as signObject } from "../proof-BigVZwkl.mjs";
14
14
  import { Collection, Create, Note, Object as Object$1, Person, Tombstone, lookupObject } from "@fedify/vocab";
15
15
  import { mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { exportDidKey, formatIri, parseIri } from "@fedify/vocab-runtime";