@fedify/fedify 1.9.0-dev.1668 → 1.9.0-dev.1689

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 (138) hide show
  1. package/dist/{actor-Ch5yFYFG.d.ts → actor-C1Euqngb.d.ts} +1 -1
  2. package/dist/{actor-fGD4yb1K.cjs → actor-CK94m0Yv.cjs} +7263 -2440
  3. package/dist/{actor-ChSW_rBk.js → actor-Dpkqj5Dv.js} +7263 -2440
  4. package/dist/{actor-BHAPrCDB.js → actor-DzdLVqkJ.js} +1 -1
  5. package/dist/{actor-CHOM_AN3.d.cts → actor-Ydzhc8dj.d.cts} +1 -1
  6. package/dist/{authdocloader-eSrbn3wM.cjs → authdocloader-4iBGWlQw.cjs} +3 -3
  7. package/dist/{authdocloader-ChsJ9FJN.js → authdocloader-BVvTFQbi.js} +3 -3
  8. package/dist/{authdocloader-CgrKtaQg.js → authdocloader-DdSBpn11.js} +3 -3
  9. package/dist/{builder-DI4-Kpdg.js → builder-BR--hcb8.js} +10 -4
  10. package/dist/{client-B8gJ1cw8.js → client-BoUqciR8.js} +1 -1
  11. package/dist/compat/mod.d.cts +7 -7
  12. package/dist/compat/mod.d.ts +7 -7
  13. package/dist/compat/transformers.test.js +16 -16
  14. package/dist/{context-DFruNLny.d.ts → context-CZorAkt8.d.ts} +66 -6
  15. package/dist/{context-KXVF2AhH.d.cts → context-DCh96LcF.d.cts} +66 -6
  16. package/dist/{docloader-CSB8cAnw.cjs → docloader-Bui9z8Lb.cjs} +1 -1
  17. package/dist/{docloader-Bqh-eFNP.js → docloader-DyvW1gbN.js} +1 -1
  18. package/dist/{esm-DTi75ew2.js → esm-DMb2eQXG.js} +1 -1
  19. package/dist/federation/builder.test.js +5 -5
  20. package/dist/federation/collection.test.js +3 -3
  21. package/dist/federation/handler.test.js +17 -17
  22. package/dist/federation/idempotency.test.d.ts +3 -0
  23. package/dist/federation/idempotency.test.js +202 -0
  24. package/dist/federation/inbox.test.js +4 -4
  25. package/dist/federation/keycache.test.js +4 -4
  26. package/dist/federation/kv.test.js +3 -3
  27. package/dist/federation/middleware.test.js +18 -18
  28. package/dist/federation/mod.cjs +10 -10
  29. package/dist/federation/mod.d.cts +7 -7
  30. package/dist/federation/mod.d.ts +7 -7
  31. package/dist/federation/mod.js +10 -10
  32. package/dist/federation/mq.test.js +3 -3
  33. package/dist/federation/retry.test.js +3 -3
  34. package/dist/federation/router.test.js +3 -3
  35. package/dist/federation/send.test.js +10 -10
  36. package/dist/fixtures/media.example.com/avatars/test-avatar.jpg.json +6 -0
  37. package/dist/{http-B_zBcsai.d.cts → http-B1_DzfAU.d.cts} +1 -1
  38. package/dist/{http-BDErrXSN.cjs → http-BAaVL480.cjs} +3 -3
  39. package/dist/{http-BpAVdmaR.js → http-C7nvEG1N.js} +2 -2
  40. package/dist/{http-D8Q4xH0d.d.ts → http-wsGR6KkT.d.ts} +1 -1
  41. package/dist/{http-DBHpjcjo.js → http-xsj5Fzwl.js} +3 -3
  42. package/dist/{inbox-BA9sYsBf.js → inbox-DZNE3Jtq.js} +29 -7
  43. package/dist/{key-B27QtSbc.js → key-C25gGlmV.js} +2 -2
  44. package/dist/key-CHU24Npw.cjs +10 -0
  45. package/dist/{key-sCE-TgxY.js → key-CbnQpdZy.js} +2 -2
  46. package/dist/{key-2rIHnPaA.js → key-DOPWTj2e.js} +4 -4
  47. package/dist/{key-DSOJOcRH.js → key-DgZIZVqA.js} +3 -3
  48. package/dist/{key-CYpTUnwf.cjs → key-DqqCoLbc.cjs} +2 -2
  49. package/dist/{keycache-CiW2SvJu.js → keycache-CoMI1L_W.js} +1 -1
  50. package/dist/{keys-5cHW76LQ.js → keys-CMahfArj.js} +1 -1
  51. package/dist/{ld-upnKn3yw.js → ld-WZpO-MzE.js} +2 -2
  52. package/dist/{lookup-BrrOs_g1.cjs → lookup-D_w567L8.cjs} +1 -1
  53. package/dist/{lookup-B61sZAOY.js → lookup-WoJkw8wY.js} +1 -1
  54. package/dist/{lookup-CZBG-vCx.js → lookup-y6-PEpxS.js} +21 -12
  55. package/dist/middleware-BYEKw_OJ.js +17 -0
  56. package/dist/{middleware-P3jCWk4K.cjs → middleware-CWlrInU2.cjs} +52 -20
  57. package/dist/{middleware-CfP7UhQy.js → middleware-Cj9WC_iX.js} +52 -20
  58. package/dist/{middleware-CyUVZG3t.js → middleware-CjgR6ayA.js} +21 -17
  59. package/dist/middleware-DbxA0Z6o.js +26 -0
  60. package/dist/middleware-hTlyJu9R.cjs +17 -0
  61. package/dist/{mod-NKH_G-IY.d.cts → mod-BUbqxBev.d.cts} +19 -1
  62. package/dist/{mod-YfAcrVbP.d.cts → mod-BojaEE1l.d.cts} +2 -2
  63. package/dist/{mod-Cy6pkZSn.d.ts → mod-CDObsV1d.d.ts} +19 -1
  64. package/dist/{mod-BAuhKa9d.d.ts → mod-CIbqfZW0.d.ts} +1 -1
  65. package/dist/{mod-B7Pc0I7F.d.ts → mod-DgcYoyZK.d.ts} +2 -2
  66. package/dist/{mod-C3CGxYoF.d.cts → mod-Dt-G9ZOS.d.cts} +1 -1
  67. package/dist/{mod-COw_caPC.d.cts → mod-fjqfsrty.d.cts} +2 -2
  68. package/dist/{mod-CiXjux2r.d.ts → mod-tWXEItkO.d.ts} +2 -2
  69. package/dist/mod.cjs +10 -10
  70. package/dist/mod.d.cts +10 -10
  71. package/dist/mod.d.ts +10 -10
  72. package/dist/mod.js +10 -10
  73. package/dist/nodeinfo/client.test.js +5 -5
  74. package/dist/nodeinfo/handler.test.js +16 -16
  75. package/dist/nodeinfo/mod.cjs +2 -2
  76. package/dist/nodeinfo/mod.js +2 -2
  77. package/dist/nodeinfo/semver.test.js +3 -3
  78. package/dist/nodeinfo/types.test.js +3 -3
  79. package/dist/{owner-C9Ry0TOI.d.cts → owner-6KSEp9eV.d.cts} +2 -2
  80. package/dist/{owner-D38zBIMc.d.ts → owner-BbeUDvOu.d.ts} +2 -2
  81. package/dist/{owner-zvsMGYzc.js → owner-CPBOVM7l.js} +2 -2
  82. package/dist/{proof-CC_7UV_j.cjs → proof-BLoRsaYR.cjs} +3 -3
  83. package/dist/{proof-Bt6yHsMN.js → proof-CpmDDzvf.js} +3 -3
  84. package/dist/{proof-BgKYSJ00.js → proof-h0JvKPRP.js} +2 -2
  85. package/dist/runtime/authdocloader.test.js +9 -9
  86. package/dist/runtime/docloader.test.js +4 -4
  87. package/dist/runtime/key.test.js +5 -5
  88. package/dist/runtime/langstr.test.js +3 -3
  89. package/dist/runtime/link.test.js +3 -3
  90. package/dist/runtime/mod.cjs +6 -6
  91. package/dist/runtime/mod.d.cts +3 -3
  92. package/dist/runtime/mod.d.ts +3 -3
  93. package/dist/runtime/mod.js +6 -6
  94. package/dist/runtime/multibase/multibase.test.js +3 -3
  95. package/dist/runtime/url.test.js +3 -3
  96. package/dist/{send-DlqdAGHP.js → send-CD-m2vwX.js} +2 -2
  97. package/dist/sig/http.test.js +8 -8
  98. package/dist/sig/key.test.js +6 -6
  99. package/dist/sig/ld.test.js +7 -7
  100. package/dist/sig/mod.cjs +6 -6
  101. package/dist/sig/mod.d.cts +5 -5
  102. package/dist/sig/mod.d.ts +5 -5
  103. package/dist/sig/mod.js +6 -6
  104. package/dist/sig/owner.test.js +7 -7
  105. package/dist/sig/proof.test.js +7 -7
  106. package/dist/testing/docloader.test.js +3 -3
  107. package/dist/testing/mod.d.ts +272 -0
  108. package/dist/testing/mod.js +3 -3
  109. package/dist/{testing-CAAJTPCt.js → testing-DvTABhvG.js} +2 -2
  110. package/dist/{type-BRNRL3aj.js → type-BCazg_Pu.js} +6943 -2120
  111. package/dist/{types-C8yjtF5A.js → types-BsM0mf3R.js} +1 -1
  112. package/dist/{types-Dz0NMslg.cjs → types-F8JMlP-f.cjs} +1 -1
  113. package/dist/vocab/actor.test.js +5 -5
  114. package/dist/vocab/lookup.test.js +255 -5
  115. package/dist/vocab/mod.cjs +4 -4
  116. package/dist/vocab/mod.d.cts +3 -3
  117. package/dist/vocab/mod.d.ts +3 -3
  118. package/dist/vocab/mod.js +4 -4
  119. package/dist/vocab/type.test.js +3 -3
  120. package/dist/vocab/vocab.test.js +397 -8
  121. package/dist/{vocab-BDMmyzZA.cjs → vocab-C-qxDq1m.cjs} +23 -14
  122. package/dist/{vocab-BEEm2I6u.d.ts → vocab-CDHNj5zp.d.ts} +290 -0
  123. package/dist/{vocab-BzGg7ltX.d.cts → vocab-Cfs0937i.d.cts} +290 -0
  124. package/dist/{vocab-WpDLcZH7.js → vocab-DdTdRfBW.js} +23 -14
  125. package/dist/webfinger/handler.test.js +16 -16
  126. package/dist/webfinger/lookup.test.js +4 -4
  127. package/dist/webfinger/mod.cjs +2 -2
  128. package/dist/webfinger/mod.js +2 -2
  129. package/dist/x/cfworkers.test.js +3 -3
  130. package/dist/x/hono.d.cts +6 -6
  131. package/dist/x/hono.d.ts +6 -6
  132. package/dist/x/sveltekit.d.cts +6 -6
  133. package/dist/x/sveltekit.d.ts +6 -6
  134. package/package.json +1 -1
  135. package/dist/key-Ck4-GNm0.cjs +0 -10
  136. package/dist/middleware-D8O6iKhr.js +0 -26
  137. package/dist/middleware-DI4sIaI4.js +0 -17
  138. package/dist/middleware-lw0MLhVG.cjs +0 -17
@@ -3,7 +3,7 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Activity, deno_default, getTypeId } from "./type-BRNRL3aj.js";
6
+ import { Activity, deno_default, getTypeId } from "./type-BCazg_Pu.js";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
9
9
 
@@ -41,17 +41,39 @@ var InboxListenerSet = class InboxListenerSet {
41
41
  return this.dispatchWithClass(activity)?.listener ?? null;
42
42
  }
43
43
  };
44
- async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider }) {
44
+ let warnedAboutDefaultIdempotency = false;
45
+ async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
45
46
  const logger = getLogger([
46
47
  "fedify",
47
48
  "federation",
48
49
  "inbox"
49
50
  ]);
50
- const cacheKey = activity.id == null ? null : [
51
- ...kvPrefixes.activityIdempotence,
52
- ctx.origin,
53
- activity.id.href
54
- ];
51
+ let cacheKey = null;
52
+ if (activity.id != null) {
53
+ const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
54
+ const strategy = idempotencyStrategy ?? "per-origin";
55
+ if (idempotencyStrategy === void 0 && !warnedAboutDefaultIdempotency) {
56
+ logger.warn("Using default idempotency strategy 'per-origin'. This default will change to 'per-inbox' in Fedify 2.0. Please explicitly set the idempotency strategy using .withIdempotency().");
57
+ warnedAboutDefaultIdempotency = true;
58
+ }
59
+ let keyString;
60
+ if (typeof strategy === "function") {
61
+ const result = await strategy(inboxContext, activity);
62
+ keyString = result;
63
+ } else switch (strategy) {
64
+ case "global":
65
+ keyString = activity.id.href;
66
+ break;
67
+ case "per-origin":
68
+ keyString = `${ctx.origin}\n${activity.id.href}`;
69
+ break;
70
+ case "per-inbox":
71
+ keyString = `${ctx.origin}\n${activity.id.href}\n${recipient == null ? "sharedInbox" : `inbox\n${recipient}`}`;
72
+ break;
73
+ default: keyString = `${ctx.origin}\n${activity.id.href}`;
74
+ }
75
+ if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
76
+ }
55
77
  if (cacheKey != null) {
56
78
  const cached = await kv.get(cacheKey);
57
79
  if (cached === true) {
@@ -3,8 +3,8 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { CryptographicKey, Object as Object$1, deno_default, getDocumentLoader } from "./type-BRNRL3aj.js";
7
- import { isActor } from "./actor-BHAPrCDB.js";
6
+ import { CryptographicKey, Object as Object$1, deno_default, getDocumentLoader } from "./type-BCazg_Pu.js";
7
+ import { isActor } from "./actor-DzdLVqkJ.js";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
10
10
 
@@ -0,0 +1,10 @@
1
+
2
+ const { Temporal } = require("@js-temporal/polyfill");
3
+ const { URLPattern } = require("urlpattern-polyfill");
4
+
5
+ require('./docloader-Bui9z8Lb.cjs');
6
+ require('./actor-CK94m0Yv.cjs');
7
+ require('./lookup-D_w567L8.cjs');
8
+ const require_key = require('./key-DqqCoLbc.cjs');
9
+
10
+ exports.validateCryptoKey = require_key.validateCryptoKey;
@@ -2,8 +2,8 @@
2
2
  import { Temporal } from "@js-temporal/polyfill";
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
 
5
- import { deno_default, getDocumentLoader } from "./docloader-Bqh-eFNP.js";
6
- import { CryptographicKey, Object as Object$1, isActor } from "./actor-ChSW_rBk.js";
5
+ import { deno_default, getDocumentLoader } from "./docloader-DyvW1gbN.js";
6
+ import { CryptographicKey, Object as Object$1, isActor } from "./actor-Dpkqj5Dv.js";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
9
9
 
@@ -2,9 +2,9 @@
2
2
  import { Temporal } from "@js-temporal/polyfill";
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
 
5
- import "./docloader-Bqh-eFNP.js";
6
- import "./actor-ChSW_rBk.js";
7
- import "./lookup-B61sZAOY.js";
8
- import { exportJwk, fetchKey, generateCryptoKeyPair, importJwk, validateCryptoKey } from "./key-sCE-TgxY.js";
5
+ import "./docloader-DyvW1gbN.js";
6
+ import "./actor-Dpkqj5Dv.js";
7
+ import "./lookup-WoJkw8wY.js";
8
+ import { exportJwk, fetchKey, generateCryptoKeyPair, importJwk, validateCryptoKey } from "./key-CbnQpdZy.js";
9
9
 
10
10
  export { validateCryptoKey };
@@ -3,8 +3,8 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import "./type-BRNRL3aj.js";
7
- import "./actor-BHAPrCDB.js";
8
- import { exportJwk, fetchKey, generateCryptoKeyPair, importJwk, validateCryptoKey } from "./key-B27QtSbc.js";
6
+ import "./type-BCazg_Pu.js";
7
+ import "./actor-DzdLVqkJ.js";
8
+ import { exportJwk, fetchKey, generateCryptoKeyPair, importJwk, validateCryptoKey } from "./key-C25gGlmV.js";
9
9
 
10
10
  export { validateCryptoKey };
@@ -3,8 +3,8 @@
3
3
  const { URLPattern } = require("urlpattern-polyfill");
4
4
 
5
5
  const require_chunk = require('./chunk-DqRYRqnO.cjs');
6
- const require_docloader = require('./docloader-CSB8cAnw.cjs');
7
- const require_actor = require('./actor-fGD4yb1K.cjs');
6
+ const require_docloader = require('./docloader-Bui9z8Lb.cjs');
7
+ const require_actor = require('./actor-CK94m0Yv.cjs');
8
8
  const __logtape_logtape = require_chunk.__toESM(require("@logtape/logtape"));
9
9
  const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
10
10
 
@@ -3,7 +3,7 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { CryptographicKey, Multikey } from "./type-BRNRL3aj.js";
6
+ import { CryptographicKey, Multikey } from "./type-BCazg_Pu.js";
7
7
 
8
8
  //#region src/federation/keycache.ts
9
9
  var KvKeyCache = class {
@@ -3,7 +3,7 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { CryptographicKey, Multikey, importSpki } from "./type-BRNRL3aj.js";
6
+ import { CryptographicKey, Multikey, importSpki } from "./type-BCazg_Pu.js";
7
7
 
8
8
  //#region src/testing/keys.ts
9
9
  const rsaPublicKey1 = new CryptographicKey({
@@ -3,8 +3,8 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Activity, CryptographicKey, Object as Object$1, deno_default, getDocumentLoader, getTypeId } from "./type-BRNRL3aj.js";
7
- import { fetchKey, validateCryptoKey } from "./key-B27QtSbc.js";
6
+ import { Activity, CryptographicKey, Object as Object$1, deno_default, getDocumentLoader, getTypeId } from "./type-BCazg_Pu.js";
7
+ import { fetchKey, validateCryptoKey } from "./key-C25gGlmV.js";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { SpanStatusCode, trace } from "@opentelemetry/api";
10
10
  import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
@@ -3,7 +3,7 @@
3
3
  const { URLPattern } = require("urlpattern-polyfill");
4
4
 
5
5
  const require_chunk = require('./chunk-DqRYRqnO.cjs');
6
- const require_docloader = require('./docloader-CSB8cAnw.cjs');
6
+ const require_docloader = require('./docloader-Bui9z8Lb.cjs');
7
7
  const __logtape_logtape = require_chunk.__toESM(require("@logtape/logtape"));
8
8
  const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
9
9
 
@@ -2,7 +2,7 @@
2
2
  import { Temporal } from "@js-temporal/polyfill";
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
 
5
- import { UrlError, deno_default, getUserAgent, validatePublicUrl } from "./docloader-Bqh-eFNP.js";
5
+ import { UrlError, deno_default, getUserAgent, validatePublicUrl } from "./docloader-DyvW1gbN.js";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
8
8
 
@@ -3,7 +3,7 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Object as Object$1, deno_default, getDocumentLoader, getTypeId, lookupWebFinger } from "./type-BRNRL3aj.js";
6
+ import { Object as Object$1, deno_default, getDocumentLoader, getTypeId, lookupWebFinger } from "./type-BCazg_Pu.js";
7
7
  import { cloneDeep, delay } from "es-toolkit";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -240,14 +240,13 @@ async function lookupObject(identifier, options = {}) {
240
240
  async function lookupObjectInternal(identifier, options = {}) {
241
241
  const documentLoader = options.documentLoader ?? getDocumentLoader({ userAgent: options.userAgent });
242
242
  if (typeof identifier === "string") identifier = toAcctUrl(identifier) ?? new URL(identifier);
243
- let document = null;
243
+ let remoteDoc = null;
244
244
  if (identifier.protocol === "http:" || identifier.protocol === "https:") try {
245
- const remoteDoc = await documentLoader(identifier.href, { signal: options.signal });
246
- document = remoteDoc.document;
245
+ remoteDoc = await documentLoader(identifier.href, { signal: options.signal });
247
246
  } catch (error) {
248
247
  logger.debug("Failed to fetch remote document:\n{error}", { error });
249
248
  }
250
- if (document == null) {
249
+ if (remoteDoc == null) {
251
250
  const jrd = await lookupWebFinger(identifier, {
252
251
  userAgent: options.userAgent,
253
252
  tracerProvider: options.tracerProvider,
@@ -258,8 +257,7 @@ async function lookupObjectInternal(identifier, options = {}) {
258
257
  for (const l of jrd.links) {
259
258
  if (l.type !== "application/activity+json" && !l.type?.match(/application\/ld\+json;\s*profile="https:\/\/www.w3.org\/ns\/activitystreams"/) || l.rel !== "self" || l.href == null) continue;
260
259
  try {
261
- const remoteDoc = await documentLoader(l.href, { signal: options.signal });
262
- document = remoteDoc.document;
260
+ remoteDoc = await documentLoader(l.href, { signal: options.signal });
263
261
  break;
264
262
  } catch (error) {
265
263
  logger.debug("Failed to fetch remote document:\n{error}", { error });
@@ -267,23 +265,34 @@ async function lookupObjectInternal(identifier, options = {}) {
267
265
  }
268
266
  }
269
267
  }
270
- if (document == null) return null;
268
+ if (remoteDoc == null) return null;
269
+ let object;
271
270
  try {
272
- return await Object$1.fromJsonLd(document, {
271
+ object = await Object$1.fromJsonLd(remoteDoc.document, {
273
272
  documentLoader,
274
273
  contextLoader: options.contextLoader,
275
- tracerProvider: options.tracerProvider
274
+ tracerProvider: options.tracerProvider,
275
+ baseUrl: new URL(remoteDoc.documentUrl)
276
276
  });
277
277
  } catch (error) {
278
278
  if (error instanceof TypeError) {
279
279
  logger.debug("Failed to parse JSON-LD document: {error}\n{document}", {
280
- error,
281
- document
280
+ ...remoteDoc,
281
+ error
282
282
  });
283
283
  return null;
284
284
  }
285
285
  throw error;
286
286
  }
287
+ if (options.crossOrigin !== "trust" && object.id != null && object.id.origin !== new URL(remoteDoc.documentUrl).origin) {
288
+ if (options.crossOrigin === "throw") throw new Error(`The object's @id (${object.id.href}) has a different origin than the document URL (${remoteDoc.documentUrl}); refusing to return the object. If you want to bypass this check and are aware of the security implications, set the crossOrigin option to "trust".`);
289
+ logger.warn("The object's @id ({objectId}) has a different origin than the document URL ({documentUrl}); refusing to return the object. If you want to bypass this check and are aware of the security implications, set the crossOrigin option to \"trust\".", {
290
+ ...remoteDoc,
291
+ objectId: object.id.href
292
+ });
293
+ return null;
294
+ }
295
+ return object;
287
296
  }
288
297
  /**
289
298
  * Traverses a collection, yielding each item in the collection.
@@ -0,0 +1,17 @@
1
+
2
+ import { Temporal } from "@js-temporal/polyfill";
3
+ import { URLPattern } from "urlpattern-polyfill";
4
+
5
+ import "./transformers-BFT6d7J5.js";
6
+ import "./docloader-DyvW1gbN.js";
7
+ import "./actor-Dpkqj5Dv.js";
8
+ import { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, createFederation } from "./middleware-Cj9WC_iX.js";
9
+ import "./lookup-WoJkw8wY.js";
10
+ import "./key-CbnQpdZy.js";
11
+ import "./http-xsj5Fzwl.js";
12
+ import "./proof-CpmDDzvf.js";
13
+ import "./types-BsM0mf3R.js";
14
+ import "./authdocloader-BVvTFQbi.js";
15
+ import "./vocab-DdTdRfBW.js";
16
+
17
+ export { FederationImpl };
@@ -4,15 +4,15 @@
4
4
 
5
5
  const require_chunk = require('./chunk-DqRYRqnO.cjs');
6
6
  const require_transformers = require('./transformers-CoBS-oFG.cjs');
7
- const require_docloader = require('./docloader-CSB8cAnw.cjs');
8
- const require_actor = require('./actor-fGD4yb1K.cjs');
9
- const require_lookup = require('./lookup-BrrOs_g1.cjs');
10
- const require_key = require('./key-CYpTUnwf.cjs');
11
- const require_http = require('./http-BDErrXSN.cjs');
12
- const require_proof = require('./proof-CC_7UV_j.cjs');
13
- const require_types = require('./types-Dz0NMslg.cjs');
14
- const require_authdocloader = require('./authdocloader-eSrbn3wM.cjs');
15
- const require_vocab = require('./vocab-BDMmyzZA.cjs');
7
+ const require_docloader = require('./docloader-Bui9z8Lb.cjs');
8
+ const require_actor = require('./actor-CK94m0Yv.cjs');
9
+ const require_lookup = require('./lookup-D_w567L8.cjs');
10
+ const require_key = require('./key-DqqCoLbc.cjs');
11
+ const require_http = require('./http-BAaVL480.cjs');
12
+ const require_proof = require('./proof-BLoRsaYR.cjs');
13
+ const require_types = require('./types-F8JMlP-f.cjs');
14
+ const require_authdocloader = require('./authdocloader-4iBGWlQw.cjs');
15
+ const require_vocab = require('./vocab-C-qxDq1m.cjs');
16
16
  const __logtape_logtape = require_chunk.__toESM(require("@logtape/logtape"));
17
17
  const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
18
18
  const byte_encodings_hex = require_chunk.__toESM(require("byte-encodings/hex"));
@@ -56,17 +56,39 @@ var InboxListenerSet = class InboxListenerSet {
56
56
  return this.dispatchWithClass(activity)?.listener ?? null;
57
57
  }
58
58
  };
59
- async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider }) {
59
+ let warnedAboutDefaultIdempotency = false;
60
+ async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
60
61
  const logger$1 = (0, __logtape_logtape.getLogger)([
61
62
  "fedify",
62
63
  "federation",
63
64
  "inbox"
64
65
  ]);
65
- const cacheKey = activity.id == null ? null : [
66
- ...kvPrefixes.activityIdempotence,
67
- ctx.origin,
68
- activity.id.href
69
- ];
66
+ let cacheKey = null;
67
+ if (activity.id != null) {
68
+ const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, require_actor.getTypeId(activity).href);
69
+ const strategy = idempotencyStrategy ?? "per-origin";
70
+ if (idempotencyStrategy === void 0 && !warnedAboutDefaultIdempotency) {
71
+ logger$1.warn("Using default idempotency strategy 'per-origin'. This default will change to 'per-inbox' in Fedify 2.0. Please explicitly set the idempotency strategy using .withIdempotency().");
72
+ warnedAboutDefaultIdempotency = true;
73
+ }
74
+ let keyString;
75
+ if (typeof strategy === "function") {
76
+ const result = await strategy(inboxContext, activity);
77
+ keyString = result;
78
+ } else switch (strategy) {
79
+ case "global":
80
+ keyString = activity.id.href;
81
+ break;
82
+ case "per-origin":
83
+ keyString = `${ctx.origin}\n${activity.id.href}`;
84
+ break;
85
+ case "per-inbox":
86
+ keyString = `${ctx.origin}\n${activity.id.href}\n${recipient == null ? "sharedInbox" : `inbox\n${recipient}`}`;
87
+ break;
88
+ default: keyString = `${ctx.origin}\n${activity.id.href}`;
89
+ }
90
+ if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
91
+ }
70
92
  if (cacheKey != null) {
71
93
  const cached = await kv.get(cacheKey);
72
94
  if (cached === true) {
@@ -308,6 +330,7 @@ var FederationBuilderImpl = class {
308
330
  inboxListeners;
309
331
  inboxErrorHandler;
310
332
  sharedInboxKeyDispatcher;
333
+ idempotencyStrategy;
311
334
  collectionTypeIds;
312
335
  collectionCallbacks;
313
336
  /**
@@ -322,7 +345,7 @@ var FederationBuilderImpl = class {
322
345
  this.collectionTypeIds = {};
323
346
  }
324
347
  async build(options) {
325
- const { FederationImpl: FederationImpl$1 } = await Promise.resolve().then(() => require("./middleware-lw0MLhVG.cjs"));
348
+ const { FederationImpl: FederationImpl$1 } = await Promise.resolve().then(() => require("./middleware-hTlyJu9R.cjs"));
326
349
  const f = new FederationImpl$1(options);
327
350
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
328
351
  f.router = this.router.clone();
@@ -344,6 +367,7 @@ var FederationBuilderImpl = class {
344
367
  f.inboxListeners = this.inboxListeners?.clone();
345
368
  f.inboxErrorHandler = this.inboxErrorHandler;
346
369
  f.sharedInboxKeyDispatcher = this.sharedInboxKeyDispatcher;
370
+ f.idempotencyStrategy = this.idempotencyStrategy;
347
371
  return f;
348
372
  }
349
373
  _getTracer() {
@@ -766,6 +790,10 @@ var FederationBuilderImpl = class {
766
790
  setSharedKeyDispatcher: (dispatcher) => {
767
791
  this.sharedInboxKeyDispatcher = dispatcher;
768
792
  return setters;
793
+ },
794
+ withIdempotency: (strategy) => {
795
+ this.idempotencyStrategy = strategy;
796
+ return setters;
769
797
  }
770
798
  };
771
799
  return setters;
@@ -1297,7 +1325,8 @@ async function handleInbox(request, options) {
1297
1325
  * @param span The OpenTelemetry span for tracing.
1298
1326
  * @returns A promise that resolves to an HTTP response.
1299
1327
  */
1300
- async function handleInboxInternal(request, { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider }, span) {
1328
+ async function handleInboxInternal(request, parameters, span) {
1329
+ const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider } = parameters;
1301
1330
  const logger$1 = (0, __logtape_logtape.getLogger)([
1302
1331
  "fedify",
1303
1332
  "federation",
@@ -1499,7 +1528,8 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
1499
1528
  kvPrefixes,
1500
1529
  queue,
1501
1530
  span,
1502
- tracerProvider
1531
+ tracerProvider,
1532
+ idempotencyStrategy: parameters.idempotencyStrategy
1503
1533
  });
1504
1534
  if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
1505
1535
  status: 202,
@@ -3096,7 +3126,8 @@ var FederationImpl = class extends FederationBuilderImpl {
3096
3126
  onNotFound,
3097
3127
  signatureTimeWindow: this.signatureTimeWindow,
3098
3128
  skipSignatureVerification: this.skipSignatureVerification,
3099
- tracerProvider: this.tracerProvider
3129
+ tracerProvider: this.tracerProvider,
3130
+ idempotencyStrategy: this.idempotencyStrategy
3100
3131
  });
3101
3132
  case "following": return await handleCollection(request, {
3102
3133
  name: "following",
@@ -3846,7 +3877,8 @@ var ContextImpl = class ContextImpl {
3846
3877
  kvPrefixes: this.federation.kvPrefixes,
3847
3878
  queue: this.federation.inboxQueue,
3848
3879
  span,
3849
- tracerProvider: options.tracerProvider ?? this.tracerProvider
3880
+ tracerProvider: options.tracerProvider ?? this.tracerProvider,
3881
+ idempotencyStrategy: this.federation.idempotencyStrategy
3850
3882
  });
3851
3883
  return routeResult === "alreadyProcessed" || routeResult === "enqueued" || routeResult === "unsupportedActivity" || routeResult === "success";
3852
3884
  }
@@ -3,15 +3,15 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
 
5
5
  import { getDefaultActivityTransformers } from "./transformers-BFT6d7J5.js";
6
- import { deno_default, getDocumentLoader, kvCache } from "./docloader-Bqh-eFNP.js";
7
- import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId } from "./actor-ChSW_rBk.js";
8
- import { lookupWebFinger } from "./lookup-B61sZAOY.js";
9
- import { exportJwk, importJwk, validateCryptoKey } from "./key-sCE-TgxY.js";
10
- import { doubleKnock, verifyRequest } from "./http-DBHpjcjo.js";
11
- import { detachSignature, doesActorOwnKey, getKeyOwner, hasSignature, signJsonLd, signObject, verifyJsonLd, verifyObject } from "./proof-Bt6yHsMN.js";
12
- import { getNodeInfo, nodeInfoToJson } from "./types-C8yjtF5A.js";
13
- import { getAuthenticatedDocumentLoader } from "./authdocloader-ChsJ9FJN.js";
14
- import { lookupObject, traverseCollection } from "./vocab-WpDLcZH7.js";
6
+ import { deno_default, getDocumentLoader, kvCache } from "./docloader-DyvW1gbN.js";
7
+ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId } from "./actor-Dpkqj5Dv.js";
8
+ import { lookupWebFinger } from "./lookup-WoJkw8wY.js";
9
+ import { exportJwk, importJwk, validateCryptoKey } from "./key-CbnQpdZy.js";
10
+ import { doubleKnock, verifyRequest } from "./http-xsj5Fzwl.js";
11
+ import { detachSignature, doesActorOwnKey, getKeyOwner, hasSignature, signJsonLd, signObject, verifyJsonLd, verifyObject } from "./proof-CpmDDzvf.js";
12
+ import { getNodeInfo, nodeInfoToJson } from "./types-BsM0mf3R.js";
13
+ import { getAuthenticatedDocumentLoader } from "./authdocloader-BVvTFQbi.js";
14
+ import { lookupObject, traverseCollection } from "./vocab-DdTdRfBW.js";
15
15
  import { getLogger, withContext } from "@logtape/logtape";
16
16
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
17
17
  import { encodeHex } from "byte-encodings/hex";
@@ -55,17 +55,39 @@ var InboxListenerSet = class InboxListenerSet {
55
55
  return this.dispatchWithClass(activity)?.listener ?? null;
56
56
  }
57
57
  };
58
- async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider }) {
58
+ let warnedAboutDefaultIdempotency = false;
59
+ async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
59
60
  const logger$1 = getLogger([
60
61
  "fedify",
61
62
  "federation",
62
63
  "inbox"
63
64
  ]);
64
- const cacheKey = activity.id == null ? null : [
65
- ...kvPrefixes.activityIdempotence,
66
- ctx.origin,
67
- activity.id.href
68
- ];
65
+ let cacheKey = null;
66
+ if (activity.id != null) {
67
+ const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
68
+ const strategy = idempotencyStrategy ?? "per-origin";
69
+ if (idempotencyStrategy === void 0 && !warnedAboutDefaultIdempotency) {
70
+ logger$1.warn("Using default idempotency strategy 'per-origin'. This default will change to 'per-inbox' in Fedify 2.0. Please explicitly set the idempotency strategy using .withIdempotency().");
71
+ warnedAboutDefaultIdempotency = true;
72
+ }
73
+ let keyString;
74
+ if (typeof strategy === "function") {
75
+ const result = await strategy(inboxContext, activity);
76
+ keyString = result;
77
+ } else switch (strategy) {
78
+ case "global":
79
+ keyString = activity.id.href;
80
+ break;
81
+ case "per-origin":
82
+ keyString = `${ctx.origin}\n${activity.id.href}`;
83
+ break;
84
+ case "per-inbox":
85
+ keyString = `${ctx.origin}\n${activity.id.href}\n${recipient == null ? "sharedInbox" : `inbox\n${recipient}`}`;
86
+ break;
87
+ default: keyString = `${ctx.origin}\n${activity.id.href}`;
88
+ }
89
+ if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
90
+ }
69
91
  if (cacheKey != null) {
70
92
  const cached = await kv.get(cacheKey);
71
93
  if (cached === true) {
@@ -307,6 +329,7 @@ var FederationBuilderImpl = class {
307
329
  inboxListeners;
308
330
  inboxErrorHandler;
309
331
  sharedInboxKeyDispatcher;
332
+ idempotencyStrategy;
310
333
  collectionTypeIds;
311
334
  collectionCallbacks;
312
335
  /**
@@ -321,7 +344,7 @@ var FederationBuilderImpl = class {
321
344
  this.collectionTypeIds = {};
322
345
  }
323
346
  async build(options) {
324
- const { FederationImpl: FederationImpl$1 } = await import("./middleware-DI4sIaI4.js");
347
+ const { FederationImpl: FederationImpl$1 } = await import("./middleware-BYEKw_OJ.js");
325
348
  const f = new FederationImpl$1(options);
326
349
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
327
350
  f.router = this.router.clone();
@@ -343,6 +366,7 @@ var FederationBuilderImpl = class {
343
366
  f.inboxListeners = this.inboxListeners?.clone();
344
367
  f.inboxErrorHandler = this.inboxErrorHandler;
345
368
  f.sharedInboxKeyDispatcher = this.sharedInboxKeyDispatcher;
369
+ f.idempotencyStrategy = this.idempotencyStrategy;
346
370
  return f;
347
371
  }
348
372
  _getTracer() {
@@ -765,6 +789,10 @@ var FederationBuilderImpl = class {
765
789
  setSharedKeyDispatcher: (dispatcher) => {
766
790
  this.sharedInboxKeyDispatcher = dispatcher;
767
791
  return setters;
792
+ },
793
+ withIdempotency: (strategy) => {
794
+ this.idempotencyStrategy = strategy;
795
+ return setters;
768
796
  }
769
797
  };
770
798
  return setters;
@@ -1296,7 +1324,8 @@ async function handleInbox(request, options) {
1296
1324
  * @param span The OpenTelemetry span for tracing.
1297
1325
  * @returns A promise that resolves to an HTTP response.
1298
1326
  */
1299
- async function handleInboxInternal(request, { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider }, span) {
1327
+ async function handleInboxInternal(request, parameters, span) {
1328
+ const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider } = parameters;
1300
1329
  const logger$1 = getLogger([
1301
1330
  "fedify",
1302
1331
  "federation",
@@ -1498,7 +1527,8 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
1498
1527
  kvPrefixes,
1499
1528
  queue,
1500
1529
  span,
1501
- tracerProvider
1530
+ tracerProvider,
1531
+ idempotencyStrategy: parameters.idempotencyStrategy
1502
1532
  });
1503
1533
  if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
1504
1534
  status: 202,
@@ -3095,7 +3125,8 @@ var FederationImpl = class extends FederationBuilderImpl {
3095
3125
  onNotFound,
3096
3126
  signatureTimeWindow: this.signatureTimeWindow,
3097
3127
  skipSignatureVerification: this.skipSignatureVerification,
3098
- tracerProvider: this.tracerProvider
3128
+ tracerProvider: this.tracerProvider,
3129
+ idempotencyStrategy: this.idempotencyStrategy
3099
3130
  });
3100
3131
  case "following": return await handleCollection(request, {
3101
3132
  name: "following",
@@ -3845,7 +3876,8 @@ var ContextImpl = class ContextImpl {
3845
3876
  kvPrefixes: this.federation.kvPrefixes,
3846
3877
  queue: this.federation.inboxQueue,
3847
3878
  span,
3848
- tracerProvider: options.tracerProvider ?? this.tracerProvider
3879
+ tracerProvider: options.tracerProvider ?? this.tracerProvider,
3880
+ idempotencyStrategy: this.federation.idempotencyStrategy
3849
3881
  });
3850
3882
  return routeResult === "alreadyProcessed" || routeResult === "enqueued" || routeResult === "unsupportedActivity" || routeResult === "success";
3851
3883
  }
@@ -3,22 +3,22 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, deno_default, getDocumentLoader, getTypeId, kvCache, lookupWebFinger } from "./type-BRNRL3aj.js";
7
- import { getNodeInfo } from "./client-B8gJ1cw8.js";
8
- import { RouterError, lookupObject, traverseCollection } from "./lookup-CZBG-vCx.js";
6
+ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, deno_default, getDocumentLoader, getTypeId, kvCache, lookupWebFinger } from "./type-BCazg_Pu.js";
7
+ import { getNodeInfo } from "./client-BoUqciR8.js";
8
+ import { RouterError, lookupObject, traverseCollection } from "./lookup-y6-PEpxS.js";
9
9
  import { nodeInfoToJson } from "./types-BIgY6c-l.js";
10
- import { exportJwk, importJwk, validateCryptoKey } from "./key-B27QtSbc.js";
11
- import { verifyRequest } from "./http-BpAVdmaR.js";
12
- import { getAuthenticatedDocumentLoader } from "./authdocloader-CgrKtaQg.js";
13
- import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-upnKn3yw.js";
14
- import { doesActorOwnKey, getKeyOwner } from "./owner-zvsMGYzc.js";
15
- import { signObject, verifyObject } from "./proof-BgKYSJ00.js";
16
- import { routeActivity } from "./inbox-BA9sYsBf.js";
17
- import { FederationBuilderImpl } from "./builder-DI4-Kpdg.js";
10
+ import { exportJwk, importJwk, validateCryptoKey } from "./key-C25gGlmV.js";
11
+ import { verifyRequest } from "./http-C7nvEG1N.js";
12
+ import { getAuthenticatedDocumentLoader } from "./authdocloader-DdSBpn11.js";
13
+ import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-WZpO-MzE.js";
14
+ import { doesActorOwnKey, getKeyOwner } from "./owner-CPBOVM7l.js";
15
+ import { signObject, verifyObject } from "./proof-h0JvKPRP.js";
16
+ import { routeActivity } from "./inbox-DZNE3Jtq.js";
17
+ import { FederationBuilderImpl } from "./builder-BR--hcb8.js";
18
18
  import { buildCollectionSynchronizationHeader } from "./collection-CSzG2j1P.js";
19
- import { KvKeyCache } from "./keycache-CiW2SvJu.js";
19
+ import { KvKeyCache } from "./keycache-CoMI1L_W.js";
20
20
  import { createExponentialBackoffPolicy } from "./retry-D4GJ670a.js";
21
- import { extractInboxes, sendActivity } from "./send-DlqdAGHP.js";
21
+ import { extractInboxes, sendActivity } from "./send-CD-m2vwX.js";
22
22
  import { getLogger, withContext } from "@logtape/logtape";
23
23
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
24
24
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
@@ -671,7 +671,8 @@ async function handleInbox(request, options) {
671
671
  * @param span The OpenTelemetry span for tracing.
672
672
  * @returns A promise that resolves to an HTTP response.
673
673
  */
674
- async function handleInboxInternal(request, { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider }, span) {
674
+ async function handleInboxInternal(request, parameters, span) {
675
+ const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider } = parameters;
675
676
  const logger$2 = getLogger([
676
677
  "fedify",
677
678
  "federation",
@@ -873,7 +874,8 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
873
874
  kvPrefixes,
874
875
  queue,
875
876
  span,
876
- tracerProvider
877
+ tracerProvider,
878
+ idempotencyStrategy: parameters.idempotencyStrategy
877
879
  });
878
880
  if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
879
881
  status: 202,
@@ -2151,7 +2153,8 @@ var FederationImpl = class extends FederationBuilderImpl {
2151
2153
  onNotFound,
2152
2154
  signatureTimeWindow: this.signatureTimeWindow,
2153
2155
  skipSignatureVerification: this.skipSignatureVerification,
2154
- tracerProvider: this.tracerProvider
2156
+ tracerProvider: this.tracerProvider,
2157
+ idempotencyStrategy: this.idempotencyStrategy
2155
2158
  });
2156
2159
  case "following": return await handleCollection(request, {
2157
2160
  name: "following",
@@ -2901,7 +2904,8 @@ var ContextImpl = class ContextImpl {
2901
2904
  kvPrefixes: this.federation.kvPrefixes,
2902
2905
  queue: this.federation.inboxQueue,
2903
2906
  span,
2904
- tracerProvider: options.tracerProvider ?? this.tracerProvider
2907
+ tracerProvider: options.tracerProvider ?? this.tracerProvider,
2908
+ idempotencyStrategy: this.federation.idempotencyStrategy
2905
2909
  });
2906
2910
  return routeResult === "alreadyProcessed" || routeResult === "enqueued" || routeResult === "unsupportedActivity" || routeResult === "success";
2907
2911
  }