@fedify/fedify 2.2.19 → 2.2.20

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 (84) hide show
  1. package/dist/{builder-UmydCxtK.mjs → builder-BolQ56ab.mjs} +2 -2
  2. package/dist/{client-CAM_bQXx.d.cts → client-BIBzqEIp.d.cts} +0 -1
  3. package/dist/{client-9F_u23dc.mjs → client-DhxaVgOv.mjs} +113 -64
  4. package/dist/{client-CSddvgWN.d.ts → client-jE7oGvRh.d.ts} +0 -1
  5. package/dist/compat/mod.d.cts +1 -1
  6. package/dist/compat/mod.d.ts +1 -1
  7. package/dist/compat/transformers.test.mjs +1 -1
  8. package/dist/{context-tJbL_Hkw.d.cts → context-CFQGaq5x.d.cts} +28 -2
  9. package/dist/{context-OkwEpc3-.d.ts → context-DdbLVV_k.d.ts} +28 -2
  10. package/dist/{deno-CD-8UlUi.mjs → deno-BUj4roJc.mjs} +1 -1
  11. package/dist/docloader-CbtF_0cD.mjs +125 -0
  12. package/dist/federation/builder.test.mjs +1 -1
  13. package/dist/federation/handler.test.mjs +5 -5
  14. package/dist/federation/idempotency.test.mjs +2 -2
  15. package/dist/federation/inbox.test.mjs +1 -1
  16. package/dist/federation/middleware.test.mjs +389 -28
  17. package/dist/federation/mod.cjs +1 -1
  18. package/dist/federation/mod.d.cts +2 -2
  19. package/dist/federation/mod.d.ts +2 -2
  20. package/dist/federation/mod.js +1 -1
  21. package/dist/federation/send.test.mjs +445 -70
  22. package/dist/federation/temporal.test.mjs +1 -1
  23. package/dist/federation/webfinger.test.mjs +1 -1
  24. package/dist/{http-Dl00HXr4.d.ts → http-9IFUxdkp.d.cts} +1 -2
  25. package/dist/{http-DJK2udgX.js → http-C5g_VrA_.js} +172 -103
  26. package/dist/{http-BBBUbwKh.mjs → http-CQMVisM0.mjs} +195 -97
  27. package/dist/{http-DrUG4fPS.cjs → http-D8I7LBfx.cjs} +173 -104
  28. package/dist/{http-DqZhyEso.d.cts → http-SbfezERn.d.ts} +1 -2
  29. package/dist/{inbox-Dca_0fwc.mjs → inbox-CD8IDILN.mjs} +1 -1
  30. package/dist/{key-DolXUaLH.mjs → key-C3o3DGap.mjs} +1 -1
  31. package/dist/{kv-cache-DDm80t1K.js → kv-cache-CSKXXleR.js} +60 -18
  32. package/dist/{kv-cache-Bk3V1Tiu.cjs → kv-cache-DC9LcfoC.cjs} +59 -17
  33. package/dist/{ld-rTdIfZ63.mjs → ld-ijSr-0AB.mjs} +2 -2
  34. package/dist/{middleware-CpXoRHs3.mjs → middleware-CYAaUTi5.mjs} +78 -38
  35. package/dist/{middleware-BWOwEGpy.cjs → middleware-DNueR0GD.cjs} +184 -59
  36. package/dist/{middleware-B4-Rzdi3.cjs → middleware-DmcY2TWS.cjs} +1 -1
  37. package/dist/{middleware-BimXKBcP.js → middleware-sjhz30sm.js} +184 -59
  38. package/dist/{middleware-DYK_res8.mjs → middleware-yqqfI7oJ.mjs} +1 -1
  39. package/dist/{mod-B6LmugJ4.d.ts → mod-BRnwh2oy.d.ts} +2 -8
  40. package/dist/{mod-D2JyWtW3.d.cts → mod-BYWp77-z.d.cts} +1 -1
  41. package/dist/{mod-DQGjRJUG.d.ts → mod-BuRRdsfD.d.ts} +1 -1
  42. package/dist/{mod-ej_rLx8h.d.ts → mod-CM5_J_cx.d.ts} +1 -1
  43. package/dist/{mod-a6kmB8xD.d.cts → mod-CVSKw-5H.d.cts} +1 -1
  44. package/dist/{mod-V2vDnYNu.d.cts → mod-Co7LEK9X.d.cts} +2 -8
  45. package/dist/mod.cjs +5 -5
  46. package/dist/mod.d.cts +6 -6
  47. package/dist/mod.d.ts +6 -6
  48. package/dist/mod.js +5 -5
  49. package/dist/nodeinfo/client.test.mjs +337 -19
  50. package/dist/nodeinfo/handler.test.mjs +1 -1
  51. package/dist/nodeinfo/mod.cjs +1 -1
  52. package/dist/nodeinfo/mod.d.cts +1 -1
  53. package/dist/nodeinfo/mod.d.ts +1 -1
  54. package/dist/nodeinfo/mod.js +1 -1
  55. package/dist/otel/exporter.test.mjs +292 -30
  56. package/dist/otel/mod.cjs +36 -30
  57. package/dist/otel/mod.d.cts +13 -0
  58. package/dist/otel/mod.d.ts +13 -0
  59. package/dist/otel/mod.js +36 -30
  60. package/dist/{owner-CVfzyM5V.mjs → owner-B8kXzD0q.mjs} +2 -2
  61. package/dist/{proof-gOGM-sJS.mjs → proof-CBQOjOgA.mjs} +2 -2
  62. package/dist/{proof-CaQ4KG6y.js → proof-DKX6nASL.js} +1 -1
  63. package/dist/{proof-DhaTTn-P.cjs → proof-qiuGJCD7.cjs} +1 -1
  64. package/dist/{send-D35Va72B.mjs → send-DRpisX_f.mjs} +117 -32
  65. package/dist/sig/http.test.mjs +528 -2
  66. package/dist/sig/key.test.mjs +2 -2
  67. package/dist/sig/ld.test.mjs +2 -2
  68. package/dist/sig/mod.cjs +2 -2
  69. package/dist/sig/mod.d.cts +2 -2
  70. package/dist/sig/mod.d.ts +2 -2
  71. package/dist/sig/mod.js +2 -2
  72. package/dist/sig/owner.test.mjs +1 -1
  73. package/dist/sig/proof.test.mjs +1 -1
  74. package/dist/{temporal-CA4Y9hBJ.mjs → temporal-BQGEINad.mjs} +1 -1
  75. package/dist/testing/mod.d.mts +26 -1
  76. package/dist/{types-miAYfiGO.js → types-B1_pRFE_.js} +112 -63
  77. package/dist/{types-DRPjmHVV.cjs → types-DOvyymM4.cjs} +111 -62
  78. package/dist/utils/docloader.test.mjs +318 -34
  79. package/dist/utils/mod.cjs +1 -1
  80. package/dist/utils/mod.d.cts +1 -1
  81. package/dist/utils/mod.d.ts +1 -1
  82. package/dist/utils/mod.js +1 -1
  83. package/package.json +6 -6
  84. package/dist/docloader-D1ghurDJ.mjs +0 -83
@@ -10,21 +10,21 @@ import { n as assertInstanceOf, t as assert } from "../assert-BhQd8QHP.mjs";
10
10
  import { t as assertNotEquals } from "../assert_not_equals-BkxW5QJI.mjs";
11
11
  import { t as assertRejects } from "../assert_rejects-WyYSTDDX.mjs";
12
12
  import { t as assertStrictEquals } from "../assert_strict_equals-Dmjbg-bA.mjs";
13
- import { l as verifyRequest, s as signRequest } from "../http-BBBUbwKh.mjs";
13
+ import { c as signRequest, u as verifyRequest } from "../http-CQMVisM0.mjs";
14
14
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
15
- import { t as getAuthenticatedDocumentLoader } from "../docloader-D1ghurDJ.mjs";
15
+ import { n as getAuthenticatedDocumentLoader } from "../docloader-CbtF_0cD.mjs";
16
16
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
17
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-rTdIfZ63.mjs";
18
- import { t as doesActorOwnKey } from "../owner-CVfzyM5V.mjs";
19
- import { i as verifyObject, r as signObject } from "../proof-gOGM-sJS.mjs";
20
- import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-CpXoRHs3.mjs";
17
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-ijSr-0AB.mjs";
18
+ import { t as doesActorOwnKey } from "../owner-B8kXzD0q.mjs";
19
+ import { i as verifyObject, r as signObject } from "../proof-CBQOjOgA.mjs";
20
+ import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-CYAaUTi5.mjs";
21
21
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
22
22
  import * as vocab from "@fedify/vocab";
23
23
  import { Create, Offer, Person, getTypeId, lookupObject } from "@fedify/vocab";
24
24
  import { FetchError, UrlError, getDocumentLoader } from "@fedify/vocab-runtime";
25
25
  import { configure, reset } from "@logtape/logtape";
26
- import dns from "node:dns/promises";
27
26
  import serialize from "json-canon";
27
+ import dns from "node:dns/promises";
28
28
  //#region ../fixture/src/fixtures/example.com/create.json
29
29
  var id$2 = "https://example.com/create";
30
30
  var create_default = {
@@ -89,7 +89,7 @@ var person2_default = {
89
89
  };
90
90
  //#endregion
91
91
  //#region src/federation/middleware.test.ts
92
- const documentLoader = getDocumentLoader();
92
+ const documentLoader = getDocumentLoader({ allowPrivateAddress: true });
93
93
  let logtapeLock = Promise.resolve();
94
94
  async function withLogtapeLock(fn) {
95
95
  const run = logtapeLock.then(fn, fn);
@@ -225,7 +225,8 @@ test({
225
225
  const federation = createFederation({
226
226
  kv,
227
227
  documentLoaderFactory: () => rejectingLoader,
228
- contextLoaderFactory: () => mockDocumentLoader
228
+ contextLoaderFactory: () => mockDocumentLoader,
229
+ authenticatedDocumentLoaderFactory: (identity) => getAuthenticatedDocumentLoader(identity, { allowPrivateAddress: true })
229
230
  });
230
231
  let ctx = federation.createContext(new URL("https://example.com:1234/"), 123);
231
232
  assertEquals(ctx.data, 123);
@@ -330,7 +331,7 @@ test({
330
331
  documentUrl: "https://example.com/auth-check",
331
332
  document: true
332
333
  });
333
- assertEquals(await ctx.lookupObject("https://example.com/object"), null);
334
+ assertEquals(await withDnsLookup(() => Promise.reject(/* @__PURE__ */ new Error("Resolver unavailable")), () => ctx.lookupObject("https://example.com/object")), null);
334
335
  await assertRejects(() => ctx.sendActivity({ identifier: "handle" }, [], new vocab.Create({})), TypeError, "The activity to send must have at least one actor property.");
335
336
  await ctx.sendActivity({ identifier: "handle" }, [], new vocab.Create({ actor: new URL("https://example.com/users/handle") }));
336
337
  esm_default.get("https://example.com/object", () => new Response(JSON.stringify({
@@ -579,7 +580,7 @@ test({
579
580
  assertStrictEquals(clone.contextLoader, ctx.contextLoader);
580
581
  assertStrictEquals(clone.federation, ctx.federation);
581
582
  });
582
- esm_default.get("https://example.com/.well-known/nodeinfo", (cl) => {
583
+ esm_default.get("path:/.well-known/nodeinfo", (cl) => {
583
584
  const headers = cl.options.headers ?? {};
584
585
  assertEquals(new Headers(headers).get("User-Agent"), "CustomUserAgent/1.2.3");
585
586
  return new Response(JSON.stringify({ links: [{
@@ -587,7 +588,7 @@ test({
587
588
  href: "https://example.com/nodeinfo/2.1"
588
589
  }] }));
589
590
  });
590
- esm_default.get("https://example.com/nodeinfo/2.1", (cl) => {
591
+ esm_default.get("path:/nodeinfo/2.1", (cl) => {
591
592
  const headers = cl.options.headers ?? {};
592
593
  assertEquals(new Headers(headers).get("User-Agent"), "CustomUserAgent/1.2.3");
593
594
  return new Response(JSON.stringify({
@@ -608,7 +609,11 @@ test({
608
609
  kv,
609
610
  userAgent: "CustomUserAgent/1.2.3"
610
611
  }).createContext(new URL("https://example.com/"), 123);
611
- assertEquals(await ctx.lookupNodeInfo("https://example.com/"), {
612
+ const lookupExample = () => Promise.resolve([{
613
+ address: "93.184.215.14",
614
+ family: 4
615
+ }]);
616
+ assertEquals(await withDnsLookup(lookupExample, () => ctx.lookupNodeInfo("https://example.com/")), {
612
617
  software: {
613
618
  name: "foo",
614
619
  version: "1.2.3"
@@ -620,7 +625,7 @@ test({
620
625
  localComments: 456
621
626
  }
622
627
  });
623
- assertEquals(await ctx.lookupNodeInfo("https://example.com/", { parse: "none" }), {
628
+ assertEquals(await withDnsLookup(lookupExample, () => ctx.lookupNodeInfo("https://example.com/", { parse: "none" })), {
624
629
  software: {
625
630
  name: "foo",
626
631
  version: "1.2.3"
@@ -739,6 +744,343 @@ test({
739
744
  esm_default.hardReset();
740
745
  }
741
746
  });
747
+ test("RequestContext signature checks", async (t) => {
748
+ const [tracerProvider, exporter] = createTestTracerProvider();
749
+ const keyId = rsaPublicKey3.id.href;
750
+ const ownerId = rsaPublicKey3.ownerId.href;
751
+ const request = await signRequest(new Request("https://example.com/"), rsaPrivateKey3, rsaPublicKey3.id);
752
+ function setup(options = {}) {
753
+ const loads = {
754
+ key: 0,
755
+ owner: 0
756
+ };
757
+ const loader = async (url, loaderOptions) => {
758
+ if (url === keyId) loads.key++;
759
+ else if (url === ownerId) loads.owner++;
760
+ await options.gate;
761
+ return await (options.load ?? mockDocumentLoader)(url, loaderOptions);
762
+ };
763
+ const federation = createFederation({
764
+ kv: new MemoryKvStore(),
765
+ documentLoaderFactory: () => loader,
766
+ contextLoaderFactory: () => mockDocumentLoader,
767
+ tracerProvider: options.tracerProvider ?? tracerProvider
768
+ });
769
+ return {
770
+ ctx: federation.createContext(options.request ?? new Request(request), void 0),
771
+ loads,
772
+ loader,
773
+ federation
774
+ };
775
+ }
776
+ try {
777
+ for (const mode of [
778
+ "keys",
779
+ "owners",
780
+ "warm owners",
781
+ "mixed"
782
+ ]) await t.step(`coalesces ${mode}`, async () => {
783
+ exporter.clear();
784
+ let release;
785
+ const { ctx, loads, loader } = setup({ gate: new Promise((resolve) => release = resolve) });
786
+ if (mode === "warm owners") {
787
+ release();
788
+ assert(await ctx.getSignedKey());
789
+ }
790
+ const results = Promise.all(Array.from({ length: 8 }, (_, i) => {
791
+ const options = i % 2 === 0 ? {} : {
792
+ documentLoader: loader,
793
+ contextLoader: ctx.contextLoader,
794
+ tracerProvider
795
+ };
796
+ return mode === "keys" || mode === "mixed" && i % 2 === 0 ? ctx.getSignedKey(options) : ctx.getSignedKeyOwner(options);
797
+ }));
798
+ release();
799
+ for (const result of await results) assert(result != null);
800
+ assertEquals(loads, {
801
+ key: 1,
802
+ owner: mode === "keys" ? 0 : 1
803
+ });
804
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 1);
805
+ assert(await ctx.getSignedKey());
806
+ if (mode !== "keys") assert(await ctx.getSignedKeyOwner());
807
+ assertEquals(loads, {
808
+ key: 1,
809
+ owner: mode === "keys" ? 0 : 1
810
+ });
811
+ });
812
+ await t.step("memoizes null keys", async () => {
813
+ exporter.clear();
814
+ const { ctx, loads } = setup({ load: () => Promise.reject(/* @__PURE__ */ new Error("unavailable")) });
815
+ for (let i = 0; i < 3; i++) {
816
+ assertEquals(await ctx.getSignedKey(), null);
817
+ assertEquals(await ctx.getSignedKeyOwner(), null);
818
+ }
819
+ assertEquals(loads, {
820
+ key: 1,
821
+ owner: 0
822
+ });
823
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 1);
824
+ assert(await ctx.getSignedKey({ documentLoader: mockDocumentLoader }));
825
+ assert(await ctx.getSignedKeyOwner({ documentLoader: mockDocumentLoader }));
826
+ });
827
+ await t.step("coalesces key-owner FetchError results", async () => {
828
+ const { ctx, loads } = setup({ load: async (url, options) => {
829
+ if (url === ownerId) throw new FetchError(new URL(url), "HTTP 401: Unauthorized");
830
+ return await mockDocumentLoader(url, options);
831
+ } });
832
+ assert(await ctx.getSignedKey());
833
+ assertEquals(await Promise.all(Array.from({ length: 8 }, () => ctx.getSignedKeyOwner())), Array(8).fill(null));
834
+ assertEquals(await ctx.getSignedKeyOwner(), null);
835
+ assertEquals(loads, {
836
+ key: 1,
837
+ owner: 1
838
+ });
839
+ assert(await ctx.getSignedKeyOwner({ documentLoader: mockDocumentLoader }));
840
+ });
841
+ await t.step("memoizes unsigned requests", async () => {
842
+ exporter.clear();
843
+ const { ctx, loads } = setup({ request: new Request("https://example.com/") });
844
+ for (let i = 0; i < 3; i++) {
845
+ assertEquals(await ctx.getSignedKey(), null);
846
+ assertEquals(await ctx.getSignedKeyOwner(), null);
847
+ }
848
+ assertEquals(loads, {
849
+ key: 0,
850
+ owner: 0
851
+ });
852
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 1);
853
+ });
854
+ await t.step("memoizes null owners without trusting a key's owner claim", async () => {
855
+ const { ctx, loads } = setup({ load: async (url, options) => url === ownerId ? {
856
+ documentUrl: url,
857
+ contextUrl: null,
858
+ document: {
859
+ ...person2_default,
860
+ publicKey: []
861
+ }
862
+ } : await mockDocumentLoader(url, options) });
863
+ assert(await ctx.getSignedKey());
864
+ assertEquals(await Promise.all(Array.from({ length: 8 }, () => ctx.getSignedKeyOwner())), Array(8).fill(null));
865
+ for (let i = 0; i < 3; i++) assertEquals(await ctx.getSignedKeyOwner(), null);
866
+ assertEquals(loads, {
867
+ key: 1,
868
+ owner: 1
869
+ });
870
+ assert(await ctx.getSignedKeyOwner({ documentLoader: mockDocumentLoader }));
871
+ assert(await ctx.getSignedKeyOwner());
872
+ });
873
+ await t.step("isolates concurrent document loaders before success", async () => {
874
+ const { ctx, loads } = setup();
875
+ let otherLoads = 0;
876
+ const otherLoader = async (url, options) => {
877
+ otherLoads++;
878
+ if (url === ownerId) return {
879
+ documentUrl: url,
880
+ contextUrl: null,
881
+ document: {
882
+ ...person2_default,
883
+ name: "Other view"
884
+ }
885
+ };
886
+ return await mockDocumentLoader(url, options);
887
+ };
888
+ const [first, second] = await Promise.all([ctx.getSignedKeyOwner(), ctx.getSignedKeyOwner({ documentLoader: otherLoader })]);
889
+ assertEquals(first?.name, "Jane Doe");
890
+ assertEquals(second?.name, "Other view");
891
+ const cached = await ctx.getSignedKeyOwner();
892
+ assert(cached === first || cached === second);
893
+ assertStrictEquals(await ctx.getSignedKeyOwner({ documentLoader: otherLoader }), cached);
894
+ assertEquals(loads, {
895
+ key: 1,
896
+ owner: 1
897
+ });
898
+ assertEquals(otherLoads, 2);
899
+ });
900
+ await t.step("preserves in-flight null while another loader succeeds", async () => {
901
+ exporter.clear();
902
+ let release;
903
+ const gate = new Promise((resolve) => release = resolve);
904
+ const { ctx, loads } = setup({ load: async () => {
905
+ await gate;
906
+ throw new TypeError("fetch failed");
907
+ } });
908
+ const failed = Promise.all([ctx.getSignedKey(), ctx.getSignedKeyOwner()]);
909
+ const owner = await ctx.getSignedKeyOwner({ documentLoader: mockDocumentLoader });
910
+ assert(owner);
911
+ release();
912
+ assertEquals(await failed, [null, null]);
913
+ assertStrictEquals(await ctx.getSignedKeyOwner(), owner);
914
+ assert(await ctx.getSignedKey());
915
+ assertEquals(loads, {
916
+ key: 1,
917
+ owner: 0
918
+ });
919
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 2);
920
+ });
921
+ await t.step("isolates context loaders", async () => {
922
+ exporter.clear();
923
+ const { ctx, loads } = setup();
924
+ const otherContextLoader = (url, options) => mockDocumentLoader(url, options);
925
+ await Promise.all([ctx.getSignedKeyOwner(), ctx.getSignedKeyOwner({ contextLoader: otherContextLoader })]);
926
+ assertEquals(loads, {
927
+ key: 2,
928
+ owner: 2
929
+ });
930
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 2);
931
+ });
932
+ await t.step("shares work across tracer providers", async () => {
933
+ exporter.clear();
934
+ const [otherProvider, otherExporter] = createTestTracerProvider();
935
+ try {
936
+ const { ctx, loads } = setup();
937
+ await Promise.all([
938
+ ctx.getSignedKeyOwner(),
939
+ ctx.getSignedKeyOwner({ tracerProvider: otherProvider }),
940
+ ctx.getSignedKey(),
941
+ ctx.getSignedKey({ tracerProvider: otherProvider })
942
+ ]);
943
+ assert(await ctx.getSignedKeyOwner({ tracerProvider: otherProvider }));
944
+ assertEquals(loads, {
945
+ key: 1,
946
+ owner: 1
947
+ });
948
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 1);
949
+ assertEquals(otherExporter.getSpans("http_signatures.verify").length, 0);
950
+ } finally {
951
+ await otherProvider.shutdown();
952
+ }
953
+ });
954
+ await t.step("reuses success with a fresh authorization loader", async () => {
955
+ exporter.clear();
956
+ const { ctx, loads } = setup();
957
+ let freshLoads = 0;
958
+ const freshLoader = (url, options) => {
959
+ freshLoads++;
960
+ return mockDocumentLoader(url, options);
961
+ };
962
+ const key = await ctx.getSignedKey({ documentLoader: freshLoader });
963
+ assert(key);
964
+ assertStrictEquals(await ctx.getSignedKey(), key);
965
+ const owner = await ctx.getSignedKeyOwner();
966
+ assert(owner);
967
+ assertStrictEquals(await ctx.getSignedKeyOwner({ documentLoader: freshLoader }), owner);
968
+ assertEquals(loads, {
969
+ key: 0,
970
+ owner: 1
971
+ });
972
+ assertEquals(freshLoads, 1);
973
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 1);
974
+ });
975
+ await t.step("retains a transient owner lookup failure as null", async () => {
976
+ let fail = true;
977
+ const { ctx, loads } = setup({ load: async (url, options) => {
978
+ if (url === ownerId && fail) throw new TypeError("fetch failed");
979
+ return await mockDocumentLoader(url, options);
980
+ } });
981
+ assert(await ctx.getSignedKey());
982
+ assertEquals(await ctx.getSignedKeyOwner(), null);
983
+ fail = false;
984
+ assertEquals(await ctx.getSignedKeyOwner(), null);
985
+ assertEquals(loads, {
986
+ key: 1,
987
+ owner: 1
988
+ });
989
+ assert(await ctx.getSignedKeyOwner({ documentLoader: mockDocumentLoader }));
990
+ });
991
+ await t.step("rechecks an owner after another loader verifies the key", async () => {
992
+ let fail = true;
993
+ const { ctx, loads } = setup({ load: async (url, options) => {
994
+ if (url === keyId && fail) throw new TypeError("fetch failed");
995
+ return await mockDocumentLoader(url, options);
996
+ } });
997
+ assertEquals(await ctx.getSignedKeyOwner(), null);
998
+ fail = false;
999
+ assertEquals(await ctx.getSignedKeyOwner(), null);
1000
+ assertEquals(loads, {
1001
+ key: 1,
1002
+ owner: 0
1003
+ });
1004
+ assert(await ctx.getSignedKey({ documentLoader: mockDocumentLoader }));
1005
+ assertEquals((await ctx.getSignedKeyOwner())?.id?.href, ownerId);
1006
+ assertEquals(loads, {
1007
+ key: 1,
1008
+ owner: 1
1009
+ });
1010
+ });
1011
+ await t.step("retries unexpected key rejections from a rejection handler", async () => {
1012
+ exporter.clear();
1013
+ const failure = /* @__PURE__ */ new Error("transient context loader failure");
1014
+ let rejectContext = true;
1015
+ const contextLoader = async (url, options) => {
1016
+ if (rejectContext) throw failure;
1017
+ return await mockDocumentLoader(url, options);
1018
+ };
1019
+ const { ctx, loads } = setup();
1020
+ const options = { contextLoader };
1021
+ const failedKeys = Promise.allSettled([
1022
+ ctx.getSignedKey(options),
1023
+ ctx.getSignedKeyOwner(options),
1024
+ ctx.getSignedKey(options)
1025
+ ]);
1026
+ const recovery = ctx.getSignedKey(options).catch(() => {
1027
+ rejectContext = false;
1028
+ return ctx.getSignedKey(options);
1029
+ });
1030
+ for (const result of await failedKeys) assertEquals(result.status, "rejected");
1031
+ assert(await recovery);
1032
+ assertEquals(loads, {
1033
+ key: 2,
1034
+ owner: 0
1035
+ });
1036
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 2);
1037
+ });
1038
+ await t.step("retries owner rejections while retaining the verified key", async () => {
1039
+ exporter.clear();
1040
+ let rejectContext = false;
1041
+ const contextLoader = async (url, options) => {
1042
+ if (rejectContext) throw new Error("transient owner context failure");
1043
+ return await mockDocumentLoader(url, options);
1044
+ };
1045
+ const { ctx, loads } = setup();
1046
+ const options = { contextLoader };
1047
+ assert(await ctx.getSignedKey(options));
1048
+ assertEquals(loads, {
1049
+ key: 1,
1050
+ owner: 0
1051
+ });
1052
+ rejectContext = true;
1053
+ const failures = await Promise.allSettled([ctx.getSignedKeyOwner(options), ctx.getSignedKeyOwner(options)]);
1054
+ for (const result of failures) assertEquals(result.status, "rejected");
1055
+ assertEquals(loads, {
1056
+ key: 1,
1057
+ owner: 1
1058
+ });
1059
+ rejectContext = false;
1060
+ assert(await ctx.getSignedKeyOwner(options));
1061
+ assertEquals(loads, {
1062
+ key: 1,
1063
+ owner: 2
1064
+ });
1065
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 1);
1066
+ });
1067
+ await t.step("keeps clones and separate requests independent", async () => {
1068
+ exporter.clear();
1069
+ const { ctx, loads, federation } = setup();
1070
+ assert(await ctx.getSignedKeyOwner());
1071
+ const clone = ctx.clone(void 0);
1072
+ const separate = federation.createContext(new Request(request), void 0);
1073
+ await Promise.all([clone.getSignedKeyOwner(), separate.getSignedKeyOwner()]);
1074
+ assertEquals(loads, {
1075
+ key: 3,
1076
+ owner: 3
1077
+ });
1078
+ assertEquals(exporter.getSpans("http_signatures.verify").length, 3);
1079
+ });
1080
+ } finally {
1081
+ await tracerProvider.shutdown();
1082
+ }
1083
+ });
742
1084
  test("Federation.fetch() [rfc9421] multiple POST signatures", async (t) => {
743
1085
  for (const validSecond of [true, false]) await t.step(validSecond ? "valid second signature" : "both signatures invalid", async () => {
744
1086
  const inbox = [];
@@ -782,7 +1124,7 @@ test("Federation.fetch()", async (t) => {
782
1124
  kv,
783
1125
  documentLoaderFactory: () => mockDocumentLoader,
784
1126
  authenticatedDocumentLoaderFactory(identity) {
785
- const docLoader = getAuthenticatedDocumentLoader(identity);
1127
+ const docLoader = getAuthenticatedDocumentLoader(identity, { allowPrivateAddress: true });
786
1128
  return (url) => {
787
1129
  if (new URL(url).host === "example.com") return docLoader(url);
788
1130
  return mockDocumentLoader(url);
@@ -988,7 +1330,7 @@ test("Federation.setInboxListeners()", async (t) => {
988
1330
  kv,
989
1331
  documentLoaderFactory: () => mockDocumentLoader,
990
1332
  authenticatedDocumentLoaderFactory(identity) {
991
- const docLoader = getAuthenticatedDocumentLoader(identity);
1333
+ const docLoader = getAuthenticatedDocumentLoader(identity, { allowPrivateAddress: true });
992
1334
  return (url) => {
993
1335
  const urlObj = new URL(url);
994
1336
  authenticatedRequests.push([url, identity.keyId.href]);
@@ -1311,7 +1653,7 @@ test("Federation.setInboxListeners()", async (t) => {
1311
1653
  kv,
1312
1654
  documentLoaderFactory: () => mockDocumentLoader,
1313
1655
  authenticatedDocumentLoaderFactory(identity) {
1314
- const docLoader = getAuthenticatedDocumentLoader(identity);
1656
+ const docLoader = getAuthenticatedDocumentLoader(identity, { allowPrivateAddress: true });
1315
1657
  return (url) => {
1316
1658
  if (new URL(url).host === "example.com") return docLoader(url);
1317
1659
  return mockDocumentLoader(url);
@@ -1524,10 +1866,11 @@ test("Federation.setOutboxListeners()", async (t) => {
1524
1866
  sinks: ["buffer"]
1525
1867
  }]
1526
1868
  });
1527
- const federation = createFederation({
1869
+ const federation = new FederationImpl({
1528
1870
  kv,
1529
1871
  documentLoaderFactory: () => mockDocumentLoader
1530
1872
  });
1873
+ federation.allowPrivateAddress = true;
1531
1874
  federation.setActorDispatcher("/users/{identifier}", (_ctx, identifier) => identifier === "john" ? new vocab.Person({}) : null).setKeyPairsDispatcher(() => [{
1532
1875
  privateKey: rsaPrivateKey2,
1533
1876
  publicKey: rsaPublicKey2.publicKey
@@ -1630,10 +1973,11 @@ test("Federation.setOutboxListeners()", async (t) => {
1630
1973
  sinks: ["buffer"]
1631
1974
  }]
1632
1975
  });
1633
- const federation = createFederation({
1976
+ const federation = new FederationImpl({
1634
1977
  kv,
1635
1978
  documentLoaderFactory: () => mockDocumentLoader
1636
1979
  });
1980
+ federation.allowPrivateAddress = true;
1637
1981
  federation.setActorDispatcher("/{identifier}", (_ctx, identifier) => identifier === "person2" ? new vocab.Person({}) : null).setKeyPairsDispatcher(() => [{
1638
1982
  privateKey: rsaPrivateKey2,
1639
1983
  publicKey: rsaPublicKey2.publicKey
@@ -1858,7 +2202,7 @@ test("FederationImpl.sendActivity()", async (t) => {
1858
2202
  });
1859
2203
  const federation = new FederationImpl({
1860
2204
  kv: new MemoryKvStore(),
1861
- contextLoaderFactory: () => mockDocumentLoader
2205
+ allowPrivateAddress: true
1862
2206
  });
1863
2207
  const context = federation.createContext(new URL("https://example.com/"));
1864
2208
  await t.step("success", async () => {
@@ -3900,7 +4244,7 @@ test("ContextImpl.sendActivity()", async (t) => {
3900
4244
  const kv = new MemoryKvStore();
3901
4245
  const federation = new FederationImpl({
3902
4246
  kv,
3903
- contextLoaderFactory: () => mockDocumentLoader
4247
+ allowPrivateAddress: true
3904
4248
  });
3905
4249
  federation.setActorDispatcher("/{identifier}", async (ctx, identifier) => {
3906
4250
  if (identifier !== "1") return null;
@@ -4023,11 +4367,13 @@ test("ContextImpl.sendActivity()", async (t) => {
4023
4367
  });
4024
4368
  await t.step("records recipient span attributes correctly", async () => {
4025
4369
  const [tracerProvider, exporter] = createTestTracerProvider();
4026
- const ctx = new FederationImpl({
4370
+ const federation3 = new FederationImpl({
4027
4371
  kv,
4028
4372
  contextLoaderFactory: () => mockDocumentLoader,
4029
4373
  tracerProvider
4030
- }).createContext(new URL("https://example.com/"), void 0);
4374
+ });
4375
+ federation3.allowPrivateAddress = true;
4376
+ const ctx = federation3.createContext(new URL("https://example.com/"), void 0);
4031
4377
  const activity = new vocab.Create({
4032
4378
  id: new URL("https://example.com/activity/telemetry"),
4033
4379
  actor: new URL("https://example.com/person"),
@@ -4061,7 +4407,7 @@ test("ContextImpl.sendActivity()", async (t) => {
4061
4407
  };
4062
4408
  const federation2 = new FederationImpl({
4063
4409
  kv,
4064
- contextLoaderFactory: () => mockDocumentLoader,
4410
+ allowPrivateAddress: true,
4065
4411
  queue
4066
4412
  });
4067
4413
  federation2.setActorDispatcher("/{identifier}", async (ctx, identifier) => {
@@ -4232,7 +4578,7 @@ test("ContextImpl.sendActivity()", async (t) => {
4232
4578
  const asyncEnqueued = [];
4233
4579
  const fed = new FederationImpl({
4234
4580
  kv,
4235
- contextLoaderFactory: () => mockDocumentLoader,
4581
+ allowPrivateAddress: true,
4236
4582
  queue: {
4237
4583
  enqueue(message) {
4238
4584
  return new Promise((resolve) => {
@@ -4399,10 +4745,10 @@ test({
4399
4745
  const signedInvite = await signObject(new vocab.Invite({ actor: new URL("https://example.com/person2") }), ed25519PrivateKey, ed25519Multikey.id);
4400
4746
  assert(await ctx.routeActivity("id", signedInvite));
4401
4747
  assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
4402
- assertFalse(await ctx.routeActivity(null, new vocab.Create({
4748
+ assertFalse(await withDnsLookup(() => Promise.reject(/* @__PURE__ */ new Error("Resolver unavailable")), () => ctx.routeActivity(null, new vocab.Create({
4403
4749
  id: new URL("https://example.com/not-found"),
4404
4750
  actor: new URL("https://example.com/person")
4405
- })));
4751
+ }))));
4406
4752
  assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
4407
4753
  assertFalse(await ctx.routeActivity(null, new vocab.Create({
4408
4754
  id: new URL("https://example.com/person"),
@@ -4761,7 +5107,7 @@ test("InboxContextImpl.forwardActivity()", async (t) => {
4761
5107
  const kv = new MemoryKvStore();
4762
5108
  const federation = new FederationImpl({
4763
5109
  kv,
4764
- contextLoaderFactory: () => mockDocumentLoader
5110
+ allowPrivateAddress: true
4765
5111
  });
4766
5112
  await t.step("skip", async () => {
4767
5113
  await new InboxContextImpl(null, {
@@ -4884,6 +5230,7 @@ test("InboxContextImpl.forwardActivity()", async (t) => {
4884
5230
  contextLoaderFactory: () => mockDocumentLoader,
4885
5231
  tracerProvider
4886
5232
  });
5233
+ federationWithTracing.allowPrivateAddress = true;
4887
5234
  await new InboxContextImpl(null, await signJsonLd({
4888
5235
  "@context": "https://www.w3.org/ns/activitystreams",
4889
5236
  "type": "Create",
@@ -5018,5 +5365,19 @@ test("Federation.fetch() bounds inbox bodies before dispatch", async () => {
5018
5365
  }), { contextData: void 0 })).status, 202);
5019
5366
  assert(dispatched);
5020
5367
  });
5368
+ /**
5369
+ * Runs the given function while `node:dns/promises`' `lookup()`, which the
5370
+ * default public fetch resolves hostnames with, is replaced, so that no test
5371
+ * depends on the real DNS.
5372
+ */
5373
+ async function withDnsLookup(lookup, fn) {
5374
+ const originalLookup = dns.lookup;
5375
+ dns.lookup = lookup;
5376
+ try {
5377
+ return await fn();
5378
+ } finally {
5379
+ dns.lookup = originalLookup;
5380
+ }
5381
+ }
5021
5382
  //#endregion
5022
5383
  export {};
@@ -2,7 +2,7 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("../chunk-DDcVe30Y.cjs");
5
- const require_middleware = require("../middleware-BWOwEGpy.cjs");
5
+ const require_middleware = require("../middleware-DNueR0GD.cjs");
6
6
  let es_toolkit = require("es-toolkit");
7
7
  //#region src/federation/kv.ts
8
8
  /**
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as ActorAliasMapper, A as FederationKvPrefixes, B as Router, C as IdempotencyKeyCallback, Ct as SendActivityError, D as ObjectCallbackSetters, Dt as digest, E as InboxListenerSetters, Et as buildCollectionSynchronizationHeader, F as RetryContext, G as respondWithObject, H as RouterOptions, I as RetryPolicy, J as InProcessMessageQueueOptions, K as respondWithObjectIfAcceptable, L as createExponentialBackoffPolicy, M as FederationQueueOptions, N as createFederation, O as OutboxListenerSetters, P as CreateExponentialBackoffPolicyOptions, Q as ParallelMessageQueue, R as Message, S as FederationStartQueueOptions, St as WebFingerLinksDispatcher, T as InboxChallengePolicy, Tt as PageItems, U as RouterRouteResult, V as RouterError, W as RespondWithObjectOptions, X as MessageQueueEnqueueOptions, Y as MessageQueue, Z as MessageQueueListenOptions, _ as Federatable, _t as OutboxListenerErrorHandler, a as GetSignedKeyOptions, at as CollectionCursor, b as FederationFetchOptions, bt as UnverifiedActivityHandler, c as ParseUriResult, ct as CustomCollectionCursor, d as SendActivityOptions, dt as InboxListener, et as ActorDispatcher, f as SendActivityOptionsForCollection, ft as NodeInfoDispatcher, g as CustomCollectionCallbackSetters, gt as OutboxListener, h as ConstructorWithTypeId, ht as OutboxErrorHandler, i as GetActorOptions, it as CollectionCounter, j as FederationOrigin, k as Rfc6570Expression, l as RequestContext, lt as CustomCollectionDispatcher, m as CollectionCallbackSetters, mt as ObjectDispatcher, n as Context, nt as ActorKeyPairsDispatcher, o as InboxContext, ot as CollectionDispatcher, p as ActorCallbackSetters, pt as ObjectAuthorizePredicate, q as InProcessMessageQueue, r as ForwardActivityOptions, rt as AuthorizePredicate, s as OutboxContext, st as CustomCollectionCounter, t as ActorKeyPair, tt as ActorHandleMapper, u as RouteActivityOptions, ut as InboxErrorHandler, v as Federation, vt as OutboxPermanentFailureHandler, w as IdempotencyStrategy, wt as SenderKeyPair, x as FederationOptions, xt as UnverifiedActivityReason, y as FederationBuilder, yt as SharedInboxKeyDispatcher, z as createFederationBuilder } from "../context-tJbL_Hkw.cjs";
2
+ import { $ as ActorAliasMapper, A as FederationKvPrefixes, B as Router, C as IdempotencyKeyCallback, Ct as SendActivityError, D as ObjectCallbackSetters, Dt as digest, E as InboxListenerSetters, Et as buildCollectionSynchronizationHeader, F as RetryContext, G as respondWithObject, H as RouterOptions, I as RetryPolicy, J as InProcessMessageQueueOptions, K as respondWithObjectIfAcceptable, L as createExponentialBackoffPolicy, M as FederationQueueOptions, N as createFederation, O as OutboxListenerSetters, P as CreateExponentialBackoffPolicyOptions, Q as ParallelMessageQueue, R as Message, S as FederationStartQueueOptions, St as WebFingerLinksDispatcher, T as InboxChallengePolicy, Tt as PageItems, U as RouterRouteResult, V as RouterError, W as RespondWithObjectOptions, X as MessageQueueEnqueueOptions, Y as MessageQueue, Z as MessageQueueListenOptions, _ as Federatable, _t as OutboxListenerErrorHandler, a as GetSignedKeyOptions, at as CollectionCursor, b as FederationFetchOptions, bt as UnverifiedActivityHandler, c as ParseUriResult, ct as CustomCollectionCursor, d as SendActivityOptions, dt as InboxListener, et as ActorDispatcher, f as SendActivityOptionsForCollection, ft as NodeInfoDispatcher, g as CustomCollectionCallbackSetters, gt as OutboxListener, h as ConstructorWithTypeId, ht as OutboxErrorHandler, i as GetActorOptions, it as CollectionCounter, j as FederationOrigin, k as Rfc6570Expression, l as RequestContext, lt as CustomCollectionDispatcher, m as CollectionCallbackSetters, mt as ObjectDispatcher, n as Context, nt as ActorKeyPairsDispatcher, o as InboxContext, ot as CollectionDispatcher, p as ActorCallbackSetters, pt as ObjectAuthorizePredicate, q as InProcessMessageQueue, r as ForwardActivityOptions, rt as AuthorizePredicate, s as OutboxContext, st as CustomCollectionCounter, t as ActorKeyPair, tt as ActorHandleMapper, u as RouteActivityOptions, ut as InboxErrorHandler, v as Federation, vt as OutboxPermanentFailureHandler, w as IdempotencyStrategy, wt as SenderKeyPair, x as FederationOptions, xt as UnverifiedActivityReason, y as FederationBuilder, yt as SharedInboxKeyDispatcher, z as createFederationBuilder } from "../context-CFQGaq5x.cjs";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-CZKl1IUS.cjs";
4
- import { n as handleWebFinger, t as WebFingerHandlerParameters } from "../mod-a6kmB8xD.cjs";
4
+ import { n as handleWebFinger, t as WebFingerHandlerParameters } from "../mod-CVSKw-5H.cjs";
5
5
  export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MemoryKvStore, Message, MessageQueue, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as ActorAliasMapper, A as FederationKvPrefixes, B as Router, C as IdempotencyKeyCallback, Ct as SendActivityError, D as ObjectCallbackSetters, Dt as digest, E as InboxListenerSetters, Et as buildCollectionSynchronizationHeader, F as RetryContext, G as respondWithObject, H as RouterOptions, I as RetryPolicy, J as InProcessMessageQueueOptions, K as respondWithObjectIfAcceptable, L as createExponentialBackoffPolicy, M as FederationQueueOptions, N as createFederation, O as OutboxListenerSetters, P as CreateExponentialBackoffPolicyOptions, Q as ParallelMessageQueue, R as Message, S as FederationStartQueueOptions, St as WebFingerLinksDispatcher, T as InboxChallengePolicy, Tt as PageItems, U as RouterRouteResult, V as RouterError, W as RespondWithObjectOptions, X as MessageQueueEnqueueOptions, Y as MessageQueue, Z as MessageQueueListenOptions, _ as Federatable, _t as OutboxListenerErrorHandler, a as GetSignedKeyOptions, at as CollectionCursor, b as FederationFetchOptions, bt as UnverifiedActivityHandler, c as ParseUriResult, ct as CustomCollectionCursor, d as SendActivityOptions, dt as InboxListener, et as ActorDispatcher, f as SendActivityOptionsForCollection, ft as NodeInfoDispatcher, g as CustomCollectionCallbackSetters, gt as OutboxListener, h as ConstructorWithTypeId, ht as OutboxErrorHandler, i as GetActorOptions, it as CollectionCounter, j as FederationOrigin, k as Rfc6570Expression, l as RequestContext, lt as CustomCollectionDispatcher, m as CollectionCallbackSetters, mt as ObjectDispatcher, n as Context, nt as ActorKeyPairsDispatcher, o as InboxContext, ot as CollectionDispatcher, p as ActorCallbackSetters, pt as ObjectAuthorizePredicate, q as InProcessMessageQueue, r as ForwardActivityOptions, rt as AuthorizePredicate, s as OutboxContext, st as CustomCollectionCounter, t as ActorKeyPair, tt as ActorHandleMapper, u as RouteActivityOptions, ut as InboxErrorHandler, v as Federation, vt as OutboxPermanentFailureHandler, w as IdempotencyStrategy, wt as SenderKeyPair, x as FederationOptions, xt as UnverifiedActivityReason, y as FederationBuilder, yt as SharedInboxKeyDispatcher, z as createFederationBuilder } from "../context-OkwEpc3-.js";
2
+ import { $ as ActorAliasMapper, A as FederationKvPrefixes, B as Router, C as IdempotencyKeyCallback, Ct as SendActivityError, D as ObjectCallbackSetters, Dt as digest, E as InboxListenerSetters, Et as buildCollectionSynchronizationHeader, F as RetryContext, G as respondWithObject, H as RouterOptions, I as RetryPolicy, J as InProcessMessageQueueOptions, K as respondWithObjectIfAcceptable, L as createExponentialBackoffPolicy, M as FederationQueueOptions, N as createFederation, O as OutboxListenerSetters, P as CreateExponentialBackoffPolicyOptions, Q as ParallelMessageQueue, R as Message, S as FederationStartQueueOptions, St as WebFingerLinksDispatcher, T as InboxChallengePolicy, Tt as PageItems, U as RouterRouteResult, V as RouterError, W as RespondWithObjectOptions, X as MessageQueueEnqueueOptions, Y as MessageQueue, Z as MessageQueueListenOptions, _ as Federatable, _t as OutboxListenerErrorHandler, a as GetSignedKeyOptions, at as CollectionCursor, b as FederationFetchOptions, bt as UnverifiedActivityHandler, c as ParseUriResult, ct as CustomCollectionCursor, d as SendActivityOptions, dt as InboxListener, et as ActorDispatcher, f as SendActivityOptionsForCollection, ft as NodeInfoDispatcher, g as CustomCollectionCallbackSetters, gt as OutboxListener, h as ConstructorWithTypeId, ht as OutboxErrorHandler, i as GetActorOptions, it as CollectionCounter, j as FederationOrigin, k as Rfc6570Expression, l as RequestContext, lt as CustomCollectionDispatcher, m as CollectionCallbackSetters, mt as ObjectDispatcher, n as Context, nt as ActorKeyPairsDispatcher, o as InboxContext, ot as CollectionDispatcher, p as ActorCallbackSetters, pt as ObjectAuthorizePredicate, q as InProcessMessageQueue, r as ForwardActivityOptions, rt as AuthorizePredicate, s as OutboxContext, st as CustomCollectionCounter, t as ActorKeyPair, tt as ActorHandleMapper, u as RouteActivityOptions, ut as InboxErrorHandler, v as Federation, vt as OutboxPermanentFailureHandler, w as IdempotencyStrategy, wt as SenderKeyPair, x as FederationOptions, xt as UnverifiedActivityReason, y as FederationBuilder, yt as SharedInboxKeyDispatcher, z as createFederationBuilder } from "../context-DdbLVV_k.js";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-CxaI4eGo.js";
4
- import { n as handleWebFinger, t as WebFingerHandlerParameters } from "../mod-DQGjRJUG.js";
4
+ import { n as handleWebFinger, t as WebFingerHandlerParameters } from "../mod-BuRRdsfD.js";
5
5
  export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MemoryKvStore, Message, MessageQueue, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "../middleware-BimXKBcP.js";
3
+ import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "../middleware-sjhz30sm.js";
4
4
  import { isEqual } from "es-toolkit";
5
5
  //#region src/federation/kv.ts
6
6
  /**