@fedify/fedify 2.4.0-dev.1962 → 2.4.0-dev.1988

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 (83) hide show
  1. package/dist/{builder-CWYQXC2W.mjs → builder-Cts78G9N.mjs} +2 -2
  2. package/dist/{client-CtxvmazV.mjs → client-DpnpgjyX.mjs} +78 -4
  3. package/dist/compat/mod.d.cts +1 -1
  4. package/dist/compat/mod.d.ts +1 -1
  5. package/dist/compat/transformers.test.mjs +1 -1
  6. package/dist/{context-COLwHogJ.d.cts → context-BeDnDuF3.d.cts} +4 -3
  7. package/dist/{context-DiiCt4S7.d.ts → context-uyRUWoZQ.d.ts} +4 -3
  8. package/dist/{deno-CfLMX4HF.mjs → deno-BgMEefEr.mjs} +1 -1
  9. package/dist/{docloader-CDmmYxYb.mjs → docloader-DEYs99FZ.mjs} +2 -2
  10. package/dist/federation/builder.test.mjs +1 -1
  11. package/dist/federation/handler.test.mjs +122 -4
  12. package/dist/federation/idempotency.test.mjs +2 -2
  13. package/dist/federation/keycache.test.mjs +52 -9
  14. package/dist/federation/metrics.test.mjs +1 -1
  15. package/dist/federation/middleware.test.mjs +111 -15
  16. package/dist/federation/mod.cjs +1 -1
  17. package/dist/federation/mod.d.cts +2 -2
  18. package/dist/federation/mod.d.ts +2 -2
  19. package/dist/federation/mod.js +1 -1
  20. package/dist/federation/send.test.mjs +139 -4
  21. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  22. package/dist/federation/tasks/tasks.test.mjs +2 -2
  23. package/dist/federation/temporal.test.mjs +1 -1
  24. package/dist/federation/webfinger.test.mjs +1 -1
  25. package/dist/{federation-CIeDMHxZ.cjs → federation-DzPUG_AP.cjs} +93 -17
  26. package/dist/{http-6TI0tI03.d.cts → http-65PYi9jY.d.ts} +34 -2
  27. package/dist/{http-CdrSn2ip.d.ts → http-CP-7OdSq.d.cts} +34 -2
  28. package/dist/{http-DWZZicb2.js → http-CgwqtxAy.js} +169 -7
  29. package/dist/{http-BR190IDB.mjs → http-CtidZS_t.mjs} +3 -3
  30. package/dist/{http-C3kkrvAE.cjs → http-Z3anvCd-.cjs} +180 -6
  31. package/dist/{key-BcA-AzPp.mjs → key-Cwbg5ggV.mjs} +169 -7
  32. package/dist/{keycache-ZLqIfrkL.mjs → keycache-BUDHB5rY.mjs} +12 -4
  33. package/dist/{kv-cache-DCItgZUM.cjs → kv-cache-BM2-w-Wq.cjs} +2 -2
  34. package/dist/{kv-cache-5d2HgB_-.js → kv-cache-CykuL0ya.js} +2 -2
  35. package/dist/{kv-cache-m962_cok.mjs → kv-cache-DHiR8yTf.mjs} +1 -1
  36. package/dist/{ld-QpPkmUjy.mjs → ld-CzhdWyTt.mjs} +3 -3
  37. package/dist/{metrics-Dkyzq7ml.mjs → metrics-CrqsHP0l.mjs} +1 -1
  38. package/dist/{middleware-BdKtWJK1.mjs → middleware-CZpYxSKD.mjs} +1 -1
  39. package/dist/{middleware-BNktRUnj.js → middleware-CeCj5caM.js} +101 -25
  40. package/dist/{middleware-BaZ32nCi.mjs → middleware-DCpiAsZi.mjs} +34 -23
  41. package/dist/{mod-DypxPS9H.d.ts → mod-C0BYc0OU.d.ts} +1 -1
  42. package/dist/{mod-CnGLNoVw.d.cts → mod-CbKDOnCt.d.cts} +1 -1
  43. package/dist/{mod-CLHkCwLm.d.cts → mod-CyiSjRkk.d.cts} +1 -1
  44. package/dist/{mod-CSH1Ee-I.d.ts → mod-D882_Xsg.d.ts} +1 -1
  45. package/dist/{mod-DzRXACM5.d.ts → mod-UDwMjuHM.d.ts} +1 -1
  46. package/dist/{mod-BZldCEU0.d.cts → mod-x9W0d0Pk.d.cts} +1 -1
  47. package/dist/mod.cjs +5 -5
  48. package/dist/mod.d.cts +6 -6
  49. package/dist/mod.d.ts +6 -6
  50. package/dist/mod.js +5 -5
  51. package/dist/nodeinfo/client.test.mjs +28 -1
  52. package/dist/nodeinfo/handler.test.mjs +1 -1
  53. package/dist/nodeinfo/mod.cjs +1 -1
  54. package/dist/nodeinfo/mod.js +1 -1
  55. package/dist/{owner-r_waTiQj.d.cts → owner-BF0L9cMt.d.cts} +11 -0
  56. package/dist/{owner-DGSfntI-.d.ts → owner-BSzr5-I8.d.ts} +11 -0
  57. package/dist/owner-BqVXJLW8.mjs +175 -0
  58. package/dist/{proof-DrWB_vel.js → proof-CUghqhAf.js} +122 -65
  59. package/dist/{proof-CYdLcTFg.cjs → proof-DHu5zI0Z.cjs} +122 -65
  60. package/dist/{proof-Mov6-gSw.mjs → proof-DL8Iid3a.mjs} +14 -11
  61. package/dist/{send-DB1mkFKO.mjs → send-6jS4xFsX.mjs} +68 -11
  62. package/dist/sig/http.test.mjs +2 -2
  63. package/dist/sig/key.test.mjs +169 -2
  64. package/dist/sig/ld.test.mjs +55 -2
  65. package/dist/sig/mod.cjs +2 -2
  66. package/dist/sig/mod.d.cts +3 -3
  67. package/dist/sig/mod.d.ts +3 -3
  68. package/dist/sig/mod.js +2 -2
  69. package/dist/sig/owner.test.mjs +103 -4
  70. package/dist/sig/proof.test.mjs +143 -2
  71. package/dist/{temporal-Yi0JAV9z.mjs → temporal-DcyzeytP.mjs} +1 -1
  72. package/dist/testing/kv.test.mjs +1 -1
  73. package/dist/testing/mod.d.mts +2 -1
  74. package/dist/{types-RXm5YxpC.cjs → types-Be2zbyeG.cjs} +94 -2
  75. package/dist/{types-Dtyf8lVj.js → types-C_cNlNVK.js} +78 -4
  76. package/dist/utils/docloader.test.mjs +27 -3
  77. package/dist/utils/kv-cache.test.mjs +1 -1
  78. package/dist/utils/mod.cjs +1 -1
  79. package/dist/utils/mod.d.cts +1 -1
  80. package/dist/utils/mod.d.ts +1 -1
  81. package/dist/utils/mod.js +1 -1
  82. package/package.json +7 -7
  83. package/dist/owner-B795xXwU.mjs +0 -120
@@ -16,14 +16,14 @@ import "../std__assert-CxFT0MNt.mjs";
16
16
  import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
17
17
  import { t as assertStrictEquals } from "../assert_strict_equals-Bpjl4Psw.mjs";
18
18
  import { t as assert } from "../assert-CebeUf0C.mjs";
19
- import { g as recordInboxActivity } from "../metrics-Dkyzq7ml.mjs";
20
- import { l as verifyRequest, s as signRequest } from "../http-BR190IDB.mjs";
19
+ import { g as recordInboxActivity } from "../metrics-CrqsHP0l.mjs";
20
+ import { l as verifyRequest, s as signRequest } from "../http-CtidZS_t.mjs";
21
21
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
22
- import { t as getAuthenticatedDocumentLoader } from "../docloader-CDmmYxYb.mjs";
23
- import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-BaZ32nCi.mjs";
24
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-QpPkmUjy.mjs";
25
- import { t as doesActorOwnKey } from "../owner-B795xXwU.mjs";
26
- import { i as verifyObject, r as signObject } from "../proof-Mov6-gSw.mjs";
22
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-DEYs99FZ.mjs";
23
+ import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-DCpiAsZi.mjs";
24
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-CzhdWyTt.mjs";
25
+ import { t as doesActorOwnKey } from "../owner-BqVXJLW8.mjs";
26
+ import { i as verifyObject, r as signObject } from "../proof-DL8Iid3a.mjs";
27
27
  import { t as CircuitBreaker } from "../circuit-breaker-C5NqoLBJ.mjs";
28
28
  import { t as TaskCodec } from "../codec-C6rTrpIp.mjs";
29
29
  import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-DW6YC_Pe.mjs";
@@ -33,7 +33,7 @@ import * as vocab from "@fedify/vocab";
33
33
  import { Create, Note, Offer, Person, getTypeId, lookupObject } from "@fedify/vocab";
34
34
  import { SpanStatusCode, metrics } from "@opentelemetry/api";
35
35
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
36
- import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
36
+ import { FetchError, UrlError, getDocumentLoader } from "@fedify/vocab-runtime";
37
37
  import { deepStrictEqual, ok, rejects, strictEqual } from "node:assert/strict";
38
38
  import serialize from "json-canon";
39
39
  import { DataPointType, MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
@@ -2165,7 +2165,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2165
2165
  const records = [];
2166
2166
  await reset();
2167
2167
  esm_default.spyGlobal();
2168
- esm_default.post("https://remote.example/inbox", {
2168
+ esm_default.post("https://example.com/inbox", {
2169
2169
  status: 202,
2170
2170
  body: "Accepted"
2171
2171
  });
@@ -2191,7 +2191,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2191
2191
  federation.setOutboxListeners("/users/{identifier}/outbox").on(vocab.Activity, async (ctx, activity) => {
2192
2192
  await ctx.sendActivity({ identifier: ctx.identifier }, new vocab.Person({
2193
2193
  id: new URL("https://remote.example/users/alice"),
2194
- inbox: new URL("https://remote.example/inbox")
2194
+ inbox: new URL("https://example.com/inbox")
2195
2195
  }), activity);
2196
2196
  }).authorize((ctx, identifier) => {
2197
2197
  return identifier === "john" && ctx.request.headers.get("authorization") === "Bearer token";
@@ -2267,7 +2267,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2267
2267
  let ldsVerified = false;
2268
2268
  await reset();
2269
2269
  esm_default.spyGlobal();
2270
- esm_default.post("https://remote.example/inbox", async (cl) => {
2270
+ esm_default.post("https://example.com/inbox", async (cl) => {
2271
2271
  const verifyOptions = {
2272
2272
  documentLoader: mockDocumentLoader,
2273
2273
  contextLoader: mockDocumentLoader
@@ -2300,7 +2300,7 @@ test("Federation.setOutboxListeners()", async (t) => {
2300
2300
  keyId: rsaPublicKey2.id
2301
2301
  }], {
2302
2302
  id: new URL("https://remote.example/users/alice"),
2303
- inboxId: new URL("https://remote.example/inbox")
2303
+ inboxId: new URL("https://example.com/inbox")
2304
2304
  }, { skipIfUnsigned: true });
2305
2305
  }).authorize((ctx, identifier) => {
2306
2306
  return identifier === "person2" && ctx.request.headers.get("authorization") === "Bearer token";
@@ -3110,6 +3110,7 @@ test("FederationImpl.processQueuedTask()", async (t) => {
3110
3110
  const kv = new MemoryKvStore();
3111
3111
  const queuedMessages = [];
3112
3112
  const federation = new FederationImpl({
3113
+ allowPrivateAddress: true,
3113
3114
  kv,
3114
3115
  queue: {
3115
3116
  nativeRetrial: true,
@@ -3172,6 +3173,7 @@ test("FederationImpl.processQueuedTask()", async (t) => {
3172
3173
  const kv = new MemoryKvStore();
3173
3174
  let queuedMessages = [];
3174
3175
  const federation = new FederationImpl({
3176
+ allowPrivateAddress: true,
3175
3177
  kv,
3176
3178
  queue: {
3177
3179
  enqueue(message, _options) {
@@ -3242,6 +3244,7 @@ test("FederationImpl.processQueuedTask()", async (t) => {
3242
3244
  const kv = new MemoryKvStore();
3243
3245
  const [meterProvider, recorder] = createTestMeterProvider();
3244
3246
  await new FederationImpl({
3247
+ allowPrivateAddress: true,
3245
3248
  kv,
3246
3249
  meterProvider,
3247
3250
  queue: {
@@ -3284,6 +3287,7 @@ test("FederationImpl.processQueuedTask()", async (t) => {
3284
3287
  const kv = new MemoryKvStore();
3285
3288
  const [meterProvider, recorder] = createTestMeterProvider();
3286
3289
  await new FederationImpl({
3290
+ allowPrivateAddress: true,
3287
3291
  kv,
3288
3292
  meterProvider,
3289
3293
  queue: {
@@ -4972,6 +4976,7 @@ test("FederationImpl.processQueuedTask() permanent failure", async (t) => {
4972
4976
  return Promise.resolve();
4973
4977
  }
4974
4978
  },
4979
+ allowPrivateAddress: true,
4975
4980
  ...options.permanentFailureStatusCodes ? { permanentFailureStatusCodes: options.permanentFailureStatusCodes } : {},
4976
4981
  ...options.meterProvider ? { meterProvider: options.meterProvider } : {},
4977
4982
  ...options.tracerProvider ? { tracerProvider: options.tracerProvider } : {}
@@ -5170,6 +5175,7 @@ test("FederationImpl.processQueuedTask() circuit breaker", async (t) => {
5170
5175
  return Promise.resolve();
5171
5176
  }
5172
5177
  },
5178
+ allowPrivateAddress: true,
5173
5179
  circuitBreaker: options,
5174
5180
  ...federationOptions
5175
5181
  });
@@ -6183,7 +6189,8 @@ test("FederationImpl.processQueuedTask() queue task metrics", async (t) => {
6183
6189
  listen(_handler, _options) {
6184
6190
  return Promise.resolve();
6185
6191
  }
6186
- }
6192
+ },
6193
+ allowPrivateAddress: true
6187
6194
  });
6188
6195
  federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
6189
6196
  esm_default.spyGlobal();
@@ -7523,6 +7530,7 @@ test("createFederation() applies publicKeyTtl to cached public keys", async () =
7523
7530
  const publicKeyKey = [
7524
7531
  "_fedify",
7525
7532
  "publicKey",
7533
+ "2",
7526
7534
  keyId
7527
7535
  ];
7528
7536
  assertEquals((await deliver()).status, 202);
@@ -7530,10 +7538,11 @@ test("createFederation() applies publicKeyTtl to cached public keys", async () =
7530
7538
  assert(keyFetches > 0);
7531
7539
  assert(await kv.get(publicKeyKey) != null);
7532
7540
  assertEquals(kv.lastTtl(publicKeyKey)?.total("day"), 7);
7533
- keyFetches = 0;
7541
+ const keyCacheWrites = () => kv.writes.filter((w) => w.key.length === publicKeyKey.length && w.key.every((part, i) => part === publicKeyKey[i])).length;
7542
+ const warmWrites = keyCacheWrites();
7534
7543
  assertEquals((await deliver()).status, 202);
7535
7544
  assertEquals(inbox.length, 2);
7536
- assertEquals(keyFetches, 0);
7545
+ assertEquals(keyCacheWrites(), warmWrites);
7537
7546
  kv.advance({ days: 8 });
7538
7547
  assertEquals(await kv.get(publicKeyKey), void 0);
7539
7548
  keyFetches = 0;
@@ -7786,5 +7795,92 @@ test("ContextImpl.enqueueTaskMany()", async (t) => {
7786
7795
  strictEqual(queue.enqueued.length, 0);
7787
7796
  });
7788
7797
  });
7798
+ test("ContextImpl.sendActivity() honors the private-address policy", async (t) => {
7799
+ for (const allowPrivateAddress of [false, true]) await t.step(`allowPrivateAddress: ${allowPrivateAddress}`, async () => {
7800
+ const inbox = "http://127.0.0.1/inbox";
7801
+ esm_default.mockGlobal().post(inbox, 202);
7802
+ try {
7803
+ const ctx = createFederation({
7804
+ kv: new MemoryKvStore(),
7805
+ allowPrivateAddress
7806
+ }).createContext(new URL("https://example.com/"));
7807
+ const send = () => ctx.sendActivity({
7808
+ privateKey: ed25519PrivateKey,
7809
+ keyId: ed25519Multikey.id
7810
+ }, new Person({
7811
+ id: new URL("https://example.com/recipient"),
7812
+ inbox: new URL(inbox)
7813
+ }), new Create({
7814
+ id: new URL("https://example.com/activity"),
7815
+ actor: new URL("https://example.com/person")
7816
+ }), { immediate: true });
7817
+ if (allowPrivateAddress) {
7818
+ await send();
7819
+ assertEquals(esm_default.callHistory.calls(inbox).length, 1);
7820
+ } else {
7821
+ await assertRejects(send, UrlError);
7822
+ assertEquals(esm_default.callHistory.calls(inbox).length, 0);
7823
+ }
7824
+ } finally {
7825
+ esm_default.hardReset();
7826
+ }
7827
+ });
7828
+ });
7829
+ test("Federation.fetch() bounds inbox bodies before dispatch", async () => {
7830
+ let dispatched = false;
7831
+ const json = JSON.stringify({
7832
+ "@context": "https://www.w3.org/ns/activitystreams",
7833
+ id: "https://example.com/activities/bounded",
7834
+ type: "Create",
7835
+ actor: "https://example.com/actor"
7836
+ });
7837
+ const federation = createFederation({
7838
+ kv: new MemoryKvStore(),
7839
+ skipSignatureVerification: true,
7840
+ contextLoaderFactory: () => mockDocumentLoader
7841
+ });
7842
+ federation.setActorDispatcher("/actors/{identifier}", () => new Person({ id: new URL("https://example.com/actor") }));
7843
+ federation.setInboxListeners("/actors/{identifier}/inbox", "/inbox").on(Create, () => {
7844
+ dispatched = true;
7845
+ });
7846
+ for (const contentLength of [
7847
+ void 0,
7848
+ "1",
7849
+ String(16777217)
7850
+ ]) {
7851
+ assertEquals((await federation.fetch(new Request("https://example.com/inbox", {
7852
+ method: "POST",
7853
+ headers: contentLength == null ? {} : { "Content-Length": contentLength },
7854
+ body: json.padEnd(16777217)
7855
+ }), { contextData: void 0 })).status, 413);
7856
+ assertFalse(dispatched);
7857
+ }
7858
+ let canceled = false;
7859
+ let pulls = 0;
7860
+ const body = new ReadableStream({
7861
+ pull(controller) {
7862
+ pulls++;
7863
+ controller.enqueue(new Uint8Array(64 * 1024));
7864
+ },
7865
+ cancel() {
7866
+ canceled = true;
7867
+ }
7868
+ }, { highWaterMark: 0 });
7869
+ const request = new Request("https://example.com/inbox", {
7870
+ method: "POST",
7871
+ body,
7872
+ duplex: "half"
7873
+ });
7874
+ assertEquals((await federation.fetch(request, { contextData: void 0 })).status, 413);
7875
+ await new Promise((resolve) => setTimeout(resolve, 0));
7876
+ assert(canceled);
7877
+ assert(pulls <= 260);
7878
+ assertFalse(dispatched);
7879
+ assertEquals((await federation.fetch(new Request("https://example.com/inbox", {
7880
+ method: "POST",
7881
+ body: json
7882
+ }), { contextData: void 0 })).status, 202);
7883
+ assert(dispatched);
7884
+ });
7789
7885
  //#endregion
7790
7886
  export {};
@@ -1,6 +1,6 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_federation = require("../federation-CIeDMHxZ.cjs");
3
+ const require_federation = require("../federation-DzPUG_AP.cjs");
4
4
  exports.CircuitBreaker = require_federation.CircuitBreaker;
5
5
  exports.InProcessMessageQueue = require_federation.InProcessMessageQueue;
6
6
  exports.MemoryKvStore = require_federation.MemoryKvStore;
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthorizePredicate, B as TaskEnqueueOptions, Bt as SendActivityError, C as FederationStartQueueOptions, Ct as CustomCollectionCounter, D as InboxListenerSetters, Dt as InboxListener, E as InboxChallengePolicy, Et as InboxErrorHandler, F as createFederation, Ft as OutboxPermanentFailureHandler, G as RetryPolicy, H as TaskRegistry, Ht as PageItems, I as Message, It as SharedInboxKeyDispatcher, J as respondWithObject, K as createExponentialBackoffPolicy, L as createFederationBuilder, Lt as UnverifiedActivityHandler, M as FederationKvPrefixes, Mt as OutboxErrorHandler, N as FederationOrigin, Nt as OutboxListener, O as MediaUploaderSetters, Ot as MediaUploaderCallback, P as FederationQueueOptions, Pt as OutboxListenerErrorHandler, Q as MessageQueue, R as TaskDefinition, Rt as UnverifiedActivityReason, S as FederationOptions, St as CollectionDispatcher, T as IdempotencyStrategy, Tt as CustomCollectionDispatcher, U as CreateExponentialBackoffPolicyOptions, Ut as buildCollectionSynchronizationHeader, V as TaskHandler, Vt as SenderKeyPair, W as RetryContext, Wt as digest, X as InProcessMessageQueue, Y as respondWithObjectIfAcceptable, Z as InProcessMessageQueueOptions, _ as Federatable, _t as ActorHandleMapper, a as GetSignedKeyOptions, at as CircuitBreakerBeforeSendDecision, b as FederationBuilder, bt as CollectionCounter, c as ParseUriResult, ct as CircuitBreakerKvState, d as SendActivityOptions, dt as CircuitBreakerStateChange, et as MessageQueueEnqueueOptions, f as SendActivityOptionsForCollection, ft as NormalizedCircuitBreakerOptions, g as CustomCollectionCallbackSetters, gt as ActorDispatcher, h as ConstructorWithTypeId, ht as ActorAliasMapper, i as GetActorOptions, it as CircuitBreakerActivityDrop, j as Rfc6570Expression, jt as ObjectDispatcher, k as ObjectCallbackSetters, kt as NodeInfoDispatcher, l as RequestContext, lt as CircuitBreakerOptions, m as CollectionCallbackSetters, mt as parseCircuitBreakerKvState, n as Context, nt as ParallelMessageQueue, o as InboxContext, ot as CircuitBreakerCreateOptions, p as ActorCallbackSetters, pt as normalizeCircuitBreakerOptions, q as RespondWithObjectOptions, r as ForwardActivityOptions, rt as CircuitBreaker, s as OutboxContext, st as CircuitBreakerFailurePolicy, t as ActorKeyPair, tt as MessageQueueListenOptions, u as RouteActivityOptions, ut as CircuitBreakerState, v as Federation, vt as ActorKeyPairsDispatcher, w as IdempotencyKeyCallback, wt as CustomCollectionCursor, x as FederationFetchOptions, xt as CollectionCursor, y as FederationBenchmarkOptions, yt as AuthorizePredicate, z as TaskDefinitionOptions, zt as WebFingerLinksDispatcher } from "../context-COLwHogJ.cjs";
2
+ import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthorizePredicate, B as TaskEnqueueOptions, Bt as SendActivityError, C as FederationStartQueueOptions, Ct as CustomCollectionCounter, D as InboxListenerSetters, Dt as InboxListener, E as InboxChallengePolicy, Et as InboxErrorHandler, F as createFederation, Ft as OutboxPermanentFailureHandler, G as RetryPolicy, H as TaskRegistry, Ht as PageItems, I as Message, It as SharedInboxKeyDispatcher, J as respondWithObject, K as createExponentialBackoffPolicy, L as createFederationBuilder, Lt as UnverifiedActivityHandler, M as FederationKvPrefixes, Mt as OutboxErrorHandler, N as FederationOrigin, Nt as OutboxListener, O as MediaUploaderSetters, Ot as MediaUploaderCallback, P as FederationQueueOptions, Pt as OutboxListenerErrorHandler, Q as MessageQueue, R as TaskDefinition, Rt as UnverifiedActivityReason, S as FederationOptions, St as CollectionDispatcher, T as IdempotencyStrategy, Tt as CustomCollectionDispatcher, U as CreateExponentialBackoffPolicyOptions, Ut as buildCollectionSynchronizationHeader, V as TaskHandler, Vt as SenderKeyPair, W as RetryContext, Wt as digest, X as InProcessMessageQueue, Y as respondWithObjectIfAcceptable, Z as InProcessMessageQueueOptions, _ as Federatable, _t as ActorHandleMapper, a as GetSignedKeyOptions, at as CircuitBreakerBeforeSendDecision, b as FederationBuilder, bt as CollectionCounter, c as ParseUriResult, ct as CircuitBreakerKvState, d as SendActivityOptions, dt as CircuitBreakerStateChange, et as MessageQueueEnqueueOptions, f as SendActivityOptionsForCollection, ft as NormalizedCircuitBreakerOptions, g as CustomCollectionCallbackSetters, gt as ActorDispatcher, h as ConstructorWithTypeId, ht as ActorAliasMapper, i as GetActorOptions, it as CircuitBreakerActivityDrop, j as Rfc6570Expression, jt as ObjectDispatcher, k as ObjectCallbackSetters, kt as NodeInfoDispatcher, l as RequestContext, lt as CircuitBreakerOptions, m as CollectionCallbackSetters, mt as parseCircuitBreakerKvState, n as Context, nt as ParallelMessageQueue, o as InboxContext, ot as CircuitBreakerCreateOptions, p as ActorCallbackSetters, pt as normalizeCircuitBreakerOptions, q as RespondWithObjectOptions, r as ForwardActivityOptions, rt as CircuitBreaker, s as OutboxContext, st as CircuitBreakerFailurePolicy, t as ActorKeyPair, tt as MessageQueueListenOptions, u as RouteActivityOptions, ut as CircuitBreakerState, v as Federation, vt as ActorKeyPairsDispatcher, w as IdempotencyKeyCallback, wt as CustomCollectionCursor, x as FederationFetchOptions, xt as CollectionCursor, y as FederationBenchmarkOptions, yt as AuthorizePredicate, z as TaskDefinitionOptions, zt as WebFingerLinksDispatcher } from "../context-BeDnDuF3.cjs";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-BhNbN8Ed.cjs";
4
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-BZldCEU0.cjs";
4
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-x9W0d0Pk.cjs";
5
5
  export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthorizePredicate, B as TaskEnqueueOptions, Bt as SendActivityError, C as FederationStartQueueOptions, Ct as CustomCollectionCounter, D as InboxListenerSetters, Dt as InboxListener, E as InboxChallengePolicy, Et as InboxErrorHandler, F as createFederation, Ft as OutboxPermanentFailureHandler, G as RetryPolicy, H as TaskRegistry, Ht as PageItems, I as Message, It as SharedInboxKeyDispatcher, J as respondWithObject, K as createExponentialBackoffPolicy, L as createFederationBuilder, Lt as UnverifiedActivityHandler, M as FederationKvPrefixes, Mt as OutboxErrorHandler, N as FederationOrigin, Nt as OutboxListener, O as MediaUploaderSetters, Ot as MediaUploaderCallback, P as FederationQueueOptions, Pt as OutboxListenerErrorHandler, Q as MessageQueue, R as TaskDefinition, Rt as UnverifiedActivityReason, S as FederationOptions, St as CollectionDispatcher, T as IdempotencyStrategy, Tt as CustomCollectionDispatcher, U as CreateExponentialBackoffPolicyOptions, Ut as buildCollectionSynchronizationHeader, V as TaskHandler, Vt as SenderKeyPair, W as RetryContext, Wt as digest, X as InProcessMessageQueue, Y as respondWithObjectIfAcceptable, Z as InProcessMessageQueueOptions, _ as Federatable, _t as ActorHandleMapper, a as GetSignedKeyOptions, at as CircuitBreakerBeforeSendDecision, b as FederationBuilder, bt as CollectionCounter, c as ParseUriResult, ct as CircuitBreakerKvState, d as SendActivityOptions, dt as CircuitBreakerStateChange, et as MessageQueueEnqueueOptions, f as SendActivityOptionsForCollection, ft as NormalizedCircuitBreakerOptions, g as CustomCollectionCallbackSetters, gt as ActorDispatcher, h as ConstructorWithTypeId, ht as ActorAliasMapper, i as GetActorOptions, it as CircuitBreakerActivityDrop, j as Rfc6570Expression, jt as ObjectDispatcher, k as ObjectCallbackSetters, kt as NodeInfoDispatcher, l as RequestContext, lt as CircuitBreakerOptions, m as CollectionCallbackSetters, mt as parseCircuitBreakerKvState, n as Context, nt as ParallelMessageQueue, o as InboxContext, ot as CircuitBreakerCreateOptions, p as ActorCallbackSetters, pt as normalizeCircuitBreakerOptions, q as RespondWithObjectOptions, r as ForwardActivityOptions, rt as CircuitBreaker, s as OutboxContext, st as CircuitBreakerFailurePolicy, t as ActorKeyPair, tt as MessageQueueListenOptions, u as RouteActivityOptions, ut as CircuitBreakerState, v as Federation, vt as ActorKeyPairsDispatcher, w as IdempotencyKeyCallback, wt as CustomCollectionCursor, x as FederationFetchOptions, xt as CollectionCursor, y as FederationBenchmarkOptions, yt as AuthorizePredicate, z as TaskDefinitionOptions, zt as WebFingerLinksDispatcher } from "../context-DiiCt4S7.js";
2
+ import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthorizePredicate, B as TaskEnqueueOptions, Bt as SendActivityError, C as FederationStartQueueOptions, Ct as CustomCollectionCounter, D as InboxListenerSetters, Dt as InboxListener, E as InboxChallengePolicy, Et as InboxErrorHandler, F as createFederation, Ft as OutboxPermanentFailureHandler, G as RetryPolicy, H as TaskRegistry, Ht as PageItems, I as Message, It as SharedInboxKeyDispatcher, J as respondWithObject, K as createExponentialBackoffPolicy, L as createFederationBuilder, Lt as UnverifiedActivityHandler, M as FederationKvPrefixes, Mt as OutboxErrorHandler, N as FederationOrigin, Nt as OutboxListener, O as MediaUploaderSetters, Ot as MediaUploaderCallback, P as FederationQueueOptions, Pt as OutboxListenerErrorHandler, Q as MessageQueue, R as TaskDefinition, Rt as UnverifiedActivityReason, S as FederationOptions, St as CollectionDispatcher, T as IdempotencyStrategy, Tt as CustomCollectionDispatcher, U as CreateExponentialBackoffPolicyOptions, Ut as buildCollectionSynchronizationHeader, V as TaskHandler, Vt as SenderKeyPair, W as RetryContext, Wt as digest, X as InProcessMessageQueue, Y as respondWithObjectIfAcceptable, Z as InProcessMessageQueueOptions, _ as Federatable, _t as ActorHandleMapper, a as GetSignedKeyOptions, at as CircuitBreakerBeforeSendDecision, b as FederationBuilder, bt as CollectionCounter, c as ParseUriResult, ct as CircuitBreakerKvState, d as SendActivityOptions, dt as CircuitBreakerStateChange, et as MessageQueueEnqueueOptions, f as SendActivityOptionsForCollection, ft as NormalizedCircuitBreakerOptions, g as CustomCollectionCallbackSetters, gt as ActorDispatcher, h as ConstructorWithTypeId, ht as ActorAliasMapper, i as GetActorOptions, it as CircuitBreakerActivityDrop, j as Rfc6570Expression, jt as ObjectDispatcher, k as ObjectCallbackSetters, kt as NodeInfoDispatcher, l as RequestContext, lt as CircuitBreakerOptions, m as CollectionCallbackSetters, mt as parseCircuitBreakerKvState, n as Context, nt as ParallelMessageQueue, o as InboxContext, ot as CircuitBreakerCreateOptions, p as ActorCallbackSetters, pt as normalizeCircuitBreakerOptions, q as RespondWithObjectOptions, r as ForwardActivityOptions, rt as CircuitBreaker, s as OutboxContext, st as CircuitBreakerFailurePolicy, t as ActorKeyPair, tt as MessageQueueListenOptions, u as RouteActivityOptions, ut as CircuitBreakerState, v as Federation, vt as ActorKeyPairsDispatcher, w as IdempotencyKeyCallback, wt as CustomCollectionCursor, x as FederationFetchOptions, xt as CollectionCursor, y as FederationBenchmarkOptions, yt as AuthorizePredicate, z as TaskDefinitionOptions, zt as WebFingerLinksDispatcher } from "../context-uyRUWoZQ.js";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-BhNbN8Ed.js";
4
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-CSH1Ee-I.js";
4
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-D882_Xsg.js";
5
5
  export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-BNktRUnj.js";
3
+ import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-CeCj5caM.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";
@@ -10,13 +10,13 @@ import { t as assertNotEquals } from "../assert_not_equals-BN7yDMWe.mjs";
10
10
  import "../std__assert-CxFT0MNt.mjs";
11
11
  import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
12
12
  import { t as assert } from "../assert-CebeUf0C.mjs";
13
- import { l as verifyRequest } from "../http-BR190IDB.mjs";
13
+ import { l as verifyRequest } from "../http-CtidZS_t.mjs";
14
14
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
15
- import { t as doesActorOwnKey } from "../owner-B795xXwU.mjs";
16
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-DB1mkFKO.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-BqVXJLW8.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-6jS4xFsX.mjs";
17
17
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
18
18
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
19
- import { FetchError } from "@fedify/vocab-runtime";
19
+ import { FetchError, UrlError } from "@fedify/vocab-runtime";
20
20
  import { AggregationTemporality, InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
21
21
  //#region src/federation/send.test.ts
22
22
  test("extractInboxes()", () => {
@@ -465,6 +465,7 @@ test("sendActivity() records OpenTelemetry delivery metrics", async (t) => {
465
465
  activityId: "https://example.com/activity",
466
466
  activityType: "https://www.w3.org/ns/activitystreams#Create",
467
467
  keys: [],
468
+ allowPrivateAddress: true,
468
469
  inbox: new URL("https://metrics.example:8443/inbox/path?x=1"),
469
470
  meterProvider
470
471
  });
@@ -502,6 +503,7 @@ test("sendActivity() records OpenTelemetry delivery metrics", async (t) => {
502
503
  activityId: "https://example.com/follow",
503
504
  activityType: "https://www.w3.org/ns/activitystreams#Follow",
504
505
  keys: [],
506
+ allowPrivateAddress: true,
505
507
  inbox: new URL("https://metrics.example/inbox"),
506
508
  meterProvider
507
509
  }), SendActivityError);
@@ -539,6 +541,7 @@ test("sendActivity() exports delivery metrics through OpenTelemetry SDK", async
539
541
  activityId: "https://example.com/activity",
540
542
  activityType: "https://www.w3.org/ns/activitystreams#Create",
541
543
  keys: [],
544
+ allowPrivateAddress: true,
542
545
  inbox: new URL("https://sdk-metrics.example/inbox"),
543
546
  meterProvider
544
547
  });
@@ -555,5 +558,137 @@ test("sendActivity() exports delivery metrics through OpenTelemetry SDK", async
555
558
  }
556
559
  }
557
560
  });
561
+ for (const signed of [false, true]) {
562
+ const keys = [{
563
+ privateKey: signed ? rsaPrivateKey2 : ed25519PrivateKey,
564
+ keyId: signed ? rsaPublicKey2.id : ed25519Multikey.id
565
+ }];
566
+ test(`sendActivity() validates destinations (signed: ${signed})`, async (t) => {
567
+ const activity = {
568
+ type: "Create",
569
+ id: "https://example.com/activity"
570
+ };
571
+ const publicInbox = "https://8.8.8.8/inbox";
572
+ const privateInbox = "http://127.0.0.1/inbox";
573
+ for (const target of [
574
+ privateInbox,
575
+ "http://169.254.169.254/",
576
+ "http://[::1]/"
577
+ ]) await t.step(`rejects ${target} before fetching`, async () => {
578
+ esm_default.mockGlobal().catch(202);
579
+ try {
580
+ await assertRejects(() => sendActivity({
581
+ activity,
582
+ keys,
583
+ inbox: new URL(target)
584
+ }), UrlError);
585
+ assertEquals(esm_default.callHistory.calls().length, 0);
586
+ } finally {
587
+ esm_default.hardReset();
588
+ }
589
+ });
590
+ for (const status of [
591
+ 301,
592
+ 302,
593
+ 303,
594
+ 307,
595
+ 308
596
+ ]) for (const allowPrivateAddress of [false, true]) await t.step(`${status} private redirect, opt-in: ${allowPrivateAddress}`, async () => {
597
+ esm_default.mockGlobal();
598
+ esm_default.route(publicInbox, {
599
+ status,
600
+ headers: { Location: privateInbox }
601
+ });
602
+ esm_default.route(privateInbox, 202);
603
+ try {
604
+ const send = () => sendActivity({
605
+ activity,
606
+ keys,
607
+ inbox: new URL(publicInbox),
608
+ allowPrivateAddress
609
+ });
610
+ if (allowPrivateAddress) {
611
+ await send();
612
+ const calls = esm_default.callHistory.calls(privateInbox);
613
+ assertEquals(calls.length, 1);
614
+ const request = calls[0].request;
615
+ const preservesBody = signed || status === 307 || status === 308;
616
+ assertEquals(request.method, preservesBody ? "POST" : "GET");
617
+ assertEquals(await request.clone().text(), preservesBody ? JSON.stringify(activity) : "");
618
+ } else {
619
+ await assertRejects(send, UrlError);
620
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 0);
621
+ }
622
+ } finally {
623
+ esm_default.hardReset();
624
+ }
625
+ });
626
+ await t.step("rejects a private destination after a public redirect", async () => {
627
+ esm_default.mockGlobal().route(publicInbox, {
628
+ status: 307,
629
+ headers: { Location: "/next" }
630
+ }).route("https://8.8.8.8/next", {
631
+ status: 308,
632
+ headers: { Location: privateInbox }
633
+ }).route(privateInbox, 202);
634
+ try {
635
+ await assertRejects(() => sendActivity({
636
+ activity,
637
+ keys,
638
+ inbox: new URL(publicInbox)
639
+ }), UrlError);
640
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 0);
641
+ } finally {
642
+ esm_default.hardReset();
643
+ }
644
+ });
645
+ await t.step("limits redirect loops", async () => {
646
+ esm_default.mockGlobal().route(publicInbox, {
647
+ status: 307,
648
+ headers: { Location: publicInbox }
649
+ });
650
+ try {
651
+ await assertRejects(() => sendActivity({
652
+ activity,
653
+ keys,
654
+ inbox: new URL(publicInbox)
655
+ }));
656
+ assert(esm_default.callHistory.calls().length <= 21);
657
+ } finally {
658
+ esm_default.hardReset();
659
+ }
660
+ });
661
+ await t.step("allows a direct private inbox with opt-in", async () => {
662
+ esm_default.mockGlobal().route(privateInbox, 202);
663
+ try {
664
+ await sendActivity({
665
+ activity,
666
+ keys,
667
+ inbox: new URL(privateInbox),
668
+ allowPrivateAddress: true
669
+ });
670
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 1);
671
+ } finally {
672
+ esm_default.hardReset();
673
+ }
674
+ });
675
+ await t.step("allows relative public redirects", async () => {
676
+ esm_default.mockGlobal().route(publicInbox, {
677
+ status: 307,
678
+ headers: { Location: "/next" }
679
+ }).route("https://8.8.8.8/next", 202);
680
+ try {
681
+ await sendActivity({
682
+ activity,
683
+ keys,
684
+ inbox: new URL(publicInbox)
685
+ });
686
+ assertEquals(esm_default.callHistory.calls("https://8.8.8.8/next").length, 1);
687
+ } finally {
688
+ esm_default.hardReset();
689
+ }
690
+ });
691
+ });
692
+ }
558
693
  //#endregion
559
694
  export {};
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
5
  import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-dbCShlCb.mjs";
6
6
  import "../../testing-hbky2gMN.mjs";
7
- import { o as createFederation } from "../../middleware-BaZ32nCi.mjs";
7
+ import { o as createFederation } from "../../middleware-DCpiAsZi.mjs";
8
8
  import { n as ParallelMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
9
9
  import { configure, reset } from "@logtape/logtape";
10
10
  import { delay } from "es-toolkit";
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
5
  import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-dbCShlCb.mjs";
6
6
  import "../../testing-hbky2gMN.mjs";
7
- import { o as createFederation } from "../../middleware-BaZ32nCi.mjs";
8
- import { r as createFederationBuilder } from "../../builder-CWYQXC2W.mjs";
7
+ import { o as createFederation } from "../../middleware-DCpiAsZi.mjs";
8
+ import { r as createFederationBuilder } from "../../builder-Cts78G9N.mjs";
9
9
  import { t as TaskCodec } from "../../codec-C6rTrpIp.mjs";
10
10
  import { t as InProcessMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
11
11
  import { W3CTraceContextPropagator } from "@opentelemetry/core";
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertFalse } from "../assert_false-3pLLLsO4.mjs";
5
5
  import "../std__assert-CxFT0MNt.mjs";
6
6
  import { t as assert } from "../assert-CebeUf0C.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-Yi0JAV9z.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-DcyzeytP.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  //#region src/federation/temporal.test.ts
10
10
  test("hasMalformedKnownTemporalLiteral() detects expanded proof timestamps", async () => {
@@ -6,7 +6,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-CBlRfA-_.mjs";
7
7
  import { t as assertNotEquals } from "../assert_not_equals-BN7yDMWe.mjs";
8
8
  import "../std__assert-CxFT0MNt.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-BaZ32nCi.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-DCpiAsZi.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