@fedify/fedify 2.4.0-dev.2155 → 2.4.0-dev.2157

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 (91) hide show
  1. package/dist/{builder-CxHALSwA.mjs → builder-CLaS4-yA.mjs} +2 -2
  2. package/dist/{client-DpnpgjyX.mjs → client-CEnNz8O7.mjs} +7 -3
  3. package/dist/compat/transformers.test.mjs +1 -1
  4. package/dist/{compound-proof-nhrXTRQO.mjs → compound-proof-D7K94KPz.mjs} +2 -2
  5. package/dist/{context-OrnjnuMq.mjs → context-B2rlkkyJ.mjs} +1 -1
  6. package/dist/{deno-YLLbRq06.mjs → deno-D1gcWWqB.mjs} +1 -1
  7. package/dist/{dist-BQvArojP.mjs → dist-DJQM4u7i.mjs} +2 -1
  8. package/dist/docloader-BMqr3hji.mjs +79 -0
  9. package/dist/federation/builder.test.mjs +1 -1
  10. package/dist/federation/compound-fanout.test.mjs +3 -3
  11. package/dist/federation/handler-compound-proof.test.mjs +4 -4
  12. package/dist/federation/handler.test.mjs +6 -6
  13. package/dist/federation/hashlink-media.test.mjs +2 -2
  14. package/dist/federation/idempotency.test.mjs +2 -2
  15. package/dist/federation/metrics.test.mjs +1 -1
  16. package/dist/federation/middleware.test.mjs +187 -10
  17. package/dist/federation/mod.cjs +1 -1
  18. package/dist/federation/mod.js +1 -1
  19. package/dist/federation/mq.test.mjs +98 -69
  20. package/dist/federation/outgoing-proof.test.mjs +5 -5
  21. package/dist/federation/portable-actor.test.mjs +3 -3
  22. package/dist/federation/portable-chain.test.mjs +3 -3
  23. package/dist/federation/portable-collection.test.mjs +4 -4
  24. package/dist/federation/portable-gateway-keys.test.mjs +4 -4
  25. package/dist/federation/portable-inbox.test.mjs +4 -4
  26. package/dist/federation/portable.test.mjs +3 -3
  27. package/dist/federation/send.test.mjs +84 -3
  28. package/dist/federation/tasks/enqueue.test.mjs +3 -3
  29. package/dist/federation/tasks/tasks.test.mjs +4 -4
  30. package/dist/federation/temporal.test.mjs +1 -1
  31. package/dist/federation/webfinger.test.mjs +2 -2
  32. package/dist/{federation-D9TufmIO.cjs → federation-2e8XrN7q.cjs} +19 -5
  33. package/dist/{http-eqYXHRkz.cjs → http-BObQoB0j.cjs} +7 -3
  34. package/dist/{http-CXnNbRe_.mjs → http-CGcLv8rh.mjs} +9 -5
  35. package/dist/{http-Dk4O3WM0.js → http-Dgtt45-K.js} +7 -3
  36. package/dist/{key-BZ-Z4uez.mjs → key-CPM4r6tP.mjs} +2 -2
  37. package/dist/{kv-cache-3uKc0G76.js → kv-cache-BweyIZTb.js} +35 -9
  38. package/dist/{kv-cache-DzClEalR.cjs → kv-cache-D2fnB8qu.cjs} +34 -8
  39. package/dist/{kv-cache-DZr8HTel.mjs → kv-cache-bdPqTR1k.mjs} +1 -1
  40. package/dist/{ld-Djxsq6JR.mjs → ld-lU_ZqzsQ.mjs} +4 -4
  41. package/dist/{metrics-CBHhbHgG.mjs → metrics-B41pRPfd.mjs} +1 -1
  42. package/dist/{middleware-BDUR99k3.js → middleware-BYWyYjmX.js} +19 -5
  43. package/dist/{middleware-BahNnLfD.mjs → middleware-TrCVULgs.mjs} +1 -1
  44. package/dist/{middleware-DDa8pCUa.mjs → middleware-xdukzV3x.mjs} +15 -15
  45. package/dist/{mod-CZetqT5h.d.ts → mod-DaiBrWDW.d.ts} +2 -0
  46. package/dist/{mod-D4g9ffEn.d.cts → mod-Mt4aO3DX.d.cts} +2 -0
  47. package/dist/mod.cjs +5 -5
  48. package/dist/mod.d.cts +1 -1
  49. package/dist/mod.d.ts +1 -1
  50. package/dist/mod.js +5 -5
  51. package/dist/nodeinfo/client.test.mjs +49 -1
  52. package/dist/nodeinfo/handler.test.mjs +2 -2
  53. package/dist/nodeinfo/mod.cjs +1 -1
  54. package/dist/nodeinfo/mod.js +1 -1
  55. package/dist/{owner-OdWSE8am.mjs → owner-D63yPo_i.mjs} +3 -3
  56. package/dist/{portable-collection-wBWbuHOH.cjs → portable-collection-B8ojoQ50.cjs} +1 -1
  57. package/dist/{portable-collection-BCy06GiS.js → portable-collection-C3xEzYri.js} +1 -1
  58. package/dist/{portable-collection-DAV7Ho3m.mjs → portable-collection-_lZg-osX.mjs} +2 -2
  59. package/dist/{portable-key-BL6K88p2.mjs → portable-key-D8uWZF7b.mjs} +1 -1
  60. package/dist/{proof-vZ04IAjq.mjs → proof-C2YwD8a_.mjs} +4 -4
  61. package/dist/{send-ylV8KCLx.mjs → send-D9SGhxTB.mjs} +18 -4
  62. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  63. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  64. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  65. package/dist/sig/compound-proof.test.mjs +2 -2
  66. package/dist/sig/http.test.mjs +42 -2
  67. package/dist/sig/key.test.mjs +1 -1
  68. package/dist/sig/ld.test.mjs +5 -2
  69. package/dist/sig/mod.cjs +2 -2
  70. package/dist/sig/mod.js +2 -2
  71. package/dist/sig/owner.test.mjs +1 -1
  72. package/dist/sig/portable-collection.test.mjs +2 -2
  73. package/dist/sig/portable-key.test.mjs +6 -6
  74. package/dist/sig/proof.test.mjs +3 -3
  75. package/dist/{tasks-dbCShlCb.mjs → tasks-IG3pHfvZ.mjs} +1 -1
  76. package/dist/{temporal-BTD4f_mZ.mjs → temporal-q6FSekcN.mjs} +1 -1
  77. package/dist/testing/context.test.mjs +1 -1
  78. package/dist/testing/kv.test.mjs +3 -3
  79. package/dist/testing/mod.mjs +4 -4
  80. package/dist/{testing-CKaJhcA0.mjs → testing-C1itIjqW.mjs} +3 -3
  81. package/dist/{types-C_cNlNVK.js → types-_S2_MeLF.js} +7 -3
  82. package/dist/{types-Be2zbyeG.cjs → types-poIao40f.cjs} +7 -3
  83. package/dist/utils/docloader.test.mjs +297 -2
  84. package/dist/utils/kv-cache.test.mjs +1 -1
  85. package/dist/utils/mod.cjs +1 -1
  86. package/dist/utils/mod.d.cts +1 -1
  87. package/dist/utils/mod.d.ts +1 -1
  88. package/dist/utils/mod.js +1 -1
  89. package/dist/vocab/cjs.test.mjs +1 -1
  90. package/package.json +7 -7
  91. package/dist/docloader-vc-pSu9-.mjs +0 -53
@@ -1,8 +1,7 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as AssertionError } from "../assertion_error-B-cx0fFA.mjs";
5
- import { s as format, t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
4
+ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
5
  import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
6
  import { t as assertGreaterOrEqual } from "../assert_greater_or_equal-BlafOF4-.mjs";
8
7
  import "../std__assert-DvMDRPes.mjs";
@@ -11,31 +10,6 @@ import { t as assert } from "../assert-D1Eafmd_.mjs";
11
10
  import { n as ParallelMessageQueue, t as InProcessMessageQueue } from "../mq-Dm1Wmtm-.mjs";
12
11
  import { delay } from "es-toolkit";
13
12
  import { test } from "@fedify/fixture";
14
- //#region ../../node_modules/.pnpm/@jsr+std__assert@0.226.0/node_modules/@jsr/std__assert/assert_greater.js
15
- /**
16
- * Make an assertion that `actual` is greater than `expected`.
17
- * If not then throw.
18
- *
19
- * @example Usage
20
- * ```ts no-eval
21
- * import { assertGreater } from "@std/assert/assert-greater";
22
- *
23
- * assertGreater(2, 1); // Doesn't throw
24
- * assertGreater(1, 1); // Throws
25
- * assertGreater(0, 1); // Throws
26
- * ```
27
- *
28
- * @typeParam T The type of the values to compare.
29
- * @param actual The actual value to compare.
30
- * @param expected The expected value to compare.
31
- * @param msg The optional message to display if the assertion fails.
32
- */ function assertGreater(actual, expected, msg) {
33
- if (actual > expected) return;
34
- const actualString = format(actual);
35
- const expectedString = format(expected);
36
- throw new AssertionError(msg ?? `Expect ${actualString} > ${expectedString}`);
37
- }
38
- //#endregion
39
13
  //#region src/federation/mq.test.ts
40
14
  async function disposeMessageQueue(mq) {
41
15
  if (Symbol.asyncDispose in mq) {
@@ -70,50 +44,105 @@ test("InProcessMessageQueue", async (t) => {
70
44
  const listening = mq.listen((message) => {
71
45
  messages.push(message);
72
46
  }, controller);
73
- await t.step("enqueue()", async () => {
74
- await mq.enqueue("Hello, world!");
75
- });
76
- await waitFor(() => messages.length > 0, 15e3);
77
- await t.step("listen()", () => {
78
- assertEquals(messages, ["Hello, world!"]);
79
- });
80
- let started = 0;
81
- await t.step("enqueue() with delay", async () => {
82
- started = Date.now();
83
- await mq.enqueue("Delayed message", { delay: Temporal.Duration.from({ seconds: 3 }) });
84
- assertEquals(messages, ["Hello, world!"]);
85
- });
86
- await waitFor(() => messages.length > 1, 15e3);
87
- await t.step("listen() with delay", () => {
88
- assertEquals(messages, ["Hello, world!", "Delayed message"]);
89
- assertGreater(Date.now() - started, 3e3);
90
- });
91
- while (messages.length > 0) messages.pop();
92
- await t.step("enqueueMany()", async () => {
93
- const testMessages = Array.from({ length: 5 }, (_, i) => `Batch message ${i}!`);
94
- await mq.enqueueMany(testMessages);
95
- });
96
- await waitFor(() => messages.length >= 5, 15e3);
97
- await t.step("listen() [multiple]", () => {
98
- assertEquals(messages.length, 5);
99
- for (let i = 0; i < 5; i++) assertEquals(messages[i], `Batch message ${i}!`);
100
- });
101
- while (messages.length > 0) messages.pop();
102
- started = 0;
103
- await t.step("enqueueMany() with delay", async () => {
104
- started = Date.now();
105
- const testMessages = Array.from({ length: 3 }, (_, i) => `Delayed batch ${i}!`);
106
- await mq.enqueueMany(testMessages, { delay: Temporal.Duration.from({ seconds: 2 }) });
107
- assertEquals(messages.length, 0);
47
+ try {
48
+ await t.step("enqueue()", async () => {
49
+ await mq.enqueue("Hello, world!");
50
+ });
51
+ await waitFor(() => messages.length > 0, 15e3);
52
+ await t.step("listen()", () => {
53
+ assertEquals(messages, ["Hello, world!"]);
54
+ });
55
+ await t.step("enqueue() with delay", async () => {
56
+ const { timers, enqueued } = captureTimers(() => mq.enqueue("Delayed message", { delay: Temporal.Duration.from({ seconds: 3 }) }));
57
+ await enqueued;
58
+ assertEquals(timers.length, 1);
59
+ assertEquals(timers[0].delay, 3e3);
60
+ await mq.enqueue("Single delay marker");
61
+ await waitFor(() => messages.includes("Single delay marker"), 15e3);
62
+ assertEquals(messages, ["Hello, world!", "Single delay marker"]);
63
+ timers[0].callback();
64
+ });
65
+ await waitFor(() => messages.length >= 3, 15e3);
66
+ await t.step("listen() with delay", () => {
67
+ assertEquals(messages, [
68
+ "Hello, world!",
69
+ "Single delay marker",
70
+ "Delayed message"
71
+ ]);
72
+ });
73
+ while (messages.length > 0) messages.pop();
74
+ await t.step("enqueueMany()", async () => {
75
+ const testMessages = Array.from({ length: 5 }, (_, i) => `Batch message ${i}!`);
76
+ await mq.enqueueMany(testMessages);
77
+ });
78
+ await waitFor(() => messages.length >= 5, 15e3);
79
+ await t.step("listen() [multiple]", () => {
80
+ assertEquals(messages.length, 5);
81
+ for (let i = 0; i < 5; i++) assertEquals(messages[i], `Batch message ${i}!`);
82
+ });
83
+ while (messages.length > 0) messages.pop();
84
+ await t.step("enqueueMany() with delay", async () => {
85
+ const testMessages = Array.from({ length: 3 }, (_, i) => `Delayed batch ${i}!`);
86
+ const { timers, enqueued } = captureTimers(() => mq.enqueueMany(testMessages, { delay: Temporal.Duration.from({ seconds: 2 }) }));
87
+ await enqueued;
88
+ assertEquals(timers.length, 1);
89
+ assertEquals(timers[0].delay, 2e3);
90
+ await mq.enqueue("Batch delay marker");
91
+ await waitFor(() => messages.includes("Batch delay marker"), 15e3);
92
+ assertEquals(messages, ["Batch delay marker"]);
93
+ timers[0].callback();
94
+ });
95
+ await waitFor(() => messages.length >= 4, 15e3);
96
+ await t.step("listen() [delayed multiple]", () => {
97
+ assertEquals(messages.length, 4);
98
+ assertEquals(messages[0], "Batch delay marker");
99
+ for (let i = 0; i < 3; i++) assertEquals(messages[i + 1], `Delayed batch ${i}!`);
100
+ });
101
+ } finally {
102
+ controller.abort();
103
+ await listening;
104
+ }
105
+ });
106
+ function captureTimers(enqueue) {
107
+ const timers = [];
108
+ const original = globalThis.setTimeout;
109
+ globalThis.setTimeout = ((callback, delay) => {
110
+ timers.push({
111
+ callback,
112
+ delay
113
+ });
114
+ return 0;
108
115
  });
109
- await waitFor(() => messages.length >= 3, 15e3);
110
- await t.step("listen() [delayed multiple]", () => {
111
- assertEquals(messages.length, 3);
112
- assertGreater(Date.now() - started, 2e3);
113
- for (let i = 0; i < 3; i++) assertEquals(messages[i], `Delayed batch ${i}!`);
116
+ try {
117
+ return {
118
+ timers,
119
+ enqueued: enqueue()
120
+ };
121
+ } finally {
122
+ globalThis.setTimeout = original;
123
+ }
124
+ }
125
+ test("InProcessMessageQueue real delay", async (t) => {
126
+ for (const batch of [false, true]) await t.step(batch ? "enqueueMany()" : "enqueue()", async () => {
127
+ const mq = new InProcessMessageQueue();
128
+ const messages = [];
129
+ const controller = new AbortController();
130
+ const listening = mq.listen((message) => {
131
+ messages.push(message);
132
+ }, controller);
133
+ try {
134
+ const delayed = batch ? ["Delayed 1", "Delayed 2"] : ["Delayed"];
135
+ const options = { delay: Temporal.Duration.from({ milliseconds: 100 }) };
136
+ if (batch) await mq.enqueueMany(delayed, options);
137
+ else await mq.enqueue(delayed[0], options);
138
+ await mq.enqueue("Immediate");
139
+ await waitFor(() => messages.length >= delayed.length + 1, 15e3);
140
+ assertEquals(messages, ["Immediate", ...delayed]);
141
+ } finally {
142
+ controller.abort();
143
+ await listening;
144
+ }
114
145
  });
115
- controller.abort();
116
- await listening;
117
146
  });
118
147
  test("InProcessMessageQueue.getDepth()", async () => {
119
148
  const mq = new InProcessMessageQueue();
@@ -7,12 +7,12 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
8
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { n as exportJwk } from "../key-BZ-Z4uez.mjs";
11
- import { s as detachSignature } from "../ld-Djxsq6JR.mjs";
12
- import { a as signObject } from "../proof-vZ04IAjq.mjs";
10
+ import { n as exportJwk } from "../key-CPM4r6tP.mjs";
11
+ import { s as detachSignature } from "../ld-lU_ZqzsQ.mjs";
12
+ import { a as signObject } from "../proof-C2YwD8a_.mjs";
13
13
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { c as assertPortableActorActivity, n as FederationImpl, o as createFederation } from "../middleware-DDa8pCUa.mjs";
15
- import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-nhrXTRQO.mjs";
14
+ import { c as assertPortableActorActivity, n as FederationImpl, o as createFederation } from "../middleware-xdukzV3x.mjs";
15
+ import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-D7K94KPz.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
17
  import { Create, Note, Person } from "@fedify/vocab";
18
18
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -8,10 +8,10 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
9
9
  import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { a as signObject, c as verifyPortableObjectProof } from "../proof-vZ04IAjq.mjs";
12
- import { d as verifyRequest, l as signRequest } from "../http-CXnNbRe_.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-C2YwD8a_.mjs";
12
+ import { d as verifyRequest, l as signRequest } from "../http-CGcLv8rh.mjs";
13
13
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DDa8pCUa.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-xdukzV3x.mjs";
15
15
  import { n as RouterError } from "../router-u5O5KCQr.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
17
  import { Note, Person, Tombstone, lookupObject } from "@fedify/vocab";
@@ -7,10 +7,10 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { n as exportJwk } from "../key-BZ-Z4uez.mjs";
11
- import { c as verifyPortableObjectProof, s as verifyObject } from "../proof-vZ04IAjq.mjs";
10
+ import { n as exportJwk } from "../key-CPM4r6tP.mjs";
11
+ import { c as verifyPortableObjectProof, s as verifyObject } from "../proof-C2YwD8a_.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
13
- import { n as FederationImpl } from "../middleware-DDa8pCUa.mjs";
13
+ import { n as FederationImpl } from "../middleware-xdukzV3x.mjs";
14
14
  import { Create, DataIntegrityProof, Note, OrderedCollection, Person, traverseCollection } from "@fedify/vocab";
15
15
  import { mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { FetchError, encodeMultibase, exportDidKey } from "@fedify/vocab-runtime";
@@ -7,11 +7,11 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { a as signObject } from "../proof-vZ04IAjq.mjs";
10
+ import { a as signObject } from "../proof-C2YwD8a_.mjs";
11
11
  import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
12
- import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DDa8pCUa.mjs";
13
- import { t as verifyPortableObject } from "../portable-collection-DAV7Ho3m.mjs";
14
- import { s as verifyServedPortableObjects } from "../compound-proof-nhrXTRQO.mjs";
12
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-xdukzV3x.mjs";
13
+ import { t as verifyPortableObject } from "../portable-collection-_lZg-osX.mjs";
14
+ import { s as verifyServedPortableObjects } from "../compound-proof-D7K94KPz.mjs";
15
15
  import { n as RouterError } from "../router-u5O5KCQr.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
17
  import { Create, Note, Object as Object$1, OrderedCollection, Person, Tombstone, lookupObject, traverseCollection } from "@fedify/vocab";
@@ -2,15 +2,15 @@ import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as esm_default } from "../esm-BHXXx4Wx.mjs";
5
- import { r as createRequestContext, t as createInboxContext } from "../context-OrnjnuMq.mjs";
5
+ import { r as createRequestContext, t as createInboxContext } from "../context-B2rlkkyJ.mjs";
6
6
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
7
7
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
10
- import { p as signJsonLd } from "../ld-Djxsq6JR.mjs";
11
- import { l as signRequest } from "../http-CXnNbRe_.mjs";
10
+ import { p as signJsonLd } from "../ld-lU_ZqzsQ.mjs";
11
+ import { l as signRequest } from "../http-CGcLv8rh.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
13
- import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-DDa8pCUa.mjs";
13
+ import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-xdukzV3x.mjs";
14
14
  import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
15
15
  import { t as KvKeyCache } from "../keycache-BInaECGj.mjs";
16
16
  import { Create, CryptographicKey, Person } from "@fedify/vocab";
@@ -8,11 +8,11 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
9
9
  import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { p as signJsonLd } from "../ld-Djxsq6JR.mjs";
12
- import { a as signObject } from "../proof-vZ04IAjq.mjs";
13
- import { f as verifyRequestDetailed, l as signRequest } from "../http-CXnNbRe_.mjs";
11
+ import { p as signJsonLd } from "../ld-lU_ZqzsQ.mjs";
12
+ import { a as signObject } from "../proof-C2YwD8a_.mjs";
13
+ import { f as verifyRequestDetailed, l as signRequest } from "../http-CGcLv8rh.mjs";
14
14
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
15
- import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-DDa8pCUa.mjs";
15
+ import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-xdukzV3x.mjs";
16
16
  import { Create, CryptographicKey, Follow, Note, Person, Tombstone } from "@fedify/vocab";
17
17
  import { mockDocumentLoader, test } from "@fedify/fixture";
18
18
  import { exportDidKey, formatIri, parseIri } from "@fedify/vocab-runtime";
@@ -8,10 +8,10 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { a as signObject, c as verifyPortableObjectProof } from "../proof-vZ04IAjq.mjs";
12
- import { l as signRequest } from "../http-CXnNbRe_.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-C2YwD8a_.mjs";
12
+ import { l as signRequest } from "../http-CGcLv8rh.mjs";
13
13
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DDa8pCUa.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-xdukzV3x.mjs";
15
15
  import { configure, reset } from "@logtape/logtape";
16
16
  import { Collection, Create, Note, Object as Object$1, Person, Tombstone, lookupObject } from "@fedify/vocab";
17
17
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -10,13 +10,14 @@ import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
10
10
  import "../std__assert-DvMDRPes.mjs";
11
11
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
12
12
  import { t as assert } from "../assert-D1Eafmd_.mjs";
13
- import { d as verifyRequest } from "../http-CXnNbRe_.mjs";
13
+ import { d as verifyRequest } from "../http-CGcLv8rh.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-OdWSE8am.mjs";
16
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-ylV8KCLx.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-D63yPo_i.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-D9SGhxTB.mjs";
17
17
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
18
18
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
19
19
  import { FetchError, UrlError } from "@fedify/vocab-runtime";
20
+ import dns from "node:dns/promises";
20
21
  import { AggregationTemporality, InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
21
22
  //#region src/federation/send.test.ts
22
23
  test("extractInboxes()", () => {
@@ -690,5 +691,85 @@ for (const signed of [false, true]) {
690
691
  });
691
692
  });
692
693
  }
694
+ for (const signed of [false, true]) test({
695
+ name: `sendActivity() classifies DNS failures (signed: ${signed})`,
696
+ ignore: "Deno" in globalThis && (await Deno.permissions.query({ name: "net" })).state !== "granted",
697
+ async fn(t) {
698
+ const activity = {
699
+ type: "Create",
700
+ id: "https://example.com/activity"
701
+ };
702
+ const destination = "https://delivery.invalid/inbox";
703
+ const publicInbox = "https://8.8.8.8/inbox";
704
+ const keys = signed ? [{
705
+ privateKey: rsaPrivateKey2,
706
+ keyId: rsaPublicKey2.id
707
+ }] : [];
708
+ for (const result of [
709
+ "throws",
710
+ "empty",
711
+ "cname",
712
+ "private"
713
+ ]) for (const redirected of [false, true]) await t.step(`${result}, redirected: ${redirected}`, async () => {
714
+ const [meterProvider, recorder] = createTestMeterProvider();
715
+ const originalLookup = dns.lookup;
716
+ const resolverError = /* @__PURE__ */ new Error("Resolver unavailable");
717
+ const lookups = [];
718
+ dns.lookup = ((hostname, options) => {
719
+ lookups.push(hostname);
720
+ assertEquals(hostname, "delivery.invalid");
721
+ assertEquals(options, { all: true });
722
+ if (result === "throws") return Promise.reject(resolverError);
723
+ return Promise.resolve(result === "empty" ? [] : [{
724
+ address: result === "private" ? "127.0.0.1" : "alias.invalid.",
725
+ family: 4
726
+ }]);
727
+ });
728
+ try {
729
+ esm_default.mockGlobal().catch(202);
730
+ if (redirected) esm_default.route(publicInbox, {
731
+ status: 307,
732
+ headers: { Location: destination }
733
+ });
734
+ const send = () => sendActivity({
735
+ activity,
736
+ activityType: "https://www.w3.org/ns/activitystreams#Create",
737
+ meterProvider,
738
+ keys,
739
+ inbox: new URL(redirected ? publicInbox : destination)
740
+ });
741
+ if (result === "private") assertEquals((await assertRejects(send, UrlError)).reason, "disallowed");
742
+ else {
743
+ const error = await assertRejects(send, FetchError);
744
+ assertEquals(error.url.href, destination);
745
+ assertInstanceOf(error.cause, UrlError);
746
+ assertEquals(error.cause.reason, "dns");
747
+ assertEquals(error.cause.cause, result === "throws" ? resolverError : void 0);
748
+ }
749
+ const expectedCount = result === "private" && !redirected ? 0 : 1;
750
+ const sent = recorder.getMeasurements("activitypub.delivery.sent");
751
+ const durations = recorder.getMeasurements("activitypub.delivery.duration");
752
+ assertEquals(sent.length, expectedCount);
753
+ assertEquals(durations.length, expectedCount);
754
+ if (expectedCount === 1) {
755
+ assertEquals(sent[0].value, 1);
756
+ assertEquals(sent[0].attributes, {
757
+ "activitypub.remote.host": redirected ? "8.8.8.8" : "delivery.invalid",
758
+ "activitypub.activity.type": "https://www.w3.org/ns/activitystreams#Create",
759
+ "activitypub.delivery.success": false
760
+ });
761
+ assertEquals(durations[0].attributes, sent[0].attributes);
762
+ assertGreaterOrEqual(durations[0].value, 0);
763
+ }
764
+ assertEquals(lookups, ["delivery.invalid"]);
765
+ assertEquals(esm_default.callHistory.calls(destination).length, 0);
766
+ assertEquals(esm_default.callHistory.calls().length, redirected ? 1 : 0);
767
+ } finally {
768
+ dns.lookup = originalLookup;
769
+ esm_default.hardReset();
770
+ }
771
+ });
772
+ }
773
+ });
693
774
  //#endregion
694
775
  export {};
@@ -2,9 +2,9 @@ import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
- import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-dbCShlCb.mjs";
6
- import "../../testing-CKaJhcA0.mjs";
7
- import { o as createFederation } from "../../middleware-DDa8pCUa.mjs";
5
+ import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-IG3pHfvZ.mjs";
6
+ import "../../testing-C1itIjqW.mjs";
7
+ import { o as createFederation } from "../../middleware-xdukzV3x.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";
@@ -2,10 +2,10 @@ import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
- import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-dbCShlCb.mjs";
6
- import "../../testing-CKaJhcA0.mjs";
7
- import { o as createFederation } from "../../middleware-DDa8pCUa.mjs";
8
- import { r as createFederationBuilder } from "../../builder-CxHALSwA.mjs";
5
+ import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-IG3pHfvZ.mjs";
6
+ import "../../testing-C1itIjqW.mjs";
7
+ import { o as createFederation } from "../../middleware-xdukzV3x.mjs";
8
+ import { r as createFederationBuilder } from "../../builder-CLaS4-yA.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-CPdRnc3E.mjs";
5
5
  import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assert } from "../assert-D1Eafmd_.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-BTD4f_mZ.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-q6FSekcN.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  //#region src/federation/temporal.test.ts
10
10
  test("hasMalformedKnownTemporalLiteral() detects expanded proof timestamps", async () => {
@@ -1,12 +1,12 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { r as createRequestContext } from "../context-OrnjnuMq.mjs";
4
+ import { r as createRequestContext } from "../context-B2rlkkyJ.mjs";
5
5
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-DDa8pCUa.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-xdukzV3x.mjs";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  import { createTestMeterProvider, test } from "@fedify/fixture";
12
12
  import { parseIri } from "@fedify/vocab-runtime";
@@ -1,10 +1,10 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-Dmm3t92W.cjs");
3
3
  const require_transformers = require("./transformers-BalCrSsr.cjs");
4
- const require_http = require("./http-eqYXHRkz.cjs");
5
- const require_types = require("./types-Be2zbyeG.cjs");
6
- const require_portable_collection = require("./portable-collection-wBWbuHOH.cjs");
7
- const require_kv_cache = require("./kv-cache-DzClEalR.cjs");
4
+ const require_http = require("./http-BObQoB0j.cjs");
5
+ const require_types = require("./types-poIao40f.cjs");
6
+ const require_portable_collection = require("./portable-collection-B8ojoQ50.cjs");
7
+ const require_kv_cache = require("./kv-cache-D2fnB8qu.cjs");
8
8
  let _logtape_logtape = require("@logtape/logtape");
9
9
  let _fedify_uri_template = require("@fedify/uri-template");
10
10
  let _fedify_vocab = require("@fedify/vocab");
@@ -3016,6 +3016,15 @@ async function sendActivityInternal({ activity, activityId, activityType, keys,
3016
3016
  if (!allowPrivateAddress) try {
3017
3017
  await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
3018
3018
  } catch (error) {
3019
+ if (error instanceof _fedify_vocab_runtime.UrlError && error.reason === "dns") {
3020
+ logger.error("DNS resolution failed for URL: {url}", {
3021
+ url,
3022
+ error
3023
+ });
3024
+ const failure = new _fedify_vocab_runtime.FetchError(url, error.message);
3025
+ failure.cause = error;
3026
+ throw failure;
3027
+ }
3019
3028
  if (error instanceof _fedify_vocab_runtime.UrlError) logger.error("Disallowed private URL: {url}", {
3020
3029
  url,
3021
3030
  error
@@ -3023,7 +3032,12 @@ async function sendActivityInternal({ activity, activityId, activityType, keys,
3023
3032
  throw error;
3024
3033
  }
3025
3034
  }
3026
- await validateUrl(inbox.href);
3035
+ try {
3036
+ await validateUrl(inbox.href);
3037
+ } catch (error) {
3038
+ if (error instanceof _fedify_vocab_runtime.FetchError) federationMetrics.recordDelivery(inbox, require_http.getDurationMs(started), false, activityType);
3039
+ throw error;
3040
+ }
3027
3041
  headers = new Headers(headers);
3028
3042
  headers.set("Content-Type", "application/activity+json");
3029
3043
  const request = new Request(inbox, {
@@ -16,7 +16,7 @@ json_canon = require_rolldown_runtime.__toESM(json_canon, 1);
16
16
  let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
17
17
  //#region deno.json
18
18
  var name = "@fedify/fedify";
19
- var version = "2.4.0-dev.2155+2ccc5085";
19
+ var version = "2.4.0-dev.2157+b76e5888";
20
20
  //#endregion
21
21
  //#region src/sig/portable-key-id.ts
22
22
  const COMPATIBLE_KEY_ID_PATH_PATTERN = /^\/\.well-known\/apgateway\/did(?::|%3A)/i;
@@ -5804,7 +5804,7 @@ function normalizeContextReference(reference, baseUrl) {
5804
5804
  /** @internal */
5805
5805
  function isInvalidUrlTypeError(error) {
5806
5806
  const code = error.code;
5807
- return error instanceof TypeError && (code === "ERR_INVALID_URL" || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
5807
+ return error instanceof TypeError && (code === "ERR_INVALID_URL" || error.message === "Invalid URL string." || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
5808
5808
  }
5809
5809
  async function applyGraphAliasContext(state, context, documentLoader, remoteContextCache, baseUrl = null, processingContexts = /* @__PURE__ */ new Set()) {
5810
5810
  if (context === null) return createGraphAliasContextState();
@@ -8908,6 +8908,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
8908
8908
  failure = result;
8909
8909
  failureAlgorithm = algorithm;
8910
8910
  };
8911
+ let body = null;
8912
+ let digestValid = null;
8911
8913
  for (const sigName of signatureNames) {
8912
8914
  if (!signatures[sigName]) {
8913
8915
  setFailure(invalidSignatureResult(parseKeyId(signatureInputs[sigName]?.keyId)));
@@ -8959,7 +8961,9 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
8959
8961
  setFailure(invalidSignatureResult(keyId));
8960
8962
  continue;
8961
8963
  }
8962
- if (!await verifyRfc9421ContentDigest(contentDigestHeader, await request.arrayBuffer())) {
8964
+ body ??= await request.arrayBuffer();
8965
+ digestValid ??= await verifyRfc9421ContentDigest(contentDigestHeader, body);
8966
+ if (!digestValid) {
8963
8967
  logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
8964
8968
  setFailure(invalidSignatureResult(keyId));
8965
8969
  continue;
@@ -1,12 +1,12 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-YLLbRq06.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CBHhbHgG.mjs";
4
+ import { n as version, t as name } from "./deno-D1gcWWqB.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-B41pRPfd.mjs";
6
6
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPVqki78.mjs";
7
7
  import { f as parseKeyIdString } from "./portable-key-id-Bg259c4Z.mjs";
8
- import { a as fetchKeyDetailed, c as validateCryptoKey, t as bypassKeyCacheReads } from "./key-BZ-Z4uez.mjs";
9
- import { n as resolvePortableActorKey, r as verifyPortableGatewayKeyDocument } from "./portable-key-BL6K88p2.mjs";
8
+ import { a as fetchKeyDetailed, c as validateCryptoKey, t as bypassKeyCacheReads } from "./key-CPM4r6tP.mjs";
9
+ import { n as resolvePortableActorKey, r as verifyPortableGatewayKeyDocument } from "./portable-key-D8uWZF7b.mjs";
10
10
  import { getLogger } from "@logtape/logtape";
11
11
  import { CryptographicKey } from "@fedify/vocab";
12
12
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -804,6 +804,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
804
804
  failure = result;
805
805
  failureAlgorithm = algorithm;
806
806
  };
807
+ let body = null;
808
+ let digestValid = null;
807
809
  for (const sigName of signatureNames) {
808
810
  if (!signatures[sigName]) {
809
811
  setFailure(invalidSignatureResult(parseKeyId(signatureInputs[sigName]?.keyId)));
@@ -855,7 +857,9 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
855
857
  setFailure(invalidSignatureResult(keyId));
856
858
  continue;
857
859
  }
858
- if (!await verifyRfc9421ContentDigest(contentDigestHeader, await request.arrayBuffer())) {
860
+ body ??= await request.arrayBuffer();
861
+ digestValid ??= await verifyRfc9421ContentDigest(contentDigestHeader, body);
862
+ if (!digestValid) {
859
863
  logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
860
864
  setFailure(invalidSignatureResult(keyId));
861
865
  continue;
@@ -14,7 +14,7 @@ import serialize from "json-canon";
14
14
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
15
15
  //#region deno.json
16
16
  var name = "@fedify/fedify";
17
- var version = "2.4.0-dev.2155+2ccc5085";
17
+ var version = "2.4.0-dev.2157+b76e5888";
18
18
  //#endregion
19
19
  //#region src/sig/portable-key-id.ts
20
20
  const COMPATIBLE_KEY_ID_PATH_PATTERN = /^\/\.well-known\/apgateway\/did(?::|%3A)/i;
@@ -2238,7 +2238,7 @@ function normalizeContextReference(reference, baseUrl) {
2238
2238
  /** @internal */
2239
2239
  function isInvalidUrlTypeError(error) {
2240
2240
  const code = error.code;
2241
- return error instanceof TypeError && (code === "ERR_INVALID_URL" || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
2241
+ return error instanceof TypeError && (code === "ERR_INVALID_URL" || error.message === "Invalid URL string." || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
2242
2242
  }
2243
2243
  async function applyGraphAliasContext(state, context, documentLoader, remoteContextCache, baseUrl = null, processingContexts = /* @__PURE__ */ new Set()) {
2244
2244
  if (context === null) return createGraphAliasContextState();
@@ -5340,6 +5340,8 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
5340
5340
  failure = result;
5341
5341
  failureAlgorithm = algorithm;
5342
5342
  };
5343
+ let body = null;
5344
+ let digestValid = null;
5343
5345
  for (const sigName of signatureNames) {
5344
5346
  if (!signatures[sigName]) {
5345
5347
  setFailure(invalidSignatureResult(parseKeyId(signatureInputs[sigName]?.keyId)));
@@ -5391,7 +5393,9 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
5391
5393
  setFailure(invalidSignatureResult(keyId));
5392
5394
  continue;
5393
5395
  }
5394
- if (!await verifyRfc9421ContentDigest(contentDigestHeader, await request.arrayBuffer())) {
5396
+ body ??= await request.arrayBuffer();
5397
+ digestValid ??= await verifyRfc9421ContentDigest(contentDigestHeader, body);
5398
+ if (!digestValid) {
5395
5399
  logger.debug("Failed to verify; Content-Digest verification failed.", { contentDigest: contentDigestHeader });
5396
5400
  setFailure(invalidSignatureResult(keyId));
5397
5401
  continue;