/** * Self-description routes (ADR 0051 §1, design sketch §A.2). * * `GET /api/v1/openapi.json` serves an **OpenAPI 3.1** document for the read * API, assembled from two sources that are already the truth: * * 1. the **metric registry** (`@uptimizr/metrics`) — one path per registered * `endpoint`, the operation's summary/description/tags, the `200` response * schema (the registry `row` converted with `z.toJSONSchema`), per-column * units and descriptions, and the semantics OpenAPI has no vocabulary for * (result grain, group-by dimensions, caveats, capture channels, row caps, * comparison direction) as `x-uptimizr-*` vendor extensions; * 2. the **live Fastify route table** — every parameter's JSON Schema is the Zod * querystring/params schema that actually validates the request, captured * through an `onRoute` hook. Nothing about a parameter's *type* is restated * here, so the document cannot drift from the validator; the registry * supplies the parameter's *meaning* (`FILTER_TARGETS`). * * The document is **not authenticated** — it is documentation, it contains no * project data, and a client needs it before it has credentials. It is served * under the same global rate limit as every other route (`app.register(rateLimit)` * in `app.ts`). * * Routes that are not registry metrics are described only when they are trivial * and honest to describe (`/health`, this route, the scene-representation * listing, and the `metadata` group of #310 — annotations, glossary, saved * analyses — whose bodies are converted from the Zod contracts that validate * them). Ingestion (`POST /api/v1/collect`), the scene-proxy write * (`PUT …/representation`), the retention-gated raw event stream and the live * SSE surface are deliberately omitted rather than half-described. * listing, and the conditional-subscription resource). Ingestion * (`POST /api/v1/collect`), the scene-proxy write (`PUT …/representation`), the * retention-gated raw event stream and every SSE surface — the live endpoints * and `GET /api/v1/subscriptions/stream` alike — are deliberately omitted rather * than half-described: a hijacked `text/event-stream` response is not an * operation with a JSON body, and pretending otherwise misleads a generated * client. * * Conditional subscriptions (#311) are the one **write** surface described here. * They earn it: they are a CRUD resource rather than a query, and the only place * a caller needs a written contract for a request *body* — a closed Zod union * that cannot be inferred from a querystring. */ import type { FastifyInstance, FastifyPluginAsync } from "fastify"; import { z } from "zod"; /** A minimal OpenAPI document shape — enough to build and serve one. */ export type OpenApiDocument = Record; /** One route as Fastify registered it, with its Zod schemas (if any). */ export interface RouteSchemaEntry { method: string; /** Fastify path, `:param` placeholders included. */ path: string; querystring?: z.ZodObject; params?: z.ZodObject; } export interface MetaRoutesOptions { /** * The collector's route table, captured by {@link collectRouteSchemas} before * the other route plugins were registered. */ routeSchemas: readonly RouteSchemaEntry[]; } /** * Install an `onRoute` hook that records every route registered on `app` (and on * any plugin registered into it afterwards) together with its Zod schemas. * Returns the array the hook fills in — it is complete once `app.ready()` has * resolved, which is always before the first request is served. */ export declare function collectRouteSchemas(app: FastifyInstance): RouteSchemaEntry[]; /** * Build the OpenAPI 3.1 document for the read API from the metric registry and * the collector's own route table. Pure: it reads definitions only, never the * store, so it can be built once and served as a constant. */ export declare function buildOpenApiDocument(routeSchemas?: readonly RouteSchemaEntry[]): OpenApiDocument; /** * Meta routes: the generated OpenAPI document. Registered last in `app.ts` so * `routeSchemas` is already populated when the document is built. */ export declare const metaRoutes: FastifyPluginAsync; //# sourceMappingURL=meta.d.ts.map