@fedify/fedify 2.3.15-dev.2482 → 2.3.15

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 (87) hide show
  1. package/dist/{builder-CocMrVkL.mjs → builder-B6vSXYxn.mjs} +2 -2
  2. package/dist/{client-CAM_bQXx.d.cts → client-BIBzqEIp.d.cts} +0 -1
  3. package/dist/{client-1He2YuBF.mjs → client-DpUNYKla.mjs} +113 -64
  4. package/dist/{client-CSddvgWN.d.ts → client-jE7oGvRh.d.ts} +0 -1
  5. package/dist/compat/mod.d.cts +1 -1
  6. package/dist/compat/mod.d.ts +1 -1
  7. package/dist/compat/transformers.test.mjs +1 -1
  8. package/dist/{context-MOrCC7yl.d.cts → context-CE_Tj_Oc.d.cts} +28 -2
  9. package/dist/{context-BWbdE_MZ.d.ts → context-H_5tZXg-.d.ts} +28 -2
  10. package/dist/{deno-po8iekMB.mjs → deno-BCuL3mid.mjs} +1 -1
  11. package/dist/docloader-D2dr1_6B.mjs +125 -0
  12. package/dist/federation/builder.test.mjs +1 -1
  13. package/dist/federation/handler.test.mjs +5 -5
  14. package/dist/federation/idempotency.test.mjs +2 -2
  15. package/dist/federation/inbox.test.mjs +1 -1
  16. package/dist/federation/metrics.test.mjs +1 -1
  17. package/dist/federation/middleware.test.mjs +390 -29
  18. package/dist/federation/mod.cjs +1 -1
  19. package/dist/federation/mod.d.cts +2 -2
  20. package/dist/federation/mod.d.ts +2 -2
  21. package/dist/federation/mod.js +1 -1
  22. package/dist/federation/send.test.mjs +498 -88
  23. package/dist/federation/temporal.test.mjs +1 -1
  24. package/dist/federation/webfinger.test.mjs +1 -1
  25. package/dist/{http-Cdu8BGtv.js → http-BkjxY3U0.js} +172 -103
  26. package/dist/{http-BNCLeQJ-.mjs → http-CSDcThvz.mjs} +196 -98
  27. package/dist/{http-DQmNpfym.d.ts → http-CZPYFK3b.d.cts} +1 -2
  28. package/dist/{http-DiWQB8Mr.d.cts → http-DmP0sr2l.d.ts} +1 -2
  29. package/dist/{http-WcSdFbt1.cjs → http-gOkAiIe1.cjs} +173 -104
  30. package/dist/{inbox-g1sd_Vjn.mjs → inbox-BHxez4d5.mjs} +2 -2
  31. package/dist/{key-BR2TRTXR.mjs → key-D8IMQ72M.mjs} +2 -2
  32. package/dist/{kv-cache-Bw_gduSm.cjs → kv-cache-Alm5UmJa.cjs} +59 -17
  33. package/dist/{kv-cache-8SigUtvX.mjs → kv-cache-Blr9nDDp.mjs} +1 -1
  34. package/dist/{kv-cache-C0AqpjoS.js → kv-cache-CkXgU-ak.js} +60 -18
  35. package/dist/{ld-CSNsWdYE.mjs → ld-CVxxE1Pp.mjs} +3 -3
  36. package/dist/{metrics-BS7YzLVA.mjs → metrics-SYIZHFf_.mjs} +1 -1
  37. package/dist/{middleware-D-SL8Bkj.cjs → middleware-4yPyyoF5.cjs} +236 -98
  38. package/dist/{middleware-B1RRLN7m.mjs → middleware-CfskJGfV.mjs} +80 -40
  39. package/dist/{middleware-Dlo7NnZl.mjs → middleware-D3JWfiCu.mjs} +1 -1
  40. package/dist/{middleware-WL-JfDiK.js → middleware-DhN7c65B.js} +237 -99
  41. package/dist/{mod-LmD03uRA.d.ts → mod-CDFFESfL.d.ts} +1 -1
  42. package/dist/{mod-Bid79LFU.d.cts → mod-C_gFmeNq.d.cts} +1 -1
  43. package/dist/{mod-Co1M3Ux0.d.cts → mod-DDVkmZ_h.d.cts} +2 -8
  44. package/dist/{mod-B6PwkUMU.d.cts → mod-DDjtbkZO.d.cts} +1 -1
  45. package/dist/{mod-Br8yJNcE.d.ts → mod-DMjhnFbg.d.ts} +2 -8
  46. package/dist/{mod-TLEvgT1i.d.ts → mod-HQXFvOHs.d.ts} +1 -1
  47. package/dist/mod.cjs +5 -5
  48. package/dist/mod.d.cts +6 -6
  49. package/dist/mod.d.ts +6 -6
  50. package/dist/mod.js +5 -5
  51. package/dist/nodeinfo/client.test.mjs +337 -19
  52. package/dist/nodeinfo/handler.test.mjs +1 -1
  53. package/dist/nodeinfo/mod.cjs +1 -1
  54. package/dist/nodeinfo/mod.d.cts +1 -1
  55. package/dist/nodeinfo/mod.d.ts +1 -1
  56. package/dist/nodeinfo/mod.js +1 -1
  57. package/dist/otel/exporter.test.mjs +292 -30
  58. package/dist/otel/mod.cjs +36 -30
  59. package/dist/otel/mod.d.cts +13 -0
  60. package/dist/otel/mod.d.ts +13 -0
  61. package/dist/otel/mod.js +36 -30
  62. package/dist/{owner-DeggvxcG.mjs → owner-BluLVPf0.mjs} +2 -2
  63. package/dist/{proof-teNNYmFh.cjs → proof-CR-HwI0l.cjs} +1 -1
  64. package/dist/{proof-DMcUrrp8.mjs → proof-Co6nQBVR.mjs} +3 -3
  65. package/dist/{proof-v-IzWx7x.js → proof-Dg0d9QBo.js} +1 -1
  66. package/dist/{send-BsthcvPG.mjs → send-D_DnqOFA.mjs} +171 -73
  67. package/dist/sig/http.test.mjs +528 -2
  68. package/dist/sig/key.test.mjs +2 -2
  69. package/dist/sig/ld.test.mjs +2 -2
  70. package/dist/sig/mod.cjs +2 -2
  71. package/dist/sig/mod.d.cts +2 -2
  72. package/dist/sig/mod.d.ts +2 -2
  73. package/dist/sig/mod.js +2 -2
  74. package/dist/sig/owner.test.mjs +1 -1
  75. package/dist/sig/proof.test.mjs +1 -1
  76. package/dist/{temporal-Cji8Y8eQ.mjs → temporal-B8FUNkXB.mjs} +1 -1
  77. package/dist/testing/mod.d.mts +26 -0
  78. package/dist/{types-miAYfiGO.js → types-B1_pRFE_.js} +112 -63
  79. package/dist/{types-DRPjmHVV.cjs → types-DOvyymM4.cjs} +111 -62
  80. package/dist/utils/docloader.test.mjs +318 -34
  81. package/dist/utils/kv-cache.test.mjs +1 -1
  82. package/dist/utils/mod.cjs +1 -1
  83. package/dist/utils/mod.d.cts +1 -1
  84. package/dist/utils/mod.d.ts +1 -1
  85. package/dist/utils/mod.js +1 -1
  86. package/package.json +8 -8
  87. package/dist/docloader-BVj35vgR.mjs +0 -83
@@ -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-po8iekMB.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-BS7YzLVA.mjs";
4
+ import { n as version, t as name } from "./deno-BCuL3mid.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-SYIZHFf_.mjs";
6
6
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-Dd__NiUL.mjs";
7
- import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-BR2TRTXR.mjs";
7
+ import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-D8IMQ72M.mjs";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { CryptographicKey } from "@fedify/vocab";
10
10
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -900,10 +900,10 @@ async function createRedirectRequest(request, location, body, validateRedirect)
900
900
  cache: request.cache
901
901
  });
902
902
  }
903
- async function fetchDoubleKnockRequest(request, signedRequest, signal) {
903
+ async function fetchDoubleKnockRequest(session, request, signedRequest, signal) {
904
904
  const maxAttempts = request.method === "GET" || request.method === "HEAD" ? 2 : 1;
905
905
  for (let attempt = 1;; attempt++) try {
906
- return await fetch(signedRequest, {
906
+ return await session.fetch(signedRequest, {
907
907
  redirect: "manual",
908
908
  signal
909
909
  });
@@ -964,108 +964,206 @@ function getAbortReason(signal) {
964
964
  * @since 1.6.0
965
965
  */
966
966
  async function doubleKnock(request, identity, options = {}) {
967
- return await doubleKnockInternal(request, identity, options);
967
+ const { response } = await doubleKnockCore(request, identity, options, openGlobalFetchHop);
968
+ return response;
968
969
  }
969
- async function doubleKnockInternal(request, identity, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
970
- const { specDeterminer, log, tracerProvider, signal } = options;
971
- const maximumRedirection = options.maxRedirection ?? DEFAULT_MAX_REDIRECTION;
972
- visited.add(request.url);
973
- const origin = new URL(request.url).origin;
974
- const firstTrySpec = specDeterminer == null ? "rfc9421" : await specDeterminer.determineSpec(origin);
975
- const body = options.body !== void 0 ? options.body : request.method !== "GET" && request.method !== "HEAD" ? await request.clone().arrayBuffer() : null;
976
- let signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
977
- spec: firstTrySpec,
978
- tracerProvider,
979
- body
970
+ /**
971
+ * Performs a double-knock request like {@link doubleKnock}, opening a session
972
+ * for every hop with the given function, and passes the final response to
973
+ * the given function. The final session is closed after `consume` settles,
974
+ * so `consume` must read or cancel the response body before it returns.
975
+ * This is not exported from any entry point.
976
+ * @param request The request to send.
977
+ * @param identity The identity to use for signing the request.
978
+ * @param options The options for double-knock requests.
979
+ * @param openHop The function to open a session for each hop. The session of
980
+ * a hop is closed before the next hop is opened.
981
+ * @param consume The function to consume the final response.
982
+ * @returns The value returned by `consume`.
983
+ */
984
+ async function doubleKnockScoped(request, identity, options, openHop, consume) {
985
+ const { response, session } = await doubleKnockCore(request, identity, options, openHop);
986
+ try {
987
+ return await consume(response);
988
+ } catch (error) {
989
+ getLogger([
990
+ "fedify",
991
+ "sig",
992
+ "http"
993
+ ]).debug("Failed to consume the response from {url}; closing the session: {error}", {
994
+ url: request.url,
995
+ error
996
+ });
997
+ throw error;
998
+ } finally {
999
+ await session.close();
1000
+ }
1001
+ }
1002
+ /**
1003
+ * A hop session for {@link doubleKnock}: it uses the global `fetch()` without
1004
+ * validating or pinning addresses, and its `close()` does nothing, so that
1005
+ * the final response can be returned to the caller.
1006
+ */
1007
+ function openGlobalFetchHop(url) {
1008
+ const sessionUrl = new URL(url);
1009
+ return Promise.resolve({
1010
+ get url() {
1011
+ return new URL(sessionUrl);
1012
+ },
1013
+ fetch: (input, init) => fetch(input, init),
1014
+ close: () => Promise.resolve()
980
1015
  });
981
- log?.(signedRequest);
982
- let response = await fetchDoubleKnockRequest(request, signedRequest, signal);
983
- if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
984
- if (redirected >= maximumRedirection) throw new FetchError(request.url, `Too many redirections (${redirected + 1})`);
985
- const redirectRequest = await createRedirectRequest(request, response.headers.get("Location"), body, options.validateRedirect);
986
- if (visited.has(redirectRequest.url)) throw new FetchError(request.url, `Redirect loop detected: ${redirectRequest.url}`);
987
- return doubleKnockInternal(redirectRequest, identity, {
988
- ...options,
989
- body
990
- }, redirected + 1, visited);
991
- } else if (response.status === 400 || response.status === 401 || response.status > 401) {
992
- const logger = getLogger([
1016
+ }
1017
+ function isRedirectResponse(response) {
1018
+ return response.status >= 300 && response.status < 400 && response.headers.has("Location");
1019
+ }
1020
+ /**
1021
+ * Starts cancelling the body of a response that is not passed to the caller,
1022
+ * without waiting for it to settle. The cancellation of a branch of a tee
1023
+ * (e.g., a body cloned by a fetch mock) settles only after the other branch
1024
+ * is cancelled too, per the Streams standard, so awaiting it could block
1025
+ * forever. Failures are only logged.
1026
+ */
1027
+ function cancelResponseBody(response, url) {
1028
+ response.body?.cancel().catch((error) => {
1029
+ getLogger([
993
1030
  "fedify",
994
1031
  "sig",
995
1032
  "http"
996
- ]);
997
- const acceptSigHeader = response.headers.get("Accept-Signature");
998
- if (acceptSigHeader != null) {
999
- const entries = validateAcceptSignature(parseAcceptSignature(acceptSigHeader));
1000
- const localKeyId = identity.keyId.href;
1001
- const localAlg = "rsa-v1_5-sha256";
1002
- let fulfilled = false;
1003
- let challengeRequest;
1004
- for (const entry of entries) {
1005
- const rfc9421 = fulfillAcceptSignature(entry, localKeyId, localAlg);
1006
- if (rfc9421 == null) continue;
1007
- logger.debug("Received Accept-Signature challenge; accumulating label {label} and components {components}.", {
1008
- label: rfc9421.label,
1009
- components: rfc9421.components
1010
- });
1011
- try {
1012
- challengeRequest = await signRequest(challengeRequest ?? request, identity.privateKey, identity.keyId, {
1013
- spec: "rfc9421",
1014
- tracerProvider,
1015
- body,
1016
- rfc9421
1033
+ ]).debug("Failed to cancel the response body from {url}: {error}", {
1034
+ url,
1035
+ error
1036
+ });
1037
+ });
1038
+ }
1039
+ async function doubleKnockCore(request, identity, options, openHop) {
1040
+ const { specDeterminer, log, tracerProvider, signal } = options;
1041
+ const maximumRedirection = options.maxRedirection ?? DEFAULT_MAX_REDIRECTION;
1042
+ const visited = /* @__PURE__ */ new Set();
1043
+ const body = options.body !== void 0 ? options.body : request.method !== "GET" && request.method !== "HEAD" ? await request.clone().arrayBuffer() : null;
1044
+ let session = await openHop(request.url);
1045
+ try {
1046
+ for (let redirected = 0;; redirected++) {
1047
+ visited.add(request.url);
1048
+ const origin = new URL(request.url).origin;
1049
+ const firstTrySpec = specDeterminer == null ? "rfc9421" : await specDeterminer.determineSpec(origin);
1050
+ let signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
1051
+ spec: firstTrySpec,
1052
+ tracerProvider,
1053
+ body
1054
+ });
1055
+ log?.(signedRequest);
1056
+ let response = await fetchDoubleKnockRequest(session, request, signedRequest, signal);
1057
+ const firstRedirected = isRedirectResponse(response);
1058
+ if (!firstRedirected && (response.status === 400 || response.status === 401 || response.status > 401)) {
1059
+ const logger = getLogger([
1060
+ "fedify",
1061
+ "sig",
1062
+ "http"
1063
+ ]);
1064
+ const acceptSigHeader = response.headers.get("Accept-Signature");
1065
+ if (acceptSigHeader != null) {
1066
+ const entries = validateAcceptSignature(parseAcceptSignature(acceptSigHeader));
1067
+ const localKeyId = identity.keyId.href;
1068
+ const localAlg = "rsa-v1_5-sha256";
1069
+ let fulfilled = false;
1070
+ let challengeRequest;
1071
+ for (const entry of entries) {
1072
+ const rfc9421 = fulfillAcceptSignature(entry, localKeyId, localAlg);
1073
+ if (rfc9421 == null) continue;
1074
+ logger.debug("Received Accept-Signature challenge; accumulating label {label} and components {components}.", {
1075
+ label: rfc9421.label,
1076
+ components: rfc9421.components
1077
+ });
1078
+ try {
1079
+ challengeRequest = await signRequest(challengeRequest ?? request, identity.privateKey, identity.keyId, {
1080
+ spec: "rfc9421",
1081
+ tracerProvider,
1082
+ body,
1083
+ rfc9421
1084
+ });
1085
+ fulfilled = true;
1086
+ } catch (error) {
1087
+ logger.debug("Failed to fulfill Accept-Signature challenge entry {label}: {error}", {
1088
+ label: entry.label,
1089
+ error
1090
+ });
1091
+ }
1092
+ }
1093
+ if (fulfilled && challengeRequest != null) {
1094
+ cancelResponseBody(response, request.url);
1095
+ signedRequest = challengeRequest;
1096
+ log?.(signedRequest);
1097
+ response = await session.fetch(signedRequest, {
1098
+ redirect: "manual",
1099
+ signal
1100
+ });
1101
+ }
1102
+ if (fulfilled && !isRedirectResponse(response)) {
1103
+ if (response.status < 300) {
1104
+ await specDeterminer?.rememberSpec(origin, "rfc9421");
1105
+ return {
1106
+ response,
1107
+ session
1108
+ };
1109
+ }
1110
+ if (response.status !== 400 && response.status !== 401) return {
1111
+ response,
1112
+ session
1113
+ };
1114
+ }
1115
+ }
1116
+ if (!isRedirectResponse(response)) {
1117
+ const spec = firstTrySpec === "draft-cavage-http-signatures-12" ? "rfc9421" : "draft-cavage-http-signatures-12";
1118
+ getLogger([
1119
+ "fedify",
1120
+ "sig",
1121
+ "http"
1122
+ ]).debug("Failed to verify with the spec {spec} ({status} {statusText}); retrying with spec {secondSpec}... (double-knocking)", {
1123
+ spec: firstTrySpec,
1124
+ secondSpec: spec,
1125
+ status: response.status,
1126
+ statusText: response.statusText
1017
1127
  });
1018
- fulfilled = true;
1019
- } catch (error) {
1020
- logger.debug("Failed to fulfill Accept-Signature challenge entry {label}: {error}", {
1021
- label: entry.label,
1022
- error
1128
+ cancelResponseBody(response, request.url);
1129
+ signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
1130
+ spec,
1131
+ tracerProvider,
1132
+ body
1023
1133
  });
1134
+ log?.(signedRequest);
1135
+ response = await fetchDoubleKnockRequest(session, request, signedRequest, signal);
1136
+ if (!isRedirectResponse(response) && response.status !== 400 && response.status !== 401) await specDeterminer?.rememberSpec(origin, spec);
1024
1137
  }
1025
- }
1026
- if (fulfilled && challengeRequest != null) {
1027
- signedRequest = challengeRequest;
1028
- log?.(signedRequest);
1029
- response = await fetch(signedRequest, {
1030
- redirect: "manual",
1031
- signal
1032
- });
1033
- if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) return doubleKnock(await createRedirectRequest(request, response.headers.get("Location"), body, options.validateRedirect), identity, {
1034
- ...options,
1035
- body
1036
- });
1037
- }
1038
- if (fulfilled && response.status < 300) {
1039
- await specDeterminer?.rememberSpec(origin, "rfc9421");
1040
- return response;
1041
- }
1042
- if (fulfilled && response.status !== 400 && response.status !== 401) return response;
1043
- }
1044
- const spec = firstTrySpec === "draft-cavage-http-signatures-12" ? "rfc9421" : "draft-cavage-http-signatures-12";
1045
- logger.debug("Failed to verify with the spec {spec} ({status} {statusText}); retrying with spec {secondSpec}... (double-knocking)", {
1046
- spec: firstTrySpec,
1047
- secondSpec: spec,
1048
- status: response.status,
1049
- statusText: response.statusText
1050
- });
1051
- signedRequest = await signRequest(request, identity.privateKey, identity.keyId, {
1052
- spec,
1053
- tracerProvider,
1054
- body
1055
- });
1056
- log?.(signedRequest);
1057
- response = await fetchDoubleKnockRequest(request, signedRequest, signal);
1058
- if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
1138
+ } else if (!firstRedirected) await specDeterminer?.rememberSpec(origin, firstTrySpec);
1139
+ if (!isRedirectResponse(response)) return {
1140
+ response,
1141
+ session
1142
+ };
1143
+ cancelResponseBody(response, request.url);
1144
+ await session.close();
1059
1145
  if (redirected >= maximumRedirection) throw new FetchError(request.url, `Too many redirections (${redirected + 1})`);
1060
- const redirectRequest = await createRedirectRequest(request, response.headers.get("Location"), body, options.validateRedirect);
1146
+ const location = response.headers.get("Location");
1147
+ const redirectRequest = await createRedirectRequest(request, location, body, options.validateRedirect);
1061
1148
  if (visited.has(redirectRequest.url)) throw new FetchError(request.url, `Redirect loop detected: ${redirectRequest.url}`);
1062
- return doubleKnockInternal(redirectRequest, identity, {
1063
- ...options,
1064
- body
1065
- }, redirected + 1, visited);
1066
- } else if (response.status !== 400 && response.status !== 401) await specDeterminer?.rememberSpec(origin, spec);
1067
- } else await specDeterminer?.rememberSpec(origin, firstTrySpec);
1068
- return response;
1149
+ request = redirectRequest;
1150
+ session = await openHop(request.url);
1151
+ }
1152
+ } catch (error) {
1153
+ try {
1154
+ await session.close();
1155
+ } catch (closeError) {
1156
+ getLogger([
1157
+ "fedify",
1158
+ "sig",
1159
+ "http"
1160
+ ]).debug("Failed to close the session for {url}: {error}", {
1161
+ url: request.url,
1162
+ error: closeError
1163
+ });
1164
+ }
1165
+ throw error;
1166
+ }
1069
1167
  }
1070
1168
  /**
1071
1169
  * Performs a timing-safe equality comparison between two `Uint8Array` values.
@@ -1095,4 +1193,4 @@ function timingSafeEqual(a, b) {
1095
1193
  return result === 0;
1096
1194
  }
1097
1195
  //#endregion
1098
- export { parseRfc9421Signature as a, timingSafeEqual as c, formatRfc9421SignatureParameters as i, verifyRequest as l, doubleKnock as n, parseRfc9421SignatureInput as o, formatRfc9421Signature as r, signRequest as s, createRfc9421SignatureBase as t, verifyRequestDetailed as u };
1196
+ export { formatRfc9421SignatureParameters as a, signRequest as c, verifyRequestDetailed as d, formatRfc9421Signature as i, timingSafeEqual as l, doubleKnock as n, parseRfc9421Signature as o, doubleKnockScoped as r, parseRfc9421SignatureInput as s, createRfc9421SignatureBase as t, verifyRequest as u };
@@ -1,8 +1,7 @@
1
1
  /// <reference lib="esnext.temporal" />
2
2
  import { Actor, CryptographicKey, Multikey } from "@fedify/vocab";
3
- import { MeterProvider, TracerProvider } from "@opentelemetry/api";
4
3
  import { DocumentLoader } from "@fedify/vocab-runtime";
5
-
4
+ import { MeterProvider, TracerProvider } from "@opentelemetry/api";
6
5
  //#region src/sig/key.d.ts
7
6
  /**
8
7
  * Generates a key pair which is appropriate for Fedify.
@@ -1,8 +1,7 @@
1
1
  /// <reference lib="esnext.temporal" />
2
2
  import { Actor, CryptographicKey, Multikey } from "@fedify/vocab";
3
- import { DocumentLoader } from "@fedify/vocab-runtime";
4
3
  import { MeterProvider, TracerProvider } from "@opentelemetry/api";
5
-
4
+ import { DocumentLoader } from "@fedify/vocab-runtime";
6
5
  //#region src/sig/key.d.ts
7
6
  /**
8
7
  * Generates a key pair which is appropriate for Fedify.