@fedify/fedify 2.4.0-dev.2190 → 2.4.0-dev.2193

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 (78) hide show
  1. package/dist/{builder-CFF0YNTp.mjs → builder-0onlMY4u.mjs} +25 -5
  2. package/dist/compat/transformers.test.mjs +1 -1
  3. package/dist/{compound-proof-F2jjkrt0.mjs → compound-proof-B-Fk6Slo.mjs} +2 -2
  4. package/dist/{deno-EopndaNb.mjs → deno-DB_Sh0LK.mjs} +1 -1
  5. package/dist/{docloader-u6zzOExF.mjs → docloader-DpWYYY6a.mjs} +2 -2
  6. package/dist/federation/builder.test.mjs +1 -1
  7. package/dist/federation/compound-fanout.test.mjs +3 -3
  8. package/dist/federation/handler-compound-proof.test.mjs +52 -3
  9. package/dist/federation/handler.test.mjs +5 -5
  10. package/dist/federation/hashlink-media.test.mjs +2 -2
  11. package/dist/federation/idempotency.test.mjs +2 -2
  12. package/dist/federation/metrics.test.mjs +1 -1
  13. package/dist/federation/middleware.test.mjs +52 -7
  14. package/dist/federation/mod.cjs +1 -1
  15. package/dist/federation/mod.js +1 -1
  16. package/dist/federation/outgoing-proof.test.mjs +5 -5
  17. package/dist/federation/portable-actor.test.mjs +3 -3
  18. package/dist/federation/portable-chain.test.mjs +3 -3
  19. package/dist/federation/portable-collection.test.mjs +4 -4
  20. package/dist/federation/portable-gateway-keys.test.mjs +4 -4
  21. package/dist/federation/portable-inbox.test.mjs +4 -4
  22. package/dist/federation/portable-parse-uri.test.mjs +1 -1
  23. package/dist/federation/portable-route-activity.test.mjs +2 -2
  24. package/dist/federation/portable.test.mjs +49 -5
  25. package/dist/federation/send.test.mjs +3 -3
  26. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  27. package/dist/federation/tasks/tasks.test.mjs +2 -2
  28. package/dist/federation/temporal.test.mjs +1 -1
  29. package/dist/federation/webfinger.test.mjs +1 -1
  30. package/dist/{federation-BSS2dUO7.cjs → federation-BsGo0EH2.cjs} +41 -17
  31. package/dist/{http-CCr2_ipG.cjs → http-BEivI0TS.cjs} +44 -2
  32. package/dist/{http-BqN5kyUf.js → http-BGmxtpo2.js} +45 -3
  33. package/dist/{http-Y1ObT1A8.mjs → http-DQf9Mw4V.mjs} +4 -4
  34. package/dist/{key-DyXf88bq.mjs → key-DA3Yx8p2.mjs} +2 -2
  35. package/dist/{kv-cache-DUXluAc0.cjs → kv-cache-1hafSoqH.cjs} +1 -1
  36. package/dist/{kv-cache-C02XitwK.js → kv-cache-DduYhpee.js} +1 -1
  37. package/dist/{kv-cache-C8YjNAi_.mjs → kv-cache-OFBvrKh3.mjs} +1 -1
  38. package/dist/{ld-oQj6j_hP.mjs → ld-C15yzuY6.mjs} +3 -3
  39. package/dist/{metrics-zMe834ID.mjs → metrics-B1H23mlq.mjs} +1 -1
  40. package/dist/{middleware-Ck9yghxs.mjs → middleware-BZQnf0nI.mjs} +1 -1
  41. package/dist/{middleware-Bdu2-OPD.mjs → middleware-BqqycC0P.mjs} +29 -25
  42. package/dist/{middleware-CaR2MRWY.js → middleware-ClaUFaLb.js} +41 -17
  43. package/dist/{mod-Ck9_lSJB.d.ts → mod-Cy9VNHVw.d.ts} +12 -1
  44. package/dist/{mod-DHTuu3l8.d.cts → mod-DoTWIc7F.d.cts} +12 -1
  45. package/dist/mod.cjs +4 -4
  46. package/dist/mod.d.cts +1 -1
  47. package/dist/mod.d.ts +1 -1
  48. package/dist/mod.js +4 -4
  49. package/dist/nodeinfo/handler.test.mjs +1 -1
  50. package/dist/{owner-Dem4fbwc.mjs → owner-BVpZBM-V.mjs} +3 -3
  51. package/dist/{portable-collection-DJe_bk50.cjs → portable-collection-BFSShzwh.cjs} +1 -1
  52. package/dist/{portable-collection-BEqLrMW3.js → portable-collection-D535cSz_.js} +1 -1
  53. package/dist/{portable-collection-BL6aZlQ0.mjs → portable-collection-Dn2GdZdI.mjs} +2 -2
  54. package/dist/{portable-key-Duue9Y2Y.mjs → portable-key-Bmwmq7Y6.mjs} +1 -1
  55. package/dist/{proof-C9115DX_.mjs → proof-DrJWKeOl.mjs} +48 -6
  56. package/dist/{send-D0hxFFRB.mjs → send-CT3a-0Vd.mjs} +3 -3
  57. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  58. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  59. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  60. package/dist/sig/compound-proof.test.mjs +2 -2
  61. package/dist/sig/http.test.mjs +2 -2
  62. package/dist/sig/key.test.mjs +1 -1
  63. package/dist/sig/ld.test.mjs +2 -2
  64. package/dist/sig/mod.cjs +2 -2
  65. package/dist/sig/mod.d.cts +1 -1
  66. package/dist/sig/mod.d.ts +1 -1
  67. package/dist/sig/mod.js +2 -2
  68. package/dist/sig/owner.test.mjs +1 -1
  69. package/dist/sig/portable-collection.test.mjs +1 -1
  70. package/dist/sig/portable-key.test.mjs +6 -6
  71. package/dist/sig/proof.test.mjs +141 -7
  72. package/dist/{temporal-DKchpKyp.mjs → temporal-DNqluyEc.mjs} +1 -1
  73. package/dist/testing/kv.test.mjs +1 -1
  74. package/dist/utils/docloader.test.mjs +2 -2
  75. package/dist/utils/kv-cache.test.mjs +1 -1
  76. package/dist/utils/mod.cjs +1 -1
  77. package/dist/utils/mod.js +1 -1
  78. package/package.json +6 -6
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
5
5
  import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assert } from "../assert-D1Eafmd_.mjs";
7
- import { t as hasMalformedKnownTemporalLiteral } from "../temporal-DKchpKyp.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-DNqluyEc.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 MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
- import { o as createFederation, s as handleWebFinger } from "../middleware-Bdu2-OPD.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-BqqycC0P.mjs";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  import { createTestMeterProvider, test } from "@fedify/fixture";
12
12
  import { parseIri } from "@fedify/vocab-runtime";
@@ -1,10 +1,10 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-Dmm3t92W.cjs");
3
3
  const require_transformers = require("./transformers-BalCrSsr.cjs");
4
- const require_http = require("./http-CCr2_ipG.cjs");
4
+ const require_http = require("./http-BEivI0TS.cjs");
5
5
  const require_types = require("./types-poIao40f.cjs");
6
- const require_portable_collection = require("./portable-collection-DJe_bk50.cjs");
7
- const require_kv_cache = require("./kv-cache-DUXluAc0.cjs");
6
+ const require_portable_collection = require("./portable-collection-BFSShzwh.cjs");
7
+ const require_kv_cache = require("./kv-cache-1hafSoqH.cjs");
8
8
  let _logtape_logtape = require("@logtape/logtape");
9
9
  let _fedify_uri_template = require("@fedify/uri-template");
10
10
  let _fedify_vocab = require("@fedify/vocab");
@@ -210,6 +210,7 @@ var FederationBuilderImpl = class {
210
210
  if (actor.id == null) logger.warn("Actor dispatcher returned an actor without an id property. Set the property with Context.getActorUri(identifier).");
211
211
  else if (!portable && actor.id.href != context.getActorUri(identifier).href) logger.warn("Actor dispatcher returned an actor with an id property that does not match the actor URI. Set the property with Context.getActorUri(identifier).");
212
212
  if (actor instanceof _fedify_vocab.Tombstone) return actor;
213
+ if (portable && actor.id != null) warnPortableActorGateways(actor.id, actor.gateways);
213
214
  if (actor.id != null && (0, _fedify_vocab_runtime_internal_portable_dereference.isCompatibleEf61Iri)(actor.id)) warnCompatibleActorId(actor.id, actor.gateway);
214
215
  if (portable) this.#warnPortableCollectionIds(context, identifier, actor);
215
216
  if (this.followingCallbacks != null && this.followingCallbacks.dispatcher != null) {
@@ -813,9 +814,28 @@ function warnMismatchedTombstoneId(context, cls, values, tombstone) {
813
814
  });
814
815
  }
815
816
  /**
817
+ * Warns about an FEP-ef61 portable actor whose `gateways` is empty or has
818
+ * an item that is not an HTTP(S) origin, which FEP-ef61 does not allow.
819
+ * Every item is checked, since the list and its URLs can be mutated after
820
+ * the actor is constructed.
821
+ */
822
+ function warnPortableActorGateways(actorId, gateways) {
823
+ if (gateways.length > 0 && gateways.every(_fedify_vocab_runtime.isGatewayUrl)) return;
824
+ (0, _logtape_logtape.getLogger)([
825
+ "fedify",
826
+ "federation",
827
+ "actor"
828
+ ]).warn("Actor dispatcher returned an FEP-ef61 portable actor, {actorId}, whose gateways property is empty or has an item that is not an HTTP(S) origin. FEP-ef61 requires a portable actor to have at least one gateway, and every gateway to be an HTTP(S) URI with an empty path, query, and fragment. Set the gateways property.", {
829
+ actorId: actorId.href,
830
+ gateways: gateways.map((g) => g.href)
831
+ });
832
+ }
833
+ /**
816
834
  * Warns about an FEP-ef61 portable actor identified by a compatible identifier
817
835
  * that is malformed, or is not on the actor's first gateway, where FEP-ef61
818
- * requires publishers to construct compatible identifiers.
836
+ * requires publishers to construct compatible identifiers. A missing or
837
+ * invalid first gateway is reported by {@link warnPortableActorGateways}
838
+ * instead.
819
839
  */
820
840
  function warnCompatibleActorId(actorId, gateway) {
821
841
  const logger = (0, _logtape_logtape.getLogger)([
@@ -833,8 +853,8 @@ function warnCompatibleActorId(actorId, gateway) {
833
853
  });
834
854
  return;
835
855
  }
836
- if (gateway == null || !(0, _fedify_vocab_runtime.isGatewayUrl)(gateway)) logger.warn("Actor dispatcher returned an actor whose id property, {actorId}, is an FEP-ef61 compatible identifier, but whose first gateway is not an HTTP(S) origin. Set the gateways property, and construct the compatible identifier with its first gateway.", { actorId: actorId.href });
837
- else if (actorId.origin !== gateway.origin) logger.warn("Actor dispatcher returned an actor whose id property, {actorId}, is an FEP-ef61 compatible identifier on another gateway than its first gateway, {gateway}. FEP-ef61 requires publishers to construct compatible identifiers with the first gateway in the actor's gateways.", {
856
+ if (gateway == null || !(0, _fedify_vocab_runtime.isGatewayUrl)(gateway)) return;
857
+ if (actorId.origin !== gateway.origin) logger.warn("Actor dispatcher returned an actor whose id property, {actorId}, is an FEP-ef61 compatible identifier on another gateway than its first gateway, {gateway}. FEP-ef61 requires publishers to construct compatible identifiers with the first gateway in the actor's gateways.", {
838
858
  actorId: actorId.href,
839
859
  gateway: gateway.origin
840
860
  });
@@ -3792,7 +3812,7 @@ function isInvalidJsonLdError(error) {
3792
3812
  return name === "UnsafeJsonLdError" || error instanceof require_http.InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
3793
3813
  }
3794
3814
  function isValidationTypeError(error) {
3795
- return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:)/.test(error.message) || require_http.isInvalidUrlTypeError(error));
3815
+ return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:|Invalid FEP-ef61 gateway:)/.test(error.message) || require_http.isInvalidUrlTypeError(error));
3796
3816
  }
3797
3817
  function isPermanentActivityParseError(error) {
3798
3818
  return isInvalidJsonLdError(error) || isValidationTypeError(error);
@@ -3935,7 +3955,11 @@ async function handlePortableObject(request, { values, context, objectDispatcher
3935
3955
  return await onNotFound(request);
3936
3956
  }
3937
3957
  if (tombstone || result.reason.type !== "unsecuredCollection" && result.reason.type !== "unsupportedObjectType") {
3938
- logger.error("Refusing to serve the portable object {portableId}, as it does not satisfy the FEP-ef61 proof policy: {reason}. Portable actors, activities, objects, and tombstones need an Object Integrity Proof made with a key of the DID in their ID.", {
3958
+ if (result.reason.type === "invalidGateways") logger.error("Refusing to serve the portable actor {portableId}, as its gateways property is missing, empty, or has an item that is not an HTTP(S) origin. FEP-ef61 requires a portable actor to list at least one gateway where it can be retrieved.", {
3959
+ portableId: canonicalId,
3960
+ reason: result.reason.type
3961
+ });
3962
+ else logger.error("Refusing to serve the portable object {portableId}, as it does not satisfy the FEP-ef61 proof policy: {reason}. Portable actors, activities, objects, and tombstones need an Object Integrity Proof made with a key of the DID in their ID.", {
3939
3963
  portableId: canonicalId,
3940
3964
  reason: result.reason.type
3941
3965
  });
@@ -4054,13 +4078,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
4054
4078
  * @param parameters The parameters for handling the collection.
4055
4079
  * @returns A promise that resolves to an HTTP response.
4056
4080
  */
4057
- async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
4058
- const spanName = name$1.trim().replace(/\s+/g, "_");
4081
+ async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
4082
+ const spanName = name$2.trim().replace(/\s+/g, "_");
4059
4083
  tracerProvider = tracerProvider ?? _opentelemetry_api.trace.getTracerProvider();
4060
4084
  const tracer = tracerProvider.getTracer(require_http.name, require_http.version);
4061
4085
  const cursor = new URL(request.url).searchParams.get("cursor");
4062
4086
  const metricBase = {
4063
- kind: getCollectionMetricKind(name$1),
4087
+ kind: getCollectionMetricKind(name$2),
4064
4088
  page: cursor != null,
4065
4089
  dispatcher: "built_in"
4066
4090
  };
@@ -4106,7 +4130,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
4106
4130
  span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
4107
4131
  return await onNotFound(request);
4108
4132
  }
4109
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
4133
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
4110
4134
  itemCount = items.length;
4111
4135
  span.setAttribute("fedify.collection.items", itemCount);
4112
4136
  return items;
@@ -4148,7 +4172,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
4148
4172
  } else {
4149
4173
  const uri = new URL(portable == null ? baseUri : pageBase);
4150
4174
  uri.searchParams.set("cursor", cursor);
4151
- const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
4175
+ const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
4152
4176
  kind: _opentelemetry_api.SpanKind.SERVER,
4153
4177
  attributes: {
4154
4178
  "activitypub.collection.id": uri.href,
@@ -4164,7 +4188,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
4164
4188
  span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
4165
4189
  return await onNotFound(request);
4166
4190
  }
4167
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
4191
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
4168
4192
  itemCount = items.length;
4169
4193
  span.setAttribute("fedify.collection.items", itemCount);
4170
4194
  return {
@@ -5355,8 +5379,8 @@ var CustomCollectionHandler = class {
5355
5379
  * @param CollectionPage The CollectionPage constructor.
5356
5380
  * @param filterPredicate Optional filter predicate for items.
5357
5381
  */
5358
- constructor(name$2, values, context, callbacks, tracerProvider = _opentelemetry_api.trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
5359
- this.name = name$2;
5382
+ constructor(name$1, values, context, callbacks, tracerProvider = _opentelemetry_api.trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
5383
+ this.name = name$1;
5360
5384
  this.values = values;
5361
5385
  this.context = context;
5362
5386
  this.callbacks = callbacks;
@@ -7235,7 +7259,7 @@ function isPermanentRemoteContextError(error) {
7235
7259
  return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && require_http.isClearlyMalformedContextReference(details.url);
7236
7260
  }
7237
7261
  function isPermanentInboxParseError(error) {
7238
- return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof require_http.InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:)/.test(error.message) || require_http.isInvalidUrlTypeError(error));
7262
+ return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof require_http.InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:|Invalid FEP-ef61 gateway:)/.test(error.message) || require_http.isInvalidUrlTypeError(error));
7239
7263
  }
7240
7264
  function hasLinkedDataSignatureJsonLdProcessingError(error) {
7241
7265
  if (error.message.startsWith("Maximum deep iterations exceeded")) return true;
@@ -16,7 +16,7 @@ json_canon = require_rolldown_runtime.__toESM(json_canon, 1);
16
16
  let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
17
17
  //#region deno.json
18
18
  var name = "@fedify/fedify";
19
- var version = "2.4.0-dev.2190+be3a8be0";
19
+ var version = "2.4.0-dev.2193+402149b5";
20
20
  //#endregion
21
21
  //#region src/sig/portable-key-id.ts
22
22
  const COMPATIBLE_KEY_ID_PATH_PATTERN = /^\/\.well-known\/apgateway\/did(?::|%3A)/i;
@@ -7473,6 +7473,7 @@ const FEP_2277_COLLECTION_PROPERTIES = [
7473
7473
  "prev",
7474
7474
  "current"
7475
7475
  ].map((property) => AS_NAMESPACE + property);
7476
+ const FEP_EF61_GATEWAYS = "https://w3id.org/fep/ef61/gateways";
7476
7477
  const PORTABLE_OBJECT_ID_PATTERN = /^ap(?:\+ef61)?:\/\//i;
7477
7478
  const FUNCTIONAL_PROOF_PROPERTIES = [
7478
7479
  `${SECURITY_NAMESPACE}cryptosuite`,
@@ -7499,6 +7500,35 @@ function hasValidPortableProofShape(proofValue) {
7499
7500
  });
7500
7501
  }
7501
7502
  /**
7503
+ * Checks whether an expanded portable actor node has the `gateways` that
7504
+ * FEP-ef61 requires: a non-empty list whose items are all HTTP(S) URIs with
7505
+ * an empty path, query, and fragment. Like the generated vocabulary decoder,
7506
+ * this also tolerates a plain set of values instead of a `@list`, and gateway
7507
+ * strings given as `@value`s instead of `@id`s.
7508
+ */
7509
+ function hasValidPortableActorGateways(node) {
7510
+ const values = node[FEP_EF61_GATEWAYS];
7511
+ if (!Array.isArray(values)) return false;
7512
+ let items = values;
7513
+ if (values.some((value) => isJsonLdNode(value) && "@list" in value)) {
7514
+ if (values.length !== 1) return false;
7515
+ items = values[0]["@list"];
7516
+ }
7517
+ if (!Array.isArray(items) || items.length < 1) return false;
7518
+ return items.every((item) => {
7519
+ if (!isJsonLdNode(item)) return false;
7520
+ const gateway = typeof item["@id"] === "string" ? item["@id"] : item["@value"];
7521
+ if (typeof gateway !== "string") return false;
7522
+ try {
7523
+ (0, _fedify_vocab_runtime.parseGatewayUrl)(gateway);
7524
+ } catch (error) {
7525
+ if (error instanceof TypeError) return false;
7526
+ throw error;
7527
+ }
7528
+ return true;
7529
+ });
7530
+ }
7531
+ /**
7502
7532
  * Classifies an expanded JSON-LD node into an FEP-2277 core type by the
7503
7533
  * properties it has.
7504
7534
  * @internal
@@ -7702,6 +7732,15 @@ async function preparePortableObjectProof(jsonLd, options) {
7702
7732
  }
7703
7733
  };
7704
7734
  }
7735
+ if (objectType === "actor" && !hasValidPortableActorGateways(root)) return {
7736
+ prepared: false,
7737
+ root,
7738
+ objectType,
7739
+ result: {
7740
+ verified: false,
7741
+ reason: { type: "invalidGateways" }
7742
+ }
7743
+ };
7705
7744
  return {
7706
7745
  prepared: true,
7707
7746
  root,
@@ -7755,7 +7794,10 @@ async function verifyPortableObjectProofPolicy(jsonLd, key, options = {}) {
7755
7794
  *
7756
7795
  * Every proof must use a DID URL whose DID matches the portable object's
7757
7796
  * authority, i.e., the DID of its canonical portable ID, and every proof must
7758
- * pass {@link verifyProof}. The proofs are verified over the document as
7797
+ * pass {@link verifyProof}. A portable actor must also have a non-empty
7798
+ * `gateways` list whose items are all HTTP(S) URIs with an empty path, query,
7799
+ * and fragment; otherwise, it is rejected with the `invalidGateways` reason
7800
+ * before its proofs are verified. The proofs are verified over the document as
7759
7801
  * given; a compatible identifier is never rewritten into a portable ID.
7760
7802
  *
7761
7803
  * [FEP-ef61]: https://w3id.org/fep/ef61
@@ -3,7 +3,7 @@ import { URLPattern } from "urlpattern-polyfill";
3
3
  import { getLogger } from "@logtape/logtape";
4
4
  import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, PUBLIC_COLLECTION, getTypeId, isActor } from "@fedify/vocab";
5
5
  import { SpanKind, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
6
- import { FetchError, canonicalizePortableUri, encodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDidKeyVerificationMethod, parseIri, preloadedContexts, toCompatibleEf61Id } from "@fedify/vocab-runtime";
6
+ import { FetchError, canonicalizePortableUri, encodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDidKeyVerificationMethod, parseGatewayUrl, parseIri, preloadedContexts, toCompatibleEf61Id } from "@fedify/vocab-runtime";
7
7
  import { getPortableGatewayCandidates, isCompatibleEf61Iri } from "@fedify/vocab-runtime/internal/portable-dereference";
8
8
  import { encodeHex } from "byte-encodings/hex";
9
9
  import jsonld from "@fedify/vocab-runtime/jsonld";
@@ -14,7 +14,7 @@ import serialize from "json-canon";
14
14
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
15
15
  //#region deno.json
16
16
  var name = "@fedify/fedify";
17
- var version = "2.4.0-dev.2190+be3a8be0";
17
+ var version = "2.4.0-dev.2193+402149b5";
18
18
  //#endregion
19
19
  //#region src/sig/portable-key-id.ts
20
20
  const COMPATIBLE_KEY_ID_PATH_PATTERN = /^\/\.well-known\/apgateway\/did(?::|%3A)/i;
@@ -3904,6 +3904,7 @@ const FEP_2277_COLLECTION_PROPERTIES = [
3904
3904
  "prev",
3905
3905
  "current"
3906
3906
  ].map((property) => AS_NAMESPACE + property);
3907
+ const FEP_EF61_GATEWAYS = "https://w3id.org/fep/ef61/gateways";
3907
3908
  const PORTABLE_OBJECT_ID_PATTERN = /^ap(?:\+ef61)?:\/\//i;
3908
3909
  const FUNCTIONAL_PROOF_PROPERTIES = [
3909
3910
  `${SECURITY_NAMESPACE}cryptosuite`,
@@ -3930,6 +3931,35 @@ function hasValidPortableProofShape(proofValue) {
3930
3931
  });
3931
3932
  }
3932
3933
  /**
3934
+ * Checks whether an expanded portable actor node has the `gateways` that
3935
+ * FEP-ef61 requires: a non-empty list whose items are all HTTP(S) URIs with
3936
+ * an empty path, query, and fragment. Like the generated vocabulary decoder,
3937
+ * this also tolerates a plain set of values instead of a `@list`, and gateway
3938
+ * strings given as `@value`s instead of `@id`s.
3939
+ */
3940
+ function hasValidPortableActorGateways(node) {
3941
+ const values = node[FEP_EF61_GATEWAYS];
3942
+ if (!Array.isArray(values)) return false;
3943
+ let items = values;
3944
+ if (values.some((value) => isJsonLdNode(value) && "@list" in value)) {
3945
+ if (values.length !== 1) return false;
3946
+ items = values[0]["@list"];
3947
+ }
3948
+ if (!Array.isArray(items) || items.length < 1) return false;
3949
+ return items.every((item) => {
3950
+ if (!isJsonLdNode(item)) return false;
3951
+ const gateway = typeof item["@id"] === "string" ? item["@id"] : item["@value"];
3952
+ if (typeof gateway !== "string") return false;
3953
+ try {
3954
+ parseGatewayUrl(gateway);
3955
+ } catch (error) {
3956
+ if (error instanceof TypeError) return false;
3957
+ throw error;
3958
+ }
3959
+ return true;
3960
+ });
3961
+ }
3962
+ /**
3933
3963
  * Classifies an expanded JSON-LD node into an FEP-2277 core type by the
3934
3964
  * properties it has.
3935
3965
  * @internal
@@ -4133,6 +4163,15 @@ async function preparePortableObjectProof(jsonLd, options) {
4133
4163
  }
4134
4164
  };
4135
4165
  }
4166
+ if (objectType === "actor" && !hasValidPortableActorGateways(root)) return {
4167
+ prepared: false,
4168
+ root,
4169
+ objectType,
4170
+ result: {
4171
+ verified: false,
4172
+ reason: { type: "invalidGateways" }
4173
+ }
4174
+ };
4136
4175
  return {
4137
4176
  prepared: true,
4138
4177
  root,
@@ -4186,7 +4225,10 @@ async function verifyPortableObjectProofPolicy(jsonLd, key, options = {}) {
4186
4225
  *
4187
4226
  * Every proof must use a DID URL whose DID matches the portable object's
4188
4227
  * authority, i.e., the DID of its canonical portable ID, and every proof must
4189
- * pass {@link verifyProof}. The proofs are verified over the document as
4228
+ * pass {@link verifyProof}. A portable actor must also have a non-empty
4229
+ * `gateways` list whose items are all HTTP(S) URIs with an empty path, query,
4230
+ * and fragment; otherwise, it is rejected with the `invalidGateways` reason
4231
+ * before its proofs are verified. The proofs are verified over the document as
4190
4232
  * given; a compatible identifier is never rewritten into a portable ID.
4191
4233
  *
4192
4234
  * [FEP-ef61]: https://w3id.org/fep/ef61
@@ -1,13 +1,13 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-EopndaNb.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-zMe834ID.mjs";
4
+ import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-B1H23mlq.mjs";
6
6
  import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPVqki78.mjs";
7
7
  import { m as parseKeyIdString } from "./portable-key-id-Ca30-hOa.mjs";
8
8
  import { a as promoteKeyOwnerEvidence } from "./key-owner-evidence-APB6NpSk.mjs";
9
- import { a as fetchKeyDetailed, c as validateCryptoKey, t as bypassKeyCacheReads } from "./key-DyXf88bq.mjs";
10
- import { n as resolvePortableActorKey, r as verifyPortableGatewayKeyDocument } from "./portable-key-Duue9Y2Y.mjs";
9
+ import { a as fetchKeyDetailed, c as validateCryptoKey, t as bypassKeyCacheReads } from "./key-DA3Yx8p2.mjs";
10
+ import { n as resolvePortableActorKey, r as verifyPortableGatewayKeyDocument } from "./portable-key-Bmwmq7Y6.mjs";
11
11
  import { getLogger } from "@logtape/logtape";
12
12
  import { CryptographicKey } from "@fedify/vocab";
13
13
  import { SpanStatusCode, trace } from "@opentelemetry/api";
@@ -1,8 +1,8 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-EopndaNb.mjs";
5
- import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-zMe834ID.mjs";
4
+ import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
5
+ import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-B1H23mlq.mjs";
6
6
  import { c as isPortableActorDocument, d as isPortableUri, l as isPortableId, m as parseKeyIdString, s as isCompatibleKeyId } from "./portable-key-id-Ca30-hOa.mjs";
7
7
  import { n as attachKeyOwnerEvidence, t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-APB6NpSk.mjs";
8
8
  import { getLogger } from "@logtape/logtape";
@@ -1,5 +1,5 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
- const require_http = require("./http-CCr2_ipG.cjs");
2
+ const require_http = require("./http-BEivI0TS.cjs");
3
3
  let _logtape_logtape = require("@logtape/logtape");
4
4
  let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
5
5
  let es_toolkit = require("es-toolkit");
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-BqN5kyUf.js";
3
+ import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-BGmxtpo2.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, resolveDocumentLoaderTimeout, validatePublicUrl, withDocumentLoaderTimeout } from "@fedify/vocab-runtime";
6
6
  import { curry } from "es-toolkit";
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { p as recordDocumentCache } from "./metrics-zMe834ID.mjs";
4
+ import { p as recordDocumentCache } from "./metrics-B1H23mlq.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,9 +1,9 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-EopndaNb.mjs";
5
- import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-zMe834ID.mjs";
6
- import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-DyXf88bq.mjs";
4
+ import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
5
+ import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-B1H23mlq.mjs";
6
+ import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-DA3Yx8p2.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 "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-EopndaNb.mjs";
4
+ import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
5
5
  import { metrics } from "@opentelemetry/api";
6
6
  import { FetchError } from "@fedify/vocab-runtime";
7
7
  //#region src/federation/metrics.ts
@@ -1,5 +1,5 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as FederationImpl } from "./middleware-Bdu2-OPD.mjs";
4
+ import { n as FederationImpl } from "./middleware-BqqycC0P.mjs";
5
5
  export { FederationImpl };
@@ -1,29 +1,29 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-EopndaNb.mjs";
5
- import { 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, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-zMe834ID.mjs";
4
+ import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
5
+ import { 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, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-B1H23mlq.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
7
7
  import { d as isPortableUri, f as isSameObjectId, i as getPortableDid, l as isPortableId, n as getCanonicalPortableId, o as hasPortableActor, r as getGatewayKeyBase, s as isCompatibleKeyId, t as getAuthenticationOrigin, u as isPortableKeyId } from "./portable-key-id-Ca30-hOa.mjs";
8
- import { c as validateCryptoKey, n as exportJwk, s as importJwk } from "./key-DyXf88bq.mjs";
8
+ import { c as validateCryptoKey, n as exportJwk, s as importJwk } from "./key-DA3Yx8p2.mjs";
9
9
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
10
- import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-oQj6j_hP.mjs";
11
- import { a as signObject, c as verifyPortableObjectProof, i as hasProofLike, s as verifyObject, t as InvalidPortableObjectIdError, u as verifyPortableObjectProofWithRoot } from "./proof-C9115DX_.mjs";
12
- import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-Y1ObT1A8.mjs";
13
- import { t as getAuthenticatedDocumentLoader } from "./docloader-u6zzOExF.mjs";
14
- import { n as kvCache } from "./kv-cache-C8YjNAi_.mjs";
10
+ import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-C15yzuY6.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof, i as hasProofLike, s as verifyObject, t as InvalidPortableObjectIdError, u as verifyPortableObjectProofWithRoot } from "./proof-DrJWKeOl.mjs";
12
+ import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-DQf9Mw4V.mjs";
13
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-DpWYYY6a.mjs";
14
+ import { n as kvCache } from "./kv-cache-OFBvrKh3.mjs";
15
15
  import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-CEnNz8O7.mjs";
16
16
  import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
17
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-Dem4fbwc.mjs";
18
- import { t as verifyPortableObject } from "./portable-collection-BL6aZlQ0.mjs";
19
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-D0hxFFRB.mjs";
20
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-CFF0YNTp.mjs";
17
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-BVpZBM-V.mjs";
18
+ import { t as verifyPortableObject } from "./portable-collection-Dn2GdZdI.mjs";
19
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CT3a-0Vd.mjs";
20
+ import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-0onlMY4u.mjs";
21
21
  import { t as CircuitBreaker } from "./circuit-breaker-XJ53md4S.mjs";
22
22
  import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
23
- import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, s as verifyServedPortableObjects, t as containsCompoundPortableObject } from "./compound-proof-F2jjkrt0.mjs";
23
+ import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, s as verifyServedPortableObjects, t as containsCompoundPortableObject } from "./compound-proof-B-Fk6Slo.mjs";
24
24
  import { t as KvKeyCache } from "./keycache-Da8A8mZa.mjs";
25
25
  import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
26
- import { t as hasMalformedKnownTemporalLiteral } from "./temporal-DKchpKyp.mjs";
26
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-DNqluyEc.mjs";
27
27
  import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
28
28
  import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
29
29
  import { getLogger, withContext } from "@logtape/logtape";
@@ -1127,7 +1127,7 @@ function isInvalidJsonLdError(error) {
1127
1127
  return name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError$1(error) || name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure$1(error);
1128
1128
  }
1129
1129
  function isValidationTypeError(error) {
1130
- return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:)/.test(error.message) || isInvalidUrlTypeError(error));
1130
+ return error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:|Invalid FEP-ef61 gateway:)/.test(error.message) || isInvalidUrlTypeError(error));
1131
1131
  }
1132
1132
  function isPermanentActivityParseError(error) {
1133
1133
  return isInvalidJsonLdError(error) || isValidationTypeError(error);
@@ -1270,7 +1270,11 @@ async function handlePortableObject(request, { values, context, objectDispatcher
1270
1270
  return await onNotFound(request);
1271
1271
  }
1272
1272
  if (tombstone || result.reason.type !== "unsecuredCollection" && result.reason.type !== "unsupportedObjectType") {
1273
- logger.error("Refusing to serve the portable object {portableId}, as it does not satisfy the FEP-ef61 proof policy: {reason}. Portable actors, activities, objects, and tombstones need an Object Integrity Proof made with a key of the DID in their ID.", {
1273
+ if (result.reason.type === "invalidGateways") logger.error("Refusing to serve the portable actor {portableId}, as its gateways property is missing, empty, or has an item that is not an HTTP(S) origin. FEP-ef61 requires a portable actor to list at least one gateway where it can be retrieved.", {
1274
+ portableId: canonicalId,
1275
+ reason: result.reason.type
1276
+ });
1277
+ else logger.error("Refusing to serve the portable object {portableId}, as it does not satisfy the FEP-ef61 proof policy: {reason}. Portable actors, activities, objects, and tombstones need an Object Integrity Proof made with a key of the DID in their ID.", {
1274
1278
  portableId: canonicalId,
1275
1279
  reason: result.reason.type
1276
1280
  });
@@ -1389,13 +1393,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
1389
1393
  * @param parameters The parameters for handling the collection.
1390
1394
  * @returns A promise that resolves to an HTTP response.
1391
1395
  */
1392
- async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
1393
- const spanName = name$1.trim().replace(/\s+/g, "_");
1396
+ async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
1397
+ const spanName = name$2.trim().replace(/\s+/g, "_");
1394
1398
  tracerProvider = tracerProvider ?? trace.getTracerProvider();
1395
1399
  const tracer = tracerProvider.getTracer(name, version);
1396
1400
  const cursor = new URL(request.url).searchParams.get("cursor");
1397
1401
  const metricBase = {
1398
- kind: getCollectionMetricKind(name$1),
1402
+ kind: getCollectionMetricKind(name$2),
1399
1403
  page: cursor != null,
1400
1404
  dispatcher: "built_in"
1401
1405
  };
@@ -1441,7 +1445,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
1441
1445
  span.setStatus({ code: SpanStatusCode.ERROR });
1442
1446
  return await onNotFound(request);
1443
1447
  }
1444
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
1448
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
1445
1449
  itemCount = items.length;
1446
1450
  span.setAttribute("fedify.collection.items", itemCount);
1447
1451
  return items;
@@ -1483,7 +1487,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
1483
1487
  } else {
1484
1488
  const uri = new URL(portable == null ? baseUri : pageBase);
1485
1489
  uri.searchParams.set("cursor", cursor);
1486
- const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
1490
+ const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
1487
1491
  kind: SpanKind.SERVER,
1488
1492
  attributes: {
1489
1493
  "activitypub.collection.id": uri.href,
@@ -1499,7 +1503,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
1499
1503
  span.setStatus({ code: SpanStatusCode.ERROR });
1500
1504
  return await onNotFound(request);
1501
1505
  }
1502
- const items = filterCollectionItems(page.items, name$1, filterPredicate);
1506
+ const items = filterCollectionItems(page.items, name$2, filterPredicate);
1503
1507
  itemCount = items.length;
1504
1508
  span.setAttribute("fedify.collection.items", itemCount);
1505
1509
  return {
@@ -2690,8 +2694,8 @@ var CustomCollectionHandler = class {
2690
2694
  * @param CollectionPage The CollectionPage constructor.
2691
2695
  * @param filterPredicate Optional filter predicate for items.
2692
2696
  */
2693
- constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
2694
- this.name = name$2;
2697
+ constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
2698
+ this.name = name$1;
2695
2699
  this.values = values;
2696
2700
  this.context = context;
2697
2701
  this.callbacks = callbacks;
@@ -4070,7 +4074,7 @@ function isPermanentRemoteContextError(error) {
4070
4074
  return isRemoteContextLoadingFailure(error) && typeof details?.url === "string" && !URL.canParse(details.url) && isClearlyMalformedContextReference(details.url);
4071
4075
  }
4072
4076
  function isPermanentInboxParseError(error) {
4073
- return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:)/.test(error.message) || isInvalidUrlTypeError(error));
4077
+ return error instanceof Error && (error.name === "UnsafeJsonLdError" || error instanceof InvalidContextReferenceError || isPermanentRemoteContextError(error) || error.name === "jsonld.SyntaxError" && !isRemoteContextLoadingFailure(error)) || error instanceof TypeError && (/^(Invalid JSON-LD:|Invalid type:|Unexpected type:|Invalid @id:|Invalid FEP-ef61 gateway:)/.test(error.message) || isInvalidUrlTypeError(error));
4074
4078
  }
4075
4079
  function hasLinkedDataSignatureJsonLdProcessingError(error) {
4076
4080
  if (error.message.startsWith("Maximum deep iterations exceeded")) return true;