@fedify/fedify 2.5.0-dev.2448 → 2.5.0-dev.2494

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 (126) hide show
  1. package/README.md +3 -0
  2. package/dist/{builder-DbC8bn6k.mjs → builder-Y3pokaG2.mjs} +2 -2
  3. package/dist/{client-D-XP_Ccb.d.cts → client-3InDZbba.d.cts} +0 -1
  4. package/dist/{client-D-XP_Ccb.d.ts → client-3InDZbba.d.ts} +0 -1
  5. package/dist/{client-CEnNz8O7.mjs → client-5SIFzW3q.mjs} +113 -64
  6. package/dist/compat/mod.d.cts +1 -1
  7. package/dist/compat/mod.d.ts +1 -1
  8. package/dist/compat/transformers.test.mjs +1 -1
  9. package/dist/{compound-proof-heeXW2_A.mjs → compound-proof-BM7AINht.mjs} +2 -2
  10. package/dist/{context-GlHrzdSP.d.ts → context-DQJE9YfH.d.ts} +29 -3
  11. package/dist/{context-BazwQrHn.d.cts → context-DSuL3YWx.d.cts} +29 -3
  12. package/dist/{deno-Dpewt_jJ.mjs → deno-D7blYLbb.mjs} +1 -1
  13. package/dist/docloader-DbBbDaY-.mjs +136 -0
  14. package/dist/{exporter-DThFfe7P.mjs → exporter-DVG68ozH.mjs} +36 -30
  15. package/dist/federation/builder.test.mjs +1 -1
  16. package/dist/federation/compound-fanout.test.mjs +6 -3
  17. package/dist/federation/handler-compound-proof.test.mjs +3 -3
  18. package/dist/federation/handler.test.mjs +5 -5
  19. package/dist/federation/hashlink-media.test.mjs +2 -2
  20. package/dist/federation/idempotency.test.mjs +2 -2
  21. package/dist/federation/inbox-actorless.test.mjs +5 -5
  22. package/dist/federation/inbox-report.test.mjs +5 -5
  23. package/dist/federation/inbox-view.test.mjs +1 -1
  24. package/dist/federation/inbox.test.mjs +1 -1
  25. package/dist/federation/metrics.test.mjs +1 -1
  26. package/dist/federation/middleware.test.mjs +468 -33
  27. package/dist/federation/mod.cjs +1 -1
  28. package/dist/federation/mod.d.cts +3 -3
  29. package/dist/federation/mod.d.ts +3 -3
  30. package/dist/federation/mod.js +1 -1
  31. package/dist/federation/mq.test.mjs +1 -1
  32. package/dist/federation/outgoing-proof.test.mjs +9 -6
  33. package/dist/federation/portable-actor.test.mjs +3 -3
  34. package/dist/federation/portable-chain.test.mjs +3 -3
  35. package/dist/federation/portable-collection.test.mjs +4 -4
  36. package/dist/federation/portable-delivery.test.mjs +2 -2
  37. package/dist/federation/portable-gateway-keys.test.mjs +11 -5
  38. package/dist/federation/portable-inbox.test.mjs +4 -4
  39. package/dist/federation/portable-parse-uri.test.mjs +1 -1
  40. package/dist/federation/portable-route-activity.test.mjs +2 -2
  41. package/dist/federation/portable.test.mjs +3 -3
  42. package/dist/federation/send.test.mjs +502 -93
  43. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  44. package/dist/federation/tasks/tasks.test.mjs +2 -2
  45. package/dist/federation/temporal.test.mjs +1 -1
  46. package/dist/federation/webfinger.test.mjs +1 -1
  47. package/dist/{federation-D8YexkP1.cjs → federation-CFaTsSMN.cjs} +246 -108
  48. package/dist/{http-CAl7Num5.cjs → http-2SwIR4b-.cjs} +179 -110
  49. package/dist/{http-BBr-VLil.js → http-CrYxBKqG.js} +178 -109
  50. package/dist/{http-BZkyQIkb.mjs → http-CxKd10Lq.mjs} +204 -106
  51. package/dist/{inbox-wDuMKaFW.mjs → inbox-CM0UktG8.mjs} +2 -2
  52. package/dist/{inbox-view-NE9wXdLo.mjs → inbox-view-BJ5DBPFo.mjs} +1 -1
  53. package/dist/{key-nYGY4QB9.d.cts → key-DbLNT-vA.d.ts} +1 -2
  54. package/dist/{key-DhsBxxZN.d.ts → key-DlHT4R6k.d.cts} +1 -2
  55. package/dist/{kv-cache-CTQSfkmp.mjs → kv-cache-CIdGATck.mjs} +1 -1
  56. package/dist/{kv-cache-CjgCOz3i.cjs → kv-cache-Cd8xKv-x.cjs} +72 -27
  57. package/dist/{kv-cache-U7uz5nx4.js → kv-cache-DbgFe35y.js} +73 -28
  58. package/dist/{ld-Cel1RRZ5.d.cts → ld-CWVpo_NM.d.cts} +1 -1
  59. package/dist/{ld-CQFuiah9.mjs → ld-DUeBHFWH.mjs} +2 -2
  60. package/dist/{ld-CcuZ4NZa.d.ts → ld-Inagww4R.d.ts} +1 -1
  61. package/dist/{metrics-B-QxRSSR.mjs → metrics-B7TvoAP7.mjs} +1 -1
  62. package/dist/{middleware-BdlNa8BD.mjs → middleware-BE4JXx-U.mjs} +1 -1
  63. package/dist/{middleware-CuVa0UuS.mjs → middleware-BEaUojg7.mjs} +89 -49
  64. package/dist/{middleware-P-AZEQMn.js → middleware-CId6efsJ.js} +247 -109
  65. package/dist/{mod-DvWOv2Ho.d.cts → mod-6TQ4UQZb.d.cts} +1 -1
  66. package/dist/{mod-BHQE-7WQ.d.ts → mod-B4kBw1-8.d.ts} +1 -1
  67. package/dist/{mod-DkhfZC1u.d.ts → mod-B7j30IQf.d.ts} +2 -9
  68. package/dist/{mod-B2783_3v.d.cts → mod-C1nT74IG.d.cts} +1 -1
  69. package/dist/{mod-DjZfJj9R.d.ts → mod-CIeBgsOC.d.ts} +1 -1
  70. package/dist/{mod-B5-wdzmJ.d.cts → mod-YvA4Rk8J.d.cts} +2 -9
  71. package/dist/mod.cjs +5 -5
  72. package/dist/mod.d.cts +7 -7
  73. package/dist/mod.d.ts +7 -7
  74. package/dist/mod.js +5 -5
  75. package/dist/nodeinfo/client.test.mjs +337 -19
  76. package/dist/nodeinfo/handler.test.mjs +1 -1
  77. package/dist/nodeinfo/mod.cjs +1 -1
  78. package/dist/nodeinfo/mod.d.cts +1 -1
  79. package/dist/nodeinfo/mod.d.ts +1 -1
  80. package/dist/nodeinfo/mod.js +1 -1
  81. package/dist/otel/exporter.test.mjs +257 -1
  82. package/dist/otel/mod.cjs +36 -30
  83. package/dist/otel/mod.d.cts +13 -0
  84. package/dist/otel/mod.d.ts +13 -0
  85. package/dist/otel/mod.js +36 -30
  86. package/dist/{owner-ccKkQOAf.mjs → owner-CwijV0c5.mjs} +3 -3
  87. package/dist/{portable-collection-DUlQ3s2M.js → portable-collection-2jn_4V7Y.js} +1 -1
  88. package/dist/{portable-collection-CndnpXfo.mjs → portable-collection-B023xqhZ.mjs} +2 -2
  89. package/dist/{portable-collection-TC-kvkVI.cjs → portable-collection-BeS88JJp.cjs} +1 -1
  90. package/dist/{portable-key-D5tFOoV-.mjs → portable-key-BpBucRfb.mjs} +1 -1
  91. package/dist/{proof-DPoF06nz.mjs → proof-DQh2z9fx.mjs} +3 -3
  92. package/dist/{send-CF44O1Df.mjs → send-DN5HNBv-.mjs} +174 -76
  93. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  94. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  95. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  96. package/dist/sig/compound-proof.test.mjs +2 -2
  97. package/dist/sig/http.test.mjs +553 -2
  98. package/dist/sig/key.test.mjs +1 -1
  99. package/dist/sig/ld.test.mjs +1 -1
  100. package/dist/sig/mitra-receive-interop.test.mjs +4 -4
  101. package/dist/sig/mitra-send-interop.test.mjs +3 -3
  102. package/dist/sig/mod.cjs +2 -2
  103. package/dist/sig/mod.d.cts +3 -3
  104. package/dist/sig/mod.d.ts +3 -3
  105. package/dist/sig/mod.js +2 -2
  106. package/dist/sig/owner.test.mjs +1 -1
  107. package/dist/sig/portable-collection.test.mjs +1 -1
  108. package/dist/sig/portable-interop.test.mjs +3 -3
  109. package/dist/sig/portable-key.test.mjs +5 -5
  110. package/dist/sig/proof.test.mjs +4 -4
  111. package/dist/sig/tootik-request-interop.test.mjs +4 -4
  112. package/dist/sig/tootik-send-interop.test.mjs +3 -3
  113. package/dist/sig/verification.test.mjs +3 -3
  114. package/dist/{temporal-XlZ4Wb94.mjs → temporal-yl7Z7A6y.mjs} +1 -1
  115. package/dist/testing/kv.test.mjs +1 -1
  116. package/dist/testing/mod.d.mts +26 -0
  117. package/dist/{types-_S2_MeLF.js → types-DUjZb4i6.js} +112 -63
  118. package/dist/{types-poIao40f.cjs → types-hKCCjii0.cjs} +111 -62
  119. package/dist/utils/docloader.test.mjs +344 -36
  120. package/dist/utils/kv-cache.test.mjs +1 -1
  121. package/dist/utils/mod.cjs +1 -1
  122. package/dist/utils/mod.d.cts +1 -1
  123. package/dist/utils/mod.d.ts +1 -1
  124. package/dist/utils/mod.js +1 -1
  125. package/package.json +8 -8
  126. package/dist/docloader-CpsDyqVN.mjs +0 -91
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { F as hasSignatureLike, H as verifySignature, J as generateCryptoKeyPair, K as fetchKey, M as detachSignature, St as validateAcceptSignature, T as verifyProof, V as verifyJsonLd, W as exportJwk, Y as importJwk, _ as signObject, a as signRequest, bt as fulfillAcceptSignature, c as verifyRequestDetailed, h as hasProofLike, j as createSignature, k as attachSignature, p as createProof, q as fetchKeyDetailed, s as verifyRequest, x as verifyPortableObjectProof, xt as parseAcceptSignature, y as verifyObject, yt as formatAcceptSignature, z as signJsonLd } from "../http-BBr-VLil.js";
4
- import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "../portable-collection-DUlQ3s2M.js";
3
+ import { F as hasSignatureLike, H as verifySignature, J as generateCryptoKeyPair, K as fetchKey, M as detachSignature, St as validateAcceptSignature, T as verifyProof, V as verifyJsonLd, W as exportJwk, Y as importJwk, _ as signObject, a as signRequest, bt as fulfillAcceptSignature, c as verifyRequestDetailed, h as hasProofLike, j as createSignature, k as attachSignature, p as createProof, q as fetchKeyDetailed, s as verifyRequest, x as verifyPortableObjectProof, xt as parseAcceptSignature, y as verifyObject, yt as formatAcceptSignature, z as signJsonLd } from "../http-CrYxBKqG.js";
4
+ import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "../portable-collection-2jn_4V7Y.js";
5
5
  export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyPortableObject, verifyPortableObjectProof, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
6
6
  import "../std__assert-DvMDRPes.mjs";
7
7
  import { t as assert } from "../assert-D1Eafmd_.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-ccKkQOAf.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CwijV0c5.mjs";
10
10
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
11
11
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/sig/owner.test.ts
@@ -2,7 +2,7 @@ import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
5
- import { t as verifyPortableObject } from "../portable-collection-CndnpXfo.mjs";
5
+ import { t as verifyPortableObject } from "../portable-collection-B023xqhZ.mjs";
6
6
  import { Collection, CollectionPage, Note, OrderedCollection, Person, traverseCollection } from "@fedify/vocab";
7
7
  import { FetchError, encodeMultibase, exportDidKey, preloadedContexts } from "@fedify/vocab-runtime";
8
8
  import { test } from "@fedify/fixture";
@@ -4,9 +4,9 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
5
5
  import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assert } from "../assert-D1Eafmd_.mjs";
7
- import { d as verifyPortableObjectProof, h as verifyProof } from "../proof-DPoF06nz.mjs";
8
- import { n as getKeyOwner } from "../owner-ccKkQOAf.mjs";
9
- import { t as verifyPortableObject } from "../portable-collection-CndnpXfo.mjs";
7
+ import { d as verifyPortableObjectProof, h as verifyProof } from "../proof-DQh2z9fx.mjs";
8
+ import { n as getKeyOwner } from "../owner-CwijV0c5.mjs";
9
+ import { t as verifyPortableObject } from "../portable-collection-B023xqhZ.mjs";
10
10
  import { Application, DataIntegrityProof, lookupObject } from "@fedify/vocab";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region test-vectors/fep-ef61/tootik-v0.25.4/actor.json
@@ -2,12 +2,12 @@ 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 { C as fetchKey, _ as verifyJsonLd, m as signJsonLd, w as fetchKeyDetailed } from "../ld-CQFuiah9.mjs";
6
- import { h as verifyProof, r as createProof } from "../proof-DPoF06nz.mjs";
7
- import { n as resolvePortableActorKey } from "../portable-key-D5tFOoV-.mjs";
8
- import { f as verifyRequest, l as signRequest, p as verifyRequestDetailed } from "../http-BZkyQIkb.mjs";
5
+ import { C as fetchKey, _ as verifyJsonLd, m as signJsonLd, w as fetchKeyDetailed } from "../ld-DUeBHFWH.mjs";
6
+ import { h as verifyProof, r as createProof } from "../proof-DQh2z9fx.mjs";
7
+ import { n as resolvePortableActorKey } from "../portable-key-BpBucRfb.mjs";
8
+ import { m as verifyRequestDetailed, p as verifyRequest, u as signRequest } from "../http-CxKd10Lq.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
10
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-ccKkQOAf.mjs";
10
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CwijV0c5.mjs";
11
11
  import { t as KvKeyCache } from "../keycache-N2opu4-3.mjs";
12
12
  import { Create, CryptographicKey, Multikey, Note, Person } from "@fedify/vocab";
13
13
  import { FetchError, encodeMultibase, exportDidKey, exportSpki, parseIri, preloadedContexts } from "@fedify/vocab-runtime";
@@ -11,10 +11,10 @@ import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
11
11
  import { t as assert } from "../assert-D1Eafmd_.mjs";
12
12
  import { a as verificationObservation } from "../verification-Dpfcw8ml.mjs";
13
13
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
14
- import { a as hasProofLike, c as verifyMapLocalProof, d as verifyPortableObjectProof, h as verifyProof, l as verifyObject, r as createProof, s as signObject, u as verifyObjectDetailed } from "../proof-DPoF06nz.mjs";
15
- import { f as verifyRequest } from "../http-BZkyQIkb.mjs";
14
+ import { a as hasProofLike, c as verifyMapLocalProof, d as verifyPortableObjectProof, h as verifyProof, l as verifyObject, r as createProof, s as signObject, u as verifyObjectDetailed } from "../proof-DQh2z9fx.mjs";
15
+ import { p as verifyRequest } from "../http-CxKd10Lq.mjs";
16
16
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
17
- import { t as getAuthenticatedDocumentLoader } from "../docloader-CpsDyqVN.mjs";
17
+ import { n as getAuthenticatedDocumentLoader } from "../docloader-DbBbDaY-.mjs";
18
18
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place, Translation } from "@fedify/vocab";
19
19
  import { FetchError, decodeMultibase, encodeMultibase, exportDidKey, exportMultibaseKey, formatIri, importMultibaseKey, parseIri } from "@fedify/vocab-runtime";
20
20
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -2530,7 +2530,7 @@ test("getAuthenticatedDocumentLoader() signs portable object requests to gateway
2530
2530
  documentLoader: getAuthenticatedDocumentLoader({
2531
2531
  keyId: new URL("https://example.com/key2"),
2532
2532
  privateKey: rsaPrivateKey2
2533
- }),
2533
+ }, { allowPrivateAddress: true }),
2534
2534
  contextLoader: mockDocumentLoader,
2535
2535
  gateways: ["https://example.com"],
2536
2536
  verifyPortableObject: verifyPortableObjectProof
@@ -5,10 +5,10 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import "../std__assert-DvMDRPes.mjs";
7
7
  import { t as assert } from "../assert-D1Eafmd_.mjs";
8
- import { d as verifyPortableObjectProof } from "../proof-DPoF06nz.mjs";
9
- import { p as verifyRequestDetailed } from "../http-BZkyQIkb.mjs";
10
- import { o as createFederation } from "../middleware-CuVa0UuS.mjs";
11
- import { t as doesActorOwnKey } from "../owner-ccKkQOAf.mjs";
8
+ import { d as verifyPortableObjectProof } from "../proof-DQh2z9fx.mjs";
9
+ import { m as verifyRequestDetailed } from "../http-CxKd10Lq.mjs";
10
+ import { o as createFederation } from "../middleware-BEaUojg7.mjs";
11
+ import { t as doesActorOwnKey } from "../owner-CwijV0c5.mjs";
12
12
  import { Follow, Person } from "@fedify/vocab";
13
13
  import { mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { encodeHex } from "byte-encodings/hex";
@@ -4,9 +4,9 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
5
5
  import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assert } from "../assert-D1Eafmd_.mjs";
7
- import { d as verifyPortableObjectProof } from "../proof-DPoF06nz.mjs";
8
- import { p as verifyRequestDetailed } from "../http-BZkyQIkb.mjs";
9
- import { t as doesActorOwnKey } from "../owner-ccKkQOAf.mjs";
7
+ import { d as verifyPortableObjectProof } from "../proof-DQh2z9fx.mjs";
8
+ import { m as verifyRequestDetailed } from "../http-CxKd10Lq.mjs";
9
+ import { t as doesActorOwnKey } from "../owner-CwijV0c5.mjs";
10
10
  import { Create } from "@fedify/vocab";
11
11
  import { decodeMultibase, importDidKey } from "@fedify/vocab-runtime";
12
12
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -2,9 +2,9 @@ import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { a as verificationObservation } from "../verification-Dpfcw8ml.mjs";
5
- import { _ as verifyJsonLd, m as signJsonLd } from "../ld-CQFuiah9.mjs";
6
- import { l as verifyObject, s as signObject } from "../proof-DPoF06nz.mjs";
7
- import { l as signRequest, p as verifyRequestDetailed } from "../http-BZkyQIkb.mjs";
5
+ import { _ as verifyJsonLd, m as signJsonLd } from "../ld-DUeBHFWH.mjs";
6
+ import { l as verifyObject, s as signObject } from "../proof-DQh2z9fx.mjs";
7
+ import { m as verifyRequestDetailed, u as signRequest } from "../http-CxKd10Lq.mjs";
8
8
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
9
9
  import { Activity, Create, CryptographicKey, Multikey } from "@fedify/vocab";
10
10
  import { FetchError } from "@fedify/vocab-runtime";
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { c as getNormalizationContextLoader } from "./ld-CQFuiah9.mjs";
4
+ import { c as getNormalizationContextLoader } from "./ld-DUeBHFWH.mjs";
5
5
  import jsonld from "@fedify/vocab-runtime/jsonld";
6
6
  //#region src/federation/temporal.ts
7
7
  function isPlainObject(value) {
@@ -6,7 +6,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
7
7
  import { n as baseOptions, o as stringSchema, t as MockQueue } from "../tasks-IG3pHfvZ.mjs";
8
8
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
9
- import { o as createFederation } from "../middleware-CuVa0UuS.mjs";
9
+ import { o as createFederation } from "../middleware-BEaUojg7.mjs";
10
10
  //#region src/testing/kv.test.ts
11
11
  test("ManualClockKvStore keeps an entry at its exact expiration instant", async () => {
12
12
  const kv = new ManualClockKvStore();
@@ -4695,6 +4695,11 @@ interface RequestContext<TContextData> extends Context<TContextData> {
4695
4695
  * Gets the public key of the sender, if any exists and it is verified.
4696
4696
  * Otherwise, `null` is returned.
4697
4697
  *
4698
+ * Successful results are reused for this request regardless of the options.
4699
+ * Pending checks and `null` results are reused for the same effective
4700
+ * document and context loaders, including failed lookups. Rejected checks
4701
+ * can be retried. Shared work uses the first caller's tracer provider.
4702
+ *
4698
4703
  * This can be used for implementing [authorized fetch] (also known as
4699
4704
  * secure mode) in ActivityPub.
4700
4705
  *
@@ -4708,6 +4713,11 @@ interface RequestContext<TContextData> extends Context<TContextData> {
4708
4713
  * Gets the public key of the sender, if any exists and it is verified.
4709
4714
  * Otherwise, `null` is returned.
4710
4715
  *
4716
+ * Successful results are reused for this request regardless of the options.
4717
+ * Pending checks and `null` results are reused for the same effective
4718
+ * document and context loaders, including failed lookups. Rejected checks
4719
+ * can be retried. Shared work uses the first caller's tracer provider.
4720
+ *
4711
4721
  * This can be used for implementing [authorized fetch] (also known as
4712
4722
  * secure mode) in ActivityPub.
4713
4723
  *
@@ -4727,6 +4737,14 @@ interface RequestContext<TContextData> extends Context<TContextData> {
4727
4737
  * Gets the owner of the signed key, if any exists and it is verified.
4728
4738
  * Otherwise, `null` is returned.
4729
4739
  *
4740
+ * Verified keys and owners are reused for this request regardless of the
4741
+ * options. Pending checks are shared for the same effective document and
4742
+ * context loaders. A `null` result from an owner lookup after key
4743
+ * verification is retained for those loaders. A `null` result caused by
4744
+ * an unverified key is not retained, allowing an owner lookup after another
4745
+ * loader verifies the key. Rejected checks can be retried. Shared work
4746
+ * uses the first caller's tracer provider.
4747
+ *
4730
4748
  * This can be used for implementing [authorized fetch] (also known as
4731
4749
  * secure mode) in ActivityPub.
4732
4750
  *
@@ -4741,6 +4759,14 @@ interface RequestContext<TContextData> extends Context<TContextData> {
4741
4759
  * Gets the owner of the signed key, if any exists and it is verified.
4742
4760
  * Otherwise, `null` is returned.
4743
4761
  *
4762
+ * Verified keys and owners are reused for this request regardless of the
4763
+ * options. Pending checks are shared for the same effective document and
4764
+ * context loaders. A `null` result from an owner lookup after key
4765
+ * verification is retained for those loaders. A `null` result caused by
4766
+ * an unverified key is not retained, allowing an owner lookup after another
4767
+ * loader verifies the key. Rejected checks can be retried. Shared work
4768
+ * uses the first caller's tracer provider.
4769
+ *
4744
4770
  * This can be used for implementing [authorized fetch] (also known as
4745
4771
  * secure mode) in ActivityPub.
4746
4772
  *
@@ -1,7 +1,8 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { getLogger } from "@logtape/logtape";
4
- import { FetchError, UrlError, getUserAgent, validatePublicUrl } from "@fedify/vocab-runtime";
4
+ import { FetchError, UrlError, getUserAgent } from "@fedify/vocab-runtime";
5
+ import { openPublicFetch } from "@fedify/vocab-runtime/internal";
5
6
  //#region src/utils/body.ts
6
7
  /** Decoded JSON body limit: 16 MiB. @internal */
7
8
  const MAX_BODY_SIZE = 16 * 1024 * 1024;
@@ -84,23 +85,34 @@ const logger = getLogger([
84
85
  ]);
85
86
  const DEFAULT_MAX_REDIRECTION = 5;
86
87
  /**
87
- * Fetches a URL while guarding against SSRF. Before every request—including
88
- * each redirect hop—the destination is validated with
89
- * {@link validatePublicUrl}, so that loopback, link-local, and private
90
- * addresses, as well as non-HTTP(S) schemes such as `data:`, are rejected.
91
- * Redirects are followed manually with a cap, so that a public URL cannot
92
- * bounce the request to an internal address.
88
+ * Fetches a URL while guarding against SSRF. Every request—including each
89
+ * redirect hop—is made in its own session opened with `openPublicFetch()`,
90
+ * which rejects loopback, link-local, and private addresses, as well as
91
+ * non-HTTP(S) schemes such as `data:`, and connects only to the validated
92
+ * addresses where the runtime supports it. Redirects are followed manually
93
+ * with a cap, so that a public URL cannot bounce the request to an internal
94
+ * address.
95
+ *
96
+ * The final response is passed to `consume`, which must consume or cancel its
97
+ * body; the session is closed after `consume` settles. The cancellation of
98
+ * redirect response bodies is started before their sessions are closed.
93
99
  * @param url The URL to fetch.
94
100
  * @param headers The request headers.
95
- * @returns The final response, or `null` if the URL is disallowed, its
96
- * hostname cannot be resolved, or there are too many redirects.
101
+ * @param consume The function to consume the final response with.
102
+ * @param deps The dependencies.
103
+ * @returns The value returned by `consume`, or `null` if the URL is
104
+ * disallowed, its hostname cannot be resolved, or there are too many
105
+ * redirects.
106
+ * @internal
97
107
  */
98
- async function fetchPublicUrl(url, headers) {
108
+ async function fetchPublicUrl(url, headers, consume, deps = {}) {
109
+ const openHop = deps.openHop ?? ((hopUrl) => openPublicFetch(hopUrl));
99
110
  let current = url instanceof URL ? url : new URL(url);
100
111
  let redirected = 0;
101
112
  while (true) {
113
+ let session;
102
114
  try {
103
- await validatePublicUrl(current.href);
115
+ session = await openHop(current.href);
104
116
  } catch (e) {
105
117
  if (e instanceof UrlError) {
106
118
  if (e.reason === "dns") logger.error("DNS lookup failed for {url}: {error}", {
@@ -115,52 +127,89 @@ async function fetchPublicUrl(url, headers) {
115
127
  }
116
128
  throw e;
117
129
  }
118
- const response = await fetch(current, {
119
- headers,
120
- redirect: "manual"
121
- });
122
- if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
123
- redirected++;
124
- if (redirected >= DEFAULT_MAX_REDIRECTION) {
125
- logger.error("Too many redirections ({redirections}) while fetching {url}.", {
126
- redirections: redirected,
127
- url: current.href
128
- });
129
- return null;
130
- }
131
- const next = new URL(response.headers.get("Location"), response.url == null || response.url === "" ? current : response.url);
132
- if (next.protocol !== current.protocol) {
133
- logger.error("Refused a redirect to a different protocol ({protocol} to {redirectedProtocol}) while fetching NodeInfo.", {
134
- protocol: current.protocol,
135
- redirectedProtocol: next.protocol
136
- });
137
- return null;
138
- }
139
- current = next;
140
- continue;
130
+ let location;
131
+ try {
132
+ const response = await session.fetch(current, {
133
+ headers,
134
+ redirect: "manual"
135
+ });
136
+ if (response.status < 300 || response.status >= 400 || !response.headers.has("Location")) return await consume(response);
137
+ location = response.headers.get("Location");
138
+ cancelBody(response, current);
139
+ } finally {
140
+ await session.close();
141
+ }
142
+ redirected++;
143
+ if (redirected >= DEFAULT_MAX_REDIRECTION) {
144
+ logger.error("Too many redirections ({redirections}) while fetching {url}.", {
145
+ redirections: redirected,
146
+ url: current.href
147
+ });
148
+ return null;
149
+ }
150
+ const next = new URL(location, current);
151
+ if (next.protocol !== current.protocol) {
152
+ logger.error("Refused a redirect to a different protocol ({protocol} to {redirectedProtocol}) while fetching NodeInfo.", {
153
+ protocol: current.protocol,
154
+ redirectedProtocol: next.protocol
155
+ });
156
+ return null;
141
157
  }
142
- return response;
158
+ current = next;
143
159
  }
144
160
  }
161
+ /**
162
+ * Starts cancelling a response body that is not read, without waiting for it
163
+ * to settle. The cancellation of a branch of a tee (e.g., a body cloned by
164
+ * a fetch mock) settles only after the other branch is cancelled too, per
165
+ * the Streams standard, so awaiting it could block forever. A failure is
166
+ * only logged.
167
+ */
168
+ function cancelBody(response, url) {
169
+ response.body?.cancel().catch((error) => {
170
+ logger.debug("Failed to cancel the response body from {url}: {error}", {
171
+ url: url.toString(),
172
+ error
173
+ });
174
+ });
175
+ }
145
176
  async function getNodeInfo(url, options = {}) {
177
+ return await getNodeInfoInternal(url, options);
178
+ }
179
+ /**
180
+ * The implementation of {@link getNodeInfo}, which is not exported from any
181
+ * entry point.
182
+ * @param url The base URL of the server, or the URL of the NodeInfo document
183
+ * if `options.direct` is turned on.
184
+ * @param options Options for fetching the NodeInfo document.
185
+ * @param deps The dependencies.
186
+ * @returns The NodeInfo document if it could be fetched successfully.
187
+ * Otherwise, `undefined` is returned.
188
+ * @internal
189
+ */
190
+ async function getNodeInfoInternal(url, options = {}, deps = {}) {
146
191
  try {
192
+ const headers = {
193
+ Accept: "application/json",
194
+ "User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
195
+ };
147
196
  let nodeInfoUrl = url;
148
197
  if (!options.direct) {
149
198
  const wellKnownUrl = new URL("/.well-known/nodeinfo", url);
150
- const wellKnownResponse = await fetchPublicUrl(wellKnownUrl, {
151
- Accept: "application/json",
152
- "User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
153
- });
154
- if (wellKnownResponse == null) return void 0;
155
- if (!wellKnownResponse.ok) {
156
- logger.error("Failed to fetch {url}: {status} {statusText}", {
157
- url: wellKnownUrl.href,
158
- status: wellKnownResponse.status,
159
- statusText: wellKnownResponse.statusText
160
- });
161
- return;
162
- }
163
- const wellKnownRd = JSON.parse(await readBoundedText(wellKnownResponse, MAX_BODY_SIZE, wellKnownUrl));
199
+ const wellKnown = await fetchPublicUrl(wellKnownUrl, headers, async (response) => {
200
+ if (!response.ok) {
201
+ logger.error("Failed to fetch {url}: {status} {statusText}", {
202
+ url: wellKnownUrl.href,
203
+ status: response.status,
204
+ statusText: response.statusText
205
+ });
206
+ cancelBody(response, wellKnownUrl);
207
+ return;
208
+ }
209
+ return { rd: JSON.parse(await readBoundedText(response, MAX_BODY_SIZE, wellKnownUrl)) };
210
+ }, deps);
211
+ if (wellKnown == null) return void 0;
212
+ const wellKnownRd = wellKnown.rd;
164
213
  const link = wellKnownRd?.links?.find((link) => link != null && "rel" in link && (link.rel === "http://nodeinfo.diaspora.software/ns/schema/2.0" || link.rel === "http://nodeinfo.diaspora.software/ns/schema/2.1") && "href" in link && link.href != null);
165
214
  if (link == null || link.href == null) {
166
215
  logger.error("Failed to find a NodeInfo document link from {url}: {resourceDescriptor}", {
@@ -171,20 +220,20 @@ async function getNodeInfo(url, options = {}) {
171
220
  }
172
221
  nodeInfoUrl = link.href;
173
222
  }
174
- const response = await fetchPublicUrl(nodeInfoUrl, {
175
- Accept: "application/json",
176
- "User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
177
- });
178
- if (response == null) return void 0;
179
- if (!response.ok) {
180
- logger.error("Failed to fetch NodeInfo document from {url}: {status} {statusText}", {
181
- url: nodeInfoUrl.toString(),
182
- status: response.status,
183
- statusText: response.statusText
184
- });
185
- return;
186
- }
187
- const data = JSON.parse(await readBoundedText(response, MAX_BODY_SIZE, nodeInfoUrl));
223
+ const document = await fetchPublicUrl(nodeInfoUrl, headers, async (response) => {
224
+ if (!response.ok) {
225
+ logger.error("Failed to fetch NodeInfo document from {url}: {status} {statusText}", {
226
+ url: nodeInfoUrl.toString(),
227
+ status: response.status,
228
+ statusText: response.statusText
229
+ });
230
+ cancelBody(response, nodeInfoUrl);
231
+ return;
232
+ }
233
+ return { data: JSON.parse(await readBoundedText(response, MAX_BODY_SIZE, nodeInfoUrl)) };
234
+ }, deps);
235
+ if (document == null) return void 0;
236
+ const { data } = document;
188
237
  if (options.parse === "none") return data;
189
238
  return parseNodeInfo(data, { tryBestEffort: options.parse === "best-effort" }) ?? void 0;
190
239
  } catch (error) {