import type { FastifyPluginAsync } from "fastify"; import type { CollectorConfig } from "../config.js"; import type { CollectorStore } from "../store.js"; import { type ConnectionLimiter } from "../connectionLimiter.js"; import type { SubscriptionScheduler } from "../subscriptions/scheduler.js"; import type { SubscriptionStream } from "../subscriptions/stream.js"; /** * **Conditional subscriptions API** — `/api/v1/subscriptions` (#311, ADR 0051 * §6 / sketch §F.1–F.3). * * Its own plugin, registered with one line in `app.ts`, for the same reason * `insights.ts` is: it is a different *kind* of surface from the aggregate reads * — a small CRUD resource plus an SSE stream, with its own error vocabulary and * its own capability split. * * ## The capability split * * Reads (`GET`) need `query`: a subscription is project configuration, and a key * that can read the project's telemetry can read what it is watching for. * **Writes need `annotate`** (ADR 0051 §7) — the same grant the metadata write * path uses — because creating a subscription is how an agent asks the collector * to make an outbound request on its behalf. A plain `query` key cannot do that. * * ## Secrets * * A webhook `secret` is accepted on create and never returned again: every read * answers with a masked placeholder (`@uptimizr/db`'s `MASKED_SECRET`). There is * no rotate endpoint on purpose — replacing the subscription is one call, and it * makes the change visible in the listing rather than silent. * * ## The SSE stream * * `GET /api/v1/subscriptions/stream?token=…` uses the live-token model of * ADR 0032 §7 (an `EventSource` cannot send `x-api-key`) and shares the live * endpoints' connection budget, because it is the same kind of held-open socket * and the same kind of memory. */ interface Options { store: CollectorStore; config: CollectorConfig; scheduler: SubscriptionScheduler; stream: SubscriptionStream; /** * The collector-wide SSE connection budget, shared with the live endpoints * (ADR 0032 §6): this stream is the same kind of held-open socket, so one * counter serves both and `LIVE_MAX_CONNECTIONS` bounds the total. */ connections?: ConnectionLimiter; } export declare const subscriptionRoutes: FastifyPluginAsync; export {}; //# sourceMappingURL=subscriptions.d.ts.map