@fedify/fedify 2.2.0-pr.710.22 → 2.2.0-pr.710.26

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 (46) hide show
  1. package/dist/{builder-bnytmADH.mjs → builder-BG2fljmM.mjs} +2 -2
  2. package/dist/compat/public-audience.test.mjs +19 -3
  3. package/dist/compat/transformers.test.mjs +1 -1
  4. package/dist/{deno-sxAmy69e.mjs → deno-Bg4eBr2D.mjs} +1 -1
  5. package/dist/{docloader-CAcGw6pQ.mjs → docloader-DNzzLpZS.mjs} +2 -2
  6. package/dist/federation/builder.test.mjs +1 -1
  7. package/dist/federation/handler.test.mjs +2 -2
  8. package/dist/federation/idempotency.test.mjs +2 -2
  9. package/dist/federation/middleware.test.mjs +6 -6
  10. package/dist/federation/mod.cjs +1 -1
  11. package/dist/federation/mod.js +1 -1
  12. package/dist/federation/send.test.mjs +3 -3
  13. package/dist/federation/webfinger.test.mjs +1 -1
  14. package/dist/{http-DI4R9CTK.js → http-Cbg9qm41.js} +1 -1
  15. package/dist/{http-BKrXOLjL.mjs → http-DWkREdt7.mjs} +2 -2
  16. package/dist/{http-C1BAaJ_m.cjs → http-Dgit35mk.cjs} +1 -1
  17. package/dist/{key-CwG1d1a2.mjs → key-DkuUQiqs.mjs} +1 -1
  18. package/dist/{kv-cache-BQS2P8gv.js → kv-cache-Bl6yhpBL.js} +1 -1
  19. package/dist/{kv-cache-p33MTfBu.cjs → kv-cache-e9fvIFDA.cjs} +1 -1
  20. package/dist/{ld-t2WD3nYp.mjs → ld-1klZemqw.mjs} +2 -2
  21. package/dist/{middleware-D545J7x8.mjs → middleware-BDpu1OCd.mjs} +1 -1
  22. package/dist/{middleware-D8r5yKV-.mjs → middleware-D1zxydrX.mjs} +10 -10
  23. package/dist/{middleware-RhsXBX0y.js → middleware-DRNKgUtw.js} +3 -3
  24. package/dist/{middleware-C4JOTHSG.cjs → middleware-DY-mzSrv.cjs} +1 -1
  25. package/dist/{middleware-cGUpoNb_.cjs → middleware-G6DmtY5H.cjs} +4 -4
  26. package/dist/mod.cjs +4 -4
  27. package/dist/mod.js +4 -4
  28. package/dist/nodeinfo/handler.test.mjs +1 -1
  29. package/dist/{owner-J1wYUBAp.mjs → owner-ijaWLw_K.mjs} +2 -2
  30. package/dist/{proof-DngAmXc3.mjs → proof-BbfBQytm.mjs} +3 -3
  31. package/dist/{proof-0fe_hpBU.cjs → proof-CP0GRqWY.cjs} +3 -3
  32. package/dist/{proof-DJiXN7Qc.js → proof-CQJHVvjQ.js} +3 -3
  33. package/dist/{public-audience-5WWE-JTr.mjs → public-audience-eovWqzOF.mjs} +2 -2
  34. package/dist/{send-CCwbKHXy.mjs → send-CJyp2e8W.mjs} +2 -2
  35. package/dist/sig/http.test.mjs +2 -2
  36. package/dist/sig/key.test.mjs +1 -1
  37. package/dist/sig/ld.test.mjs +2 -2
  38. package/dist/sig/mod.cjs +2 -2
  39. package/dist/sig/mod.js +2 -2
  40. package/dist/sig/owner.test.mjs +1 -1
  41. package/dist/sig/proof.test.mjs +2 -2
  42. package/dist/utils/docloader.test.mjs +2 -2
  43. package/dist/utils/mod.cjs +1 -1
  44. package/dist/utils/mod.js +1 -1
  45. package/package.json +16 -7
  46. package/skills/fedify/SKILL.md +462 -0
@@ -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-sxAmy69e.mjs";
5
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
6
6
  import { t as ActivityListenerSet } from "./activity-listener-CFzUqoCS.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-D545J7x8.mjs");
61
+ const { FederationImpl } = await import("./middleware-BDpu1OCd.mjs");
62
62
  const f = new FederationImpl(options);
63
63
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
64
64
  f.router = this.router.clone();
@@ -3,23 +3,29 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { t as assertNotEquals } from "../assert_not_equals--wG9hV7u.mjs";
6
- import { t as normalizePublicAudience } from "../public-audience-5WWE-JTr.mjs";
6
+ import { t as normalizePublicAudience } from "../public-audience-eovWqzOF.mjs";
7
7
  import { test } from "@fedify/fixture";
8
8
  import { Create, Note, PUBLIC_COLLECTION } from "@fedify/vocab";
9
9
  import { getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
10
10
  //#region src/compat/public-audience.test.ts
11
11
  const PUBLIC_URI = PUBLIC_COLLECTION.href;
12
12
  const AS_CONTEXT = "https://www.w3.org/ns/activitystreams";
13
- test("normalizePublicAudience() rewrites as:Public in addressing fields", async () => {
13
+ test("normalizePublicAudience() rewrites every addressing field and both CURIE forms", async () => {
14
14
  const output = await normalizePublicAudience({
15
15
  "@context": AS_CONTEXT,
16
16
  type: "Note",
17
17
  id: "https://example.com/notes/1",
18
18
  to: "as:Public",
19
- cc: ["as:Public", "https://example.com/bob"]
19
+ cc: ["as:Public", "https://example.com/bob"],
20
+ bto: "Public",
21
+ bcc: ["Public"],
22
+ audience: ["as:Public", "Public"]
20
23
  });
21
24
  assertEquals(output.to, PUBLIC_URI);
22
25
  assertEquals(output.cc, [PUBLIC_URI, "https://example.com/bob"]);
26
+ assertEquals(output.bto, PUBLIC_URI);
27
+ assertEquals(output.bcc, [PUBLIC_URI]);
28
+ assertEquals(output.audience, [PUBLIC_URI, PUBLIC_URI]);
23
29
  });
24
30
  test("normalizePublicAudience() normalises activities serialized by @fedify/vocab", async () => {
25
31
  const compact = await new Create({
@@ -122,6 +128,16 @@ test("normalizePublicAudience() stops before blowing the stack on pathological n
122
128
  object: deep
123
129
  }), "object");
124
130
  });
131
+ test("normalizePublicAudience() does not poison the global prototype via a __proto__ key", async () => {
132
+ await normalizePublicAudience(JSON.parse(`{
133
+ "@context": "https://www.w3.org/ns/activitystreams",
134
+ "type": "Note",
135
+ "id": "https://example.com/notes/proto-pollution",
136
+ "to": "as:Public",
137
+ "__proto__": { "polluted": true }
138
+ }`));
139
+ assertEquals(Object.prototype.polluted, void 0);
140
+ });
125
141
  test("normalizePublicAudience() bails out on nested @context that redefines as:", async () => {
126
142
  const output = await normalizePublicAudience({
127
143
  "@context": AS_CONTEXT,
@@ -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-ddO5KLpe.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
8
- import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-D8r5yKV-.mjs";
8
+ import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-D1zxydrX.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.0-pr.710.22+527afb16";
6
+ var version = "2.2.0-pr.710.26+a95be522";
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-CwG1d1a2.mjs";
5
- import { n as doubleKnock } from "./http-BKrXOLjL.mjs";
4
+ import { o as validateCryptoKey } from "./key-DkuUQiqs.mjs";
5
+ import { n as doubleKnock } from "./http-DWkREdt7.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 { a as assertExists } from "../std__assert-Duiq_YC9.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
9
- import { n as createFederationBuilder } from "../builder-bnytmADH.mjs";
9
+ import { n as createFederationBuilder } from "../builder-BG2fljmM.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
@@ -7,10 +7,10 @@ import "../std__assert-Duiq_YC9.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-ddO5KLpe.mjs";
9
9
  import { r as parseAcceptSignature } from "../accept-Dd__NiUL.mjs";
10
- import { s as signRequest } from "../http-BKrXOLjL.mjs";
10
+ import { s as signRequest } from "../http-DWkREdt7.mjs";
11
11
  import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
12
12
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
13
- 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-D8r5yKV-.mjs";
13
+ 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-D1zxydrX.mjs";
14
14
  import { t as ActivityListenerSet } from "../activity-listener-CFzUqoCS.mjs";
15
15
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
16
16
  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-Duiq_YC9.mjs";
6
6
  import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
7
- import { r as signObject } from "../proof-DngAmXc3.mjs";
7
+ import { r as signObject } from "../proof-BbfBQytm.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
9
- import { o as createFederation } from "../middleware-D8r5yKV-.mjs";
9
+ import { o as createFederation } from "../middleware-D1zxydrX.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
@@ -10,14 +10,14 @@ import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
10
10
  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 assert } from "../assert-ddO5KLpe.mjs";
13
- import { l as verifyRequest, s as signRequest } from "../http-BKrXOLjL.mjs";
13
+ import { l as verifyRequest, s as signRequest } from "../http-DWkREdt7.mjs";
14
14
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
15
- import { t as getAuthenticatedDocumentLoader } from "../docloader-CAcGw6pQ.mjs";
16
- import { a as signJsonLd, o as verifyJsonLd, r as detachSignature } from "../ld-t2WD3nYp.mjs";
17
- import { t as doesActorOwnKey } from "../owner-J1wYUBAp.mjs";
18
- import { i as verifyObject, r as signObject } from "../proof-DngAmXc3.mjs";
15
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-DNzzLpZS.mjs";
16
+ import { a as signJsonLd, o as verifyJsonLd, r as detachSignature } from "../ld-1klZemqw.mjs";
17
+ import { t as doesActorOwnKey } from "../owner-ijaWLw_K.mjs";
18
+ import { i as verifyObject, r as signObject } from "../proof-BbfBQytm.mjs";
19
19
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
20
- import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-D8r5yKV-.mjs";
20
+ import { i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-D1zxydrX.mjs";
21
21
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
22
22
  import * as vocab from "@fedify/vocab";
23
23
  import { 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-cGUpoNb_.cjs");
5
+ const require_middleware = require("../middleware-G6DmtY5H.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-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-RhsXBX0y.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-DRNKgUtw.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-ddO5KLpe.mjs";
11
- import { l as verifyRequest } from "../http-BKrXOLjL.mjs";
11
+ import { l as verifyRequest } from "../http-DWkREdt7.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
13
- import { t as doesActorOwnKey } from "../owner-J1wYUBAp.mjs";
14
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CCwbKHXy.mjs";
13
+ import { t as doesActorOwnKey } from "../owner-ijaWLw_K.mjs";
14
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CJyp2e8W.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
@@ -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-Duiq_YC9.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
8
- import { o as createFederation, s as handleWebFinger } from "../middleware-D8r5yKV-.mjs";
8
+ import { o as createFederation, s as handleWebFinger } from "../middleware-D1zxydrX.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
@@ -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.0-pr.710.22+527afb16";
13
+ var version = "2.2.0-pr.710.26+a95be522";
14
14
  //#endregion
15
15
  //#region src/sig/accept.ts
16
16
  /**
@@ -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-sxAmy69e.mjs";
4
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
5
5
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-Dd__NiUL.mjs";
6
- import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-CwG1d1a2.mjs";
6
+ import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-DkuUQiqs.mjs";
7
7
  import { CryptographicKey } from "@fedify/vocab";
8
8
  import { SpanStatusCode, trace } from "@opentelemetry/api";
9
9
  import { FetchError } from "@fedify/vocab-runtime";
@@ -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.0-pr.710.22+527afb16";
14
+ var version = "2.2.0-pr.710.26+a95be522";
15
15
  //#endregion
16
16
  //#region src/sig/accept.ts
17
17
  /**
@@ -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-sxAmy69e.mjs";
4
+ import { n as version, t as name } from "./deno-Bg4eBr2D.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";
@@ -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-DI4R9CTK.js";
3
+ import { d as validateCryptoKey, t as doubleKnock } from "./http-Cbg9qm41.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,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-C1BAaJ_m.cjs");
4
+ const require_http = require("./http-Dgit35mk.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,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-sxAmy69e.mjs";
5
- import { n as fetchKey, o as validateCryptoKey } from "./key-CwG1d1a2.mjs";
4
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
5
+ import { n as fetchKey, o as validateCryptoKey } from "./key-DkuUQiqs.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";
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as FederationImpl } from "./middleware-D8r5yKV-.mjs";
4
+ import { n as FederationImpl } from "./middleware-D1zxydrX.mjs";
5
5
  export { FederationImpl };
@@ -2,24 +2,24 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { n as RouterError } from "./router-CrMLXoOr.mjs";
5
- import { n as version, t as name } from "./deno-sxAmy69e.mjs";
5
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-Dd__NiUL.mjs";
7
- import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-CwG1d1a2.mjs";
8
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-BKrXOLjL.mjs";
9
- import { t as getAuthenticatedDocumentLoader } from "./docloader-CAcGw6pQ.mjs";
7
+ import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-DkuUQiqs.mjs";
8
+ import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-DWkREdt7.mjs";
9
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-DNzzLpZS.mjs";
10
10
  import { n as kvCache } from "./kv-cache-B01V7s3h.mjs";
11
- import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-t2WD3nYp.mjs";
12
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-J1wYUBAp.mjs";
13
- import { t as normalizePublicAudience } from "./public-audience-5WWE-JTr.mjs";
14
- import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-DngAmXc3.mjs";
11
+ import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-1klZemqw.mjs";
12
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-ijaWLw_K.mjs";
13
+ import { t as normalizePublicAudience } from "./public-audience-eovWqzOF.mjs";
14
+ import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-BbfBQytm.mjs";
15
15
  import { t as getNodeInfo } from "./client-DVu6Fmom.mjs";
16
16
  import { t as nodeInfoToJson } from "./types-CGUnLkU3.mjs";
17
- import { t as FederationBuilderImpl } from "./builder-bnytmADH.mjs";
17
+ import { t as FederationBuilderImpl } from "./builder-BG2fljmM.mjs";
18
18
  import { t as buildCollectionSynchronizationHeader } from "./collection-BQRKGS7L.mjs";
19
19
  import { t as KvKeyCache } from "./keycache-C2t1kvP5.mjs";
20
20
  import { t as acceptsJsonLd } from "./negotiation-xb0QR3u_.mjs";
21
21
  import { t as createExponentialBackoffPolicy } from "./retry-CJL0poaU.mjs";
22
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CCwbKHXy.mjs";
22
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CJyp2e8W.mjs";
23
23
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
24
24
  import { lookupWebFinger } from "@fedify/webfinger";
25
25
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -2,10 +2,10 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  import { t as __exportAll } from "./chunk-nlSIicah.js";
4
4
  import { r as getDefaultActivityTransformers } from "./transformers-ve6e2xcg.js";
5
- import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-DI4R9CTK.js";
6
- import { c as getKeyOwner, d as detachSignature, f as hasSignatureLike, i as verifyObject, m as verifyJsonLd, n as hasProofLike, o as normalizePublicAudience, p as signJsonLd, r as signObject, s as doesActorOwnKey } from "./proof-DJiXN7Qc.js";
5
+ import { _ as version, a as verifyRequestDetailed, d as validateCryptoKey, f as formatAcceptSignature, g as name, i as verifyRequest, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, u as importJwk } from "./http-Cbg9qm41.js";
6
+ import { c as getKeyOwner, d as detachSignature, f as hasSignatureLike, i as verifyObject, m as verifyJsonLd, n as hasProofLike, o as normalizePublicAudience, p as signJsonLd, r as signObject, s as doesActorOwnKey } from "./proof-CQJHVvjQ.js";
7
7
  import { n as getNodeInfo, t as nodeInfoToJson } from "./types-hvL8ElAs.js";
8
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BQS2P8gv.js";
8
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-Bl6yhpBL.js";
9
9
  import { getLogger, withContext } from "@logtape/logtape";
10
10
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
11
11
  import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
@@ -1,4 +1,4 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
- const require_middleware = require("./middleware-cGUpoNb_.cjs");
3
+ const require_middleware = require("./middleware-G6DmtY5H.cjs");
4
4
  exports.FederationImpl = require_middleware.FederationImpl;
@@ -2,10 +2,10 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  require("./chunk-DDcVe30Y.cjs");
4
4
  const require_transformers = require("./transformers-NeAONrAq.cjs");
5
- const require_http = require("./http-C1BAaJ_m.cjs");
6
- const require_proof = require("./proof-0fe_hpBU.cjs");
5
+ const require_http = require("./http-Dgit35mk.cjs");
6
+ const require_proof = require("./proof-CP0GRqWY.cjs");
7
7
  const require_types = require("./types-KC4QAoxe.cjs");
8
- const require_kv_cache = require("./kv-cache-p33MTfBu.cjs");
8
+ const require_kv_cache = require("./kv-cache-e9fvIFDA.cjs");
9
9
  let _logtape_logtape = require("@logtape/logtape");
10
10
  let _fedify_vocab = require("@fedify/vocab");
11
11
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -210,7 +210,7 @@ var FederationBuilderImpl = class {
210
210
  this.collectionTypeIds = {};
211
211
  }
212
212
  async build(options) {
213
- const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-C4JOTHSG.cjs"));
213
+ const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-DY-mzSrv.cjs"));
214
214
  const f = new FederationImpl(options);
215
215
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
216
216
  f.router = this.router.clone();
package/dist/mod.cjs CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("./chunk-DDcVe30Y.cjs");
5
5
  const require_transformers = require("./transformers-NeAONrAq.cjs");
6
6
  require("./compat/mod.cjs");
7
- const require_http = require("./http-C1BAaJ_m.cjs");
8
- const require_middleware = require("./middleware-cGUpoNb_.cjs");
9
- const require_proof = require("./proof-0fe_hpBU.cjs");
7
+ const require_http = require("./http-Dgit35mk.cjs");
8
+ const require_middleware = require("./middleware-G6DmtY5H.cjs");
9
+ const require_proof = require("./proof-CP0GRqWY.cjs");
10
10
  const require_types = require("./types-KC4QAoxe.cjs");
11
- const require_kv_cache = require("./kv-cache-p33MTfBu.cjs");
11
+ const require_kv_cache = require("./kv-cache-e9fvIFDA.cjs");
12
12
  const require_federation_mod = require("./federation/mod.cjs");
13
13
  require("./nodeinfo/mod.cjs");
14
14
  require("./runtime/mod.cjs");
package/dist/mod.js CHANGED
@@ -3,11 +3,11 @@ import "urlpattern-polyfill";
3
3
  import "./chunk-nlSIicah.js";
4
4
  import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-ve6e2xcg.js";
5
5
  import "./compat/mod.js";
6
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-DI4R9CTK.js";
7
- 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-RhsXBX0y.js";
8
- import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "./proof-DJiXN7Qc.js";
6
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-Cbg9qm41.js";
7
+ 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-DRNKgUtw.js";
8
+ import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "./proof-CQJHVvjQ.js";
9
9
  import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-hvL8ElAs.js";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BQS2P8gv.js";
10
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-Bl6yhpBL.js";
11
11
  import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue } from "./federation/mod.js";
12
12
  import "./nodeinfo/mod.js";
13
13
  import "./runtime/mod.js";
@@ -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-Duiq_YC9.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-C-TG81Sv.mjs";
8
- import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-D8r5yKV-.mjs";
8
+ import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-D1zxydrX.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/nodeinfo/handler.test.ts
11
11
  test("handleNodeInfo()", async () => {
@@ -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-sxAmy69e.mjs";
5
- import "./key-CwG1d1a2.mjs";
4
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
5
+ import "./key-DkuUQiqs.mjs";
6
6
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
7
7
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
8
8
  import { getDocumentLoader } from "@fedify/vocab-runtime";
@@ -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-sxAmy69e.mjs";
5
- import { n as fetchKey, o as validateCryptoKey } from "./key-CwG1d1a2.mjs";
6
- import { t as normalizePublicAudience } from "./public-audience-5WWE-JTr.mjs";
4
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
5
+ import { n as fetchKey, o as validateCryptoKey } from "./key-DkuUQiqs.mjs";
6
+ import { t as normalizePublicAudience } from "./public-audience-eovWqzOF.mjs";
7
7
  import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
8
8
  import { SpanStatusCode, trace } from "@opentelemetry/api";
9
9
  import { getLogger } from "@logtape/logtape";
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  const require_chunk = require("./chunk-DDcVe30Y.cjs");
4
- const require_http = require("./http-C1BAaJ_m.cjs");
4
+ const require_http = require("./http-Dgit35mk.cjs");
5
5
  let _logtape_logtape = require("@logtape/logtape");
6
6
  let _fedify_vocab = require("@fedify/vocab");
7
7
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -403,7 +403,7 @@ const PUBLIC_ADDRESSING_FIELDS = new Set([
403
403
  "audience"
404
404
  ]);
405
405
  const preloadedOnlyDocumentLoader = (url) => {
406
- if (url in _fedify_vocab_runtime.preloadedContexts) return Promise.resolve({
406
+ if (Object.hasOwn(_fedify_vocab_runtime.preloadedContexts, url)) return Promise.resolve({
407
407
  contextUrl: null,
408
408
  documentUrl: url,
409
409
  document: _fedify_vocab_runtime.preloadedContexts[url]
@@ -440,7 +440,7 @@ function rewritePublicAudience(value, parentKey, depth = 0) {
440
440
  if (typeof value !== "object" || value == null) return value;
441
441
  const record = value;
442
442
  let changed = false;
443
- const normalized = {};
443
+ const normalized = Object.create(null);
444
444
  for (const key of Object.keys(record)) {
445
445
  const rewritten = key === "@context" ? record[key] : rewritePublicAudience(record[key], key, depth + 1);
446
446
  if (rewritten !== record[key]) changed = true;
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-DI4R9CTK.js";
3
+ import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-Cbg9qm41.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, PUBLIC_COLLECTION, getTypeId, isActor } from "@fedify/vocab";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
@@ -400,7 +400,7 @@ const PUBLIC_ADDRESSING_FIELDS = new Set([
400
400
  "audience"
401
401
  ]);
402
402
  const preloadedOnlyDocumentLoader = (url) => {
403
- if (url in preloadedContexts) return Promise.resolve({
403
+ if (Object.hasOwn(preloadedContexts, url)) return Promise.resolve({
404
404
  contextUrl: null,
405
405
  documentUrl: url,
406
406
  document: preloadedContexts[url]
@@ -437,7 +437,7 @@ function rewritePublicAudience(value, parentKey, depth = 0) {
437
437
  if (typeof value !== "object" || value == null) return value;
438
438
  const record = value;
439
439
  let changed = false;
440
- const normalized = {};
440
+ const normalized = Object.create(null);
441
441
  for (const key of Object.keys(record)) {
442
442
  const rewritten = key === "@context" ? record[key] : rewritePublicAudience(record[key], key, depth + 1);
443
443
  if (rewritten !== record[key]) changed = true;
@@ -19,7 +19,7 @@ const PUBLIC_ADDRESSING_FIELDS = new Set([
19
19
  "audience"
20
20
  ]);
21
21
  const preloadedOnlyDocumentLoader = (url) => {
22
- if (url in preloadedContexts) return Promise.resolve({
22
+ if (Object.hasOwn(preloadedContexts, url)) return Promise.resolve({
23
23
  contextUrl: null,
24
24
  documentUrl: url,
25
25
  document: preloadedContexts[url]
@@ -56,7 +56,7 @@ function rewritePublicAudience(value, parentKey, depth = 0) {
56
56
  if (typeof value !== "object" || value == null) return value;
57
57
  const record = value;
58
58
  let changed = false;
59
- const normalized = {};
59
+ const normalized = Object.create(null);
60
60
  for (const key of Object.keys(record)) {
61
61
  const rewritten = key === "@context" ? record[key] : rewritePublicAudience(record[key], key, depth + 1);
62
62
  if (rewritten !== record[key]) changed = true;
@@ -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-sxAmy69e.mjs";
5
- import { n as doubleKnock } from "./http-BKrXOLjL.mjs";
4
+ import { n as version, t as name } from "./deno-Bg4eBr2D.mjs";
5
+ import { n as doubleKnock } from "./http-DWkREdt7.mjs";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  //#region src/federation/send.ts
@@ -7,8 +7,8 @@ import { a as assertExists, t as assertStringIncludes } from "../std__assert-Dui
7
7
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
9
9
  import { t as assert } from "../assert-ddO5KLpe.mjs";
10
- import { t as exportJwk } from "../key-CwG1d1a2.mjs";
11
- import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-BKrXOLjL.mjs";
10
+ import { t as exportJwk } from "../key-DkuUQiqs.mjs";
11
+ import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-DWkREdt7.mjs";
12
12
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
13
13
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-Duiq_YC9.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
- import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-CwG1d1a2.mjs";
8
+ import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-DkuUQiqs.mjs";
9
9
  import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { CryptographicKey, Multikey } from "@fedify/vocab";
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
7
7
  import { t as assert } from "../assert-ddO5KLpe.mjs";
8
- import { i as generateCryptoKeyPair } from "../key-CwG1d1a2.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-DkuUQiqs.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
10
- import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-t2WD3nYp.mjs";
10
+ import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-1klZemqw.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { CryptographicKey } from "@fedify/vocab";
13
13
  import { encodeBase64 } from "byte-encodings/base64";
package/dist/sig/mod.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_http = require("../http-C1BAaJ_m.cjs");
5
- const require_proof = require("../proof-0fe_hpBU.cjs");
4
+ const require_http = require("../http-Dgit35mk.cjs");
5
+ const require_proof = require("../proof-CP0GRqWY.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-DI4R9CTK.js";
4
- import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "../proof-DJiXN7Qc.js";
3
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-Cbg9qm41.js";
4
+ import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "../proof-CQJHVvjQ.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, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import "../std__assert-Duiq_YC9.mjs";
6
6
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assert } from "../assert-ddO5KLpe.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-J1wYUBAp.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-ijaWLw_K.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
12
12
  //#region src/sig/owner.test.ts
@@ -7,8 +7,8 @@ import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-ddO5KLpe.mjs";
9
9
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
10
- import { t as normalizePublicAudience } from "../public-audience-5WWE-JTr.mjs";
11
- import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-DngAmXc3.mjs";
10
+ import { t as normalizePublicAudience } from "../public-audience-eovWqzOF.mjs";
11
+ import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-BbfBQytm.mjs";
12
12
  import { mockDocumentLoader, test } from "@fedify/fixture";
13
13
  import { Create, DataIntegrityProof, Multikey, Note, PUBLIC_COLLECTION, Place } from "@fedify/vocab";
14
14
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
@@ -5,9 +5,9 @@ import { t as esm_default } from "../esm-DVILvP5e.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-Duiq_YC9.mjs";
7
7
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
- import { l as verifyRequest } from "../http-BKrXOLjL.mjs";
8
+ import { l as verifyRequest } from "../http-DWkREdt7.mjs";
9
9
  import { i as rsaPrivateKey2 } from "../keys-BAK-tUlf.mjs";
10
- import { t as getAuthenticatedDocumentLoader } from "../docloader-CAcGw6pQ.mjs";
10
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-DNzzLpZS.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { UrlError } from "@fedify/vocab-runtime";
13
13
  //#region src/utils/docloader.test.ts
@@ -1,6 +1,6 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_kv_cache = require("../kv-cache-p33MTfBu.cjs");
4
+ const require_kv_cache = require("../kv-cache-e9fvIFDA.cjs");
5
5
  exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
6
6
  exports.kvCache = require_kv_cache.kvCache;
package/dist/utils/mod.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-BQS2P8gv.js";
3
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-Bl6yhpBL.js";
4
4
  export { getAuthenticatedDocumentLoader, kvCache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/fedify",
3
- "version": "2.2.0-pr.710.22+527afb16",
3
+ "version": "2.2.0-pr.710.26+a95be522",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",
@@ -32,8 +32,17 @@
32
32
  },
33
33
  "type": "module",
34
34
  "files": [
35
- "dist"
35
+ "dist",
36
+ "skills"
36
37
  ],
38
+ "agents": {
39
+ "skills": [
40
+ {
41
+ "name": "fedify",
42
+ "path": "./skills/fedify"
43
+ }
44
+ ]
45
+ },
37
46
  "module": "./dist/mod.js",
38
47
  "main": "./dist/mod.cjs",
39
48
  "types": "./dist/mod.d.ts",
@@ -144,9 +153,9 @@
144
153
  "uri-template-router": "^1.0.0",
145
154
  "url-template": "^3.1.1",
146
155
  "urlpattern-polyfill": "^10.1.0",
147
- "@fedify/vocab": "2.2.0-pr.710.22+527afb16",
148
- "@fedify/webfinger": "2.2.0-pr.710.22+527afb16",
149
- "@fedify/vocab-runtime": "2.2.0-pr.710.22+527afb16"
156
+ "@fedify/vocab-runtime": "2.2.0-pr.710.26+a95be522",
157
+ "@fedify/webfinger": "2.2.0-pr.710.26+a95be522",
158
+ "@fedify/vocab": "2.2.0-pr.710.26+a95be522"
150
159
  },
151
160
  "devDependencies": {
152
161
  "@std/assert": "npm:@jsr/std__assert@^0.226.0",
@@ -158,8 +167,8 @@
158
167
  "tsx": "^4.19.4",
159
168
  "typescript": "^5.9.2",
160
169
  "wrangler": "^4.17.0",
161
- "@fedify/fixture": "2.0.0",
162
- "@fedify/vocab-tools": "^2.2.0-pr.710.22+527afb16"
170
+ "@fedify/vocab-tools": "^2.2.0-pr.710.26+a95be522",
171
+ "@fedify/fixture": "2.0.0"
163
172
  },
164
173
  "scripts": {
165
174
  "build:self": "tsdown",
@@ -0,0 +1,462 @@
1
+ ---
2
+ name: fedify
3
+ description: >-
4
+ Use this skill whenever writing JavaScript or TypeScript code that uses
5
+ Fedify to build an ActivityPub server, handle federation activities,
6
+ implement fediverse features, or integrate Fedify with a web framework
7
+ such as Hono, Express, Next.js, Nuxt, Fastify, Koa, NestJS, Astro,
8
+ SvelteKit, Fresh, h3, Elysia, or Cloudflare Workers. Covers the
9
+ `Federation` builder pattern, actor/inbox/outbox/collection dispatchers,
10
+ inbox listeners, vocabulary objects from `@fedify/vocab`, key pair
11
+ management, HTTP Signatures, Object Integrity Proofs, the `KvStore` and
12
+ `MessageQueue` interfaces, database adapter packages, structured logging
13
+ with LogTape, OpenTelemetry tracing, the `fedify` CLI toolchain, and
14
+ common mistakes. Also apply when the user mentions ActivityPub,
15
+ federation, fediverse, WebFinger, NodeInfo, FEPs, or Mastodon
16
+ interoperability, even if they do not name Fedify explicitly.
17
+ ---
18
+
19
+ Fedify skill
20
+ ============
21
+
22
+ Fedify is a TypeScript library for ActivityPub server applications. It
23
+ works across Deno, Node.js, and Bun. The library takes care of the fiddly
24
+ parts of the fediverse (HTTP Signatures, Object Integrity Proofs,
25
+ WebFinger, NodeInfo, JSON-LD, delivery queues) so application code can
26
+ stay focused on dispatchers and activity handlers.
27
+
28
+ Always link into the full documentation at <https://fedify.dev/>
29
+ instead of guessing. Every docs page is also served as raw Markdown
30
+ by appending `.md` to its path, so
31
+ <https://fedify.dev/manual/federation.md> returns `text/markdown`.
32
+ This skill uses the `.md` form in every fedify.dev link below so you
33
+ can read the source directly without HTML rendering; when you present
34
+ a link *to the user*, strip the `.md` suffix so browsers render the
35
+ HTML page (so `https://fedify.dev/manual/federation.md` becomes
36
+ `https://fedify.dev/manual/federation`). The index at
37
+ <https://fedify.dev/llms.txt> and the full bundle at
38
+ <https://fedify.dev/llms-full.txt> are authoritative; this skill only
39
+ points the way. Do not invent APIs; verify names against those docs
40
+ or against the installed `@fedify/fedify` types.
41
+
42
+
43
+ Builder pattern
44
+ ---------------
45
+
46
+ Two entry points reach a `Federation<TContextData>` object:
47
+
48
+ - `createFederationBuilder<TContextData>()` returns a
49
+ `FederationBuilder<TContextData>`. Register dispatchers and
50
+ listeners on it, then `await builder.build(options)` to obtain the
51
+ `Federation<TContextData>`. Prefer this in larger apps, especially
52
+ when you need to split configuration across files or avoid circular
53
+ imports. In serverless runtimes such as Cloudflare Workers,
54
+ bindings are only available per-request, so the `Federation` must be
55
+ constructed inside the request handler; the builder pattern is the
56
+ documented approach there because dispatcher registration can happen
57
+ at module load time and only the asynchronous `.build(options)` call
58
+ runs per request.
59
+ - `createFederation<TContextData>(options)` returns a
60
+ `Federation<TContextData>` directly. Appropriate when everything
61
+ fits in one module.
62
+
63
+ `.build()` is asynchronous; always `await` it. See
64
+ <https://fedify.dev/manual/federation.md>.
65
+
66
+ ~~~~ typescript
67
+ import { createFederationBuilder, MemoryKvStore } from "@fedify/fedify";
68
+
69
+ const builder = createFederationBuilder<AppState>();
70
+ // ...register dispatchers on builder...
71
+ export const federation = await builder.build({
72
+ kv: new MemoryKvStore(), // development only
73
+ });
74
+ ~~~~
75
+
76
+ > [!IMPORTANT]
77
+ > Production deployments *must* provide a real `queue` implementation.
78
+ > Without one, outgoing activities are sent synchronously and delivery
79
+ > becomes unreliable under load. See
80
+ > <https://fedify.dev/manual/federation.md>.
81
+
82
+ > [!WARNING]
83
+ > Never set `allowPrivateAddress: true` outside tests. It disables the
84
+ > SSRF guard that blocks Fedify from fetching private or loopback
85
+ > addresses. See <https://fedify.dev/manual/federation.md> and
86
+ > <https://fedify.dev/manual/deploy.md>.
87
+
88
+
89
+ Dispatchers
90
+ -----------
91
+
92
+ Every route Fedify serves is driven by a dispatcher callback registered on
93
+ the builder (or `Federation` object). Do not hand-roll these routes in
94
+ the web framework; the dispatcher signatures encode the library's URI
95
+ template guarantees.
96
+
97
+ - `setActorDispatcher(path, dispatcher)`: returns an
98
+ `ActorCallbackSetters` chain that also carries
99
+ `setKeyPairsDispatcher()`.
100
+ - `setObjectDispatcher(type, path, dispatcher)`: for individual
101
+ `Object` types such as `Note` or `Article`.
102
+ - `setInboxDispatcher(path, dispatcher)`: the inbox *collection*
103
+ endpoint. The inbox *listener* is a different API (see below).
104
+ - `setOutboxDispatcher(path, dispatcher)`.
105
+ - `setFollowingDispatcher(path, dispatcher)` /
106
+ `setFollowersDispatcher(path, dispatcher)` /
107
+ `setLikedDispatcher(path, dispatcher)` /
108
+ `setFeaturedDispatcher(path, dispatcher)` /
109
+ `setFeaturedTagsDispatcher(path, dispatcher)`.
110
+ - `setCollectionDispatcher()` and `setOrderedCollectionDispatcher()`
111
+ for custom collections.
112
+ - `setNodeInfoDispatcher(path, dispatcher)` and
113
+ `setWebFingerLinksDispatcher(dispatcher)` for protocol endpoints.
114
+
115
+ Paths use URI templates. If an identifier can contain URI characters,
116
+ switch the template variable from `{identifier}` to `{+identifier}` to
117
+ avoid double-encoding. See <https://fedify.dev/manual/uri-template.md>.
118
+
119
+ > [!WARNING]
120
+ > Simple expansion (`{identifier}`) percent-encodes reserved characters a
121
+ > second time. If actors or objects are keyed by URIs, use reserved
122
+ > expansion (`{+identifier}`).
123
+
124
+ See <https://fedify.dev/manual/actor.md>,
125
+ <https://fedify.dev/manual/object.md>, and
126
+ <https://fedify.dev/manual/collections.md>.
127
+
128
+
129
+ Inbox listeners
130
+ ---------------
131
+
132
+ `setInboxListeners(inboxPath, sharedInboxPath?)` returns an
133
+ `InboxListenerSetters` object with:
134
+
135
+ - `.on(ActivityType, handler)`: chainable, keyed by the *class*
136
+ (`Follow`, `Create`, `Undo`, etc.).
137
+ - `.onError(handler)`.
138
+ - `.onUnverifiedActivity(handler)`.
139
+ - `.setSharedKeyDispatcher(dispatcher)`.
140
+ - `.withIdempotency(strategy)`.
141
+
142
+ > [!WARNING]
143
+ > Activities of a type that is not registered via `.on()` are answered
144
+ > with HTTP 202 and logged at error level as an unsupported activity,
145
+ > but never reach a listener. To catch everything, register a listener
146
+ > for the base `Activity` class.
147
+
148
+ See <https://fedify.dev/manual/inbox.md>.
149
+
150
+
151
+ Context and `TContextData`
152
+ --------------------------
153
+
154
+ `Context<TContextData>` is the per-operation handle Fedify passes to
155
+ dispatchers and listeners. The `TContextData` generic carries
156
+ application state (database handles, request id, auth session). Treat it
157
+ as the single place to inject dependencies; do not reach for module-level
158
+ singletons inside handlers.
159
+
160
+ `RequestContext<TContextData>` extends `Context<TContextData>` with
161
+ request-scoped helpers.
162
+
163
+ Use `ctx.get…Uri()` helpers (for example `ctx.getActorUri(identifier)`)
164
+ to build canonical URIs instead of string-concatenating paths.
165
+
166
+ > [!CAUTION]
167
+ > The `crossOrigin: "trust"` option on context methods and on vocabulary
168
+ > dereferencing disables the same-origin check. Only use it when the
169
+ > remote document is known to be trustworthy; it was the source of
170
+ > prior interop bugs.
171
+
172
+ See <https://fedify.dev/manual/context.md> and
173
+ <https://fedify.dev/manual/context-advanced.md>.
174
+
175
+
176
+ Framework integrations
177
+ ----------------------
178
+
179
+ Mount Fedify through the dedicated integration package for the target
180
+ framework. Do not translate requests manually; the integration handles
181
+ content negotiation, signature verification, and response streaming.
182
+
183
+ | Framework | Package |
184
+ | ------------------ | -------------------- |
185
+ | Astro | *@fedify/astro* |
186
+ | Cloudflare Workers | *@fedify/cfworkers* |
187
+ | Elysia | *@fedify/elysia* |
188
+ | Express | *@fedify/express* |
189
+ | Fastify | *@fedify/fastify* |
190
+ | Fresh | *@fedify/fresh* |
191
+ | h3 | *@fedify/h3* |
192
+ | Hono | *@fedify/hono* |
193
+ | Koa | *@fedify/koa* |
194
+ | NestJS | *@fedify/nestjs* |
195
+ | Next.js | *@fedify/next* |
196
+ | Nuxt | *@fedify/nuxt* |
197
+ | SolidStart | *@fedify/solidstart* |
198
+ | SvelteKit | *@fedify/sveltekit* |
199
+
200
+ Two more packages are frequently useful: *@fedify/debugger* for a local
201
+ ActivityPub dashboard, and *@fedify/relay* for relay implementations.
202
+
203
+ See <https://fedify.dev/manual/integration.md>.
204
+
205
+
206
+ Built-in protocol endpoints
207
+ ---------------------------
208
+
209
+ Fedify serves these endpoints automatically as soon as the federation
210
+ handler is mounted; do not reimplement them.
211
+
212
+ - `/.well-known/webfinger` (WebFinger). Customize link output with
213
+ `setWebFingerLinksDispatcher()`. See
214
+ <https://fedify.dev/manual/webfinger.md>.
215
+ - `/.well-known/nodeinfo` and the versioned NodeInfo document.
216
+ Customize with `setNodeInfoDispatcher()`. See
217
+ <https://fedify.dev/manual/nodeinfo.md>.
218
+
219
+
220
+ Outgoing activities
221
+ -------------------
222
+
223
+ `ctx.sendActivity(sender, recipients, activity, options?)` is the single
224
+ entry point for outbound delivery. Two overloads:
225
+
226
+ - Explicit recipients: pass a single `Recipient` or an array. The
227
+ `sender` may be a `SenderKeyPair`, a `SenderKeyPair[]`, or
228
+ `{ identifier }` / `{ username }`.
229
+ - Fan-out: pass the literal `"followers"` to deliver to the sender's
230
+ `Followers` collection. In this overload the `sender` must be
231
+ `{ identifier }` or `{ username }`; a raw `SenderKeyPair` or
232
+ `SenderKeyPair[]` is rejected because Fedify needs the actor
233
+ identifier to resolve the followers collection.
234
+
235
+ Always route outbound activities through the queue in production; this is
236
+ the same `queue` provided to `createFederation()` or `.build()`. Without
237
+ a queue the call blocks until every recipient responds and failed
238
+ deliveries have no retry.
239
+
240
+ > [!CAUTION]
241
+ > Do not derive an activity's `id` from `(actor, object)`. The same
242
+ > actor can send the same activity shape to the same object more than
243
+ > once (for example `Follow` → `Undo(Follow)` → `Follow` again), and
244
+ > those must be distinct activities. Use a fresh UUID or counter in the
245
+ > fragment.
246
+
247
+ See <https://fedify.dev/manual/send.md>.
248
+
249
+
250
+ Vocabulary imports
251
+ ------------------
252
+
253
+ Import ActivityStreams and ActivityPub vocabulary types from
254
+ `@fedify/vocab`. The historical path `@fedify/fedify/vocab` is a
255
+ deprecated shim kept for backwards compatibility; new code should not use
256
+ it. Likewise, `@fedify/vocab-runtime` replaces the old
257
+ `@fedify/fedify/runtime` path, and `@fedify/webfinger` replaces the old
258
+ in-tree *src/webfinger*.
259
+
260
+ > [!CAUTION]
261
+ > Several vocabulary classes collide with JavaScript globals (notably
262
+ > `Object`). When importing, either use a namespace import
263
+ > (`import * as vocab from "@fedify/vocab"`) or alias the individual
264
+ > class.
265
+
266
+ `fromJsonLd()` and `toJsonLd()` are asynchronous; always `await` them.
267
+
268
+ > [!WARNING]
269
+ > `crossOrigin: "trust"` on vocabulary deserialization trusts embedded
270
+ > objects without re-fetching. Treat it as you would
271
+ > `dangerouslySetInnerHTML`.
272
+
273
+ See <https://fedify.dev/manual/vocab.md>.
274
+
275
+
276
+ Key pair management
277
+ -------------------
278
+
279
+ `setActorDispatcher(...).setKeyPairsDispatcher(dispatcher)` supplies the
280
+ actor's key pairs. Return *two* keys per actor:
281
+
282
+ - An RSA-PKCS#1-v1.5 key for HTTP Signatures (Mastodon interop).
283
+ - An Ed25519 key for FEP-8b32 Object Integrity Proofs.
284
+
285
+ Fedify signs outbound activities with whatever keys are available; for
286
+ interop with the widest set of peers, provide both.
287
+
288
+ > [!WARNING]
289
+ > Private keys must live in secret storage. They are not configuration;
290
+ > do not check them into repositories, embed them in container images,
291
+ > or expose them via admin endpoints.
292
+
293
+ See <https://fedify.dev/manual/actor.md>.
294
+
295
+
296
+ Persistent storage
297
+ ------------------
298
+
299
+ Fedify defines two storage interfaces: `KvStore` (key/value cache and
300
+ idempotence) and `MessageQueue` (delivery plus inbox processing), both
301
+ re-exported from `@fedify/fedify`. Use the built-in `MemoryKvStore` only
302
+ in development or tests.
303
+
304
+ | Package | `KvStore` | `MessageQueue` |
305
+ | ------------------- | --------- | -------------- |
306
+ | *@fedify/sqlite* | yes | yes |
307
+ | *@fedify/postgres* | yes | yes |
308
+ | *@fedify/mysql* | yes | yes |
309
+ | *@fedify/redis* | yes | yes |
310
+ | *@fedify/amqp* | no | yes |
311
+ | *@fedify/denokv* | yes | yes |
312
+ | *@fedify/cfworkers* | yes | yes |
313
+
314
+ > [!WARNING]
315
+ > `PostgresMessageQueue` and similar implementations require connection
316
+ > pooling sized for parallel consumers; a single shared connection will
317
+ > deadlock under `ParallelMessageQueue`. See
318
+ > <https://fedify.dev/manual/mq.md>.
319
+
320
+ > [!WARNING]
321
+ > Do not load-balance worker nodes that drain the queue. Each worker
322
+ > should take traffic independently; putting them behind a load balancer
323
+ > breaks idempotency tracking. See <https://fedify.dev/manual/deploy.md>.
324
+
325
+ See <https://fedify.dev/manual/kv.md> and <https://fedify.dev/manual/mq.md>.
326
+
327
+
328
+ Observability
329
+ -------------
330
+
331
+ ### LogTape
332
+
333
+ Fedify emits structured logs via [LogTape] under the following
334
+ categories. Configure LogTape once at application start (if this
335
+ project has a separate LogTape skill installed, defer to it for the
336
+ generic setup):
337
+
338
+ - `fedify.compat.transformers`
339
+ - `fedify.federation`, `fedify.federation.actor`,
340
+ `fedify.federation.collection`, `fedify.federation.fanout`,
341
+ `fedify.federation.http`, `fedify.federation.inbox`,
342
+ `fedify.federation.outbox`, `fedify.federation.queue`
343
+ - `fedify.nodeinfo.client`
344
+ - `fedify.otel.exporter`
345
+ - `fedify.sig.http`, `fedify.sig.key`, `fedify.sig.ld`,
346
+ `fedify.sig.proof`
347
+ - `fedify.utils.docloader`, `fedify.utils.kv-cache`
348
+ - `fedify.webfinger.server`
349
+
350
+ > [!CAUTION]
351
+ > Since LogTape 0.7.0, implicit contexts require explicit configuration.
352
+ > See <https://fedify.dev/manual/log.md>.
353
+
354
+ [LogTape]: https://logtape.org/
355
+
356
+ ### OpenTelemetry
357
+
358
+ Pass a `tracerProvider` in `FederationOptions` to have Fedify instrument
359
+ its internals. For trace persistence, `@fedify/fedify/otel` exports
360
+ `FedifySpanExporter`, which writes traces to a `KvStore` so the
361
+ *@fedify/debugger* dashboard can render them.
362
+
363
+ > [!CAUTION]
364
+ > Initialize the OpenTelemetry SDK *before* importing Fedify. Later
365
+ > registration leaves earlier spans untraced.
366
+
367
+ See <https://fedify.dev/manual/log.md> and
368
+ <https://fedify.dev/manual/opentelemetry.md>.
369
+
370
+
371
+ Looking up FEPs
372
+ ---------------
373
+
374
+ When the user references a Fediverse Enhancement Proposal (for example
375
+ `FEP-8fcf` or `FEP-1b12`), clone the proposals repository locally and
376
+ read the relevant file; Codeberg blocks web scraping and `WebFetch`-style
377
+ requests fail:
378
+
379
+ ~~~~ bash
380
+ git clone https://codeberg.org/fediverse/fep.git
381
+ ~~~~
382
+
383
+ Files are under *fep/* keyed by the four-hex-digit identifier (for
384
+ example *fep/8fcf/fep-8fcf.md*). If the project is configured with the
385
+ [FEP MCP server], prefer that instead.
386
+
387
+ [FEP MCP server]: https://github.com/dahlia/fep-mcp
388
+
389
+
390
+ CLI helpers
391
+ -----------
392
+
393
+ The `fedify` CLI (distributed as *@fedify/cli*) covers bootstrapping and
394
+ debugging:
395
+
396
+ - `fedify init`: scaffold a new project (pick web framework, package
397
+ manager, KV store, and message queue).
398
+ - `fedify lookup`: resolve a handle, URL, or WebFinger identifier and
399
+ print the dereferenced document.
400
+ - `fedify inbox`: spin up a temporary inbox with a tunnel to inspect
401
+ incoming activities from real peers.
402
+ - `fedify webfinger`, `fedify nodeinfo`, `fedify tunnel`,
403
+ `fedify relay`.
404
+
405
+ > [!WARNING]
406
+ > `fedify inbox` and `fedify tunnel` are development tools. They open a
407
+ > public tunnel to your local process; do not run them against
408
+ > production data.
409
+
410
+ See <https://fedify.dev/cli.md>.
411
+
412
+
413
+ Common mistakes to avoid
414
+ ------------------------
415
+
416
+ - Forgetting to `await builder.build(...)` or `await ctx.sendActivity(...)`.
417
+ Both are asynchronous.
418
+ - Hand-rolling `/.well-known/webfinger` or `/.well-known/nodeinfo`
419
+ routes; Fedify already serves them.
420
+ - Importing from the deprecated shims `@fedify/fedify/vocab` or
421
+ `@fedify/fedify/runtime`, or from the old in-tree *src/webfinger*
422
+ path, instead of the dedicated packages `@fedify/vocab`,
423
+ `@fedify/vocab-runtime`, and `@fedify/webfinger`.
424
+ - Omitting the `queue` option in production; outgoing delivery becomes
425
+ synchronous and unreliable.
426
+ - Running with `MemoryKvStore` in production; it evaporates on every
427
+ restart.
428
+ - Running behind a reverse proxy, a tunnel (`fedify tunnel`, ngrok,
429
+ Cloudflare Tunnel, Tailscale Funnel), or a load balancer without
430
+ propagating the original origin. Fedify reads `request.url`, so
431
+ without `X-Forwarded-*` handling it will mint actor IDs and activity
432
+ URLs using the internal origin (for example `http://localhost:3000`)
433
+ instead of the public `https://…` address that remote peers
434
+ dereference. Fix one of two ways: pin
435
+ `FederationOptions.origin` to the canonical URL, or pipe requests
436
+ through [x-forwarded-fetch] before they reach Fedify (gated on a
437
+ `BEHIND_PROXY` flag, since `X-Forwarded-Host` is spoofable from the
438
+ open internet). See <https://fedify.dev/manual/deploy.md>.
439
+ - Enabling `allowPrivateAddress: true` outside tests; that disables the
440
+ SSRF guard.
441
+ - Using `crossOrigin: "trust"` without verifying the remote is
442
+ actually trusted.
443
+ - Registering inbox handlers only for specific activity types and
444
+ expecting delivery-level error handling; unregistered types are
445
+ answered with HTTP 202 and logged at error level as unsupported,
446
+ but never reach a listener. Add a catch-all on `Activity` if you
447
+ need to observe them.
448
+ - Wiring Fedify into a web framework by writing custom routes instead
449
+ of importing the matching `@fedify/<framework>` package.
450
+ - Load-balancing queue worker nodes; each worker must take traffic
451
+ independently.
452
+ - Using simple URI-template expansion (`{identifier}`) when identifiers
453
+ contain reserved URI characters; switch to `{+identifier}`.
454
+ - Deriving an activity's `id` from `(actor, object)`; the same pair
455
+ can legitimately produce multiple activities of the same shape.
456
+ - Returning `Tombstone` from an actor dispatcher without checking
457
+ `RequestContext.getActor({ tombstone: "passthrough" })` semantics;
458
+ see <https://fedify.dev/manual/actor.md>.
459
+ - Committing private keys, embedding them in bundles, or exposing them
460
+ through admin endpoints.
461
+
462
+ [x-forwarded-fetch]: https://github.com/dahlia/x-forwarded-fetch