@fedify/fedify 2.3.0-dev.1013 → 2.3.0-dev.1034

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 (95) hide show
  1. package/dist/{builder-CROLcFVM.mjs → builder-y06Dq5bp.mjs} +14 -4
  2. package/dist/chunk-QSgtlS85.mjs +29 -0
  3. package/dist/compat/mod.d.cts +1 -1
  4. package/dist/compat/mod.d.ts +1 -1
  5. package/dist/compat/outgoing-jsonld.test.mjs +1 -1
  6. package/dist/compat/public-audience.test.mjs +1 -1
  7. package/dist/compat/transformers.test.mjs +2 -2
  8. package/dist/{context-Dk_tacqz.mjs → context-7Azky82W.mjs} +3 -2
  9. package/dist/{context-BDl7Y6f-.d.cts → context-BKLGj9QO.d.cts} +24 -1
  10. package/dist/{context-zTZAI3KP.d.ts → context-DrNqYkPw.d.ts} +24 -1
  11. package/dist/{deno-Ctd-K-t6.mjs → deno-DB1H1VHx.mjs} +1 -1
  12. package/dist/{docloader-q9QT51g3.mjs → docloader-3HwiWeYL.mjs} +2 -2
  13. package/dist/{esm-DVILvP5e.mjs → esm-DhnRLoG9.mjs} +1 -24
  14. package/dist/execAsync-eck5rbtb.mjs +13 -0
  15. package/dist/federation/builder.test.mjs +8 -3
  16. package/dist/federation/collection.test.mjs +1 -1
  17. package/dist/federation/handler.test.mjs +48 -11
  18. package/dist/federation/idempotency.test.mjs +4 -4
  19. package/dist/federation/inbox.test.mjs +1 -1
  20. package/dist/federation/keycache.test.mjs +2 -2
  21. package/dist/federation/kv.test.mjs +1 -1
  22. package/dist/federation/middleware.test.mjs +138 -15
  23. package/dist/federation/mod.cjs +1 -1
  24. package/dist/federation/mod.d.cts +2 -2
  25. package/dist/federation/mod.d.ts +2 -2
  26. package/dist/federation/mod.js +1 -1
  27. package/dist/federation/negotiation.test.mjs +1 -1
  28. package/dist/federation/retry.test.mjs +1 -1
  29. package/dist/federation/send.test.mjs +4540 -11
  30. package/dist/federation/webfinger.test.mjs +3 -3
  31. package/dist/getMachineId-bsd-DqZ4QRFp.mjs +29 -0
  32. package/dist/getMachineId-darwin-DMbbW3m7.mjs +26 -0
  33. package/dist/getMachineId-linux-lyeD2ug3.mjs +22 -0
  34. package/dist/getMachineId-unsupported-JuKr57jY.mjs +17 -0
  35. package/dist/getMachineId-win-Dxyf5pJq.mjs +28 -0
  36. package/dist/{http-1NL30qCe.js → http-BUr93aO6.js} +1 -1
  37. package/dist/{http-CX_zHeOD.mjs → http-D9zG-L9N.mjs} +3 -3
  38. package/dist/{http-Du1Jgf2P.cjs → http-FnUTcdMf.cjs} +1 -1
  39. package/dist/{key-C1Oto4it.mjs → key-CV57mOYH.mjs} +1 -1
  40. package/dist/{kv-cache-aGOwL6Vj.cjs → kv-cache-BG9O8wVV.cjs} +1 -1
  41. package/dist/{kv-cache-CsC3P4uu.js → kv-cache-C3esyJFP.js} +1 -1
  42. package/dist/{ld-Dl1HIB1a.mjs → ld-sUf94RJ8.mjs} +2 -2
  43. package/dist/{middleware-BiFLcrEX.cjs → middleware-CKkBrsOD.cjs} +203 -32
  44. package/dist/{middleware-C1cf3_6V.mjs → middleware-cMxbPxDe.mjs} +1 -1
  45. package/dist/{middleware-CKJC8DRf.js → middleware-fAuUxD9-.js} +203 -32
  46. package/dist/{middleware-BwC5U8zJ.cjs → middleware-ohzkLsW4.cjs} +1 -1
  47. package/dist/{middleware-CEWDB8EB.mjs → middleware-pb2EqN_r.mjs} +75 -27
  48. package/dist/{mod-ckCOmoCz.d.ts → mod-B8Z8mBLk.d.ts} +1 -1
  49. package/dist/{mod-BghZgD_U.d.cts → mod-DClCOv0M.d.cts} +1 -1
  50. package/dist/mod.cjs +4 -4
  51. package/dist/mod.d.cts +2 -2
  52. package/dist/mod.d.ts +2 -2
  53. package/dist/mod.js +4 -4
  54. package/dist/nodeinfo/client.test.mjs +2 -2
  55. package/dist/nodeinfo/handler.test.mjs +3 -3
  56. package/dist/nodeinfo/types.test.mjs +1 -1
  57. package/dist/otel/exporter.test.mjs +25 -22
  58. package/dist/otel/mod.cjs +6 -5
  59. package/dist/otel/mod.d.cts +3 -2
  60. package/dist/otel/mod.d.ts +3 -2
  61. package/dist/otel/mod.js +6 -5
  62. package/dist/{outgoing-jsonld-CNmZLixq.mjs → outgoing-jsonld-Bi7n-dEy.mjs} +1 -1
  63. package/dist/{owner-CEWFJlqo.mjs → owner-DsPgl527.mjs} +2 -2
  64. package/dist/{proof-CDA3f-i5.cjs → proof-BhJpq_J9.cjs} +1 -1
  65. package/dist/{proof-BFyPVl1r.mjs → proof-iVfYyJpY.mjs} +4 -4
  66. package/dist/{proof-Dedf8md5.js → proof-k4mEvvdS.js} +1 -1
  67. package/dist/send-D-vYdfC6.mjs +306 -0
  68. package/dist/sig/accept.test.mjs +1 -1
  69. package/dist/sig/http.test.mjs +4 -4
  70. package/dist/sig/key.test.mjs +2 -2
  71. package/dist/sig/ld.test.mjs +3 -3
  72. package/dist/sig/mod.cjs +2 -2
  73. package/dist/sig/mod.js +2 -2
  74. package/dist/sig/owner.test.mjs +2 -2
  75. package/dist/sig/proof.test.mjs +3 -3
  76. package/dist/testing/mod.d.mts +18 -1
  77. package/dist/testing/mod.mjs +1 -1
  78. package/dist/utils/docloader.test.mjs +4 -4
  79. package/dist/utils/kv-cache.test.mjs +1 -1
  80. package/dist/utils/mod.cjs +1 -1
  81. package/dist/utils/mod.js +1 -1
  82. package/package.json +7 -6
  83. package/dist/send-BJickEP4.mjs +0 -193
  84. /package/dist/{accept-CPkZzmGN.mjs → accept-CceiKpCy.mjs} +0 -0
  85. /package/dist/{activity-listener-ell7W1s9.mjs → activity-listener-tztVvlNb.mjs} +0 -0
  86. /package/dist/{client-D_1QpnWt.mjs → client-CIiz1WX7.mjs} +0 -0
  87. /package/dist/{collection-D-HqUuA2.mjs → collection-CA3V5zyK.mjs} +0 -0
  88. /package/dist/{keycache-EGATflN-.mjs → keycache-BeU0LCII.mjs} +0 -0
  89. /package/dist/{keys-DGu1NFwu.mjs → keys-C3kae-6B.mjs} +0 -0
  90. /package/dist/{kv-cache-U__xU4qR.mjs → kv-cache-Bmv7tUzz.mjs} +0 -0
  91. /package/dist/{kv-rV3vodCc.mjs → kv-x2IvBUyq.mjs} +0 -0
  92. /package/dist/{negotiation-SQvQgUqe.mjs → negotiation-VnHNB0Q5.mjs} +0 -0
  93. /package/dist/{public-audience-DYFHzm_c.mjs → public-audience-PVTwU_Ex.mjs} +0 -0
  94. /package/dist/{retry-bMXBL97A.mjs → retry-_VvV0h9f.mjs} +0 -0
  95. /package/dist/{types-J53Kw7so.mjs → types-BFowWFTT.mjs} +0 -0
@@ -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-Ctd-K-t6.mjs";
5
- import { n as fetchKey, o as validateCryptoKey } from "./key-C1Oto4it.mjs";
6
- import { n as preloadedOnlyDocumentLoader } from "./public-audience-DYFHzm_c.mjs";
7
- import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-CNmZLixq.mjs";
4
+ import { n as version, t as name } from "./deno-DB1H1VHx.mjs";
5
+ import { n as fetchKey, o as validateCryptoKey } from "./key-CV57mOYH.mjs";
6
+ import { n as preloadedOnlyDocumentLoader } from "./public-audience-PVTwU_Ex.mjs";
7
+ import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-Bi7n-dEy.mjs";
8
8
  import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
9
9
  import { SpanStatusCode, trace } from "@opentelemetry/api";
10
10
  import { getLogger } from "@logtape/logtape";
@@ -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-1NL30qCe.js";
3
+ import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-BUr93aO6.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";
@@ -0,0 +1,306 @@
1
+ import "@js-temporal/polyfill";
2
+ import "urlpattern-polyfill";
3
+ globalThis.addEventListener = () => {};
4
+ import { n as version, t as name } from "./deno-DB1H1VHx.mjs";
5
+ import { n as doubleKnock } from "./http-D9zG-L9N.mjs";
6
+ import { SpanKind, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
7
+ import { getLogger } from "@logtape/logtape";
8
+ //#region src/federation/metrics.ts
9
+ var FederationMetrics = class {
10
+ deliverySent;
11
+ deliveryPermanentFailure;
12
+ signatureVerificationFailure;
13
+ deliveryDuration;
14
+ inboxProcessingDuration;
15
+ constructor(meterProvider) {
16
+ const meter = meterProvider.getMeter(name, version);
17
+ this.deliverySent = meter.createCounter("activitypub.delivery.sent", {
18
+ description: "ActivityPub delivery attempts.",
19
+ unit: "{attempt}"
20
+ });
21
+ this.deliveryPermanentFailure = meter.createCounter("activitypub.delivery.permanent_failure", {
22
+ description: "ActivityPub deliveries abandoned as permanent failures.",
23
+ unit: "{failure}"
24
+ });
25
+ this.signatureVerificationFailure = meter.createCounter("activitypub.signature.verification_failure", {
26
+ description: "ActivityPub signature verification failures.",
27
+ unit: "{failure}"
28
+ });
29
+ this.deliveryDuration = meter.createHistogram("activitypub.delivery.duration", {
30
+ description: "Duration of ActivityPub delivery attempts.",
31
+ unit: "ms"
32
+ });
33
+ this.inboxProcessingDuration = meter.createHistogram("activitypub.inbox.processing_duration", {
34
+ description: "Duration of ActivityPub inbox listener processing.",
35
+ unit: "ms"
36
+ });
37
+ }
38
+ recordDelivery(inbox, durationMs, success, activityType) {
39
+ const deliveryAttributes = {
40
+ "activitypub.remote.host": getRemoteHost(inbox),
41
+ "activitypub.delivery.success": success
42
+ };
43
+ if (activityType != null) deliveryAttributes["activitypub.activity.type"] = activityType;
44
+ this.deliverySent.add(1, deliveryAttributes);
45
+ this.deliveryDuration.record(durationMs, deliveryAttributes);
46
+ }
47
+ recordPermanentFailure(inbox, statusCode) {
48
+ this.deliveryPermanentFailure.add(1, {
49
+ "activitypub.remote.host": getRemoteHost(inbox),
50
+ "http.response.status_code": statusCode
51
+ });
52
+ }
53
+ recordSignatureVerificationFailure(reason, remoteHost) {
54
+ const attributes = { "activitypub.verification.failure_reason": reason };
55
+ if (remoteHost != null) attributes["activitypub.remote.host"] = remoteHost;
56
+ this.signatureVerificationFailure.add(1, attributes);
57
+ }
58
+ recordInboxProcessingDuration(activityType, durationMs) {
59
+ this.inboxProcessingDuration.record(durationMs, { "activitypub.activity.type": activityType });
60
+ }
61
+ };
62
+ const federationMetrics = /* @__PURE__ */ new WeakMap();
63
+ /**
64
+ * Gets the cached Fedify metric instruments for a meter provider.
65
+ * @since 2.3.0
66
+ */
67
+ function getFederationMetrics(meterProvider = metrics.getMeterProvider()) {
68
+ let instruments = federationMetrics.get(meterProvider);
69
+ if (instruments == null) {
70
+ instruments = new FederationMetrics(meterProvider);
71
+ federationMetrics.set(meterProvider, instruments);
72
+ }
73
+ return instruments;
74
+ }
75
+ /**
76
+ * Gets the bounded remote host attribute value for a URL.
77
+ * @since 2.3.0
78
+ */
79
+ function getRemoteHost(url) {
80
+ return url.hostname;
81
+ }
82
+ /**
83
+ * Gets an elapsed duration in milliseconds from a `performance.now()` value.
84
+ * @since 2.3.0
85
+ */
86
+ function getDurationMs(start) {
87
+ return Math.max(0, performance.now() - start);
88
+ }
89
+ //#endregion
90
+ //#region src/federation/send.ts
91
+ /**
92
+ * Extracts the inbox URLs from recipients.
93
+ * @param parameters The parameters to extract the inboxes.
94
+ * See also {@link ExtractInboxesParameters}.
95
+ * @returns The inboxes as a map of inbox URL to actor URIs.
96
+ */
97
+ function extractInboxes({ recipients, preferSharedInbox, excludeBaseUris }) {
98
+ const inboxes = {};
99
+ for (const recipient of recipients) {
100
+ let inbox;
101
+ let sharedInbox = false;
102
+ if (preferSharedInbox && recipient.endpoints?.sharedInbox != null) {
103
+ inbox = recipient.endpoints.sharedInbox;
104
+ sharedInbox = true;
105
+ } else inbox = recipient.inboxId;
106
+ if (inbox != null && recipient.id != null) {
107
+ if (excludeBaseUris != null && excludeBaseUris.some((u) => u.origin === inbox?.origin)) continue;
108
+ inboxes[inbox.href] ??= {
109
+ actorIds: /* @__PURE__ */ new Set(),
110
+ sharedInbox
111
+ };
112
+ inboxes[inbox.href].actorIds.add(recipient.id.href);
113
+ }
114
+ }
115
+ return inboxes;
116
+ }
117
+ /**
118
+ * Sends an {@link Activity} to an inbox.
119
+ *
120
+ * @param parameters The parameters for sending the activity.
121
+ * See also {@link SendActivityParameters}.
122
+ * @throws {Error} If the activity fails to send.
123
+ */
124
+ function sendActivity(options) {
125
+ const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
126
+ return tracerProvider.getTracer(name, version).startActiveSpan("activitypub.send_activity", {
127
+ kind: SpanKind.CLIENT,
128
+ attributes: { "activitypub.shared_inbox": options.sharedInbox ?? false }
129
+ }, async (span) => {
130
+ if (options.activityId != null) span.setAttribute("activitypub.activity.id", options.activityId);
131
+ if (options.activityType != null) span.setAttribute("activitypub.activity.type", options.activityType);
132
+ try {
133
+ await sendActivityInternal({
134
+ ...options,
135
+ tracerProvider
136
+ }, span);
137
+ } catch (e) {
138
+ span.setStatus({
139
+ code: SpanStatusCode.ERROR,
140
+ message: String(e)
141
+ });
142
+ throw e;
143
+ } finally {
144
+ span.end();
145
+ }
146
+ });
147
+ }
148
+ const MAX_ERROR_RESPONSE_BODY_BYTES = 1024;
149
+ function getActivityActorId(activity) {
150
+ if (!isRecord(activity)) return void 0;
151
+ return getIdValue(activity.actor);
152
+ }
153
+ function getIdValue(value) {
154
+ if (typeof value === "string" && value !== "") return value;
155
+ if (value instanceof URL) return value.href;
156
+ if (Array.isArray(value)) {
157
+ for (const item of value) {
158
+ const id = getIdValue(item);
159
+ if (id != null) return id;
160
+ }
161
+ return;
162
+ }
163
+ if (isRecord(value)) return getIdValue(value.id);
164
+ }
165
+ function isRecord(value) {
166
+ return typeof value === "object" && value != null;
167
+ }
168
+ async function readLimitedResponseBody(response, maxBytes) {
169
+ if (response.body == null) return "";
170
+ const reader = response.body.getReader();
171
+ const decoder = new TextDecoder();
172
+ const chunks = [];
173
+ let totalBytes = 0;
174
+ let truncated = false;
175
+ try {
176
+ while (true) {
177
+ const { done, value } = await reader.read();
178
+ if (done) break;
179
+ if (totalBytes + value.length > maxBytes) {
180
+ const remaining = maxBytes - totalBytes;
181
+ if (remaining > 0) chunks.push(decoder.decode(value.slice(0, remaining), { stream: true }));
182
+ truncated = true;
183
+ break;
184
+ }
185
+ chunks.push(decoder.decode(value, { stream: true }));
186
+ totalBytes += value.length;
187
+ }
188
+ } finally {
189
+ reader.releaseLock();
190
+ }
191
+ let result = chunks.join("");
192
+ if (truncated) result += "… (truncated)";
193
+ return result;
194
+ }
195
+ async function sendActivityInternal({ activity, activityId, activityType, keys, inbox, headers, specDeterminer, meterProvider, tracerProvider }, span) {
196
+ const logger = getLogger([
197
+ "fedify",
198
+ "federation",
199
+ "outbox"
200
+ ]);
201
+ const federationMetrics = getFederationMetrics(meterProvider);
202
+ const started = performance.now();
203
+ let deliverySuccess = false;
204
+ headers = new Headers(headers);
205
+ headers.set("Content-Type", "application/activity+json");
206
+ const request = new Request(inbox, {
207
+ method: "POST",
208
+ headers,
209
+ body: JSON.stringify(activity)
210
+ });
211
+ let rsaKey = null;
212
+ for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
213
+ rsaKey = key;
214
+ break;
215
+ }
216
+ if (rsaKey == null) logger.warn("No supported key found to sign the request to {inbox}. The request will be sent without a signature. In order to sign the request, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
217
+ inbox: inbox.href,
218
+ keys: keys.map((pair) => ({
219
+ keyId: pair.keyId.href,
220
+ privateKey: pair.privateKey
221
+ }))
222
+ });
223
+ let response;
224
+ try {
225
+ response = rsaKey == null ? await fetch(request) : await doubleKnock(request, rsaKey, {
226
+ tracerProvider,
227
+ specDeterminer
228
+ });
229
+ } catch (error) {
230
+ logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
231
+ activityId,
232
+ inbox: inbox.href,
233
+ error
234
+ });
235
+ federationMetrics.recordDelivery(inbox, getDurationMs(started), false, activityType);
236
+ throw error;
237
+ }
238
+ try {
239
+ if (!response.ok) {
240
+ let error;
241
+ try {
242
+ error = await readLimitedResponseBody(response, MAX_ERROR_RESPONSE_BODY_BYTES);
243
+ } catch (_) {
244
+ error = "";
245
+ }
246
+ logger.error("Failed to send activity {activityId} to {inbox} ({status} {statusText}):\n{error}", {
247
+ activityId,
248
+ inbox: inbox.href,
249
+ status: response.status,
250
+ statusText: response.statusText,
251
+ error
252
+ });
253
+ throw new SendActivityError(inbox, response.status, `Failed to send activity ${activityId} to ${inbox.href} (${response.status} ${response.statusText}):\n${error}`, error);
254
+ }
255
+ deliverySuccess = true;
256
+ const eventAttributes = {
257
+ "activitypub.inbox.url": inbox.href,
258
+ "activitypub.activity.id": activityId ?? ""
259
+ };
260
+ if (activityType != null) eventAttributes["activitypub.activity.type"] = activityType;
261
+ const actorId = getActivityActorId(activity);
262
+ if (actorId != null) eventAttributes["activitypub.actor.id"] = actorId;
263
+ span.addEvent("activitypub.activity.sent", eventAttributes);
264
+ } finally {
265
+ federationMetrics.recordDelivery(inbox, getDurationMs(started), deliverySuccess, activityType);
266
+ }
267
+ }
268
+ /**
269
+ * An error that is thrown when an activity fails to send to a remote inbox.
270
+ * It contains structured information about the failure, including the HTTP
271
+ * status code, the inbox URL, and the response body.
272
+ * @since 2.0.0
273
+ */
274
+ var SendActivityError = class extends Error {
275
+ /**
276
+ * The inbox URL that the activity was being sent to.
277
+ */
278
+ inbox;
279
+ /**
280
+ * The HTTP status code returned by the inbox.
281
+ */
282
+ statusCode;
283
+ /**
284
+ * The response body from the inbox, if any. Note that this may be
285
+ * truncated to a maximum of 1 KiB to prevent excessive memory consumption
286
+ * when remote servers return large error pages (e.g., Cloudflare error pages).
287
+ * If truncated, the string will end with `"… (truncated)"`.
288
+ */
289
+ responseBody;
290
+ /**
291
+ * Creates a new {@link SendActivityError}.
292
+ * @param inbox The inbox URL.
293
+ * @param statusCode The HTTP status code.
294
+ * @param message The error message.
295
+ * @param responseBody The response body.
296
+ */
297
+ constructor(inbox, statusCode, message, responseBody) {
298
+ super(message);
299
+ this.name = "SendActivityError";
300
+ this.inbox = inbox;
301
+ this.statusCode = statusCode;
302
+ this.responseBody = responseBody;
303
+ }
304
+ };
305
+ //#endregion
306
+ export { getFederationMetrics as a, getDurationMs as i, extractInboxes as n, getRemoteHost as o, sendActivity as r, SendActivityError as t };
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature, t as formatAcceptSignature } from "../accept-CPkZzmGN.mjs";
4
+ import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature, t as formatAcceptSignature } from "../accept-CceiKpCy.mjs";
5
5
  import { test } from "@fedify/fixture";
6
6
  import { deepStrictEqual, strictEqual } from "node:assert/strict";
7
7
  //#region src/sig/accept.test.ts
@@ -1,15 +1,15 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as esm_default } from "../esm-DVILvP5e.mjs";
5
4
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
5
  import { i as assertExists, t as assertStringIncludes } from "../std__assert-CRDpx_HF.mjs";
7
6
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
9
8
  import { t as assert } from "../assert-DikXweDx.mjs";
10
- import { t as exportJwk } from "../key-C1Oto4it.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-CX_zHeOD.mjs";
12
- import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
9
+ import { t as esm_default } from "../esm-DhnRLoG9.mjs";
10
+ import { t as exportJwk } from "../key-CV57mOYH.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-D9zG-L9N.mjs";
12
+ import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-C3kae-6B.mjs";
13
13
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
15
15
  import { encodeBase64 } from "byte-encodings/base64";
@@ -5,8 +5,8 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-CRDpx_HF.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-C1Oto4it.mjs";
9
- import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
8
+ import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-CV57mOYH.mjs";
9
+ import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-C3kae-6B.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { CryptographicKey, Multikey } from "@fedify/vocab";
12
12
  import { FetchError } from "@fedify/vocab-runtime";
@@ -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-DikXweDx.mjs";
8
- import { i as generateCryptoKeyPair } from "../key-C1Oto4it.mjs";
9
- import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.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-Dl1HIB1a.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-CV57mOYH.mjs";
9
+ import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-C3kae-6B.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-sUf94RJ8.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-Du1Jgf2P.cjs");
5
- const require_proof = require("../proof-CDA3f-i5.cjs");
4
+ const require_http = require("../http-FnUTcdMf.cjs");
5
+ const require_proof = require("../proof-BhJpq_J9.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-1NL30qCe.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-Dedf8md5.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-BUr93aO6.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-k4mEvvdS.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 };
@@ -5,8 +5,8 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-CRDpx_HF.mjs";
6
6
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assert } from "../assert-DikXweDx.mjs";
8
- import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CEWFJlqo.mjs";
8
+ import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-C3kae-6B.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-DsPgl527.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
@@ -6,9 +6,9 @@ import "../std__assert-CRDpx_HF.mjs";
6
6
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
- import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
10
- import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-CNmZLixq.mjs";
11
- import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-BFyPVl1r.mjs";
9
+ import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-C3kae-6B.mjs";
10
+ import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-Bi7n-dEy.mjs";
11
+ import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-iVfYyJpY.mjs";
12
12
  import { mockDocumentLoader, test } from "@fedify/fixture";
13
13
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place } from "@fedify/vocab";
14
14
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
@@ -3,7 +3,7 @@ import { URLPattern } from "urlpattern-polyfill";
3
3
  import { testDefinitions } from "@fedify/fixture";
4
4
  import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
5
5
  import { Link as Link$1, LookupWebFingerOptions, ResourceDescriptor } from "@fedify/webfinger";
6
- import { TracerProvider } from "@opentelemetry/api";
6
+ import { MeterProvider, TracerProvider } from "@opentelemetry/api";
7
7
  import { DocumentLoader, GetUserAgentOptions } from "@fedify/vocab-runtime";
8
8
 
9
9
  //#region src/nodeinfo/types.d.ts
@@ -1137,6 +1137,18 @@ interface ActorCallbackSetters<TContextData> {
1137
1137
  * @since 1.4.0
1138
1138
  */
1139
1139
  mapAlias(mapper: ActorAliasMapper<TContextData>): ActorCallbackSetters<TContextData>;
1140
+ /**
1141
+ * Maps a fixed path to a sentinel identifier. It is useful for exposing
1142
+ * a single, instance-level actor at a fixed path, such as `/actor` for
1143
+ * a relay or `/bot` for a bot.
1144
+ * @param path The fixed path to map to the identifier.
1145
+ * @param identifier The sentinel identifier to map the path to.
1146
+ * @returns The setters object so that settings can be chained.
1147
+ * @throws {RouterError} If the provided path or identifier is invalid or fails
1148
+ * runtime validation.
1149
+ * @since 2.3.0
1150
+ */
1151
+ mapActorAlias(path: `/${string}`, identifier: string): ActorCallbackSetters<TContextData>;
1140
1152
  /**
1141
1153
  * Specifies the conditions under which requests are authorized.
1142
1154
  * @param predicate A callback that returns whether a request is authorized.
@@ -1495,6 +1507,11 @@ interface Context<TContextData> {
1495
1507
  * @since 1.3.0
1496
1508
  */
1497
1509
  readonly tracerProvider: TracerProvider;
1510
+ /**
1511
+ * The OpenTelemetry meter provider.
1512
+ * @since 2.3.0
1513
+ */
1514
+ readonly meterProvider?: MeterProvider;
1498
1515
  /**
1499
1516
  * The document loader for loading remote JSON-LD documents.
1500
1517
  */
@@ -1,6 +1,6 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-Dk_tacqz.mjs";
4
+ import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-7Azky82W.mjs";
5
5
  import { testDefinitions } from "@fedify/fixture";
6
6
  export { createInboxContext, createOutboxContext, createRequestContext, testDefinitions };
@@ -1,13 +1,13 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as esm_default } from "../esm-DVILvP5e.mjs";
5
4
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
5
  import "../std__assert-CRDpx_HF.mjs";
7
6
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
- import { l as verifyRequest } from "../http-CX_zHeOD.mjs";
9
- import { i as rsaPrivateKey2 } from "../keys-DGu1NFwu.mjs";
10
- import { t as getAuthenticatedDocumentLoader } from "../docloader-q9QT51g3.mjs";
7
+ import { t as esm_default } from "../esm-DhnRLoG9.mjs";
8
+ import { l as verifyRequest } from "../http-D9zG-L9N.mjs";
9
+ import { i as rsaPrivateKey2 } from "../keys-C3kae-6B.mjs";
10
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-3HwiWeYL.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,7 +1,7 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as kvCache, t as MockKvStore } from "../kv-cache-U__xU4qR.mjs";
4
+ import { n as kvCache, t as MockKvStore } from "../kv-cache-Bmv7tUzz.mjs";
5
5
  import { mockDocumentLoader, test } from "@fedify/fixture";
6
6
  import { deepStrictEqual, throws } from "node:assert";
7
7
  import { preloadedContexts } from "@fedify/vocab-runtime";
@@ -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-aGOwL6Vj.cjs");
4
+ const require_kv_cache = require("../kv-cache-BG9O8wVV.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-CsC3P4uu.js";
3
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-C3esyJFP.js";
4
4
  export { getAuthenticatedDocumentLoader, kvCache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/fedify",
3
- "version": "2.3.0-dev.1013+4aa6a88c",
3
+ "version": "2.3.0-dev.1034+b85b5daa",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",
@@ -153,11 +153,12 @@
153
153
  "uri-template-router": "^1.0.0",
154
154
  "url-template": "^3.1.1",
155
155
  "urlpattern-polyfill": "^10.1.0",
156
- "@fedify/vocab": "2.3.0-dev.1013+4aa6a88c",
157
- "@fedify/vocab-runtime": "2.3.0-dev.1013+4aa6a88c",
158
- "@fedify/webfinger": "2.3.0-dev.1013+4aa6a88c"
156
+ "@fedify/vocab-runtime": "2.3.0-dev.1034+b85b5daa",
157
+ "@fedify/vocab": "2.3.0-dev.1034+b85b5daa",
158
+ "@fedify/webfinger": "2.3.0-dev.1034+b85b5daa"
159
159
  },
160
160
  "devDependencies": {
161
+ "@opentelemetry/sdk-metrics": "2.5.0",
161
162
  "@std/assert": "npm:@jsr/std__assert@^0.226.0",
162
163
  "@std/path": "npm:@jsr/std__path@^1.0.6",
163
164
  "@types/node": "^24.2.1",
@@ -167,8 +168,8 @@
167
168
  "tsx": "^4.19.4",
168
169
  "typescript": "^5.9.2",
169
170
  "wrangler": "^4.17.0",
170
- "@fedify/vocab-tools": "^2.3.0-dev.1013+4aa6a88c",
171
- "@fedify/fixture": "2.0.0"
171
+ "@fedify/fixture": "2.0.0",
172
+ "@fedify/vocab-tools": "^2.3.0-dev.1034+b85b5daa"
172
173
  },
173
174
  "scripts": {
174
175
  "build:self": "tsdown",