@fedify/fedify 2.3.6 → 2.3.8

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 (108) hide show
  1. package/dist/{assert_instance_of-DBC5X09g.mjs → assert-jSdZMYam.mjs} +19 -1
  2. package/dist/{builder-CW-9AJCO.mjs → builder-CDForRSL.mjs} +3 -3
  3. package/dist/{client-D1KuWxjH.mjs → client-DYDoDpMa.mjs} +78 -4
  4. package/dist/compat/mod.d.cts +1 -1
  5. package/dist/compat/mod.d.ts +1 -1
  6. package/dist/compat/outgoing-jsonld.test.mjs +1 -1
  7. package/dist/compat/public-audience.test.mjs +1 -1
  8. package/dist/compat/transformers.test.mjs +3 -4
  9. package/dist/{context-DVoTs_wM.mjs → context-BepjCFHN.mjs} +1 -0
  10. package/dist/{context-BxVVO5Ro.d.ts → context-CAKnQy1x.d.ts} +4 -3
  11. package/dist/{context-BpmLyiPx.d.cts → context-CSIggG9_.d.cts} +4 -3
  12. package/dist/{deno-KC-uf6Un.mjs → deno--DCBC7WG.mjs} +1 -1
  13. package/dist/{docloader-BHS1yt22.mjs → docloader-BAdp-ZeK.mjs} +2 -2
  14. package/dist/federation/builder.test.mjs +2 -2
  15. package/dist/federation/circuit-breaker.test.mjs +3 -3
  16. package/dist/federation/collection.test.mjs +1 -1
  17. package/dist/federation/handler.test.mjs +128 -11
  18. package/dist/federation/idempotency.test.mjs +4 -4
  19. package/dist/federation/inbox.test.mjs +1 -1
  20. package/dist/federation/keycache.test.mjs +44 -10
  21. package/dist/federation/kv.test.mjs +1 -1
  22. package/dist/federation/metrics.test.mjs +1 -1
  23. package/dist/federation/middleware.test.mjs +109 -19
  24. package/dist/federation/mod.cjs +1 -1
  25. package/dist/federation/mod.d.cts +2 -2
  26. package/dist/federation/mod.d.ts +2 -2
  27. package/dist/federation/mod.js +1 -1
  28. package/dist/federation/mq.test.mjs +1 -1
  29. package/dist/federation/negotiation.test.mjs +2 -2
  30. package/dist/federation/retry.test.mjs +1 -1
  31. package/dist/federation/router.test.mjs +1 -1
  32. package/dist/federation/send.test.mjs +141 -7
  33. package/dist/federation/temporal.test.mjs +2 -2
  34. package/dist/federation/webfinger.test.mjs +3 -3
  35. package/dist/{http-DzgaVy-x.js → http-BKJYj9oz.js} +155 -7
  36. package/dist/{http-DL5ZJBC4.cjs → http-ChVf88XZ.cjs} +166 -6
  37. package/dist/{http-BcbYkefs.mjs → http-ClEDLGpr.mjs} +4 -4
  38. package/dist/{http-lf8Hsd91.d.ts → http-DQmNpfym.d.ts} +1 -1
  39. package/dist/{http-VyDTd4G3.d.cts → http-DiWQB8Mr.d.cts} +1 -1
  40. package/dist/{key-Cbkqgt-G.mjs → key-C-7sqo8D.mjs} +155 -7
  41. package/dist/{keycache-BeU0LCII.mjs → keycache-B3qRQNLj.mjs} +12 -4
  42. package/dist/{kv-cache-CT228f7w.mjs → kv-cache-C5FK4PLG.mjs} +1 -1
  43. package/dist/{kv-cache-BWNRhap7.js → kv-cache-C_w70bFh.js} +2 -2
  44. package/dist/{kv-cache-Dw94l8rT.cjs → kv-cache-DFBOAyNj.cjs} +2 -2
  45. package/dist/{ld-c-9mCB36.mjs → ld-CtFHB6rU.mjs} +3 -3
  46. package/dist/{metrics-D8s1eKfJ.mjs → metrics-FDcYXRP5.mjs} +1 -1
  47. package/dist/{middleware-B29rR42K.cjs → middleware-BdDtzhXb.cjs} +101 -25
  48. package/dist/{middleware-3L9f9ZTw.mjs → middleware-COzI8bCL.mjs} +41 -30
  49. package/dist/{middleware-D_cNQ7Yq.js → middleware-DunPXFJL.js} +101 -25
  50. package/dist/{middleware-Be2z0t5f.mjs → middleware-K7mJeIgT.mjs} +1 -1
  51. package/dist/{mod-yvIXFAEi.d.cts → mod-1TuoXkGs.d.cts} +1 -1
  52. package/dist/{mod-B0hW12_O.d.cts → mod-Bid79LFU.d.cts} +1 -1
  53. package/dist/{mod-Rpy4Uwkk.d.ts → mod-CFuyfw3c.d.ts} +1 -1
  54. package/dist/{mod-DFvNJcNb.d.ts → mod-DHgc4ygG.d.ts} +1 -1
  55. package/dist/{mod-CjERT09F.d.cts → mod-PVR75MeU.d.cts} +1 -1
  56. package/dist/{mod-COIAjwRS.d.ts → mod-TLEvgT1i.d.ts} +1 -1
  57. package/dist/mod.cjs +5 -5
  58. package/dist/mod.d.cts +6 -6
  59. package/dist/mod.d.ts +6 -6
  60. package/dist/mod.js +5 -5
  61. package/dist/nodeinfo/client.test.mjs +28 -1
  62. package/dist/nodeinfo/handler.test.mjs +3 -3
  63. package/dist/nodeinfo/mod.cjs +1 -1
  64. package/dist/nodeinfo/mod.js +1 -1
  65. package/dist/nodeinfo/types.test.mjs +1 -1
  66. package/dist/otel/exporter.test.mjs +1 -1
  67. package/dist/{outgoing-jsonld-OFoubetZ.mjs → outgoing-jsonld-HOAywiid.mjs} +1 -1
  68. package/dist/{owner-CnngXDNJ.d.ts → owner-B3hNQCG8.d.cts} +12 -1
  69. package/dist/owner-CGuS9lE7.mjs +175 -0
  70. package/dist/{owner-DEvZuyOE.d.cts → owner-CiBPcC6F.d.ts} +12 -1
  71. package/dist/{proof-D_6qtBdQ.mjs → proof--56drUyt.mjs} +5 -5
  72. package/dist/{proof-DGlDXtcc.cjs → proof-Dgozne0w.cjs} +112 -58
  73. package/dist/{proof-CrtfGSi7.js → proof-tjbzynMa.js} +112 -58
  74. package/dist/{send-i63Det4Y.mjs → send-CC1A7ATC.mjs} +68 -11
  75. package/dist/sig/accept.test.mjs +1 -1
  76. package/dist/sig/http.test.mjs +4 -4
  77. package/dist/sig/key.test.mjs +170 -3
  78. package/dist/sig/ld.test.mjs +56 -4
  79. package/dist/sig/mod.cjs +2 -2
  80. package/dist/sig/mod.d.cts +3 -3
  81. package/dist/sig/mod.d.ts +3 -3
  82. package/dist/sig/mod.js +2 -2
  83. package/dist/sig/owner.test.mjs +105 -6
  84. package/dist/sig/proof.test.mjs +73 -5
  85. package/dist/{temporal-CcVjTX30.mjs → temporal-DvptXZ7V.mjs} +1 -1
  86. package/dist/testing/mod.mjs +1 -1
  87. package/dist/{types-m8u9L86X.cjs → types-DWs-qZaY.cjs} +94 -2
  88. package/dist/{types-DTONwNqL.js → types-sXITXcWa.js} +78 -4
  89. package/dist/utils/docloader.test.mjs +28 -4
  90. package/dist/utils/kv-cache.test.mjs +1 -1
  91. package/dist/utils/mod.cjs +1 -1
  92. package/dist/utils/mod.d.cts +1 -1
  93. package/dist/utils/mod.d.ts +1 -1
  94. package/dist/utils/mod.js +1 -1
  95. package/package.json +7 -7
  96. package/dist/assert-OguE97r2.mjs +0 -23
  97. package/dist/owner-CjkdUXE3.mjs +0 -120
  98. /package/dist/{accept-CPkZzmGN.mjs → accept-Dd__NiUL.mjs} +0 -0
  99. /package/dist/{activity-listener-tztVvlNb.mjs → activity-listener-ell7W1s9.mjs} +0 -0
  100. /package/dist/{circuit-breaker-D1fxthDI.mjs → circuit-breaker-CDABzqVf.mjs} +0 -0
  101. /package/dist/{circuit-breaker-test-utils-CAdwjgMi.mjs → circuit-breaker-test-utils-Dm5MM6l9.mjs} +0 -0
  102. /package/dist/{collection-Cc3DVAhE.mjs → collection-CA3V5zyK.mjs} +0 -0
  103. /package/dist/{keys-DGu1NFwu.mjs → keys-BAK-tUlf.mjs} +0 -0
  104. /package/dist/{kv-rV3vodCc.mjs → kv-CX8qfaad.mjs} +0 -0
  105. /package/dist/{negotiation-DDstyBvc.mjs → negotiation-CDW-_gUU.mjs} +0 -0
  106. /package/dist/{public-audience-DZJAUUi8.mjs → public-audience-jwoSIGUw.mjs} +0 -0
  107. /package/dist/{retry-CXg_MBI-.mjs → retry-_VvV0h9f.mjs} +0 -0
  108. /package/dist/{types-J53Kw7so.mjs → types-s4mCTGkT.mjs} +0 -0
@@ -5,29 +5,28 @@ import { t as esm_default } from "../esm-vrlUxr60.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
6
6
  import { r as assertExists } from "../std__assert-BBjXFNOb.mjs";
7
7
  import { r as assertFalse, t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
8
- import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
8
+ import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
9
9
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
10
10
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
11
11
  import { t as assertStrictEquals } from "../assert_strict_equals-XEgZAlrj.mjs";
12
- import { t as assert } from "../assert-OguE97r2.mjs";
13
- import { g as recordInboxActivity } from "../metrics-D8s1eKfJ.mjs";
14
- import { l as verifyRequest, s as signRequest } from "../http-BcbYkefs.mjs";
15
- import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
16
- import { t as getAuthenticatedDocumentLoader } from "../docloader-BHS1yt22.mjs";
17
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-c-9mCB36.mjs";
18
- import { t as doesActorOwnKey } from "../owner-CjkdUXE3.mjs";
19
- import { i as verifyObject, r as signObject } from "../proof-D_6qtBdQ.mjs";
20
- import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
21
- import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-3L9f9ZTw.mjs";
22
- import { t as CircuitBreaker } from "../circuit-breaker-D1fxthDI.mjs";
23
- import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-CAdwjgMi.mjs";
12
+ import { g as recordInboxActivity } from "../metrics-FDcYXRP5.mjs";
13
+ import { l as verifyRequest, s as signRequest } from "../http-ClEDLGpr.mjs";
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-BAdp-ZeK.mjs";
16
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-CtFHB6rU.mjs";
17
+ import { t as doesActorOwnKey } from "../owner-CGuS9lE7.mjs";
18
+ import { i as verifyObject, r as signObject } from "../proof--56drUyt.mjs";
19
+ import { t as MemoryKvStore } from "../kv-CX8qfaad.mjs";
20
+ import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-COzI8bCL.mjs";
21
+ import { t as CircuitBreaker } from "../circuit-breaker-CDABzqVf.mjs";
22
+ import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-Dm5MM6l9.mjs";
24
23
  import { configure, reset } from "@logtape/logtape";
25
24
  import { RouterError } from "@fedify/uri-template";
26
25
  import * as vocab from "@fedify/vocab";
27
26
  import { Create, Offer, Person, getTypeId, lookupObject } from "@fedify/vocab";
28
27
  import { SpanStatusCode, metrics } from "@opentelemetry/api";
29
28
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
30
- import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
29
+ import { FetchError, UrlError, getDocumentLoader } from "@fedify/vocab-runtime";
31
30
  import serialize from "json-canon";
32
31
  import { DataPointType, MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
33
32
  //#region ../fixture/src/fixtures/example.com/create.json
@@ -2159,7 +2158,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2159
2158
  const records = [];
2160
2159
  await reset();
2161
2160
  esm_default.spyGlobal();
2162
- esm_default.post("https://remote.example/inbox", {
2161
+ esm_default.post("https://example.com/inbox", {
2163
2162
  status: 202,
2164
2163
  body: "Accepted"
2165
2164
  });
@@ -2185,7 +2184,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2185
2184
  federation.setOutboxListeners("/users/{identifier}/outbox").on(vocab.Activity, async (ctx, activity) => {
2186
2185
  await ctx.sendActivity({ identifier: ctx.identifier }, new vocab.Person({
2187
2186
  id: new URL("https://remote.example/users/alice"),
2188
- inbox: new URL("https://remote.example/inbox")
2187
+ inbox: new URL("https://example.com/inbox")
2189
2188
  }), activity);
2190
2189
  }).authorize((ctx, identifier) => {
2191
2190
  return identifier === "john" && ctx.request.headers.get("authorization") === "Bearer token";
@@ -2261,7 +2260,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2261
2260
  let ldsVerified = false;
2262
2261
  await reset();
2263
2262
  esm_default.spyGlobal();
2264
- esm_default.post("https://remote.example/inbox", async (cl) => {
2263
+ esm_default.post("https://example.com/inbox", async (cl) => {
2265
2264
  const verifyOptions = {
2266
2265
  documentLoader: mockDocumentLoader,
2267
2266
  contextLoader: mockDocumentLoader
@@ -2294,7 +2293,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2294
2293
  keyId: rsaPublicKey2.id
2295
2294
  }], {
2296
2295
  id: new URL("https://remote.example/users/alice"),
2297
- inboxId: new URL("https://remote.example/inbox")
2296
+ inboxId: new URL("https://example.com/inbox")
2298
2297
  }, { skipIfUnsigned: true });
2299
2298
  }).authorize((ctx, identifier) => {
2300
2299
  return identifier === "person2" && ctx.request.headers.get("authorization") === "Bearer token";
@@ -4518,6 +4517,7 @@ test("FederationImpl.processQueuedTask() permanent failure", async (t) => {
4518
4517
  return Promise.resolve();
4519
4518
  }
4520
4519
  },
4520
+ allowPrivateAddress: true,
4521
4521
  ...options.permanentFailureStatusCodes ? { permanentFailureStatusCodes: options.permanentFailureStatusCodes } : {},
4522
4522
  ...options.meterProvider ? { meterProvider: options.meterProvider } : {},
4523
4523
  ...options.tracerProvider ? { tracerProvider: options.tracerProvider } : {}
@@ -4716,6 +4716,7 @@ test("FederationImpl.processQueuedTask() circuit breaker", async (t) => {
4716
4716
  return Promise.resolve();
4717
4717
  }
4718
4718
  },
4719
+ allowPrivateAddress: true,
4719
4720
  circuitBreaker: options,
4720
4721
  ...federationOptions
4721
4722
  });
@@ -5729,7 +5730,8 @@ test("FederationImpl.processQueuedTask() queue task metrics", async (t) => {
5729
5730
  listen(_handler, _options) {
5730
5731
  return Promise.resolve();
5731
5732
  }
5732
- }
5733
+ },
5734
+ allowPrivateAddress: true
5733
5735
  });
5734
5736
  federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
5735
5737
  esm_default.spyGlobal();
@@ -6965,5 +6967,93 @@ test("createFederation() omits instrumentation when no meterProvider is set", ()
6965
6967
  assertStrictEquals(ctx.documentLoader, mockDocumentLoader);
6966
6968
  assertStrictEquals(ctx.contextLoader, mockDocumentLoader);
6967
6969
  });
6970
+ test("ContextImpl.sendActivity() honors the private-address policy", async (t) => {
6971
+ for (const allowPrivateAddress of [false, true]) await t.step(`allowPrivateAddress: ${allowPrivateAddress}`, async () => {
6972
+ const inbox = "http://127.0.0.1/inbox";
6973
+ esm_default.mockGlobal().post(inbox, 202);
6974
+ try {
6975
+ const ctx = createFederation({
6976
+ kv: new MemoryKvStore(),
6977
+ allowPrivateAddress
6978
+ }).createContext(new URL("https://example.com/"));
6979
+ const send = () => ctx.sendActivity({
6980
+ privateKey: ed25519PrivateKey,
6981
+ keyId: ed25519Multikey.id
6982
+ }, new Person({
6983
+ id: new URL("https://example.com/recipient"),
6984
+ inbox: new URL(inbox)
6985
+ }), new Create({
6986
+ id: new URL("https://example.com/activity"),
6987
+ actor: new URL("https://example.com/person")
6988
+ }), { immediate: true });
6989
+ if (allowPrivateAddress) {
6990
+ await send();
6991
+ assertEquals(esm_default.callHistory.calls(inbox).length, 1);
6992
+ } else {
6993
+ await assertRejects(send, UrlError);
6994
+ assertEquals(esm_default.callHistory.calls(inbox).length, 0);
6995
+ }
6996
+ } finally {
6997
+ esm_default.hardReset();
6998
+ }
6999
+ });
7000
+ });
7001
+ test("Federation.fetch() bounds inbox bodies before dispatch", async () => {
7002
+ let dispatched = false;
7003
+ const json = JSON.stringify({
7004
+ "@context": "https://www.w3.org/ns/activitystreams",
7005
+ id: "https://example.com/activities/bounded",
7006
+ type: "Create",
7007
+ actor: "https://example.com/actor"
7008
+ });
7009
+ const size = 16 * 1024 * 1024;
7010
+ const federation = createFederation({
7011
+ kv: new MemoryKvStore(),
7012
+ skipSignatureVerification: true,
7013
+ contextLoaderFactory: () => mockDocumentLoader
7014
+ });
7015
+ federation.setActorDispatcher("/actors/{identifier}", () => new Person({ id: new URL("https://example.com/actor") }));
7016
+ federation.setInboxListeners("/actors/{identifier}/inbox", "/inbox").on(Create, () => {
7017
+ dispatched = true;
7018
+ });
7019
+ for (const contentLength of [
7020
+ void 0,
7021
+ "1",
7022
+ String(size + 1)
7023
+ ]) {
7024
+ assertEquals((await federation.fetch(new Request("https://example.com/inbox", {
7025
+ method: "POST",
7026
+ headers: contentLength == null ? {} : { "Content-Length": contentLength },
7027
+ body: json.padEnd(size + 1)
7028
+ }), { contextData: void 0 })).status, 413);
7029
+ assertFalse(dispatched);
7030
+ }
7031
+ let canceled = false;
7032
+ let pulls = 0;
7033
+ const body = new ReadableStream({
7034
+ pull(controller) {
7035
+ pulls++;
7036
+ controller.enqueue(new Uint8Array(64 * 1024));
7037
+ },
7038
+ cancel() {
7039
+ canceled = true;
7040
+ }
7041
+ }, { highWaterMark: 0 });
7042
+ const request = new Request("https://example.com/inbox", {
7043
+ method: "POST",
7044
+ body,
7045
+ duplex: "half"
7046
+ });
7047
+ assertEquals((await federation.fetch(request, { contextData: void 0 })).status, 413);
7048
+ await new Promise((resolve) => setTimeout(resolve, 0));
7049
+ assert(canceled);
7050
+ assert(pulls <= 260);
7051
+ assertFalse(dispatched);
7052
+ assertEquals((await federation.fetch(new Request("https://example.com/inbox", {
7053
+ method: "POST",
7054
+ body: json
7055
+ }), { contextData: void 0 })).status, 202);
7056
+ assert(dispatched);
7057
+ });
6968
7058
  //#endregion
6969
7059
  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-B29rR42K.cjs");
5
+ const require_middleware = require("../middleware-BdDtzhXb.cjs");
6
6
  let _logtape_logtape = require("@logtape/logtape");
7
7
  let _fedify_uri_template = require("@fedify/uri-template");
8
8
  let es_toolkit = require("es-toolkit");
@@ -1,6 +1,6 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as CustomCollectionCursor, A as Rfc6570Expression, At as parseCircuitBreakerKvState, B as createFederationBuilder, C as FederationStartQueueOptions, Ct as CircuitBreakerFailurePolicy, D as InboxListenerSetters, Dt as CircuitBreakerStateChange, E as InboxChallengePolicy, Et as CircuitBreakerState, F as CreateExponentialBackoffPolicyOptions, G as ActorDispatcher, H as respondWithObject, I as RetryContext, J as AuthorizePredicate, K as ActorHandleMapper, L as RetryPolicy, M as FederationOrigin, N as FederationQueueOptions, O as ObjectCallbackSetters, Ot as NormalizedCircuitBreakerOptions, P as createFederation, Q as CustomCollectionCounter, R as createExponentialBackoffPolicy, S as FederationOptions, St as CircuitBreakerCreateOptions, T as IdempotencyStrategy, Tt as CircuitBreakerOptions, U as respondWithObjectIfAcceptable, V as RespondWithObjectOptions, W as ActorAliasMapper, X as CollectionCursor, Y as CollectionCounter, Z as CollectionDispatcher, _ as Federatable, _t as buildCollectionSynchronizationHeader, a as GetSignedKeyOptions, at as ObjectDispatcher, b as FederationBuilder, bt as CircuitBreakerActivityDrop, c as ParseUriResult, ct as OutboxListenerErrorHandler, d as SendActivityOptions, dt as UnverifiedActivityHandler, et as CustomCollectionDispatcher, f as SendActivityOptionsForCollection, ft as UnverifiedActivityReason, g as CustomCollectionCallbackSetters, gt as PageItems, h as ConstructorWithTypeId, ht as SenderKeyPair, i as GetActorOptions, it as ObjectAuthorizePredicate, j as FederationKvPrefixes, k as OutboxListenerSetters, kt as normalizeCircuitBreakerOptions, l as RequestContext, lt as OutboxPermanentFailureHandler, m as CollectionCallbackSetters, mt as SendActivityError, n as Context, nt as InboxListener, o as InboxContext, ot as OutboxErrorHandler, p as ActorCallbackSetters, pt as WebFingerLinksDispatcher, q as ActorKeyPairsDispatcher, r as ForwardActivityOptions, rt as NodeInfoDispatcher, s as OutboxContext, st as OutboxListener, t as ActorKeyPair, tt as InboxErrorHandler, u as RouteActivityOptions, ut as SharedInboxKeyDispatcher, v as Federation, vt as digest, w as IdempotencyKeyCallback, wt as CircuitBreakerKvState, x as FederationFetchOptions, xt as CircuitBreakerBeforeSendDecision, y as FederationBenchmarkOptions, yt as CircuitBreaker, z as Message } from "../context-BpmLyiPx.cjs";
2
+ import { $ as CustomCollectionCursor, A as Rfc6570Expression, At as parseCircuitBreakerKvState, B as createFederationBuilder, C as FederationStartQueueOptions, Ct as CircuitBreakerFailurePolicy, D as InboxListenerSetters, Dt as CircuitBreakerStateChange, E as InboxChallengePolicy, Et as CircuitBreakerState, F as CreateExponentialBackoffPolicyOptions, G as ActorDispatcher, H as respondWithObject, I as RetryContext, J as AuthorizePredicate, K as ActorHandleMapper, L as RetryPolicy, M as FederationOrigin, N as FederationQueueOptions, O as ObjectCallbackSetters, Ot as NormalizedCircuitBreakerOptions, P as createFederation, Q as CustomCollectionCounter, R as createExponentialBackoffPolicy, S as FederationOptions, St as CircuitBreakerCreateOptions, T as IdempotencyStrategy, Tt as CircuitBreakerOptions, U as respondWithObjectIfAcceptable, V as RespondWithObjectOptions, W as ActorAliasMapper, X as CollectionCursor, Y as CollectionCounter, Z as CollectionDispatcher, _ as Federatable, _t as buildCollectionSynchronizationHeader, a as GetSignedKeyOptions, at as ObjectDispatcher, b as FederationBuilder, bt as CircuitBreakerActivityDrop, c as ParseUriResult, ct as OutboxListenerErrorHandler, d as SendActivityOptions, dt as UnverifiedActivityHandler, et as CustomCollectionDispatcher, f as SendActivityOptionsForCollection, ft as UnverifiedActivityReason, g as CustomCollectionCallbackSetters, gt as PageItems, h as ConstructorWithTypeId, ht as SenderKeyPair, i as GetActorOptions, it as ObjectAuthorizePredicate, j as FederationKvPrefixes, k as OutboxListenerSetters, kt as normalizeCircuitBreakerOptions, l as RequestContext, lt as OutboxPermanentFailureHandler, m as CollectionCallbackSetters, mt as SendActivityError, n as Context, nt as InboxListener, o as InboxContext, ot as OutboxErrorHandler, p as ActorCallbackSetters, pt as WebFingerLinksDispatcher, q as ActorKeyPairsDispatcher, r as ForwardActivityOptions, rt as NodeInfoDispatcher, s as OutboxContext, st as OutboxListener, t as ActorKeyPair, tt as InboxErrorHandler, u as RouteActivityOptions, ut as SharedInboxKeyDispatcher, v as Federation, vt as digest, w as IdempotencyKeyCallback, wt as CircuitBreakerKvState, x as FederationFetchOptions, xt as CircuitBreakerBeforeSendDecision, y as FederationBenchmarkOptions, yt as CircuitBreaker, z as Message } from "../context-CSIggG9_.cjs";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-gJ8LYbxX.cjs";
4
4
  import { a as MessageQueueEnqueueOptions, i as MessageQueueDepth, n as InProcessMessageQueueOptions, o as MessageQueueListenOptions, r as MessageQueue, s as ParallelMessageQueue, t as InProcessMessageQueue } from "../mq-D8uSFzxe.cjs";
5
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-CjERT09F.cjs";
5
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-PVR75MeU.cjs";
6
6
  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, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, 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, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,6 +1,6 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as CustomCollectionCursor, A as Rfc6570Expression, At as parseCircuitBreakerKvState, B as createFederationBuilder, C as FederationStartQueueOptions, Ct as CircuitBreakerFailurePolicy, D as InboxListenerSetters, Dt as CircuitBreakerStateChange, E as InboxChallengePolicy, Et as CircuitBreakerState, F as CreateExponentialBackoffPolicyOptions, G as ActorDispatcher, H as respondWithObject, I as RetryContext, J as AuthorizePredicate, K as ActorHandleMapper, L as RetryPolicy, M as FederationOrigin, N as FederationQueueOptions, O as ObjectCallbackSetters, Ot as NormalizedCircuitBreakerOptions, P as createFederation, Q as CustomCollectionCounter, R as createExponentialBackoffPolicy, S as FederationOptions, St as CircuitBreakerCreateOptions, T as IdempotencyStrategy, Tt as CircuitBreakerOptions, U as respondWithObjectIfAcceptable, V as RespondWithObjectOptions, W as ActorAliasMapper, X as CollectionCursor, Y as CollectionCounter, Z as CollectionDispatcher, _ as Federatable, _t as buildCollectionSynchronizationHeader, a as GetSignedKeyOptions, at as ObjectDispatcher, b as FederationBuilder, bt as CircuitBreakerActivityDrop, c as ParseUriResult, ct as OutboxListenerErrorHandler, d as SendActivityOptions, dt as UnverifiedActivityHandler, et as CustomCollectionDispatcher, f as SendActivityOptionsForCollection, ft as UnverifiedActivityReason, g as CustomCollectionCallbackSetters, gt as PageItems, h as ConstructorWithTypeId, ht as SenderKeyPair, i as GetActorOptions, it as ObjectAuthorizePredicate, j as FederationKvPrefixes, k as OutboxListenerSetters, kt as normalizeCircuitBreakerOptions, l as RequestContext, lt as OutboxPermanentFailureHandler, m as CollectionCallbackSetters, mt as SendActivityError, n as Context, nt as InboxListener, o as InboxContext, ot as OutboxErrorHandler, p as ActorCallbackSetters, pt as WebFingerLinksDispatcher, q as ActorKeyPairsDispatcher, r as ForwardActivityOptions, rt as NodeInfoDispatcher, s as OutboxContext, st as OutboxListener, t as ActorKeyPair, tt as InboxErrorHandler, u as RouteActivityOptions, ut as SharedInboxKeyDispatcher, v as Federation, vt as digest, w as IdempotencyKeyCallback, wt as CircuitBreakerKvState, x as FederationFetchOptions, xt as CircuitBreakerBeforeSendDecision, y as FederationBenchmarkOptions, yt as CircuitBreaker, z as Message } from "../context-BxVVO5Ro.js";
2
+ import { $ as CustomCollectionCursor, A as Rfc6570Expression, At as parseCircuitBreakerKvState, B as createFederationBuilder, C as FederationStartQueueOptions, Ct as CircuitBreakerFailurePolicy, D as InboxListenerSetters, Dt as CircuitBreakerStateChange, E as InboxChallengePolicy, Et as CircuitBreakerState, F as CreateExponentialBackoffPolicyOptions, G as ActorDispatcher, H as respondWithObject, I as RetryContext, J as AuthorizePredicate, K as ActorHandleMapper, L as RetryPolicy, M as FederationOrigin, N as FederationQueueOptions, O as ObjectCallbackSetters, Ot as NormalizedCircuitBreakerOptions, P as createFederation, Q as CustomCollectionCounter, R as createExponentialBackoffPolicy, S as FederationOptions, St as CircuitBreakerCreateOptions, T as IdempotencyStrategy, Tt as CircuitBreakerOptions, U as respondWithObjectIfAcceptable, V as RespondWithObjectOptions, W as ActorAliasMapper, X as CollectionCursor, Y as CollectionCounter, Z as CollectionDispatcher, _ as Federatable, _t as buildCollectionSynchronizationHeader, a as GetSignedKeyOptions, at as ObjectDispatcher, b as FederationBuilder, bt as CircuitBreakerActivityDrop, c as ParseUriResult, ct as OutboxListenerErrorHandler, d as SendActivityOptions, dt as UnverifiedActivityHandler, et as CustomCollectionDispatcher, f as SendActivityOptionsForCollection, ft as UnverifiedActivityReason, g as CustomCollectionCallbackSetters, gt as PageItems, h as ConstructorWithTypeId, ht as SenderKeyPair, i as GetActorOptions, it as ObjectAuthorizePredicate, j as FederationKvPrefixes, k as OutboxListenerSetters, kt as normalizeCircuitBreakerOptions, l as RequestContext, lt as OutboxPermanentFailureHandler, m as CollectionCallbackSetters, mt as SendActivityError, n as Context, nt as InboxListener, o as InboxContext, ot as OutboxErrorHandler, p as ActorCallbackSetters, pt as WebFingerLinksDispatcher, q as ActorKeyPairsDispatcher, r as ForwardActivityOptions, rt as NodeInfoDispatcher, s as OutboxContext, st as OutboxListener, t as ActorKeyPair, tt as InboxErrorHandler, u as RouteActivityOptions, ut as SharedInboxKeyDispatcher, v as Federation, vt as digest, w as IdempotencyKeyCallback, wt as CircuitBreakerKvState, x as FederationFetchOptions, xt as CircuitBreakerBeforeSendDecision, y as FederationBenchmarkOptions, yt as CircuitBreaker, z as Message } from "../context-CAKnQy1x.js";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-D6hNiMTK.js";
4
4
  import { a as MessageQueueEnqueueOptions, i as MessageQueueDepth, n as InProcessMessageQueueOptions, o as MessageQueueListenOptions, r as MessageQueue, s as ParallelMessageQueue, t as InProcessMessageQueue } from "../mq-D-nlpY04.js";
5
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-Rpy4Uwkk.js";
5
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-CFuyfw3c.js";
6
6
  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, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, 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, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, 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 SendActivityError, c as buildCollectionSynchronizationHeader, d as normalizeCircuitBreakerOptions, f as parseCircuitBreakerKvState, i as createExponentialBackoffPolicy, l as digest, o as respondWithObject, p as createFederationBuilder, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as CircuitBreaker } from "../middleware-D_cNQ7Yq.js";
3
+ import { a as SendActivityError, c as buildCollectionSynchronizationHeader, d as normalizeCircuitBreakerOptions, f as parseCircuitBreakerKvState, i as createExponentialBackoffPolicy, l as digest, o as respondWithObject, p as createFederationBuilder, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as CircuitBreaker } from "../middleware-DunPXFJL.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";
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { n as assertGreater } from "../std__assert-BBjXFNOb.mjs";
6
6
  import { n as assertGreaterOrEqual, r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
7
- import { t as assert } from "../assert-OguE97r2.mjs";
7
+ import { t as assert } from "../assert-jSdZMYam.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  import { delay } from "es-toolkit";
10
10
  //#region src/federation/mq.ts
@@ -3,8 +3,8 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import "../std__assert-BBjXFNOb.mjs";
5
5
  import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
6
- import { t as assert } from "../assert-OguE97r2.mjs";
7
- import { t as acceptsJsonLd } from "../negotiation-DDstyBvc.mjs";
6
+ import { t as assert } from "../assert-jSdZMYam.mjs";
7
+ import { t as acceptsJsonLd } from "../negotiation-CDW-_gUU.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  //#region src/federation/negotiation.test.ts
10
10
  test("acceptsJsonLd()", () => {
@@ -3,7 +3,7 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { l as AssertionError, t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
6
- import { t as createExponentialBackoffPolicy } from "../retry-CXg_MBI-.mjs";
6
+ import { t as createExponentialBackoffPolicy } from "../retry-_VvV0h9f.mjs";
7
7
  import { test } from "@fedify/fixture";
8
8
  //#region src/federation/retry.test.ts
9
9
  test("createExponentialBackoffPolicy()", () => {
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
6
  import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
7
+ import { t as assert } from "../assert-jSdZMYam.mjs";
7
8
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
8
- import { t as assert } from "../assert-OguE97r2.mjs";
9
9
  import { getLogger } from "@logtape/logtape";
10
10
  import { Router, RouterError, assertPath, isPath } from "@fedify/uri-template";
11
11
  import { test } from "@fedify/fixture";
@@ -5,16 +5,15 @@ import { t as esm_default } from "../esm-vrlUxr60.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
6
6
  import "../std__assert-BBjXFNOb.mjs";
7
7
  import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
8
- import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
8
+ import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
9
9
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
10
- import { t as assert } from "../assert-OguE97r2.mjs";
11
- import { l as verifyRequest } from "../http-BcbYkefs.mjs";
12
- import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
13
- import { t as doesActorOwnKey } from "../owner-CjkdUXE3.mjs";
14
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-i63Det4Y.mjs";
10
+ import { l as verifyRequest } from "../http-ClEDLGpr.mjs";
11
+ import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
12
+ import { t as doesActorOwnKey } from "../owner-CGuS9lE7.mjs";
13
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CC1A7ATC.mjs";
15
14
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
16
15
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
17
- import { FetchError } from "@fedify/vocab-runtime";
16
+ import { FetchError, UrlError } from "@fedify/vocab-runtime";
18
17
  import { AggregationTemporality, InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
19
18
  //#region src/federation/send.test.ts
20
19
  test("extractInboxes()", () => {
@@ -463,6 +462,7 @@ test("sendActivity() records OpenTelemetry delivery metrics", async (t) => {
463
462
  activityId: "https://example.com/activity",
464
463
  activityType: "https://www.w3.org/ns/activitystreams#Create",
465
464
  keys: [],
465
+ allowPrivateAddress: true,
466
466
  inbox: new URL("https://metrics.example:8443/inbox/path?x=1"),
467
467
  meterProvider
468
468
  });
@@ -500,6 +500,7 @@ test("sendActivity() records OpenTelemetry delivery metrics", async (t) => {
500
500
  activityId: "https://example.com/follow",
501
501
  activityType: "https://www.w3.org/ns/activitystreams#Follow",
502
502
  keys: [],
503
+ allowPrivateAddress: true,
503
504
  inbox: new URL("https://metrics.example/inbox"),
504
505
  meterProvider
505
506
  }), SendActivityError);
@@ -537,6 +538,7 @@ test("sendActivity() exports delivery metrics through OpenTelemetry SDK", async
537
538
  activityId: "https://example.com/activity",
538
539
  activityType: "https://www.w3.org/ns/activitystreams#Create",
539
540
  keys: [],
541
+ allowPrivateAddress: true,
540
542
  inbox: new URL("https://sdk-metrics.example/inbox"),
541
543
  meterProvider
542
544
  });
@@ -553,5 +555,137 @@ test("sendActivity() exports delivery metrics through OpenTelemetry SDK", async
553
555
  }
554
556
  }
555
557
  });
558
+ for (const signed of [false, true]) {
559
+ const keys = [{
560
+ privateKey: signed ? rsaPrivateKey2 : ed25519PrivateKey,
561
+ keyId: signed ? rsaPublicKey2.id : ed25519Multikey.id
562
+ }];
563
+ test(`sendActivity() validates destinations (signed: ${signed})`, async (t) => {
564
+ const activity = {
565
+ type: "Create",
566
+ id: "https://example.com/activity"
567
+ };
568
+ const publicInbox = "https://8.8.8.8/inbox";
569
+ const privateInbox = "http://127.0.0.1/inbox";
570
+ for (const target of [
571
+ privateInbox,
572
+ "http://169.254.169.254/",
573
+ "http://[::1]/"
574
+ ]) await t.step(`rejects ${target} before fetching`, async () => {
575
+ esm_default.mockGlobal().catch(202);
576
+ try {
577
+ await assertRejects(() => sendActivity({
578
+ activity,
579
+ keys,
580
+ inbox: new URL(target)
581
+ }), UrlError);
582
+ assertEquals(esm_default.callHistory.calls().length, 0);
583
+ } finally {
584
+ esm_default.hardReset();
585
+ }
586
+ });
587
+ for (const status of [
588
+ 301,
589
+ 302,
590
+ 303,
591
+ 307,
592
+ 308
593
+ ]) for (const allowPrivateAddress of [false, true]) await t.step(`${status} private redirect, opt-in: ${allowPrivateAddress}`, async () => {
594
+ esm_default.mockGlobal();
595
+ esm_default.route(publicInbox, {
596
+ status,
597
+ headers: { Location: privateInbox }
598
+ });
599
+ esm_default.route(privateInbox, 202);
600
+ try {
601
+ const send = () => sendActivity({
602
+ activity,
603
+ keys,
604
+ inbox: new URL(publicInbox),
605
+ allowPrivateAddress
606
+ });
607
+ if (allowPrivateAddress) {
608
+ await send();
609
+ const calls = esm_default.callHistory.calls(privateInbox);
610
+ assertEquals(calls.length, 1);
611
+ const request = calls[0].request;
612
+ const preservesBody = signed || status === 307 || status === 308;
613
+ assertEquals(request.method, preservesBody ? "POST" : "GET");
614
+ assertEquals(await request.clone().text(), preservesBody ? JSON.stringify(activity) : "");
615
+ } else {
616
+ await assertRejects(send, UrlError);
617
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 0);
618
+ }
619
+ } finally {
620
+ esm_default.hardReset();
621
+ }
622
+ });
623
+ await t.step("rejects a private destination after a public redirect", async () => {
624
+ esm_default.mockGlobal().route(publicInbox, {
625
+ status: 307,
626
+ headers: { Location: "/next" }
627
+ }).route("https://8.8.8.8/next", {
628
+ status: 308,
629
+ headers: { Location: privateInbox }
630
+ }).route(privateInbox, 202);
631
+ try {
632
+ await assertRejects(() => sendActivity({
633
+ activity,
634
+ keys,
635
+ inbox: new URL(publicInbox)
636
+ }), UrlError);
637
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 0);
638
+ } finally {
639
+ esm_default.hardReset();
640
+ }
641
+ });
642
+ await t.step("limits redirect loops", async () => {
643
+ esm_default.mockGlobal().route(publicInbox, {
644
+ status: 307,
645
+ headers: { Location: publicInbox }
646
+ });
647
+ try {
648
+ await assertRejects(() => sendActivity({
649
+ activity,
650
+ keys,
651
+ inbox: new URL(publicInbox)
652
+ }));
653
+ assert(esm_default.callHistory.calls().length <= 21);
654
+ } finally {
655
+ esm_default.hardReset();
656
+ }
657
+ });
658
+ await t.step("allows a direct private inbox with opt-in", async () => {
659
+ esm_default.mockGlobal().route(privateInbox, 202);
660
+ try {
661
+ await sendActivity({
662
+ activity,
663
+ keys,
664
+ inbox: new URL(privateInbox),
665
+ allowPrivateAddress: true
666
+ });
667
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 1);
668
+ } finally {
669
+ esm_default.hardReset();
670
+ }
671
+ });
672
+ await t.step("allows relative public redirects", async () => {
673
+ esm_default.mockGlobal().route(publicInbox, {
674
+ status: 307,
675
+ headers: { Location: "/next" }
676
+ }).route("https://8.8.8.8/next", 202);
677
+ try {
678
+ await sendActivity({
679
+ activity,
680
+ keys,
681
+ inbox: new URL(publicInbox)
682
+ });
683
+ assertEquals(esm_default.callHistory.calls("https://8.8.8.8/next").length, 1);
684
+ } finally {
685
+ esm_default.hardReset();
686
+ }
687
+ });
688
+ });
689
+ }
556
690
  //#endregion
557
691
  export {};
@@ -3,8 +3,8 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import "../std__assert-BBjXFNOb.mjs";
5
5
  import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
6
- import { t as assert } from "../assert-OguE97r2.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-CcVjTX30.mjs";
6
+ import { t as assert } from "../assert-jSdZMYam.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-DvptXZ7V.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  //#region src/federation/temporal.test.ts
10
10
  test("hasMalformedKnownTemporalLiteral() detects expanded proof timestamps", async () => {
@@ -1,12 +1,12 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { r as createRequestContext } from "../context-DVoTs_wM.mjs";
4
+ import { r as createRequestContext } from "../context-BepjCFHN.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
6
6
  import "../std__assert-BBjXFNOb.mjs";
7
7
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
8
- import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-3L9f9ZTw.mjs";
8
+ import { t as MemoryKvStore } from "../kv-CX8qfaad.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-COzI8bCL.mjs";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  import { createTestMeterProvider, test } from "@fedify/fixture";
12
12
  //#region src/federation/webfinger.test.ts