@fedify/fedify 2.4.0-dev.2030 → 2.4.0-dev.2047

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 (75) hide show
  1. package/dist/{builder-BYJ5otJa.mjs → builder-Cue1kVHU.mjs} +12 -11
  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-BIvUoJxm.mjs → compound-proof-YT4tajyj.mjs} +1 -1
  6. package/dist/{context-uyRUWoZQ.d.ts → context-BJPHhBmD.d.ts} +100 -2
  7. package/dist/{context-BeDnDuF3.d.cts → context-Bh_mJfbD.d.cts} +100 -2
  8. package/dist/{context-CbS35fLr.mjs → context-DG5QeQ8W.mjs} +3 -1
  9. package/dist/{deno-Vj_9wePq.mjs → deno-Dcj6O4LJ.mjs} +1 -1
  10. package/dist/{docloader-qUudHZVH.mjs → docloader-BRlNjHlQ.mjs} +2 -2
  11. package/dist/federation/builder.test.mjs +1 -1
  12. package/dist/federation/compound-fanout.test.mjs +3 -3
  13. package/dist/federation/handler-compound-proof.test.mjs +4 -4
  14. package/dist/federation/handler.test.mjs +6 -6
  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 +8 -8
  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.test.d.mts +2 -0
  24. package/dist/federation/portable.test.mjs +430 -0
  25. package/dist/federation/send.test.mjs +3 -3
  26. package/dist/federation/tasks/enqueue.test.mjs +2 -2
  27. package/dist/federation/tasks/tasks.test.mjs +3 -3
  28. package/dist/federation/temporal.test.mjs +1 -1
  29. package/dist/federation/webfinger.test.mjs +115 -2
  30. package/dist/{federation-CTnaljmy.cjs → federation-Bdu06LEl.cjs} +324 -26
  31. package/dist/{http-By8tnmEr.js → http-BmdqHyms.js} +1 -1
  32. package/dist/{http-B5F1JMh0.cjs → http-CGjvl34X.cjs} +1 -1
  33. package/dist/{http-D4WPcJUe.mjs → http-CK6kjLnO.mjs} +3 -3
  34. package/dist/{key-B_Zc5Jbd.mjs → key-CzCAq6D9.mjs} +2 -2
  35. package/dist/{kv-cache-8K70pjtX.cjs → kv-cache-CvEicbrf.cjs} +1 -1
  36. package/dist/{kv-cache-BXdT7pJQ.mjs → kv-cache-YATuzCy-.mjs} +1 -1
  37. package/dist/{kv-cache-BswMKQjC.js → kv-cache-fi_-XZco.js} +1 -1
  38. package/dist/{ld-B16KUSIQ.mjs → ld-CNWm8mJc.mjs} +3 -3
  39. package/dist/{metrics-DpQqUAmh.mjs → metrics-CDoBPWjf.mjs} +1 -1
  40. package/dist/{middleware-BL5HFFVU.mjs → middleware-CF6uz8wa.mjs} +1 -1
  41. package/dist/{middleware-C7_hqDnl.mjs → middleware-CtFNjIUD.mjs} +326 -28
  42. package/dist/{middleware-Cxto6Bq2.js → middleware-Drzx-OID.js} +325 -27
  43. package/dist/{mod-D882_Xsg.d.ts → mod-BofpDIcU.d.ts} +1 -1
  44. package/dist/{mod-x9W0d0Pk.d.cts → mod-DU8aVzQJ.d.cts} +1 -1
  45. package/dist/mod.cjs +4 -4
  46. package/dist/mod.d.cts +4 -4
  47. package/dist/mod.d.ts +4 -4
  48. package/dist/mod.js +4 -4
  49. package/dist/nodeinfo/handler.test.mjs +2 -2
  50. package/dist/{owner-BIOIhZoM.mjs → owner-B3PgGiJ1.mjs} +2 -2
  51. package/dist/{owner-D-E0bT2O.js → owner-CMnmv7S9.js} +16 -3
  52. package/dist/{owner-WUYke16i.cjs → owner-Hurn_ocn.cjs} +16 -3
  53. package/dist/{proof-BVxJu5vv.mjs → proof-fKycdssC.mjs} +18 -5
  54. package/dist/{send-Cr5FJ7iu.mjs → send-BqBILxYE.mjs} +3 -3
  55. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  56. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  57. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  58. package/dist/sig/compound-proof.test.mjs +2 -2
  59. package/dist/sig/http.test.mjs +2 -2
  60. package/dist/sig/key.test.mjs +1 -1
  61. package/dist/sig/ld.test.mjs +2 -2
  62. package/dist/sig/mod.cjs +2 -2
  63. package/dist/sig/mod.js +2 -2
  64. package/dist/sig/owner.test.mjs +1 -1
  65. package/dist/sig/proof.test.mjs +208 -1
  66. package/dist/{temporal-CCf0lZV3.mjs → temporal-SUiLJ0Co.mjs} +1 -1
  67. package/dist/testing/kv.test.mjs +1 -1
  68. package/dist/testing/mod.d.mts +99 -1
  69. package/dist/testing/mod.mjs +2 -2
  70. package/dist/{testing-hbky2gMN.mjs → testing-By1YYsIK.mjs} +1 -1
  71. package/dist/utils/docloader.test.mjs +2 -2
  72. package/dist/utils/kv-cache.test.mjs +1 -1
  73. package/dist/utils/mod.cjs +1 -1
  74. package/dist/utils/mod.js +1 -1
  75. package/package.json +7 -7
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthorizePredicate, B as TaskEnqueueOptions, Bt as SendActivityError, C as FederationStartQueueOptions, Ct as CustomCollectionCounter, D as InboxListenerSetters, Dt as InboxListener, E as InboxChallengePolicy, Et as InboxErrorHandler, F as createFederation, Ft as OutboxPermanentFailureHandler, G as RetryPolicy, H as TaskRegistry, Ht as PageItems, I as Message, It as SharedInboxKeyDispatcher, J as respondWithObject, K as createExponentialBackoffPolicy, L as createFederationBuilder, Lt as UnverifiedActivityHandler, M as FederationKvPrefixes, Mt as OutboxErrorHandler, N as FederationOrigin, Nt as OutboxListener, O as MediaUploaderSetters, Ot as MediaUploaderCallback, P as FederationQueueOptions, Pt as OutboxListenerErrorHandler, Q as MessageQueue, R as TaskDefinition, Rt as UnverifiedActivityReason, S as FederationOptions, St as CollectionDispatcher, T as IdempotencyStrategy, Tt as CustomCollectionDispatcher, U as CreateExponentialBackoffPolicyOptions, Ut as buildCollectionSynchronizationHeader, V as TaskHandler, Vt as SenderKeyPair, W as RetryContext, Wt as digest, X as InProcessMessageQueue, Y as respondWithObjectIfAcceptable, Z as InProcessMessageQueueOptions, _ as Federatable, _t as ActorHandleMapper, a as GetSignedKeyOptions, at as CircuitBreakerBeforeSendDecision, b as FederationBuilder, bt as CollectionCounter, c as ParseUriResult, ct as CircuitBreakerKvState, d as SendActivityOptions, dt as CircuitBreakerStateChange, et as MessageQueueEnqueueOptions, f as SendActivityOptionsForCollection, ft as NormalizedCircuitBreakerOptions, g as CustomCollectionCallbackSetters, gt as ActorDispatcher, h as ConstructorWithTypeId, ht as ActorAliasMapper, i as GetActorOptions, it as CircuitBreakerActivityDrop, j as Rfc6570Expression, jt as ObjectDispatcher, k as ObjectCallbackSetters, kt as NodeInfoDispatcher, l as RequestContext, lt as CircuitBreakerOptions, m as CollectionCallbackSetters, mt as parseCircuitBreakerKvState, n as Context, nt as ParallelMessageQueue, o as InboxContext, ot as CircuitBreakerCreateOptions, p as ActorCallbackSetters, pt as normalizeCircuitBreakerOptions, q as RespondWithObjectOptions, r as ForwardActivityOptions, rt as CircuitBreaker, s as OutboxContext, st as CircuitBreakerFailurePolicy, t as ActorKeyPair, tt as MessageQueueListenOptions, u as RouteActivityOptions, ut as CircuitBreakerState, v as Federation, vt as ActorKeyPairsDispatcher, w as IdempotencyKeyCallback, wt as CustomCollectionCursor, x as FederationFetchOptions, xt as CollectionCursor, y as FederationBenchmarkOptions, yt as AuthorizePredicate, z as TaskDefinitionOptions, zt as WebFingerLinksDispatcher } from "../context-BeDnDuF3.cjs";
2
+ import { $ as MessageQueue, A as ObjectCallbackSetters, At as NodeInfoDispatcher, B as TaskDefinitionOptions, Bt as WebFingerLinksDispatcher, C as FederationOptions, Ct as CollectionDispatcher, D as InboxChallengePolicy, Dt as InboxErrorHandler, E as IdempotencyStrategy, Et as CustomCollectionDispatcher, F as FederationQueueOptions, Ft as OutboxListenerErrorHandler, G as RetryContext, Gt as digest, H as TaskHandler, Ht as SenderKeyPair, I as createFederation, It as OutboxPermanentFailureHandler, J as RespondWithObjectOptions, K as RetryPolicy, L as Message, Lt as SharedInboxKeyDispatcher, M as Rfc6570Expression, Mt as ObjectDispatcher, N as FederationKvPrefixes, Nt as OutboxErrorHandler, O as InboxListenerSetters, Ot as InboxListener, P as FederationOrigin, Pt as OutboxListener, Q as InProcessMessageQueueOptions, R as createFederationBuilder, Rt as UnverifiedActivityHandler, S as FederationFetchOptions, St as CollectionCursor, T as IdempotencyKeyCallback, Tt as CustomCollectionCursor, U as TaskRegistry, Ut as PageItems, V as TaskEnqueueOptions, Vt as SendActivityError, W as CreateExponentialBackoffPolicyOptions, Wt as buildCollectionSynchronizationHeader, X as respondWithObjectIfAcceptable, Y as respondWithObject, Z as InProcessMessageQueue, _ as CustomCollectionCallbackSetters, _t as ActorDispatcher, a as GetSignedKeyOptions, at as CircuitBreakerActivityDrop, b as FederationBenchmarkOptions, bt as AuthorizePredicate, c as ParseUriResult, ct as CircuitBreakerFailurePolicy, d as RouteActivityOptions, dt as CircuitBreakerState, et as MessageQueueDepth, f as SendActivityOptions, ft as CircuitBreakerStateChange, g as ConstructorWithTypeId, gt as ActorAliasMapper, h as CollectionCallbackSetters, ht as parseCircuitBreakerKvState, i as GetActorOptions, it as CircuitBreaker, j as OutboxListenerSetters, jt as ObjectAuthorizePredicate, k as MediaUploaderSetters, kt as MediaUploaderCallback, l as PortableRequest, lt as CircuitBreakerKvState, m as ActorCallbackSetters, mt as normalizeCircuitBreakerOptions, n as Context, nt as MessageQueueListenOptions, o as InboxContext, ot as CircuitBreakerBeforeSendDecision, p as SendActivityOptionsForCollection, pt as NormalizedCircuitBreakerOptions, q as createExponentialBackoffPolicy, r as ForwardActivityOptions, rt as ParallelMessageQueue, s as OutboxContext, st as CircuitBreakerCreateOptions, t as ActorKeyPair, tt as MessageQueueEnqueueOptions, u as RequestContext, ut as CircuitBreakerOptions, v as Federatable, vt as ActorHandleMapper, w as FederationStartQueueOptions, wt as CustomCollectionCounter, x as FederationBuilder, xt as CollectionCounter, y as Federation, yt as ActorKeyPairsDispatcher, z as TaskDefinition, zt as UnverifiedActivityReason } from "../context-Bh_mJfbD.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-x9W0d0Pk.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, 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, 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-DU8aVzQJ.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, 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, 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 MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthorizePredicate, B as TaskEnqueueOptions, Bt as SendActivityError, C as FederationStartQueueOptions, Ct as CustomCollectionCounter, D as InboxListenerSetters, Dt as InboxListener, E as InboxChallengePolicy, Et as InboxErrorHandler, F as createFederation, Ft as OutboxPermanentFailureHandler, G as RetryPolicy, H as TaskRegistry, Ht as PageItems, I as Message, It as SharedInboxKeyDispatcher, J as respondWithObject, K as createExponentialBackoffPolicy, L as createFederationBuilder, Lt as UnverifiedActivityHandler, M as FederationKvPrefixes, Mt as OutboxErrorHandler, N as FederationOrigin, Nt as OutboxListener, O as MediaUploaderSetters, Ot as MediaUploaderCallback, P as FederationQueueOptions, Pt as OutboxListenerErrorHandler, Q as MessageQueue, R as TaskDefinition, Rt as UnverifiedActivityReason, S as FederationOptions, St as CollectionDispatcher, T as IdempotencyStrategy, Tt as CustomCollectionDispatcher, U as CreateExponentialBackoffPolicyOptions, Ut as buildCollectionSynchronizationHeader, V as TaskHandler, Vt as SenderKeyPair, W as RetryContext, Wt as digest, X as InProcessMessageQueue, Y as respondWithObjectIfAcceptable, Z as InProcessMessageQueueOptions, _ as Federatable, _t as ActorHandleMapper, a as GetSignedKeyOptions, at as CircuitBreakerBeforeSendDecision, b as FederationBuilder, bt as CollectionCounter, c as ParseUriResult, ct as CircuitBreakerKvState, d as SendActivityOptions, dt as CircuitBreakerStateChange, et as MessageQueueEnqueueOptions, f as SendActivityOptionsForCollection, ft as NormalizedCircuitBreakerOptions, g as CustomCollectionCallbackSetters, gt as ActorDispatcher, h as ConstructorWithTypeId, ht as ActorAliasMapper, i as GetActorOptions, it as CircuitBreakerActivityDrop, j as Rfc6570Expression, jt as ObjectDispatcher, k as ObjectCallbackSetters, kt as NodeInfoDispatcher, l as RequestContext, lt as CircuitBreakerOptions, m as CollectionCallbackSetters, mt as parseCircuitBreakerKvState, n as Context, nt as ParallelMessageQueue, o as InboxContext, ot as CircuitBreakerCreateOptions, p as ActorCallbackSetters, pt as normalizeCircuitBreakerOptions, q as RespondWithObjectOptions, r as ForwardActivityOptions, rt as CircuitBreaker, s as OutboxContext, st as CircuitBreakerFailurePolicy, t as ActorKeyPair, tt as MessageQueueListenOptions, u as RouteActivityOptions, ut as CircuitBreakerState, v as Federation, vt as ActorKeyPairsDispatcher, w as IdempotencyKeyCallback, wt as CustomCollectionCursor, x as FederationFetchOptions, xt as CollectionCursor, y as FederationBenchmarkOptions, yt as AuthorizePredicate, z as TaskDefinitionOptions, zt as WebFingerLinksDispatcher } from "../context-uyRUWoZQ.js";
2
+ import { $ as MessageQueue, A as ObjectCallbackSetters, At as NodeInfoDispatcher, B as TaskDefinitionOptions, Bt as WebFingerLinksDispatcher, C as FederationOptions, Ct as CollectionDispatcher, D as InboxChallengePolicy, Dt as InboxErrorHandler, E as IdempotencyStrategy, Et as CustomCollectionDispatcher, F as FederationQueueOptions, Ft as OutboxListenerErrorHandler, G as RetryContext, Gt as digest, H as TaskHandler, Ht as SenderKeyPair, I as createFederation, It as OutboxPermanentFailureHandler, J as RespondWithObjectOptions, K as RetryPolicy, L as Message, Lt as SharedInboxKeyDispatcher, M as Rfc6570Expression, Mt as ObjectDispatcher, N as FederationKvPrefixes, Nt as OutboxErrorHandler, O as InboxListenerSetters, Ot as InboxListener, P as FederationOrigin, Pt as OutboxListener, Q as InProcessMessageQueueOptions, R as createFederationBuilder, Rt as UnverifiedActivityHandler, S as FederationFetchOptions, St as CollectionCursor, T as IdempotencyKeyCallback, Tt as CustomCollectionCursor, U as TaskRegistry, Ut as PageItems, V as TaskEnqueueOptions, Vt as SendActivityError, W as CreateExponentialBackoffPolicyOptions, Wt as buildCollectionSynchronizationHeader, X as respondWithObjectIfAcceptable, Y as respondWithObject, Z as InProcessMessageQueue, _ as CustomCollectionCallbackSetters, _t as ActorDispatcher, a as GetSignedKeyOptions, at as CircuitBreakerActivityDrop, b as FederationBenchmarkOptions, bt as AuthorizePredicate, c as ParseUriResult, ct as CircuitBreakerFailurePolicy, d as RouteActivityOptions, dt as CircuitBreakerState, et as MessageQueueDepth, f as SendActivityOptions, ft as CircuitBreakerStateChange, g as ConstructorWithTypeId, gt as ActorAliasMapper, h as CollectionCallbackSetters, ht as parseCircuitBreakerKvState, i as GetActorOptions, it as CircuitBreaker, j as OutboxListenerSetters, jt as ObjectAuthorizePredicate, k as MediaUploaderSetters, kt as MediaUploaderCallback, l as PortableRequest, lt as CircuitBreakerKvState, m as ActorCallbackSetters, mt as normalizeCircuitBreakerOptions, n as Context, nt as MessageQueueListenOptions, o as InboxContext, ot as CircuitBreakerBeforeSendDecision, p as SendActivityOptionsForCollection, pt as NormalizedCircuitBreakerOptions, q as createExponentialBackoffPolicy, r as ForwardActivityOptions, rt as ParallelMessageQueue, s as OutboxContext, st as CircuitBreakerCreateOptions, t as ActorKeyPair, tt as MessageQueueEnqueueOptions, u as RequestContext, ut as CircuitBreakerOptions, v as Federatable, vt as ActorHandleMapper, w as FederationStartQueueOptions, wt as CustomCollectionCounter, x as FederationBuilder, xt as CollectionCounter, y as Federation, yt as ActorKeyPairsDispatcher, z as TaskDefinition, zt as UnverifiedActivityReason } from "../context-BJPHhBmD.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-D882_Xsg.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, 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, 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-BofpDIcU.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, 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, 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 respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-Cxto6Bq2.js";
3
+ import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "../middleware-Drzx-OID.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-B_Zc5Jbd.mjs";
10
+ import { t as exportJwk } from "../key-CzCAq6D9.mjs";
11
11
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
12
- import { n as FederationImpl, o as createFederation } from "../middleware-C7_hqDnl.mjs";
13
- import { s as detachSignature } from "../ld-B16KUSIQ.mjs";
14
- import { r as signObject } from "../proof-BVxJu5vv.mjs";
15
- import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-BIvUoJxm.mjs";
12
+ import { n as FederationImpl, o as createFederation } from "../middleware-CtFNjIUD.mjs";
13
+ import { s as detachSignature } from "../ld-CNWm8mJc.mjs";
14
+ import { r as signObject } from "../proof-fKycdssC.mjs";
15
+ import { a as verifyCompoundPortableObjectProofs } from "../compound-proof-YT4tajyj.mjs";
16
16
  import { Create, Note, Person } from "@fedify/vocab";
17
17
  import { mockDocumentLoader, test } from "@fedify/fixture";
18
18
  import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
@@ -0,0 +1,2 @@
1
+ import { Temporal } from "temporal-polyfill";
2
+ import { URLPattern } from "urlpattern-polyfill";
@@ -0,0 +1,430 @@
1
+ import "temporal-polyfill";
2
+ import "urlpattern-polyfill";
3
+ globalThis.addEventListener = () => {};
4
+ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
+ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
+ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
7
+ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
8
+ import "../std__assert-DvMDRPes.mjs";
9
+ import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
10
+ import { s as signRequest } from "../http-CK6kjLnO.mjs";
11
+ import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
12
+ import { g as PORTABLE_OBJECT_CONTENT_TYPE, o as createFederation } from "../middleware-CtFNjIUD.mjs";
13
+ import { o as verifyPortableObjectProof, r as signObject } from "../proof-fKycdssC.mjs";
14
+ import { Collection, Create, Note, Object as Object$1, Person, Tombstone, lookupObject } from "@fedify/vocab";
15
+ import { mockDocumentLoader, test } from "@fedify/fixture";
16
+ import { exportDidKey, formatIri, parseIri } from "@fedify/vocab-runtime";
17
+ //#region src/federation/portable.test.ts
18
+ const did = await exportDidKey(ed25519PublicKey.publicKey);
19
+ const keyId = new URL(`${did}#${did.substring(8)}`);
20
+ const otherKeyPair = await crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"]);
21
+ const otherDid = await exportDidKey(otherKeyPair.publicKey);
22
+ const otherKeyId = new URL(`${otherDid}#${otherDid.substring(8)}`);
23
+ const ACCEPT = "application/activity+json";
24
+ function gatewayUrl(path, authority = did) {
25
+ return `https://example.com/.well-known/apgateway/${authority}${path}`;
26
+ }
27
+ function gatewayRequest(path, init = {}) {
28
+ const { authority, ...rest } = init;
29
+ return new Request(gatewayUrl(path, authority), {
30
+ ...rest,
31
+ headers: {
32
+ Accept: ACCEPT,
33
+ ...rest.headers
34
+ }
35
+ });
36
+ }
37
+ function createTestFederation() {
38
+ return createFederation({
39
+ kv: new MemoryKvStore(),
40
+ documentLoaderFactory: () => mockDocumentLoader,
41
+ contextLoaderFactory: () => mockDocumentLoader
42
+ });
43
+ }
44
+ async function sign(object, privateKey = ed25519PrivateKey, key = keyId) {
45
+ return await signObject(object, privateKey, key, { contextLoader: mockDocumentLoader });
46
+ }
47
+ async function signedNote(path, authority = did, content = "Hello") {
48
+ return await sign(new Note({
49
+ id: parseIri(`ap+ef61://${authority}${path}`),
50
+ attribution: parseIri(`ap+ef61://${authority}/actor`),
51
+ content
52
+ }));
53
+ }
54
+ test("Federation.fetch() serves portable objects through object dispatchers", async (t) => {
55
+ const federation = createTestFederation();
56
+ const calls = [];
57
+ federation.setObjectDispatcher(Note, "/users/{userId}/notes/{noteId}", async (ctx, values) => {
58
+ calls.push({
59
+ values,
60
+ portableRequest: ctx.portableRequest
61
+ });
62
+ if (values.noteId === "missing") return null;
63
+ if (values.noteId === "https") return new Note({
64
+ id: ctx.getObjectUri(Note, values),
65
+ content: "Not portable"
66
+ });
67
+ if (values.noteId === "ap") return await sign(new Note({
68
+ id: parseIri(`ap://${did}/users/${values.userId}/notes/ap`),
69
+ content: "Hello"
70
+ }));
71
+ if (values.noteId === "ignores-authority") return await signedNote(`/users/${values.userId}/notes/${values.noteId}`);
72
+ if (ctx.portableRequest?.authority !== did) return null;
73
+ return await sign(new Note({
74
+ id: ctx.getPortableObjectUri(Note, values),
75
+ attribution: parseIri(`ap+ef61://${did}/actor`),
76
+ content: `Note ${values.noteId} by ${values.userId}`
77
+ }));
78
+ });
79
+ federation.setActorDispatcher("/actors/{identifier}", (ctx, identifier) => new Person({ id: ctx.getActorUri(identifier) }));
80
+ await t.step("serves a portable object", async () => {
81
+ calls.length = 0;
82
+ const response = await federation.fetch(gatewayRequest("/users/alice/notes/123"), { contextData: void 0 });
83
+ assertEquals(response.status, 200);
84
+ assertEquals(response.headers.get("Content-Type"), PORTABLE_OBJECT_CONTENT_TYPE);
85
+ assertEquals(response.headers.get("Vary"), "Accept");
86
+ const json = await response.json();
87
+ assertEquals(json.id, `ap+ef61://${did}/users/alice/notes/123`);
88
+ assertEquals(json.content, "Note 123 by alice");
89
+ assertEquals((await verifyPortableObjectProof(json, { contextLoader: mockDocumentLoader })).verified, true);
90
+ assertEquals(calls.length, 1);
91
+ assertEquals(calls[0].values, {
92
+ userId: "alice",
93
+ noteId: "123"
94
+ });
95
+ assertEquals(calls[0].portableRequest?.authority, did);
96
+ assertEquals(formatIri(calls[0].portableRequest.id), `ap+ef61://${did}/users/alice/notes/123`);
97
+ });
98
+ await t.step("accepts a percent-encoded DID authority", async () => {
99
+ calls.length = 0;
100
+ assertEquals((await federation.fetch(gatewayRequest("/users/alice/notes/123", { authority: did.replaceAll(":", "%3A") }), { contextData: void 0 })).status, 200);
101
+ assertEquals(calls[0].portableRequest?.authority, did);
102
+ });
103
+ await t.step("ignores the query, including location hints", async () => {
104
+ assertEquals((await federation.fetch(gatewayRequest("/users/alice/notes/123?@gateway=https%3A%2F%2Fexample.com&x=%ZZ"), { contextData: void 0 })).status, 200);
105
+ });
106
+ await t.step("accepts an ap: ID returned by the dispatcher", async () => {
107
+ assertEquals((await federation.fetch(gatewayRequest("/users/alice/notes/ap"), { contextData: void 0 })).status, 200);
108
+ });
109
+ await t.step("responds to HEAD without a body", async () => {
110
+ const response = await federation.fetch(gatewayRequest("/users/alice/notes/123", { method: "HEAD" }), { contextData: void 0 });
111
+ assertEquals(response.status, 200);
112
+ assertEquals(response.headers.get("Content-Type"), PORTABLE_OBJECT_CONTENT_TYPE);
113
+ assertEquals(response.body, null);
114
+ });
115
+ await t.step("responds with 404 for objects it does not serve", async () => {
116
+ for (const request of [
117
+ gatewayRequest("/users/alice/notes/missing"),
118
+ gatewayRequest("/users/alice/notes/https"),
119
+ gatewayRequest("/users/alice/notes/123", { authority: otherDid }),
120
+ gatewayRequest("/users/alice/notes/ignores-authority", { authority: otherDid }),
121
+ gatewayRequest("/users/alice/posts/123"),
122
+ gatewayRequest("/actors/alice")
123
+ ]) assertEquals((await federation.fetch(request, { contextData: void 0 })).status, 404, request.url);
124
+ });
125
+ await t.step("responds with 400 for malformed portable IDs", async () => {
126
+ for (const path of [
127
+ `/.well-known/apgateway/${did}`,
128
+ "/.well-known/apgateway/did:key:/users/alice/notes/123",
129
+ `/.well-known/apgateway/${did}/users/alice/notes/%ZZ`
130
+ ]) assertEquals((await federation.fetch(new Request(`https://example.com${path}`, { headers: { Accept: ACCEPT } }), { contextData: void 0 })).status, 400, path);
131
+ });
132
+ await t.step("leaves other gateway requests to onNotFound()", async () => {
133
+ for (const request of [
134
+ new Request("https://example.com/.well-known/apgateway", { headers: { Accept: ACCEPT } }),
135
+ new Request("https://example.com/.well-known/apgateway/hl:zQmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"),
136
+ gatewayRequest("/users/alice/notes/123", {
137
+ method: "POST",
138
+ body: "{}"
139
+ })
140
+ ]) {
141
+ let notFound = false;
142
+ assertEquals((await federation.fetch(request, {
143
+ contextData: void 0,
144
+ onNotFound() {
145
+ notFound = true;
146
+ return new Response("Not found", { status: 404 });
147
+ }
148
+ })).status, 404);
149
+ assertEquals(notFound, true, request.url);
150
+ }
151
+ });
152
+ await t.step("responds to HEAD without a body on errors", async () => {
153
+ for (const [request, status] of [[gatewayRequest("/users/alice/notes/missing", { method: "HEAD" }), 404], [gatewayRequest("/users/alice/notes/123", {
154
+ method: "HEAD",
155
+ headers: { Accept: "text/html" }
156
+ }), 406]]) {
157
+ const response = await federation.fetch(request, { contextData: void 0 });
158
+ assertEquals(response.status, status);
159
+ assertEquals(response.body, null);
160
+ }
161
+ });
162
+ await t.step("responds with 406 without a JSON-LD Accept header", async () => {
163
+ assertEquals((await federation.fetch(gatewayRequest("/users/alice/notes/123", { headers: { Accept: "text/html" } }), { contextData: void 0 })).status, 406);
164
+ });
165
+ await t.step("keeps ordinary object requests unchanged", async () => {
166
+ const response = await federation.fetch(new Request("https://example.com/users/alice/notes/https", { headers: { Accept: ACCEPT } }), { contextData: void 0 });
167
+ assertEquals(response.status, 200);
168
+ assertEquals(response.headers.get("Content-Type"), "application/activity+json");
169
+ assertEquals((await response.json()).id, "https://example.com/users/alice/notes/https");
170
+ });
171
+ });
172
+ test("Federation.fetch() applies the FEP-ef61 proof policy to portable objects", async (t) => {
173
+ const federation = createTestFederation();
174
+ const objects = {
175
+ "valid": () => signedNote("/objects/valid"),
176
+ "unsigned": () => Promise.resolve(new Note({ id: parseIri(`ap+ef61://${did}/objects/unsigned`) })),
177
+ "wrong-did": () => sign(new Note({ id: parseIri(`ap+ef61://${did}/objects/wrong-did`) }), otherKeyPair.privateKey, otherKeyId),
178
+ "tampered": async () => (await signedNote("/objects/tampered")).clone({ content: "Tampered" }),
179
+ "unsigned-collection": () => Promise.resolve(new Collection({
180
+ id: parseIri(`ap+ef61://${did}/objects/unsigned-collection`),
181
+ totalItems: 0
182
+ })),
183
+ "aliased-collection": () => Collection.fromJsonLd({
184
+ "@context": ["https://www.w3.org/ns/activitystreams", { "identifier": "@id" }],
185
+ type: "Collection",
186
+ identifier: `ap+ef61://${did}/objects/aliased-collection`,
187
+ totalItems: 0
188
+ }, {
189
+ contextLoader: mockDocumentLoader,
190
+ documentLoader: mockDocumentLoader
191
+ }),
192
+ "tampered-collection": async () => (await sign(new Collection({
193
+ id: parseIri(`ap+ef61://${did}/objects/tampered-collection`),
194
+ totalItems: 0
195
+ }))).clone({ totalItems: 1 }),
196
+ "activity": () => sign(new Create({
197
+ id: parseIri(`ap+ef61://${did}/objects/activity`),
198
+ actor: parseIri(`ap+ef61://${did}/actor`),
199
+ object: parseIri(`ap+ef61://${did}/objects/valid`)
200
+ })),
201
+ "actor": () => sign(new Person({
202
+ id: parseIri(`ap+ef61://${did}/objects/actor`),
203
+ inbox: parseIri(`ap+ef61://${did}/objects/actor/inbox`),
204
+ outbox: parseIri(`ap+ef61://${did}/objects/actor/outbox`),
205
+ gateways: [new URL("https://example.com/")]
206
+ })),
207
+ "mutated-id": async () => {
208
+ const signed = await signedNote("/objects/original");
209
+ const object = await Note.fromJsonLd(await signed.toJsonLd({ contextLoader: mockDocumentLoader }), {
210
+ contextLoader: mockDocumentLoader,
211
+ documentLoader: mockDocumentLoader
212
+ });
213
+ object.id.pathname = "/objects/mutated-id";
214
+ return object;
215
+ },
216
+ "unsigned-actor": () => Promise.resolve(new Person({
217
+ id: parseIri(`ap+ef61://${did}/objects/unsigned-actor`),
218
+ inbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/inbox`),
219
+ outbox: parseIri(`ap+ef61://${did}/objects/unsigned-actor/outbox`),
220
+ gateways: [new URL("https://example.com/")]
221
+ }))
222
+ };
223
+ federation.setObjectDispatcher(Object$1, "/objects/{id}", (_ctx, { id }) => objects[id]?.() ?? null);
224
+ for (const [id, status] of globalThis.Object.entries({
225
+ "valid": 200,
226
+ "unsigned": 500,
227
+ "wrong-did": 500,
228
+ "tampered": 500,
229
+ "unsigned-collection": 200,
230
+ "aliased-collection": 200,
231
+ "tampered-collection": 500,
232
+ "activity": 200,
233
+ "actor": 200,
234
+ "mutated-id": 404,
235
+ "unsigned-actor": 500
236
+ })) await t.step(`${id} → ${status}`, async () => {
237
+ const response = await federation.fetch(gatewayRequest(`/objects/${id}`), { contextData: void 0 });
238
+ assertEquals(response.status, status);
239
+ if (status === 500) assertEquals(await response.text(), "Internal server error.");
240
+ });
241
+ await t.step("responds to HEAD without a body on failure", async () => {
242
+ const response = await federation.fetch(gatewayRequest("/objects/unsigned", { method: "HEAD" }), { contextData: void 0 });
243
+ assertEquals(response.status, 500);
244
+ assertEquals(response.body, null);
245
+ });
246
+ });
247
+ test("Federation.fetch() authorizes portable object requests", async (t) => {
248
+ const federation = createTestFederation();
249
+ let dispatched = 0;
250
+ federation.setObjectDispatcher(Note, "/notes/{id}", (ctx, values) => {
251
+ dispatched++;
252
+ if (values.id === "unsigned") return new Note({ id: ctx.getPortableObjectUri(Note, values) });
253
+ return signedNote(`/notes/${values.id}`);
254
+ }).authorize(async (ctx) => {
255
+ assertEquals(ctx.portableRequest?.authority, did);
256
+ return (await ctx.getSignedKeyOwner())?.id?.href === "https://example.com/person2";
257
+ });
258
+ await t.step("allows a signed request by the audience", async () => {
259
+ const request = await signRequest(gatewayRequest("/notes/1"), rsaPrivateKey3, rsaPublicKey3.id);
260
+ assertEquals((await federation.fetch(request, { contextData: void 0 })).status, 200);
261
+ });
262
+ await t.step("denies an unsigned request", async () => {
263
+ assertEquals((await federation.fetch(gatewayRequest("/notes/1"), { contextData: void 0 })).status, 401);
264
+ });
265
+ await t.step("denies a request signed by someone else", async () => {
266
+ const request = await signRequest(gatewayRequest("/notes/1"), rsaPrivateKey2, rsaPublicKey2.id);
267
+ assertEquals((await federation.fetch(request, { contextData: void 0 })).status, 401);
268
+ });
269
+ await t.step("denies a request whose target was tampered with", async () => {
270
+ const signed = await signRequest(gatewayRequest("/notes/1"), rsaPrivateKey3, rsaPublicKey3.id);
271
+ assertEquals((await federation.fetch(new Request(gatewayUrl("/notes/2"), { headers: signed.headers }), { contextData: void 0 })).status, 401);
272
+ });
273
+ await t.step("authorizes before checking proofs", async () => {
274
+ dispatched = 0;
275
+ assertEquals((await federation.fetch(gatewayRequest("/notes/unsigned"), { contextData: void 0 })).status, 401);
276
+ assertEquals(dispatched, 1);
277
+ });
278
+ });
279
+ test("Federation.fetch() lets application routes shadow the gateway", async () => {
280
+ const federation = createTestFederation();
281
+ const paths = [];
282
+ federation.setObjectDispatcher(Note, "/{+path}", (_ctx, { path }) => {
283
+ paths.push(path);
284
+ return null;
285
+ });
286
+ assertEquals((await federation.fetch(gatewayRequest("/notes/1"), { contextData: void 0 })).status, 404);
287
+ assertEquals(paths, [`.well-known/apgateway/${did}/notes/1`]);
288
+ });
289
+ test("Federation.fetch() compares portable IDs with the requested path", async () => {
290
+ const federation = createTestFederation();
291
+ federation.setObjectDispatcher(Note, "/notes/{id}", async (ctx, values) => {
292
+ if (values.id === "a/b") return await sign(new Note({ id: ctx.getPortableObjectUri(Note, values) }));
293
+ return await signedNote(`/notes/${values.id}`);
294
+ });
295
+ let response = await federation.fetch(gatewayRequest("/notes/a%2Fb"), { contextData: void 0 });
296
+ assertEquals(response.status, 200);
297
+ assertEquals((await response.json()).id, `ap+ef61://${did}/notes/a%2Fb`);
298
+ const tolerant = createFederation({
299
+ kv: new MemoryKvStore(),
300
+ documentLoaderFactory: () => mockDocumentLoader,
301
+ contextLoaderFactory: () => mockDocumentLoader,
302
+ trailingSlashInsensitive: true
303
+ });
304
+ tolerant.setObjectDispatcher(Note, "/notes/{id}", (_ctx, values) => signedNote(`/notes/${values.id}`));
305
+ response = await tolerant.fetch(gatewayRequest("/notes/1/"), { contextData: void 0 });
306
+ assertEquals(response.status, 404);
307
+ });
308
+ test("RequestContext.portableRequest", async (t) => {
309
+ const federation = createTestFederation();
310
+ const contexts = [];
311
+ federation.setObjectDispatcher(Tombstone, "/tombstones/{id}", (ctx) => {
312
+ contexts.push(ctx);
313
+ return null;
314
+ });
315
+ federation.setObjectDispatcher(Note, "/notes/{id}", async (ctx, values) => {
316
+ contexts.push(ctx);
317
+ ctx.portableRequest.id.pathname = "/notes/other";
318
+ await ctx.getObject(Tombstone, { id: values.id });
319
+ contexts.push(ctx.clone(void 0));
320
+ return await sign(new Note({ id: ctx.getPortableObjectUri(Note, values) }));
321
+ });
322
+ assertEquals((await federation.fetch(gatewayRequest("/notes/1"), { contextData: void 0 })).status, 200);
323
+ await t.step("is frozen and returns a new URL each time", () => {
324
+ const [ctx] = contexts;
325
+ const portableRequest = ctx.portableRequest;
326
+ assertEquals(globalThis.Object.isFrozen(portableRequest), true);
327
+ assertEquals(formatIri(portableRequest.id), `ap+ef61://${did}/notes/1`);
328
+ assertInstanceOf(portableRequest.id, URL);
329
+ const first = portableRequest.id;
330
+ const second = portableRequest.id;
331
+ assertEquals(first === second, false);
332
+ });
333
+ await t.step("is kept by derived contexts", () => {
334
+ assertEquals(contexts.length, 3);
335
+ assertStrictEquals(contexts[1].portableRequest, contexts[0].portableRequest);
336
+ assertStrictEquals(contexts[2].portableRequest, contexts[0].portableRequest);
337
+ });
338
+ await t.step("is undefined for ordinary requests", () => {
339
+ assertEquals(federation.createContext(new Request("https://example.com/notes/1"), void 0).portableRequest, void 0);
340
+ });
341
+ });
342
+ test("Context.getPortableObjectUri()", async (t) => {
343
+ const federation = createTestFederation();
344
+ federation.setObjectDispatcher(Note, "/users/{userId}/notes/{noteId}", () => null);
345
+ const ctx = federation.createContext(new URL("https://example.com/"), void 0);
346
+ const values = {
347
+ userId: "alice",
348
+ noteId: "123"
349
+ };
350
+ await t.step("builds a portable ID from the object path", () => {
351
+ const uri = ctx.getPortableObjectUri(Note, values, did);
352
+ assertInstanceOf(uri, URL);
353
+ assertEquals(uri.protocol, "ap+ef61:");
354
+ assertEquals(formatIri(uri), `ap+ef61://${did}/users/alice/notes/123`);
355
+ assertEquals(ctx.getObjectUri(Note, values), new URL("https://example.com/users/alice/notes/123"));
356
+ });
357
+ await t.step("requires a bare DID authority", () => {
358
+ for (const authority of [
359
+ `${did}/extra`,
360
+ `${did}?query`,
361
+ `${did}#fragment`,
362
+ "did:key:",
363
+ "https://example.com",
364
+ ""
365
+ ]) assertThrows(() => ctx.getPortableObjectUri(Note, values, authority), TypeError, void 0, authority);
366
+ });
367
+ await t.step("requires an authority outside gateway requests", () => {
368
+ const requestCtx = federation.createContext(new Request("https://example.com/"), void 0);
369
+ assertThrows(() => requestCtx.getPortableObjectUri(Note, values), TypeError);
370
+ assertEquals(formatIri(requestCtx.getPortableObjectUri(Note, values, did)), `ap+ef61://${did}/users/alice/notes/123`);
371
+ });
372
+ await t.step("validates values like getObjectUri()", () => {
373
+ assertThrows(() => ctx.getPortableObjectUri(Note, { userId: "alice" }, did), TypeError);
374
+ assertThrows(() => ctx.getPortableObjectUri(Person, values, did));
375
+ });
376
+ });
377
+ test("Federation.fetch() serves portable actors through WebFinger", async () => {
378
+ const federation = createTestFederation();
379
+ const getActor = async (ctx, name) => {
380
+ if (name !== "alice") return null;
381
+ return await sign(new Person({
382
+ id: ctx.getPortableObjectUri(Person, { name }, did),
383
+ preferredUsername: name,
384
+ gateways: [new URL("https://example.com")]
385
+ }));
386
+ };
387
+ federation.setActorDispatcher("/users/{identifier}", (ctx, identifier) => getActor(ctx, identifier)).mapHandle((_ctx, username) => username);
388
+ federation.setObjectDispatcher(Person, "/actors/{name}", (ctx, values) => ctx.portableRequest?.authority === did ? getActor(ctx, values.name) : null);
389
+ const webFinger = await federation.fetch(new Request("https://example.com/.well-known/webfinger?resource=acct:alice@example.com"), { contextData: void 0 });
390
+ assertEquals(webFinger.status, 200);
391
+ const jrd = await webFinger.json();
392
+ const compatibleId = gatewayUrl("/actors/alice");
393
+ assertEquals(jrd.subject, "acct:alice@example.com");
394
+ assertEquals(jrd.links?.[0], {
395
+ rel: "self",
396
+ href: compatibleId,
397
+ type: "application/activity+json"
398
+ });
399
+ const documentLoader = async (url) => {
400
+ const response = await federation.fetch(new Request(url, { headers: { Accept: ACCEPT } }), { contextData: void 0 });
401
+ if (!response.ok) throw new Error(`HTTP ${response.status}: ${url}`);
402
+ return {
403
+ contextUrl: null,
404
+ documentUrl: url,
405
+ document: await response.json()
406
+ };
407
+ };
408
+ const actor = await lookupObject(compatibleId, {
409
+ documentLoader,
410
+ contextLoader: mockDocumentLoader,
411
+ verifyPortableObject: verifyPortableObjectProof
412
+ });
413
+ assertInstanceOf(actor, Person);
414
+ assertEquals(formatIri(actor.id), `ap+ef61://${did}/actors/alice`);
415
+ assertEquals(actor.preferredUsername, "alice");
416
+ const ctx = federation.createContext(new URL("https://example.com/"), void 0);
417
+ assertInstanceOf(await ctx.lookupObject(compatibleId, { documentLoader }), Person);
418
+ const unsigned = {
419
+ "@context": "https://www.w3.org/ns/activitystreams",
420
+ id: `ap://${did}/actors/alice`,
421
+ type: "Person"
422
+ };
423
+ assertEquals(await ctx.lookupObject(compatibleId, { documentLoader: (url) => Promise.resolve({
424
+ contextUrl: null,
425
+ documentUrl: url,
426
+ document: unsigned
427
+ }) }), null);
428
+ });
429
+ //#endregion
430
+ export {};
@@ -10,10 +10,10 @@ import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
10
10
  import "../std__assert-DvMDRPes.mjs";
11
11
  import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
12
12
  import { t as assert } from "../assert-D1Eafmd_.mjs";
13
- import { l as verifyRequest } from "../http-D4WPcJUe.mjs";
13
+ import { l as verifyRequest } from "../http-CK6kjLnO.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-BIOIhZoM.mjs";
16
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-Cr5FJ7iu.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-B3PgGiJ1.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-BqBILxYE.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";
@@ -3,8 +3,8 @@ import "urlpattern-polyfill";
3
3
  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
- import "../../testing-hbky2gMN.mjs";
7
- import { o as createFederation } from "../../middleware-C7_hqDnl.mjs";
6
+ import "../../testing-By1YYsIK.mjs";
7
+ import { o as createFederation } from "../../middleware-CtFNjIUD.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";
@@ -3,9 +3,9 @@ import "urlpattern-polyfill";
3
3
  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
- import "../../testing-hbky2gMN.mjs";
7
- import { o as createFederation } from "../../middleware-C7_hqDnl.mjs";
8
- import { r as createFederationBuilder } from "../../builder-BYJ5otJa.mjs";
6
+ import "../../testing-By1YYsIK.mjs";
7
+ import { o as createFederation } from "../../middleware-CtFNjIUD.mjs";
8
+ import { r as createFederationBuilder } from "../../builder-Cue1kVHU.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-CCf0lZV3.mjs";
7
+ import { t as hasMalformedKnownTemporalLiteral } from "../temporal-SUiLJ0Co.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 () => {