import type { RequestHandler } from '@sveltejs/kit'; import type { AuthLogger, RateLimitConfig } from '../../../types.js'; import type { PushSubscriptionRepository } from '../../adapters/types.js'; export interface PushSubscriptionHandlerOptions { /** * Restrict accepted push endpoints to hosts matching one of these suffixes * (e.g. `['fcm.googleapis.com', 'push.apple.com', 'updates.push.services.mozilla.com']`). * `'push.apple.com'` also matches `web.push.apple.com`. When omitted, any * HTTPS endpoint to a public host is accepted. The HTTPS + private-range SSRF * guard always applies regardless. */ allowedEndpointHosts?: string[]; /** * Rate limit for `POST`, keyed by the authenticated user id — the endpoint * requires a session, and a per-user key can't be dodged by rotating IPs. * Subscribing is a rare user action, so the default of 10/min is generous * for real use and a wall for scripted abuse. Pass `null` to disable. * * `DELETE` is not limited and does not draw on this budget: it removes a row * the caller already owns, which is the clause of the package's rule for * authenticated writes that carries no limit (AUTH.md → Rate-Limiting, * Lockout & Route Scope). `POST` is limited because it creates or reassigns * one. */ rateLimit?: RateLimitConfig | null; /** * Upper bound on stored subscriptions per user — a cost guard: every stored * row is a network fetch on every push send to that user. The cap applies * only to endpoints not yet registered for the user; re-subscribing an * existing endpoint (the browser's normal case) always passes. Exceeding it * answers `409`. Default 10 (≈ a device fleet, not a script). The check is * read-then-write and therefore approximate under concurrency — fine for a * cost guard. */ maxSubscriptionsPerUser?: number; /** * Sink for the two write outcomes worth an operator's attention: * `'rejected'` (warn — an authenticated account presented a foreign * endpoint with non-matching keys, i.e. someone is replaying endpoint URLs * they don't own) and `'reassigned'` (a push channel moved between * accounts with key possession proven — legitimate, but the previous * owner's channel just went quiet, so it should be correlatable). * Defaults to `console`; calls are shielded. Endpoint URLs are never * logged (capability discipline) — only the acting user id. */ logger?: AuthLogger; } export declare function createPushSubscriptionHandler(repo: PushSubscriptionRepository, options?: PushSubscriptionHandlerOptions): { POST: RequestHandler; DELETE: RequestHandler; };