@fedify/fedify 1.9.10 → 1.9.12-dev.2265

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 (118) hide show
  1. package/dist/{actor-BCmFER1x.js → actor-BJj7NAV7.js} +187 -187
  2. package/dist/{actor-CGzgm5oD.cjs → actor-BxUB2vBw.cjs} +187 -187
  3. package/dist/{actor-Dk8QQxfb.mjs → actor-DKEb3nb2.mjs} +1 -1
  4. package/dist/{authdocloader-C0oFDv-u.cjs → authdocloader-BkG-kREl.cjs} +3 -3
  5. package/dist/{authdocloader-BlqYxYyU.mjs → authdocloader-DVWlfdZ9.mjs} +3 -3
  6. package/dist/{authdocloader-C4Km7IX-.js → authdocloader-_m5yqwLt.js} +3 -3
  7. package/dist/{builder-Dy69enN4.mjs → builder-Dhm6irl1.mjs} +4 -4
  8. package/dist/{client-BVxHrCKU.mjs → client-CIvLnEyN.mjs} +1 -1
  9. package/dist/compat/mod.cjs +1 -1
  10. package/dist/compat/mod.d.cts +1 -1
  11. package/dist/compat/mod.d.ts +1 -1
  12. package/dist/compat/transformers.test.mjs +3 -3
  13. package/dist/{context-Cf8s07xm.d.ts → context-CNkTuNIm.d.ts} +48 -6
  14. package/dist/{context-Crmwowsw.d.cts → context-jX79cwCB.d.cts} +48 -6
  15. package/dist/{docloader-CJRlqHTE.js → docloader-CFM5B9fd.js} +121 -13
  16. package/dist/{docloader-L_Yv0SO1.cjs → docloader-ojCZeNsS.cjs} +121 -13
  17. package/dist/{esm-Bl5QZ7fr.mjs → esm-DpYRgHio.mjs} +1 -1
  18. package/dist/federation/builder.test.mjs +3 -3
  19. package/dist/federation/collection.test.mjs +1 -1
  20. package/dist/federation/handler.test.mjs +1361 -45
  21. package/dist/federation/idempotency.test.mjs +5 -5
  22. package/dist/federation/inbox.test.mjs +3 -3
  23. package/dist/federation/keycache.test.mjs +3 -3
  24. package/dist/federation/kv.test.mjs +1 -1
  25. package/dist/federation/middleware.test.mjs +1586 -82
  26. package/dist/federation/mod.cjs +2 -2
  27. package/dist/federation/mod.d.cts +1 -1
  28. package/dist/federation/mod.d.ts +1 -1
  29. package/dist/federation/mod.js +1 -1
  30. package/dist/federation/mq.test.mjs +3 -3
  31. package/dist/federation/retry.test.mjs +2 -2
  32. package/dist/federation/router.test.mjs +2 -2
  33. package/dist/federation/send.test.mjs +7 -7
  34. package/dist/federation/temporal.test.d.mts +2 -0
  35. package/dist/federation/temporal.test.mjs +71 -0
  36. package/dist/{http-ChxLPxfJ.cjs → http-B7su-Fmy.cjs} +3 -3
  37. package/dist/{http-lEtFJ9QZ.mjs → http-ChKbuD-B.mjs} +2 -2
  38. package/dist/{http-CEocuLno.js → http-DdMd8CPw.js} +3 -3
  39. package/dist/{inbox-f2JhwcoC.mjs → inbox-Du7n_Tcq.mjs} +7 -4
  40. package/dist/{key-DL1K1oFv.cjs → key-AD7NWK_B.cjs} +2 -2
  41. package/dist/{key-CcFvjYSE.mjs → key-Bd3kgBIA.mjs} +2 -2
  42. package/dist/{key-GSxkNZYW.cjs → key-COEspOg4.cjs} +1 -1
  43. package/dist/{key-DXRa1vj8.mjs → key-DINKM8mV.mjs} +1 -1
  44. package/dist/{key-CfQiiCFY.js → key-DvsZ4r4J.js} +2 -2
  45. package/dist/{keycache-Car3vCR8.mjs → keycache-DYpvtScH.mjs} +1 -1
  46. package/dist/{keys-BPA70FRA.mjs → keys-CJPe6iTW.mjs} +1 -1
  47. package/dist/ld-C51F-FdC.mjs +548 -0
  48. package/dist/{lookup-BZCRNz7r.cjs → lookup-DrAw0WK4.cjs} +1 -1
  49. package/dist/{lookup-MjsiCtwV.js → lookup-avek91qK.js} +1 -1
  50. package/dist/{lookup-ByZEGrUD.mjs → lookup-jTLErl5g.mjs} +1 -1
  51. package/dist/{middleware-D23J06Wi.js → middleware-B_5QXY9T.js} +401 -76
  52. package/dist/{middleware-DwelHV2a.cjs → middleware-BxPRXIp2.cjs} +404 -78
  53. package/dist/{middleware-DzVgR5WN.cjs → middleware-CoZn3Vmd.cjs} +1 -1
  54. package/dist/{middleware-DT1q8p2_.mjs → middleware-ScXtn6SX.mjs} +313 -80
  55. package/dist/{middleware-DQF9aAWg.mjs → middleware-ySLVbIpY.mjs} +1 -1
  56. package/dist/mod.cjs +10 -10
  57. package/dist/mod.d.cts +1 -1
  58. package/dist/mod.d.ts +1 -1
  59. package/dist/mod.js +9 -9
  60. package/dist/nodeinfo/client.test.mjs +3 -3
  61. package/dist/nodeinfo/handler.test.mjs +2 -2
  62. package/dist/nodeinfo/mod.cjs +1 -1
  63. package/dist/nodeinfo/mod.js +1 -1
  64. package/dist/nodeinfo/semver.test.mjs +1 -1
  65. package/dist/nodeinfo/types.test.mjs +1 -1
  66. package/dist/{owner-2Hw80SWJ.mjs → owner-Ul_H1ZhA.mjs} +3 -3
  67. package/dist/{proof-B6709oyL.mjs → proof-CGXr6kyw.mjs} +2 -2
  68. package/dist/{proof-DoJnUD_A.js → proof-CO1rdWN1.js} +300 -6
  69. package/dist/{proof-DOwB_RsW.cjs → proof-CpHpOx4z.cjs} +347 -5
  70. package/dist/runtime/authdocloader.test.mjs +6 -6
  71. package/dist/runtime/docloader.test.mjs +3 -3
  72. package/dist/runtime/key.test.mjs +3 -3
  73. package/dist/runtime/langstr.test.mjs +2 -2
  74. package/dist/runtime/link.test.mjs +2 -2
  75. package/dist/runtime/mod.cjs +3 -3
  76. package/dist/runtime/mod.js +3 -3
  77. package/dist/runtime/multibase/multibase.test.mjs +2 -2
  78. package/dist/runtime/url.test.mjs +53 -2
  79. package/dist/{send-CaI0XRhr.mjs → send-BktZN-8x.mjs} +2 -2
  80. package/dist/sig/http.test.mjs +6 -6
  81. package/dist/sig/key.test.mjs +4 -4
  82. package/dist/sig/ld.test.mjs +561 -5
  83. package/dist/sig/mod.cjs +3 -3
  84. package/dist/sig/mod.js +3 -3
  85. package/dist/sig/owner.test.mjs +5 -5
  86. package/dist/sig/proof.test.mjs +4 -4
  87. package/dist/temporal-DG3PUHrG.mjs +95 -0
  88. package/dist/testing/docloader.test.mjs +1 -1
  89. package/dist/testing/mod.d.mts +48 -6
  90. package/dist/testing/mod.mjs +1 -1
  91. package/dist/{testing-2hgRVgOJ.mjs → testing-Dbq3x7rR.mjs} +2 -2
  92. package/dist/{transformers-BZ3mYJ1P.cjs → transformers-ZXV8xoFH.cjs} +1 -1
  93. package/dist/{types-36cPcbK8.js → types-CysnskTc.js} +1 -1
  94. package/dist/{types-DXy2Djgl.cjs → types-kNVIK9BX.cjs} +1 -1
  95. package/dist/vocab/actor.test.mjs +4 -4
  96. package/dist/vocab/cjs.test.mjs +1 -1
  97. package/dist/vocab/lookup.test.mjs +4 -4
  98. package/dist/vocab/mod.cjs +3 -3
  99. package/dist/vocab/mod.js +3 -3
  100. package/dist/vocab/type.test.mjs +2 -2
  101. package/dist/vocab/vocab.test.mjs +3 -3
  102. package/dist/{vocab-BPE_99_6.mjs → vocab-BmWZ5Z8b.mjs} +306 -198
  103. package/dist/webfinger/handler.test.mjs +3 -3
  104. package/dist/webfinger/lookup.test.mjs +3 -3
  105. package/dist/webfinger/mod.cjs +1 -1
  106. package/dist/webfinger/mod.js +1 -1
  107. package/dist/x/cfworkers.cjs +1 -1
  108. package/dist/x/cfworkers.test.mjs +1 -1
  109. package/dist/x/hono.cjs +1 -1
  110. package/dist/x/hono.d.cts +1 -1
  111. package/dist/x/hono.d.ts +1 -1
  112. package/dist/x/sveltekit.cjs +1 -1
  113. package/dist/x/sveltekit.d.cts +1 -1
  114. package/dist/x/sveltekit.d.ts +1 -1
  115. package/package.json +1 -1
  116. package/dist/ld-C5izJRbw.mjs +0 -254
  117. /package/dist/{denokv-CoSB_Eps.mjs → denokv-NJPMXyK0.mjs} +0 -0
  118. /package/dist/{retry-Ddbq3AcK.mjs → retry-B_E3V_Dx.mjs} +0 -0
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { C as Person, E as Service, S as Organization, U as getTypeId, W as lookupWebFinger, d as Group, ot as name, r as Application, st as version } from "./vocab-BPE_99_6.mjs";
4
+ import { C as Person, E as Service, S as Organization, U as getTypeId, W as lookupWebFinger, d as Group, ot as name, r as Application, st as version } from "./vocab-BmWZ5Z8b.mjs";
5
5
  import { SpanStatusCode, trace } from "@opentelemetry/api";
6
6
  import { domainToASCII, domainToUnicode } from "node:url";
7
7
  //#region src/vocab/actor.ts
@@ -1,8 +1,8 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
- const require_docloader = require("./docloader-L_Yv0SO1.cjs");
4
- const require_key = require("./key-DL1K1oFv.cjs");
5
- const require_http = require("./http-ChxLPxfJ.cjs");
3
+ const require_docloader = require("./docloader-ojCZeNsS.cjs");
4
+ const require_key = require("./key-AD7NWK_B.cjs");
5
+ const require_http = require("./http-B7su-Fmy.cjs");
6
6
  //#region src/runtime/authdocloader.ts
7
7
  const logger = (0, require("@logtape/logtape").getLogger)([
8
8
  "fedify",
@@ -1,9 +1,9 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { $ as UrlError, K as createRequest, Q as logRequest, Y as getRemoteDocument, rt as validatePublicUrl } from "./vocab-BPE_99_6.mjs";
5
- import { a as validateCryptoKey } from "./key-CcFvjYSE.mjs";
6
- import { n as doubleKnock } from "./http-lEtFJ9QZ.mjs";
4
+ import { $ as UrlError, K as createRequest, Q as logRequest, Y as getRemoteDocument, rt as validatePublicUrl } from "./vocab-BmWZ5Z8b.mjs";
5
+ import { a as validateCryptoKey } from "./key-Bd3kgBIA.mjs";
6
+ import { n as doubleKnock } from "./http-ChKbuD-B.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  //#region src/runtime/authdocloader.ts
9
9
  const logger = getLogger([
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { a as getRemoteDocument, c as logRequest, l as UrlError, n as createRequest, u as validatePublicUrl } from "./docloader-CJRlqHTE.js";
4
- import { o as validateCryptoKey } from "./key-CfQiiCFY.js";
5
- import { t as doubleKnock } from "./http-CEocuLno.js";
3
+ import { a as getRemoteDocument, c as logRequest, l as UrlError, n as createRequest, u as validatePublicUrl } from "./docloader-CFM5B9fd.js";
4
+ import { o as validateCryptoKey } from "./key-DvsZ4r4J.js";
5
+ import { t as doubleKnock } from "./http-DdMd8CPw.js";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  //#region src/runtime/authdocloader.ts
8
8
  const logger = getLogger([
@@ -1,9 +1,9 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { U as getTypeId, ot as name, st as version } from "./vocab-BPE_99_6.mjs";
5
- import { i as RouterError, r as Router } from "./lookup-ByZEGrUD.mjs";
6
- import { t as InboxListenerSet } from "./inbox-f2JhwcoC.mjs";
4
+ import { U as getTypeId, ot as name, st as version } from "./vocab-BmWZ5Z8b.mjs";
5
+ import { i as RouterError, r as Router } from "./lookup-jTLErl5g.mjs";
6
+ import { t as InboxListenerSet } from "./inbox-Du7n_Tcq.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
9
9
  //#region src/federation/builder.ts
@@ -40,7 +40,7 @@ var FederationBuilderImpl = class {
40
40
  this.collectionTypeIds = {};
41
41
  }
42
42
  async build(options) {
43
- const { FederationImpl } = await import("./middleware-DQF9aAWg.mjs");
43
+ const { FederationImpl } = await import("./middleware-ySLVbIpY.mjs");
44
44
  const f = new FederationImpl(options);
45
45
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
46
46
  f.router = this.router.clone();
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { X as getUserAgent } from "./vocab-BPE_99_6.mjs";
4
+ import { X as getUserAgent } from "./vocab-BmWZ5Z8b.mjs";
5
5
  import { n as parseSemVer } from "./semver-CgD82xxg.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  //#region src/nodeinfo/client.ts
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_transformers = require("../transformers-BZ3mYJ1P.cjs");
4
+ const require_transformers = require("../transformers-ZXV8xoFH.cjs");
5
5
  exports.actorDehydrator = require_transformers.actorDehydrator;
6
6
  exports.autoIdAssigner = require_transformers.autoIdAssigner;
7
7
  exports.getDefaultActivityTransformers = require_transformers.getDefaultActivityTransformers;
@@ -1,5 +1,5 @@
1
1
  import { n as Activity } from "../vocab-BLvSEtuz.cjs";
2
- import { n as Context, pt as ActivityTransformer } from "../context-Crmwowsw.cjs";
2
+ import { n as Context, pt as ActivityTransformer } from "../context-jX79cwCB.cjs";
3
3
 
4
4
  //#region src/compat/transformers.d.ts
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { n as Activity } from "../vocab-lhCS9lzq.js";
4
- import { n as Context, pt as ActivityTransformer } from "../context-Cf8s07xm.js";
4
+ import { n as Context, pt as ActivityTransformer } from "../context-CNkTuNIm.js";
5
5
 
6
6
  //#region src/compat/transformers.d.ts
7
7
  /**
@@ -1,13 +1,13 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { C as Person, u as Follow } from "../vocab-BPE_99_6.mjs";
5
- import { t as test } from "../testing-2hgRVgOJ.mjs";
4
+ import { C as Person, u as Follow } from "../vocab-BmWZ5Z8b.mjs";
5
+ import { t as test } from "../testing-Dbq3x7rR.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
9
  import { t as MemoryKvStore } from "../kv-DM1zFCtL.mjs";
10
- import { _ as actorDehydrator, n as FederationImpl, v as autoIdAssigner } from "../middleware-DT1q8p2_.mjs";
10
+ import { _ as actorDehydrator, n as FederationImpl, v as autoIdAssigner } from "../middleware-ScXtn6SX.mjs";
11
11
  //#region src/compat/transformers.test.ts
12
12
  const context = new FederationImpl({ kv: new MemoryKvStore() }).createContext(new URL("http://example.com/"));
13
13
  test("autoIdAssigner", async () => {
@@ -480,6 +480,42 @@ interface InboxMessage {
480
480
  id: ReturnType<typeof crypto.randomUUID>;
481
481
  baseUrl: string;
482
482
  activity: unknown;
483
+ /**
484
+ * The normalized JSON-LD representation of a signed inbox activity that
485
+ * Fedify already compacted successfully while accepting the request. Queue
486
+ * workers can reuse this producer-side parse cache under stricter loader or
487
+ * network constraints without changing the raw payload preserved for
488
+ * forwarding.
489
+ *
490
+ * This may exist even when {@link ldSignatureVerified} is `false`, because
491
+ * fallback-authenticated traffic and already-queued backlog items can still
492
+ * depend on the cached normalized form to avoid re-fetching remote custom
493
+ * contexts during worker processing.
494
+ *
495
+ * This is optional for backward compatibility with messages that were
496
+ * queued by older Fedify versions or that were already in a queue before
497
+ * upgrading.
498
+ *
499
+ * Fedify keeps this on the queued message itself instead of an external
500
+ * sidecar because generic queue backends do not provide reliable lifecycle
501
+ * guarantees for auxiliary storage across retries and redeliveries.
502
+ *
503
+ * @internal
504
+ */
505
+ normalizedActivity?: unknown;
506
+ /**
507
+ * Whether the producer actually verified the Linked Data Signature before
508
+ * queueing this message. This lets workers distinguish verified LDS replay
509
+ * from other authenticated inbox traffic that merely happened to include a
510
+ * signature block. This provenance marker is separate from the optional
511
+ * normalizedActivity parse cache.
512
+ *
513
+ * `undefined` preserves backward compatibility with older queued messages
514
+ * that predate this marker.
515
+ *
516
+ * @internal
517
+ */
518
+ ldSignatureVerified?: boolean;
483
519
  started: string;
484
520
  attempt: number;
485
521
  identifier: string | null;
@@ -2049,9 +2085,12 @@ interface InboxContext<TContextData> extends Context<TContextData> {
2049
2085
  * Forwards a received activity to the recipients' inboxes. The forwarded
2050
2086
  * activity will be signed in HTTP Signatures by the forwarder, but its
2051
2087
  * payload will not be modified, i.e., Linked Data Signatures and Object
2052
- * Integrity Proofs will not be added. Therefore, if the activity is not
2053
- * signed (i.e., it has neither Linked Data Signatures nor Object Integrity
2054
- * Proofs), the recipient probably will not trust the activity.
2088
+ * Integrity Proofs will not be added. Even when Fedify internally
2089
+ * normalizes a Linked Data Signature activity for parsing, this method still
2090
+ * forwards the original received payload so the sender's signatures/proofs
2091
+ * are preserved as-is. Therefore, if the activity is not signed (i.e., it
2092
+ * has neither Linked Data Signatures nor Object Integrity Proofs), the
2093
+ * recipient probably will not trust the activity.
2055
2094
  * @param forwarder The forwarder's identifier or the forwarder's username
2056
2095
  * or the forwarder's key pair(s).
2057
2096
  * @param recipients The recipients of the activity.
@@ -2069,9 +2108,12 @@ interface InboxContext<TContextData> extends Context<TContextData> {
2069
2108
  * Forwards a received activity to the recipients' inboxes. The forwarded
2070
2109
  * activity will be signed in HTTP Signatures by the forwarder, but its
2071
2110
  * payload will not be modified, i.e., Linked Data Signatures and Object
2072
- * Integrity Proofs will not be added. Therefore, if the activity is not
2073
- * signed (i.e., it has neither Linked Data Signatures nor Object Integrity
2074
- * Proofs), the recipient probably will not trust the activity.
2111
+ * Integrity Proofs will not be added. Even when Fedify internally
2112
+ * normalizes a Linked Data Signature activity for parsing, this method still
2113
+ * forwards the original received payload so the sender's signatures/proofs
2114
+ * are preserved as-is. Therefore, if the activity is not signed (i.e., it
2115
+ * has neither Linked Data Signatures nor Object Integrity Proofs), the
2116
+ * recipient probably will not trust the activity.
2075
2117
  * @param forwarder The forwarder's identifier or the forwarder's username.
2076
2118
  * @param recipients In this case, it must be `"followers"`.
2077
2119
  * @param options Options for forwarding the activity.
@@ -478,6 +478,42 @@ interface InboxMessage {
478
478
  id: ReturnType<typeof crypto.randomUUID>;
479
479
  baseUrl: string;
480
480
  activity: unknown;
481
+ /**
482
+ * The normalized JSON-LD representation of a signed inbox activity that
483
+ * Fedify already compacted successfully while accepting the request. Queue
484
+ * workers can reuse this producer-side parse cache under stricter loader or
485
+ * network constraints without changing the raw payload preserved for
486
+ * forwarding.
487
+ *
488
+ * This may exist even when {@link ldSignatureVerified} is `false`, because
489
+ * fallback-authenticated traffic and already-queued backlog items can still
490
+ * depend on the cached normalized form to avoid re-fetching remote custom
491
+ * contexts during worker processing.
492
+ *
493
+ * This is optional for backward compatibility with messages that were
494
+ * queued by older Fedify versions or that were already in a queue before
495
+ * upgrading.
496
+ *
497
+ * Fedify keeps this on the queued message itself instead of an external
498
+ * sidecar because generic queue backends do not provide reliable lifecycle
499
+ * guarantees for auxiliary storage across retries and redeliveries.
500
+ *
501
+ * @internal
502
+ */
503
+ normalizedActivity?: unknown;
504
+ /**
505
+ * Whether the producer actually verified the Linked Data Signature before
506
+ * queueing this message. This lets workers distinguish verified LDS replay
507
+ * from other authenticated inbox traffic that merely happened to include a
508
+ * signature block. This provenance marker is separate from the optional
509
+ * normalizedActivity parse cache.
510
+ *
511
+ * `undefined` preserves backward compatibility with older queued messages
512
+ * that predate this marker.
513
+ *
514
+ * @internal
515
+ */
516
+ ldSignatureVerified?: boolean;
481
517
  started: string;
482
518
  attempt: number;
483
519
  identifier: string | null;
@@ -2047,9 +2083,12 @@ interface InboxContext<TContextData> extends Context<TContextData> {
2047
2083
  * Forwards a received activity to the recipients' inboxes. The forwarded
2048
2084
  * activity will be signed in HTTP Signatures by the forwarder, but its
2049
2085
  * payload will not be modified, i.e., Linked Data Signatures and Object
2050
- * Integrity Proofs will not be added. Therefore, if the activity is not
2051
- * signed (i.e., it has neither Linked Data Signatures nor Object Integrity
2052
- * Proofs), the recipient probably will not trust the activity.
2086
+ * Integrity Proofs will not be added. Even when Fedify internally
2087
+ * normalizes a Linked Data Signature activity for parsing, this method still
2088
+ * forwards the original received payload so the sender's signatures/proofs
2089
+ * are preserved as-is. Therefore, if the activity is not signed (i.e., it
2090
+ * has neither Linked Data Signatures nor Object Integrity Proofs), the
2091
+ * recipient probably will not trust the activity.
2053
2092
  * @param forwarder The forwarder's identifier or the forwarder's username
2054
2093
  * or the forwarder's key pair(s).
2055
2094
  * @param recipients The recipients of the activity.
@@ -2067,9 +2106,12 @@ interface InboxContext<TContextData> extends Context<TContextData> {
2067
2106
  * Forwards a received activity to the recipients' inboxes. The forwarded
2068
2107
  * activity will be signed in HTTP Signatures by the forwarder, but its
2069
2108
  * payload will not be modified, i.e., Linked Data Signatures and Object
2070
- * Integrity Proofs will not be added. Therefore, if the activity is not
2071
- * signed (i.e., it has neither Linked Data Signatures nor Object Integrity
2072
- * Proofs), the recipient probably will not trust the activity.
2109
+ * Integrity Proofs will not be added. Even when Fedify internally
2110
+ * normalizes a Linked Data Signature activity for parsing, this method still
2111
+ * forwards the original received payload so the sender's signatures/proofs
2112
+ * are preserved as-is. Therefore, if the activity is not signed (i.e., it
2113
+ * has neither Linked Data Signatures nor Object Integrity Proofs), the
2114
+ * recipient probably will not trust the activity.
2073
2115
  * @param forwarder The forwarder's identifier or the forwarder's username.
2074
2116
  * @param recipients In this case, it must be `"followers"`.
2075
2117
  * @param options Options for forwarding the activity.
@@ -6,7 +6,7 @@ import { lookup } from "node:dns/promises";
6
6
  import { isIP } from "node:net";
7
7
  //#region deno.json
8
8
  var name = "@fedify/fedify";
9
- var version = "1.9.10";
9
+ var version = "1.9.12-dev.2265+f8512d84";
10
10
  //#endregion
11
11
  //#region src/runtime/contexts.ts
12
12
  const preloadedContexts = {
@@ -4373,29 +4373,137 @@ function validatePublicIpAddress(address, family) {
4373
4373
  throw new UrlError(`Invalid or private address: ${address}`);
4374
4374
  }
4375
4375
  function isValidPublicIPv4Address(address) {
4376
- const parts = address.split(".");
4377
- const first = parseInt(parts[0]);
4378
- if (first === 0 || first === 10 || first === 127) return false;
4379
- const second = parseInt(parts[1]);
4380
- if (first === 169 && second === 254) return false;
4381
- if (first === 172 && second >= 16 && second <= 31) return false;
4382
- if (first === 192 && second === 168) return false;
4383
- return true;
4376
+ const parts = parseIPv4Address(address);
4377
+ if (parts == null) return false;
4378
+ const value = ipv4PartsToNumber(parts);
4379
+ return !nonPublicIPv4Prefixes.some(({ base, prefix }) => matchesIPv4Prefix(value, base, prefix));
4384
4380
  }
4385
4381
  function isValidPublicIPv6Address(address) {
4386
- address = expandIPv6Address(address);
4387
- if (address.at(4) !== ":") return false;
4388
- const firstWord = parseInt(address.substring(0, 4), 16);
4389
- return !(firstWord >= 64512 && firstWord <= 65023 || firstWord >= 65152 && firstWord <= 65215 || firstWord === 0 || firstWord >= 65280);
4382
+ const words = parseIPv6Address(address);
4383
+ if (words == null) return false;
4384
+ if (nonPublicIPv6Prefixes.some(({ words: prefixWords, prefix }) => matchesIPv6Prefix(words, prefixWords, prefix))) return false;
4385
+ for (const { extractIPv4, prefix, words: prefixWords } of ipv6WithIPv4Prefixes) {
4386
+ if (!matchesIPv6Prefix(words, prefixWords, prefix)) continue;
4387
+ const ipv4Address = extractIPv4(words);
4388
+ if (ipv4Address != null && !isValidPublicIPv4Address(ipv4Address)) return false;
4389
+ }
4390
+ return true;
4390
4391
  }
4391
4392
  function expandIPv6Address(address) {
4392
4393
  address = address.toLowerCase();
4394
+ const ipv4Delimiter = address.lastIndexOf(":");
4395
+ if (address.includes(".") && ipv4Delimiter >= 0) {
4396
+ const ipv4Parts = parseIPv4Address(address.substring(ipv4Delimiter + 1));
4397
+ if (ipv4Parts == null) return address;
4398
+ const high = (ipv4Parts[0] << 8) + ipv4Parts[1];
4399
+ const low = (ipv4Parts[2] << 8) + ipv4Parts[3];
4400
+ address = address.substring(0, ipv4Delimiter + 1) + high.toString(16) + ":" + low.toString(16);
4401
+ }
4393
4402
  if (address === "::") return "0000:0000:0000:0000:0000:0000:0000:0000";
4394
4403
  if (address.startsWith("::")) address = "0000" + address;
4395
4404
  if (address.endsWith("::")) address = address + "0000";
4396
4405
  address = address.replace("::", ":0000".repeat(8 - (address.match(/:/g) || []).length) + ":");
4397
4406
  return address.split(":").map((part) => part.padStart(4, "0")).join(":");
4398
4407
  }
4408
+ const nonPublicIPv4Prefixes = [
4409
+ ipv4Prefix("0.0.0.0/8", "RFC 6890"),
4410
+ ipv4Prefix("10.0.0.0/8", "RFC 1918"),
4411
+ ipv4Prefix("100.64.0.0/10", "RFC 6598"),
4412
+ ipv4Prefix("127.0.0.0/8", "RFC 1122"),
4413
+ ipv4Prefix("169.254.0.0/16", "RFC 3927"),
4414
+ ipv4Prefix("172.16.0.0/12", "RFC 1918"),
4415
+ ipv4Prefix("192.0.0.0/24", "RFC 6890"),
4416
+ ipv4Prefix("192.0.2.0/24", "RFC 5737"),
4417
+ ipv4Prefix("192.88.99.0/24", "RFC 7526"),
4418
+ ipv4Prefix("192.168.0.0/16", "RFC 1918"),
4419
+ ipv4Prefix("198.18.0.0/15", "RFC 2544"),
4420
+ ipv4Prefix("198.51.100.0/24", "RFC 5737"),
4421
+ ipv4Prefix("203.0.113.0/24", "RFC 5737"),
4422
+ ipv4Prefix("224.0.0.0/4", "RFC 5771"),
4423
+ ipv4Prefix("240.0.0.0/4", "RFC 1112")
4424
+ ];
4425
+ const nonPublicIPv6Prefixes = [
4426
+ ipv6Prefix("::/16", "RFC 4291"),
4427
+ ipv6Prefix("2001::/32", "RFC 4380"),
4428
+ ipv6Prefix("2002::/16", "RFC 3056"),
4429
+ ipv6Prefix("64:ff9b:1::/48", "RFC 8215"),
4430
+ ipv6Prefix("fc00::/7", "RFC 4193"),
4431
+ ipv6Prefix("fe80::/10", "RFC 4291"),
4432
+ ipv6Prefix("ff00::/8", "RFC 4291")
4433
+ ];
4434
+ const ipv6WithIPv4Prefixes = [{
4435
+ ...ipv6Prefix("64:ff9b::/96", "RFC 6052"),
4436
+ extractIPv4: (words) => ipv4FromWords(words[6], words[7])
4437
+ }];
4438
+ function ipv4Prefix(cidr, rfc) {
4439
+ const [address, prefixText] = cidr.split("/");
4440
+ const prefix = parseInt(prefixText, 10);
4441
+ const parts = parseIPv4Address(address);
4442
+ if (parts == null || !Number.isInteger(prefix) || prefix < 0 || prefix > 32) throw new Error(`Invalid IPv4 prefix: ${cidr}`);
4443
+ return {
4444
+ cidr,
4445
+ base: ipv4PartsToNumber(parts),
4446
+ prefix,
4447
+ rfc
4448
+ };
4449
+ }
4450
+ function ipv6Prefix(cidr, rfc) {
4451
+ const [address, prefixText] = cidr.split("/");
4452
+ const prefix = parseInt(prefixText, 10);
4453
+ const words = parseIPv6Address(address);
4454
+ if (words == null || !Number.isInteger(prefix) || prefix < 0 || prefix > 128) throw new Error(`Invalid IPv6 prefix: ${cidr}`);
4455
+ return {
4456
+ cidr,
4457
+ words,
4458
+ prefix,
4459
+ rfc
4460
+ };
4461
+ }
4462
+ function parseIPv4Address(address) {
4463
+ const parts = address.split(".").map((part) => {
4464
+ if (!/^\d+$/.test(part)) return NaN;
4465
+ return parseInt(part, 10);
4466
+ });
4467
+ if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return null;
4468
+ return parts;
4469
+ }
4470
+ function parseIPv6Address(address) {
4471
+ const parts = expandIPv6Address(address).split(":");
4472
+ if (parts.length !== 8) return null;
4473
+ const words = parts.map((part) => {
4474
+ if (!/^[0-9a-f]{1,4}$/i.test(part)) return NaN;
4475
+ return parseInt(part, 16);
4476
+ });
4477
+ if (words.some((word) => !Number.isInteger(word) || word < 0 || word > 65535)) return null;
4478
+ return words;
4479
+ }
4480
+ function ipv4PartsToNumber(parts) {
4481
+ return parts[0] * 2 ** 24 + parts[1] * 2 ** 16 + parts[2] * 2 ** 8 + parts[3];
4482
+ }
4483
+ function ipv4FromWords(highWord, lowWord) {
4484
+ return [
4485
+ highWord >> 8,
4486
+ highWord & 255,
4487
+ lowWord >> 8,
4488
+ lowWord & 255
4489
+ ].join(".");
4490
+ }
4491
+ function matchesIPv4Prefix(address, prefixBase, prefixLength) {
4492
+ const blockSize = 2 ** (32 - prefixLength);
4493
+ return Math.floor(address / blockSize) === Math.floor(prefixBase / blockSize);
4494
+ }
4495
+ function matchesIPv6Prefix(address, prefixWords, prefixLength) {
4496
+ let remaining = prefixLength;
4497
+ for (let i = 0; i < 8 && remaining > 0; i++) if (remaining >= 16) {
4498
+ if (address[i] !== prefixWords[i]) return false;
4499
+ remaining -= 16;
4500
+ } else {
4501
+ const mask = 65535 << 16 - remaining & 65535;
4502
+ if ((address[i] & mask) !== (prefixWords[i] & mask)) return false;
4503
+ remaining = 0;
4504
+ }
4505
+ return true;
4506
+ }
4399
4507
  //#endregion
4400
4508
  //#region src/runtime/docloader.ts
4401
4509
  const logger = getLogger([
@@ -29,7 +29,7 @@ let node_dns_promises = require("node:dns/promises");
29
29
  let node_net = require("node:net");
30
30
  //#region deno.json
31
31
  var name = "@fedify/fedify";
32
- var version = "1.9.10";
32
+ var version = "1.9.12-dev.2265+f8512d84";
33
33
  //#endregion
34
34
  //#region src/runtime/contexts.ts
35
35
  const preloadedContexts = {
@@ -4396,29 +4396,137 @@ function validatePublicIpAddress(address, family) {
4396
4396
  throw new UrlError(`Invalid or private address: ${address}`);
4397
4397
  }
4398
4398
  function isValidPublicIPv4Address(address) {
4399
- const parts = address.split(".");
4400
- const first = parseInt(parts[0]);
4401
- if (first === 0 || first === 10 || first === 127) return false;
4402
- const second = parseInt(parts[1]);
4403
- if (first === 169 && second === 254) return false;
4404
- if (first === 172 && second >= 16 && second <= 31) return false;
4405
- if (first === 192 && second === 168) return false;
4406
- return true;
4399
+ const parts = parseIPv4Address(address);
4400
+ if (parts == null) return false;
4401
+ const value = ipv4PartsToNumber(parts);
4402
+ return !nonPublicIPv4Prefixes.some(({ base, prefix }) => matchesIPv4Prefix(value, base, prefix));
4407
4403
  }
4408
4404
  function isValidPublicIPv6Address(address) {
4409
- address = expandIPv6Address(address);
4410
- if (address.at(4) !== ":") return false;
4411
- const firstWord = parseInt(address.substring(0, 4), 16);
4412
- return !(firstWord >= 64512 && firstWord <= 65023 || firstWord >= 65152 && firstWord <= 65215 || firstWord === 0 || firstWord >= 65280);
4405
+ const words = parseIPv6Address(address);
4406
+ if (words == null) return false;
4407
+ if (nonPublicIPv6Prefixes.some(({ words: prefixWords, prefix }) => matchesIPv6Prefix(words, prefixWords, prefix))) return false;
4408
+ for (const { extractIPv4, prefix, words: prefixWords } of ipv6WithIPv4Prefixes) {
4409
+ if (!matchesIPv6Prefix(words, prefixWords, prefix)) continue;
4410
+ const ipv4Address = extractIPv4(words);
4411
+ if (ipv4Address != null && !isValidPublicIPv4Address(ipv4Address)) return false;
4412
+ }
4413
+ return true;
4413
4414
  }
4414
4415
  function expandIPv6Address(address) {
4415
4416
  address = address.toLowerCase();
4417
+ const ipv4Delimiter = address.lastIndexOf(":");
4418
+ if (address.includes(".") && ipv4Delimiter >= 0) {
4419
+ const ipv4Parts = parseIPv4Address(address.substring(ipv4Delimiter + 1));
4420
+ if (ipv4Parts == null) return address;
4421
+ const high = (ipv4Parts[0] << 8) + ipv4Parts[1];
4422
+ const low = (ipv4Parts[2] << 8) + ipv4Parts[3];
4423
+ address = address.substring(0, ipv4Delimiter + 1) + high.toString(16) + ":" + low.toString(16);
4424
+ }
4416
4425
  if (address === "::") return "0000:0000:0000:0000:0000:0000:0000:0000";
4417
4426
  if (address.startsWith("::")) address = "0000" + address;
4418
4427
  if (address.endsWith("::")) address = address + "0000";
4419
4428
  address = address.replace("::", ":0000".repeat(8 - (address.match(/:/g) || []).length) + ":");
4420
4429
  return address.split(":").map((part) => part.padStart(4, "0")).join(":");
4421
4430
  }
4431
+ const nonPublicIPv4Prefixes = [
4432
+ ipv4Prefix("0.0.0.0/8", "RFC 6890"),
4433
+ ipv4Prefix("10.0.0.0/8", "RFC 1918"),
4434
+ ipv4Prefix("100.64.0.0/10", "RFC 6598"),
4435
+ ipv4Prefix("127.0.0.0/8", "RFC 1122"),
4436
+ ipv4Prefix("169.254.0.0/16", "RFC 3927"),
4437
+ ipv4Prefix("172.16.0.0/12", "RFC 1918"),
4438
+ ipv4Prefix("192.0.0.0/24", "RFC 6890"),
4439
+ ipv4Prefix("192.0.2.0/24", "RFC 5737"),
4440
+ ipv4Prefix("192.88.99.0/24", "RFC 7526"),
4441
+ ipv4Prefix("192.168.0.0/16", "RFC 1918"),
4442
+ ipv4Prefix("198.18.0.0/15", "RFC 2544"),
4443
+ ipv4Prefix("198.51.100.0/24", "RFC 5737"),
4444
+ ipv4Prefix("203.0.113.0/24", "RFC 5737"),
4445
+ ipv4Prefix("224.0.0.0/4", "RFC 5771"),
4446
+ ipv4Prefix("240.0.0.0/4", "RFC 1112")
4447
+ ];
4448
+ const nonPublicIPv6Prefixes = [
4449
+ ipv6Prefix("::/16", "RFC 4291"),
4450
+ ipv6Prefix("2001::/32", "RFC 4380"),
4451
+ ipv6Prefix("2002::/16", "RFC 3056"),
4452
+ ipv6Prefix("64:ff9b:1::/48", "RFC 8215"),
4453
+ ipv6Prefix("fc00::/7", "RFC 4193"),
4454
+ ipv6Prefix("fe80::/10", "RFC 4291"),
4455
+ ipv6Prefix("ff00::/8", "RFC 4291")
4456
+ ];
4457
+ const ipv6WithIPv4Prefixes = [{
4458
+ ...ipv6Prefix("64:ff9b::/96", "RFC 6052"),
4459
+ extractIPv4: (words) => ipv4FromWords(words[6], words[7])
4460
+ }];
4461
+ function ipv4Prefix(cidr, rfc) {
4462
+ const [address, prefixText] = cidr.split("/");
4463
+ const prefix = parseInt(prefixText, 10);
4464
+ const parts = parseIPv4Address(address);
4465
+ if (parts == null || !Number.isInteger(prefix) || prefix < 0 || prefix > 32) throw new Error(`Invalid IPv4 prefix: ${cidr}`);
4466
+ return {
4467
+ cidr,
4468
+ base: ipv4PartsToNumber(parts),
4469
+ prefix,
4470
+ rfc
4471
+ };
4472
+ }
4473
+ function ipv6Prefix(cidr, rfc) {
4474
+ const [address, prefixText] = cidr.split("/");
4475
+ const prefix = parseInt(prefixText, 10);
4476
+ const words = parseIPv6Address(address);
4477
+ if (words == null || !Number.isInteger(prefix) || prefix < 0 || prefix > 128) throw new Error(`Invalid IPv6 prefix: ${cidr}`);
4478
+ return {
4479
+ cidr,
4480
+ words,
4481
+ prefix,
4482
+ rfc
4483
+ };
4484
+ }
4485
+ function parseIPv4Address(address) {
4486
+ const parts = address.split(".").map((part) => {
4487
+ if (!/^\d+$/.test(part)) return NaN;
4488
+ return parseInt(part, 10);
4489
+ });
4490
+ if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return null;
4491
+ return parts;
4492
+ }
4493
+ function parseIPv6Address(address) {
4494
+ const parts = expandIPv6Address(address).split(":");
4495
+ if (parts.length !== 8) return null;
4496
+ const words = parts.map((part) => {
4497
+ if (!/^[0-9a-f]{1,4}$/i.test(part)) return NaN;
4498
+ return parseInt(part, 16);
4499
+ });
4500
+ if (words.some((word) => !Number.isInteger(word) || word < 0 || word > 65535)) return null;
4501
+ return words;
4502
+ }
4503
+ function ipv4PartsToNumber(parts) {
4504
+ return parts[0] * 2 ** 24 + parts[1] * 2 ** 16 + parts[2] * 2 ** 8 + parts[3];
4505
+ }
4506
+ function ipv4FromWords(highWord, lowWord) {
4507
+ return [
4508
+ highWord >> 8,
4509
+ highWord & 255,
4510
+ lowWord >> 8,
4511
+ lowWord & 255
4512
+ ].join(".");
4513
+ }
4514
+ function matchesIPv4Prefix(address, prefixBase, prefixLength) {
4515
+ const blockSize = 2 ** (32 - prefixLength);
4516
+ return Math.floor(address / blockSize) === Math.floor(prefixBase / blockSize);
4517
+ }
4518
+ function matchesIPv6Prefix(address, prefixWords, prefixLength) {
4519
+ let remaining = prefixLength;
4520
+ for (let i = 0; i < 8 && remaining > 0; i++) if (remaining >= 16) {
4521
+ if (address[i] !== prefixWords[i]) return false;
4522
+ remaining -= 16;
4523
+ } else {
4524
+ const mask = 65535 << 16 - remaining & 65535;
4525
+ if ((address[i] & mask) !== (prefixWords[i] & mask)) return false;
4526
+ remaining = 0;
4527
+ }
4528
+ return true;
4529
+ }
4422
4530
  //#endregion
4423
4531
  //#region src/runtime/docloader.ts
4424
4532
  const logger = (0, _logtape_logtape.getLogger)([
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { ct as __commonJSMin, dt as __toESM } from "./vocab-BPE_99_6.mjs";
4
+ import { ct as __commonJSMin, dt as __toESM } from "./vocab-BmWZ5Z8b.mjs";
5
5
  //#region ../../node_modules/.pnpm/glob-to-regexp@0.4.1/node_modules/glob-to-regexp/index.js
6
6
  var require_glob_to_regexp = /* @__PURE__ */ __commonJSMin(((exports, module) => {
7
7
  module.exports = function(glob, opts) {
@@ -1,14 +1,14 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { C as Person, _ as Note, t as Activity } from "../vocab-BPE_99_6.mjs";
5
- import { t as test } from "../testing-2hgRVgOJ.mjs";
4
+ import { C as Person, _ as Note, t as Activity } from "../vocab-BmWZ5Z8b.mjs";
5
+ import { t as test } from "../testing-Dbq3x7rR.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
7
7
  import { a as assertExists } from "../std__assert-2v7gYiZp.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BIL7gChy.mjs";
9
9
  import { t as MemoryKvStore } from "../kv-DM1zFCtL.mjs";
10
10
  import { n as parseSemVer } from "../semver-CgD82xxg.mjs";
11
- import { n as createFederationBuilder } from "../builder-Dy69enN4.mjs";
11
+ import { n as createFederationBuilder } from "../builder-Dhm6irl1.mjs";
12
12
  //#region src/federation/builder.test.ts
13
13
  test("FederationBuilder", async (t) => {
14
14
  await t.step("should build a Federation object with registered components", async () => {
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as test } from "../testing-2hgRVgOJ.mjs";
4
+ import { t as test } from "../testing-Dbq3x7rR.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-2v7gYiZp.mjs";
7
7
  import { n as digest, t as buildCollectionSynchronizationHeader } from "../collection-BD6-SZ6O.mjs";