@fedify/fedify 2.3.0-dev.1119 → 2.3.0-dev.1131

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 (68) hide show
  1. package/dist/{builder-Ond_h57y.mjs → builder-DckAhD27.mjs} +2 -2
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{context-cSUMk2da.d.ts → context-Cq18Gplu.d.ts} +3 -208
  6. package/dist/{context-Ch-ZLyTQ.d.cts → context-tc6VOOOL.d.cts} +3 -208
  7. package/dist/{deno-DVsHS7rA.mjs → deno--CS-SBS9.mjs} +1 -1
  8. package/dist/{docloader-WsWfKaE5.mjs → docloader-k6huZLQL.mjs} +2 -2
  9. package/dist/federation/builder.test.mjs +1 -1
  10. package/dist/federation/handler.test.mjs +2 -2
  11. package/dist/federation/idempotency.test.mjs +2 -2
  12. package/dist/federation/metrics.test.mjs +229 -1
  13. package/dist/federation/middleware.test.mjs +64 -6
  14. package/dist/federation/mod.cjs +1 -1
  15. package/dist/federation/mod.d.cts +3 -2
  16. package/dist/federation/mod.d.ts +3 -2
  17. package/dist/federation/mod.js +1 -1
  18. package/dist/federation/send.test.mjs +3 -3
  19. package/dist/federation/webfinger.test.mjs +1 -1
  20. package/dist/{http-CubOB9wq.cjs → http-CJfvRL7D.cjs} +263 -19
  21. package/dist/{http-DUV8ysti.mjs → http-IywnQdiX.mjs} +7 -5
  22. package/dist/{http-D6LP89UO.d.ts → http-VyDTd4G3.d.cts} +8 -1
  23. package/dist/{http-CouJSFVK.js → http-cqujdCRz.js} +252 -20
  24. package/dist/{http-D6aw3j2U.d.cts → http-lf8Hsd91.d.ts} +8 -1
  25. package/dist/{key-BoWaYRHm.mjs → key-Df3tMleh.mjs} +42 -17
  26. package/dist/{kv-cache-Dz31ATUT.cjs → kv-cache-L0SMQkcd.cjs} +19 -2
  27. package/dist/{kv-cache-DBNpsneh.js → kv-cache-pEejzYq4.js} +19 -2
  28. package/dist/{kv-cache-DihufyAQ.mjs → kv-cache-q9Ec2ryS.mjs} +19 -1
  29. package/dist/{ld-B5K1mSuG.mjs → ld-BGwiJpl3.mjs} +3 -3
  30. package/dist/{metrics-C4attqv0.mjs → metrics-BTOMkW8C.mjs} +209 -2
  31. package/dist/{middleware-CmsDtIHI.cjs → middleware-B2rtdpFV.cjs} +45 -17
  32. package/dist/{middleware-t0jC8I99.mjs → middleware-BB0IbDow.mjs} +54 -26
  33. package/dist/{middleware-BDKFRjue.mjs → middleware-Dnql59Y8.mjs} +1 -1
  34. package/dist/{middleware-Dtjz-hSk.js → middleware-DtOddSVg.js} +45 -17
  35. package/dist/{mod-BDhgfjP7.d.cts → mod-B0hW12_O.d.cts} +1 -1
  36. package/dist/{mod-B-Lin9Sy.d.ts → mod-COIAjwRS.d.ts} +1 -1
  37. package/dist/{mod-C6E8rkcz.d.ts → mod-CajNYYkt.d.ts} +1 -1
  38. package/dist/{mod-DLrRb0dx.d.ts → mod-DFvNJcNb.d.ts} +54 -3
  39. package/dist/{mod-P9tE2WmM.d.cts → mod-DnzgcPcy.d.cts} +1 -1
  40. package/dist/{mod-BR_BB0bh.d.cts → mod-yvIXFAEi.d.cts} +54 -3
  41. package/dist/mod.cjs +4 -4
  42. package/dist/mod.d.cts +6 -5
  43. package/dist/mod.d.ts +6 -5
  44. package/dist/mod.js +4 -4
  45. package/dist/mq-D-nlpY04.d.ts +208 -0
  46. package/dist/mq-D8uSFzxe.d.cts +208 -0
  47. package/dist/nodeinfo/handler.test.mjs +1 -1
  48. package/dist/{owner-hDxI0ufu.mjs → owner-CIt4hvmM.mjs} +2 -2
  49. package/dist/{proof-BUWfVr6Q.cjs → proof-B1_u25UV.cjs} +1 -1
  50. package/dist/{proof-DhVuz4bc.mjs → proof-BYlrRSmZ.mjs} +3 -3
  51. package/dist/{proof-n60t8o9P.js → proof-DMGIjHYH.js} +1 -1
  52. package/dist/{send-BPhyR5Oo.mjs → send-DJFpze7B.mjs} +3 -3
  53. package/dist/sig/http.test.mjs +6 -2
  54. package/dist/sig/key.test.mjs +99 -2
  55. package/dist/sig/ld.test.mjs +2 -2
  56. package/dist/sig/mod.cjs +2 -2
  57. package/dist/sig/mod.d.cts +2 -2
  58. package/dist/sig/mod.d.ts +2 -2
  59. package/dist/sig/mod.js +2 -2
  60. package/dist/sig/owner.test.mjs +1 -1
  61. package/dist/sig/proof.test.mjs +1 -1
  62. package/dist/utils/docloader.test.mjs +2 -2
  63. package/dist/utils/kv-cache.test.mjs +67 -2
  64. package/dist/utils/mod.cjs +1 -1
  65. package/dist/utils/mod.d.cts +1 -1
  66. package/dist/utils/mod.d.ts +1 -1
  67. package/dist/utils/mod.js +1 -1
  68. package/package.json +6 -6
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { E as version, T as name, d as validateCryptoKey, f as getDurationMs, g as measureSignatureKeyFetch, p as getFederationMetrics, s as fetchKey } from "./http-CouJSFVK.js";
3
+ import { D as name, O as version, _ as measureSignatureKeyFetch, d as validateCryptoKey, f as getDurationMs, p as getFederationMetrics, s as fetchKey } from "./http-cqujdCRz.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";
@@ -1,9 +1,9 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-DVsHS7rA.mjs";
5
- import { n as getFederationMetrics, t as getDurationMs } from "./metrics-C4attqv0.mjs";
6
- import { n as doubleKnock } from "./http-DUV8ysti.mjs";
4
+ import { n as version, t as name } from "./deno--CS-SBS9.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics } from "./metrics-BTOMkW8C.mjs";
6
+ import { n as doubleKnock } from "./http-IywnQdiX.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
9
9
  //#region src/federation/send.ts
@@ -7,8 +7,8 @@ import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
9
  import { t as esm_default } from "../esm-sdtqOUPu.mjs";
10
- import { t as exportJwk } from "../key-BoWaYRHm.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-DUV8ysti.mjs";
10
+ import { t as exportJwk } from "../key-Df3tMleh.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-IywnQdiX.mjs";
12
12
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-CSYsOMFG.mjs";
13
13
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
@@ -259,6 +259,10 @@ test("verifyRequestDetailed() records verification duration metric", async (t) =
259
259
  assertEquals(measurement.attributes["activitypub.signature.result"], "verified");
260
260
  assertEquals(measurement.attributes["http_signatures.algorithm"], "rsa-sha256");
261
261
  assertFalse("http_signatures.failure_reason" in measurement.attributes);
262
+ const keyLookups = recorder.getMeasurements("activitypub.key.lookup");
263
+ assertEquals(keyLookups.length, 1);
264
+ assertEquals(keyLookups[0].attributes["activitypub.lookup.kind"], "public_key");
265
+ assertEquals(keyLookups[0].attributes["activitypub.lookup.result"], "fetched");
262
266
  });
263
267
  await t.step("missing signature is recorded as result=missing", async () => {
264
268
  const [meterProvider, recorder] = createTestMeterProvider();
@@ -5,10 +5,10 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-BTEgfoJo.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-DQP-q39h.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-BoWaYRHm.mjs";
8
+ import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-Df3tMleh.mjs";
9
9
  import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-CSYsOMFG.mjs";
10
10
  import { CryptographicKey, Multikey } from "@fedify/vocab";
11
- import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
+ import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { FetchError } from "@fedify/vocab-runtime";
13
13
  //#region src/sig/key.test.ts
14
14
  test("validateCryptoKey()", async () => {
@@ -303,5 +303,102 @@ test("fetchKeyDetailed() returns detailed fetch errors", async () => {
303
303
  if (detailedError == null || !("error" in detailedError)) throw new Error("Expected non-HTTP fetch error details.");
304
304
  assertEquals(detailedError.error, failure);
305
305
  });
306
+ test("fetchKey() records activitypub.key.lookup with hit on cached key", async () => {
307
+ const [meterProvider, recorder] = createTestMeterProvider();
308
+ const cache = {};
309
+ const options = {
310
+ documentLoader: mockDocumentLoader,
311
+ contextLoader: mockDocumentLoader,
312
+ keyCache: {
313
+ get(keyId) {
314
+ return Promise.resolve(cache[keyId.href]);
315
+ },
316
+ set(keyId, key) {
317
+ cache[keyId.href] = key;
318
+ return Promise.resolve();
319
+ }
320
+ },
321
+ meterProvider
322
+ };
323
+ await fetchKey("https://example.com/key", CryptographicKey, options);
324
+ recorder.clear();
325
+ assertEquals((await fetchKey("https://example.com/key", CryptographicKey, options)).cached, true);
326
+ const counters = recorder.getMeasurements("activitypub.key.lookup");
327
+ assertEquals(counters.length, 1);
328
+ assertEquals(counters[0].attributes["activitypub.lookup.kind"], "public_key");
329
+ assertEquals(counters[0].attributes["activitypub.lookup.result"], "hit");
330
+ assertEquals(counters[0].attributes["activitypub.cache.enabled"], true);
331
+ assertEquals(counters[0].attributes["activitypub.remote.host"], "example.com");
332
+ const duration = recorder.getMeasurement("activitypub.key.lookup.duration");
333
+ assertEquals(duration?.type, "histogram");
334
+ assertEquals(duration?.attributes["activitypub.lookup.result"], "hit");
335
+ });
336
+ test("fetchKey() records activitypub.key.lookup with fetched on cache miss", async () => {
337
+ const [meterProvider, recorder] = createTestMeterProvider();
338
+ assertEquals((await fetchKey("https://example.com/key", CryptographicKey, {
339
+ documentLoader: mockDocumentLoader,
340
+ contextLoader: mockDocumentLoader,
341
+ meterProvider
342
+ })).cached, false);
343
+ const counter = recorder.getMeasurement("activitypub.key.lookup");
344
+ assertEquals(counter?.attributes["activitypub.lookup.result"], "fetched");
345
+ assertEquals(counter?.attributes["activitypub.cache.enabled"], false);
346
+ assertEquals(counter?.attributes["activitypub.remote.host"], "example.com");
347
+ assertEquals(recorder.getMeasurement("activitypub.key.lookup.duration")?.attributes["activitypub.lookup.result"], "fetched");
348
+ });
349
+ test("fetchKey() records not_found and status code on HTTP 404", async () => {
350
+ const [meterProvider, recorder] = createTestMeterProvider();
351
+ const missingKeyId = new URL("https://example.com/missing-key");
352
+ const documentLoader = (url) => {
353
+ if (url === missingKeyId.href) throw new FetchError(missingKeyId, `HTTP 404: ${missingKeyId.href}`, new Response(null, { status: 404 }));
354
+ return mockDocumentLoader(url);
355
+ };
356
+ assertEquals((await fetchKey(missingKeyId, CryptographicKey, {
357
+ documentLoader,
358
+ contextLoader: mockDocumentLoader,
359
+ meterProvider
360
+ })).key, null);
361
+ const counter = recorder.getMeasurement("activitypub.key.lookup");
362
+ assertEquals(counter?.attributes["activitypub.lookup.result"], "not_found");
363
+ assertEquals(counter?.attributes["http.response.status_code"], 404);
364
+ assertEquals(counter?.attributes["activitypub.cache.enabled"], false);
365
+ assertEquals(counter?.attributes["activitypub.remote.host"], "example.com");
366
+ });
367
+ test("fetchKey() records network_error on TypeError from the document loader", async () => {
368
+ const [meterProvider, recorder] = createTestMeterProvider();
369
+ const documentLoader = () => {
370
+ throw new TypeError("connect failed");
371
+ };
372
+ await fetchKey("https://example.com/key", CryptographicKey, {
373
+ documentLoader,
374
+ contextLoader: mockDocumentLoader,
375
+ meterProvider
376
+ });
377
+ const counter = recorder.getMeasurement("activitypub.key.lookup");
378
+ assertEquals(counter?.attributes["activitypub.lookup.result"], "network_error");
379
+ assertEquals("http.response.status_code" in counter.attributes, false);
380
+ });
381
+ test("fetchKeyDetailed() records activitypub.key.lookup with the same taxonomy", async () => {
382
+ const [meterProvider, recorder] = createTestMeterProvider();
383
+ const goneKeyId = new URL("https://example.com/gone-key");
384
+ const documentLoader = (url) => {
385
+ if (url === goneKeyId.href) throw new FetchError(goneKeyId, `HTTP 410: ${goneKeyId.href}`, new Response(null, { status: 410 }));
386
+ return mockDocumentLoader(url);
387
+ };
388
+ await fetchKeyDetailed(goneKeyId, CryptographicKey, {
389
+ documentLoader,
390
+ contextLoader: mockDocumentLoader,
391
+ meterProvider
392
+ });
393
+ const counter = recorder.getMeasurement("activitypub.key.lookup");
394
+ assertEquals(counter?.attributes["activitypub.lookup.result"], "not_found");
395
+ assertEquals(counter?.attributes["http.response.status_code"], 410);
396
+ });
397
+ test("fetchKey() works when meterProvider is omitted", async () => {
398
+ assertEquals((await fetchKey("https://example.com/key", CryptographicKey, {
399
+ documentLoader: mockDocumentLoader,
400
+ contextLoader: mockDocumentLoader
401
+ })).cached, false);
402
+ });
306
403
  //#endregion
307
404
  export {};
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from "../assert_rejects-DQP-q39h.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-BoWaYRHm.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-Df3tMleh.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-CSYsOMFG.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-B5K1mSuG.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-BGwiJpl3.mjs";
11
11
  import { CryptographicKey } from "@fedify/vocab";
12
12
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
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-CubOB9wq.cjs");
5
- const require_proof = require("../proof-BUWfVr6Q.cjs");
4
+ const require_http = require("../http-CJfvRL7D.cjs");
5
+ const require_proof = require("../proof-B1_u25UV.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-D6aw3j2U.cjs";
2
+ import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-VyDTd4G3.cjs";
3
3
  import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-DEvZuyOE.cjs";
4
- import { _ as hasSignatureLike, a as createProof, b as verifySignature, c as verifyObject, d as SignJsonLdOptions, f as VerifyJsonLdOptions, g as detachSignature, h as createSignature, i as VerifyProofOptions, l as verifyProof, m as attachSignature, n as SignObjectOptions, o as hasProofLike, p as VerifySignatureOptions, r as VerifyObjectOptions, s as signObject, t as CreateProofOptions, u as CreateSignatureOptions, v as signJsonLd, y as verifyJsonLd } from "../mod-BDhgfjP7.cjs";
4
+ import { _ as hasSignatureLike, a as createProof, b as verifySignature, c as verifyObject, d as SignJsonLdOptions, f as VerifyJsonLdOptions, g as detachSignature, h as createSignature, i as VerifyProofOptions, l as verifyProof, m as attachSignature, n as SignObjectOptions, o as hasProofLike, p as VerifySignatureOptions, r as VerifyObjectOptions, s as signObject, t as CreateProofOptions, u as CreateSignatureOptions, v as signJsonLd, y as verifyJsonLd } from "../mod-B0hW12_O.cjs";
5
5
  export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, 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 };
package/dist/sig/mod.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-D6LP89UO.js";
2
+ import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-lf8Hsd91.js";
3
3
  import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-CnngXDNJ.js";
4
- import { _ as hasSignatureLike, a as createProof, b as verifySignature, c as verifyObject, d as SignJsonLdOptions, f as VerifyJsonLdOptions, g as detachSignature, h as createSignature, i as VerifyProofOptions, l as verifyProof, m as attachSignature, n as SignObjectOptions, o as hasProofLike, p as VerifySignatureOptions, r as VerifyObjectOptions, s as signObject, t as CreateProofOptions, u as CreateSignatureOptions, v as signJsonLd, y as verifyJsonLd } from "../mod-B-Lin9Sy.js";
4
+ import { _ as hasSignatureLike, a as createProof, b as verifySignature, c as verifyObject, d as SignJsonLdOptions, f as VerifyJsonLdOptions, g as detachSignature, h as createSignature, i as VerifyProofOptions, l as verifyProof, m as attachSignature, n as SignObjectOptions, o as hasProofLike, p as VerifySignatureOptions, r as VerifyObjectOptions, s as signObject, t as CreateProofOptions, u as CreateSignatureOptions, v as signJsonLd, y as verifyJsonLd } from "../mod-COIAjwRS.js";
5
5
  export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, 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 };
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { C as parseAcceptSignature, S as fulfillAcceptSignature, a as verifyRequestDetailed, c as fetchKeyDetailed, i as verifyRequest, l as generateCryptoKeyPair, o as exportJwk, r as signRequest, s as fetchKey, u as importJwk, w as validateAcceptSignature, x as formatAcceptSignature } from "../http-CouJSFVK.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-n60t8o9P.js";
3
+ import { C as formatAcceptSignature, E as validateAcceptSignature, T as parseAcceptSignature, a as verifyRequestDetailed, c as fetchKeyDetailed, i as verifyRequest, l as generateCryptoKeyPair, o as exportJwk, r as signRequest, s as fetchKey, u as importJwk, w as fulfillAcceptSignature } from "../http-cqujdCRz.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-DMGIjHYH.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-BTEgfoJo.mjs";
6
6
  import { r as assertFalse } from "../assert_rejects-DQP-q39h.mjs";
7
7
  import { t as assert } from "../assert-DikXweDx.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-CSYsOMFG.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-hDxI0ufu.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CIt4hvmM.mjs";
10
10
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
11
11
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/sig/owner.test.ts
@@ -8,7 +8,7 @@ import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
9
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-CSYsOMFG.mjs";
10
10
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-BNL8AC14.mjs";
11
- import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-DhVuz4bc.mjs";
11
+ import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-BYlrRSmZ.mjs";
12
12
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place } from "@fedify/vocab";
13
13
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-BTEgfoJo.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-DQP-q39h.mjs";
7
7
  import { t as esm_default } from "../esm-sdtqOUPu.mjs";
8
- import { l as verifyRequest } from "../http-DUV8ysti.mjs";
8
+ import { l as verifyRequest } from "../http-IywnQdiX.mjs";
9
9
  import { i as rsaPrivateKey2 } from "../keys-CSYsOMFG.mjs";
10
- import { t as getAuthenticatedDocumentLoader } from "../docloader-WsWfKaE5.mjs";
10
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-k6huZLQL.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,9 +1,9 @@
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-DihufyAQ.mjs";
4
+ import { n as kvCache, t as MockKvStore } from "../kv-cache-q9Ec2ryS.mjs";
5
5
  import { deepStrictEqual, throws } from "node:assert";
6
- import { mockDocumentLoader, test } from "@fedify/fixture";
6
+ import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
7
7
  import { preloadedContexts } from "@fedify/vocab-runtime";
8
8
  //#region src/utils/kv-cache.test.ts
9
9
  test("kvCache()", async (t) => {
@@ -139,6 +139,71 @@ test("kvCache()", async (t) => {
139
139
  }
140
140
  });
141
141
  });
142
+ await t.step("records activitypub.document.cache with miss then hit", async () => {
143
+ const kv = new MockKvStore();
144
+ const [meterProvider, recorder] = createTestMeterProvider();
145
+ const loader = kvCache({
146
+ kv,
147
+ loader: mockDocumentLoader,
148
+ rules: [["https://example.com/object", { days: 1 }]],
149
+ prefix: ["_test", "doc-cache"],
150
+ meterProvider,
151
+ kind: "object"
152
+ });
153
+ await loader("https://example.com/object");
154
+ const afterMiss = recorder.getMeasurements("activitypub.document.cache");
155
+ deepStrictEqual(afterMiss.length, 1);
156
+ deepStrictEqual(afterMiss[0].type, "counter");
157
+ deepStrictEqual(afterMiss[0].value, 1);
158
+ deepStrictEqual(afterMiss[0].attributes["activitypub.lookup.kind"], "object");
159
+ deepStrictEqual(afterMiss[0].attributes["activitypub.lookup.result"], "miss");
160
+ deepStrictEqual(afterMiss[0].attributes["activitypub.remote.host"], "example.com");
161
+ await loader("https://example.com/object");
162
+ const all = recorder.getMeasurements("activitypub.document.cache");
163
+ deepStrictEqual(all.length, 2);
164
+ deepStrictEqual(all[1].attributes["activitypub.lookup.result"], "hit");
165
+ deepStrictEqual(all[1].attributes["activitypub.lookup.kind"], "object");
166
+ deepStrictEqual(all[1].attributes["activitypub.remote.host"], "example.com");
167
+ });
168
+ await t.step("preloaded contexts emit no activitypub.document.cache", async () => {
169
+ const kv = new MockKvStore();
170
+ const [meterProvider, recorder] = createTestMeterProvider();
171
+ await kvCache({
172
+ kv,
173
+ loader: mockDocumentLoader,
174
+ prefix: ["_test", "doc-cache-preloaded"],
175
+ meterProvider,
176
+ kind: "context"
177
+ })("https://www.w3.org/ns/activitystreams");
178
+ deepStrictEqual(recorder.getMeasurements("activitypub.document.cache").length, 0, "preloaded contexts must bypass the KV cache and the cache metric");
179
+ });
180
+ await t.step("no cache rule match emits no activitypub.document.cache", async () => {
181
+ const kv = new MockKvStore();
182
+ const [meterProvider, recorder] = createTestMeterProvider();
183
+ await kvCache({
184
+ kv,
185
+ loader: mockDocumentLoader,
186
+ rules: [],
187
+ prefix: ["_test", "doc-cache-no-rule"],
188
+ meterProvider,
189
+ kind: "object"
190
+ })("https://example.com/object");
191
+ deepStrictEqual(recorder.getMeasurements("activitypub.document.cache").length, 0);
192
+ });
193
+ await t.step("omitting meterProvider records no cache measurements", async () => {
194
+ const kv = new MockKvStore();
195
+ const [meterProvider, recorder] = createTestMeterProvider();
196
+ const loader = kvCache({
197
+ kv,
198
+ loader: mockDocumentLoader,
199
+ rules: [["https://example.com/object", { days: 1 }]],
200
+ prefix: ["_test", "doc-cache-no-mp"]
201
+ });
202
+ await loader("https://example.com/object");
203
+ await loader("https://example.com/object");
204
+ deepStrictEqual(recorder.getMeasurements("activitypub.document.cache").length, 0);
205
+ deepStrictEqual(typeof meterProvider.getMeter, "function");
206
+ });
142
207
  await t.step("preloaded contexts bypass cache", async () => {
143
208
  const kv = new MockKvStore();
144
209
  let loaderCalled = false;
@@ -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-Dz31ATUT.cjs");
4
+ const require_kv_cache = require("../kv-cache-L0SMQkcd.cjs");
5
5
  exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
6
6
  exports.kvCache = require_kv_cache.kvCache;
@@ -1,3 +1,3 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-BR_BB0bh.cjs";
2
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-yvIXFAEi.cjs";
3
3
  export { getAuthenticatedDocumentLoader, kvCache };
@@ -1,3 +1,3 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-DLrRb0dx.js";
2
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-DFvNJcNb.js";
3
3
  export { getAuthenticatedDocumentLoader, kvCache };
package/dist/utils/mod.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-DBNpsneh.js";
3
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-pEejzYq4.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.1119+6cc02662",
3
+ "version": "2.3.0-dev.1131+553b59b8",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",
@@ -153,9 +153,9 @@
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.1119+6cc02662",
157
- "@fedify/vocab-runtime": "2.3.0-dev.1119+6cc02662",
158
- "@fedify/webfinger": "2.3.0-dev.1119+6cc02662"
156
+ "@fedify/vocab": "2.3.0-dev.1131+553b59b8",
157
+ "@fedify/webfinger": "2.3.0-dev.1131+553b59b8",
158
+ "@fedify/vocab-runtime": "2.3.0-dev.1131+553b59b8"
159
159
  },
160
160
  "devDependencies": {
161
161
  "@opentelemetry/sdk-metrics": "2.7.1",
@@ -168,8 +168,8 @@
168
168
  "tsx": "^4.21.0",
169
169
  "typescript": "^6.0.0",
170
170
  "wrangler": "^4.17.0",
171
- "@fedify/fixture": "2.0.0",
172
- "@fedify/vocab-tools": "^2.3.0-dev.1119+6cc02662"
171
+ "@fedify/vocab-tools": "^2.3.0-dev.1131+553b59b8",
172
+ "@fedify/fixture": "2.0.0"
173
173
  },
174
174
  "scripts": {
175
175
  "build:self": "tsdown",