@fedify/fedify 2.4.0-dev.2103 → 2.4.0-dev.2108

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 (80) hide show
  1. package/dist/{builder-CHht75pX.mjs → builder-BRlYEsrV.mjs} +28 -4
  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-DKKH_Nr1.mjs → compound-proof-CHGINiJg.mjs} +2 -2
  6. package/dist/{context-CfJE_oQu.d.ts → context-B4F4kGJq.d.ts} +92 -10
  7. package/dist/{context-mDTxTw-S.d.cts → context-Cqx9M_zO.d.cts} +92 -10
  8. package/dist/{deno-CkjiYK_Z.mjs → deno-CC4RKEEp.mjs} +1 -1
  9. package/dist/{docloader-C1hAJnWc.mjs → docloader-D3_m98fe.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 +118 -5
  14. package/dist/federation/hashlink-media.test.mjs +2 -2
  15. package/dist/federation/idempotency.test.mjs +2 -2
  16. package/dist/federation/metrics.test.mjs +1 -1
  17. package/dist/federation/middleware.test.mjs +184 -7
  18. package/dist/federation/mod.cjs +1 -1
  19. package/dist/federation/mod.d.cts +3 -3
  20. package/dist/federation/mod.d.ts +3 -3
  21. package/dist/federation/mod.js +1 -1
  22. package/dist/federation/outgoing-proof.test.mjs +5 -5
  23. package/dist/federation/portable-actor.test.mjs +3 -3
  24. package/dist/federation/portable-gateway-keys.test.mjs +3 -3
  25. package/dist/federation/portable-inbox.test.mjs +4 -4
  26. package/dist/federation/portable.test.mjs +31 -4
  27. package/dist/federation/send.test.mjs +3 -3
  28. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  29. package/dist/federation/tasks/tasks.test.mjs +2 -2
  30. package/dist/federation/temporal.test.mjs +1 -1
  31. package/dist/federation/webfinger.test.mjs +1 -1
  32. package/dist/{federation-C1dL6SiT.cjs → federation-dqo6ZzgT.cjs} +48 -15
  33. package/dist/{http-Cala2Grs.cjs → http-B7wEqv49.cjs} +1 -1
  34. package/dist/{http-BU-8fUrz.mjs → http-CHEYA5fH.mjs} +4 -4
  35. package/dist/{http-tTlTeFa0.js → http-CaUBCHYJ.js} +1 -1
  36. package/dist/{key-I8gLBkcf.mjs → key-B8u1vdvF.mjs} +2 -2
  37. package/dist/{kv-cache-Bl5EBFrU.cjs → kv-cache-0pYMPrkL.cjs} +1 -1
  38. package/dist/{kv-cache-DJFoGRWQ.mjs → kv-cache-CTdvf_Iq.mjs} +1 -1
  39. package/dist/{kv-cache-CxQu_cd4.js → kv-cache-ibncHN1D.js} +1 -1
  40. package/dist/{ld-wiJbqJHa.mjs → ld-BTMJHEGV.mjs} +3 -3
  41. package/dist/{metrics-BCAa5-kE.mjs → metrics-CF1TEvdS.mjs} +1 -1
  42. package/dist/{middleware-FnITXhtz.mjs → middleware-B-rZ7oE-.mjs} +24 -15
  43. package/dist/{middleware-6p2dYEVA.mjs → middleware-DCMTJT3_.mjs} +1 -1
  44. package/dist/{middleware-B6IVTVL0.js → middleware-Dl-Y_ZlC.js} +40 -7
  45. package/dist/{mod-BYvPz_T0.d.ts → mod-4s_XgF17.d.ts} +1 -1
  46. package/dist/{mod-B3OzOobN.d.cts → mod-BuFmStNT.d.cts} +1 -1
  47. package/dist/mod.cjs +5 -5
  48. package/dist/mod.d.cts +4 -4
  49. package/dist/mod.d.ts +4 -4
  50. package/dist/mod.js +5 -5
  51. package/dist/nodeinfo/handler.test.mjs +1 -1
  52. package/dist/{owner-DCt8W_Cv.cjs → owner-CGnHPl4k.cjs} +1 -1
  53. package/dist/{owner-BJp47LxN.mjs → owner-CY--JSqO.mjs} +3 -3
  54. package/dist/{owner-j5yrbXS1.js → owner-M8dOKEl6.js} +1 -1
  55. package/dist/{portable-key-B5oKE_wZ.mjs → portable-key-C0-ghkgM.mjs} +1 -1
  56. package/dist/{proof-BE4T5zF6.mjs → proof-DDw0i9b1.mjs} +4 -4
  57. package/dist/{send-BFITuKHw.mjs → send-CU3sHGPt.mjs} +3 -3
  58. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  59. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  60. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  61. package/dist/sig/compound-proof.test.mjs +2 -2
  62. package/dist/sig/http.test.mjs +2 -2
  63. package/dist/sig/key.test.mjs +1 -1
  64. package/dist/sig/ld.test.mjs +2 -2
  65. package/dist/sig/mod.cjs +3 -3
  66. package/dist/sig/mod.js +3 -3
  67. package/dist/sig/owner.test.mjs +1 -1
  68. package/dist/sig/portable-collection.test.mjs +2 -2
  69. package/dist/sig/portable-key.test.mjs +3 -3
  70. package/dist/sig/proof.test.mjs +3 -3
  71. package/dist/{sig-CRTRoouH.cjs → sig-C2CORtvg.cjs} +2 -2
  72. package/dist/{sig-CJHdGk9w.js → sig-fycq7sOr.js} +2 -2
  73. package/dist/{temporal-CyDDbE4i.mjs → temporal-NHiSpGcW.mjs} +1 -1
  74. package/dist/testing/kv.test.mjs +1 -1
  75. package/dist/testing/mod.d.mts +91 -9
  76. package/dist/utils/docloader.test.mjs +2 -2
  77. package/dist/utils/kv-cache.test.mjs +1 -1
  78. package/dist/utils/mod.cjs +1 -1
  79. package/dist/utils/mod.js +1 -1
  80. package/package.json +7 -7
@@ -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 { a as generateCryptoKeyPair } from "../key-I8gLBkcf.mjs";
14
- import { a as compactJsonLd, p as signJsonLd } from "../ld-wiJbqJHa.mjs";
15
- import { i as signObject } from "../proof-BE4T5zF6.mjs";
16
- import { l as signRequest } from "../http-BU-8fUrz.mjs";
13
+ import { a as generateCryptoKeyPair } from "../key-B8u1vdvF.mjs";
14
+ import { a as compactJsonLd, p as signJsonLd } from "../ld-BTMJHEGV.mjs";
15
+ import { i as signObject } from "../proof-DDw0i9b1.mjs";
16
+ import { l as signRequest } from "../http-CHEYA5fH.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-FnITXhtz.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-B-rZ7oE-.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";
@@ -500,6 +500,119 @@ test("handleObject()", async () => {
500
500
  assertEquals(onNotFoundCalled, null);
501
501
  assertEquals(onUnauthorizedCalled, null);
502
502
  });
503
+ test("handleObject() with a tombstone", async () => {
504
+ const federation = createFederation({ kv: new MemoryKvStore() });
505
+ const url = new URL("https://example.com/users/someone/notes/123");
506
+ let context = createRequestContext({
507
+ federation,
508
+ data: void 0,
509
+ url,
510
+ request: new Request(url, { headers: { Accept: "application/activity+json" } })
511
+ });
512
+ const objectDispatcher = (_ctx, values) => {
513
+ if (values.id !== "123") return null;
514
+ return new Tombstone({
515
+ id: new URL(`https://example.com/users/${values.identifier}/notes/${values.id}`),
516
+ formerType: Note,
517
+ deleted: Temporal.Instant.from("2024-01-15T00:00:00Z")
518
+ });
519
+ };
520
+ let onNotFoundCalled = null;
521
+ const onNotFound = (request) => {
522
+ onNotFoundCalled = request;
523
+ return new Response("Not found", { status: 404 });
524
+ };
525
+ let onUnauthorizedCalled = null;
526
+ const onUnauthorized = (request) => {
527
+ onUnauthorizedCalled = request;
528
+ return new Response("Unauthorized", { status: 401 });
529
+ };
530
+ let response = await handleObject(context.request, {
531
+ context,
532
+ values: {
533
+ identifier: "someone",
534
+ id: "123"
535
+ },
536
+ objectDispatcher,
537
+ onNotFound,
538
+ onUnauthorized
539
+ });
540
+ assertEquals(response.status, 410);
541
+ assertEquals(response.headers.get("Content-Type"), "application/activity+json");
542
+ assertEquals(response.headers.get("Vary"), "Accept");
543
+ const body = await response.json();
544
+ assertEquals(body.id, "https://example.com/users/someone/notes/123");
545
+ assertEquals(body.type, "Tombstone");
546
+ assertEquals(body.formerType, "as:Note");
547
+ assertEquals(body.deleted, "2024-01-15T00:00:00Z");
548
+ assertEquals(onNotFoundCalled, null);
549
+ assertEquals(onUnauthorizedCalled, null);
550
+ response = await handleObject(context.request, {
551
+ context,
552
+ values: {
553
+ identifier: "someone",
554
+ id: "456"
555
+ },
556
+ objectDispatcher,
557
+ onNotFound,
558
+ onUnauthorized
559
+ });
560
+ assertEquals(response.status, 404);
561
+ assertEquals(onNotFoundCalled, context.request);
562
+ assertEquals(onUnauthorizedCalled, null);
563
+ onNotFoundCalled = null;
564
+ let authorized = false;
565
+ const authorizePredicate = () => authorized;
566
+ response = await handleObject(context.request, {
567
+ context,
568
+ values: {
569
+ identifier: "someone",
570
+ id: "123"
571
+ },
572
+ objectDispatcher,
573
+ authorizePredicate,
574
+ onNotFound,
575
+ onUnauthorized
576
+ });
577
+ assertEquals(response.status, 401);
578
+ assertEquals(onNotFoundCalled, null);
579
+ assertEquals(onUnauthorizedCalled, context.request);
580
+ onUnauthorizedCalled = null;
581
+ authorized = true;
582
+ response = await handleObject(context.request, {
583
+ context,
584
+ values: {
585
+ identifier: "someone",
586
+ id: "123"
587
+ },
588
+ objectDispatcher,
589
+ authorizePredicate,
590
+ onNotFound,
591
+ onUnauthorized
592
+ });
593
+ assertEquals(response.status, 410);
594
+ assertEquals(onUnauthorizedCalled, null);
595
+ context = createRequestContext({
596
+ ...context,
597
+ request: new Request(url, {
598
+ method: "HEAD",
599
+ headers: { Accept: "application/activity+json" }
600
+ })
601
+ });
602
+ response = await handleObject(context.request, {
603
+ context,
604
+ values: {
605
+ identifier: "someone",
606
+ id: "123"
607
+ },
608
+ objectDispatcher,
609
+ onNotFound,
610
+ onUnauthorized
611
+ });
612
+ assertEquals(response.status, 410);
613
+ assertEquals(response.headers.get("Content-Type"), "application/activity+json");
614
+ assertEquals(response.body, null);
615
+ });
503
616
  test("handleCollection()", async () => {
504
617
  let context = createRequestContext({
505
618
  federation: createFederation({ kv: new MemoryKvStore() }),
@@ -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-FnITXhtz.mjs";
14
- import { r as createFederationBuilder } from "../builder-CHht75pX.mjs";
13
+ import { o as createFederation, x as parseHashlinkGatewayRequest } from "../middleware-B-rZ7oE-.mjs";
14
+ import { r as createFederationBuilder } from "../builder-BRlYEsrV.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 { i as signObject } from "../proof-BE4T5zF6.mjs";
7
+ import { i as signObject } from "../proof-DDw0i9b1.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-FnITXhtz.mjs";
9
+ import { o as createFederation } from "../middleware-B-rZ7oE-.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-BCAa5-kE.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-CF1TEvdS.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-BCAa5-kE.mjs";
20
- import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-wiJbqJHa.mjs";
21
- import { i as signObject, o as verifyObject } from "../proof-BE4T5zF6.mjs";
22
- import { d as verifyRequest, l as signRequest } from "../http-BU-8fUrz.mjs";
19
+ import { g as recordInboxActivity } from "../metrics-CF1TEvdS.mjs";
20
+ import { a as compactJsonLd, h as verifyJsonLd, p as signJsonLd, s as detachSignature } from "../ld-BTMJHEGV.mjs";
21
+ import { i as signObject, o as verifyObject } from "../proof-DDw0i9b1.mjs";
22
+ import { d as verifyRequest, l as signRequest } from "../http-CHEYA5fH.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-C1hAJnWc.mjs";
25
- import { S as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-FnITXhtz.mjs";
26
- import { t as doesActorOwnKey } from "../owner-BJp47LxN.mjs";
24
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-D3_m98fe.mjs";
25
+ import { S as handleBenchmarkTrigger, i as KvSpecDeterminer, n as FederationImpl, o as createFederation, r as InboxContextImpl, t as ContextImpl } from "../middleware-B-rZ7oE-.mjs";
26
+ import { t as doesActorOwnKey } from "../owner-CY--JSqO.mjs";
27
27
  import { t as CircuitBreaker } from "../circuit-breaker-C5NqoLBJ.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";
@@ -7882,5 +7882,182 @@ test("Federation.fetch() bounds inbox bodies before dispatch", async () => {
7882
7882
  }), { contextData: void 0 })).status, 202);
7883
7883
  assert(dispatched);
7884
7884
  });
7885
+ function getRawMessage(record) {
7886
+ return typeof record.rawMessage === "string" ? record.rawMessage : record.rawMessage.join("");
7887
+ }
7888
+ test("Federation.fetch() serves tombstones of objects", async (t) => {
7889
+ const deleted = Temporal.Instant.from("2024-01-15T00:00:00Z");
7890
+ const federation = createFederation({
7891
+ kv: new MemoryKvStore(),
7892
+ documentLoaderFactory: () => mockDocumentLoader,
7893
+ contextLoaderFactory: () => mockDocumentLoader
7894
+ });
7895
+ federation.setObjectDispatcher(vocab.Note, "/users/{identifier}/notes/{id}", (ctx, values) => {
7896
+ if (values.id === "missing") return null;
7897
+ if (values.id === "deleted") return new vocab.Tombstone({
7898
+ id: ctx.getObjectUri(vocab.Note, values),
7899
+ formerType: vocab.Note,
7900
+ deleted
7901
+ });
7902
+ return new vocab.Note({
7903
+ id: ctx.getObjectUri(vocab.Note, values),
7904
+ content: "Hello"
7905
+ });
7906
+ });
7907
+ federation.setObjectDispatcher(vocab.Tombstone, "/tombstones/{id}", (ctx, values) => new vocab.Tombstone({ id: ctx.getObjectUri(vocab.Tombstone, values) }));
7908
+ federation.setObjectDispatcher(vocab.Object, "/objects/{id}", (ctx, values) => values.id === "deleted" ? new vocab.Tombstone({ id: ctx.getObjectUri(vocab.Object, values) }) : new vocab.Note({ id: ctx.getObjectUri(vocab.Object, values) }));
7909
+ function fetch(path, method = "GET") {
7910
+ return federation.fetch(new Request(`https://example.com${path}`, {
7911
+ method,
7912
+ headers: { Accept: "application/activity+json" }
7913
+ }), { contextData: void 0 });
7914
+ }
7915
+ await t.step("GET responds with 410 Gone and the tombstone", async () => {
7916
+ const response = await fetch("/users/john/notes/deleted");
7917
+ assertEquals(response.status, 410);
7918
+ assertEquals(response.headers.get("Content-Type"), "application/activity+json");
7919
+ const body = await response.json();
7920
+ assertEquals(body.id, "https://example.com/users/john/notes/deleted");
7921
+ assertEquals(body.type, "Tombstone");
7922
+ assertEquals(body.formerType, "as:Note");
7923
+ assertEquals(body.deleted, "2024-01-15T00:00:00Z");
7924
+ });
7925
+ await t.step("HEAD responds with 410 Gone without a body", async () => {
7926
+ const response = await fetch("/users/john/notes/deleted", "HEAD");
7927
+ assertEquals(response.status, 410);
7928
+ assertEquals(response.body, null);
7929
+ });
7930
+ await t.step("objects and null are served as before", async () => {
7931
+ const response = await fetch("/users/john/notes/123");
7932
+ assertEquals(response.status, 200);
7933
+ assertEquals((await response.json()).type, "Note");
7934
+ assertEquals((await fetch("/users/john/notes/missing")).status, 404);
7935
+ });
7936
+ await t.step("Tombstone and Object dispatchers respond with 410", async () => {
7937
+ assertEquals((await fetch("/tombstones/1")).status, 410);
7938
+ assertEquals((await fetch("/objects/deleted")).status, 410);
7939
+ assertEquals((await fetch("/objects/live")).status, 200);
7940
+ });
7941
+ await t.step("RequestContext.getObject()", async () => {
7942
+ const ctx = federation.createContext(new Request("https://example.com/"), void 0);
7943
+ const values = {
7944
+ identifier: "john",
7945
+ id: "deleted"
7946
+ };
7947
+ assertEquals(await ctx.getObject(vocab.Note, values), null);
7948
+ assertEquals(await ctx.getObject(vocab.Note, values, { tombstone: "suppress" }), null);
7949
+ assertEquals(await ctx.getObject(vocab.Note, values, {}), null);
7950
+ const tombstone = await ctx.getObject(vocab.Note, values, { tombstone: "passthrough" });
7951
+ assertInstanceOf(tombstone, vocab.Tombstone);
7952
+ assertEquals(tombstone.id, new URL("https://example.com/users/john/notes/deleted"));
7953
+ assertEquals(tombstone.deleted, deleted);
7954
+ assertInstanceOf(await ctx.getObject(vocab.Note, values, { tombstone: "passthrough" }), vocab.Tombstone);
7955
+ assertInstanceOf(await ctx.getObject(vocab.Note, {
7956
+ identifier: "john",
7957
+ id: "123"
7958
+ }), vocab.Note);
7959
+ assertEquals(await ctx.getObject(vocab.Note, {
7960
+ identifier: "john",
7961
+ id: "missing"
7962
+ }, { tombstone: "passthrough" }), null);
7963
+ assertInstanceOf(await ctx.getObject(vocab.Tombstone, { id: "1" }), vocab.Tombstone);
7964
+ assertInstanceOf(await ctx.getObject(vocab.Object, { id: "deleted" }, { tombstone: "suppress" }), vocab.Tombstone);
7965
+ });
7966
+ await t.step("authorization predicates can get the tombstone", async () => {
7967
+ await withLogtapeLock(async () => {
7968
+ const records = [];
7969
+ await reset();
7970
+ try {
7971
+ await configure({
7972
+ sinks: { buffer(record) {
7973
+ records.push(record);
7974
+ } },
7975
+ filters: {},
7976
+ loggers: [{
7977
+ category: ["fedify", "federation"],
7978
+ sinks: ["buffer"]
7979
+ }, {
7980
+ category: ["logtape", "meta"],
7981
+ sinks: []
7982
+ }]
7983
+ });
7984
+ const federation = createFederation({
7985
+ kv: new MemoryKvStore(),
7986
+ documentLoaderFactory: () => mockDocumentLoader,
7987
+ contextLoaderFactory: () => mockDocumentLoader
7988
+ });
7989
+ let dispatched = 0;
7990
+ federation.setObjectDispatcher(vocab.Note, "/notes/{id}", (ctx, values) => {
7991
+ dispatched++;
7992
+ return new vocab.Tombstone({ id: ctx.getObjectUri(vocab.Note, values) });
7993
+ }).authorize(async (ctx, values) => {
7994
+ return await ctx.getObject(vocab.Note, values, { tombstone: "passthrough" }) instanceof vocab.Tombstone;
7995
+ });
7996
+ assertEquals((await federation.fetch(new Request("https://example.com/notes/1", { headers: { Accept: "application/activity+json" } }), { contextData: void 0 })).status, 410);
7997
+ assertEquals(dispatched, 2);
7998
+ assert(records.some((record) => getRawMessage(record).startsWith("RequestContext.getObject(") && getRawMessage(record).includes("may cause an infinite loop")));
7999
+ } finally {
8000
+ await reset();
8001
+ }
8002
+ });
8003
+ });
8004
+ await t.step("warns about the id of a tombstone", async () => {
8005
+ await withLogtapeLock(async () => {
8006
+ const records = [];
8007
+ await reset();
8008
+ try {
8009
+ await configure({
8010
+ sinks: { buffer(record) {
8011
+ records.push(record);
8012
+ } },
8013
+ filters: {},
8014
+ loggers: [{
8015
+ category: [
8016
+ "fedify",
8017
+ "federation",
8018
+ "object"
8019
+ ],
8020
+ sinks: ["buffer"]
8021
+ }, {
8022
+ category: ["logtape", "meta"],
8023
+ sinks: []
8024
+ }]
8025
+ });
8026
+ const federation = createFederation({
8027
+ kv: new MemoryKvStore(),
8028
+ documentLoaderFactory: () => mockDocumentLoader,
8029
+ contextLoaderFactory: () => mockDocumentLoader
8030
+ });
8031
+ const ids = {
8032
+ "matching": new URL("https://example.com/notes/matching"),
8033
+ "missing": null,
8034
+ "mismatched": new URL("https://example.com/other/mismatched"),
8035
+ "ap": new URL("ap://did%3Akey%3Az6MkTest/notes/ap"),
8036
+ "ap-ef61": new URL("ap+ef61://did%3Akey%3Az6MkTest/notes/ap-ef61")
8037
+ };
8038
+ federation.setObjectDispatcher(vocab.Note, "/notes/{id}", (_ctx, { id }) => id === "live" ? new vocab.Note({ id: new URL("https://example.com/other/live") }) : new vocab.Tombstone({ id: ids[id] }));
8039
+ const warnings = async (id) => {
8040
+ records.length = 0;
8041
+ assertEquals((await federation.fetch(new Request(`https://example.com/notes/${id}`, { headers: { Accept: "application/activity+json" } }), { contextData: void 0 })).status, id === "live" ? 200 : 410);
8042
+ return records.filter((r) => r.level === "warning");
8043
+ };
8044
+ assertEquals(await warnings("matching"), []);
8045
+ const missing = await warnings("missing");
8046
+ assertEquals(missing.length, 1);
8047
+ assert(getRawMessage(missing[0]).includes("without an id property"));
8048
+ const mismatched = await warnings("mismatched");
8049
+ assertEquals(mismatched.length, 1);
8050
+ assert(getRawMessage(mismatched[0]).includes("does not match"));
8051
+ assertEquals(mismatched[0].properties.tombstoneId, "https://example.com/other/mismatched");
8052
+ assertEquals(mismatched[0].properties.objectUri, "https://example.com/notes/mismatched");
8053
+ assertEquals(await warnings("ap"), []);
8054
+ assertEquals(await warnings("ap-ef61"), []);
8055
+ assertEquals(await warnings("live"), []);
8056
+ } finally {
8057
+ await reset();
8058
+ }
8059
+ });
8060
+ });
8061
+ });
7885
8062
  //#endregion
7886
8063
  export {};
@@ -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-C1dL6SiT.cjs");
3
+ const require_federation = require("../federation-dqo6ZzgT.cjs");
4
4
  exports.CircuitBreaker = require_federation.CircuitBreaker;
5
5
  exports.InProcessMessageQueue = require_federation.InProcessMessageQueue;
6
6
  exports.MemoryKvStore = require_federation.MemoryKvStore;
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as InProcessMessageQueueOptions, A as ObjectCallbackSetters, At as InboxErrorHandler, B as TaskDefinition, Bt as PortableActorIdMapper, C as FederationOptions, Ct as CollectionCursor, D as InboxChallengePolicy, Dt as CustomCollectionDispatcher, E as IdempotencyStrategy, Et as CustomCollectionCursor, F as FederationOrigin, Ft as ObjectDispatcher, G as CreateExponentialBackoffPolicyOptions, Gt as SendActivityError, H as TaskEnqueueOptions, Ht as UnverifiedActivityHandler, I as FederationQueueOptions, It as OutboxErrorHandler, J as createExponentialBackoffPolicy, Jt as buildCollectionSynchronizationHeader, K as RetryContext, Kt as SenderKeyPair, L as createFederation, Lt as OutboxListener, M as PortableInboxForwardingOptions, Mt as MediaUploaderCallback, N as Rfc6570Expression, Nt as NodeInfoDispatcher, O as InboxListenerSetters, Ot as HashlinkMediaDispatcher, P as FederationKvPrefixes, Pt as ObjectAuthorizePredicate, Q as InProcessMessageQueue, R as Message, Rt as OutboxListenerErrorHandler, S as FederationFetchOptions, St as CollectionCounter, T as IdempotencyKeyCallback, Tt as CustomCollectionCounter, U as TaskHandler, Ut as UnverifiedActivityReason, V as TaskDefinitionOptions, Vt as SharedInboxKeyDispatcher, W as TaskRegistry, Wt as WebFingerLinksDispatcher, X as respondWithObject, Y as RespondWithObjectOptions, Yt as digest, Z as respondWithObjectIfAcceptable, _ as CustomCollectionCallbackSetters, _t as ActorAliasMapper, a as GetSignedKeyOptions, at as CircuitBreaker, b as FederationBenchmarkOptions, bt as ActorKeyPairsDispatcher, c as ParseUriResult, ct as CircuitBreakerCreateOptions, d as RouteActivityOptions, dt as CircuitBreakerOptions, et as MessageQueue, f as SendActivityOptions, ft as CircuitBreakerState, g as ConstructorWithTypeId, gt as parseCircuitBreakerKvState, h as CollectionCallbackSetters, ht as normalizeCircuitBreakerOptions, i as GetActorOptions, it as ParallelMessageQueue, j as OutboxListenerSetters, jt as InboxListener, k as MediaUploaderSetters, kt as HashlinkMediaRequest, l as PortableRequest, lt as CircuitBreakerFailurePolicy, m as ActorCallbackSetters, mt as NormalizedCircuitBreakerOptions, n as Context, nt as MessageQueueEnqueueOptions, o as InboxContext, ot as CircuitBreakerActivityDrop, p as SendActivityOptionsForCollection, pt as CircuitBreakerStateChange, q as RetryPolicy, qt as PageItems, r as ForwardActivityOptions, rt as MessageQueueListenOptions, s as OutboxContext, st as CircuitBreakerBeforeSendDecision, t as ActorKeyPair, tt as MessageQueueDepth, u as RequestContext, ut as CircuitBreakerKvState, v as Federatable, vt as ActorDispatcher, w as FederationStartQueueOptions, wt as CollectionDispatcher, x as FederationBuilder, xt as AuthorizePredicate, y as Federation, yt as ActorHandleMapper, z as createFederationBuilder, zt as OutboxPermanentFailureHandler } from "../context-mDTxTw-S.cjs";
2
+ import { $ as InProcessMessageQueue, A as MediaUploaderSetters, At as HashlinkMediaRequest, B as createFederationBuilder, Bt as OutboxPermanentFailureHandler, C as FederationFetchOptions, Ct as CollectionCounter, D as IdempotencyStrategy, Dt as CustomCollectionCursor, E as IdempotencyKeyCallback, Et as CustomCollectionCounter, F as FederationKvPrefixes, Ft as ObjectAuthorizePredicate, G as TaskRegistry, Gt as WebFingerLinksDispatcher, H as TaskDefinitionOptions, Ht as SharedInboxKeyDispatcher, I as FederationOrigin, It as ObjectDispatcher, J as RetryPolicy, Jt as PageItems, K as CreateExponentialBackoffPolicyOptions, Kt as SendActivityError, L as FederationQueueOptions, Lt as OutboxErrorHandler, M as OutboxListenerSetters, Mt as InboxListener, N as PortableInboxForwardingOptions, Nt as MediaUploaderCallback, O as InboxChallengePolicy, Ot as CustomCollectionDispatcher, P as Rfc6570Expression, Pt as NodeInfoDispatcher, Q as respondWithObjectIfAcceptable, R as createFederation, Rt as OutboxListener, S as FederationBuilder, St as AuthorizePredicate, T as FederationStartQueueOptions, Tt as CollectionDispatcher, U as TaskEnqueueOptions, Ut as UnverifiedActivityHandler, V as TaskDefinition, Vt as PortableActorIdMapper, W as TaskHandler, Wt as UnverifiedActivityReason, X as RespondWithObjectOptions, Xt as digest, Y as createExponentialBackoffPolicy, Yt as buildCollectionSynchronizationHeader, Z as respondWithObject, _ as ConstructorWithTypeId, _t as parseCircuitBreakerKvState, a as GetObjectOptions, at as ParallelMessageQueue, b as Federation, bt as ActorHandleMapper, c as OutboxContext, ct as CircuitBreakerBeforeSendDecision, d as RequestContext, dt as CircuitBreakerKvState, et as InProcessMessageQueueOptions, f as RouteActivityOptions, ft as CircuitBreakerOptions, g as CollectionCallbackSetters, gt as normalizeCircuitBreakerOptions, h as ActorCallbackSetters, ht as NormalizedCircuitBreakerOptions, i as GetActorOptions, it as MessageQueueListenOptions, j as ObjectCallbackSetters, jt as InboxErrorHandler, k as InboxListenerSetters, kt as HashlinkMediaDispatcher, l as ParseUriResult, lt as CircuitBreakerCreateOptions, m as SendActivityOptionsForCollection, mt as CircuitBreakerStateChange, n as Context, nt as MessageQueueDepth, o as GetSignedKeyOptions, ot as CircuitBreaker, p as SendActivityOptions, pt as CircuitBreakerState, q as RetryContext, qt as SenderKeyPair, r as ForwardActivityOptions, rt as MessageQueueEnqueueOptions, s as InboxContext, st as CircuitBreakerActivityDrop, t as ActorKeyPair, tt as MessageQueue, u as PortableRequest, ut as CircuitBreakerFailurePolicy, v as CustomCollectionCallbackSetters, vt as ActorAliasMapper, w as FederationOptions, wt as CollectionCursor, x as FederationBenchmarkOptions, xt as ActorKeyPairsDispatcher, y as Federatable, yt as ActorDispatcher, z as Message, zt as OutboxListenerErrorHandler } from "../context-Cqx9M_zO.cjs";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-BhNbN8Ed.cjs";
4
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-B3OzOobN.cjs";
5
- export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, HashlinkMediaDispatcher, HashlinkMediaRequest, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableActorIdMapper, PortableInboxForwardingOptions, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
4
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-BuFmStNT.cjs";
5
+ export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetObjectOptions, GetSignedKeyOptions, HashlinkMediaDispatcher, HashlinkMediaRequest, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableActorIdMapper, PortableInboxForwardingOptions, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as InProcessMessageQueueOptions, A as ObjectCallbackSetters, At as InboxErrorHandler, B as TaskDefinition, Bt as PortableActorIdMapper, C as FederationOptions, Ct as CollectionCursor, D as InboxChallengePolicy, Dt as CustomCollectionDispatcher, E as IdempotencyStrategy, Et as CustomCollectionCursor, F as FederationOrigin, Ft as ObjectDispatcher, G as CreateExponentialBackoffPolicyOptions, Gt as SendActivityError, H as TaskEnqueueOptions, Ht as UnverifiedActivityHandler, I as FederationQueueOptions, It as OutboxErrorHandler, J as createExponentialBackoffPolicy, Jt as buildCollectionSynchronizationHeader, K as RetryContext, Kt as SenderKeyPair, L as createFederation, Lt as OutboxListener, M as PortableInboxForwardingOptions, Mt as MediaUploaderCallback, N as Rfc6570Expression, Nt as NodeInfoDispatcher, O as InboxListenerSetters, Ot as HashlinkMediaDispatcher, P as FederationKvPrefixes, Pt as ObjectAuthorizePredicate, Q as InProcessMessageQueue, R as Message, Rt as OutboxListenerErrorHandler, S as FederationFetchOptions, St as CollectionCounter, T as IdempotencyKeyCallback, Tt as CustomCollectionCounter, U as TaskHandler, Ut as UnverifiedActivityReason, V as TaskDefinitionOptions, Vt as SharedInboxKeyDispatcher, W as TaskRegistry, Wt as WebFingerLinksDispatcher, X as respondWithObject, Y as RespondWithObjectOptions, Yt as digest, Z as respondWithObjectIfAcceptable, _ as CustomCollectionCallbackSetters, _t as ActorAliasMapper, a as GetSignedKeyOptions, at as CircuitBreaker, b as FederationBenchmarkOptions, bt as ActorKeyPairsDispatcher, c as ParseUriResult, ct as CircuitBreakerCreateOptions, d as RouteActivityOptions, dt as CircuitBreakerOptions, et as MessageQueue, f as SendActivityOptions, ft as CircuitBreakerState, g as ConstructorWithTypeId, gt as parseCircuitBreakerKvState, h as CollectionCallbackSetters, ht as normalizeCircuitBreakerOptions, i as GetActorOptions, it as ParallelMessageQueue, j as OutboxListenerSetters, jt as InboxListener, k as MediaUploaderSetters, kt as HashlinkMediaRequest, l as PortableRequest, lt as CircuitBreakerFailurePolicy, m as ActorCallbackSetters, mt as NormalizedCircuitBreakerOptions, n as Context, nt as MessageQueueEnqueueOptions, o as InboxContext, ot as CircuitBreakerActivityDrop, p as SendActivityOptionsForCollection, pt as CircuitBreakerStateChange, q as RetryPolicy, qt as PageItems, r as ForwardActivityOptions, rt as MessageQueueListenOptions, s as OutboxContext, st as CircuitBreakerBeforeSendDecision, t as ActorKeyPair, tt as MessageQueueDepth, u as RequestContext, ut as CircuitBreakerKvState, v as Federatable, vt as ActorDispatcher, w as FederationStartQueueOptions, wt as CollectionDispatcher, x as FederationBuilder, xt as AuthorizePredicate, y as Federation, yt as ActorHandleMapper, z as createFederationBuilder, zt as OutboxPermanentFailureHandler } from "../context-CfJE_oQu.js";
2
+ import { $ as InProcessMessageQueue, A as MediaUploaderSetters, At as HashlinkMediaRequest, B as createFederationBuilder, Bt as OutboxPermanentFailureHandler, C as FederationFetchOptions, Ct as CollectionCounter, D as IdempotencyStrategy, Dt as CustomCollectionCursor, E as IdempotencyKeyCallback, Et as CustomCollectionCounter, F as FederationKvPrefixes, Ft as ObjectAuthorizePredicate, G as TaskRegistry, Gt as WebFingerLinksDispatcher, H as TaskDefinitionOptions, Ht as SharedInboxKeyDispatcher, I as FederationOrigin, It as ObjectDispatcher, J as RetryPolicy, Jt as PageItems, K as CreateExponentialBackoffPolicyOptions, Kt as SendActivityError, L as FederationQueueOptions, Lt as OutboxErrorHandler, M as OutboxListenerSetters, Mt as InboxListener, N as PortableInboxForwardingOptions, Nt as MediaUploaderCallback, O as InboxChallengePolicy, Ot as CustomCollectionDispatcher, P as Rfc6570Expression, Pt as NodeInfoDispatcher, Q as respondWithObjectIfAcceptable, R as createFederation, Rt as OutboxListener, S as FederationBuilder, St as AuthorizePredicate, T as FederationStartQueueOptions, Tt as CollectionDispatcher, U as TaskEnqueueOptions, Ut as UnverifiedActivityHandler, V as TaskDefinition, Vt as PortableActorIdMapper, W as TaskHandler, Wt as UnverifiedActivityReason, X as RespondWithObjectOptions, Xt as digest, Y as createExponentialBackoffPolicy, Yt as buildCollectionSynchronizationHeader, Z as respondWithObject, _ as ConstructorWithTypeId, _t as parseCircuitBreakerKvState, a as GetObjectOptions, at as ParallelMessageQueue, b as Federation, bt as ActorHandleMapper, c as OutboxContext, ct as CircuitBreakerBeforeSendDecision, d as RequestContext, dt as CircuitBreakerKvState, et as InProcessMessageQueueOptions, f as RouteActivityOptions, ft as CircuitBreakerOptions, g as CollectionCallbackSetters, gt as normalizeCircuitBreakerOptions, h as ActorCallbackSetters, ht as NormalizedCircuitBreakerOptions, i as GetActorOptions, it as MessageQueueListenOptions, j as ObjectCallbackSetters, jt as InboxErrorHandler, k as InboxListenerSetters, kt as HashlinkMediaDispatcher, l as ParseUriResult, lt as CircuitBreakerCreateOptions, m as SendActivityOptionsForCollection, mt as CircuitBreakerStateChange, n as Context, nt as MessageQueueDepth, o as GetSignedKeyOptions, ot as CircuitBreaker, p as SendActivityOptions, pt as CircuitBreakerState, q as RetryContext, qt as SenderKeyPair, r as ForwardActivityOptions, rt as MessageQueueEnqueueOptions, s as InboxContext, st as CircuitBreakerActivityDrop, t as ActorKeyPair, tt as MessageQueue, u as PortableRequest, ut as CircuitBreakerFailurePolicy, v as CustomCollectionCallbackSetters, vt as ActorAliasMapper, w as FederationOptions, wt as CollectionCursor, x as FederationBenchmarkOptions, xt as ActorKeyPairsDispatcher, y as Federatable, yt as ActorDispatcher, z as Message, zt as OutboxListenerErrorHandler } from "../context-B4F4kGJq.js";
3
3
  import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "../kv-BhNbN8Ed.js";
4
- import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-BYvPz_T0.js";
5
- export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetSignedKeyOptions, HashlinkMediaDispatcher, HashlinkMediaRequest, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableActorIdMapper, PortableInboxForwardingOptions, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
4
+ import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "../mod-4s_XgF17.js";
5
+ export { ActorAliasMapper, ActorCallbackSetters, ActorDispatcher, ActorHandleMapper, ActorKeyPair, ActorKeyPairsDispatcher, AuthorizePredicate, CircuitBreaker, CircuitBreakerActivityDrop, CircuitBreakerBeforeSendDecision, CircuitBreakerCreateOptions, CircuitBreakerFailurePolicy, CircuitBreakerKvState, CircuitBreakerOptions, CircuitBreakerState, CircuitBreakerStateChange, CollectionCallbackSetters, CollectionCounter, CollectionCursor, CollectionDispatcher, ConstructorWithTypeId, Context, CreateExponentialBackoffPolicyOptions, CustomCollectionCallbackSetters, CustomCollectionCounter, CustomCollectionCursor, CustomCollectionDispatcher, Federatable, Federation, FederationBenchmarkOptions, FederationBuilder, FederationFetchOptions, FederationKvPrefixes, FederationOptions, FederationOrigin, FederationQueueOptions, FederationStartQueueOptions, ForwardActivityOptions, GetActorOptions, GetObjectOptions, GetSignedKeyOptions, HashlinkMediaDispatcher, HashlinkMediaRequest, IdempotencyKeyCallback, IdempotencyStrategy, InProcessMessageQueue, InProcessMessageQueueOptions, InboxChallengePolicy, InboxContext, InboxErrorHandler, InboxListener, InboxListenerSetters, KvKey, KvStore, KvStoreListEntry, KvStoreSetOptions, MediaUploaderCallback, MediaUploaderSetters, MemoryKvStore, Message, MessageQueue, MessageQueueDepth, MessageQueueEnqueueOptions, MessageQueueListenOptions, NodeInfoDispatcher, NormalizedCircuitBreakerOptions, ObjectAuthorizePredicate, ObjectCallbackSetters, ObjectDispatcher, OutboxContext, OutboxErrorHandler, OutboxListener, OutboxListenerErrorHandler, OutboxListenerSetters, OutboxPermanentFailureHandler, PageItems, ParallelMessageQueue, ParseUriResult, PortableActorIdMapper, PortableInboxForwardingOptions, PortableRequest, RequestContext, RespondWithObjectOptions, RetryContext, RetryPolicy, Rfc6570Expression, RouteActivityOptions, Router, RouterError, RouterOptions, RouterRouteResult, SendActivityError, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair, SharedInboxKeyDispatcher, TaskDefinition, TaskDefinitionOptions, TaskEnqueueOptions, TaskHandler, TaskRegistry, UnverifiedActivityHandler, UnverifiedActivityReason, WebFingerHandlerParameters, WebFingerLinksDispatcher, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, normalizeCircuitBreakerOptions, parseCircuitBreakerKvState, respondWithObject, respondWithObjectIfAcceptable };
@@ -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-B6IVTVL0.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-Dl-Y_ZlC.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 { t as exportJwk } from "../key-I8gLBkcf.mjs";
11
- import { s as detachSignature } from "../ld-wiJbqJHa.mjs";
12
- import { i as signObject } from "../proof-BE4T5zF6.mjs";
10
+ import { t as exportJwk } from "../key-B8u1vdvF.mjs";
11
+ import { s as detachSignature } from "../ld-BTMJHEGV.mjs";
12
+ import { i as signObject } from "../proof-DDw0i9b1.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-FnITXhtz.mjs";
15
- import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-DKKH_Nr1.mjs";
14
+ import { c as assertPortableActorActivity, n as FederationImpl, o as createFederation } from "../middleware-B-rZ7oE-.mjs";
15
+ import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-CHGINiJg.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 { i as signObject, s as verifyPortableObjectProof } from "../proof-BE4T5zF6.mjs";
12
- import { d as verifyRequest, l as signRequest } from "../http-BU-8fUrz.mjs";
11
+ import { i as signObject, s as verifyPortableObjectProof } from "../proof-DDw0i9b1.mjs";
12
+ import { d as verifyRequest, l as signRequest } from "../http-CHEYA5fH.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-FnITXhtz.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-B-rZ7oE-.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 MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
7
7
  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
- import { p as signJsonLd } from "../ld-wiJbqJHa.mjs";
11
- import { l as signRequest } from "../http-BU-8fUrz.mjs";
10
+ import { p as signJsonLd } from "../ld-BTMJHEGV.mjs";
11
+ import { l as signRequest } from "../http-CHEYA5fH.mjs";
12
12
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
13
- import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-FnITXhtz.mjs";
13
+ import { f as handleInbox, n as FederationImpl, o as createFederation } from "../middleware-B-rZ7oE-.mjs";
14
14
  import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
15
15
  import { t as KvKeyCache } from "../keycache-BUDHB5rY.mjs";
16
16
  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-wiJbqJHa.mjs";
12
- import { i as signObject } from "../proof-BE4T5zF6.mjs";
13
- import { f as verifyRequestDetailed, l as signRequest } from "../http-BU-8fUrz.mjs";
11
+ import { p as signJsonLd } from "../ld-BTMJHEGV.mjs";
12
+ import { i as signObject } from "../proof-DDw0i9b1.mjs";
13
+ import { f as verifyRequestDetailed, l as signRequest } from "../http-CHEYA5fH.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-FnITXhtz.mjs";
15
+ import { _ as coversDelivery, o as createFederation, v as forwardPortableInboxActivity, y as resolvePortableInboxForwardingOptions } from "../middleware-B-rZ7oE-.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";
@@ -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 { i as signObject, s as verifyPortableObjectProof } from "../proof-BE4T5zF6.mjs";
12
- import { l as signRequest } from "../http-BU-8fUrz.mjs";
11
+ import { i as signObject, s as verifyPortableObjectProof } from "../proof-DDw0i9b1.mjs";
12
+ import { l as signRequest } from "../http-CHEYA5fH.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-FnITXhtz.mjs";
14
+ import { b as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-B-rZ7oE-.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";
@@ -220,6 +220,18 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
220
220
  inbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/inbox`),
221
221
  outbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/outbox`),
222
222
  gateways: [new URL("https://example.com/")]
223
+ })),
224
+ "tombstone": () => sign(new Tombstone({
225
+ id: parseIri(`ap+ef61://${did}/objects/tombstone`),
226
+ formerType: Note
227
+ })),
228
+ "unsigned-tombstone": () => Promise.resolve(new Tombstone({
229
+ id: parseIri(`ap+ef61://${did}/objects/unsigned-tombstone`),
230
+ formerType: Note
231
+ })),
232
+ "mismatched-tombstone": () => sign(new Tombstone({
233
+ id: parseIri(`ap+ef61://${did}/objects/other`),
234
+ formerType: Note
223
235
  }))
224
236
  };
225
237
  federation.setObjectDispatcher(Object$1, "/objects/{id}", (_ctx, { id }) => objects[id]?.() ?? null);
@@ -234,7 +246,10 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
234
246
  "activity": 200,
235
247
  "actor": 200,
236
248
  "mutated-id": 404,
237
- "unsigned-actor": 500
249
+ "unsigned-actor": 500,
250
+ "tombstone": 200,
251
+ "unsigned-tombstone": 500,
252
+ "mismatched-tombstone": 404
238
253
  })) await t.step(`${id} → ${status}`, async () => {
239
254
  const response = await federation.fetch(gatewayRequest(`/objects/${id}`), { contextData: void 0 });
240
255
  assertEquals(response.status, status);
@@ -245,6 +260,18 @@ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects",
245
260
  assertEquals(response.status, 500);
246
261
  assertEquals(response.body, null);
247
262
  });
263
+ await t.step("serves a signed tombstone with its body", async () => {
264
+ const response = await federation.fetch(gatewayRequest("/objects/tombstone"), { contextData: void 0 });
265
+ assertEquals(response.status, 200);
266
+ const body = await response.json();
267
+ assertEquals(body.type, "Tombstone");
268
+ assertEquals(body.id, `ap+ef61://${did}/objects/tombstone`);
269
+ });
270
+ await t.step("responds to HEAD for a tombstone without a body", async () => {
271
+ const response = await federation.fetch(gatewayRequest("/objects/tombstone", { method: "HEAD" }), { contextData: void 0 });
272
+ assertEquals(response.status, 200);
273
+ assertEquals(response.body, null);
274
+ });
248
275
  });
249
276
  test("Federation.fetch() authorizes portable object requests", async (t) => {
250
277
  const federation = createTestFederation();
@@ -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 { d as verifyRequest } from "../http-BU-8fUrz.mjs";
13
+ import { d as verifyRequest } from "../http-CHEYA5fH.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-BJp47LxN.mjs";
16
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-BFITuKHw.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-CY--JSqO.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CU3sHGPt.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-dbCShlCb.mjs";
6
6
  import "../../testing-BWq1dCzx.mjs";
7
- import { o as createFederation } from "../../middleware-FnITXhtz.mjs";
7
+ import { o as createFederation } from "../../middleware-B-rZ7oE-.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";