UNPKG

@fedify/fedify

Version:

An ActivityPub server framework

1,197 lines (1,196 loc) 120 kB
/// <reference lib="esnext.temporal" /> import { o as JsonValue, s as NodeInfo, t as GetNodeInfoOptions } from "./client-CSddvgWN.js"; import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-BDZeS5om.js"; import { n as GetKeyOwnerOptions } from "./owner-CnngXDNJ.js"; import { n as KvStore, t as KvKey } from "./kv-D6hNiMTK.js"; import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab"; import { Span, Tracer, TracerProvider } from "@opentelemetry/api"; import { AuthenticatedDocumentLoaderFactory, DocumentLoader, DocumentLoaderFactory, GetUserAgentOptions } from "@fedify/vocab-runtime"; import { Link as Link$1, LookupWebFingerOptions, ResourceDescriptor } from "@fedify/webfinger"; //#region src/compat/types.d.ts /** * A function that transforms an activity object. * @since 1.4.0 */ type ActivityTransformer<TContextData> = (activity: Activity, context: Context<TContextData>) => Activity; //#endregion //#region src/federation/collection.d.ts /** * A page of items. */ interface PageItems<TItem> { readonly prevCursor?: string | null; readonly nextCursor?: string | null; readonly items: readonly TItem[]; } /** * Calculates the [partial follower collection digest][1]. * * [1]: https://w3id.org/fep/8fcf#partial-follower-collection-digest * @param uris The URIs to calculate the digest. Duplicate URIs are ignored. * @returns The digest. */ declare function digest(uris: Iterable<string | URL>): Promise<Uint8Array>; /** * Builds [`Collection-Synchronization`][1] header content. * * [1]: https://w3id.org/fep/8fcf#the-collection-synchronization-http-header * * @param collectionId The sender's followers collection URI. * @param actorIds The actor URIs to digest. * @returns The header content. */ declare function buildCollectionSynchronizationHeader(collectionId: string | URL, actorIds: Iterable<string | URL>): Promise<string>; //#endregion //#region src/federation/send.d.ts /** * A key pair for an actor who sends an activity. * @since 0.10.0 */ interface SenderKeyPair { /** * The actor's private key to sign the request. */ readonly privateKey: CryptoKey; /** * The public key ID that corresponds to the private key. */ readonly keyId: URL; } /** * An error that is thrown when an activity fails to send to a remote inbox. * It contains structured information about the failure, including the HTTP * status code, the inbox URL, and the response body. * @since 2.0.0 */ declare class SendActivityError extends Error { /** * The inbox URL that the activity was being sent to. */ readonly inbox: URL; /** * The HTTP status code returned by the inbox. */ readonly statusCode: number; /** * The response body from the inbox, if any. Note that this may be * truncated to a maximum of 1 KiB to prevent excessive memory consumption * when remote servers return large error pages (e.g., Cloudflare error pages). * If truncated, the string will end with `"… (truncated)"`. */ readonly responseBody: string; /** * Creates a new {@link SendActivityError}. * @param inbox The inbox URL. * @param statusCode The HTTP status code. * @param message The error message. * @param responseBody The response body. */ constructor(inbox: URL, statusCode: number, message: string, responseBody: string); } //#endregion //#region src/federation/callback.d.ts /** * A callback that dispatches a {@link NodeInfo} object. * * @template TContextData The context data to pass to the {@link Context}. */ type NodeInfoDispatcher<TContextData> = (context: RequestContext<TContextData>) => NodeInfo | Promise<NodeInfo>; /** * A callback that dispatches a array of {@link Link}. * * @template TContextData The context data to pass to the {@link Context}. * @param resource The URL queried via WebFinger. * @returns Links related to the queried resource. */ type WebFingerLinksDispatcher<TContextData> = (context: RequestContext<TContextData>, resource: URL) => readonly Link$1[] | Promise<readonly Link$1[]>; /** * A callback that dispatches an {@link Actor} object or a {@link Tombstone}. * * @template TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param identifier The actor's internal identifier or username. */ type ActorDispatcher<TContextData> = (context: RequestContext<TContextData>, identifier: string) => Actor | Tombstone | null | Promise<Actor | Tombstone | null>; /** * A callback that dispatches key pairs for an actor. * * @template TContextData The context data to pass to the {@link Context}. * @param context The context. * @param identifier The actor's internal identifier or username. * @returns The key pairs. * @since 0.10.0 */ type ActorKeyPairsDispatcher<TContextData> = (context: Context<TContextData>, identifier: string) => CryptoKeyPair[] | Promise<CryptoKeyPair[]>; /** * A callback that maps a WebFinger username to the corresponding actor's * internal identifier, or `null` if the username is not found. * @template TContextData The context data to pass to the {@link Context}. * @param context The context. * @param username The WebFinger username. * @returns The actor's internal identifier, or `null` if the username is not * found. * @since 0.15.0 */ type ActorHandleMapper<TContextData> = (context: Context<TContextData>, username: string) => string | null | Promise<string | null>; /** * A callback that maps a WebFinger query to the corresponding actor's * internal identifier or username, or `null` if the query is not found. * @template TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param resource The URL that was queried through WebFinger. * @returns The actor's internal identifier or username, or `null` if the query * is not found. * @since 1.4.0 */ type ActorAliasMapper<TContextData> = (context: RequestContext<TContextData>, resource: URL) => { identifier: string; } | { username: string; } | null | Promise<{ identifier: string; } | { username: string; } | null>; /** * A callback that dispatches an object. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @since 0.7.0 */ type ObjectDispatcher<TContextData, TObject extends Object$1, TParam extends string> = (context: RequestContext<TContextData>, values: Record<TParam, string>) => TObject | null | Promise<TObject | null>; /** * A callback that dispatches a collection. * * @template TItem The type of items in the collection. * @template TContext The type of the context. {@link Context} or * {@link RequestContext}. * @template TContextData The context data to pass to the `TContext`. * @template TFilter The type of the filter, if any. * @param context The context. * @param identifier The internal identifier or the username of the collection * owner. * @param cursor The cursor to start the collection from, or `null` to dispatch * the entire collection without pagination. * @param filter The filter to apply to the collection, if any. */ type CollectionDispatcher<TItem, TContext extends Context<TContextData>, TContextData, TFilter> = (context: TContext, identifier: string, cursor: string | null, filter?: TFilter) => PageItems<TItem> | null | Promise<PageItems<TItem> | null>; /** * A callback that counts the number of items in a collection. * * @template TContextData The context data to pass to the {@link Context}. * @param context The context. * @param identifier The internal identifier or the username of the collection * owner. * @param filter The filter to apply to the collection, if any. */ type CollectionCounter<TContextData, TFilter> = (context: RequestContext<TContextData>, identifier: string, filter?: TFilter) => number | bigint | null | Promise<number | bigint | null>; /** * A callback that returns a cursor for a collection. * * @template TContext The type of the context. {@link Context} or * {@link RequestContext}. * @template TContextData The context data to pass to the {@link Context}. * @template TFilter The type of the filter, if any. * @param context The context. * @param identifier The internal identifier or the username of the collection * owner. * @param filter The filter to apply to the collection, if any. */ type CollectionCursor<TContext extends Context<TContextData>, TContextData, TFilter> = (context: TContext, identifier: string, filter?: TFilter) => string | null | Promise<string | null>; /** * A callback that listens for activities in an inbox. * * @template TContextData The context data to pass to the {@link Context}. * @template TActivity The type of activity to listen for. * @param context The inbox context. * @param activity The activity that was received. */ type InboxListener<TContextData, TActivity extends Activity> = (context: InboxContext<TContextData>, activity: TActivity) => void | Promise<void>; /** * A callback that listens for activities in an outbox. * * @template TContextData The context data to pass to the {@link Context}. * @template TActivity The type of activity to listen for. * @param context The outbox context. * @param activity The activity that was received. * @since 2.2.0 */ type OutboxListener<TContextData, TActivity extends Activity> = (context: OutboxContext<TContextData>, activity: TActivity) => void | Promise<void>; /** * The reason why an incoming activity could not be verified. * * Unlike inbox listeners registered through {@link InboxListenerSetters.on}, * unverified activity handlers are called only when the activity payload could * be parsed but its HTTP signatures could not be verified. * * @since 2.1.0 */ type UnverifiedActivityReason = VerifyRequestFailureReason; /** * A callback that handles activities whose signatures could not be verified. * * Returning a {@link Response} overrides Fedify's default `401 Unauthorized` * response. Returning `void` keeps the default behavior. * * @template TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param activity The incoming activity that could be parsed. * @param reason The reason why signature verification failed. * @since 2.1.0 */ type UnverifiedActivityHandler<TContextData> = (context: RequestContext<TContextData>, activity: Activity, reason: UnverifiedActivityReason) => void | Response | Promise<void | Response>; /** * A callback that handles errors in an inbox. * * @template TContextData The context data to pass to the {@link Context}. * @param context The inbox context. */ type InboxErrorHandler<TContextData> = (context: Context<TContextData>, error: Error) => void | Promise<void>; /** * A callback that handles errors in an outbox listener. * * @template TContextData The context data to pass to the {@link Context}. * @param context The outbox context. * @param error The error that occurred. * @since 2.2.0 */ type OutboxListenerErrorHandler<TContextData> = (context: OutboxContext<TContextData>, error: Error) => void | Promise<void>; /** * A callback that dispatches the key pair for the authenticated document loader * of the {@link Context} passed to the shared inbox listener. * * @template TContextData The context data to pass to the {@link Context}. * @param context The context. * @returns The username or the internal identifier of the actor or the key pair * for the authenticated document loader of the {@link Context} passed * to the shared inbox listener. If `null` is returned, the request is * not authorized. * @since 0.11.0 */ type SharedInboxKeyDispatcher<TContextData> = (context: Context<TContextData>) => SenderKeyPair | { identifier: string; } | { username: string; } | null | Promise<SenderKeyPair | { identifier: string; } | { username: string; } | null>; /** * A callback that handles errors during outbox processing. * * @param error The error that occurred. * @param activity The activity that caused the error. If it is `null`, the * error occurred during deserializing the activity. * @since 0.6.0 */ type OutboxErrorHandler = (error: Error, activity: Activity | null) => void | Promise<void>; /** * A callback that handles permanent delivery failures when sending activities * to remote inboxes. * * This handler is called when an inbox returns an HTTP status code that * indicates permanent failure (such as `410 Gone` or `404 Not Found`), * allowing the application to clean up followers that are no longer reachable. * * Unlike {@link OutboxErrorHandler}, which is called for every delivery failure * (including retries), this handler is called only once for permanent failures, * after which delivery is not retried. * * If any errors are thrown in this callback, they are caught, logged, * and ignored. * * @template TContextData The context data to pass to the {@link Context}. * @param context The context. * @param values The delivery failure information. * @since 2.0.0 */ type OutboxPermanentFailureHandler<TContextData> = (context: Context<TContextData>, values: { /** The inbox URL that failed. */readonly inbox: URL; /** The activity that failed to deliver. */ readonly activity: Activity; /** The error that occurred. */ readonly error: SendActivityError; /** The HTTP status code returned by the inbox. */ readonly statusCode: number; /** * The actor IDs that were supposed to receive the activity at this inbox. */ readonly actorIds: readonly URL[]; }) => void | Promise<void>; /** * A callback that determines if a request is authorized or not. * * @template TContextData The context data to pass to the {@link Context}. * @param context The request context. * @param identifier The internal identifier of the actor that is being * requested. * @returns `true` if the request is authorized, `false` otherwise. * @since 0.7.0 */ type AuthorizePredicate<TContextData> = (context: RequestContext<TContextData>, identifier: string) => boolean | Promise<boolean>; /** * A callback that determines if a request is authorized or not. * * @template TContextData The context data to pass to the {@link Context}. * @template TParam The parameter names of the requested URL. * @param context The request context. * @param values The parameters of the requested URL. * @returns `true` if the request is authorized, `false` otherwise. * @since 0.7.0 */ type ObjectAuthorizePredicate<TContextData, TParam extends string> = (context: RequestContext<TContextData>, values: Record<TParam, string>) => boolean | Promise<boolean>; /** * A callback that dispatches a custom collection. * * @template TItem The type of items in the collection. * @template TParams The parameter names of the requested URL. * @template TContext The type of the context. {@link Context} or * {@link RequestContext}. * @template TContextData The context data to pass to the `TContext`. * @template TFilter The type of the filter, if any. * @param context The context. * @param values The parameters of the requested URL. * @param cursor The cursor to start the collection from, or `null` to dispatch * the entire collection without pagination. * @since 1.8.0 */ type CustomCollectionDispatcher<TItem, TParam extends string, TContext extends Context<TContextData>, TContextData> = (context: TContext, values: Record<TParam, string>, cursor: string | null) => PageItems<TItem> | null | Promise<PageItems<TItem> | null>; /** * A callback that counts the number of items in a custom collection. * * @template TParams The parameter names of the requested URL. * @template TContextData The context data to pass to the {@link Context}. * @param context The context. * @param values The parameters of the requested URL. * @since 1.8.0 */ type CustomCollectionCounter<TParam extends string, TContextData> = (context: RequestContext<TContextData>, values: Record<TParam, string>) => number | bigint | null | Promise<number | bigint | null>; /** * A callback that returns a cursor for a custom collection. * * @template TParams The parameter names of the requested URL. * @template TContext The type of the context. {@link Context} or * {@link RequestContext}. * @template TContextData The context data to pass to the {@link Context}. * @template TFilter The type of the filter, if any. * @param context The context. * @param values The parameters of the requested URL. * @since 1.8.0 */ type CustomCollectionCursor<TParam extends string, TContext extends Context<TContextData>, TContextData> = (context: TContext, values: Record<TParam, string>) => string | null | Promise<string | null>; //#endregion //#region src/federation/mq.d.ts /** * Additional options for enqueuing a message in a queue. * * @since 0.5.0 */ interface MessageQueueEnqueueOptions { /** * The delay before the message is enqueued. No delay by default. * * It must not be negative. */ readonly delay?: Temporal.Duration; /** * An optional key that ensures messages with the same ordering key are * processed sequentially (one at a time). Messages with different ordering * keys (or no ordering key) may be processed in parallel. * * This is useful for ensuring that related messages are processed in order, * such as ensuring that a `Delete` activity is processed after a `Create` * activity for the same object. * * @since 2.0.0 */ readonly orderingKey?: string; } /** * Additional options for listening to a message queue. * * @since 1.0.0 */ interface MessageQueueListenOptions { /** * The signal to abort listening to the message queue. */ signal?: AbortSignal; } /** * An abstract interface for a message queue. * * @since 0.5.0 */ interface MessageQueue { /** * Whether the message queue backend provides native retry mechanisms. * When `true`, Fedify will skip its own retry logic and rely on the backend * to handle retries. When `false` or omitted, Fedify will handle retries * using its own retry policies. * * @default `false` * @since 1.7.0 */ readonly nativeRetrial?: boolean; /** * Enqueues a message in the queue. * @param message The message to enqueue. * @param options Additional options for enqueuing the message. */ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>; /** * Enqueues multiple messages in the queue. This operation is optional, * and may not be supported by all implementations. If not supported, * Fedify will invoke {@link enqueue} for each message. * * @param messages The messages to enqueue. * @param options Additional options for enqueuing the messages. */ enqueueMany?: (messages: readonly any[], options?: MessageQueueEnqueueOptions) => Promise<void>; /** * Listens for messages in the queue. * @param handler The handler for messages in the queue. * @param options Additional options for listening to the message queue. * @returns A promise that resolves when the listening is done. It never * rejects, and is resolved when the signal is aborted. If no * signal is provided, it never resolves. */ listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>; } /** * Additional options for {@link InProcessMessageQueue}. * @since 1.0.0 */ interface InProcessMessageQueueOptions { /** * The interval to poll for messages in the queue. 5 seconds by default. * @default `{ seconds: 5 }` */ pollInterval?: Temporal.Duration | Temporal.DurationLike; } /** * A message queue that processes messages in the same process. * Do not use this in production as it does neither persist messages nor * distribute them across multiple processes. * * @since 0.5.0 */ declare class InProcessMessageQueue implements MessageQueue { #private; /** * In-process message queue does not provide native retry mechanisms. * @since 1.7.0 */ readonly nativeRetrial = false; /** * Constructs a new {@link InProcessMessageQueue} with the given options. * @param options Additional options for the in-process message queue. */ constructor(options?: InProcessMessageQueueOptions); enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>; enqueueMany(messages: readonly any[], options?: MessageQueueEnqueueOptions): Promise<void>; listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>; } /** * A message queue that processes messages in parallel. It takes another * {@link MessageQueue}, and processes messages in parallel up to a certain * number of workers. * * Actually, it's rather a decorator than a queue itself. * * Note that the workers do not run in truly parallel, in the sense that they * are not running in separate threads or processes. They are running in the * same process, but are scheduled to run in parallel. Hence, this is useful * for I/O-bound tasks, but not for CPU-bound tasks, which is okay for Fedify's * workloads. * * When using `ParallelMessageQueue`, the ordering guarantee is preserved * *only if* the underlying queue implementation delivers messages in a wrapper * format that includes the `__fedify_ordering_key__` property. Currently, * only `DenoKvMessageQueue` and `WorkersMessageQueue` use this format. * For other queue implementations (e.g., `InProcessMessageQueue`, * `RedisMessageQueue`, `PostgresMessageQueue`, `SqliteMessageQueue`, * `AmqpMessageQueue`), the ordering key cannot be detected by * `ParallelMessageQueue`, so ordering guarantees are handled by those * implementations directly rather than at the `ParallelMessageQueue` level. * * Messages with the same ordering key will never be processed concurrently * by different workers, ensuring sequential processing within each key. * Messages with different ordering keys (or no ordering key) can still be * processed in parallel. * * @since 1.0.0 */ declare class ParallelMessageQueue implements MessageQueue { #private; readonly queue: MessageQueue; readonly workers: number; /** * Inherits the native retry capability from the wrapped queue. * @since 1.7.0 */ readonly nativeRetrial?: boolean; /** * Constructs a new {@link ParallelMessageQueue} with the given queue and * number of workers. * @param queue The message queue to use under the hood. Note that * {@link ParallelMessageQueue} cannot be nested. * @param workers The number of workers to process messages in parallel. * @throws {TypeError} If the given queue is an instance of * {@link ParallelMessageQueue}. */ constructor(queue: MessageQueue, workers: number); enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>; enqueueMany(messages: readonly any[], options?: MessageQueueEnqueueOptions): Promise<void>; listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>; } //#endregion //#region src/federation/handler.d.ts /** * Options for the {@link respondWithObject} and * {@link respondWithObjectIfAcceptable} functions. * @since 0.3.0 */ interface RespondWithObjectOptions { /** * The document loader to use for compacting JSON-LD. * @since 0.8.0 */ contextLoader: DocumentLoader; } /** * Responds with the given object in JSON-LD format. * * @param object The object to respond with. * @param options Options. * @since 0.3.0 */ declare function respondWithObject(object: Object$1, options?: RespondWithObjectOptions): Promise<Response>; /** * Responds with the given object in JSON-LD format if the request accepts * JSON-LD. * * @param object The object to respond with. * @param request The request to check for JSON-LD acceptability. * @param options Options. * @since 0.3.0 */ declare function respondWithObjectIfAcceptable(object: Object$1, request: Request, options?: RespondWithObjectOptions): Promise<Response | null>; //#endregion //#region src/federation/router.d.ts /** * Options for the {@link Router}. * @since 0.12.0 */ interface RouterOptions { /** * Whether to ignore trailing slashes when matching paths. */ trailingSlashInsensitive?: boolean; } /** * The result of {@link Router.route} method. * @since 1.3.0 */ interface RouterRouteResult { /** * The matched route name. */ name: string; /** * The URL template of the matched route. */ template: string; /** * The values extracted from the URL. */ values: Record<string, string>; } /** * URL router and constructor based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). */ declare class Router { #private; /** * Whether to ignore trailing slashes when matching paths. * @since 1.6.0 */ trailingSlashInsensitive: boolean; /** * Create a new {@link Router}. * @param options Options for the router. */ constructor(options?: RouterOptions); clone(): Router; /** * Checks if a path name exists in the router. * @param name The name of the path. * @returns `true` if the path name exists, otherwise `false`. */ has(name: string): boolean; /** * Adds a new path rule to the router. * @param template The path pattern. * @param name The name of the path. * @returns The names of the variables in the path pattern. */ add(template: string, name: string): Set<string>; /** * Resolves a path name and values from a URL, if any match. * @param url The URL to resolve. * @returns The name of the path and its values, if any match. Otherwise, * `null`. */ route(url: string): RouterRouteResult | null; /** * Constructs a URL/path from a path name and values. * @param name The name of the path. * @param values The values to expand the path with. * @returns The URL/path, if the name exists. Otherwise, `null`. */ build(name: string, values: Record<string, string>): string | null; } /** * An error thrown by the {@link Router}. */ declare class RouterError extends Error { /** * Create a new {@link RouterError}. * @param message The error message. */ constructor(message: string); } //#endregion //#region src/federation/builder.d.ts /** * Creates a new {@link FederationBuilder} instance. * @returns A new {@link FederationBuilder} instance. * @since 1.6.0 */ declare function createFederationBuilder<TContextData>(): FederationBuilder<TContextData>; //#endregion //#region src/federation/queue.d.ts interface SenderKeyJwkPair { readonly keyId: string; readonly privateKey: JsonWebKey; } /** * A message that represents a task to be processed by the background worker. * The concrete type of the message depends on the `type` property. * * Please do not depend on the concrete types of the messages, as they may * change in the future. You should treat the `Message` type as an opaque * type. * @since 1.6.0 */ type Message = FanoutMessage | OutboxMessage | InboxMessage; interface FanoutMessage { readonly type: "fanout"; readonly id: ReturnType<typeof crypto.randomUUID>; readonly baseUrl: string; readonly keys: readonly SenderKeyJwkPair[]; readonly inboxes: Readonly<Record<string, { readonly actorIds: readonly string[]; readonly sharedInbox: boolean; }>>; readonly activity: unknown; readonly activityId?: string; readonly activityType: string; readonly collectionSync?: string; readonly orderingKey?: string; /** * Whether to apply outgoing JSON-LD wire-format normalization to queued * activities that already carry Object Integrity Proofs. * * `true` is used for proofs Fedify created before fanout, or when callers * explicitly request normalization for locally pre-signed activities. * `false`/`undefined` preserves existing proofs as-is. */ readonly normalizeExistingProofs?: boolean; readonly traceContext: Readonly<Record<string, string>>; } interface OutboxMessage { readonly type: "outbox"; readonly id: ReturnType<typeof crypto.randomUUID>; readonly baseUrl: string; readonly keys: readonly SenderKeyJwkPair[]; readonly activity: unknown; readonly activityId?: string; readonly activityType: string; readonly inbox: string; readonly sharedInbox: boolean; readonly actorIds?: readonly string[]; readonly started: string; readonly attempt: number; readonly headers: Readonly<Record<string, string>>; readonly orderingKey?: string; readonly traceContext: Readonly<Record<string, string>>; } interface InboxMessage { readonly type: "inbox"; readonly id: ReturnType<typeof crypto.randomUUID>; readonly baseUrl: string; readonly activity: unknown; /** * The normalized JSON-LD representation of a signed inbox activity that * Fedify already compacted successfully while accepting the request. Queue * workers can reuse this producer-side parse cache under stricter loader or * network constraints without changing the raw payload preserved for * forwarding. * * This may exist even when {@link ldSignatureVerified} is `false`, because * fallback-authenticated traffic and already-queued backlog items can still * depend on the cached normalized form to avoid re-fetching remote custom * contexts during worker processing. * * This is optional for backward compatibility with messages that were * queued by older Fedify versions or that were already in a queue before * upgrading. * * Fedify keeps this on the queued message itself instead of an external * sidecar because generic queue backends do not provide reliable lifecycle * guarantees for auxiliary storage across retries and redeliveries. * * @internal */ readonly normalizedActivity?: unknown; /** * Whether the producer actually verified the Linked Data Signature before * queueing this message. This lets workers distinguish verified LDS replay * from other authenticated inbox traffic that merely happened to include a * signature block. This provenance marker is separate from the optional * normalizedActivity parse cache. * * `undefined` preserves backward compatibility with older queued messages * that predate this marker. * * @internal */ readonly ldSignatureVerified?: boolean; readonly started: string; readonly attempt: number; readonly identifier: string | null; readonly traceContext: Readonly<Record<string, string>>; } //#endregion //#region src/federation/retry.d.ts /** * The context passed to a {@link RetryPolicy} callback. * @since 0.12.0 */ interface RetryContext { /** * The elapsed time since the first attempt. */ readonly elapsedTime: Temporal.Duration; /** * The number of attempts so far. */ readonly attempts: number; } /** * A policy that determines the delay before the next retry. * @param context The retry context. * @returns The delay before the next retry, or `null` to stop retrying. * It must not negative. * @since 0.12.0 */ type RetryPolicy = (context: RetryContext) => Temporal.Duration | null; /** * Options for {@link createExponentialBackoffPolicy} function. * @since 0.12.0 */ interface CreateExponentialBackoffPolicyOptions { /** * The initial delay before the first retry. Defaults to 1 second. */ readonly initialDelay?: Temporal.DurationLike; /** * The maximum delay between retries. Defaults to 12 hours. */ readonly maxDelay?: Temporal.DurationLike; /** * The maximum number of attempts before giving up. * Defaults to 10. */ readonly maxAttempts?: number; /** * The factor to multiply the previous delay by for each retry. * Defaults to 2. */ readonly factor?: number; /** * Whether to add jitter to the delay to avoid synchronization. * Turned on by default. */ readonly jitter?: boolean; } /** * Creates an exponential backoff retry policy. The delay between retries * starts at the `initialDelay` and is multiplied by the `factor` for each * subsequent retry, up to the `maxDelay`. The policy will give up after * `maxAttempts` attempts. The actual delay is randomized to avoid * synchronization (jitter). * @param options The options for the policy. * @returns The retry policy. * @since 0.12.0 */ declare function createExponentialBackoffPolicy(options?: CreateExponentialBackoffPolicyOptions): RetryPolicy; //#endregion //#region src/federation/middleware.d.ts /** * Configures the task queues for sending and receiving activities. * @since 1.3.0 */ interface FederationQueueOptions { /** * The message queue for incoming activities. If not provided, incoming * activities will not be queued and will be processed immediately. */ readonly inbox?: MessageQueue; /** * The message queue for outgoing activities. If not provided, outgoing * activities will not be queued and will be sent immediately. */ readonly outbox?: MessageQueue; /** * The message queue for fanning out outgoing activities. If not provided, * outgoing activities will not be fanned out in the background, but will be * fanned out immediately, which causes slow response times on * {@link Context.sendActivity} calls. */ readonly fanout?: MessageQueue; } /** * Prefixes for namespacing keys in the Deno KV store. */ interface FederationKvPrefixes { /** * The key prefix used for storing whether activities have already been * processed or not. * @default `["_fedify", "activityIdempotence"]` */ readonly activityIdempotence: KvKey; /** * The key prefix used for storing remote JSON-LD documents. * @default `["_fedify", "remoteDocument"]` */ readonly remoteDocument: KvKey; /** * The key prefix used for caching public keys. * @default `["_fedify", "publicKey"]` * @since 0.12.0 */ readonly publicKey: KvKey; /** * The key prefix used for caching HTTP Message Signatures specs. * The cached spec is used to reduce the number of requests to make signed * requests ("double-knocking" technique). * @default `["_fedify", "httpMessageSignaturesSpec"]` * @since 1.6.0 */ readonly httpMessageSignaturesSpec: KvKey; /** * The key prefix used for storing `Accept-Signature` challenge nonces. * Only used when {@link InboxChallengePolicy.requestNonce} is `true`. * @default `["_fedify", "acceptSignatureNonce"]` * @since 2.1.0 */ readonly acceptSignatureNonce: KvKey; } /** * Options for {@link FederationOptions.origin} when it is not a string. * @since 1.5.0 */ interface FederationOrigin { /** * The canonical hostname for fediverse handles (which are looked up through * WebFinger). This is used for WebFinger lookups. It has to be a valid * hostname, e.g., `"example.com"`. */ handleHost: string; /** * The canonical origin for web URLs. This is used for constructing absolute * URLs. It has to start with either `"http://"` or `"https://"`, and must * not contain a path or query string, e.g., `"https://example.com"`. */ webOrigin: string; } /** * Create a new {@link Federation} instance. * @param parameters Parameters for initializing the instance. * @returns A new {@link Federation} instance. * @since 0.10.0 */ declare function createFederation<TContextData>(options: FederationOptions<TContextData>): Federation<TContextData>; //#endregion //#region src/federation/federation.d.ts /** * Options for {@link Federation.startQueue} method. * @since 1.0.0 */ interface FederationStartQueueOptions { /** * The signal to abort the task queue. */ signal?: AbortSignal; /** * Starts the task worker only for the specified queue. If unspecified, * which is the default, the task worker starts for all three queues: * inbox, outbox, and fanout. * @since 1.3.0 */ queue?: "inbox" | "outbox" | "fanout"; } /** * A common interface between {@link Federation} and {@link FederationBuilder}. * @template TContextData The context data to pass to the {@link Context}. * @since 1.6.0 */ interface Federatable<TContextData> { /** * Registers a NodeInfo dispatcher. * @param path The URI path pattern for the NodeInfo dispatcher. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have no variables. * @param dispatcher A NodeInfo dispatcher callback to register. * @throws {RouterError} Thrown if the path pattern is invalid. */ setNodeInfoDispatcher(path: string, dispatcher: NodeInfoDispatcher<TContextData>): void; /** * Registers a links dispatcher to WebFinger * @param dispatcher A links dispatcher callback to register. */ setWebFingerLinksDispatcher(dispatcher: WebFingerLinksDispatcher<TContextData>): void; /** * Registers an actor dispatcher. * * @example * ``` typescript * federation.setActorDispatcher( * "/users/{identifier}", * async (ctx, identifier) => { * return new Person({ * id: ctx.getActorUri(identifier), * // ... * }); * } * ); * ``` * * @param path The URI path pattern for the actor dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher An actor dispatcher callback to register. It may return * an actor, a `Tombstone`, or `null` if the actor is not * found. * @returns An object with methods to set other actor dispatcher callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setActorDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: ActorDispatcher<TContextData>): ActorCallbackSetters<TContextData>; /** * Registers an object dispatcher. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @param cls The Activity Vocabulary class of the object to dispatch. * @param path The URI path pattern for the object dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one or more variables. * @param dispatcher An object dispatcher callback to register. */ setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: ConstructorWithTypeId<TObject>, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @param cls The Activity Vocabulary class of the object to dispatch. * @param path The URI path pattern for the object dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one or more variables. * @param dispatcher An object dispatcher callback to register. */ setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: ConstructorWithTypeId<TObject>, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @param cls The Activity Vocabulary class of the object to dispatch. * @param path The URI path pattern for the object dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one or more variables. * @param dispatcher An object dispatcher callback to register. */ setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: ConstructorWithTypeId<TObject>, path: `${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}{${TParam}}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @param cls The Activity Vocabulary class of the object to dispatch. * @param path The URI path pattern for the object dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one or more variables. * @param dispatcher An object dispatcher callback to register. */ setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: ConstructorWithTypeId<TObject>, path: `${string}${Rfc6570Expression<TParam>}${string}${Rfc6570Expression<TParam>}${string}${Rfc6570Expression<TParam>}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @param cls The Activity Vocabulary class of the object to dispatch. * @param path The URI path pattern for the object dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one or more variables. * @param dispatcher An object dispatcher callback to register. */ setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: ConstructorWithTypeId<TObject>, path: `${string}${Rfc6570Expression<TParam>}${string}${Rfc6570Expression<TParam>}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an object dispatcher. * * @template TContextData The context data to pass to the {@link Context}. * @template TObject The type of object to dispatch. * @template TParam The parameter names of the requested URL. * @param cls The Activity Vocabulary class of the object to dispatch. * @param path The URI path pattern for the object dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one or more variables. * @param dispatcher An object dispatcher callback to register. */ setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: ConstructorWithTypeId<TObject>, path: `${string}${Rfc6570Expression<TParam>}${string}`, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>; /** * Registers an inbox dispatcher. * * @param path The URI path pattern for the inbox dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`, and must match * the inbox listener path. * @param dispatcher An inbox dispatcher callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setInboxDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers an outbox dispatcher. * * @example * ``` typescript * federation.setOutboxDispatcher( * "/users/{identifier}/outbox", * async (ctx, identifier, options) => { * let items: Activity[]; * let nextCursor: string; * // ... * return { items, nextCursor }; * } * ); * ``` * * @param path The URI path pattern for the outbox dispatcher. The syntax is * based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher An outbox dispatcher callback to register. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setOutboxDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Assigns the URL path for the outbox and starts setting outbox listeners. * * @example * ``` typescript * federation * .setOutboxListeners("/users/{identifier}/outbox") * .on(Activity, async (ctx, activity) => { * await ctx.sendActivity({ identifier: ctx.identifier }, "followers", activity); * }) * .authorize(async (ctx, identifier) => { * return ctx.request.headers.get("authorization") === `Bearer ${identifier}`; * }); * ``` * * @param outboxPath The URI path pattern for the outbox. The syntax is based * on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The * path must have one variable: `{identifier}`. If an * outbox dispatcher is configured, this path must match * the outbox dispatcher path. * @returns An object to register outbox listeners. * @throws {RouterError} Thrown if the path pattern is invalid. * @since 2.2.0 */ setOutboxListeners(outboxPath: `${string}${Rfc6570Expression<"identifier">}${string}`): OutboxListenerSetters<TContextData>; /** * Registers a following collection dispatcher. * @param path The URI path pattern for the following collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A following collection callback to register. * @returns An object with methods to set other following collection * callbacks. * @throws {RouterError} Thrown if the path pattern is invalid. */ setFollowingDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Actor | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a followers collection dispatcher. * @param path The URI path pattern for the followers collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A followers collection callback to register. * @returns An object with methods to set other followers collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setFollowersDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Recipient, Context<TContextData>, TContextData, URL>): CollectionCallbackSetters<Context<TContextData>, TContextData, URL>; /** * Registers a liked collection dispatcher. * @param path The URI path pattern for the liked collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A liked collection callback to register. * @returns An object with methods to set other liked collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setLikedDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Object$1 | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a featured collection dispatcher. * @param path The URI path pattern for the featured collection. The syntax * is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A featured collection callback to register. * @returns An object with methods to set other featured collection * callbacks. * @throws {@link RouterError} Thrown if the path pattern is invalid. */ setFeaturedDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Object$1, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>; /** * Registers a featured tags collection dispatcher. * @param path The URI path pattern for the featured tags collection. * The syntax is based on URI Template * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path * must have one variable: `{identifier}`. * @param dispatcher A featured tags collection callback to register. * @returns An obje