@fedify/fedify 2.4.0-dev.2256 → 2.4.0-dev.2260

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 (105) hide show
  1. package/dist/{builder-DvSQqk2l.mjs → builder-BK8HfSUm.mjs} +8 -2
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{compound-proof-5bg_j_ye.mjs → compound-proof-D--HeIbV.mjs} +41 -4
  6. package/dist/{context-CtI307_A.d.ts → context-7NyiqIcg.d.ts} +111 -2
  7. package/dist/{context-B6X-t8gI.d.cts → context-tsYPJ2Ew.d.cts} +111 -2
  8. package/dist/{deno-AmcRMq5z.mjs → deno-DVP7DGJC.mjs} +1 -1
  9. package/dist/{docloader-CIP_SG39.mjs → docloader-Dv1JJl37.mjs} +2 -2
  10. package/dist/federation/builder.test.mjs +1 -1
  11. package/dist/federation/compound-fanout.test.mjs +3 -3
  12. package/dist/federation/handler-compound-proof.test.mjs +3 -3
  13. package/dist/federation/handler.test.mjs +76 -5
  14. package/dist/federation/hashlink-media.test.mjs +2 -2
  15. package/dist/federation/idempotency.test.mjs +2 -2
  16. package/dist/federation/inbox-report.test.d.mts +2 -0
  17. package/dist/federation/inbox-report.test.mjs +475 -0
  18. package/dist/federation/metrics.test.mjs +1 -1
  19. package/dist/federation/middleware.test.mjs +7 -7
  20. package/dist/federation/mod.cjs +1 -1
  21. package/dist/federation/mod.d.cts +4 -3
  22. package/dist/federation/mod.d.ts +4 -3
  23. package/dist/federation/mod.js +1 -1
  24. package/dist/federation/outgoing-proof.test.mjs +54 -10
  25. package/dist/federation/portable-actor.test.mjs +3 -3
  26. package/dist/federation/portable-chain.test.mjs +3 -3
  27. package/dist/federation/portable-collection.test.mjs +66 -4
  28. package/dist/federation/portable-delivery.test.mjs +2 -2
  29. package/dist/federation/portable-gateway-keys.test.mjs +4 -4
  30. package/dist/federation/portable-inbox.test.mjs +67 -6
  31. package/dist/federation/portable-parse-uri.test.mjs +1 -1
  32. package/dist/federation/portable-route-activity.test.mjs +2 -2
  33. package/dist/federation/portable.test.mjs +3 -3
  34. package/dist/federation/send.test.mjs +3 -3
  35. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  36. package/dist/federation/tasks/tasks.test.mjs +2 -2
  37. package/dist/federation/temporal.test.mjs +1 -1
  38. package/dist/federation/webfinger.test.mjs +1 -1
  39. package/dist/{federation-BDzIgqOd.cjs → federation-Bo5z395X.cjs} +552 -122
  40. package/dist/{http-1fZ83jj7.cjs → http-BIhWdDf5.cjs} +447 -110
  41. package/dist/{http-BGb3QioZ.js → http-DRMu1C2T.js} +430 -111
  42. package/dist/{http-DkqWu-sm.mjs → http-DvpuyDJB.mjs} +141 -98
  43. package/dist/{key-CEsu7oaD.mjs → key-B7N8mNoY.mjs} +30 -3
  44. package/dist/{http-BrwKINQn.d.cts → key-C1nv7_jD.d.ts} +638 -229
  45. package/dist/{http-DGx0KOws.d.ts → key-DYxuyd-s.d.cts} +638 -229
  46. package/dist/{kv-cache-CJS4mImS.mjs → kv-cache-D0kA0rml.mjs} +1 -1
  47. package/dist/{kv-cache-CGhEgt98.js → kv-cache-DZLpqhW9.js} +1 -1
  48. package/dist/{kv-cache-BEWuZSB4.cjs → kv-cache-mF8Zmjix.cjs} +1 -1
  49. package/dist/{ld-Cf4CPWN_.mjs → ld-BDMNyM2M.mjs} +40 -5
  50. package/dist/{metrics-CocsZP0E.mjs → metrics-BbBj-VZN.mjs} +2 -1
  51. package/dist/{middleware-Cne_jMZo.mjs → middleware-CE1X7-UM.mjs} +1 -1
  52. package/dist/{middleware-Dxn0E9ES.mjs → middleware-DAA7wDdS.mjs} +520 -131
  53. package/dist/{middleware-BfYke3YQ.js → middleware-DfUWPAa-.js} +552 -122
  54. package/dist/{mod-C7_2j7VT.d.cts → mod-BojP2Bw3.d.cts} +1 -1
  55. package/dist/{mod-BlLwewYe.d.ts → mod-CavhAgLw.d.cts} +5 -255
  56. package/dist/{mod-VHYh1lTK.d.cts → mod-CtpF2BU5.d.ts} +5 -255
  57. package/dist/{mod-B8MI1mpi.d.ts → mod-DEZXwV6J.d.ts} +1 -1
  58. package/dist/{mod-DFL6IxYQ.d.cts → mod-Dw-nPxQh.d.cts} +1 -1
  59. package/dist/{mod-BhTaDR5H.d.ts → mod-Xj5P4s4d.d.ts} +1 -1
  60. package/dist/mod.cjs +4 -4
  61. package/dist/mod.d.cts +7 -7
  62. package/dist/mod.d.ts +7 -7
  63. package/dist/mod.js +4 -4
  64. package/dist/nodeinfo/handler.test.mjs +1 -1
  65. package/dist/{owner-DSJ7nFgy.mjs → owner-CzUycuhd.mjs} +3 -3
  66. package/dist/{portable-collection-BuBV6xTo.js → portable-collection-COcJxZg_.js} +1 -1
  67. package/dist/{portable-collection-qskqXJrH.mjs → portable-collection-CTcNJiAa.mjs} +2 -2
  68. package/dist/{portable-collection-r-mHg1PV.cjs → portable-collection-cPMffcHJ.cjs} +1 -1
  69. package/dist/{portable-key-woGH_1nn.mjs → portable-key-B4QN3OzR.mjs} +1 -1
  70. package/dist/{proof-8WiH_-Gq.mjs → proof-nce4pf5S.mjs} +133 -16
  71. package/dist/{send-JKzZBgPU.mjs → send-4Idpe2z0.mjs} +3 -3
  72. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  73. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  74. package/dist/sig/compound-proof-verification.test.mjs +19 -2
  75. package/dist/sig/compound-proof.test.mjs +2 -2
  76. package/dist/sig/http.test.mjs +2 -2
  77. package/dist/sig/key.test.mjs +1 -1
  78. package/dist/sig/ld.test.mjs +2 -2
  79. package/dist/sig/mitra-receive-interop.test.mjs +4 -4
  80. package/dist/sig/mitra-send-interop.test.mjs +3 -3
  81. package/dist/sig/mod.cjs +2 -2
  82. package/dist/sig/mod.d.cts +2 -2
  83. package/dist/sig/mod.d.ts +2 -2
  84. package/dist/sig/mod.js +2 -2
  85. package/dist/sig/owner.test.mjs +1 -1
  86. package/dist/sig/portable-collection.test.mjs +1 -1
  87. package/dist/sig/portable-interop.test.mjs +3 -3
  88. package/dist/sig/portable-key.test.mjs +6 -6
  89. package/dist/sig/proof.test.mjs +76 -3
  90. package/dist/sig/tootik-request-interop.test.mjs +4 -4
  91. package/dist/sig/tootik-send-interop.test.mjs +3 -3
  92. package/dist/sig/verification.test.d.mts +2 -0
  93. package/dist/sig/verification.test.mjs +310 -0
  94. package/dist/{temporal-CT3fRaMH.mjs → temporal-BbjmPHYn.mjs} +1 -1
  95. package/dist/testing/kv.test.mjs +1 -1
  96. package/dist/testing/mod.d.mts +315 -28
  97. package/dist/utils/docloader.test.mjs +2 -2
  98. package/dist/utils/kv-cache.test.mjs +1 -1
  99. package/dist/utils/mod.cjs +1 -1
  100. package/dist/utils/mod.d.cts +1 -1
  101. package/dist/utils/mod.d.ts +1 -1
  102. package/dist/utils/mod.js +1 -1
  103. package/dist/verification-C3954hQh.mjs +5 -0
  104. package/dist/verification-Dpfcw8ml.mjs +105 -0
  105. package/package.json +7 -7
@@ -7,14 +7,14 @@ 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-CEsu7oaD.mjs";
11
- import { s as detachSignature } from "../ld-Cf4CPWN_.mjs";
12
- import { a as signObject } from "../proof-8WiH_-Gq.mjs";
10
+ import { n as exportJwk } from "../key-B7N8mNoY.mjs";
11
+ import { s as detachSignature } from "../ld-BDMNyM2M.mjs";
12
+ import { a as signObject } from "../proof-nce4pf5S.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 getEmbeddedFirstGateway, S as getCompactRootId, c as assertPortableActorActivity, n as FederationImpl, o as createFederation, w as warnCompatibleIdsInJson } from "../middleware-Dxn0E9ES.mjs";
15
- import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-5bg_j_ye.mjs";
14
+ import { C as getEmbeddedFirstGateway, S as getCompactRootId, c as assertPortableActorActivity, n as FederationImpl, o as createFederation, w as warnCompatibleIdsInJson } from "../middleware-DAA7wDdS.mjs";
15
+ import { o as verifyCompoundPortableObjectProofs } from "../compound-proof-D--HeIbV.mjs";
16
16
  import { configure, reset } from "@logtape/logtape";
17
- import { Announce, Create, Note, Person } from "@fedify/vocab";
17
+ import { Accept, Announce, Create, Follow, Note, Person } from "@fedify/vocab";
18
18
  import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
19
19
  import { mockDocumentLoader, test } from "@fedify/fixture";
20
20
  //#region src/federation/outgoing-proof.test.ts
@@ -298,6 +298,42 @@ test("a proof set on an embedded map is not delivered either", async () => {
298
298
  const { bodies } = await capture(() => assertRejects(() => ctx.sendActivity(rsaKey, recipient, httpCreate(child)), TypeError, "JSON Pointer \"/object/proof\""));
299
299
  assertEquals(bodies.length, 0);
300
300
  });
301
+ test("a received signed object rebuilt inside a portable activity is not delivered", async () => {
302
+ const followerKey = await didKey();
303
+ const signedFollow = await signObject(new Follow({
304
+ id: new URL("https://example.com/follows/1"),
305
+ actor: new URL("https://example.com/users/bob"),
306
+ object: parseIri("ap+ef61://did:key:z6Mkabc/actor")
307
+ }), followerKey.privateKey, new URL("https://example.com/users/bob#key"), {
308
+ ...options,
309
+ created
310
+ });
311
+ const follow = await Follow.fromJsonLd(await signedFollow.toJsonLd({
312
+ format: "compact",
313
+ ...options
314
+ }), options);
315
+ const owner = await didKey();
316
+ const accept = (object) => new Accept({
317
+ id: parseIri(`ap+ef61://${owner.did}/accepts/${crypto.randomUUID()}`),
318
+ actor: parseIri(`ap+ef61://${owner.did}/actor`),
319
+ object
320
+ });
321
+ const unsigned = accept(follow);
322
+ const presigned = await signObject(accept(follow), owner.privateKey, owner.keyId, {
323
+ ...options,
324
+ created
325
+ });
326
+ const cases = [[unsigned, [rsaKey, sender(owner)]], [presigned, [rsaKey]]];
327
+ for (const [activity, keys] of cases) {
328
+ assertEquals((await capture(() => assertRejects(() => createTestFederation().createContext(new URL("https://example.com/")).sendActivity(keys, recipient, activity), TypeError, "JSON Pointer \"/object\""))).bodies.length, 0);
329
+ const fanout = createQueue();
330
+ await assertRejects(() => createTestFederation(fanout.queue).createContext(new URL("https://example.com/")).sendActivity(keys, recipient, activity, { fanout: "force" }), TypeError, "JSON Pointer \"/object\"");
331
+ assertEquals(fanout.queued.length, 0);
332
+ }
333
+ const { bodies } = await capture(() => createTestFederation().createContext(new URL("https://example.com/")).sendActivity([rsaKey, sender(owner)], recipient, accept(follow.id)));
334
+ assertEquals(bodies.length, 1);
335
+ await assertCompoundVerifies(bodies[0]);
336
+ });
301
337
  test("forced fanout selects the DID-matching key before enqueueing", async () => {
302
338
  const owner = await didKey();
303
339
  const childOwner = await didKey();
@@ -327,9 +363,9 @@ test("forced fanout selects the DID-matching key before enqueueing", async () =>
327
363
  });
328
364
  test("the fanout worker selects one key for an unsigned portable activity", async () => {
329
365
  const owner = await didKey();
330
- const activity = portableCreate(owner, await signedChild(await didKey()));
366
+ const child = await signedChild(await didKey());
331
367
  const federation = createTestFederation();
332
- const message = {
368
+ const message = async (activity) => ({
333
369
  type: "fanout",
334
370
  id: crypto.randomUUID(),
335
371
  baseUrl: "https://example.com",
@@ -352,10 +388,18 @@ test("the fanout worker selects one key for an unsigned portable activity", asyn
352
388
  activityId: activity.id.href,
353
389
  activityType: "https://www.w3.org/ns/activitystreams#Create",
354
390
  traceContext: {}
355
- };
356
- const { bodies } = await capture(() => federation.processQueuedTask(void 0, message));
391
+ });
392
+ const byId = new Create({
393
+ id: parseIri(`ap+ef61://${owner.did}/activities/${crypto.randomUUID()}`),
394
+ actor: parseIri(`ap+ef61://${owner.did}/actor`),
395
+ object: child.id
396
+ });
397
+ const { bodies } = await capture(async () => federation.processQueuedTask(void 0, await message(byId)));
357
398
  assertEquals(bodies.length, 1);
358
399
  assertEquals(proofOf(bodies[0]).verificationMethod, owner.keyId.href);
400
+ await assertCompoundVerifies(bodies[0]);
401
+ const embedded = await message(portableCreate(owner, child));
402
+ assertEquals((await capture(() => assertRejects(() => federation.processQueuedTask(void 0, embedded), TypeError, "JSON Pointer \"/object\""))).bodies.length, 0);
359
403
  });
360
404
  test("actor key pairs follow the compound-proof key selection too", async () => {
361
405
  const dispatched = [];
@@ -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-8WiH_-Gq.mjs";
12
- import { f as verifyRequest, l as signRequest } from "../http-DkqWu-sm.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-nce4pf5S.mjs";
12
+ import { f as verifyRequest, l as signRequest } from "../http-DvpuyDJB.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-Dxn0E9ES.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DAA7wDdS.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-CEsu7oaD.mjs";
11
- import { c as verifyPortableObjectProof, s as verifyObject } from "../proof-8WiH_-Gq.mjs";
10
+ import { n as exportJwk } from "../key-B7N8mNoY.mjs";
11
+ import { c as verifyPortableObjectProof, s as verifyObject } from "../proof-nce4pf5S.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-Dxn0E9ES.mjs";
13
+ import { n as FederationImpl } from "../middleware-DAA7wDdS.mjs";
14
14
  import { Create, DataIntegrityProof, Note, OrderedCollection, Person, traverseCollection } from "@fedify/vocab";
15
15
  import { FetchError, encodeMultibase, exportDidKey } from "@fedify/vocab-runtime";
16
16
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -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-8WiH_-Gq.mjs";
10
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-nce4pf5S.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-Dxn0E9ES.mjs";
13
- import { t as verifyPortableObject } from "../portable-collection-qskqXJrH.mjs";
14
- import { s as verifyServedPortableObjects } from "../compound-proof-5bg_j_ye.mjs";
12
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DAA7wDdS.mjs";
13
+ import { t as verifyPortableObject } from "../portable-collection-CTcNJiAa.mjs";
14
+ import { c as verifyServedPortableObjects } from "../compound-proof-D--HeIbV.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, PUBLIC_COLLECTION, Person, Tombstone, lookupObject, traverseCollection } from "@fedify/vocab";
@@ -528,6 +528,68 @@ test("Fedify traverses portable collections that Fedify serves", async () => {
528
528
  assert(actor2 instanceof Person);
529
529
  assertEquals(await actor2.getOutbox(evilOptions), null);
530
530
  });
531
+ test("Fedify traverses portable collections through their owners' gateways", async () => {
532
+ const federation = createTestFederation();
533
+ const requests = [];
534
+ const documentLoader = async (url) => {
535
+ requests.push(url);
536
+ if (!/^https?:/.test(url)) throw new Error(`Not found: ${url}`);
537
+ const target = new URL(url);
538
+ const response = await federation.fetch(new Request(new URL(target.pathname + target.search, ORIGIN), { headers: { Accept: ACCEPT } }), { contextData: void 0 });
539
+ if (!response.ok) throw new FetchError(url, `HTTP ${response.status}`, response);
540
+ return {
541
+ contextUrl: null,
542
+ documentUrl: url,
543
+ document: await response.json()
544
+ };
545
+ };
546
+ const options = {
547
+ documentLoader,
548
+ contextLoader: mockDocumentLoader,
549
+ verifyPortableObject
550
+ };
551
+ const actor = await lookupObject(portableId("/users/alice"), {
552
+ ...options,
553
+ gateways: [ORIGIN]
554
+ });
555
+ assert(actor instanceof Person);
556
+ const outbox = await actor.getOutbox(options);
557
+ assert(outbox instanceof OrderedCollection);
558
+ assertEquals((await Array.fromAsync(traverseCollection(outbox, options))).length, PAGES.length * NOTES_PER_PAGE);
559
+ assert(requests.every((url) => url.startsWith(`${ORIGIN}/`)));
560
+ });
561
+ test("Fedify accepts empty portable collections that Fedify serves", async () => {
562
+ const federation = createTestFederation();
563
+ const [response, json] = await fetchJson(federation, gatewayUrl("/users/alice/inbox"));
564
+ assertEquals(response.status, 200);
565
+ assertEquals(json?.totalItems, 0);
566
+ assertEquals(await verifyPortableObjectProof(json, { contextLoader: mockDocumentLoader }), {
567
+ verified: false,
568
+ reason: { type: "unsecuredCollection" }
569
+ });
570
+ const documentLoader = async (url) => {
571
+ const target = new URL(url);
572
+ const response = await federation.fetch(new Request(new URL(target.pathname + target.search, ORIGIN), { headers: { Accept: ACCEPT } }), { contextData: void 0 });
573
+ if (!response.ok) throw new FetchError(url, `HTTP ${response.status}`, response);
574
+ return {
575
+ contextUrl: null,
576
+ documentUrl: url,
577
+ document: await response.json()
578
+ };
579
+ };
580
+ const options = {
581
+ documentLoader,
582
+ contextLoader: mockDocumentLoader,
583
+ gateways: [ORIGIN],
584
+ verifyPortableObject
585
+ };
586
+ const actor = await lookupObject(portableId("/users/alice"), options);
587
+ assert(actor instanceof Person);
588
+ const inbox = await actor.getInbox(options);
589
+ assert(inbox instanceof OrderedCollection);
590
+ assertEquals(inbox.totalItems, 0);
591
+ assertEquals(await Array.fromAsync(traverseCollection(inbox, options)), []);
592
+ });
531
593
  test("verifyServedPortableObjects() classifies unsigned maps under their effective contexts", async () => {
532
594
  const AS = "https://www.w3.org/ns/activitystreams";
533
595
  const collection = (member) => ({
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
4
4
  import { t as esm_default } from "../esm-BHXXx4Wx.mjs";
5
5
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { i as rsaPrivateKey2, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
7
- import { n as FederationImpl, r as InboxContextImpl } from "../middleware-Dxn0E9ES.mjs";
8
- import { n as extractInboxes, t as SendActivityError } from "../send-JKzZBgPU.mjs";
7
+ import { n as FederationImpl, r as InboxContextImpl } from "../middleware-DAA7wDdS.mjs";
8
+ import { n as extractInboxes, t as SendActivityError } from "../send-4Idpe2z0.mjs";
9
9
  import { Create, Endpoints, Note, Person } from "@fedify/vocab";
10
10
  import { parseIri } from "@fedify/vocab-runtime";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -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-Cf4CPWN_.mjs";
12
- import { f as verifyRequest, l as signRequest, p as verifyRequestDetailed } from "../http-DkqWu-sm.mjs";
11
+ import { p as signJsonLd } from "../ld-BDMNyM2M.mjs";
12
+ import { f as verifyRequest, l as signRequest, p as verifyRequestDetailed } from "../http-DvpuyDJB.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-Dxn0E9ES.mjs";
15
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-DSJ7nFgy.mjs";
14
+ import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-DAA7wDdS.mjs";
15
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CzUycuhd.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-Cf4CPWN_.mjs";
12
- import { a as signObject } from "../proof-8WiH_-Gq.mjs";
13
- import { l as signRequest, p as verifyRequestDetailed } from "../http-DkqWu-sm.mjs";
11
+ import { p as signJsonLd } from "../ld-BDMNyM2M.mjs";
12
+ import { a as signObject } from "../proof-nce4pf5S.mjs";
13
+ import { l as signRequest, p as verifyRequestDetailed } from "../http-DvpuyDJB.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-Dxn0E9ES.mjs";
15
+ import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-DAA7wDdS.mjs";
16
16
  import { Create, CryptographicKey, Follow, Note, Person, Tombstone } from "@fedify/vocab";
17
17
  import { exportDidKey, formatIri, parseIri } from "@fedify/vocab-runtime";
18
18
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -86,7 +86,10 @@ function setup({ gateways = [
86
86
  publicKey: rsaPublicKey2.publicKey
87
87
  }] : identifier === "alice" ? aliceKeyPairs : []);
88
88
  if (mapPortableActorId != null) actorCallbacks.mapPortableActorId((_ctx, identifier) => mapPortableActorId(identifier));
89
- const inboxListeners = federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
89
+ const reports = [];
90
+ const inboxListeners = federation.setInboxListeners("/users/{identifier}/inbox", "/inbox").onRequestFinished((_ctx, report) => {
91
+ reports.push(report);
92
+ });
90
93
  if (onSharedInboxKey != null) inboxListeners.setSharedKeyDispatcher(() => {
91
94
  onSharedInboxKey();
92
95
  return null;
@@ -107,7 +110,8 @@ function setup({ gateways = [
107
110
  federation,
108
111
  received,
109
112
  kv,
110
- queue
113
+ queue,
114
+ reports
111
115
  };
112
116
  }
113
117
  let activityCounter = 0;
@@ -194,6 +198,31 @@ test("Federation.fetch() refuses portable inbox deliveries it does not accept",
194
198
  assertEquals(accepting.received.length, 0);
195
199
  });
196
200
  });
201
+ test("onRequestFinished retains crypto success when a portable activity's DID mismatches", async () => {
202
+ const { federation, reports, received } = setup();
203
+ const signingKeyId = new URL(`${otherDid}#${otherDid.substring(8)}`);
204
+ const activity = await signObject(new Follow({
205
+ id: parseIri(`ap+ef61://${did}/follows/mismatched-report`),
206
+ actor: parseIri(`ap+ef61://${otherDid}/users/bob`),
207
+ object: parseIri(`ap+ef61://${did}/users/alice`)
208
+ }), otherKeyPair.privateKey, signingKeyId, { contextLoader: mockDocumentLoader });
209
+ assertEquals((await federation.fetch(post(inboxUrl(), await activity.toJsonLd({ contextLoader: mockDocumentLoader })), { contextData: void 0 })).status, 401);
210
+ assertEquals(received.length, 0);
211
+ assertEquals(reports.length, 1);
212
+ const report = reports[0];
213
+ assert(report.authentication.status === "rejected");
214
+ assert(report.authentication.reason.type === "proofPolicy");
215
+ assertEquals(report.authentication.reason.policy, "portableActivity");
216
+ assertEquals(report.authentication.reason.detail?.type, "verificationMethodMismatch");
217
+ assert(report.attempts.some((attempt) => attempt.mechanism === "objectIntegrity" && attempt.checks.some((check) => check.status === "verified")));
218
+ assert(report.attempts.some((attempt) => attempt.status === "rejected" && attempt.reason.type === "proofPolicy" && attempt.reason.reason.type === "verificationMethodMismatch"));
219
+ assertEquals(report.outcome, {
220
+ type: "response",
221
+ status: 401,
222
+ disposition: "rejected",
223
+ reason: "authentication"
224
+ });
225
+ });
197
226
  test("Federation.fetch() applies the proof policy to portable inbox deliveries", async (t) => {
198
227
  const queue = new RecordingQueue();
199
228
  const { federation, received } = setup({ queue });
@@ -1470,5 +1499,37 @@ test("Federation.fetch() keeps ordinary inbox deliveries unchanged", async () =>
1470
1499
  assertEquals(received.length, 1);
1471
1500
  assertEquals(queue.outbox.length, 0);
1472
1501
  });
1502
+ test("onRequestFinished covers portable ingress and recipient lookup failures", async () => {
1503
+ const { federation, reports } = setup({ options: { portableInboxForwarding: { maxTargets: 0 } } });
1504
+ assertEquals((await federation.fetch(post(inboxUrl(), await signedFollow()), { contextData: void 0 })).status, 202);
1505
+ assertEquals(reports.length, 1);
1506
+ assertEquals(reports[0].inbox, {
1507
+ kind: "portable",
1508
+ recipient: "alice"
1509
+ });
1510
+ assertEquals(reports[0].authentication.status, "verified");
1511
+ assert(reports[0].attempts.some((attempt) => attempt.subject.pointer === "" && attempt.status === "verified"));
1512
+ const absent = setup({ actor: () => null });
1513
+ assertEquals((await absent.federation.fetch(post(inboxUrl(), {}), { contextData: void 0 })).status, 404);
1514
+ assertEquals(absent.reports[0].payload, { status: "unavailable" });
1515
+ assertEquals(absent.reports[0].authentication, { status: "notDetermined" });
1516
+ const failure = /* @__PURE__ */ new Error("recipient lookup failed");
1517
+ const broken = setup({ actor: () => {
1518
+ throw failure;
1519
+ } });
1520
+ let thrown;
1521
+ try {
1522
+ await broken.federation.fetch(post(inboxUrl(), {}), { contextData: void 0 });
1523
+ } catch (error) {
1524
+ thrown = error;
1525
+ }
1526
+ assertEquals(thrown, failure);
1527
+ assertEquals(broken.reports.length, 1);
1528
+ assertEquals(broken.reports[0].outcome, {
1529
+ type: "exception",
1530
+ stage: "prepare",
1531
+ error: failure
1532
+ });
1533
+ });
1473
1534
  //#endregion
1474
1535
  export {};
@@ -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-Dxn0E9ES.mjs";
10
+ import { o as createFederation } from "../middleware-DAA7wDdS.mjs";
11
11
  import { Note, Object as Object$1, Person } from "@fedify/vocab";
12
12
  import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
13
13
  import { test } from "@fedify/fixture";
@@ -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-8WiH_-Gq.mjs";
9
+ import { a as signObject } from "../proof-nce4pf5S.mjs";
10
10
  import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
11
- import { o as createFederation } from "../middleware-Dxn0E9ES.mjs";
11
+ import { o as createFederation } from "../middleware-DAA7wDdS.mjs";
12
12
  import { Create, Note } from "@fedify/vocab";
13
13
  import { exportDidKey, formatIri, parseIri, toCompatibleEf61Id } from "@fedify/vocab-runtime";
14
14
  import { mockDocumentLoader, test } from "@fedify/fixture";
@@ -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-8WiH_-Gq.mjs";
12
- import { l as signRequest } from "../http-DkqWu-sm.mjs";
11
+ import { a as signObject, c as verifyPortableObjectProof } from "../proof-nce4pf5S.mjs";
12
+ import { l as signRequest } from "../http-DvpuyDJB.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-Dxn0E9ES.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-DAA7wDdS.mjs";
15
15
  import { configure, reset } from "@logtape/logtape";
16
16
  import { Collection, Create, Note, Object as Object$1, PUBLIC_COLLECTION, Person, Tombstone, lookupObject } from "@fedify/vocab";
17
17
  import { exportDidKey, formatIri, parseIri, toCompatibleEf61Id } from "@fedify/vocab-runtime";
@@ -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-DkqWu-sm.mjs";
13
+ import { f as verifyRequest } from "../http-DvpuyDJB.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-DSJ7nFgy.mjs";
16
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-JKzZBgPU.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-CzUycuhd.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-4Idpe2z0.mjs";
17
17
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
18
18
  import { FetchError, UrlError } from "@fedify/vocab-runtime";
19
19
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -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-t8xDeJZ5.mjs";
7
- import { o as createFederation } from "../../middleware-Dxn0E9ES.mjs";
7
+ import { o as createFederation } from "../../middleware-DAA7wDdS.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-t8xDeJZ5.mjs";
7
- import { o as createFederation } from "../../middleware-Dxn0E9ES.mjs";
8
- import { r as createFederationBuilder } from "../../builder-DvSQqk2l.mjs";
7
+ import { o as createFederation } from "../../middleware-DAA7wDdS.mjs";
8
+ import { r as createFederationBuilder } from "../../builder-BK8HfSUm.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";
@@ -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-CT3fRaMH.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-BbjmPHYn.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-Dxn0E9ES.mjs";
9
+ import { o as createFederation, s as handleWebFinger } from "../middleware-DAA7wDdS.mjs";
10
10
  import { Image, Link, Person, Tombstone } from "@fedify/vocab";
11
11
  import { parseIri } from "@fedify/vocab-runtime";
12
12
  import { createTestMeterProvider, test } from "@fedify/fixture";