@fedify/fedify 2.2.5 → 2.2.7

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 (52) hide show
  1. package/README.md +5 -4
  2. package/dist/{builder-zDJOhWad.mjs → builder-B2wazTqG.mjs} +4 -2
  3. package/dist/{client-D_1QpnWt.mjs → client-dx126nMS.mjs} +63 -5
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{deno-4Q9ruIMJ.mjs → deno-C-S0PIBP.mjs} +1 -1
  6. package/dist/{docloader-BHrm7BpO.mjs → docloader-uz9yC9QU.mjs} +2 -2
  7. package/dist/federation/builder.test.mjs +13 -1
  8. package/dist/federation/handler.test.mjs +3 -3
  9. package/dist/federation/idempotency.test.mjs +2 -2
  10. package/dist/federation/middleware.test.mjs +6 -6
  11. package/dist/federation/mod.cjs +1 -1
  12. package/dist/federation/mod.js +1 -1
  13. package/dist/federation/send.test.mjs +3 -3
  14. package/dist/federation/temporal.test.mjs +1 -1
  15. package/dist/federation/webfinger.test.mjs +69 -7
  16. package/dist/{http-CUIxu16z.mjs → http-6X85CU8F.mjs} +2 -2
  17. package/dist/{http-BTcDrLzD.js → http-CgXWkLVX.js} +17 -7
  18. package/dist/{http-CK9ElgLS.cjs → http-CpQrMPHt.cjs} +17 -7
  19. package/dist/{key-CVHsRpwc.mjs → key-CLIL70ZX.mjs} +17 -7
  20. package/dist/{kv-cache-DI-7Y6VS.cjs → kv-cache-DStmb1rz.cjs} +1 -1
  21. package/dist/{kv-cache-C_aWsl_r.js → kv-cache-DxK8WCAi.js} +1 -1
  22. package/dist/{ld-8MkMznIw.mjs → ld-DxefU9PP.mjs} +2 -2
  23. package/dist/{middleware-DHyZlPpi.mjs → middleware-CG-XVwTH.mjs} +67 -33
  24. package/dist/{middleware-B373Um8U.cjs → middleware-CfxcGH-c.cjs} +1 -1
  25. package/dist/{middleware-D7us7Y1k.cjs → middleware-DFvqEsxF.cjs} +63 -27
  26. package/dist/{middleware-0TW9PJkh.js → middleware-JQfoicJF.js} +62 -26
  27. package/dist/{middleware-ZavT88mD.mjs → middleware-fOW_Go1o.mjs} +1 -1
  28. package/dist/mod.cjs +5 -5
  29. package/dist/mod.js +5 -5
  30. package/dist/nodeinfo/client.test.mjs +61 -1
  31. package/dist/nodeinfo/handler.test.mjs +1 -1
  32. package/dist/nodeinfo/mod.cjs +1 -1
  33. package/dist/nodeinfo/mod.js +1 -1
  34. package/dist/{owner-BqFf5aUc.mjs → owner-BusoD2MY.mjs} +2 -2
  35. package/dist/{proof-DkLHCewr.mjs → proof-BfnzsRXs.mjs} +2 -2
  36. package/dist/{proof-v_hACCAr.js → proof-CDPESdd5.js} +1 -1
  37. package/dist/{proof-BpBLMdLk.cjs → proof-Z46FMN1e.cjs} +1 -1
  38. package/dist/{send-Cv34R1iA.mjs → send-mI-UOF8O.mjs} +2 -2
  39. package/dist/sig/http.test.mjs +2 -2
  40. package/dist/sig/key.test.mjs +51 -1
  41. package/dist/sig/ld.test.mjs +2 -2
  42. package/dist/sig/mod.cjs +2 -2
  43. package/dist/sig/mod.js +2 -2
  44. package/dist/sig/owner.test.mjs +1 -1
  45. package/dist/sig/proof.test.mjs +1 -1
  46. package/dist/{temporal-DqCyup3d.mjs → temporal-B0fodUhc.mjs} +1 -1
  47. package/dist/{types-CAY3OdLq.js → types-DTONwNqL.js} +63 -5
  48. package/dist/{types-KC4QAoxe.cjs → types-m8u9L86X.cjs} +62 -4
  49. package/dist/utils/docloader.test.mjs +2 -2
  50. package/dist/utils/mod.cjs +1 -1
  51. package/dist/utils/mod.js +1 -1
  52. package/package.json +5 -5
package/README.md CHANGED
@@ -193,7 +193,7 @@ This project exists thanks to all the people who contribute, donate, and sponsor
193
193
  it. We are grateful for their support. We would like to thank the following
194
194
  financial contributors:[^2]
195
195
 
196
- [^2]: Those lists are automatically updated every hour.
196
+ [^2]: Those lists are automatically updated twice a day.
197
197
 
198
198
  <!-- hongdown-disable -->
199
199
 
@@ -204,21 +204,22 @@ financial contributors:[^2]
204
204
  ### Corporate sponsors
205
205
 
206
206
  - [<img src="https://images.opencollective.com/ghost/avatar/128.png" width="64" height="64"> Ghost](https://ghost.org)
207
+ - [<img src="https://images.opencollective.com/altstore/avatar/128.png" width="64" height="64"> AltStore](https://altstore.io)
207
208
 
208
209
  ### Supporters
209
210
 
210
- - [Daniel Supernault](https://pixelfed.org/)
211
211
  - [tkgka](https://opencollective.com/tkgka)
212
212
  - [Blaine](https://opencollective.com/blaine)
213
213
  - [Erick González Aguilar](https://opencollective.com/erick-gonzalez-aguilar)
214
+ - [Daniel Supernault](https://pixelfed.org/)
214
215
 
215
216
  ### Backers
216
217
 
217
- Robin Riley, yamanoku, Encyclia, taye, okin, Andy Piper, box464, Evan Prodromou, Rafael Goulart, malte
218
+ Robin Riley, Encyclia, taye, box464, Evan Prodromou, okin, yamanoku, malte, Rafael Goulart, Andy Piper
218
219
 
219
220
  ### One-time donations
220
221
 
221
- Robin Riley, Markus P, Nils Bergmann, Rameez
222
+ Robin Riley, malte, Nils Bergmann, Markus P, Rameez
222
223
 
223
224
  <!-- /DO NOT EDIT -->
224
225
 
@@ -2,7 +2,7 @@ import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { n as RouterError, t as Router } from "./router-CrMLXoOr.mjs";
5
- import { n as version, t as name } from "./deno-4Q9ruIMJ.mjs";
5
+ import { n as version, t as name } from "./deno-C-S0PIBP.mjs";
6
6
  import { t as ActivityListenerSet } from "./activity-listener-ell7W1s9.mjs";
7
7
  import { Tombstone, getTypeId } from "@fedify/vocab";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
@@ -58,7 +58,7 @@ var FederationBuilderImpl = class {
58
58
  this.collectionTypeIds = {};
59
59
  }
60
60
  async build(options) {
61
- const { FederationImpl } = await import("./middleware-ZavT88mD.mjs");
61
+ const { FederationImpl } = await import("./middleware-fOW_Go1o.mjs");
62
62
  const f = new FederationImpl(options);
63
63
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
64
64
  f.router = this.router.clone();
@@ -69,6 +69,8 @@ var FederationBuilderImpl = class {
69
69
  f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
70
70
  f.objectCallbacks = { ...this.objectCallbacks };
71
71
  f.objectTypeIds = { ...this.objectTypeIds };
72
+ f.collectionCallbacks = { ...this.collectionCallbacks };
73
+ f.collectionTypeIds = { ...this.collectionTypeIds };
72
74
  f.inboxPath = this.inboxPath;
73
75
  f.outboxPath = this.outboxPath;
74
76
  f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { getUserAgent } from "@fedify/vocab-runtime";
4
+ import { UrlError, getUserAgent, validatePublicUrl } from "@fedify/vocab-runtime";
5
5
  import { getLogger } from "@logtape/logtape";
6
6
  //#region src/nodeinfo/client.ts
7
7
  const logger = getLogger([
@@ -9,15 +9,72 @@ const logger = getLogger([
9
9
  "nodeinfo",
10
10
  "client"
11
11
  ]);
12
+ const DEFAULT_MAX_REDIRECTION = 5;
13
+ /**
14
+ * Fetches a URL while guarding against SSRF. Before every request—including
15
+ * each redirect hop—the destination is validated with
16
+ * {@link validatePublicUrl}, so that loopback, link-local, and private
17
+ * addresses, as well as non-HTTP(S) schemes such as `data:`, are rejected.
18
+ * Redirects are followed manually with a cap, so that a public URL cannot
19
+ * bounce the request to an internal address.
20
+ * @param url The URL to fetch.
21
+ * @param headers The request headers.
22
+ * @returns The final response, or `null` if the URL is disallowed or there
23
+ * are too many redirects.
24
+ */
25
+ async function fetchPublicUrl(url, headers) {
26
+ let current = url instanceof URL ? url : new URL(url);
27
+ let redirected = 0;
28
+ while (true) {
29
+ try {
30
+ await validatePublicUrl(current.href);
31
+ } catch (e) {
32
+ if (e instanceof UrlError) {
33
+ logger.error("Refused to fetch a private or invalid URL {url}: {error}", {
34
+ url: current.href,
35
+ error: e
36
+ });
37
+ return null;
38
+ }
39
+ throw e;
40
+ }
41
+ const response = await fetch(current, {
42
+ headers,
43
+ redirect: "manual"
44
+ });
45
+ if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
46
+ redirected++;
47
+ if (redirected >= DEFAULT_MAX_REDIRECTION) {
48
+ logger.error("Too many redirections ({redirections}) while fetching {url}.", {
49
+ redirections: redirected,
50
+ url: current.href
51
+ });
52
+ return null;
53
+ }
54
+ const next = new URL(response.headers.get("Location"), response.url == null || response.url === "" ? current : response.url);
55
+ if (next.protocol !== current.protocol) {
56
+ logger.error("Refused a redirect to a different protocol ({protocol} to {redirectedProtocol}) while fetching NodeInfo.", {
57
+ protocol: current.protocol,
58
+ redirectedProtocol: next.protocol
59
+ });
60
+ return null;
61
+ }
62
+ current = next;
63
+ continue;
64
+ }
65
+ return response;
66
+ }
67
+ }
12
68
  async function getNodeInfo(url, options = {}) {
13
69
  try {
14
70
  let nodeInfoUrl = url;
15
71
  if (!options.direct) {
16
72
  const wellKnownUrl = new URL("/.well-known/nodeinfo", url);
17
- const wellKnownResponse = await fetch(wellKnownUrl, { headers: {
73
+ const wellKnownResponse = await fetchPublicUrl(wellKnownUrl, {
18
74
  Accept: "application/json",
19
75
  "User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
20
- } });
76
+ });
77
+ if (wellKnownResponse == null) return void 0;
21
78
  if (!wellKnownResponse.ok) {
22
79
  logger.error("Failed to fetch {url}: {status} {statusText}", {
23
80
  url: wellKnownUrl.href,
@@ -37,10 +94,11 @@ async function getNodeInfo(url, options = {}) {
37
94
  }
38
95
  nodeInfoUrl = link.href;
39
96
  }
40
- const response = await fetch(nodeInfoUrl, { headers: {
97
+ const response = await fetchPublicUrl(nodeInfoUrl, {
41
98
  Accept: "application/json",
42
99
  "User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
43
- } });
100
+ });
101
+ if (response == null) return void 0;
44
102
  if (!response.ok) {
45
103
  logger.error("Failed to fetch NodeInfo document from {url}: {status} {statusText}", {
46
104
  url: nodeInfoUrl.toString(),
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
6
6
  import { t as assert } from "../assert-DikXweDx.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
- import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-DHyZlPpi.mjs";
8
+ import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-CG-XVwTH.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  import { Follow, Person } from "@fedify/vocab";
11
11
  //#region src/compat/transformers.test.ts
@@ -3,6 +3,6 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  //#region deno.json
5
5
  var name = "@fedify/fedify";
6
- var version = "2.2.5";
6
+ var version = "2.2.7";
7
7
  //#endregion
8
8
  export { version as n, name as t };
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { o as validateCryptoKey } from "./key-CVHsRpwc.mjs";
5
- import { n as doubleKnock } from "./http-CUIxu16z.mjs";
4
+ import { o as validateCryptoKey } from "./key-CLIL70ZX.mjs";
5
+ import { n as doubleKnock } from "./http-6X85CU8F.mjs";
6
6
  import { curry } from "es-toolkit";
7
7
  import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
8
8
  import { getLogger } from "@logtape/logtape";
@@ -6,7 +6,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import { i as assertExists } from "../std__assert-CRDpx_HF.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
- import { n as createFederationBuilder } from "../builder-zDJOhWad.mjs";
9
+ import { n as createFederationBuilder } from "../builder-B2wazTqG.mjs";
10
10
  import { test } from "@fedify/fixture";
11
11
  import { Activity, Note, Person } from "@fedify/vocab";
12
12
  //#region src/federation/builder.test.ts
@@ -180,6 +180,18 @@ test("FederationBuilder", async (t) => {
180
180
  });
181
181
  builder.setCollectionDispatcher(strId, Note, "/string-id/{id}", dispatcher);
182
182
  });
183
+ await t.step("propagates custom collection dispatchers to the built federation", async () => {
184
+ const kv = new MemoryKvStore();
185
+ const builder = createFederationBuilder();
186
+ builder.setCollectionDispatcher("test", Note, "/c/{id}", () => ({ items: [] }));
187
+ const impl = await builder.build({
188
+ kv,
189
+ origin: "https://example.com"
190
+ });
191
+ assertExists(impl.collectionCallbacks["test"]);
192
+ assertEquals(impl.collectionTypeIds["test"], Note);
193
+ assertEquals((await impl.fetch(new Request("https://example.com/c/x", { headers: { accept: "application/activity+json" } }), { contextData: void 0 })).status, 200);
194
+ });
183
195
  });
184
196
  //#endregion
185
197
  export {};
@@ -8,11 +8,11 @@ import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
8
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
9
9
  import { t as assert } from "../assert-DikXweDx.mjs";
10
10
  import { r as parseAcceptSignature } from "../accept-CPkZzmGN.mjs";
11
- import { s as signRequest } from "../http-CUIxu16z.mjs";
11
+ import { s as signRequest } from "../http-6X85CU8F.mjs";
12
12
  import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
13
- import { a as compactJsonLd, p as signJsonLd } from "../ld-8MkMznIw.mjs";
13
+ import { a as compactJsonLd, p as signJsonLd } from "../ld-DxefU9PP.mjs";
14
14
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
15
- import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-DHyZlPpi.mjs";
15
+ import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-CG-XVwTH.mjs";
16
16
  import { t as ActivityListenerSet } from "../activity-listener-ell7W1s9.mjs";
17
17
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
18
18
  import { Activity, Create, Note, Person, Tombstone } from "@fedify/vocab";
@@ -4,9 +4,9 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-CRDpx_HF.mjs";
6
6
  import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
7
- import { r as signObject } from "../proof-DkLHCewr.mjs";
7
+ import { r as signObject } from "../proof-BfnzsRXs.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
- import { o as createFederation } from "../middleware-DHyZlPpi.mjs";
9
+ import { o as createFederation } from "../middleware-CG-XVwTH.mjs";
10
10
  import { mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, Follow, Person } from "@fedify/vocab";
12
12
  //#region src/federation/idempotency.test.ts
@@ -11,14 +11,14 @@ import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
11
11
  import { t as assertNotEquals } from "../assert_not_equals--wG9hV7u.mjs";
12
12
  import { t as assertStrictEquals } from "../assert_strict_equals-Dmjbg-bA.mjs";
13
13
  import { t as assert } from "../assert-DikXweDx.mjs";
14
- import { l as verifyRequest, s as signRequest } from "../http-CUIxu16z.mjs";
14
+ import { l as verifyRequest, s as signRequest } from "../http-6X85CU8F.mjs";
15
15
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
16
- import { t as getAuthenticatedDocumentLoader } from "../docloader-BHrm7BpO.mjs";
17
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-8MkMznIw.mjs";
18
- import { t as doesActorOwnKey } from "../owner-BqFf5aUc.mjs";
19
- import { i as verifyObject, r as signObject } from "../proof-DkLHCewr.mjs";
16
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-uz9yC9QU.mjs";
17
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-DxefU9PP.mjs";
18
+ import { t as doesActorOwnKey } from "../owner-BusoD2MY.mjs";
19
+ import { i as verifyObject, r as signObject } from "../proof-BfnzsRXs.mjs";
20
20
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
21
- import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-DHyZlPpi.mjs";
21
+ import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-CG-XVwTH.mjs";
22
22
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
23
23
  import * as vocab from "@fedify/vocab";
24
24
  import { Create, Offer, Person, getTypeId, lookupObject } from "@fedify/vocab";
@@ -2,7 +2,7 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("../chunk-DDcVe30Y.cjs");
5
- const require_middleware = require("../middleware-D7us7Y1k.cjs");
5
+ const require_middleware = require("../middleware-DFvqEsxF.cjs");
6
6
  let es_toolkit = require("es-toolkit");
7
7
  //#region src/federation/kv.ts
8
8
  /**
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "../middleware-0TW9PJkh.js";
3
+ import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "../middleware-JQfoicJF.js";
4
4
  import { isEqual } from "es-toolkit";
5
5
  //#region src/federation/kv.ts
6
6
  /**
@@ -8,10 +8,10 @@ import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z
8
8
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
9
9
  import { t as assertNotEquals } from "../assert_not_equals--wG9hV7u.mjs";
10
10
  import { t as assert } from "../assert-DikXweDx.mjs";
11
- import { l as verifyRequest } from "../http-CUIxu16z.mjs";
11
+ import { l as verifyRequest } from "../http-6X85CU8F.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
13
- import { t as doesActorOwnKey } from "../owner-BqFf5aUc.mjs";
14
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-Cv34R1iA.mjs";
13
+ import { t as doesActorOwnKey } from "../owner-BusoD2MY.mjs";
14
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-mI-UOF8O.mjs";
15
15
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
17
17
  //#region src/federation/send.test.ts
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import "../std__assert-CRDpx_HF.mjs";
5
5
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
6
6
  import { t as assert } from "../assert-DikXweDx.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-DqCyup3d.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-B0fodUhc.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 () => {
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-Dk_tacqz.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-CRDpx_HF.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
- import { o as createFederation, s as handleWebFinger } from "../middleware-DHyZlPpi.mjs";
8
+ import { o as createFederation, s as handleWebFinger } from "../middleware-CG-XVwTH.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  //#region src/federation/webfinger.test.ts
@@ -257,7 +257,7 @@ test("handleWebFinger()", async (t) => {
257
257
  });
258
258
  onNotFoundCalled = null;
259
259
  const actorHandleMapper = (_ctx, username) => {
260
- return username === "foo" ? "someone" : username === "bar" ? "someone2" : null;
260
+ return username === "foo" ? "someone" : username === "bar" ? "someone2" : username === "qux" ? "someone2" : null;
261
261
  };
262
262
  await t.step("handle mapper", async () => {
263
263
  const u = new URL(url);
@@ -380,21 +380,83 @@ test("handleWebFinger()", async (t) => {
380
380
  assertEquals(response.status, 404);
381
381
  });
382
382
  await t.step("handleHost", async () => {
383
- const u = new URL(url);
384
- u.searchParams.set("resource", "acct:someone@example.com");
383
+ let u = new URL("https://ap.example.com/.well-known/webfinger");
384
+ u.searchParams.set("resource", "acct:someone@ap.example.com");
385
385
  let context = createContext(u);
386
386
  let request = context.request;
387
387
  let response = await handleWebFinger(request, {
388
388
  context,
389
- host: "handle.example.com",
389
+ host: "example.com",
390
390
  actorDispatcher,
391
391
  onNotFound
392
392
  });
393
393
  assertEquals(response.status, 200);
394
394
  assertEquals(await response.json(), {
395
- ...expected,
396
- aliases: [...expected.aliases, "acct:someone@handle.example.com"]
395
+ subject: "acct:someone@example.com",
396
+ aliases: ["https://ap.example.com/users/someone", "acct:someone@ap.example.com"],
397
+ links: [
398
+ {
399
+ href: "https://ap.example.com/users/someone",
400
+ rel: "self",
401
+ type: "application/activity+json"
402
+ },
403
+ {
404
+ href: "https://ap.example.com/@someone",
405
+ rel: "http://webfinger.net/rel/profile-page"
406
+ },
407
+ {
408
+ href: "https://ap.example.com/@someone",
409
+ rel: "alternate",
410
+ type: "text/html"
411
+ },
412
+ {
413
+ href: "https://ap.example.com/icon.jpg",
414
+ rel: "http://webfinger.net/rel/avatar",
415
+ type: "image/jpeg"
416
+ }
417
+ ]
418
+ });
419
+ u.searchParams.set("resource", "acct:qux@ap.example.com");
420
+ context = createContext(u);
421
+ request = context.request;
422
+ response = await handleWebFinger(request, {
423
+ context,
424
+ host: "example.com",
425
+ actorDispatcher,
426
+ actorHandleMapper,
427
+ onNotFound
397
428
  });
429
+ assertEquals(response.status, 200);
430
+ assertEquals(await response.json(), {
431
+ subject: "acct:bar@example.com",
432
+ aliases: [
433
+ "https://ap.example.com/users/someone2",
434
+ "acct:qux@ap.example.com",
435
+ "acct:bar@ap.example.com"
436
+ ],
437
+ links: [
438
+ {
439
+ href: "https://ap.example.com/users/someone2",
440
+ rel: "self",
441
+ type: "application/activity+json"
442
+ },
443
+ {
444
+ href: "https://ap.example.com/@someone2",
445
+ rel: "http://webfinger.net/rel/profile-page"
446
+ },
447
+ {
448
+ href: "https://ap.example.com/@someone2",
449
+ rel: "alternate",
450
+ type: "text/html"
451
+ },
452
+ {
453
+ href: "https://ap.example.com/icon.jpg",
454
+ rel: "http://webfinger.net/rel/avatar",
455
+ type: "image/jpeg"
456
+ }
457
+ ]
458
+ });
459
+ u = new URL(url);
398
460
  u.searchParams.set("resource", "acct:someone@handle.example.com");
399
461
  context = createContext(u);
400
462
  request = context.request;
@@ -1,9 +1,9 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-4Q9ruIMJ.mjs";
4
+ import { n as version, t as name } from "./deno-C-S0PIBP.mjs";
5
5
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPkZzmGN.mjs";
6
- import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-CVHsRpwc.mjs";
6
+ import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-CLIL70ZX.mjs";
7
7
  import { CryptographicKey } from "@fedify/vocab";
8
8
  import { SpanStatusCode, trace } from "@opentelemetry/api";
9
9
  import { FetchError } from "@fedify/vocab-runtime";
@@ -10,7 +10,7 @@ import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } fro
10
10
  import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
11
11
  //#region deno.json
12
12
  var name = "@fedify/fedify";
13
- var version = "2.2.5";
13
+ var version = "2.2.7";
14
14
  //#endregion
15
15
  //#region src/sig/accept.ts
16
16
  /**
@@ -392,21 +392,31 @@ async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoade
392
392
  const keys = cls === CryptographicKey ? object.getPublicKeys({
393
393
  documentLoader,
394
394
  contextLoader,
395
+ suppressError: true,
395
396
  tracerProvider
396
397
  }) : object.getAssertionMethods({
397
398
  documentLoader,
398
399
  contextLoader,
400
+ suppressError: true,
399
401
  tracerProvider
400
402
  });
401
403
  let length = 0;
402
404
  let lastKey = null;
403
- for await (const k of keys) {
404
- length++;
405
- lastKey = k;
406
- if (k.id?.href === keyId) {
407
- key = k;
408
- break;
405
+ try {
406
+ for await (const k of keys) {
407
+ length++;
408
+ lastKey = k;
409
+ if (k.id?.href === keyId) {
410
+ key = k;
411
+ break;
412
+ }
409
413
  }
414
+ } catch (e) {
415
+ if (!(e instanceof TypeError)) throw e;
416
+ logger.debug("Failed to verify; a malformed key was encountered while iterating the keys of {keyId}; treating it as a missing key: {error}", {
417
+ keyId,
418
+ error: e
419
+ });
410
420
  }
411
421
  const keyIdUrl = new URL(keyId);
412
422
  if (key == null && keyIdUrl.hash === "" && length === 1) key = lastKey;
@@ -11,7 +11,7 @@ let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conve
11
11
  let byte_encodings_base64 = require("byte-encodings/base64");
12
12
  //#region deno.json
13
13
  var name = "@fedify/fedify";
14
- var version = "2.2.5";
14
+ var version = "2.2.7";
15
15
  //#endregion
16
16
  //#region src/sig/accept.ts
17
17
  /**
@@ -393,21 +393,31 @@ async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoade
393
393
  const keys = cls === _fedify_vocab.CryptographicKey ? object.getPublicKeys({
394
394
  documentLoader,
395
395
  contextLoader,
396
+ suppressError: true,
396
397
  tracerProvider
397
398
  }) : object.getAssertionMethods({
398
399
  documentLoader,
399
400
  contextLoader,
401
+ suppressError: true,
400
402
  tracerProvider
401
403
  });
402
404
  let length = 0;
403
405
  let lastKey = null;
404
- for await (const k of keys) {
405
- length++;
406
- lastKey = k;
407
- if (k.id?.href === keyId) {
408
- key = k;
409
- break;
406
+ try {
407
+ for await (const k of keys) {
408
+ length++;
409
+ lastKey = k;
410
+ if (k.id?.href === keyId) {
411
+ key = k;
412
+ break;
413
+ }
410
414
  }
415
+ } catch (e) {
416
+ if (!(e instanceof TypeError)) throw e;
417
+ logger.debug("Failed to verify; a malformed key was encountered while iterating the keys of {keyId}; treating it as a missing key: {error}", {
418
+ keyId,
419
+ error: e
420
+ });
411
421
  }
412
422
  const keyIdUrl = new URL(keyId);
413
423
  if (key == null && keyIdUrl.hash === "" && length === 1) key = lastKey;
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-4Q9ruIMJ.mjs";
4
+ import { n as version, t as name } from "./deno-C-S0PIBP.mjs";
5
5
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
7
7
  import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
@@ -247,21 +247,31 @@ async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoade
247
247
  const keys = cls === CryptographicKey ? object.getPublicKeys({
248
248
  documentLoader,
249
249
  contextLoader,
250
+ suppressError: true,
250
251
  tracerProvider
251
252
  }) : object.getAssertionMethods({
252
253
  documentLoader,
253
254
  contextLoader,
255
+ suppressError: true,
254
256
  tracerProvider
255
257
  });
256
258
  let length = 0;
257
259
  let lastKey = null;
258
- for await (const k of keys) {
259
- length++;
260
- lastKey = k;
261
- if (k.id?.href === keyId) {
262
- key = k;
263
- break;
260
+ try {
261
+ for await (const k of keys) {
262
+ length++;
263
+ lastKey = k;
264
+ if (k.id?.href === keyId) {
265
+ key = k;
266
+ break;
267
+ }
264
268
  }
269
+ } catch (e) {
270
+ if (!(e instanceof TypeError)) throw e;
271
+ logger.debug("Failed to verify; a malformed key was encountered while iterating the keys of {keyId}; treating it as a missing key: {error}", {
272
+ keyId,
273
+ error: e
274
+ });
265
275
  }
266
276
  const keyIdUrl = new URL(keyId);
267
277
  if (key == null && keyIdUrl.hash === "" && length === 1) key = lastKey;
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  require("./chunk-DDcVe30Y.cjs");
4
- const require_http = require("./http-CK9ElgLS.cjs");
4
+ const require_http = require("./http-CpQrMPHt.cjs");
5
5
  let _logtape_logtape = require("@logtape/logtape");
6
6
  let es_toolkit = require("es-toolkit");
7
7
  let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { d as validateCryptoKey, t as doubleKnock } from "./http-BTcDrLzD.js";
3
+ import { d as validateCryptoKey, t as doubleKnock } from "./http-CgXWkLVX.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { curry } from "es-toolkit";
6
6
  import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-4Q9ruIMJ.mjs";
5
- import { n as fetchKey, o as validateCryptoKey } from "./key-CVHsRpwc.mjs";
4
+ import { n as version, t as name } from "./deno-C-S0PIBP.mjs";
5
+ import { n as fetchKey, o as validateCryptoKey } from "./key-CLIL70ZX.mjs";
6
6
  import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
7
7
  import { SpanStatusCode, trace } from "@opentelemetry/api";
8
8
  import { getDocumentLoader } from "@fedify/vocab-runtime";