@fedify/fedify 2.4.0-dev.1567 → 2.4.0-dev.1570

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 (113) hide show
  1. package/README.md +4 -0
  2. package/dist/{assert-OguE97r2.mjs → assert-DvVHoIZ0.mjs} +1 -1
  3. package/dist/{assert_instance_of-DBC5X09g.mjs → assert_instance_of-CxoC8bVq.mjs} +1 -1
  4. package/dist/{assert_not_equals-DkVK8oqV.mjs → assert_not_equals-C8vcTTA3.mjs} +1 -1
  5. package/dist/{assert_rejects-DN60FHPX.mjs → assert_rejects-DAdaaIWM.mjs} +2 -2
  6. package/dist/{assert_strict_equals-XEgZAlrj.mjs → assert_strict_equals-BzqyKuYL.mjs} +1 -1
  7. package/dist/{assert_throws-BOkhLGYc.mjs → assert_throws-zN79lgIC.mjs} +1 -1
  8. package/dist/{builder-DGWCUaNQ.mjs → builder-CJnWbgbj.mjs} +23 -3
  9. package/dist/codec-nfBU4Up4.mjs +124 -0
  10. package/dist/compat/mod.d.cts +1 -1
  11. package/dist/compat/mod.d.ts +1 -1
  12. package/dist/compat/outgoing-jsonld.test.mjs +3 -3
  13. package/dist/compat/public-audience.test.mjs +3 -3
  14. package/dist/compat/transformers.test.mjs +5 -5
  15. package/dist/{context-DVoTs_wM.mjs → context-BBRTgkrs.mjs} +8 -2
  16. package/dist/{context-BBVLF7lx.d.cts → context-BLe0NPtZ.d.cts} +530 -259
  17. package/dist/{context-BU6jSQdo.d.ts → context-GfQA-CqB.d.ts} +529 -259
  18. package/dist/{deno-Dho0TW0X.mjs → deno-klNxGW7W.mjs} +1 -1
  19. package/dist/{docloader-DCQSgDOg.mjs → docloader-CuFH35j1.mjs} +3 -3
  20. package/dist/federation/builder.test.mjs +5 -5
  21. package/dist/federation/circuit-breaker.test.mjs +5 -5
  22. package/dist/federation/collection.test.mjs +3 -3
  23. package/dist/federation/handler.test.mjs +13 -23
  24. package/dist/federation/idempotency.test.mjs +6 -6
  25. package/dist/federation/inbox.test.mjs +3 -3
  26. package/dist/federation/keycache.test.mjs +5 -5
  27. package/dist/federation/kv.test.mjs +3 -3
  28. package/dist/federation/metrics.test.mjs +4 -4
  29. package/dist/federation/middleware.test.mjs +204 -19
  30. package/dist/federation/mod.cjs +3 -259
  31. package/dist/federation/mod.d.cts +4 -4
  32. package/dist/federation/mod.d.ts +4 -4
  33. package/dist/federation/mod.js +1 -257
  34. package/dist/federation/mq.test.mjs +103 -261
  35. package/dist/federation/negotiation.test.mjs +4 -4
  36. package/dist/federation/retry.test.mjs +3 -3
  37. package/dist/federation/router.test.mjs +5 -5
  38. package/dist/federation/send.test.mjs +10 -10
  39. package/dist/federation/tasks/codec.test.d.mts +2 -0
  40. package/dist/federation/tasks/codec.test.mjs +302 -0
  41. package/dist/federation/tasks/enqueue.test.d.mts +2 -0
  42. package/dist/federation/tasks/enqueue.test.mjs +1057 -0
  43. package/dist/federation/tasks/tasks.test.d.mts +2 -0
  44. package/dist/federation/tasks/tasks.test.mjs +1228 -0
  45. package/dist/federation/temporal.test.mjs +4 -4
  46. package/dist/federation/webfinger.test.mjs +6 -6
  47. package/dist/{http-sngIMb9S.js → http-D0jH0kco.js} +16 -80
  48. package/dist/{http-C7Lot0it.cjs → http-DeuPW1Oh.cjs} +14 -78
  49. package/dist/{http-Bf8YhWOi.mjs → http-JdRPUYku.mjs} +4 -4
  50. package/dist/{key-3rYgSl9f.mjs → key-o0_ipvUR.mjs} +10 -76
  51. package/dist/{kv-cache-CO2IaDJu.cjs → kv-cache-C3rqzQvu.cjs} +1 -1
  52. package/dist/{kv-cache-P3scUO6t.mjs → kv-cache-CM7w20U5.mjs} +1 -1
  53. package/dist/{kv-cache-B0siRaoZ.js → kv-cache-DSWq2JHU.js} +1 -1
  54. package/dist/{ld-CCOPy-Co.mjs → ld-C__CEgQH.mjs} +3 -3
  55. package/dist/{metrics-CR4UD_gF.mjs → metrics-CLSPm4dZ.mjs} +8 -6
  56. package/dist/{mq-D-nlpY04.d.ts → metrics-CoUJLQhZ.d.cts} +69 -1
  57. package/dist/{mq-D8uSFzxe.d.cts → metrics-Dc4jR-IC.d.ts} +69 -1
  58. package/dist/{middleware-DUelXs9h.cjs → middleware-B502nwxx.cjs} +874 -134
  59. package/dist/{middleware-CIteB8IS.mjs → middleware-CdMiavoh.mjs} +1 -1
  60. package/dist/{middleware-DfBPuuvp.mjs → middleware-CjHqy-1i.mjs} +469 -150
  61. package/dist/{middleware-BoNiH9CQ.js → middleware-zuLSkPIk.js} +863 -135
  62. package/dist/{mod-C0F6kvgS.d.cts → mod-B8Efb9qp.d.cts} +1 -1
  63. package/dist/{mod-yvIXFAEi.d.cts → mod-BtEaIEcD.d.cts} +1 -31
  64. package/dist/{mod-vPYVoa5n.d.ts → mod-Cmr39iWq.d.ts} +1 -1
  65. package/dist/{mod-DFvNJcNb.d.ts → mod-UMmveiO0.d.ts} +1 -31
  66. package/dist/mod.cjs +6 -6
  67. package/dist/mod.d.cts +6 -6
  68. package/dist/mod.d.ts +6 -6
  69. package/dist/mod.js +5 -5
  70. package/dist/mq-03vS-C9P.mjs +276 -0
  71. package/dist/nodeinfo/client.test.mjs +3 -3
  72. package/dist/nodeinfo/handler.test.mjs +5 -5
  73. package/dist/nodeinfo/types.test.mjs +4 -4
  74. package/dist/otel/exporter.test.mjs +3 -3
  75. package/dist/{outgoing-jsonld-L_DbOaFe.mjs → outgoing-jsonld-BNL8AC14.mjs} +1 -1
  76. package/dist/{owner-TUz_H-M9.mjs → owner-gz4TUfKG.mjs} +2 -2
  77. package/dist/{proof-DzKUmE7R.cjs → proof-CiDzRtr0.cjs} +1 -1
  78. package/dist/{proof-CrI3UpuA.mjs → proof-CuQpZ_AT.mjs} +5 -5
  79. package/dist/{proof-C5i7MhbD.js → proof-DQWTf6oB.js} +1 -1
  80. package/dist/{send-BBs_erdP.mjs → send-B60teucv.mjs} +3 -3
  81. package/dist/sig/accept.test.mjs +1 -1
  82. package/dist/sig/http.test.mjs +8 -8
  83. package/dist/sig/key.test.mjs +7 -191
  84. package/dist/sig/ld.test.mjs +7 -7
  85. package/dist/sig/mod.cjs +2 -2
  86. package/dist/sig/mod.js +2 -2
  87. package/dist/sig/owner.test.mjs +6 -6
  88. package/dist/sig/proof.test.mjs +9 -69
  89. package/dist/{std__assert-BBjXFNOb.mjs → std__assert-Dh6uLf_q.mjs} +4 -4
  90. package/dist/{temporal-bBIy2G-F.mjs → temporal-CvVMrvJJ.mjs} +1 -1
  91. package/dist/testing/mod.d.mts +1037 -8
  92. package/dist/testing/mod.mjs +3 -2
  93. package/dist/testing-Dy-WhqpN.mjs +77 -0
  94. package/dist/utils/docloader.test.mjs +6 -6
  95. package/dist/utils/kv-cache.test.mjs +1 -1
  96. package/dist/utils/mod.cjs +1 -1
  97. package/dist/utils/mod.d.cts +1 -1
  98. package/dist/utils/mod.d.ts +1 -1
  99. package/dist/utils/mod.js +1 -1
  100. package/package.json +8 -6
  101. /package/dist/{accept-CPkZzmGN.mjs → accept-CgDcxvjV.mjs} +0 -0
  102. /package/dist/{activity-listener-tztVvlNb.mjs → activity-listener-BeTGV3wc.mjs} +0 -0
  103. /package/dist/{assert_equals-C-ZRDbaf.mjs → assert_equals-PBVKNMJd.mjs} +0 -0
  104. /package/dist/{circuit-breaker-CSWsyoef.mjs → circuit-breaker-hJBB6jwA.mjs} +0 -0
  105. /package/dist/{client-ByXmQhYD.mjs → client-B_A6mfn3.mjs} +0 -0
  106. /package/dist/{collection-Cc3DVAhE.mjs → collection-Dp5ky45w.mjs} +0 -0
  107. /package/dist/{keycache-BeU0LCII.mjs → keycache-CaOR6NYg.mjs} +0 -0
  108. /package/dist/{keys-DGu1NFwu.mjs → keys-CSYsOMFG.mjs} +0 -0
  109. /package/dist/{kv-rV3vodCc.mjs → kv-CIvR3Non.mjs} +0 -0
  110. /package/dist/{negotiation-DDstyBvc.mjs → negotiation-m_L2nyS3.mjs} +0 -0
  111. /package/dist/{public-audience-Cvbr2Gzt.mjs → public-audience-c9zmYKgA.mjs} +0 -0
  112. /package/dist/{retry-CXg_MBI-.mjs → retry-DI4O-zYl.mjs} +0 -0
  113. /package/dist/{types-J53Kw7so.mjs → types-BFowWFTT.mjs} +0 -0
@@ -1,10 +1,10 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import "../std__assert-BBjXFNOb.mjs";
5
- import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
6
- import { t as assert } from "../assert-OguE97r2.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-bBIy2G-F.mjs";
4
+ import "../std__assert-Dh6uLf_q.mjs";
5
+ import { r as assertFalse } from "../assert_rejects-DAdaaIWM.mjs";
6
+ import { t as assert } from "../assert-DvVHoIZ0.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-CvVMrvJJ.mjs";
8
8
  import { test } from "@fedify/fixture";
9
9
  //#region src/federation/temporal.test.ts
10
10
  test("hasMalformedKnownTemporalLiteral() detects expanded proof timestamps", async () => {
@@ -1,12 +1,12 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { r as createRequestContext } from "../context-DVoTs_wM.mjs";
5
- import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
6
- import "../std__assert-BBjXFNOb.mjs";
7
- import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
8
- import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-DfBPuuvp.mjs";
4
+ import { r as createRequestContext } from "../context-BBRTgkrs.mjs";
5
+ import { t as MemoryKvStore } from "../kv-CIvR3Non.mjs";
6
+ import { t as assertEquals } from "../assert_equals-PBVKNMJd.mjs";
7
+ import "../std__assert-Dh6uLf_q.mjs";
8
+ import { t as assertNotEquals } from "../assert_not_equals-C8vcTTA3.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-CjHqy-1i.mjs";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  import { createTestMeterProvider, test } from "@fedify/fixture";
12
12
  //#region src/federation/webfinger.test.ts
@@ -1,16 +1,16 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { getLogger } from "@logtape/logtape";
4
- import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
4
+ import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
5
5
  import { SpanKind, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
6
6
  import { encodeHex } from "byte-encodings/hex";
7
7
  import { Item, decodeDict, encodeDict, encodeItem } from "structured-field-values";
8
- import { FetchError, getDocumentLoader, parseDidKeyVerificationMethod } from "@fedify/vocab-runtime";
8
+ import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
9
9
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
10
10
  import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
11
11
  //#region deno.json
12
12
  var name = "@fedify/fedify";
13
- var version = "2.4.0-dev.1567+12e6a3c0";
13
+ var version = "2.4.0-dev.1570+f1b6aaa3";
14
14
  //#endregion
15
15
  //#region src/sig/accept.ts
16
16
  /**
@@ -314,11 +314,11 @@ var FederationMetrics = class {
314
314
  unit: "{change}"
315
315
  });
316
316
  this.keyLookup = meter.createCounter("activitypub.key.lookup", {
317
- description: "Public-key lookup attempts performed by Fedify, including cache hits, local resolutions, and remote fetches.",
317
+ description: "Public-key lookup attempts performed by Fedify, including both cache hits and remote fetches.",
318
318
  unit: "{lookup}"
319
319
  });
320
320
  this.keyLookupDuration = meter.createHistogram("activitypub.key.lookup.duration", {
321
- description: "Duration of public-key lookups performed by Fedify, including cache hits, local resolutions, and any remote fetch.",
321
+ description: "Duration of public-key lookups performed by Fedify, including any remote fetch.",
322
322
  unit: "ms",
323
323
  advice: { explicitBucketBoundaries: [
324
324
  5,
@@ -472,10 +472,10 @@ var FederationMetrics = class {
472
472
  this.httpServerRequestCount.add(1, attributes);
473
473
  this.httpServerRequestDuration.record(durationMs, attributes);
474
474
  }
475
- recordQueueTaskEnqueued(common, attempt) {
475
+ recordQueueTaskEnqueued(common, attempt, count = 1) {
476
476
  const attributes = buildQueueTaskAttributes(common);
477
477
  attributes["fedify.queue.task.attempt"] = attempt;
478
- this.queueTaskEnqueued.add(1, attributes);
478
+ this.queueTaskEnqueued.add(count, attributes);
479
479
  }
480
480
  recordQueueTaskStarted(common) {
481
481
  this.queueTaskStarted.add(1, buildQueueTaskAttributes(common));
@@ -486,9 +486,10 @@ var FederationMetrics = class {
486
486
  decrementQueueTaskInFlight(common) {
487
487
  this.queueTaskInFlight.add(-1, buildQueueTaskInFlightAttributes(common));
488
488
  }
489
- recordQueueTaskOutcome(common, result, durationMs) {
489
+ recordQueueTaskOutcome(common, result, durationMs, failureReason) {
490
490
  const attributes = buildQueueTaskAttributes(common);
491
491
  attributes["fedify.queue.task.result"] = result;
492
+ if (failureReason != null && result === "failed") attributes["fedify.task.failure_reason"] = failureReason;
492
493
  if (result === "completed") this.queueTaskCompleted.add(1, attributes);
493
494
  else if (result === "failed") this.queueTaskFailed.add(1, attributes);
494
495
  this.queueTaskDuration.record(durationMs, attributes);
@@ -582,6 +583,7 @@ function buildQueueTaskAttributes(common) {
582
583
  const nativeRetrial = common.queue?.nativeRetrial;
583
584
  if (typeof nativeRetrial === "boolean") attributes["fedify.queue.native_retrial"] = nativeRetrial;
584
585
  if (common.activityType != null) attributes["activitypub.activity.type"] = common.activityType;
586
+ if (common.taskName != null) attributes["fedify.task.name"] = common.taskName;
585
587
  return attributes;
586
588
  }
587
589
  function buildQueueTaskInFlightAttributes(common) {
@@ -1147,85 +1149,24 @@ async function fetchKeyDetailed(keyId, cls, options = {}) {
1147
1149
  async function getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger) {
1148
1150
  if (keyCache == null) return null;
1149
1151
  const cachedKey = await keyCache.get(cacheKey);
1150
- const hit = checkCachedKeyHit(cachedKey, keyId, cls, logger);
1151
- if (hit != null) return hit;
1152
- if (cachedKey === null) {
1153
- logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
1154
- return {
1155
- key: null,
1156
- cached: true
1157
- };
1158
- }
1159
- return null;
1160
- }
1161
- function checkCachedKeyHit(cachedKey, keyId, cls, logger) {
1162
1152
  if (cachedKey instanceof cls && cachedKey.publicKey != null) {
1163
1153
  logger.debug("Key {keyId} found in cache.", { keyId });
1164
1154
  return {
1165
1155
  key: cachedKey,
1166
1156
  cached: true
1167
1157
  };
1158
+ } else if (cachedKey === null) {
1159
+ logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
1160
+ return {
1161
+ key: null,
1162
+ cached: true
1163
+ };
1168
1164
  }
1169
1165
  return null;
1170
1166
  }
1171
1167
  async function clearFetchErrorMetadata(keyId, keyCache) {
1172
1168
  await keyCache?.setFetchError?.(keyId, null);
1173
1169
  }
1174
- function isDidKeyUrl(keyId) {
1175
- return keyId.protocol === "did:" && keyId.pathname.startsWith("key:");
1176
- }
1177
- async function doRawKeysMatch(left, right) {
1178
- const [leftRaw, rightRaw] = await Promise.all([crypto.subtle.exportKey("raw", left), crypto.subtle.exportKey("raw", right)]);
1179
- if (leftRaw.byteLength !== rightRaw.byteLength) return false;
1180
- const leftBytes = new Uint8Array(leftRaw);
1181
- const rightBytes = new Uint8Array(rightRaw);
1182
- return leftBytes.every((byte, index) => byte === rightBytes[index]);
1183
- }
1184
- async function isCachedDidKeyValid(key, verificationMethod) {
1185
- try {
1186
- return key.id?.href === verificationMethod.id.href && key.controllerId?.href === verificationMethod.controller.href && await doRawKeysMatch(key.publicKey, verificationMethod.publicKey);
1187
- } catch {
1188
- return false;
1189
- }
1190
- }
1191
- async function resolveDidKey(cacheKey, cls, keyCache, logger) {
1192
- if (!isDidKeyUrl(cacheKey)) return null;
1193
- const keyId = cacheKey.href;
1194
- if (!(cls === Multikey)) {
1195
- logger.debug("Failed to resolve did:key {keyId}; did:key verification methods are only supported as Multikey values.", { keyId });
1196
- return {
1197
- key: null,
1198
- cached: false
1199
- };
1200
- }
1201
- let verificationMethod;
1202
- try {
1203
- verificationMethod = await parseDidKeyVerificationMethod(cacheKey);
1204
- } catch (error) {
1205
- logger.debug("Failed to resolve did:key verification method {keyId}: {error}", {
1206
- keyId,
1207
- error
1208
- });
1209
- return {
1210
- key: null,
1211
- cached: false
1212
- };
1213
- }
1214
- const hit = checkCachedKeyHit(await keyCache?.get(cacheKey), keyId, cls, logger);
1215
- if (hit?.key instanceof Multikey && await isCachedDidKeyValid(hit.key, verificationMethod)) return hit;
1216
- const key = new Multikey({
1217
- id: verificationMethod.id,
1218
- controller: verificationMethod.controller,
1219
- publicKey: verificationMethod.publicKey
1220
- });
1221
- await keyCache?.set(cacheKey, key);
1222
- await clearFetchErrorMetadata(cacheKey, keyCache);
1223
- logger.debug("Resolved did:key verification method {keyId}.", { keyId });
1224
- return {
1225
- key,
1226
- cached: false
1227
- };
1228
- }
1229
1170
  async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider }, logger) {
1230
1171
  let object;
1231
1172
  try {
@@ -1340,11 +1281,6 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
1340
1281
  ]);
1341
1282
  const keyId = cacheKey.href;
1342
1283
  const keyCache = options.keyCache;
1343
- const didKey = await resolveDidKey(cacheKey, cls, keyCache, logger);
1344
- if (didKey != null) {
1345
- outcome = { result: didKey.key == null ? "invalid" : didKey.cached ? "hit" : "fetched" };
1346
- return didKey;
1347
- }
1348
1284
  const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
1349
1285
  if (cached?.key === null && cached.cached) {
1350
1286
  const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
@@ -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.4.0-dev.1567+12e6a3c0";
14
+ var version = "2.4.0-dev.1570+f1b6aaa3";
15
15
  //#endregion
16
16
  //#region src/sig/accept.ts
17
17
  /**
@@ -315,11 +315,11 @@ var FederationMetrics = class {
315
315
  unit: "{change}"
316
316
  });
317
317
  this.keyLookup = meter.createCounter("activitypub.key.lookup", {
318
- description: "Public-key lookup attempts performed by Fedify, including cache hits, local resolutions, and remote fetches.",
318
+ description: "Public-key lookup attempts performed by Fedify, including both cache hits and remote fetches.",
319
319
  unit: "{lookup}"
320
320
  });
321
321
  this.keyLookupDuration = meter.createHistogram("activitypub.key.lookup.duration", {
322
- description: "Duration of public-key lookups performed by Fedify, including cache hits, local resolutions, and any remote fetch.",
322
+ description: "Duration of public-key lookups performed by Fedify, including any remote fetch.",
323
323
  unit: "ms",
324
324
  advice: { explicitBucketBoundaries: [
325
325
  5,
@@ -473,10 +473,10 @@ var FederationMetrics = class {
473
473
  this.httpServerRequestCount.add(1, attributes);
474
474
  this.httpServerRequestDuration.record(durationMs, attributes);
475
475
  }
476
- recordQueueTaskEnqueued(common, attempt) {
476
+ recordQueueTaskEnqueued(common, attempt, count = 1) {
477
477
  const attributes = buildQueueTaskAttributes(common);
478
478
  attributes["fedify.queue.task.attempt"] = attempt;
479
- this.queueTaskEnqueued.add(1, attributes);
479
+ this.queueTaskEnqueued.add(count, attributes);
480
480
  }
481
481
  recordQueueTaskStarted(common) {
482
482
  this.queueTaskStarted.add(1, buildQueueTaskAttributes(common));
@@ -487,9 +487,10 @@ var FederationMetrics = class {
487
487
  decrementQueueTaskInFlight(common) {
488
488
  this.queueTaskInFlight.add(-1, buildQueueTaskInFlightAttributes(common));
489
489
  }
490
- recordQueueTaskOutcome(common, result, durationMs) {
490
+ recordQueueTaskOutcome(common, result, durationMs, failureReason) {
491
491
  const attributes = buildQueueTaskAttributes(common);
492
492
  attributes["fedify.queue.task.result"] = result;
493
+ if (failureReason != null && result === "failed") attributes["fedify.task.failure_reason"] = failureReason;
493
494
  if (result === "completed") this.queueTaskCompleted.add(1, attributes);
494
495
  else if (result === "failed") this.queueTaskFailed.add(1, attributes);
495
496
  this.queueTaskDuration.record(durationMs, attributes);
@@ -583,6 +584,7 @@ function buildQueueTaskAttributes(common) {
583
584
  const nativeRetrial = common.queue?.nativeRetrial;
584
585
  if (typeof nativeRetrial === "boolean") attributes["fedify.queue.native_retrial"] = nativeRetrial;
585
586
  if (common.activityType != null) attributes["activitypub.activity.type"] = common.activityType;
587
+ if (common.taskName != null) attributes["fedify.task.name"] = common.taskName;
586
588
  return attributes;
587
589
  }
588
590
  function buildQueueTaskInFlightAttributes(common) {
@@ -1148,85 +1150,24 @@ async function fetchKeyDetailed(keyId, cls, options = {}) {
1148
1150
  async function getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger) {
1149
1151
  if (keyCache == null) return null;
1150
1152
  const cachedKey = await keyCache.get(cacheKey);
1151
- const hit = checkCachedKeyHit(cachedKey, keyId, cls, logger);
1152
- if (hit != null) return hit;
1153
- if (cachedKey === null) {
1154
- logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
1155
- return {
1156
- key: null,
1157
- cached: true
1158
- };
1159
- }
1160
- return null;
1161
- }
1162
- function checkCachedKeyHit(cachedKey, keyId, cls, logger) {
1163
1153
  if (cachedKey instanceof cls && cachedKey.publicKey != null) {
1164
1154
  logger.debug("Key {keyId} found in cache.", { keyId });
1165
1155
  return {
1166
1156
  key: cachedKey,
1167
1157
  cached: true
1168
1158
  };
1159
+ } else if (cachedKey === null) {
1160
+ logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
1161
+ return {
1162
+ key: null,
1163
+ cached: true
1164
+ };
1169
1165
  }
1170
1166
  return null;
1171
1167
  }
1172
1168
  async function clearFetchErrorMetadata(keyId, keyCache) {
1173
1169
  await keyCache?.setFetchError?.(keyId, null);
1174
1170
  }
1175
- function isDidKeyUrl(keyId) {
1176
- return keyId.protocol === "did:" && keyId.pathname.startsWith("key:");
1177
- }
1178
- async function doRawKeysMatch(left, right) {
1179
- const [leftRaw, rightRaw] = await Promise.all([crypto.subtle.exportKey("raw", left), crypto.subtle.exportKey("raw", right)]);
1180
- if (leftRaw.byteLength !== rightRaw.byteLength) return false;
1181
- const leftBytes = new Uint8Array(leftRaw);
1182
- const rightBytes = new Uint8Array(rightRaw);
1183
- return leftBytes.every((byte, index) => byte === rightBytes[index]);
1184
- }
1185
- async function isCachedDidKeyValid(key, verificationMethod) {
1186
- try {
1187
- return key.id?.href === verificationMethod.id.href && key.controllerId?.href === verificationMethod.controller.href && await doRawKeysMatch(key.publicKey, verificationMethod.publicKey);
1188
- } catch {
1189
- return false;
1190
- }
1191
- }
1192
- async function resolveDidKey(cacheKey, cls, keyCache, logger) {
1193
- if (!isDidKeyUrl(cacheKey)) return null;
1194
- const keyId = cacheKey.href;
1195
- if (!(cls === _fedify_vocab.Multikey)) {
1196
- logger.debug("Failed to resolve did:key {keyId}; did:key verification methods are only supported as Multikey values.", { keyId });
1197
- return {
1198
- key: null,
1199
- cached: false
1200
- };
1201
- }
1202
- let verificationMethod;
1203
- try {
1204
- verificationMethod = await (0, _fedify_vocab_runtime.parseDidKeyVerificationMethod)(cacheKey);
1205
- } catch (error) {
1206
- logger.debug("Failed to resolve did:key verification method {keyId}: {error}", {
1207
- keyId,
1208
- error
1209
- });
1210
- return {
1211
- key: null,
1212
- cached: false
1213
- };
1214
- }
1215
- const hit = checkCachedKeyHit(await keyCache?.get(cacheKey), keyId, cls, logger);
1216
- if (hit?.key instanceof _fedify_vocab.Multikey && await isCachedDidKeyValid(hit.key, verificationMethod)) return hit;
1217
- const key = new _fedify_vocab.Multikey({
1218
- id: verificationMethod.id,
1219
- controller: verificationMethod.controller,
1220
- publicKey: verificationMethod.publicKey
1221
- });
1222
- await keyCache?.set(cacheKey, key);
1223
- await clearFetchErrorMetadata(cacheKey, keyCache);
1224
- logger.debug("Resolved did:key verification method {keyId}.", { keyId });
1225
- return {
1226
- key,
1227
- cached: false
1228
- };
1229
- }
1230
1171
  async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider }, logger) {
1231
1172
  let object;
1232
1173
  try {
@@ -1341,11 +1282,6 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
1341
1282
  ]);
1342
1283
  const keyId = cacheKey.href;
1343
1284
  const keyCache = options.keyCache;
1344
- const didKey = await resolveDidKey(cacheKey, cls, keyCache, logger);
1345
- if (didKey != null) {
1346
- outcome = { result: didKey.key == null ? "invalid" : didKey.cached ? "hit" : "fetched" };
1347
- return didKey;
1348
- }
1349
1285
  const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
1350
1286
  if (cached?.key === null && cached.cached) {
1351
1287
  const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
@@ -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-Dho0TW0X.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CR4UD_gF.mjs";
6
- import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPkZzmGN.mjs";
7
- import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-3rYgSl9f.mjs";
4
+ import { n as version, t as name } from "./deno-klNxGW7W.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CLSPm4dZ.mjs";
6
+ import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CgDcxvjV.mjs";
7
+ import { o as validateCryptoKey, r as fetchKeyDetailed } from "./key-o0_ipvUR.mjs";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { CryptographicKey } from "@fedify/vocab";
10
10
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -1,12 +1,12 @@
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-Dho0TW0X.mjs";
5
- import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-CR4UD_gF.mjs";
4
+ import { n as version, t as name } from "./deno-klNxGW7W.mjs";
5
+ import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-CLSPm4dZ.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
- import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
7
+ import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
9
- import { FetchError, getDocumentLoader, parseDidKeyVerificationMethod } from "@fedify/vocab-runtime";
9
+ import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
10
10
  //#region src/sig/key.ts
11
11
  /**
12
12
  * Checks if the given key is valid and supported. No-op if the key is valid,
@@ -195,85 +195,24 @@ async function fetchKeyDetailed(keyId, cls, options = {}) {
195
195
  async function getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger) {
196
196
  if (keyCache == null) return null;
197
197
  const cachedKey = await keyCache.get(cacheKey);
198
- const hit = checkCachedKeyHit(cachedKey, keyId, cls, logger);
199
- if (hit != null) return hit;
200
- if (cachedKey === null) {
201
- logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
202
- return {
203
- key: null,
204
- cached: true
205
- };
206
- }
207
- return null;
208
- }
209
- function checkCachedKeyHit(cachedKey, keyId, cls, logger) {
210
198
  if (cachedKey instanceof cls && cachedKey.publicKey != null) {
211
199
  logger.debug("Key {keyId} found in cache.", { keyId });
212
200
  return {
213
201
  key: cachedKey,
214
202
  cached: true
215
203
  };
204
+ } else if (cachedKey === null) {
205
+ logger.debug("Entry {keyId} found in cache, but it is unavailable.", { keyId });
206
+ return {
207
+ key: null,
208
+ cached: true
209
+ };
216
210
  }
217
211
  return null;
218
212
  }
219
213
  async function clearFetchErrorMetadata(keyId, keyCache) {
220
214
  await keyCache?.setFetchError?.(keyId, null);
221
215
  }
222
- function isDidKeyUrl(keyId) {
223
- return keyId.protocol === "did:" && keyId.pathname.startsWith("key:");
224
- }
225
- async function doRawKeysMatch(left, right) {
226
- const [leftRaw, rightRaw] = await Promise.all([crypto.subtle.exportKey("raw", left), crypto.subtle.exportKey("raw", right)]);
227
- if (leftRaw.byteLength !== rightRaw.byteLength) return false;
228
- const leftBytes = new Uint8Array(leftRaw);
229
- const rightBytes = new Uint8Array(rightRaw);
230
- return leftBytes.every((byte, index) => byte === rightBytes[index]);
231
- }
232
- async function isCachedDidKeyValid(key, verificationMethod) {
233
- try {
234
- return key.id?.href === verificationMethod.id.href && key.controllerId?.href === verificationMethod.controller.href && await doRawKeysMatch(key.publicKey, verificationMethod.publicKey);
235
- } catch {
236
- return false;
237
- }
238
- }
239
- async function resolveDidKey(cacheKey, cls, keyCache, logger) {
240
- if (!isDidKeyUrl(cacheKey)) return null;
241
- const keyId = cacheKey.href;
242
- if (!(cls === Multikey)) {
243
- logger.debug("Failed to resolve did:key {keyId}; did:key verification methods are only supported as Multikey values.", { keyId });
244
- return {
245
- key: null,
246
- cached: false
247
- };
248
- }
249
- let verificationMethod;
250
- try {
251
- verificationMethod = await parseDidKeyVerificationMethod(cacheKey);
252
- } catch (error) {
253
- logger.debug("Failed to resolve did:key verification method {keyId}: {error}", {
254
- keyId,
255
- error
256
- });
257
- return {
258
- key: null,
259
- cached: false
260
- };
261
- }
262
- const hit = checkCachedKeyHit(await keyCache?.get(cacheKey), keyId, cls, logger);
263
- if (hit?.key instanceof Multikey && await isCachedDidKeyValid(hit.key, verificationMethod)) return hit;
264
- const key = new Multikey({
265
- id: verificationMethod.id,
266
- controller: verificationMethod.controller,
267
- publicKey: verificationMethod.publicKey
268
- });
269
- await keyCache?.set(cacheKey, key);
270
- await clearFetchErrorMetadata(cacheKey, keyCache);
271
- logger.debug("Resolved did:key verification method {keyId}.", { keyId });
272
- return {
273
- key,
274
- cached: false
275
- };
276
- }
277
216
  async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider }, logger) {
278
217
  let object;
279
218
  try {
@@ -388,11 +327,6 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
388
327
  ]);
389
328
  const keyId = cacheKey.href;
390
329
  const keyCache = options.keyCache;
391
- const didKey = await resolveDidKey(cacheKey, cls, keyCache, logger);
392
- if (didKey != null) {
393
- outcome = { result: didKey.key == null ? "invalid" : didKey.cached ? "hit" : "fetched" };
394
- return didKey;
395
- }
396
330
  const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
397
331
  if (cached?.key === null && cached.cached) {
398
332
  const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
@@ -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-C7Lot0it.cjs");
4
+ const require_http = require("./http-DeuPW1Oh.cjs");
5
5
  let _logtape_logtape = require("@logtape/logtape");
6
6
  let es_toolkit = require("es-toolkit");
7
7
  let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { p as recordDocumentCache } from "./metrics-CR4UD_gF.mjs";
4
+ import { p as recordDocumentCache } from "./metrics-CLSPm4dZ.mjs";
5
5
  import { getLogger } from "@logtape/logtape";
6
6
  import { preloadedContexts } from "@fedify/vocab-runtime";
7
7
  //#region src/utils/kv-cache.ts
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-sngIMb9S.js";
3
+ import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-D0jH0kco.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { curry } from "es-toolkit";
6
6
  import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
@@ -1,9 +1,9 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-Dho0TW0X.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CR4UD_gF.mjs";
6
- import { n as fetchKey, o as validateCryptoKey } from "./key-3rYgSl9f.mjs";
4
+ import { n as version, t as name } from "./deno-klNxGW7W.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CLSPm4dZ.mjs";
6
+ import { n as fetchKey, o as validateCryptoKey } from "./key-o0_ipvUR.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
9
9
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-Dho0TW0X.mjs";
4
+ import { n as version, t as name } from "./deno-klNxGW7W.mjs";
5
5
  import { metrics } from "@opentelemetry/api";
6
6
  import { FetchError } from "@fedify/vocab-runtime";
7
7
  //#region src/federation/metrics.ts
@@ -167,11 +167,11 @@ var FederationMetrics = class {
167
167
  unit: "{change}"
168
168
  });
169
169
  this.keyLookup = meter.createCounter("activitypub.key.lookup", {
170
- description: "Public-key lookup attempts performed by Fedify, including cache hits, local resolutions, and remote fetches.",
170
+ description: "Public-key lookup attempts performed by Fedify, including both cache hits and remote fetches.",
171
171
  unit: "{lookup}"
172
172
  });
173
173
  this.keyLookupDuration = meter.createHistogram("activitypub.key.lookup.duration", {
174
- description: "Duration of public-key lookups performed by Fedify, including cache hits, local resolutions, and any remote fetch.",
174
+ description: "Duration of public-key lookups performed by Fedify, including any remote fetch.",
175
175
  unit: "ms",
176
176
  advice: { explicitBucketBoundaries: [
177
177
  5,
@@ -325,10 +325,10 @@ var FederationMetrics = class {
325
325
  this.httpServerRequestCount.add(1, attributes);
326
326
  this.httpServerRequestDuration.record(durationMs, attributes);
327
327
  }
328
- recordQueueTaskEnqueued(common, attempt) {
328
+ recordQueueTaskEnqueued(common, attempt, count = 1) {
329
329
  const attributes = buildQueueTaskAttributes(common);
330
330
  attributes["fedify.queue.task.attempt"] = attempt;
331
- this.queueTaskEnqueued.add(1, attributes);
331
+ this.queueTaskEnqueued.add(count, attributes);
332
332
  }
333
333
  recordQueueTaskStarted(common) {
334
334
  this.queueTaskStarted.add(1, buildQueueTaskAttributes(common));
@@ -339,9 +339,10 @@ var FederationMetrics = class {
339
339
  decrementQueueTaskInFlight(common) {
340
340
  this.queueTaskInFlight.add(-1, buildQueueTaskInFlightAttributes(common));
341
341
  }
342
- recordQueueTaskOutcome(common, result, durationMs) {
342
+ recordQueueTaskOutcome(common, result, durationMs, failureReason) {
343
343
  const attributes = buildQueueTaskAttributes(common);
344
344
  attributes["fedify.queue.task.result"] = result;
345
+ if (failureReason != null && result === "failed") attributes["fedify.task.failure_reason"] = failureReason;
345
346
  if (result === "completed") this.queueTaskCompleted.add(1, attributes);
346
347
  else if (result === "failed") this.queueTaskFailed.add(1, attributes);
347
348
  this.queueTaskDuration.record(durationMs, attributes);
@@ -435,6 +436,7 @@ function buildQueueTaskAttributes(common) {
435
436
  const nativeRetrial = common.queue?.nativeRetrial;
436
437
  if (typeof nativeRetrial === "boolean") attributes["fedify.queue.native_retrial"] = nativeRetrial;
437
438
  if (common.activityType != null) attributes["activitypub.activity.type"] = common.activityType;
439
+ if (common.taskName != null) attributes["fedify.task.name"] = common.taskName;
438
440
  return attributes;
439
441
  }
440
442
  function buildQueueTaskInFlightAttributes(common) {