import type { FastifyPluginAsync } from "fastify"; import type { CollectorStore } from "../store.js"; /** * **Declarative panel specs** (#315, ADR 0051 §7, design sketch §G.3): the * panels an agent pins to the dashboard when an answer is worth keeping. * * A fourth metadata surface beside `routes/metadata.ts`, with the same rules — * writes need `annotate`, reads need `query`, the project comes from the key, * every write is audited by the app-level hook, and the store bounds the row * count per project and answers `409` when it is full. * * ## Why a spec rather than a panel module * * ADR 0041 can load a *remote panel module* at runtime, and is explicit about * the cost: such a module runs with the dashboard's full privileges, which is * why it is off by default and guarded by an origin allowlist. A panel an LLM * wrote would be exactly that. So what is stored here is **data** — a metric * id, a chart name, some column names — and the dashboard renders it with the * panel components it already ships. Pinning a panel widens the dashboard's * trust boundary by nothing, and ADR 0041's decision is left where it is. * * ## Validated twice, for two different questions * * 1. `panelSpecV1Schema` (`@uptimizr/schema`) — is this a well-formed spec? A * known chart name, bounded strings, a closed query grammar, no unknown keys. * 2. `validatePanelSpec` (`@uptimizr/metrics`) — will it *draw anything*? Does * the metric exist and accept these filters, does the chart suit its grain, * do the encoding columns exist in its result. * * The second is the one that matters here, and the reason it runs at pin time * rather than at render time: a pinned panel is read weeks after it is written, * and a line chart with no axis to walk along does not fail — it draws * *something*, which somebody then reads as a trend. The moment anybody is * paying attention is the moment the panel is pinned, so that is where the * refusal belongs. The rejection is `400 { error, issues }` — the same body * `POST /api/v1/query` answers with, carrying the validator's issue codes — so * a client can fix the spec from the response instead of guessing. */ interface Options { store: CollectorStore; } export declare const panelRoutes: FastifyPluginAsync; export {}; //# sourceMappingURL=panels.d.ts.map