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

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 (102) hide show
  1. package/dist/{builder-CxHALSwA.mjs → builder-D89oOfHC.mjs} +2 -2
  2. package/dist/{client-DpnpgjyX.mjs → client-CEnNz8O7.mjs} +7 -3
  3. package/dist/compat/mod.d.cts +1 -1
  4. package/dist/compat/mod.d.ts +1 -1
  5. package/dist/compat/transformers.test.mjs +1 -1
  6. package/dist/{compound-proof-nhrXTRQO.mjs → compound-proof-B02Os8h2.mjs} +2 -2
  7. package/dist/{context-OrnjnuMq.mjs → context-B2rlkkyJ.mjs} +1 -1
  8. package/dist/{context-BMggDR-l.d.cts → context-DpsaHkk1.d.cts} +119 -2
  9. package/dist/{context-exYu7gDU.d.ts → context-JDNkUtnu.d.ts} +119 -2
  10. package/dist/{deno-YLLbRq06.mjs → deno-CE_s0yQb.mjs} +1 -1
  11. package/dist/{dist-BQvArojP.mjs → dist-DJQM4u7i.mjs} +2 -1
  12. package/dist/docloader-C5p26tpa.mjs +79 -0
  13. package/dist/federation/builder.test.mjs +1 -1
  14. package/dist/federation/compound-fanout.test.mjs +3 -3
  15. package/dist/federation/handler-compound-proof.test.mjs +4 -4
  16. package/dist/federation/handler.test.mjs +6 -6
  17. package/dist/federation/hashlink-media.test.mjs +2 -2
  18. package/dist/federation/idempotency.test.mjs +2 -2
  19. package/dist/federation/metrics.test.mjs +1 -1
  20. package/dist/federation/middleware.test.mjs +187 -10
  21. package/dist/federation/mod.cjs +1 -1
  22. package/dist/federation/mod.d.cts +3 -3
  23. package/dist/federation/mod.d.ts +3 -3
  24. package/dist/federation/mod.js +1 -1
  25. package/dist/federation/mq.test.mjs +98 -69
  26. package/dist/federation/outgoing-proof.test.mjs +5 -5
  27. package/dist/federation/portable-actor.test.mjs +3 -3
  28. package/dist/federation/portable-chain.test.mjs +3 -3
  29. package/dist/federation/portable-collection.test.mjs +4 -4
  30. package/dist/federation/portable-gateway-keys.test.mjs +4 -4
  31. package/dist/federation/portable-inbox.test.mjs +4 -4
  32. package/dist/federation/portable-parse-uri.test.d.mts +2 -0
  33. package/dist/federation/portable-parse-uri.test.mjs +348 -0
  34. package/dist/federation/portable.test.mjs +3 -3
  35. package/dist/federation/send.test.mjs +84 -3
  36. package/dist/federation/tasks/enqueue.test.mjs +3 -3
  37. package/dist/federation/tasks/tasks.test.mjs +4 -4
  38. package/dist/federation/temporal.test.mjs +1 -1
  39. package/dist/federation/webfinger.test.mjs +2 -2
  40. package/dist/{federation-D9TufmIO.cjs → federation-dBOqmJcA.cjs} +74 -10
  41. package/dist/{http-CXnNbRe_.mjs → http-DV_yW4dv.mjs} +9 -5
  42. package/dist/{http-Dk4O3WM0.js → http-nTZuTacw.js} +7 -3
  43. package/dist/{http-eqYXHRkz.cjs → http-wdsia0-O.cjs} +7 -3
  44. package/dist/{key-BZ-Z4uez.mjs → key-C6jnekFI.mjs} +2 -2
  45. package/dist/{kv-cache-DzClEalR.cjs → kv-cache-BHNtQi9e.cjs} +34 -8
  46. package/dist/{kv-cache-DZr8HTel.mjs → kv-cache-Bxm0a0Ww.mjs} +1 -1
  47. package/dist/{kv-cache-3uKc0G76.js → kv-cache-DhIl9YlV.js} +35 -9
  48. package/dist/{ld-Djxsq6JR.mjs → ld-ya2C1Xip.mjs} +4 -4
  49. package/dist/{metrics-CBHhbHgG.mjs → metrics-ByOQOHHS.mjs} +1 -1
  50. package/dist/{middleware-DDa8pCUa.mjs → middleware-Bdwd_Gg8.mjs} +70 -20
  51. package/dist/{middleware-BahNnLfD.mjs → middleware-DoVWq8mE.mjs} +1 -1
  52. package/dist/{middleware-BDUR99k3.js → middleware-WiaN4RS3.js} +74 -10
  53. package/dist/{mod-Decmur1U.d.cts → mod-DSKkTwH2.d.cts} +1 -1
  54. package/dist/{mod-CZetqT5h.d.ts → mod-DaiBrWDW.d.ts} +2 -0
  55. package/dist/{mod-D4g9ffEn.d.cts → mod-Mt4aO3DX.d.cts} +2 -0
  56. package/dist/{mod-CnGtADvO.d.ts → mod-_4K05HZF.d.ts} +1 -1
  57. package/dist/mod.cjs +5 -5
  58. package/dist/mod.d.cts +5 -5
  59. package/dist/mod.d.ts +5 -5
  60. package/dist/mod.js +5 -5
  61. package/dist/nodeinfo/client.test.mjs +49 -1
  62. package/dist/nodeinfo/handler.test.mjs +2 -2
  63. package/dist/nodeinfo/mod.cjs +1 -1
  64. package/dist/nodeinfo/mod.js +1 -1
  65. package/dist/{owner-OdWSE8am.mjs → owner-C6Nv5yyw.mjs} +3 -3
  66. package/dist/{portable-collection-BCy06GiS.js → portable-collection-B-mU1F1-.js} +1 -1
  67. package/dist/{portable-collection-wBWbuHOH.cjs → portable-collection-C65SwL2l.cjs} +1 -1
  68. package/dist/{portable-collection-DAV7Ho3m.mjs → portable-collection-uWj3hfzv.mjs} +2 -2
  69. package/dist/{portable-key-BL6K88p2.mjs → portable-key-BXsVLSMa.mjs} +1 -1
  70. package/dist/{proof-vZ04IAjq.mjs → proof-BdO3BbLh.mjs} +4 -4
  71. package/dist/{send-ylV8KCLx.mjs → send-BwANxryy.mjs} +18 -4
  72. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  73. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  74. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  75. package/dist/sig/compound-proof.test.mjs +2 -2
  76. package/dist/sig/http.test.mjs +42 -2
  77. package/dist/sig/key.test.mjs +1 -1
  78. package/dist/sig/ld.test.mjs +5 -2
  79. package/dist/sig/mod.cjs +2 -2
  80. package/dist/sig/mod.js +2 -2
  81. package/dist/sig/owner.test.mjs +1 -1
  82. package/dist/sig/portable-collection.test.mjs +2 -2
  83. package/dist/sig/portable-key.test.mjs +6 -6
  84. package/dist/sig/proof.test.mjs +3 -3
  85. package/dist/{tasks-dbCShlCb.mjs → tasks-IG3pHfvZ.mjs} +1 -1
  86. package/dist/{temporal-BTD4f_mZ.mjs → temporal-CbPfRGZq.mjs} +1 -1
  87. package/dist/testing/context.test.mjs +1 -1
  88. package/dist/testing/kv.test.mjs +3 -3
  89. package/dist/testing/mod.d.mts +118 -1
  90. package/dist/testing/mod.mjs +4 -4
  91. package/dist/{testing-CKaJhcA0.mjs → testing-C1itIjqW.mjs} +3 -3
  92. package/dist/{types-C_cNlNVK.js → types-_S2_MeLF.js} +7 -3
  93. package/dist/{types-Be2zbyeG.cjs → types-poIao40f.cjs} +7 -3
  94. package/dist/utils/docloader.test.mjs +297 -2
  95. package/dist/utils/kv-cache.test.mjs +1 -1
  96. package/dist/utils/mod.cjs +1 -1
  97. package/dist/utils/mod.d.cts +1 -1
  98. package/dist/utils/mod.d.ts +1 -1
  99. package/dist/utils/mod.js +1 -1
  100. package/dist/vocab/cjs.test.mjs +1 -1
  101. package/package.json +7 -7
  102. package/dist/docloader-vc-pSu9-.mjs +0 -53
@@ -6,9 +6,9 @@ import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assert } from "../assert-D1Eafmd_.mjs";
7
7
  import { n as preloadedOnlyDocumentLoader } from "../public-audience--klBIOk1.mjs";
8
8
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
9
- import { a as signObject, d as verifyProof } from "../proof-vZ04IAjq.mjs";
9
+ import { a as signObject, d as verifyProof } from "../proof-BdO3BbLh.mjs";
10
10
  import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
11
- import { o as verifyCompoundProofDocuments } from "../compound-proof-nhrXTRQO.mjs";
11
+ import { o as verifyCompoundProofDocuments } from "../compound-proof-B02Os8h2.mjs";
12
12
  import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
13
13
  import { t as map_local_context_conflict_default } from "../map-local-context-conflict-DOYEEJ3u.mjs";
14
14
  import { Create, DataIntegrityProof, Note, Question } from "@fedify/vocab";
@@ -11,8 +11,8 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
11
11
  import "../std__assert-DvMDRPes.mjs";
12
12
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
13
13
  import { t as assert } from "../assert-D1Eafmd_.mjs";
14
- import { n as exportJwk } from "../key-BZ-Z4uez.mjs";
15
- import { a as listRequestSignatures, c as selectRequestSignature, d as verifyRequest, f as verifyRequestDetailed, i as formatRfc9421SignatureParameters, l as signRequest, n as doubleKnock, o as parseRfc9421Signature, r as formatRfc9421Signature, s as parseRfc9421SignatureInput, t as createRfc9421SignatureBase, u as timingSafeEqual } from "../http-CXnNbRe_.mjs";
14
+ import { n as exportJwk } from "../key-C6jnekFI.mjs";
15
+ import { a as listRequestSignatures, c as selectRequestSignature, d as verifyRequest, f as verifyRequestDetailed, i as formatRfc9421SignatureParameters, l as signRequest, n as doubleKnock, o as parseRfc9421Signature, r as formatRfc9421Signature, s as parseRfc9421SignatureInput, t as createRfc9421SignatureBase, u as timingSafeEqual } from "../http-DV_yW4dv.mjs";
16
16
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
17
17
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
18
18
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
@@ -655,6 +655,46 @@ test("verifyRequest() [rfc9421] successful GET verification", async () => {
655
655
  currentTime: Temporal.Instant.from(`${(/* @__PURE__ */ new Date(currentTimestamp * 1e3)).toISOString()}`)
656
656
  }), rsaPublicKey2, "Valid signature should verify to the correct public key");
657
657
  });
658
+ for (const failure of [
659
+ "missing key",
660
+ "invalid signature",
661
+ "digest mismatch",
662
+ "empty body",
663
+ "cached key"
664
+ ]) test(`verifyRequest() [rfc9421] multiple POST signatures: ${failure}`, async () => {
665
+ const body = failure === "empty body" ? "" : "Hello, world!";
666
+ const currentTime = Temporal.Instant.from("2024-03-05T08:09:44Z");
667
+ const signed = await signRequest(new Request("https://example.com/inbox", {
668
+ method: "POST",
669
+ body
670
+ }), rsaPrivateKey2, new URL("https://example.com/key2"), {
671
+ spec: "rfc9421",
672
+ currentTime
673
+ });
674
+ const input = signed.headers.get("Signature-Input");
675
+ const signature = signed.headers.get("Signature");
676
+ const firstInput = failure === "missing key" ? input.replace("https://example.com/key2", "https://example.com/missing-key") : input;
677
+ signed.headers.set("Signature-Input", `${firstInput}, ${input.replace(/^sig1=/, "sig2=")}`);
678
+ signed.headers.set("Signature", `sig1=:AAAAAA==:, ${signature.replace(/^sig1=/, "sig2=")}`);
679
+ const request = failure === "digest mismatch" ? new Request(signed, { body: "Tampered body" }) : signed;
680
+ const loaded = [];
681
+ assertEquals(await verifyRequest(request, {
682
+ keyCache: failure === "cached key" ? {
683
+ get: () => Promise.resolve(rsaPublicKey1),
684
+ set: async () => {}
685
+ } : void 0,
686
+ spec: "rfc9421",
687
+ currentTime,
688
+ contextLoader: mockDocumentLoader,
689
+ documentLoader: (url, options) => {
690
+ loaded.push(url);
691
+ return mockDocumentLoader(url, options);
692
+ }
693
+ }), failure === "digest mismatch" ? null : rsaPublicKey2);
694
+ assertEquals(loaded, failure === "digest mismatch" ? [] : failure === "missing key" ? ["https://example.com/missing-key", "https://example.com/key2"] : ["https://example.com/key2", "https://example.com/key2"]);
695
+ assertFalse(request.bodyUsed);
696
+ assertEquals(await request.text(), failure === "digest mismatch" ? "Tampered body" : body);
697
+ });
658
698
  test("verifyRequest() [rfc9421] manual POST verification", async () => {
659
699
  const currentTimestamp = 1709626184;
660
700
  const currentTime = Temporal.Instant.from("2024-03-05T08:09:44Z");
@@ -6,7 +6,7 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
6
6
  import "../std__assert-DvMDRPes.mjs";
7
7
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
8
8
  import { t as assert } from "../assert-D1Eafmd_.mjs";
9
- import { a as fetchKeyDetailed, c as validateCryptoKey, i as fetchKey, n as exportJwk, o as generateCryptoKeyPair, s as importJwk } from "../key-BZ-Z4uez.mjs";
9
+ import { a as fetchKeyDetailed, c as validateCryptoKey, i as fetchKey, n as exportJwk, o as generateCryptoKeyPair, s as importJwk } from "../key-C6jnekFI.mjs";
10
10
  import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
11
11
  import { CryptographicKey, Multikey } from "@fedify/vocab";
12
12
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -8,14 +8,17 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
9
9
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { o as generateCryptoKeyPair } from "../key-BZ-Z4uez.mjs";
12
- import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-Djxsq6JR.mjs";
11
+ import { o as generateCryptoKeyPair } from "../key-C6jnekFI.mjs";
12
+ import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-ya2C1Xip.mjs";
13
13
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
14
14
  import { CryptographicKey } from "@fedify/vocab";
15
15
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { encodeBase64 } from "byte-encodings/base64";
17
17
  //#region src/sig/ld.test.ts
18
18
  test("isInvalidUrlTypeError()", () => {
19
+ assert(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("Invalid URL string.")));
20
+ assertFalse(isInvalidUrlTypeError(/* @__PURE__ */ new Error("Invalid URL string.")));
21
+ assertFalse(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("Invalid URL string. Other error")));
19
22
  assert(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("Invalid URL: http://[")));
20
23
  assert(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("\"http://[\" cannot be parsed as a URL.")));
21
24
  const error = /* @__PURE__ */ new TypeError("Failed to parse URL");
package/dist/sig/mod.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_http = require("../http-eqYXHRkz.cjs");
4
- const require_portable_collection = require("../portable-collection-wBWbuHOH.cjs");
3
+ const require_http = require("../http-wdsia0-O.cjs");
4
+ const require_portable_collection = require("../portable-collection-C65SwL2l.cjs");
5
5
  exports.attachSignature = require_http.attachSignature;
6
6
  exports.createProof = require_http.createProof;
7
7
  exports.createSignature = require_http.createSignature;
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 { A as hasSignatureLike, B as fetchKey, D as detachSignature, E as createSignature, F as verifyJsonLd, H as generateCryptoKeyPair, I as verifySignature, N as signJsonLd, R as exportJwk, U as importJwk, V as fetchKeyDetailed, _ as verifyPortableObjectProof, a as signRequest, b as verifyProof, dt as fulfillAcceptSignature, f as createProof, ft as parseAcceptSignature, g as verifyObject, m as signObject, o as verifyRequest, p as hasProofLike, pt as validateAcceptSignature, s as verifyRequestDetailed, ut as formatAcceptSignature, w as attachSignature } from "../http-Dk4O3WM0.js";
4
- import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "../portable-collection-BCy06GiS.js";
3
+ import { A as hasSignatureLike, B as fetchKey, D as detachSignature, E as createSignature, F as verifyJsonLd, H as generateCryptoKeyPair, I as verifySignature, N as signJsonLd, R as exportJwk, U as importJwk, V as fetchKeyDetailed, _ as verifyPortableObjectProof, a as signRequest, b as verifyProof, dt as fulfillAcceptSignature, f as createProof, ft as parseAcceptSignature, g as verifyObject, m as signObject, o as verifyRequest, p as hasProofLike, pt as validateAcceptSignature, s as verifyRequestDetailed, ut as formatAcceptSignature, w as attachSignature } from "../http-nTZuTacw.js";
4
+ import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "../portable-collection-B-mU1F1-.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-OdWSE8am.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-C6Nv5yyw.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,12 +2,12 @@ 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-DAV7Ho3m.mjs";
5
+ import { t as verifyPortableObject } from "../portable-collection-uWj3hfzv.mjs";
6
6
  import { Collection, CollectionPage, Note, OrderedCollection, Person, traverseCollection } from "@fedify/vocab";
7
7
  import { test } from "@fedify/fixture";
8
8
  import { FetchError, encodeMultibase, exportDidKey, preloadedContexts } from "@fedify/vocab-runtime";
9
- import serialize from "json-canon";
10
9
  import { deepStrictEqual, ok, strictEqual } from "node:assert/strict";
10
+ import serialize from "json-canon";
11
11
  //#region src/sig/portable-collection.test.ts
12
12
  const AS = "https://www.w3.org/ns/activitystreams#";
13
13
  const context = [
@@ -2,18 +2,18 @@ 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 { i as fetchKey } from "../key-BZ-Z4uez.mjs";
6
- import { h as verifyJsonLd, p as signJsonLd } from "../ld-Djxsq6JR.mjs";
7
- import { d as verifyProof, r as createProof } from "../proof-vZ04IAjq.mjs";
8
- import { d as verifyRequest, f as verifyRequestDetailed, l as signRequest } from "../http-CXnNbRe_.mjs";
5
+ import { i as fetchKey } from "../key-C6jnekFI.mjs";
6
+ import { h as verifyJsonLd, p as signJsonLd } from "../ld-ya2C1Xip.mjs";
7
+ import { d as verifyProof, r as createProof } from "../proof-BdO3BbLh.mjs";
8
+ import { d as verifyRequest, f as verifyRequestDetailed, l as signRequest } from "../http-DV_yW4dv.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-OdWSE8am.mjs";
10
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-C6Nv5yyw.mjs";
11
11
  import { t as KvKeyCache } from "../keycache-BInaECGj.mjs";
12
12
  import { Create, CryptographicKey, Multikey, Note, Person } from "@fedify/vocab";
13
13
  import { test } from "@fedify/fixture";
14
14
  import { FetchError, encodeMultibase, exportDidKey, exportSpki, parseIri, preloadedContexts } from "@fedify/vocab-runtime";
15
- import serialize from "json-canon";
16
15
  import { deepStrictEqual, ok, strictEqual } from "node:assert/strict";
16
+ import serialize from "json-canon";
17
17
  //#region src/sig/portable-key.test.ts
18
18
  const did = await exportDidKey(ed25519PublicKey.publicKey);
19
19
  const didKeyId = `${did}#${did.slice(8)}`;
@@ -10,10 +10,10 @@ import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
11
11
  import { t as assert } from "../assert-D1Eafmd_.mjs";
12
12
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
13
- import { a as signObject, c as verifyPortableObjectProof, d as verifyProof, i as hasProofLike, r as createProof, s as verifyObject } from "../proof-vZ04IAjq.mjs";
14
- import { d as verifyRequest } from "../http-CXnNbRe_.mjs";
13
+ import { a as signObject, c as verifyPortableObjectProof, d as verifyProof, i as hasProofLike, r as createProof, s as verifyObject } from "../proof-BdO3BbLh.mjs";
14
+ import { d as verifyRequest } from "../http-DV_yW4dv.mjs";
15
15
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
16
- import { t as getAuthenticatedDocumentLoader } from "../docloader-vc-pSu9-.mjs";
16
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-C5p26tpa.mjs";
17
17
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place, Translation } from "@fedify/vocab";
18
18
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
19
19
  import { decodeMultibase, encodeMultibase, exportDidKey, exportMultibaseKey, formatIri, importMultibaseKey, parseIri } from "@fedify/vocab-runtime";
@@ -1,7 +1,7 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as mockDocumentLoader } from "./dist-BQvArojP.mjs";
4
+ import { t as mockDocumentLoader } from "./dist-DJQM4u7i.mjs";
5
5
  import { t as MemoryKvStore } from "./kv-DCHkaJ9-.mjs";
6
6
  import { Note } from "@fedify/vocab";
7
7
  //#region src/testing/tasks.ts
@@ -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-Djxsq6JR.mjs";
4
+ import { c as getNormalizationContextLoader } from "./ld-ya2C1Xip.mjs";
5
5
  import jsonld from "@fedify/vocab-runtime/jsonld";
6
6
  //#region src/federation/temporal.ts
7
7
  function isPlainObject(value) {
@@ -1,7 +1,7 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as test } from "../dist-BQvArojP.mjs";
4
+ import { n as test } from "../dist-DJQM4u7i.mjs";
5
5
  import { strictEqual } from "node:assert/strict";
6
6
  //#region src/testing/context.test.ts
7
7
  test("ignored nested test steps return false", async (t) => {
@@ -1,12 +1,12 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as test } from "../dist-BQvArojP.mjs";
4
+ import { n as test } from "../dist-DJQM4u7i.mjs";
5
5
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
7
- import { n as baseOptions, o as stringSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
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-DDa8pCUa.mjs";
9
+ import { o as createFederation } from "../middleware-Bdwd_Gg8.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();
@@ -3317,12 +3317,38 @@ interface Context<TContextData> {
3317
3317
  getPortableFeaturedTagsUri(identifier: string, authority: string): URL;
3318
3318
  /**
3319
3319
  * Determines the type of the URI and extracts the associated data.
3320
+ *
3321
+ * By default, only URIs on this server's origin are recognized. With
3322
+ * the `portable` option, [FEP-ef61] portable IDs, e.g.,
3323
+ * `ap+ef61://did:key:z6Mk.../users/alice`, and their compatible
3324
+ * identifiers on any gateway, e.g.,
3325
+ * `https://example.com/.well-known/apgateway/did:key:z6Mk.../users/alice`,
3326
+ * are also recognized by the same paths that the gateway endpoint routes
3327
+ * to the dispatchers, and the result has the DID in its `authority`
3328
+ * property.
3329
+ *
3330
+ * The DID of a portable ID is anyone's to choose, so recognizing it does
3331
+ * not mean that this server hosts anything for the DID. Check that
3332
+ * `authority` is the DID that the application stores for the actor or
3333
+ * object before acting on it:
3334
+ *
3335
+ * ~~~~ typescript
3336
+ * const parsed = ctx.parseUri(follow.objectId, { portable: true });
3337
+ * if (parsed?.type !== "actor") return;
3338
+ * const user = await getUser(parsed.identifier);
3339
+ * if (user == null) return;
3340
+ * if (parsed.authority != null && parsed.authority !== user.did) return;
3341
+ * ~~~~
3342
+ *
3343
+ * [FEP-ef61]: https://w3id.org/fep/ef61
3344
+ *
3320
3345
  * @param uri The URI to parse.
3346
+ * @param options Options for parsing the URI. Since 2.4.0.
3321
3347
  * @returns The result of parsing the URI. If `null` is given or
3322
3348
  * the URI is not recognized, `null` is returned.
3323
3349
  * @since 0.9.0
3324
3350
  */
3325
- parseUri(uri: URL | null): ParseUriResult | null;
3351
+ parseUri(uri: URL | null, options?: ParseUriOptions): ParseUriResult | null;
3326
3352
  /**
3327
3353
  * Gets the key pairs for an actor.
3328
3354
  * @param identifier The actor's identifier.
@@ -4220,6 +4246,30 @@ interface OutboxContext<TContextData> extends Context<TContextData> {
4220
4246
  */
4221
4247
  clone(data: TContextData): OutboxContext<TContextData>;
4222
4248
  }
4249
+ /**
4250
+ * Options for {@link Context.parseUri}.
4251
+ * @since 2.4.0
4252
+ */
4253
+ interface ParseUriOptions {
4254
+ /**
4255
+ * Whether to also recognize [FEP-ef61] portable IDs, i.e., `ap:` and
4256
+ * `ap+ef61:` URIs, and their compatible identifiers on any gateway.
4257
+ * The result of a portable ID has its DID, without percent-encoding, in
4258
+ * the `authority` property, which the caller has to compare with the DID
4259
+ * that it stores for the actor or object, since anyone can make a portable
4260
+ * ID with the same path under another DID.
4261
+ *
4262
+ * Like URIs on this server's origin, a portable ID is recognized by its
4263
+ * path, and its query, e.g., location hints, and fragment are ignored.
4264
+ * A shared inbox is never recognized in a portable ID, and a portable ID
4265
+ * with a malformed DID, or with a `did:key` DID that is not encoded in
4266
+ * base58-btc, is not recognized either.
4267
+ *
4268
+ * [FEP-ef61]: https://w3id.org/fep/ef61
4269
+ * @default `false`
4270
+ */
4271
+ readonly portable?: boolean;
4272
+ }
4223
4273
  /**
4224
4274
  * A result of parsing an URI.
4225
4275
  */
@@ -4230,6 +4280,12 @@ type ParseUriResult =
4230
4280
  {
4231
4281
  readonly type: "actor";
4232
4282
  readonly identifier: string;
4283
+ /**
4284
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4285
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4286
+ * @since 2.4.0
4287
+ */
4288
+ readonly authority?: string;
4233
4289
  }
4234
4290
  /**
4235
4291
  * The case of an object URI.
@@ -4239,6 +4295,12 @@ type ParseUriResult =
4239
4295
  readonly class: ConstructorWithTypeId<Object$1>;
4240
4296
  readonly typeId: URL;
4241
4297
  readonly values: Record<string, string>;
4298
+ /**
4299
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4300
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4301
+ * @since 2.4.0
4302
+ */
4303
+ readonly authority?: string;
4242
4304
  }
4243
4305
  /**
4244
4306
  * The case of an shared inbox URI.
@@ -4246,6 +4308,7 @@ type ParseUriResult =
4246
4308
  | {
4247
4309
  readonly type: "inbox";
4248
4310
  readonly identifier: undefined;
4311
+ readonly authority?: undefined;
4249
4312
  }
4250
4313
  /**
4251
4314
  * The case of an personal inbox URI.
@@ -4253,6 +4316,12 @@ type ParseUriResult =
4253
4316
  | {
4254
4317
  readonly type: "inbox";
4255
4318
  readonly identifier: string;
4319
+ /**
4320
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4321
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4322
+ * @since 2.4.0
4323
+ */
4324
+ readonly authority?: string;
4256
4325
  }
4257
4326
  /**
4258
4327
  * The case of an outbox collection URI.
@@ -4260,6 +4329,12 @@ type ParseUriResult =
4260
4329
  | {
4261
4330
  readonly type: "outbox";
4262
4331
  readonly identifier: string;
4332
+ /**
4333
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4334
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4335
+ * @since 2.4.0
4336
+ */
4337
+ readonly authority?: string;
4263
4338
  }
4264
4339
  /**
4265
4340
  * The case of a following collection URI.
@@ -4267,6 +4342,12 @@ type ParseUriResult =
4267
4342
  | {
4268
4343
  readonly type: "following";
4269
4344
  readonly identifier: string;
4345
+ /**
4346
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4347
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4348
+ * @since 2.4.0
4349
+ */
4350
+ readonly authority?: string;
4270
4351
  }
4271
4352
  /**
4272
4353
  * The case of a followers collection URI.
@@ -4274,6 +4355,12 @@ type ParseUriResult =
4274
4355
  | {
4275
4356
  readonly type: "followers";
4276
4357
  readonly identifier: string;
4358
+ /**
4359
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4360
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4361
+ * @since 2.4.0
4362
+ */
4363
+ readonly authority?: string;
4277
4364
  }
4278
4365
  /**
4279
4366
  * The case of a liked collection URI.
@@ -4282,6 +4369,12 @@ type ParseUriResult =
4282
4369
  | {
4283
4370
  readonly type: "liked";
4284
4371
  readonly identifier: string;
4372
+ /**
4373
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4374
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4375
+ * @since 2.4.0
4376
+ */
4377
+ readonly authority?: string;
4285
4378
  }
4286
4379
  /**
4287
4380
  * The case of a featured collection URI.
@@ -4290,6 +4383,12 @@ type ParseUriResult =
4290
4383
  | {
4291
4384
  readonly type: "featured";
4292
4385
  readonly identifier: string;
4386
+ /**
4387
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4388
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4389
+ * @since 2.4.0
4390
+ */
4391
+ readonly authority?: string;
4293
4392
  }
4294
4393
  /**
4295
4394
  * The case of a featured tags collection URI.
@@ -4298,6 +4397,12 @@ type ParseUriResult =
4298
4397
  | {
4299
4398
  readonly type: "featuredTags";
4300
4399
  readonly identifier: string;
4400
+ /**
4401
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4402
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4403
+ * @since 2.4.0
4404
+ */
4405
+ readonly authority?: string;
4301
4406
  }
4302
4407
  /**
4303
4408
  * The case of a custom collection URI.
@@ -4309,6 +4414,12 @@ type ParseUriResult =
4309
4414
  readonly class: ConstructorWithTypeId<Object$1>;
4310
4415
  readonly typeId: URL;
4311
4416
  readonly values: Record<string, string>;
4417
+ /**
4418
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4419
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4420
+ * @since 2.4.0
4421
+ */
4422
+ readonly authority?: string;
4312
4423
  }
4313
4424
  /**
4314
4425
  * The case of a custom ordered collection URI.
@@ -4320,6 +4431,12 @@ type ParseUriResult =
4320
4431
  readonly class: ConstructorWithTypeId<Object$1>;
4321
4432
  readonly typeId: URL;
4322
4433
  readonly values: Record<string, string>;
4434
+ /**
4435
+ * The DID of the portable ID, e.g., `did:key:z6Mk...`, or `undefined`
4436
+ * for a URI on this server's origin. See {@link ParseUriOptions.portable}.
4437
+ * @since 2.4.0
4438
+ */
4439
+ readonly authority?: string;
4323
4440
  };
4324
4441
  /**
4325
4442
  * Options for {@link Context.sendActivity} method.
@@ -1,9 +1,9 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { r as testDefinitions } from "../dist-BQvArojP.mjs";
5
- import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-OrnjnuMq.mjs";
4
+ import { r as testDefinitions } from "../dist-DJQM4u7i.mjs";
5
+ import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-B2rlkkyJ.mjs";
6
6
  import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
7
- import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, r as envelopeSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
8
- import "../testing-CKaJhcA0.mjs";
7
+ import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, r as envelopeSchema, t as MockQueue } from "../tasks-IG3pHfvZ.mjs";
8
+ import "../testing-C1itIjqW.mjs";
9
9
  export { ManualClockKvStore, MockQueue, baseOptions, createInboxContext, createOutboxContext, createRequestContext, envelopeSchema, makeSchema, numberSchema, stringSchema, testDefinitions };
@@ -1,8 +1,8 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import "./dist-BQvArojP.mjs";
5
- import "./context-OrnjnuMq.mjs";
4
+ import "./dist-DJQM4u7i.mjs";
5
+ import "./context-B2rlkkyJ.mjs";
6
6
  import "./kv-DBRWVx3Q.mjs";
7
- import "./tasks-dbCShlCb.mjs";
7
+ import "./tasks-IG3pHfvZ.mjs";
8
8
  export {};
@@ -92,8 +92,8 @@ const DEFAULT_MAX_REDIRECTION = 5;
92
92
  * bounce the request to an internal address.
93
93
  * @param url The URL to fetch.
94
94
  * @param headers The request headers.
95
- * @returns The final response, or `null` if the URL is disallowed or there
96
- * are too many redirects.
95
+ * @returns The final response, or `null` if the URL is disallowed, its
96
+ * hostname cannot be resolved, or there are too many redirects.
97
97
  */
98
98
  async function fetchPublicUrl(url, headers) {
99
99
  let current = url instanceof URL ? url : new URL(url);
@@ -103,7 +103,11 @@ async function fetchPublicUrl(url, headers) {
103
103
  await validatePublicUrl(current.href);
104
104
  } catch (e) {
105
105
  if (e instanceof UrlError) {
106
- logger.error("Refused to fetch a private or invalid URL {url}: {error}", {
106
+ if (e.reason === "dns") logger.error("DNS lookup failed for {url}: {error}", {
107
+ url: current.href,
108
+ error: e
109
+ });
110
+ else logger.error("Refused to fetch a private or invalid URL {url}: {error}", {
107
111
  url: current.href,
108
112
  error: e
109
113
  });
@@ -91,8 +91,8 @@ const DEFAULT_MAX_REDIRECTION = 5;
91
91
  * bounce the request to an internal address.
92
92
  * @param url The URL to fetch.
93
93
  * @param headers The request headers.
94
- * @returns The final response, or `null` if the URL is disallowed or there
95
- * are too many redirects.
94
+ * @returns The final response, or `null` if the URL is disallowed, its
95
+ * hostname cannot be resolved, or there are too many redirects.
96
96
  */
97
97
  async function fetchPublicUrl(url, headers) {
98
98
  let current = url instanceof URL ? url : new URL(url);
@@ -102,7 +102,11 @@ async function fetchPublicUrl(url, headers) {
102
102
  await (0, _fedify_vocab_runtime.validatePublicUrl)(current.href);
103
103
  } catch (e) {
104
104
  if (e instanceof _fedify_vocab_runtime.UrlError) {
105
- logger.error("Refused to fetch a private or invalid URL {url}: {error}", {
105
+ if (e.reason === "dns") logger.error("DNS lookup failed for {url}: {error}", {
106
+ url: current.href,
107
+ error: e
108
+ });
109
+ else logger.error("Refused to fetch a private or invalid URL {url}: {error}", {
106
110
  url: current.href,
107
111
  error: e
108
112
  });