import type * as app_Webhooks from '../apps/data/routes/webhooks.js'; import type * as Db from '../db/Db.js'; import * as WebhookQueueCompletions from '../db/tables/webhookQueueCompletions.js'; import * as WebhookQueueEvents from '../db/tables/webhookQueueEvents.js'; import * as WebhookSubscriptions from '../db/tables/webhookSubscriptions.js'; import type * as Metrics from '../Metrics.js'; import * as MetricSink from './MetricSink.js'; import * as WebhookDestination from './WebhookDestination.js'; export type { Destination, Result } from './WebhookDestination.js'; export { InvalidUrlError, sign, signatureHeader, verify } from './WebhookDestination.js'; /** * Event types a subscription can listen to. The canonical set lives in the apps * layer ({@link app_Webhooks.eventTypes}), co-located with the per-type schemas * and descriptions that reference apps-layer read schemas; this storage layer * only consumes the type. */ export type EventType = app_Webhooks.EventType; /** Lifecycle status of a subscription. */ export type Status = 'active' | 'disabled' | 'paused'; /** * Authenticated owner of a subscription. Derived from the request principal: * API keys are org-scoped; MPP payers are identified by their stable DID. */ export type Owner = { /** Owning organization id (any key in the org manages its webhooks). */ orgId: string; /** Owner kind. */ type: 'api_key'; } | { /** Verified MPP payer identifier (e.g. `did:pkh:…`). */ payer: string; /** Owner kind. */ type: 'mpp'; }; /** API-key scope applied when managing private-resource subscriptions. */ export type Access = { /** API-key environment. */ environment: 'production' | 'sandbox'; /** Project attribution, when the key is project-scoped. */ projectId?: string | undefined; /** API-key scopes used to authorize private resource reads. */ scopes: readonly string[]; }; /** * Optional human context describing what a subscription is for. Carried onto * every delivered {@link Envelope} and surfaced by destinations (Slack header + * description, Better Stack log fields, and the raw `url` payload). */ export type Context = { /** Longer description of the subscription's purpose. */ description?: string | undefined; /** Arbitrary key/value labels echoed on every delivery and rendered by destinations. */ metadata?: Record | undefined; /** Short label for the subscription (e.g. `Prod USDC large transfers`). */ title?: string | undefined; }; /** A durable webhook subscription record. */ export type Subscription = { /** Chain the subscription listens on. */ chainId: number; /** Optional human context describing what the subscription is for. */ context?: Context | undefined; /** ISO timestamp of creation. */ createdAt: string; /** Where matched events are delivered (URL or Slack channel). */ destination: WebhookDestination.Destination; /** API-key environment captured when the subscription was created. */ environment?: 'production' | 'sandbox' | undefined; /** Event type the subscription listens to. */ eventType: EventType; /** ISO expiry timestamp; set for MPP-owned subscriptions (TTL-bounded). */ expiresAt?: string | undefined; /** Consecutive delivery failures; drives auto-disable. */ failureCount: number; /** Event-type-specific filter predicates. */ filters: Record; /** Subscription id (`wh_…`). */ id: string; /** ISO timestamp of the last successful delivery, if any. Display only: * refreshed at most once per precision window. */ lastDeliveryAt?: string | undefined; /** Authenticated owner. */ owner: Owner; /** Project attribution captured from the creating API key. */ projectId?: string | undefined; /** HMAC signing secret. Returned once at creation; never exposed by reads. */ secret: string; /** Lifecycle status. */ status: Status; /** ISO timestamp of the last mutation. May lag repeat deliveries; see * `lastDeliveryAt`. */ updatedAt: string; }; /** Fields accepted when creating a subscription. */ export type CreateInput = { /** Chain to listen on. */ chainId: number; /** Optional human context describing what the subscription is for. */ context?: Context | undefined; /** Where matched events are delivered. `url` destinations are SSRF-validated. */ destination: WebhookDestination.Destination; /** API-key environment used to isolate private resource events. */ environment?: 'production' | 'sandbox' | undefined; /** Event type to listen to. */ eventType: EventType; /** Event-type-specific filter predicates. */ filters?: Record | undefined; /** Owner derived from the request principal. */ owner: Owner; /** Project attribution used to isolate private resource events. */ projectId?: string | undefined; /** Time-to-live in milliseconds; set the subscription to expire (MPP TTL). */ ttl?: number | undefined; }; /** Mutable fields accepted when patching a subscription. */ export type PatchInput = { /** New human context, or `null` to clear it. */ context?: Context | null | undefined; /** New delivery destination. `url` destinations are re-validated for SSRF. */ destination?: WebhookDestination.Destination | undefined; /** New filter predicates. */ filters?: Record | undefined; /** New lifecycle status (`active`/`paused`/`disabled`). */ status?: Status | undefined; }; /** Outcome status of a delivery-log row. */ export type DeliveryStatus = 'failed' | 'pending' | 'succeeded'; /** * A durable delivery-log row recording one delivery attempt. Persisted by * {@link deliverAndRecord} so deliveries are observable and replayable (Phase * C); the read endpoint returns these verbatim. */ export type Delivery = { /** Consecutive attempt number (1-based) at the time of this delivery. */ attempt: number; /** ISO timestamp the attempt was recorded. */ createdAt: string; /** * The exact envelope that was sent, persisted so the delivery can be replayed * verbatim (manual retry). Internal-only: the public delivery row omits it. */ envelope: Envelope; /** Failure reason when `status` is `failed`. */ error?: string | undefined; /** Idempotent event id this delivery carried (`evt_…`). */ eventId: string; /** Delivery id (`whd_…`); time-sortable so keys order chronologically. */ id: string; /** Subscriber callback URL the attempt targeted. */ requestUrl: string; /** Wall-clock duration of the attempt in ms, when a request was made. */ responseMs?: number | undefined; /** HTTP response status, when a response was received. */ responseStatus?: number | undefined; /** Outcome status. */ status: DeliveryStatus; /** Owning subscription id. */ subscriptionId: string; }; /** * Creates a subscription, validating its URL and (optionally) enforcing a * per-owner cap, then persists it. Capped writes serialize per owner so * concurrent requests cannot exceed the limit. */ export declare function createSubscription(db: Db.Db, input: CreateInput, options?: createSubscription.Options): Promise; export declare namespace createSubscription { /** Options for {@link createSubscription}. */ type Options = { /** Reject creation once the owner has this many live subscriptions. */ maxPerOwner?: number | undefined; /** Clock used for timestamps (injectable for tests). */ now?: (() => Date) | undefined; /** Chain head observed immediately before the subscription becomes visible. */ startBlockNumber?: number | undefined; }; } /** Reads a single subscription scoped to its owner. Returns null when absent. */ export declare function getSubscription(db: Db.Db, owner: Owner, id: string, options?: getSubscription.Options): Promise; export declare namespace getSubscription { /** Private-resource visibility options. */ type Options = { access?: Access | undefined; }; } /** * Lists an owner's subscriptions, newest first, with optional keyset paging. * Subscription ids embed a timestamp, so lexical id order is chronological. */ export declare function listSubscriptions(db: Db.Db, owner: Owner, options?: listSubscriptions.Options): Promise; export declare namespace listSubscriptions { /** Options for {@link listSubscriptions}. */ type Options = { /** Private-resource visibility scope. */ access?: Access | undefined; /** Return subscriptions older than this id (keyset paging, newest first). */ cursor?: string | undefined; /** Maximum subscriptions to return. */ limit?: number | undefined; /** Rows to skip from the head (positional pagination; exclusive with `cursor`). */ offset?: number | undefined; }; } /** * Counts an owner's subscriptions — a single indexed count, exact and cheap, * since the per-owner set is bounded by `maxPerOwner`. Feeds the opt-in * `meta.totalCount` on `GET /webhooks`. */ export declare function countSubscriptions(db: Db.Db, owner: Owner, options?: countSubscriptions.Options): Promise; export declare namespace countSubscriptions { /** Private-resource visibility options. */ type Options = { access?: Access | undefined; }; } /** * Patches an owner's subscription, re-validating the URL when changed. * Returns null when absent. The status column drives the partial active * index, so no secondary-index maintenance is needed. */ export declare function updateSubscription(db: Db.Db, owner: Owner, id: string, patch: PatchInput, options?: updateSubscription.Options): Promise; export declare namespace updateSubscription { /** Options for {@link updateSubscription}. */ type Options = { /** Private-resource visibility scope. */ access?: Access | undefined; /** Clock used for timestamps (injectable for tests). */ now?: (() => Date) | undefined; }; } /** Deletes an owner's subscription; its delivery rows cascade via the FK. */ export declare function deleteSubscription(db: Db.Db, owner: Owner, id: string, options?: deleteSubscription.Options): Promise; export declare namespace deleteSubscription { /** Private-resource visibility options. */ type Options = { access?: Access | undefined; }; } /** Reads every live active subscription on a chain in one query. */ export declare function listActiveForChain(db: Db.Db, options: listActiveForChain.Options): Promise<{ cursor: string | null; subscription: Subscription; }[]>; export declare namespace listActiveForChain { /** Filters for the chain-level subscription read. */ type Options = Pick; } /** Decodes the block component of a subscription cursor, if any. */ export declare function cursorBlock(cursor: string | null): number | undefined; /** Reads a subscription's keyset cursor. Returns null when unset. */ export declare function getCursor(db: Db.Db, subscriptionId: string): Promise; /** * Deletes expired MPP-owned subscriptions (delivery rows cascade) and * deliveries past retention. Reads already filter expiry at query time; this * is the janitor reclaiming space, run best-effort on a schedule. */ export declare function pruneExpired(db: Db.Db, options?: pruneExpired.Options): Promise; export declare namespace pruneExpired { /** Options for {@link pruneExpired}. */ type Options = { /** Clock used for expiry evaluation; injectable for tests. */ now?: (() => Date) | undefined; }; /** Rows deleted per table; a count pinned at the batch bound means expiry is outpacing pruning. */ type Result = { /** Deleted `webhook_queue_completions` rows. */ completions: number; /** Deleted `webhook_deliveries` rows. */ deliveries: number; /** Deleted `webhook_subscriptions` rows. */ subscriptions: number; }; } /** * Default delivery-log retention. Rows are written with this TTL so a busy * subscription's log doesn't grow unbounded; tune per deployment. */ export declare const deliveryRetentionMs: number; /** * Completions dedupe window: replays of a completed obligation are suppressed * this long. Deliberately its own literal so per-deployment log-retention * tuning cannot move it. */ export declare const dedupeRetentionMs: number; /** A compact Cloudflare Queue message referencing a durable staged envelope. */ export type QueueReference = { /** Idempotent event id of the staged envelope. */ eventId: string; /** Subscription that owns the staged envelope. */ subscriptionId: string; }; /** A full envelope staged outside Cloudflare Queues. */ export type QueueEvent = QueueReference & { /** ISO timestamp when the envelope was staged. */ createdAt: string; /** Full envelope loaded by the Queue consumer. */ envelope: Envelope; }; /** A claim newer than this counts as an in-flight attempt; above the 10s destination timeout default. */ export declare const deliveryAttemptStaleMs = 60000; /** * Retry backoff by attempt count: 5s, 25s, ~2m, ~10m, ~52m, then hourly. * Endpoint outages retry on this schedule until delivery or auto-disable. */ export declare function retryDelayMs(attemptCount: number): number; /** * Stages full envelopes as delivery obligations and returns compact * references safe for Queue admission. Existing rows are left untouched, so * the first staged envelope wins and terminal outcomes never resurrect. */ export declare function ensureQueueEvents(db: Db.Db, dispatchables: readonly ensureQueueEvents.Dispatchable[], options?: ensureQueueEvents.Options): Promise; export declare namespace ensureQueueEvents { /** One full envelope and the subscription that produced it. */ type Dispatchable = { /** Webhook envelope. */ envelope: Envelope; /** Subscription that owns the envelope. */ subscription: Subscription; }; /** Staging options. */ type Options = { /** Clock used for staging timestamps. */ now?: (() => Date) | undefined; /** Epoch ms the head owing these events was observed; absent on replays. */ observedAt?: number | undefined; }; /** Created-row count plus references for every requested obligation. */ type Result = { /** Newly staged obligations. */ created: number; /** Compact references for all inputs, including pre-existing rows. */ references: QueueReference[]; }; } /** Claims one due pending obligation; misses classify why the claim is unavailable. */ export declare function claimQueueEvent(db: Db.Db, reference: QueueReference): Promise; /** * Marks a claimed obligation terminal and restarts its retention window, so * the dedupe row outlives replays. Fenced by the claim marker: a stale * claimant's completion returns false instead of clobbering a newer claim. */ export declare function completeQueueEvent(db: Db.Db, reference: QueueReference, options: completeQueueEvent.Options): Promise; export declare namespace completeQueueEvent { /** Fenced terminal transition. */ type Options = { /** Claim marker from the claimed record's `attemptingAt`. */ claimedAt: string; /** Terminal obligation outcome. */ status: WebhookQueueCompletions.TerminalStatus; }; } /** * Releases a claim and schedules the next attempt on the retry backoff. * Fenced by the claim marker like {@link completeQueueEvent}. */ export declare function scheduleQueueEventRetry(db: Db.Db, reference: QueueReference, options: scheduleQueueEventRetry.Options): Promise; export declare namespace scheduleQueueEventRetry { /** Fenced retry scheduling. */ type Options = { /** Attempts claimed so far; drives the backoff position. */ attemptCount: number; /** Claim marker from the claimed record's `attemptingAt`. */ claimedAt: string; }; } /** Lists due pending references for the sweeper, oldest first. */ export declare function dueQueueEvents(db: Db.Db, limit: number): Promise; /** Returns the authoritative pending-obligation snapshot. */ export declare function pendingQueueEvents(db: Db.Db): Promise; /** Reads a full staged envelope for a compact Queue reference. */ export declare function getQueueEvent(db: Db.Db, reference: QueueReference): Promise; /** Loads a staged envelope and delivers it with the subscription's current configuration. */ export declare function deliverQueueEventAndRecord(db: Db.Db, reference: QueueReference, options?: deliverAndRecord.Options): Promise; /** * Delivers an already-loaded obligation envelope with the subscription's * current configuration, skipping the staged-row read a claim already paid. */ export declare function deliverClaimedAndRecord(db: Db.Db, claimed: deliverClaimedAndRecord.Claimed, options?: deliverClaimedAndRecord.Options): Promise; export declare namespace deliverClaimedAndRecord { /** Envelope and owning subscription id from a claimed obligation. */ type Claimed = { /** Immutable event envelope to deliver. */ envelope: Envelope; /** ISO head-observation stamp carried by the staged row; null on replays. */ observedAt?: string | null | undefined; /** Subscription re-resolved for current status and secret. */ subscriptionId: string; }; /** Delivery options plus the dequeue timestamp of the claiming path. */ type Options = deliverAndRecord.Options & { /** Epoch ms the claiming message was dequeued; defaults to now. */ dequeuedAt?: number | undefined; }; /** A delivered event or an inactive subscription. */ type Result = { /** Transport result from the current subscription state. */ result: WebhookDestination.Result; /** The envelope was delivered. */ status: 'delivered'; } | { /** The current subscription is inactive or deleted. */ status: 'skipped'; }; } export declare namespace deliverQueueEventAndRecord { /** A delivered event, inactive subscription, or stale duplicate reference. */ type Result = { /** Transport result from the current subscription state. */ result: WebhookDestination.Result; /** The staged event was delivered. */ status: 'delivered'; } | { /** The staged event or current subscription was not deliverable. */ status: 'missing' | 'skipped'; }; } /** Records one delivery-log row (stateful, owner-agnostic; scoped per subscription). */ export declare function recordDelivery(db: Db.Db, delivery: Delivery, options?: recordDelivery.Options): Promise; export declare namespace recordDelivery { /** Options for {@link recordDelivery}. */ type Options = { /** Row time-to-live in ms; defaults to {@link deliveryRetentionMs}. */ ttl?: number | undefined; }; } /** * Lists a subscription's delivery log, newest first, with optional keyset * paging. Delivery ids embed a timestamp, so lexical key order is chronological. */ export declare function listDeliveries(db: Db.Db, subscriptionId: string, options?: listDeliveries.Options): Promise; export declare namespace listDeliveries { /** Options for {@link listDeliveries}. */ type Options = { /** Return deliveries whose id sorts before this one (older entries). */ cursor?: string | undefined; /** Maximum deliveries to return. */ limit?: number | undefined; /** Rows to skip from the head (positional pagination; exclusive with `cursor`). */ offset?: number | undefined; }; } /** * Counts a subscription's delivery-log entries — a single indexed count, * exact, and bounded by the delivery retention window. Feeds the opt-in * `meta.totalCount` on `GET /webhooks/:id/deliveries`. */ export declare function countDeliveries(db: Db.Db, subscriptionId: string): Promise; /** Loads a single delivery-log row (`null` when absent), scoped to its subscription. */ export declare function getDelivery(db: Db.Db, subscriptionId: string, deliveryId: string): Promise; /** * Default number of consecutive delivery failures after which a subscription * auto-disables (and is dropped from the partial active index). */ export declare const maxFailures = 10; /** * Records a successful delivery: resets the consecutive-failure counter and * refreshes `lastDeliveryAt` at most once per precision window. Returns the * written row, or the caller's snapshot when the write was skipped or the row * deleted. */ export declare function recordSuccess(db: Db.Db, subscription: Subscription, options?: recordSuccess.Options): Promise; export declare namespace recordSuccess { /** Options for {@link recordSuccess}. */ type Options = { /** Clock used for timestamps; injectable for tests. */ now?: (() => Date) | undefined; }; } /** * Records a failed delivery: atomically increments the consecutive-failure * counter and, once it reaches `maxFailures`, sets `status: 'disabled'` so the * subscription drops out of the partial active index (surfaced via the API). * Once disabled at the cap the row is left alone, so an outage's in-flight * failures stop contending on its lock. Returns the written row, or the * caller's snapshot advanced optimistically. */ export declare function recordFailure(db: Db.Db, subscription: Subscription, options?: recordFailure.Options): Promise; export declare namespace recordFailure { /** Options for {@link recordFailure}. */ type Options = { /** Consecutive failures before auto-disabling (default {@link maxFailures}). */ maxFailures?: number | undefined; /** Clock used for timestamps; injectable for tests. */ now?: (() => Date) | undefined; }; } /** * Delivers an envelope to its subscription and records the outcome: success * resets the failure counter and stamps `lastDeliveryAt`; failure increments it * and auto-disables after {@link maxFailures}. This is the single delivery entry * point shared by the Cloudflare Queue consumer and the self-host inline path. */ export declare function deliverAndRecord(db: Db.Db, subscription: Subscription, envelope: Envelope, options?: deliverAndRecord.Options): Promise; export declare namespace deliverAndRecord { /** Options for {@link deliverAndRecord}. */ type Options = { /** * Delivery-log attempt number; the ledger claim count on the queue path. * Defaults to the subscription failure counter, which concurrent * deliveries can read stale. */ attempt?: number | undefined; /** Delivery-log row TTL in ms; defaults to {@link deliveryRetentionMs}. */ deliveryRetentionMs?: number | undefined; /** Queue dequeue time as epoch milliseconds, captured before subscription lookup. */ dequeuedAt?: number | undefined; /** `fetch` implementation passed through to {@link deliver}. */ fetch?: typeof globalThis.fetch | undefined; /** Consecutive failures before auto-disabling (default {@link maxFailures}). */ maxFailures?: number | undefined; /** Metrics backend; emits one `webhook:delivery` event per attempt. */ metrics?: Metrics.Metrics | undefined; /** Clock used for timestamps; injectable for tests. */ now?: (() => Date) | undefined; /** Epoch ms the head owing this event was observed; absent on replays. */ observedAt?: number | undefined; /** Cloudflare Queue delivery attempt, starting at one; absent for inline delivery paths. */ queueAttempt?: number | undefined; /** Queue enqueue time as epoch milliseconds, used to isolate queue wait. */ queuedAt?: number | undefined; /** Authoritative subscription lookup duration, supplied by the queue path. */ subscriptionReadMs?: number | undefined; /** Delivery timeout in ms passed through to {@link deliver}. */ timeoutMs?: number | undefined; /** Where this attempt originated; tags the `webhook:delivery` event (default `queue`). */ trigger?: MetricSink.Trigger | undefined; }; } /** * Re-resolves an enqueued subscription before delivery. Missing or inactive * subscriptions are skipped; delivery uses the current destination and secret. */ export declare function deliverCurrentAndRecord(db: Db.Db, queued: Subscription, envelope: Envelope, options?: deliverAndRecord.Options): Promise; export declare namespace deliverCurrentAndRecord { /** Authoritative delivery outcome, or a skipped stale queue message. */ type Result = { /** Transport result from the current subscription state. */ result: WebhookDestination.Result; /** The current subscription was delivered. */ status: 'delivered'; } | { /** The queued subscription is absent or inactive. */ status: 'skipped'; }; } /** * Computes a stable, idempotent event id from its on-chain coordinates so * re-deliveries are dedupable by the receiver. */ export declare function eventId(options: eventId.Options): string; export declare namespace eventId { /** Options for {@link eventId}. */ type Options = { /** Block number the event was indexed in. */ blockNumber: bigint | number | string; /** Chain the event occurred on. */ chainId: number; /** Event type. */ eventType: EventType; /** Log index within the block (or transaction index for transaction events). */ logIndex: bigint | number | string; }; } /** Computes a stable event id from an event-type-specific identity key. */ export declare function eventIdFromKey(options: eventIdFromKey.Options): string; export declare namespace eventIdFromKey { /** Stable identity inputs for a webhook event. */ type Options = { /** Chain the event belongs to. */ chainId: number; /** Event type. */ eventType: EventType; /** Stable event-type-specific identity. */ key: string; }; } /** The JSON envelope delivered to subscribers. */ export type Envelope = { /** Chain the event occurred on. */ chainId: number; /** Human context copied from the subscription, when set. */ context?: Context | undefined; /** ISO timestamp the envelope was built. */ createdAt: string; /** The same row shape the corresponding read endpoint returns. */ data: unknown; /** Stable, idempotent event id (`evt_…`). */ id: string; /** Originating subscription id. */ subscriptionId: string; /** Event type; `ping` marks a synthetic test delivery (see {@link buildPingEnvelope}). */ type: EventType | 'ping'; }; /** Builds a delivery envelope for an event matched against a subscription. */ export declare function buildEnvelope(options: buildEnvelope.Options): Envelope; export declare namespace buildEnvelope { /** Options for {@link buildEnvelope}. */ type Options = { /** Block number the event was indexed in. */ blockNumber: bigint | number | string; /** Timestamp to stamp on the envelope; defaults to now. */ createdAt?: Date | undefined; /** Decoded event row (same shape the read endpoint returns). */ data: unknown; /** Log index within the block. */ logIndex: bigint | number | string; /** Subscription the event matched. */ subscription: Subscription; }; } /** Builds a delivery envelope from a stable application-event identity. */ export declare function buildKeyedEnvelope(options: buildKeyedEnvelope.Options): Envelope; export declare namespace buildKeyedEnvelope { /** Application-event envelope fields. */ type Options = { /** Timestamp to stamp on the envelope; defaults to now. */ createdAt?: Date | undefined; /** Public event payload. */ data: unknown; /** Stable event-type-specific identity. */ key: string; /** Subscription the event matched. */ subscription: Subscription; }; } /** * Builds a synthetic `ping` envelope so an owner can test a subscription's * endpoint (connectivity, TLS, signature verification) without waiting for a real * on-chain event. The id is randomized per call so repeated pings are never * deduped by the receiver; `type` is `ping` and `data` is a recognizable * `{ ping: true }` marker rather than an event row, so receivers can tell a test * delivery apart from a real event. */ export declare function buildPingEnvelope(subscription: Subscription, options?: buildPingEnvelope.Options): Envelope; export declare namespace buildPingEnvelope { /** Options for {@link buildPingEnvelope}. */ type Options = { /** Timestamp to stamp on the envelope; defaults to now. */ createdAt?: Date | undefined; /** Deterministic nonce for the event id; defaults to random (tests only). */ nonce?: string | undefined; }; } /** * Delivers a synthetic {@link buildPingEnvelope} to a subscription's endpoint and * logs the attempt. Unlike {@link deliverAndRecord} it deliberately does NOT * touch the subscription's `failureCount`/`status`: a test ping must never * auto-disable a healthy subscription or reset a real failure streak. The * delivery row is still appended (best-effort) so the ping is observable via the * delivery log. */ export declare function ping(db: Db.Db, subscription: Subscription, options?: ping.Options): Promise; export declare namespace ping { /** Options for {@link ping}. */ type Options = { /** Delivery-log row TTL in ms; defaults to {@link deliveryRetentionMs}. */ deliveryRetentionMs?: number | undefined; /** `fetch` implementation passed through to {@link deliver}. */ fetch?: typeof globalThis.fetch | undefined; /** Deterministic event-id nonce; defaults to random (tests only). */ nonce?: string | undefined; /** Clock used for timestamps; injectable for tests. */ now?: (() => Date) | undefined; /** Delivery timeout in ms passed through to {@link deliver}. */ timeoutMs?: number | undefined; }; /** Outcome of a ping: the classified delivery result plus the logged row. */ type Result = { /** The delivery-log row that was recorded. */ delivery: Delivery; /** The synthetic envelope that was sent. */ envelope: Envelope; /** The classified transport result. */ result: WebhookDestination.Result; }; } export declare class LimitExceededError extends Error { /** The cap that was reached. */ limit: number; constructor(limit: number); } /** Thrown when an update would activate URL signing with an unrecoverable secret. */ export declare class InvalidDestinationTransitionError extends Error { constructor(); } /** * Thrown when a subscription's `filters` fail to validate against the schema for * its `eventType`. The detection path treats stored filters as **fail-closed**: * an invalid filter never degrades to a firehose, so the API rejects bad filters * at create/patch time rather than silently widening the match set later. */ export declare class InvalidFilterError extends Error { /** Event type whose filters failed validation. */ eventType: string; /** Per-field validation issues, suitable for an API error `details` array. */ details: readonly InvalidFilterError.Detail[]; constructor(eventType: string, details?: readonly InvalidFilterError.Detail[]); } export declare namespace InvalidFilterError { /** A single validation issue: a message plus the path to the invalid value. */ type Detail = { /** Human-readable validation message. */ message: string; /** Path to the invalid value within the `filters` object. */ path?: readonly (string | number)[] | undefined; }; } /** Thrown when webhook operations run without a configured state store. */ export declare class UnconfiguredError extends Error { constructor(); } //# sourceMappingURL=Webhooks.d.ts.map