/** * push/delivery.ts * * The single place a push message is actually encrypted and sent. Every send, * a `push.subscriptions.verify` test, or an approval/completion fan-out, flows * through `deliverToSubscription`, so the honesty rules live in one spot: * * - A push service that answers 404/410 means the browser subscription is gone; * the record is pruned and the receipt says `pruned`, never a fake success. * - Any other non-2xx (or a transport error) is reported as `failed` with the * status/reason, never swallowed into a success. * - The request carries the RFC 8188 `Content-Encoding: aes128gcm` body plus * the `TTL`, `Urgency`, and VAPID `Authorization` headers a push service * requires. * * The endpoint is whatever the browser registered. In tests that is a local * HTTP sink; in production it is the browser vendor's push service. This module * never contacts a hard-coded external service of its own. */ import type { VapidManager } from './vapid.js'; import type { PushSubscriptionStore } from './subscription-store.js'; import type { PushDeliveryReceipt, PushMessage, StoredPushSubscription } from './types.js'; /** The `fetch` slice used to POST an encrypted payload. Injectable for tests. */ export type PushTransport = (url: string, init: { method: string; headers: Record; body: Buffer; }) => Promise<{ status: number; }>; /** * Bounded retries before a dead endpoint that never answers 404/410 is pruned. * A push service that keeps returning 5xx/timeouts is treated as gone once the * consecutive-failure counter crosses this bound, reported as an honest `pruned` * receipt rather than an endless string of `failed`s. */ export declare const DELIVERY_FAILURE_PRUNE_THRESHOLD = 5; export interface DeliveryDeps { readonly vapid: VapidManager; readonly store: PushSubscriptionStore; readonly transport?: PushTransport | undefined; /** * Consecutive refused deliveries after which the endpoint is treated as dead. * Absent ⇒ {@link DELIVERY_FAILURE_PRUNE_THRESHOLD}. The composition root * wires it to `push.subscriptions.failureThreshold`, the same key the * subscription sweep reads, so delivery and housekeeping cannot disagree * about when a push service has proved an endpoint gone. */ readonly failureThreshold?: number | undefined; } /** * Encrypt and send one message to one subscription, prune-on-gone, and return * an honest receipt. The subscription's `lastOutcome` is stamped either way. */ export declare function deliverToSubscription(subscription: StoredPushSubscription, message: PushMessage, deps: DeliveryDeps): Promise; /** * Fan one message out to every stored subscription, delivering (and pruning) in * sequence. Returns one receipt per subscription, an empty array when there * are no subscriptions at all (the honest "nobody to notify" result, not a * silent success). */ export declare function deliverToAll(message: PushMessage, deps: DeliveryDeps): Promise; //# sourceMappingURL=delivery.d.ts.map