@fedify/fedify 2.3.2-dev.1556 → 2.3.3

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 (56) hide show
  1. package/README.md +1 -1
  2. package/dist/{builder-DosLp_w5.mjs → builder-C5tNTbfB.mjs} +4 -2
  3. package/dist/{client-ByXmQhYD.mjs → client-D1KuWxjH.mjs} +63 -5
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{deno-Bg8I1L40.mjs → deno-CLDlEM_h.mjs} +1 -1
  6. package/dist/{docloader-Dxsk3R8v.mjs → docloader-C59Y-Xd7.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/metrics.test.mjs +1 -1
  11. package/dist/federation/middleware.test.mjs +7 -7
  12. package/dist/federation/mod.cjs +1 -1
  13. package/dist/federation/mod.js +1 -1
  14. package/dist/federation/send.test.mjs +3 -3
  15. package/dist/federation/temporal.test.mjs +1 -1
  16. package/dist/federation/webfinger.test.mjs +69 -7
  17. package/dist/{http-Bw8wN_Uk.js → http-B7kkm6X3.js} +1 -1
  18. package/dist/{http-BaUm6xbz.mjs → http-DUzPFiJs.mjs} +3 -3
  19. package/dist/{http-y8Cigpuq.cjs → http-wDQjTxaL.cjs} +1 -1
  20. package/dist/{key-DOnwUeY9.mjs → key-C4wPbyOr.mjs} +2 -2
  21. package/dist/{kv-cache-B9AAXEOS.cjs → kv-cache-BOeXoqu7.cjs} +1 -1
  22. package/dist/{kv-cache-CE_QUNa6.mjs → kv-cache-D05n14J8.mjs} +1 -1
  23. package/dist/{kv-cache-DilyIIfz.js → kv-cache-DOILP4AX.js} +1 -1
  24. package/dist/{ld-CiONXo2U.mjs → ld-CGWGFEsa.mjs} +3 -3
  25. package/dist/{metrics-CmX7KEfY.mjs → metrics-BgfLGIG9.mjs} +1 -1
  26. package/dist/{middleware-Cf0dFqr9.mjs → middleware-C5Z86Ykr.mjs} +48 -31
  27. package/dist/{middleware-CRMohX8-.mjs → middleware-DL9vpn_7.mjs} +1 -1
  28. package/dist/{middleware-DZf3vcun.cjs → middleware-D_uFaE6o.cjs} +41 -22
  29. package/dist/{middleware-BEhF8uxY.js → middleware-yhZdg6HS.js} +41 -22
  30. package/dist/mod.cjs +5 -5
  31. package/dist/mod.js +5 -5
  32. package/dist/nodeinfo/client.test.mjs +61 -1
  33. package/dist/nodeinfo/handler.test.mjs +1 -1
  34. package/dist/nodeinfo/mod.cjs +1 -1
  35. package/dist/nodeinfo/mod.js +1 -1
  36. package/dist/{owner-C7h5_D1P.mjs → owner-BPbxcXKO.mjs} +2 -2
  37. package/dist/{proof-BKOUYRRh.cjs → proof-CeYtrhby.cjs} +1 -1
  38. package/dist/{proof-BVuILGqP.mjs → proof-DZzDbN7h.mjs} +3 -3
  39. package/dist/{proof-DNlVt3rz.js → proof-DpV8djtd.js} +1 -1
  40. package/dist/{send-7kSXrsl4.mjs → send-CD7M4Uyd.mjs} +3 -3
  41. package/dist/sig/http.test.mjs +2 -2
  42. package/dist/sig/key.test.mjs +1 -1
  43. package/dist/sig/ld.test.mjs +2 -2
  44. package/dist/sig/mod.cjs +2 -2
  45. package/dist/sig/mod.js +2 -2
  46. package/dist/sig/owner.test.mjs +1 -1
  47. package/dist/sig/proof.test.mjs +1 -1
  48. package/dist/{temporal-D3Bspq6d.mjs → temporal-CIrD6Oq3.mjs} +1 -1
  49. package/dist/{types-CAY3OdLq.js → types-DTONwNqL.js} +63 -5
  50. package/dist/{types-KC4QAoxe.cjs → types-m8u9L86X.cjs} +62 -4
  51. package/dist/utils/docloader.test.mjs +2 -2
  52. package/dist/utils/kv-cache.test.mjs +1 -1
  53. package/dist/utils/mod.cjs +1 -1
  54. package/dist/utils/mod.js +1 -1
  55. package/package.json +6 -6
  56. package/skills/fedify/SKILL.md +462 -0
package/README.md CHANGED
@@ -205,7 +205,7 @@ This project exists thanks to all the people who contribute, donate, and sponsor
205
205
  it. We are grateful for their support. We would like to thank the following
206
206
  financial contributors:[^2]
207
207
 
208
- [^2]: Those lists are automatically updated every hour.
208
+ [^2]: Those lists are automatically updated twice a day.
209
209
 
210
210
  <!-- hongdown-disable -->
211
211
 
@@ -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-Bg8I1L40.mjs";
4
+ import { n as version, t as name } from "./deno-CLDlEM_h.mjs";
5
5
  import { t as ActivityListenerSet } from "./activity-listener-tztVvlNb.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
@@ -80,7 +80,7 @@ var FederationBuilderImpl = class {
80
80
  * specified.
81
81
  */
82
82
  async build(options) {
83
- const { FederationImpl } = await import("./middleware-CRMohX8-.mjs");
83
+ const { FederationImpl } = await import("./middleware-DL9vpn_7.mjs");
84
84
  const f = new FederationImpl(options);
85
85
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
86
86
  f.router = this.router.clone();
@@ -91,6 +91,8 @@ var FederationBuilderImpl = class {
91
91
  f.webFingerLinksDispatcher = this.webFingerLinksDispatcher;
92
92
  f.objectCallbacks = { ...this.objectCallbacks };
93
93
  f.objectTypeIds = { ...this.objectTypeIds };
94
+ f.collectionCallbacks = { ...this.collectionCallbacks };
95
+ f.collectionTypeIds = { ...this.collectionTypeIds };
94
96
  f.inboxPath = this.inboxPath;
95
97
  f.outboxPath = this.outboxPath;
96
98
  f.inboxCallbacks = this.inboxCallbacks == null ? void 0 : { ...this.inboxCallbacks };
@@ -2,22 +2,79 @@ import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { getLogger } from "@logtape/logtape";
5
- import { getUserAgent } from "@fedify/vocab-runtime";
5
+ import { UrlError, getUserAgent, validatePublicUrl } from "@fedify/vocab-runtime";
6
6
  //#region src/nodeinfo/client.ts
7
7
  const logger = getLogger([
8
8
  "fedify",
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-C-ZRDbaf.mjs";
5
5
  import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
6
6
  import { t as assert } from "../assert-OguE97r2.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
- import { b as autoIdAssigner, n as FederationImpl, y as actorDehydrator } from "../middleware-Cf0dFqr9.mjs";
8
+ import { b as autoIdAssigner, n as FederationImpl, y as actorDehydrator } from "../middleware-C5Z86Ykr.mjs";
9
9
  import { Follow, Person } from "@fedify/vocab";
10
10
  import { test } from "@fedify/fixture";
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.3.2-dev.1556+3e14f2d7";
6
+ var version = "2.3.3";
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-DOnwUeY9.mjs";
5
- import { n as doubleKnock } from "./http-BaUm6xbz.mjs";
4
+ import { o as validateCryptoKey } from "./key-C4wPbyOr.mjs";
5
+ import { n as doubleKnock } from "./http-DUzPFiJs.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
8
8
  import { curry } from "es-toolkit";
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { r as assertExists } from "../std__assert-BBjXFNOb.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
- import { r as createFederationBuilder } from "../builder-DosLp_w5.mjs";
8
+ import { r as createFederationBuilder } from "../builder-C5tNTbfB.mjs";
9
9
  import { DisallowedOperatorError, DisallowedVarSpecModifierError, DuplicateRouteVariableError, RouteTemplateOptionsNotMatchedError, RouterError } from "@fedify/uri-template";
10
10
  import { Activity, Note, Person } from "@fedify/vocab";
11
11
  import { test } from "@fedify/fixture";
@@ -332,6 +332,18 @@ test("FederationBuilder", async (t) => {
332
332
  });
333
333
  builder.setCollectionDispatcher(strId, Note, "/string-id/{id}", dispatcher);
334
334
  });
335
+ await t.step("propagates custom collection dispatchers to the built federation", async () => {
336
+ const kv = new MemoryKvStore();
337
+ const builder = createFederationBuilder();
338
+ builder.setCollectionDispatcher("test", Note, "/c/{id}", () => ({ items: [] }));
339
+ const impl = await builder.build({
340
+ kv,
341
+ origin: "https://example.com"
342
+ });
343
+ assertExists(impl.collectionCallbacks["test"]);
344
+ assertEquals(impl.collectionTypeIds["test"], Note);
345
+ assertEquals((await impl.fetch(new Request("https://example.com/c/x", { headers: { accept: "application/activity+json" } }), { contextData: void 0 })).status, 200);
346
+ });
335
347
  });
336
348
  //#endregion
337
349
  export {};
@@ -8,11 +8,11 @@ import { n as assertGreaterOrEqual, t as assertRejects } from "../assert_rejects
8
8
  import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
9
9
  import { t as assert } from "../assert-OguE97r2.mjs";
10
10
  import { r as parseAcceptSignature } from "../accept-CPkZzmGN.mjs";
11
- import { s as signRequest } from "../http-BaUm6xbz.mjs";
11
+ import { s as signRequest } from "../http-DUzPFiJs.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-CiONXo2U.mjs";
13
+ import { a as compactJsonLd, p as signJsonLd } from "../ld-CGWGFEsa.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-Cf0dFqr9.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-C5Z86Ykr.mjs";
16
16
  import { t as ActivityListenerSet } from "../activity-listener-tztVvlNb.mjs";
17
17
  import { Activity, Create, Note, Person, Tombstone } from "@fedify/vocab";
18
18
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -4,9 +4,9 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
6
  import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
7
- import { r as signObject } from "../proof-BVuILGqP.mjs";
7
+ import { r as signObject } from "../proof-DZzDbN7h.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
- import { o as createFederation } from "../middleware-Cf0dFqr9.mjs";
9
+ import { o as createFederation } from "../middleware-C5Z86Ykr.mjs";
10
10
  import { Create, Follow, Person } from "@fedify/vocab";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/federation/idempotency.test.ts
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
7
- import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-CmX7KEfY.mjs";
7
+ import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-BgfLGIG9.mjs";
8
8
  import { createTestMeterProvider, test } from "@fedify/fixture";
9
9
  import { FetchError } from "@fedify/vocab-runtime";
10
10
  import { DataPointType, MeterProvider, MetricReader } from "@opentelemetry/sdk-metrics";
@@ -10,15 +10,15 @@ import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
10
10
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
11
11
  import { t as assertStrictEquals } from "../assert_strict_equals-XEgZAlrj.mjs";
12
12
  import { t as assert } from "../assert-OguE97r2.mjs";
13
- import { g as recordInboxActivity } from "../metrics-CmX7KEfY.mjs";
14
- import { l as verifyRequest, s as signRequest } from "../http-BaUm6xbz.mjs";
13
+ import { g as recordInboxActivity } from "../metrics-BgfLGIG9.mjs";
14
+ import { l as verifyRequest, s as signRequest } from "../http-DUzPFiJs.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-Dxsk3R8v.mjs";
17
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-CiONXo2U.mjs";
18
- import { t as doesActorOwnKey } from "../owner-C7h5_D1P.mjs";
19
- import { i as verifyObject, r as signObject } from "../proof-BVuILGqP.mjs";
16
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-C59Y-Xd7.mjs";
17
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-CGWGFEsa.mjs";
18
+ import { t as doesActorOwnKey } from "../owner-BPbxcXKO.mjs";
19
+ import { i as verifyObject, r as signObject } from "../proof-DZzDbN7h.mjs";
20
20
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
21
- import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-Cf0dFqr9.mjs";
21
+ import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-C5Z86Ykr.mjs";
22
22
  import { t as CircuitBreaker } from "../circuit-breaker-DLS_n1x5.mjs";
23
23
  import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-BVnv3T76.mjs";
24
24
  import { configure, reset } from "@logtape/logtape";
@@ -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-DZf3vcun.cjs");
5
+ const require_middleware = require("../middleware-D_uFaE6o.cjs");
6
6
  let _logtape_logtape = require("@logtape/logtape");
7
7
  let _fedify_uri_template = require("@fedify/uri-template");
8
8
  let es_toolkit = require("es-toolkit");
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as SendActivityError, c as buildCollectionSynchronizationHeader, d as normalizeCircuitBreakerOptions, f as parseCircuitBreakerKvState, i as createExponentialBackoffPolicy, l as digest, o as respondWithObject, p as createFederationBuilder, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as CircuitBreaker } from "../middleware-BEhF8uxY.js";
3
+ import { a as SendActivityError, c as buildCollectionSynchronizationHeader, d as normalizeCircuitBreakerOptions, f as parseCircuitBreakerKvState, i as createExponentialBackoffPolicy, l as digest, o as respondWithObject, p as createFederationBuilder, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as CircuitBreaker } from "../middleware-yhZdg6HS.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Router as Router$1, RouterError as RouterError$1, assertPath, isPath } from "@fedify/uri-template";
6
6
  import { isEqual } from "es-toolkit";
@@ -8,10 +8,10 @@ import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from
8
8
  import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
9
9
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
10
10
  import { t as assert } from "../assert-OguE97r2.mjs";
11
- import { l as verifyRequest } from "../http-BaUm6xbz.mjs";
11
+ import { l as verifyRequest } from "../http-DUzPFiJs.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-C7h5_D1P.mjs";
14
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-7kSXrsl4.mjs";
13
+ import { t as doesActorOwnKey } from "../owner-BPbxcXKO.mjs";
14
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CD7M4Uyd.mjs";
15
15
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
16
16
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
17
17
  import { FetchError } from "@fedify/vocab-runtime";
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import "../std__assert-BBjXFNOb.mjs";
5
5
  import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
6
6
  import { t as assert } from "../assert-OguE97r2.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-D3Bspq6d.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-CIrD6Oq3.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 () => {
@@ -6,7 +6,7 @@ import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
6
6
  import "../std__assert-BBjXFNOb.mjs";
7
7
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-Cf0dFqr9.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-C5Z86Ykr.mjs";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  import { createTestMeterProvider, test } from "@fedify/fixture";
12
12
  //#region src/federation/webfinger.test.ts
@@ -258,7 +258,7 @@ test("handleWebFinger()", async (t) => {
258
258
  });
259
259
  onNotFoundCalled = null;
260
260
  const actorHandleMapper = (_ctx, username) => {
261
- return username === "foo" ? "someone" : username === "bar" ? "someone2" : null;
261
+ return username === "foo" ? "someone" : username === "bar" ? "someone2" : username === "qux" ? "someone2" : null;
262
262
  };
263
263
  await t.step("handle mapper", async () => {
264
264
  const u = new URL(url);
@@ -381,21 +381,83 @@ test("handleWebFinger()", async (t) => {
381
381
  assertEquals(response.status, 404);
382
382
  });
383
383
  await t.step("handleHost", async () => {
384
- const u = new URL(url);
385
- u.searchParams.set("resource", "acct:someone@example.com");
384
+ let u = new URL("https://ap.example.com/.well-known/webfinger");
385
+ u.searchParams.set("resource", "acct:someone@ap.example.com");
386
386
  let context = createContext(u);
387
387
  let request = context.request;
388
388
  let response = await handleWebFinger(request, {
389
389
  context,
390
- host: "handle.example.com",
390
+ host: "example.com",
391
391
  actorDispatcher,
392
392
  onNotFound
393
393
  });
394
394
  assertEquals(response.status, 200);
395
395
  assertEquals(await response.json(), {
396
- ...expected,
397
- aliases: [...expected.aliases, "acct:someone@handle.example.com"]
396
+ subject: "acct:someone@example.com",
397
+ aliases: ["https://ap.example.com/users/someone", "acct:someone@ap.example.com"],
398
+ links: [
399
+ {
400
+ href: "https://ap.example.com/users/someone",
401
+ rel: "self",
402
+ type: "application/activity+json"
403
+ },
404
+ {
405
+ href: "https://ap.example.com/@someone",
406
+ rel: "http://webfinger.net/rel/profile-page"
407
+ },
408
+ {
409
+ href: "https://ap.example.com/@someone",
410
+ rel: "alternate",
411
+ type: "text/html"
412
+ },
413
+ {
414
+ href: "https://ap.example.com/icon.jpg",
415
+ rel: "http://webfinger.net/rel/avatar",
416
+ type: "image/jpeg"
417
+ }
418
+ ]
419
+ });
420
+ u.searchParams.set("resource", "acct:qux@ap.example.com");
421
+ context = createContext(u);
422
+ request = context.request;
423
+ response = await handleWebFinger(request, {
424
+ context,
425
+ host: "example.com",
426
+ actorDispatcher,
427
+ actorHandleMapper,
428
+ onNotFound
398
429
  });
430
+ assertEquals(response.status, 200);
431
+ assertEquals(await response.json(), {
432
+ subject: "acct:bar@example.com",
433
+ aliases: [
434
+ "https://ap.example.com/users/someone2",
435
+ "acct:qux@ap.example.com",
436
+ "acct:bar@ap.example.com"
437
+ ],
438
+ links: [
439
+ {
440
+ href: "https://ap.example.com/users/someone2",
441
+ rel: "self",
442
+ type: "application/activity+json"
443
+ },
444
+ {
445
+ href: "https://ap.example.com/@someone2",
446
+ rel: "http://webfinger.net/rel/profile-page"
447
+ },
448
+ {
449
+ href: "https://ap.example.com/@someone2",
450
+ rel: "alternate",
451
+ type: "text/html"
452
+ },
453
+ {
454
+ href: "https://ap.example.com/icon.jpg",
455
+ rel: "http://webfinger.net/rel/avatar",
456
+ type: "image/jpeg"
457
+ }
458
+ ]
459
+ });
460
+ u = new URL(url);
399
461
  u.searchParams.set("resource", "acct:someone@handle.example.com");
400
462
  context = createContext(u);
401
463
  request = context.request;
@@ -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.3.2-dev.1556+3e14f2d7";
13
+ var version = "2.3.3";
14
14
  //#endregion
15
15
  //#region src/sig/accept.ts
16
16
  /**
@@ -1,10 +1,10 @@
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-Bg8I1L40.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CmX7KEfY.mjs";
4
+ import { n as version, t as name } from "./deno-CLDlEM_h.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-BgfLGIG9.mjs";
6
6
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPkZzmGN.mjs";
7
- import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-DOnwUeY9.mjs";
7
+ import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-C4wPbyOr.mjs";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { CryptographicKey } from "@fedify/vocab";
10
10
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -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.3.2-dev.1556+3e14f2d7";
14
+ var version = "2.3.3";
15
15
  //#endregion
16
16
  //#region src/sig/accept.ts
17
17
  /**
@@ -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-Bg8I1L40.mjs";
5
- import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-CmX7KEfY.mjs";
4
+ import { n as version, t as name } from "./deno-CLDlEM_h.mjs";
5
+ import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-BgfLGIG9.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
@@ -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-y8Cigpuq.cjs");
4
+ const require_http = require("./http-wDQjTxaL.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,7 +1,7 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { p as recordDocumentCache } from "./metrics-CmX7KEfY.mjs";
4
+ import { p as recordDocumentCache } from "./metrics-BgfLGIG9.mjs";
5
5
  import { getLogger } from "@logtape/logtape";
6
6
  import { preloadedContexts } from "@fedify/vocab-runtime";
7
7
  //#region src/utils/kv-cache.ts
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-Bw8wN_Uk.js";
3
+ import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-B7kkm6X3.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,9 +1,9 @@
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-Bg8I1L40.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CmX7KEfY.mjs";
6
- import { n as fetchKey, o as validateCryptoKey } from "./key-DOnwUeY9.mjs";
4
+ import { n as version, t as name } from "./deno-CLDlEM_h.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-BgfLGIG9.mjs";
6
+ import { n as fetchKey, o as validateCryptoKey } from "./key-C4wPbyOr.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
9
9
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -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-Bg8I1L40.mjs";
4
+ import { n as version, t as name } from "./deno-CLDlEM_h.mjs";
5
5
  import { metrics } from "@opentelemetry/api";
6
6
  import { FetchError } from "@fedify/vocab-runtime";
7
7
  //#region src/federation/metrics.ts