@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
@@ -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 { i as getPortableDid, l as isPortableId, n as getCanonicalPortableId } from "./portable-key-id-Ca30-hOa.mjs";
6
6
  import { t as ActivityListenerSet } from "./activity-listener-C-BSbKI7.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
@@ -89,7 +89,7 @@ var FederationBuilderImpl = class {
89
89
  * specified.
90
90
  */
91
91
  async build(options) {
92
- const { FederationImpl } = await import("./middleware-Ck9yghxs.mjs");
92
+ const { FederationImpl } = await import("./middleware-BZQnf0nI.mjs");
93
93
  const f = new FederationImpl(options);
94
94
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
95
95
  f.router = this.router.clone();
@@ -165,6 +165,7 @@ var FederationBuilderImpl = class {
165
165
  if (actor.id == null) logger.warn("Actor dispatcher returned an actor without an id property. Set the property with Context.getActorUri(identifier).");
166
166
  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).");
167
167
  if (actor instanceof Tombstone) return actor;
168
+ if (portable && actor.id != null) warnPortableActorGateways(actor.id, actor.gateways);
168
169
  if (actor.id != null && isCompatibleEf61Iri(actor.id)) warnCompatibleActorId(actor.id, actor.gateway);
169
170
  if (portable) this.#warnPortableCollectionIds(context, identifier, actor);
170
171
  if (this.followingCallbacks != null && this.followingCallbacks.dispatcher != null) {
@@ -768,9 +769,28 @@ function warnMismatchedTombstoneId(context, cls, values, tombstone) {
768
769
  });
769
770
  }
770
771
  /**
772
+ * Warns about an FEP-ef61 portable actor whose `gateways` is empty or has
773
+ * an item that is not an HTTP(S) origin, which FEP-ef61 does not allow.
774
+ * Every item is checked, since the list and its URLs can be mutated after
775
+ * the actor is constructed.
776
+ */
777
+ function warnPortableActorGateways(actorId, gateways) {
778
+ if (gateways.length > 0 && gateways.every(isGatewayUrl)) return;
779
+ getLogger([
780
+ "fedify",
781
+ "federation",
782
+ "actor"
783
+ ]).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.", {
784
+ actorId: actorId.href,
785
+ gateways: gateways.map((g) => g.href)
786
+ });
787
+ }
788
+ /**
771
789
  * Warns about an FEP-ef61 portable actor identified by a compatible identifier
772
790
  * that is malformed, or is not on the actor's first gateway, where FEP-ef61
773
- * requires publishers to construct compatible identifiers.
791
+ * requires publishers to construct compatible identifiers. A missing or
792
+ * invalid first gateway is reported by {@link warnPortableActorGateways}
793
+ * instead.
774
794
  */
775
795
  function warnCompatibleActorId(actorId, gateway) {
776
796
  const logger = getLogger([
@@ -788,8 +808,8 @@ function warnCompatibleActorId(actorId, gateway) {
788
808
  });
789
809
  return;
790
810
  }
791
- if (gateway == null || !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 });
792
- 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.", {
811
+ if (gateway == null || !isGatewayUrl(gateway)) return;
812
+ 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.", {
793
813
  actorId: actorId.href,
794
814
  gateway: gateway.origin
795
815
  });
@@ -5,7 +5,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
7
7
  import { t as assert } from "../assert-D1Eafmd_.mjs";
8
- import { E as autoIdAssigner, T as actorDehydrator, n as FederationImpl } from "../middleware-Bdu2-OPD.mjs";
8
+ import { E as autoIdAssigner, T as actorDehydrator, n as FederationImpl } from "../middleware-BqqycC0P.mjs";
9
9
  import { Follow, Person } from "@fedify/vocab";
10
10
  import { test } from "@fedify/fixture";
11
11
  //#region src/compat/transformers.test.ts
@@ -3,8 +3,8 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { a as getRawCanonicalPortableId, l as isPortableId, n as getCanonicalPortableId } from "./portable-key-id-Ca30-hOa.mjs";
5
5
  import { n as preloadedOnlyDocumentLoader } from "./public-audience--klBIOk1.mjs";
6
- import { c as getNormalizationContextLoader } from "./ld-oQj6j_hP.mjs";
7
- import { l as verifyPortableObjectProofPolicy, n as classifyFep2277CoreType, o as verifyMapLocalProof } from "./proof-C9115DX_.mjs";
6
+ import { c as getNormalizationContextLoader } from "./ld-C15yzuY6.mjs";
7
+ import { l as verifyPortableObjectProofPolicy, n as classifyFep2277CoreType, o as verifyMapLocalProof } from "./proof-DrJWKeOl.mjs";
8
8
  import { parseIri, preloadedContexts } from "@fedify/vocab-runtime";
9
9
  import jsonld from "@fedify/vocab-runtime/jsonld";
10
10
  //#region src/sig/compound-proof.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.4.0-dev.2190+be3a8be0";
6
+ var version = "2.4.0-dev.2193+402149b5";
7
7
  //#endregion
8
8
  export { version as n, name as t };
@@ -1,8 +1,8 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { c as validateCryptoKey } from "./key-DyXf88bq.mjs";
5
- import { n as doubleKnock } from "./http-Y1ObT1A8.mjs";
4
+ import { c as validateCryptoKey } from "./key-DA3Yx8p2.mjs";
5
+ import { n as doubleKnock } from "./http-DQf9Mw4V.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { curry } from "es-toolkit";
8
8
  import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, resolveDocumentLoaderTimeout, validatePublicUrl, withDocumentLoaderTimeout } from "@fedify/vocab-runtime";
@@ -6,7 +6,7 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import { t as assertExists } from "../assert_exists-cffSpJ7X.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
- import { r as createFederationBuilder } from "../builder-CFF0YNTp.mjs";
9
+ import { r as createFederationBuilder } from "../builder-0onlMY4u.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";
@@ -6,11 +6,11 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
8
  import { t as assert } from "../assert-D1Eafmd_.mjs";
9
- import { n as exportJwk } from "../key-DyXf88bq.mjs";
9
+ import { n as exportJwk } from "../key-DA3Yx8p2.mjs";
10
10
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
11
- import { a as signObject, d as verifyProof } from "../proof-C9115DX_.mjs";
11
+ import { a as signObject, d as verifyProof } from "../proof-DrJWKeOl.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
13
- import { n as FederationImpl } from "../middleware-Bdu2-OPD.mjs";
13
+ import { n as FederationImpl } from "../middleware-BqqycC0P.mjs";
14
14
  import { Create, DataIntegrityProof, Note } from "@fedify/vocab";
15
15
  import { mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
@@ -5,10 +5,10 @@ import { r as createRequestContext, t as createInboxContext } from "../context-B
5
5
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
- import { a as compactJsonLd, m as verifyCompactJsonLd, p as signJsonLd } from "../ld-oQj6j_hP.mjs";
9
- import { l as signRequest } from "../http-Y1ObT1A8.mjs";
8
+ import { a as compactJsonLd, m as verifyCompactJsonLd, p as signJsonLd } from "../ld-C15yzuY6.mjs";
9
+ import { l as signRequest } from "../http-DQf9Mw4V.mjs";
10
10
  import { a as rsaPrivateKey3, c as rsaPublicKey3, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
11
- import { f as handleInbox, o as createFederation } from "../middleware-Bdu2-OPD.mjs";
11
+ import { f as handleInbox, o as createFederation } from "../middleware-BqqycC0P.mjs";
12
12
  import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
13
13
  import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
14
14
  import { Create, CryptographicKey, Multikey, Person, Update } from "@fedify/vocab";
@@ -331,5 +331,54 @@ test("handleInbox() accepts portable actors with keys at ap: URIs", async () =>
331
331
  const dispatched = { count: 0 };
332
332
  assertEquals([(await handle(await update("ap://did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK/actor"), dispatched)).status, dispatched.count], [401, 0]);
333
333
  });
334
+ test("handleInbox() rejects embedded portable actors without valid gateways", async () => {
335
+ const did = await exportDidKey(ed25519PublicKey.publicKey);
336
+ const verificationMethod = `${did}#${did.slice(8)}`;
337
+ const privateJwk = await crypto.subtle.exportKey("jwk", ed25519PrivateKey);
338
+ const actorId = `ap://${did}/actor`;
339
+ const update = async (gateways) => await secureDocument({
340
+ "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"],
341
+ id: `ap://${did}/activities/update`,
342
+ type: "Update",
343
+ actor: actorId,
344
+ object: await secureDocument({
345
+ "@context": [
346
+ "https://www.w3.org/ns/activitystreams",
347
+ "https://w3id.org/security/data-integrity/v1",
348
+ "https://w3id.org/fep/ef61"
349
+ ],
350
+ id: actorId,
351
+ type: "Person",
352
+ inbox: `${actorId}/inbox`,
353
+ outbox: `${actorId}/outbox`,
354
+ ...gateways
355
+ }, privateJwk, verificationMethod)
356
+ }, privateJwk, verificationMethod);
357
+ for (const [gateways, status, count] of [
358
+ [
359
+ { gateways: ["https://gw.example"] },
360
+ 202,
361
+ 1
362
+ ],
363
+ [
364
+ {},
365
+ 401,
366
+ 0
367
+ ],
368
+ [
369
+ { gateways: [] },
370
+ 401,
371
+ 0
372
+ ],
373
+ [
374
+ { gateways: ["https://gw.example/path"] },
375
+ 400,
376
+ 0
377
+ ]
378
+ ]) {
379
+ const dispatched = { count: 0 };
380
+ assertEquals([(await handle(await update(gateways), dispatched)).status, dispatched.count], [status, count], JSON.stringify(gateways));
381
+ }
382
+ });
334
383
  //#endregion
335
384
  export {};
@@ -10,12 +10,12 @@ import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
11
11
  import { t as assert } from "../assert-D1Eafmd_.mjs";
12
12
  import { r as parseAcceptSignature } from "../accept-CPVqki78.mjs";
13
- import { o as generateCryptoKeyPair } from "../key-DyXf88bq.mjs";
14
- import { a as compactJsonLd, p as signJsonLd } from "../ld-oQj6j_hP.mjs";
15
- import { a as signObject } from "../proof-C9115DX_.mjs";
16
- import { l as signRequest } from "../http-Y1ObT1A8.mjs";
13
+ import { o as generateCryptoKeyPair } from "../key-DA3Yx8p2.mjs";
14
+ import { a as compactJsonLd, p as signJsonLd } from "../ld-C15yzuY6.mjs";
15
+ import { a as signObject } from "../proof-DrJWKeOl.mjs";
16
+ import { l as signRequest } from "../http-DQf9Mw4V.mjs";
17
17
  import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
18
- import { d as handleCustomCollection, f as handleInbox, g as respondWithObjectIfAcceptable, h as respondWithObject, l as handleActor, m as handleOutbox, o as createFederation, p as handleObject, u as handleCollection } from "../middleware-Bdu2-OPD.mjs";
18
+ import { d as handleCustomCollection, f as handleInbox, g as respondWithObjectIfAcceptable, h as respondWithObject, l as handleActor, m as handleOutbox, o as createFederation, p as handleObject, u as handleCollection } from "../middleware-BqqycC0P.mjs";
19
19
  import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
20
20
  import { Activity, Create, CryptographicKey, Multikey, Note, Person, Tombstone } from "@fedify/vocab";
21
21
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -10,8 +10,8 @@ import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
11
11
  import { t as assert } from "../assert-D1Eafmd_.mjs";
12
12
  import { r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
13
- import { o as createFederation, x as parseHashlinkGatewayRequest } from "../middleware-Bdu2-OPD.mjs";
14
- import { r as createFederationBuilder } from "../builder-CFF0YNTp.mjs";
13
+ import { o as createFederation, x as parseHashlinkGatewayRequest } from "../middleware-BqqycC0P.mjs";
14
+ import { r as createFederationBuilder } from "../builder-0onlMY4u.mjs";
15
15
  import { n as RouterError } from "../router-u5O5KCQr.mjs";
16
16
  import { Note } from "@fedify/vocab";
17
17
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -4,9 +4,9 @@ globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import "../std__assert-DvMDRPes.mjs";
7
- import { a as signObject } from "../proof-C9115DX_.mjs";
7
+ import { a as signObject } from "../proof-DrJWKeOl.mjs";
8
8
  import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
9
- import { o as createFederation } from "../middleware-Bdu2-OPD.mjs";
9
+ import { o as createFederation } from "../middleware-BqqycC0P.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-Z6IcEbWU.mjs";
5
5
  import "../std__assert-DvMDRPes.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-CTptdYck.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-zMe834ID.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-B1H23mlq.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";
@@ -16,14 +16,14 @@ import "../std__assert-DvMDRPes.mjs";
16
16
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
17
17
  import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
18
18
  import { t as assert } from "../assert-D1Eafmd_.mjs";
19
- import { g as recordInboxActivity } from "../metrics-zMe834ID.mjs";
20
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-oQj6j_hP.mjs";
21
- import { a as signObject, s as verifyObject } from "../proof-C9115DX_.mjs";
22
- import { f as verifyRequest, l as signRequest } from "../http-Y1ObT1A8.mjs";
19
+ import { g as recordInboxActivity } from "../metrics-B1H23mlq.mjs";
20
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-C15yzuY6.mjs";
21
+ import { a as signObject, s as verifyObject } from "../proof-DrJWKeOl.mjs";
22
+ import { f as verifyRequest, l as signRequest } from "../http-DQf9Mw4V.mjs";
23
23
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
24
- import { t as getAuthenticatedDocumentLoader } from "../docloader-u6zzOExF.mjs";
25
- import { S as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-Bdu2-OPD.mjs";
26
- import { t as doesActorOwnKey } from "../owner-Dem4fbwc.mjs";
24
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-DpWYYY6a.mjs";
25
+ import { S as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-BqqycC0P.mjs";
26
+ import { t as doesActorOwnKey } from "../owner-BVpZBM-V.mjs";
27
27
  import { t as CircuitBreaker } from "../circuit-breaker-XJ53md4S.mjs";
28
28
  import { t as TaskCodec } from "../codec-C6rTrpIp.mjs";
29
29
  import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-DW6YC_Pe.mjs";
@@ -4318,6 +4318,51 @@ test("FederationImpl.processQueuedTask()", async (t) => {
4318
4318
  assertEquals(errorCount, 1);
4319
4319
  assertEquals(queuedMessages, []);
4320
4320
  });
4321
+ await t.step("malformed FEP-ef61 gateways are permanent queued inbox parse errors", async () => {
4322
+ const queuedMessages = [];
4323
+ const queue = {
4324
+ enqueue(message, _options) {
4325
+ queuedMessages.push(message);
4326
+ return Promise.resolve();
4327
+ },
4328
+ listen(_handler, _options) {
4329
+ return Promise.resolve();
4330
+ }
4331
+ };
4332
+ const kv = new MemoryKvStore();
4333
+ let errorCount = 0;
4334
+ const federation = new FederationImpl({
4335
+ kv,
4336
+ queue
4337
+ });
4338
+ federation.setInboxListeners("/users/{identifier}/inbox", "/inbox").on(Create, () => {
4339
+ throw new Error("listener should not run");
4340
+ }).onError(() => {
4341
+ errorCount++;
4342
+ });
4343
+ await federation.processQueuedTask(void 0, {
4344
+ type: "inbox",
4345
+ id: crypto.randomUUID(),
4346
+ baseUrl: "https://example.com",
4347
+ activity: {
4348
+ "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/fep/ef61"],
4349
+ id: "https://remote.example/activities/invalid-gateway",
4350
+ type: "Create",
4351
+ actor: "https://remote.example/users/alice",
4352
+ object: {
4353
+ id: "https://remote.example/users/bob",
4354
+ type: "Person",
4355
+ gateways: ["https://gw.example/path"]
4356
+ }
4357
+ },
4358
+ started: (/* @__PURE__ */ new Date()).toISOString(),
4359
+ attempt: 0,
4360
+ identifier: null,
4361
+ traceContext: {}
4362
+ });
4363
+ assertEquals(errorCount, 1);
4364
+ assertEquals(queuedMessages, []);
4365
+ });
4321
4366
  await t.step("legacy raw LDS inbox messages with network-path context ids retry", async () => {
4322
4367
  const queue = {
4323
4368
  enqueue(message, _options) {
@@ -1,6 +1,6 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_federation = require("../federation-BSS2dUO7.cjs");
3
+ const require_federation = require("../federation-BsGo0EH2.cjs");
4
4
  exports.CircuitBreaker = require_federation.CircuitBreaker;
5
5
  exports.InProcessMessageQueue = require_federation.InProcessMessageQueue;
6
6
  exports.MemoryKvStore = require_federation.MemoryKvStore;
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as respondWithObjectIfAcceptable, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as respondWithObject, l as CircuitBreaker, n as handleWebFinger, o as SendActivityError, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-CaR2MRWY.js";
3
+ import { a as respondWithObjectIfAcceptable, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as respondWithObject, l as CircuitBreaker, n as handleWebFinger, o as SendActivityError, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-ClaUFaLb.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,12 +7,12 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
8
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { n as exportJwk } from "../key-DyXf88bq.mjs";
11
- import { s as detachSignature } from "../ld-oQj6j_hP.mjs";
12
- import { a as signObject } from "../proof-C9115DX_.mjs";
10
+ import { n as exportJwk } from "../key-DA3Yx8p2.mjs";
11
+ import { s as detachSignature } from "../ld-C15yzuY6.mjs";
12
+ import { a as signObject } from "../proof-DrJWKeOl.mjs";
13
13
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { c as assertPortableActorActivity, n as FederationImpl, o as createFederation } from "../middleware-Bdu2-OPD.mjs";
15
- import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-F2jjkrt0.mjs";
14
+ import { c as assertPortableActorActivity, n as FederationImpl, o as createFederation } from "../middleware-BqqycC0P.mjs";
15
+ import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-B-Fk6Slo.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
17
  import { Create, Note, Person } from "@fedify/vocab";
18
18
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -8,10 +8,10 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
9
9
  import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { a as signObject, c as verifyPortableObjectProof } from "../proof-C9115DX_.mjs";
12
- import { f as verifyRequest, l as signRequest } from "../http-Y1ObT1A8.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-DrJWKeOl.mjs";
12
+ import { f as verifyRequest, l as signRequest } from "../http-DQf9Mw4V.mjs";
13
13
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-Bdu2-OPD.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-BqqycC0P.mjs";
15
15
  import { n as RouterError } from "../router-u5O5KCQr.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
17
  import { Note, Person, Tombstone, lookupObject } from "@fedify/vocab";
@@ -7,10 +7,10 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { n as exportJwk } from "../key-DyXf88bq.mjs";
11
- import { c as verifyPortableObjectProof, s as verifyObject } from "../proof-C9115DX_.mjs";
10
+ import { n as exportJwk } from "../key-DA3Yx8p2.mjs";
11
+ import { c as verifyPortableObjectProof, s as verifyObject } from "../proof-DrJWKeOl.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
13
- import { n as FederationImpl } from "../middleware-Bdu2-OPD.mjs";
13
+ import { n as FederationImpl } from "../middleware-BqqycC0P.mjs";
14
14
  import { Create, DataIntegrityProof, Note, OrderedCollection, Person, traverseCollection } from "@fedify/vocab";
15
15
  import { mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { FetchError, encodeMultibase, exportDidKey } from "@fedify/vocab-runtime";
@@ -7,11 +7,11 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assert } from "../assert-D1Eafmd_.mjs";
10
- import { a as signObject } from "../proof-C9115DX_.mjs";
10
+ import { a as signObject } from "../proof-DrJWKeOl.mjs";
11
11
  import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
12
- import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-Bdu2-OPD.mjs";
13
- import { t as verifyPortableObject } from "../portable-collection-BL6aZlQ0.mjs";
14
- import { s as verifyServedPortableObjects } from "../compound-proof-F2jjkrt0.mjs";
12
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-BqqycC0P.mjs";
13
+ import { t as verifyPortableObject } from "../portable-collection-Dn2GdZdI.mjs";
14
+ import { s as verifyServedPortableObjects } from "../compound-proof-B-Fk6Slo.mjs";
15
15
  import { n as RouterError } from "../router-u5O5KCQr.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
17
  import { Create, Note, Object as Object$1, OrderedCollection, Person, Tombstone, lookupObject, traverseCollection } from "@fedify/vocab";
@@ -8,11 +8,11 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
10
10
  import { r as getVerifiedKeyOwnerEvidence } from "../key-owner-evidence-APB6NpSk.mjs";
11
- import { p as signJsonLd } from "../ld-oQj6j_hP.mjs";
12
- import { f as verifyRequest, l as signRequest, p as verifyRequestDetailed } from "../http-Y1ObT1A8.mjs";
11
+ import { p as signJsonLd } from "../ld-C15yzuY6.mjs";
12
+ import { f as verifyRequest, l as signRequest, p as verifyRequestDetailed } from "../http-DQf9Mw4V.mjs";
13
13
  import { a as rsaPrivateKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-Bdu2-OPD.mjs";
15
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-Dem4fbwc.mjs";
14
+ import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-BqqycC0P.mjs";
15
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-BVpZBM-V.mjs";
16
16
  import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
17
17
  import { t as KvKeyCache } from "../keycache-Da8A8mZa.mjs";
18
18
  import { Create, CryptographicKey, Person } from "@fedify/vocab";
@@ -8,11 +8,11 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
9
9
  import "../std__assert-DvMDRPes.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { p as signJsonLd } from "../ld-oQj6j_hP.mjs";
12
- import { a as signObject } from "../proof-C9115DX_.mjs";
13
- import { l as signRequest, p as verifyRequestDetailed } from "../http-Y1ObT1A8.mjs";
11
+ import { p as signJsonLd } from "../ld-C15yzuY6.mjs";
12
+ import { a as signObject } from "../proof-DrJWKeOl.mjs";
13
+ import { l as signRequest, p as verifyRequestDetailed } from "../http-DQf9Mw4V.mjs";
14
14
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
15
- import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-Bdu2-OPD.mjs";
15
+ import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-BqqycC0P.mjs";
16
16
  import { Create, CryptographicKey, Follow, Note, Person, Tombstone } from "@fedify/vocab";
17
17
  import { mockDocumentLoader, test } from "@fedify/fixture";
18
18
  import { exportDidKey, formatIri, parseIri } from "@fedify/vocab-runtime";
@@ -7,7 +7,7 @@ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
8
  import { t as assert } from "../assert-D1Eafmd_.mjs";
9
9
  import { r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
10
- import { o as createFederation } from "../middleware-Bdu2-OPD.mjs";
10
+ import { o as createFederation } from "../middleware-BqqycC0P.mjs";
11
11
  import { Note, Object as Object$1, Person } from "@fedify/vocab";
12
12
  import { test } from "@fedify/fixture";
13
13
  import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
@@ -6,9 +6,9 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
8
  import { t as assert } from "../assert-D1Eafmd_.mjs";
9
- import { a as signObject } from "../proof-C9115DX_.mjs";
9
+ import { a as signObject } from "../proof-DrJWKeOl.mjs";
10
10
  import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
11
- import { o as createFederation } from "../middleware-Bdu2-OPD.mjs";
11
+ import { o as createFederation } from "../middleware-BqqycC0P.mjs";
12
12
  import { Create, Note } from "@fedify/vocab";
13
13
  import { mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { exportDidKey, formatIri, parseIri, toCompatibleEf61Id } from "@fedify/vocab-runtime";
@@ -8,10 +8,10 @@ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
8
8
  import "../std__assert-DvMDRPes.mjs";
9
9
  import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
10
10
  import { t as assert } from "../assert-D1Eafmd_.mjs";
11
- import { a as signObject, c as verifyPortableObjectProof } from "../proof-C9115DX_.mjs";
12
- import { l as signRequest } from "../http-Y1ObT1A8.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-DrJWKeOl.mjs";
12
+ import { l as signRequest } from "../http-DQf9Mw4V.mjs";
13
13
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
14
- import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-Bdu2-OPD.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-BqqycC0P.mjs";
15
15
  import { configure, reset } from "@logtape/logtape";
16
16
  import { Collection, Create, Note, Object as Object$1, Person, Tombstone, lookupObject } from "@fedify/vocab";
17
17
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -215,6 +215,11 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
215
215
  object.id.pathname = "/objects/mutated-id";
216
216
  return object;
217
217
  },
218
+ "actor-without-gateways": () => sign(new Person({
219
+ id: parseIri(`ap+ef61://${did}/objects/actor-without-gateways`),
220
+ inbox: parseIri(`ap+ef61://${did}/objects/actor-without-gateways/inbox`),
221
+ outbox: parseIri(`ap+ef61://${did}/objects/actor-without-gateways/outbox`)
222
+ })),
218
223
  "unsigned-actor": () => Promise.resolve(new Person({
219
224
  id: parseIri(`ap+ef61://${did}/objects/unsigned-actor`),
220
225
  inbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/inbox`),
@@ -234,6 +239,7 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
234
239
  "activity": 200,
235
240
  "actor": 200,
236
241
  "mutated-id": 404,
242
+ "actor-without-gateways": 500,
237
243
  "unsigned-actor": 500
238
244
  })) await t.step(`${id} → ${status}`, async () => {
239
245
  const response = await federation.fetch(gatewayRequest(`/objects/${id}`), { contextData: void 0 });
@@ -716,9 +722,11 @@ test("Federation.fetch() serves compatible-ID actors", async (t) => {
716
722
  })).map((r) => r.properties.gateway), ["https://primary.example"]);
717
723
  });
718
724
  await t.step("warns if the actor has no gateways", async () => {
719
- assertEquals((await captureWarnings(async () => {
725
+ const records = await captureWarnings(async () => {
720
726
  assertEquals((await federation.fetch(new Request("https://example.com/users/nogateway", { headers: { Accept: ACCEPT } }), { contextData: void 0 })).status, 200);
721
- })).map((r) => r.properties.actorId), [gatewayUrl("/actors/nogateway")]);
727
+ });
728
+ assertEquals(records.map((r) => r.properties.actorId), [gatewayUrl("/actors/nogateway")]);
729
+ assert(String(records[0].rawMessage).includes("gateways property"));
722
730
  });
723
731
  await t.step("warns if the ID is a malformed compatible identifier", async () => {
724
732
  const records = await captureWarnings(async () => {
@@ -728,5 +736,41 @@ test("Federation.fetch() serves compatible-ID actors", async (t) => {
728
736
  assert(String(records[0].rawMessage).includes("malformed"));
729
737
  });
730
738
  });
739
+ test("Federation.fetch() warns about portable actors without valid gateways", async (t) => {
740
+ const federation = createTestFederation();
741
+ const actors = {
742
+ valid: (ctx) => new Person({
743
+ id: ctx.getPortableObjectUri(Person, { name: "valid" }, did),
744
+ gateways: [new URL("https://example.com"), new URL("https://other.example/")]
745
+ }),
746
+ empty: (ctx) => new Person({ id: ctx.getPortableObjectUri(Person, { name: "empty" }, did) }),
747
+ mutated: (ctx) => {
748
+ const actor = new Person({
749
+ id: ctx.getPortableObjectUri(Person, { name: "mutated" }, did),
750
+ gateways: [new URL("https://example.com"), new URL("https://other.example/")]
751
+ });
752
+ actor.gateways[1].pathname = "/gateway";
753
+ return actor;
754
+ },
755
+ https: (ctx) => new Person({ id: ctx.getActorUri("https") }),
756
+ tombstone: (ctx) => new Tombstone({ id: ctx.getPortableObjectUri(Person, { name: "tombstone" }, did) })
757
+ };
758
+ federation.setActorDispatcher("/users/{identifier}", (ctx, identifier) => actors[identifier]?.(ctx) ?? null);
759
+ federation.setObjectDispatcher(Person, "/actors/{name}", () => null);
760
+ const expected = {
761
+ valid: [],
762
+ empty: [`ap+ef61://${did}/actors/empty`],
763
+ mutated: [`ap+ef61://${did}/actors/mutated`],
764
+ https: [],
765
+ tombstone: []
766
+ };
767
+ for (const [identifier, actorIds] of globalThis.Object.entries(expected)) await t.step(identifier, async () => {
768
+ const actorRecords = (await captureWarnings(async () => {
769
+ await federation.fetch(new Request(`https://example.com/users/${identifier}`, { headers: { Accept: ACCEPT } }), { contextData: void 0 });
770
+ })).filter((r) => r.category.join(".") === "fedify.federation.actor");
771
+ assertEquals(actorRecords.map((r) => r.properties.actorId), actorIds.map((id) => parseIri(id).href));
772
+ for (const record of actorRecords) assert(String(record.rawMessage).includes("gateways property"));
773
+ });
774
+ });
731
775
  //#endregion
732
776
  export {};
@@ -10,10 +10,10 @@ import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
10
10
  import "../std__assert-DvMDRPes.mjs";
11
11
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
12
12
  import { t as assert } from "../assert-D1Eafmd_.mjs";
13
- import { f as verifyRequest } from "../http-Y1ObT1A8.mjs";
13
+ import { f as verifyRequest } from "../http-DQf9Mw4V.mjs";
14
14
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
15
- import { t as doesActorOwnKey } from "../owner-Dem4fbwc.mjs";
16
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-D0hxFFRB.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-BVpZBM-V.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CT3a-0Vd.mjs";
17
17
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
18
18
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
19
19
  import { FetchError, UrlError } from "@fedify/vocab-runtime";
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
5
  import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-IG3pHfvZ.mjs";
6
6
  import "../../testing-C1itIjqW.mjs";
7
- import { o as createFederation } from "../../middleware-Bdu2-OPD.mjs";
7
+ import { o as createFederation } from "../../middleware-BqqycC0P.mjs";
8
8
  import { n as ParallelMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
9
9
  import { configure, reset } from "@logtape/logtape";
10
10
  import { delay } from "es-toolkit";
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
4
4
  import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
5
  import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-IG3pHfvZ.mjs";
6
6
  import "../../testing-C1itIjqW.mjs";
7
- import { o as createFederation } from "../../middleware-Bdu2-OPD.mjs";
8
- import { r as createFederationBuilder } from "../../builder-CFF0YNTp.mjs";
7
+ import { o as createFederation } from "../../middleware-BqqycC0P.mjs";
8
+ import { r as createFederationBuilder } from "../../builder-0onlMY4u.mjs";
9
9
  import { t as TaskCodec } from "../../codec-C6rTrpIp.mjs";
10
10
  import { t as InProcessMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
11
11
  import { W3CTraceContextPropagator } from "@opentelemetry/core";