@fedify/fedify 2.3.12-dev.2365 → 2.3.12

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 (48) hide show
  1. package/dist/{builder-BOLaWLNy.mjs → builder-B6ixdT3y.mjs} +2 -2
  2. package/dist/compat/transformers.test.mjs +1 -1
  3. package/dist/{deno-DSS6EkPl.mjs → deno-D4dcoVfF.mjs} +1 -1
  4. package/dist/{docloader-Ds5k4A6d.mjs → docloader-NOKfswJV.mjs} +2 -2
  5. package/dist/federation/builder.test.mjs +1 -1
  6. package/dist/federation/handler.test.mjs +5 -5
  7. package/dist/federation/idempotency.test.mjs +2 -2
  8. package/dist/federation/metrics.test.mjs +1 -1
  9. package/dist/federation/middleware.test.mjs +7 -7
  10. package/dist/federation/mod.cjs +1 -1
  11. package/dist/federation/mod.js +1 -1
  12. package/dist/federation/send.test.mjs +3 -3
  13. package/dist/federation/temporal.test.mjs +1 -1
  14. package/dist/federation/webfinger.test.mjs +1 -1
  15. package/dist/{http-DdaLQHim.cjs → http-D_Xrr6kp.cjs} +109 -11
  16. package/dist/{http-LMsqGo8j.js → http-DkyUBs_T.js} +110 -12
  17. package/dist/{http-D9h6mQdq.mjs → http-HjidyDfF.mjs} +3 -3
  18. package/dist/{key-vnmAGZ3_.mjs → key-Dg-NXm4K.mjs} +111 -13
  19. package/dist/{kv-cache-Dz7_SbVI.js → kv-cache-BhGeZk_o.js} +1 -1
  20. package/dist/{kv-cache-CQuscHxa.mjs → kv-cache-BpVwvcSI.mjs} +1 -1
  21. package/dist/{kv-cache-ClCz-B0L.cjs → kv-cache-BwnC6JGt.cjs} +1 -1
  22. package/dist/{ld-BRqKkOSf.mjs → ld-C1wveXXf.mjs} +3 -3
  23. package/dist/{metrics-Z0UkrR_1.mjs → metrics-cIaMxG0v.mjs} +1 -1
  24. package/dist/{middleware-B-CIN962.js → middleware-CnrzVu9i.js} +3 -3
  25. package/dist/{middleware-DanzltB1.cjs → middleware-DhOFTXmo.cjs} +3 -3
  26. package/dist/{middleware-RTcKhytV.mjs → middleware-I-XlrRVl.mjs} +12 -12
  27. package/dist/{middleware-C_kPmXE6.mjs → middleware-VxPpU0h_.mjs} +1 -1
  28. package/dist/mod.cjs +4 -4
  29. package/dist/mod.js +4 -4
  30. package/dist/nodeinfo/handler.test.mjs +1 -1
  31. package/dist/{owner-B0rmuoQB.mjs → owner-CFKfE85G.mjs} +2 -2
  32. package/dist/{proof-CKczQTG0.cjs → proof-DBxu6g2K.cjs} +1 -1
  33. package/dist/{proof-B7mAFVed.mjs → proof-DtpGEj0u.mjs} +3 -3
  34. package/dist/{proof-Bau45ZUZ.js → proof-HU__qtUD.js} +1 -1
  35. package/dist/{send-BFukz_kE.mjs → send-CwMea5r6.mjs} +3 -3
  36. package/dist/sig/http.test.mjs +2 -2
  37. package/dist/sig/key.test.mjs +209 -3
  38. package/dist/sig/ld.test.mjs +2 -2
  39. package/dist/sig/mod.cjs +2 -2
  40. package/dist/sig/mod.js +2 -2
  41. package/dist/sig/owner.test.mjs +1 -1
  42. package/dist/sig/proof.test.mjs +1 -1
  43. package/dist/{temporal-n6j0MNF9.mjs → temporal-ClSXyHyu.mjs} +1 -1
  44. package/dist/utils/docloader.test.mjs +2 -2
  45. package/dist/utils/kv-cache.test.mjs +1 -1
  46. package/dist/utils/mod.cjs +1 -1
  47. package/dist/utils/mod.js +1 -1
  48. package/package.json +7 -7
@@ -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-DSS6EkPl.mjs";
4
+ import { n as version, t as name } from "./deno-D4dcoVfF.mjs";
5
5
  import { t as ActivityListenerSet } from "./activity-listener-tztVvlNb.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
@@ -81,7 +81,7 @@ var FederationBuilderImpl = class {
81
81
  * specified.
82
82
  */
83
83
  async build(options) {
84
- const { FederationImpl } = await import("./middleware-C_kPmXE6.mjs");
84
+ const { FederationImpl } = await import("./middleware-VxPpU0h_.mjs");
85
85
  const f = new FederationImpl(options);
86
86
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
87
87
  f.router = this.router.clone();
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
6
6
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
7
- import { b as autoIdAssigner, n as FederationImpl, y as actorDehydrator } from "../middleware-RTcKhytV.mjs";
7
+ import { b as autoIdAssigner, n as FederationImpl, y as actorDehydrator } from "../middleware-I-XlrRVl.mjs";
8
8
  import { Follow, Person } from "@fedify/vocab";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/compat/transformers.test.ts
@@ -3,6 +3,6 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  //#region deno.json
5
5
  var name = "@fedify/fedify";
6
- var version = "2.3.12-dev.2365+89254121";
6
+ var version = "2.3.12";
7
7
  //#endregion
8
8
  export { version as n, name as t };
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { s as validateCryptoKey } from "./key-vnmAGZ3_.mjs";
5
- import { n as doubleKnock } from "./http-D9h6mQdq.mjs";
4
+ import { s as validateCryptoKey } from "./key-Dg-NXm4K.mjs";
5
+ import { n as doubleKnock } from "./http-HjidyDfF.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
8
8
  import { curry } from "es-toolkit";
@@ -6,7 +6,7 @@ import { n as assertExists } from "../std__assert-BvGuO4xO.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
7
7
  import { t as assertStrictEquals } from "../assert_strict_equals-XEgZAlrj.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
9
- import { r as createFederationBuilder } from "../builder-BOLaWLNy.mjs";
9
+ import { r as createFederationBuilder } from "../builder-B6ixdT3y.mjs";
10
10
  import { DisallowedOperatorError, DisallowedVarSpecModifierError, DuplicateRouteVariableError, RouteTemplateOptionsNotMatchedError, RouterError } from "@fedify/uri-template";
11
11
  import { Activity, Note, Person } from "@fedify/vocab";
12
12
  import { test } from "@fedify/fixture";
@@ -7,13 +7,13 @@ import "../std__assert-BvGuO4xO.mjs";
7
7
  import { n as assertGreaterOrEqual, t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
8
8
  import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
9
9
  import { r as parseAcceptSignature } from "../accept-Dd__NiUL.mjs";
10
- import { a as generateCryptoKeyPair } from "../key-vnmAGZ3_.mjs";
11
- import { s as signRequest } from "../http-D9h6mQdq.mjs";
10
+ import { a as generateCryptoKeyPair } from "../key-Dg-NXm4K.mjs";
11
+ import { s as signRequest } from "../http-HjidyDfF.mjs";
12
12
  import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
13
13
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
14
- import { a as compactJsonLd, p as signJsonLd } from "../ld-BRqKkOSf.mjs";
15
- import { r as signObject } from "../proof-B7mAFVed.mjs";
16
- import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-RTcKhytV.mjs";
14
+ import { a as compactJsonLd, p as signJsonLd } from "../ld-C1wveXXf.mjs";
15
+ import { r as signObject } from "../proof-DtpGEj0u.mjs";
16
+ import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-I-XlrRVl.mjs";
17
17
  import { t as ActivityListenerSet } from "../activity-listener-tztVvlNb.mjs";
18
18
  import { Activity, Create, CryptographicKey, Multikey, Note, Person, Tombstone } from "@fedify/vocab";
19
19
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -5,8 +5,8 @@ import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BvGuO4xO.mjs";
6
6
  import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
8
- import { r as signObject } from "../proof-B7mAFVed.mjs";
9
- import { o as createFederation } from "../middleware-RTcKhytV.mjs";
8
+ import { r as signObject } from "../proof-DtpGEj0u.mjs";
9
+ import { o as createFederation } from "../middleware-I-XlrRVl.mjs";
10
10
  import { Create, Follow, Person } from "@fedify/vocab";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/federation/idempotency.test.ts
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BvGuO4xO.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
7
- import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-Z0UkrR_1.mjs";
7
+ import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-cIaMxG0v.mjs";
8
8
  import { createTestMeterProvider, test } from "@fedify/fixture";
9
9
  import { FetchError } from "@fedify/vocab-runtime";
10
10
  import { DataPointType, MeterProvider, MetricReader } from "@opentelemetry/sdk-metrics";
@@ -9,15 +9,15 @@ import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
9
9
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
10
10
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
11
11
  import { t as assertStrictEquals } from "../assert_strict_equals-XEgZAlrj.mjs";
12
- import { g as recordInboxActivity } from "../metrics-Z0UkrR_1.mjs";
13
- import { l as verifyRequest, s as signRequest } from "../http-D9h6mQdq.mjs";
12
+ import { g as recordInboxActivity } from "../metrics-cIaMxG0v.mjs";
13
+ import { l as verifyRequest, s as signRequest } from "../http-HjidyDfF.mjs";
14
14
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
15
- import { t as getAuthenticatedDocumentLoader } from "../docloader-Ds5k4A6d.mjs";
15
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-NOKfswJV.mjs";
16
16
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
17
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-BRqKkOSf.mjs";
18
- import { t as doesActorOwnKey } from "../owner-B0rmuoQB.mjs";
19
- import { i as verifyObject, r as signObject } from "../proof-B7mAFVed.mjs";
20
- import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-RTcKhytV.mjs";
17
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-C1wveXXf.mjs";
18
+ import { t as doesActorOwnKey } from "../owner-CFKfE85G.mjs";
19
+ import { i as verifyObject, r as signObject } from "../proof-DtpGEj0u.mjs";
20
+ import { g as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-I-XlrRVl.mjs";
21
21
  import { t as CircuitBreaker } from "../circuit-breaker-D1fxthDI.mjs";
22
22
  import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-Dm5MM6l9.mjs";
23
23
  import { configure, reset } from "@logtape/logtape";
@@ -2,7 +2,7 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("../chunk-DDcVe30Y.cjs");
5
- const require_middleware = require("../middleware-DanzltB1.cjs");
5
+ const require_middleware = require("../middleware-DhOFTXmo.cjs");
6
6
  let _logtape_logtape = require("@logtape/logtape");
7
7
  let _fedify_uri_template = require("@fedify/uri-template");
8
8
  let es_toolkit = require("es-toolkit");
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as SendActivityError, c as buildCollectionSynchronizationHeader, d as normalizeCircuitBreakerOptions, f as parseCircuitBreakerKvState, i as createExponentialBackoffPolicy, l as digest, o as respondWithObject, p as createFederationBuilder, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as CircuitBreaker } from "../middleware-B-CIN962.js";
3
+ import { a as SendActivityError, c as buildCollectionSynchronizationHeader, d as normalizeCircuitBreakerOptions, f as parseCircuitBreakerKvState, i as createExponentialBackoffPolicy, l as digest, o as respondWithObject, p as createFederationBuilder, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as CircuitBreaker } from "../middleware-CnrzVu9i.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Router as Router$1, RouterError as RouterError$1, assertPath, isPath } from "@fedify/uri-template";
6
6
  import { isEqual } from "es-toolkit";
@@ -7,10 +7,10 @@ import "../std__assert-BvGuO4xO.mjs";
7
7
  import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
8
8
  import { n as assertInstanceOf, t as assert } from "../assert-jSdZMYam.mjs";
9
9
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
10
- import { l as verifyRequest } from "../http-D9h6mQdq.mjs";
10
+ import { l as verifyRequest } from "../http-HjidyDfF.mjs";
11
11
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
12
- import { t as doesActorOwnKey } from "../owner-B0rmuoQB.mjs";
13
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-BFukz_kE.mjs";
12
+ import { t as doesActorOwnKey } from "../owner-CFKfE85G.mjs";
13
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CwMea5r6.mjs";
14
14
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
15
15
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { FetchError, UrlError } from "@fedify/vocab-runtime";
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import "../std__assert-BvGuO4xO.mjs";
5
5
  import { r as assertFalse } from "../assert_rejects-DN60FHPX.mjs";
6
6
  import { t as assert } from "../assert-jSdZMYam.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-n6j0MNF9.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-ClSXyHyu.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 () => {
@@ -6,7 +6,7 @@ import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
6
6
  import "../std__assert-BvGuO4xO.mjs";
7
7
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
8
8
  import { t as MemoryKvStore } from "../kv-mI4Ix2EU.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-RTcKhytV.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-I-XlrRVl.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
@@ -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.3.12-dev.2365+89254121";
14
+ var version = "2.3.12";
15
15
  //#endregion
16
16
  //#region src/sig/accept.ts
17
17
  /**
@@ -961,6 +961,65 @@ function getDurationMs(start) {
961
961
  }
962
962
  //#endregion
963
963
  //#region src/sig/key.ts
964
+ /** Classifies decoding failures without hiding unexpected loader errors. */
965
+ function classifyKeyJsonLdError(error, seen = /* @__PURE__ */ new Set()) {
966
+ if (!(error instanceof Error) || !error.name.startsWith("jsonld.")) return null;
967
+ if (seen.has(error)) throw error;
968
+ seen.add(error);
969
+ const details = error.details;
970
+ if (typeof details?.code !== "string") return null;
971
+ if (details.code !== "loading remote context failed" || !("cause" in details) && !("cause" in error)) return "invalid";
972
+ const cause = "cause" in details ? details.cause : error.cause;
973
+ const nestedFailure = classifyKeyJsonLdError(cause, seen);
974
+ if (nestedFailure != null) return nestedFailure;
975
+ if (cause instanceof SyntaxError) return "invalid";
976
+ if (cause instanceof _fedify_vocab_runtime.FetchError || cause instanceof _fedify_vocab_runtime.UrlError) return "fetch";
977
+ if (cause instanceof Error && [
978
+ "AbortError",
979
+ "TimeoutError",
980
+ "NetworkError"
981
+ ].includes(cause.name)) return "fetch";
982
+ if (cause instanceof TypeError) {
983
+ const urlCode = cause.code;
984
+ if (cause.name === "InvalidContextReferenceError") return "invalid";
985
+ if (urlCode === "ERR_INVALID_URL" || cause.message === "Invalid URL string." || /^Invalid URL(?::|$)/.test(cause.message) || / cannot be parsed as a URL\.?$/.test(cause.message)) return typeof details.url === "string" && /^[A-Za-z][A-Za-z0-9+.-]*:/.test(details.url) && !URL.canParse(details.url) ? "invalid" : "fetch";
986
+ const networkCause = cause.cause;
987
+ const code = cause.code ?? networkCause?.code;
988
+ if (typeof code === "string" && [
989
+ "ECONNREFUSED",
990
+ "ECONNRESET",
991
+ "ECONNABORTED",
992
+ "ETIMEDOUT",
993
+ "EHOSTUNREACH",
994
+ "ENETUNREACH",
995
+ "ENOTFOUND",
996
+ "EAI_AGAIN",
997
+ "UND_ERR_CONNECT_TIMEOUT",
998
+ "UND_ERR_HEADERS_TIMEOUT",
999
+ "UND_ERR_BODY_TIMEOUT",
1000
+ "UND_ERR_SOCKET"
1001
+ ].includes(code) || /^(fetch failed|Failed to fetch|error sending request|error reading a body from connection|Unable to connect|ConnectionRefused|Network connection lost|The socket connection was closed unexpectedly)/.test(cause.message)) return "fetch";
1002
+ }
1003
+ throw cause;
1004
+ }
1005
+ /** Carries a context transport failure through the key decoding boundary. */
1006
+ var KeyContextFetchError = class extends Error {
1007
+ error;
1008
+ constructor(error) {
1009
+ super("Failed to fetch a key's JSON-LD context.", { cause: error });
1010
+ this.error = error;
1011
+ }
1012
+ };
1013
+ function contextFetchError(error) {
1014
+ const seen = /* @__PURE__ */ new Set();
1015
+ while (error instanceof Error && !seen.has(error)) {
1016
+ seen.add(error);
1017
+ const details = error.details;
1018
+ if (!error.name.startsWith("jsonld.") || details?.code !== "loading remote context failed") break;
1019
+ error = "cause" in details ? details.cause : error.cause;
1020
+ }
1021
+ return new KeyContextFetchError(error);
1022
+ }
964
1023
  /**
965
1024
  * Checks if the given key is valid and supported. No-op if the key is valid,
966
1025
  * otherwise throws an error.
@@ -1055,6 +1114,9 @@ async function importJwk(jwk, type) {
1055
1114
  * @internal
1056
1115
  */
1057
1116
  async function fetchActorDocument(actorId, options = {}) {
1117
+ return await fetchActorDocumentInternal(actorId, options, false);
1118
+ }
1119
+ async function fetchActorDocumentInternal(actorId, options, propagateContextFetchErrors) {
1058
1120
  const logger = (0, _logtape_logtape.getLogger)([
1059
1121
  "fedify",
1060
1122
  "sig",
@@ -1085,9 +1147,12 @@ async function fetchActorDocument(actorId, options = {}) {
1085
1147
  baseUrl: documentUrl
1086
1148
  });
1087
1149
  } catch (error) {
1088
- if (!(error instanceof TypeError)) throw error;
1089
- logger.debug("The document served at {documentUrl} is not a valid object: {error}", {
1150
+ const failure = classifyKeyJsonLdError(error);
1151
+ if (failure === "fetch" && propagateContextFetchErrors) throw contextFetchError(error);
1152
+ if (failure == null && !(error instanceof TypeError)) throw error;
1153
+ logger.debug("Failed to decode the actor document at {documentUrl}: {error}", {
1090
1154
  documentUrl: documentUrl.href,
1155
+ failure: failure ?? "invalid",
1091
1156
  error
1092
1157
  });
1093
1158
  return null;
@@ -1126,6 +1191,9 @@ async function fetchActorDocument(actorId, options = {}) {
1126
1191
  * @internal
1127
1192
  */
1128
1193
  async function verifyKeyOwnership(key, options = {}) {
1194
+ return await verifyKeyOwnershipInternal(key, options, false);
1195
+ }
1196
+ async function verifyKeyOwnershipInternal(key, options, propagateContextFetchErrors) {
1129
1197
  const logger = (0, _logtape_logtape.getLogger)([
1130
1198
  "fedify",
1131
1199
  "sig",
@@ -1135,7 +1203,7 @@ async function verifyKeyOwnership(key, options = {}) {
1135
1203
  if (keyId == null) return null;
1136
1204
  const claimedOwnerId = key instanceof _fedify_vocab.CryptographicKey ? key.ownerId : key.controllerId;
1137
1205
  if (claimedOwnerId == null) return null;
1138
- const owner = await fetchActorDocument(claimedOwnerId, options);
1206
+ const owner = await fetchActorDocumentInternal(claimedOwnerId, options, propagateContextFetchErrors);
1139
1207
  if (owner == null) {
1140
1208
  logger.debug("The owner ({claimedOwnerId}) that key {keyId} claims could not be resolved.", {
1141
1209
  keyId: keyId.href,
@@ -1287,6 +1355,21 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
1287
1355
  tracerProvider
1288
1356
  });
1289
1357
  } catch (e) {
1358
+ const failure = classifyKeyJsonLdError(e);
1359
+ if (failure === "fetch") throw contextFetchError(e);
1360
+ if (failure != null) {
1361
+ logger.debug("Failed to decode key {keyId}: {error}", {
1362
+ keyId,
1363
+ failure,
1364
+ error: e
1365
+ });
1366
+ await keyCache?.set(cacheKey, null);
1367
+ await clearFetchErrorMetadata(cacheKey, keyCache);
1368
+ return {
1369
+ key: null,
1370
+ cached: false
1371
+ };
1372
+ }
1290
1373
  if (!(e instanceof TypeError)) throw e;
1291
1374
  try {
1292
1375
  object = await cls.fromJsonLd(document, {
@@ -1295,8 +1378,14 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
1295
1378
  tracerProvider
1296
1379
  });
1297
1380
  } catch (e) {
1298
- if (e instanceof TypeError) {
1299
- logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
1381
+ const failure = classifyKeyJsonLdError(e);
1382
+ if (failure === "fetch") throw contextFetchError(e);
1383
+ if (failure != null || e instanceof TypeError) {
1384
+ logger.debug("Failed to decode key {keyId}: {error}", {
1385
+ keyId,
1386
+ failure: failure ?? "invalid",
1387
+ error: e
1388
+ });
1300
1389
  await keyCache?.set(cacheKey, null);
1301
1390
  await clearFetchErrorMetadata(cacheKey, keyCache);
1302
1391
  return {
@@ -1388,16 +1477,17 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
1388
1477
  const claimedOwnerId = key instanceof _fedify_vocab.CryptographicKey ? key.ownerId : key.controllerId;
1389
1478
  if (ownerDocument != null && claimedOwnerId == null) key = key instanceof _fedify_vocab.CryptographicKey ? key.clone({ owner: ownerDocument.id }) : key.clone({ controller: ownerDocument.id });
1390
1479
  else if (claimedOwnerId != null && claimedOwnerId.href !== ownerDocument?.id?.href) {
1391
- if (await verifyKeyOwnership(key, {
1480
+ if (await verifyKeyOwnershipInternal(key, {
1392
1481
  documentLoader,
1393
1482
  contextLoader,
1394
1483
  tracerProvider
1395
- }) == null) {
1484
+ }, true) == null) {
1396
1485
  logger.debug("Failed to verify; the owner {claimedOwnerId} that key {keyId} claims does not list the key as its own.", {
1397
1486
  keyId,
1398
1487
  claimedOwnerId: claimedOwnerId.href
1399
1488
  });
1400
1489
  await keyCache?.set(cacheKey, null);
1490
+ await clearFetchErrorMetadata(cacheKey, keyCache);
1401
1491
  return {
1402
1492
  key: null,
1403
1493
  cached: false
@@ -1448,9 +1538,17 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
1448
1538
  outcome = classified;
1449
1539
  return errored;
1450
1540
  }
1451
- const resolved = await resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, options, logger);
1452
- outcome = { result: resolved.key != null ? "fetched" : "invalid" };
1453
- return resolved;
1541
+ try {
1542
+ const resolved = await resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, options, logger);
1543
+ outcome = { result: resolved.key != null ? "fetched" : "invalid" };
1544
+ return resolved;
1545
+ } catch (error) {
1546
+ if (!(error instanceof KeyContextFetchError)) throw error;
1547
+ const classified = classifyFetchError(error.error);
1548
+ const errored = await onFetchError(error.error, cacheKey, keyId, keyCache, logger);
1549
+ outcome = classified;
1550
+ return errored;
1551
+ }
1454
1552
  } finally {
1455
1553
  recordKeyLookup(options.meterProvider, {
1456
1554
  durationMs: getDurationMs(start),
@@ -4,13 +4,13 @@ import { getLogger } from "@logtape/logtape";
4
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
- import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
7
+ import { FetchError, UrlError, getDocumentLoader } from "@fedify/vocab-runtime";
8
8
  import { Item, decodeDict, encodeDict, encodeItem } from "structured-field-values";
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.3.12-dev.2365+89254121";
13
+ var version = "2.3.12";
14
14
  //#endregion
15
15
  //#region src/sig/accept.ts
16
16
  /**
@@ -960,6 +960,65 @@ function getDurationMs(start) {
960
960
  }
961
961
  //#endregion
962
962
  //#region src/sig/key.ts
963
+ /** Classifies decoding failures without hiding unexpected loader errors. */
964
+ function classifyKeyJsonLdError(error, seen = /* @__PURE__ */ new Set()) {
965
+ if (!(error instanceof Error) || !error.name.startsWith("jsonld.")) return null;
966
+ if (seen.has(error)) throw error;
967
+ seen.add(error);
968
+ const details = error.details;
969
+ if (typeof details?.code !== "string") return null;
970
+ if (details.code !== "loading remote context failed" || !("cause" in details) && !("cause" in error)) return "invalid";
971
+ const cause = "cause" in details ? details.cause : error.cause;
972
+ const nestedFailure = classifyKeyJsonLdError(cause, seen);
973
+ if (nestedFailure != null) return nestedFailure;
974
+ if (cause instanceof SyntaxError) return "invalid";
975
+ if (cause instanceof FetchError || cause instanceof UrlError) return "fetch";
976
+ if (cause instanceof Error && [
977
+ "AbortError",
978
+ "TimeoutError",
979
+ "NetworkError"
980
+ ].includes(cause.name)) return "fetch";
981
+ if (cause instanceof TypeError) {
982
+ const urlCode = cause.code;
983
+ if (cause.name === "InvalidContextReferenceError") return "invalid";
984
+ if (urlCode === "ERR_INVALID_URL" || cause.message === "Invalid URL string." || /^Invalid URL(?::|$)/.test(cause.message) || / cannot be parsed as a URL\.?$/.test(cause.message)) return typeof details.url === "string" && /^[A-Za-z][A-Za-z0-9+.-]*:/.test(details.url) && !URL.canParse(details.url) ? "invalid" : "fetch";
985
+ const networkCause = cause.cause;
986
+ const code = cause.code ?? networkCause?.code;
987
+ if (typeof code === "string" && [
988
+ "ECONNREFUSED",
989
+ "ECONNRESET",
990
+ "ECONNABORTED",
991
+ "ETIMEDOUT",
992
+ "EHOSTUNREACH",
993
+ "ENETUNREACH",
994
+ "ENOTFOUND",
995
+ "EAI_AGAIN",
996
+ "UND_ERR_CONNECT_TIMEOUT",
997
+ "UND_ERR_HEADERS_TIMEOUT",
998
+ "UND_ERR_BODY_TIMEOUT",
999
+ "UND_ERR_SOCKET"
1000
+ ].includes(code) || /^(fetch failed|Failed to fetch|error sending request|error reading a body from connection|Unable to connect|ConnectionRefused|Network connection lost|The socket connection was closed unexpectedly)/.test(cause.message)) return "fetch";
1001
+ }
1002
+ throw cause;
1003
+ }
1004
+ /** Carries a context transport failure through the key decoding boundary. */
1005
+ var KeyContextFetchError = class extends Error {
1006
+ error;
1007
+ constructor(error) {
1008
+ super("Failed to fetch a key's JSON-LD context.", { cause: error });
1009
+ this.error = error;
1010
+ }
1011
+ };
1012
+ function contextFetchError(error) {
1013
+ const seen = /* @__PURE__ */ new Set();
1014
+ while (error instanceof Error && !seen.has(error)) {
1015
+ seen.add(error);
1016
+ const details = error.details;
1017
+ if (!error.name.startsWith("jsonld.") || details?.code !== "loading remote context failed") break;
1018
+ error = "cause" in details ? details.cause : error.cause;
1019
+ }
1020
+ return new KeyContextFetchError(error);
1021
+ }
963
1022
  /**
964
1023
  * Checks if the given key is valid and supported. No-op if the key is valid,
965
1024
  * otherwise throws an error.
@@ -1054,6 +1113,9 @@ async function importJwk(jwk, type) {
1054
1113
  * @internal
1055
1114
  */
1056
1115
  async function fetchActorDocument(actorId, options = {}) {
1116
+ return await fetchActorDocumentInternal(actorId, options, false);
1117
+ }
1118
+ async function fetchActorDocumentInternal(actorId, options, propagateContextFetchErrors) {
1057
1119
  const logger = getLogger([
1058
1120
  "fedify",
1059
1121
  "sig",
@@ -1084,9 +1146,12 @@ async function fetchActorDocument(actorId, options = {}) {
1084
1146
  baseUrl: documentUrl
1085
1147
  });
1086
1148
  } catch (error) {
1087
- if (!(error instanceof TypeError)) throw error;
1088
- logger.debug("The document served at {documentUrl} is not a valid object: {error}", {
1149
+ const failure = classifyKeyJsonLdError(error);
1150
+ if (failure === "fetch" && propagateContextFetchErrors) throw contextFetchError(error);
1151
+ if (failure == null && !(error instanceof TypeError)) throw error;
1152
+ logger.debug("Failed to decode the actor document at {documentUrl}: {error}", {
1089
1153
  documentUrl: documentUrl.href,
1154
+ failure: failure ?? "invalid",
1090
1155
  error
1091
1156
  });
1092
1157
  return null;
@@ -1125,6 +1190,9 @@ async function fetchActorDocument(actorId, options = {}) {
1125
1190
  * @internal
1126
1191
  */
1127
1192
  async function verifyKeyOwnership(key, options = {}) {
1193
+ return await verifyKeyOwnershipInternal(key, options, false);
1194
+ }
1195
+ async function verifyKeyOwnershipInternal(key, options, propagateContextFetchErrors) {
1128
1196
  const logger = getLogger([
1129
1197
  "fedify",
1130
1198
  "sig",
@@ -1134,7 +1202,7 @@ async function verifyKeyOwnership(key, options = {}) {
1134
1202
  if (keyId == null) return null;
1135
1203
  const claimedOwnerId = key instanceof CryptographicKey ? key.ownerId : key.controllerId;
1136
1204
  if (claimedOwnerId == null) return null;
1137
- const owner = await fetchActorDocument(claimedOwnerId, options);
1205
+ const owner = await fetchActorDocumentInternal(claimedOwnerId, options, propagateContextFetchErrors);
1138
1206
  if (owner == null) {
1139
1207
  logger.debug("The owner ({claimedOwnerId}) that key {keyId} claims could not be resolved.", {
1140
1208
  keyId: keyId.href,
@@ -1286,6 +1354,21 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
1286
1354
  tracerProvider
1287
1355
  });
1288
1356
  } catch (e) {
1357
+ const failure = classifyKeyJsonLdError(e);
1358
+ if (failure === "fetch") throw contextFetchError(e);
1359
+ if (failure != null) {
1360
+ logger.debug("Failed to decode key {keyId}: {error}", {
1361
+ keyId,
1362
+ failure,
1363
+ error: e
1364
+ });
1365
+ await keyCache?.set(cacheKey, null);
1366
+ await clearFetchErrorMetadata(cacheKey, keyCache);
1367
+ return {
1368
+ key: null,
1369
+ cached: false
1370
+ };
1371
+ }
1289
1372
  if (!(e instanceof TypeError)) throw e;
1290
1373
  try {
1291
1374
  object = await cls.fromJsonLd(document, {
@@ -1294,8 +1377,14 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
1294
1377
  tracerProvider
1295
1378
  });
1296
1379
  } catch (e) {
1297
- if (e instanceof TypeError) {
1298
- logger.debug("Failed to verify; key {keyId} returned an invalid object.", { keyId });
1380
+ const failure = classifyKeyJsonLdError(e);
1381
+ if (failure === "fetch") throw contextFetchError(e);
1382
+ if (failure != null || e instanceof TypeError) {
1383
+ logger.debug("Failed to decode key {keyId}: {error}", {
1384
+ keyId,
1385
+ failure: failure ?? "invalid",
1386
+ error: e
1387
+ });
1299
1388
  await keyCache?.set(cacheKey, null);
1300
1389
  await clearFetchErrorMetadata(cacheKey, keyCache);
1301
1390
  return {
@@ -1387,16 +1476,17 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
1387
1476
  const claimedOwnerId = key instanceof CryptographicKey ? key.ownerId : key.controllerId;
1388
1477
  if (ownerDocument != null && claimedOwnerId == null) key = key instanceof CryptographicKey ? key.clone({ owner: ownerDocument.id }) : key.clone({ controller: ownerDocument.id });
1389
1478
  else if (claimedOwnerId != null && claimedOwnerId.href !== ownerDocument?.id?.href) {
1390
- if (await verifyKeyOwnership(key, {
1479
+ if (await verifyKeyOwnershipInternal(key, {
1391
1480
  documentLoader,
1392
1481
  contextLoader,
1393
1482
  tracerProvider
1394
- }) == null) {
1483
+ }, true) == null) {
1395
1484
  logger.debug("Failed to verify; the owner {claimedOwnerId} that key {keyId} claims does not list the key as its own.", {
1396
1485
  keyId,
1397
1486
  claimedOwnerId: claimedOwnerId.href
1398
1487
  });
1399
1488
  await keyCache?.set(cacheKey, null);
1489
+ await clearFetchErrorMetadata(cacheKey, keyCache);
1400
1490
  return {
1401
1491
  key: null,
1402
1492
  cached: false
@@ -1447,9 +1537,17 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
1447
1537
  outcome = classified;
1448
1538
  return errored;
1449
1539
  }
1450
- const resolved = await resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, options, logger);
1451
- outcome = { result: resolved.key != null ? "fetched" : "invalid" };
1452
- return resolved;
1540
+ try {
1541
+ const resolved = await resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, options, logger);
1542
+ outcome = { result: resolved.key != null ? "fetched" : "invalid" };
1543
+ return resolved;
1544
+ } catch (error) {
1545
+ if (!(error instanceof KeyContextFetchError)) throw error;
1546
+ const classified = classifyFetchError(error.error);
1547
+ const errored = await onFetchError(error.error, cacheKey, keyId, keyCache, logger);
1548
+ outcome = classified;
1549
+ return errored;
1550
+ }
1453
1551
  } finally {
1454
1552
  recordKeyLookup(options.meterProvider, {
1455
1553
  durationMs: getDurationMs(start),
@@ -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-DSS6EkPl.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-Z0UkrR_1.mjs";
4
+ import { n as version, t as name } from "./deno-D4dcoVfF.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-cIaMxG0v.mjs";
6
6
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-Dd__NiUL.mjs";
7
- import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-vnmAGZ3_.mjs";
7
+ import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-Dg-NXm4K.mjs";
8
8
  import { getLogger } from "@logtape/logtape";
9
9
  import { CryptographicKey } from "@fedify/vocab";
10
10
  import { SpanStatusCode, trace } from "@opentelemetry/api";