# health ## Purpose Defines Zod schemas for the admin health check endpoint (`GET /admin/health`). The health endpoint exposes a structured view of the service's operational status — both an aggregate roll-up and per-subsystem detail — so that load balancers, container orchestrators, and monitoring dashboards can make informed routing and alerting decisions without parsing unstructured text responses. ## Features - `HealthStatus` enum schema — `"ok" | "degraded" | "down"` covering the full range of operational states - `HealthCheck` object schema — per-subsystem check with status, optional latency measurement, and optional message - `AdminHealthOutput` schema — aggregate `status` plus a `checks` record keyed by subsystem name (non-empty keys) - `latencyMs` validated as a non-negative number — negative latency is not physically meaningful - Full TypeScript inference via `z.infer<>` — no manual interface duplication - Zod v4 compatible ## Usage: Basic Example ```ts import { AdminHealthOutput } from "@suaveplan/api-schemas/admin"; const health = AdminHealthOutput.parse({ status: "ok", checks: { database: { status: "ok", latencyMs: 3 }, cache: { status: "ok", latencyMs: 1 }, }, }); ``` ## Usage: Advanced Example ```ts import { AdminHealthOutput, HealthStatus } from "@suaveplan/api-schemas/admin"; async function collectHealth(): Promise { const dbLatency = await measureDbPing(); const cacheLatency = await measureCachePing(); const checks = { database: { status: dbLatency < 100 ? "ok" : "degraded" as HealthStatus, latencyMs: dbLatency }, cache: { status: cacheLatency < 10 ? "ok" : "degraded" as HealthStatus, latencyMs: cacheLatency }, }; const anyDown = Object.values(checks).some((c) => c.status === "down"); const anyDegraded = Object.values(checks).some((c) => c.status === "degraded"); const status: HealthStatus = anyDown ? "down" : anyDegraded ? "degraded" : "ok"; return AdminHealthOutput.parse({ status, checks }); } ``` ## API Reference ### `HealthStatus` Zod enum: `"ok" | "degraded" | "down"`. **Type export:** `type HealthStatus = z.infer` ### `HealthCheck` Zod object schema — single subsystem check result. | Field | Type | Description | |-------------|----------------------|--------------------------------------------------| | `status` | `HealthStatus` | Status of this individual check | | `latencyMs` | `number` (≥ 0) | Round-trip latency; omit when not measured | | `message` | `string` | Optional human-readable context | **Type export:** `type HealthCheck = z.infer` ### `AdminHealthOutput` Zod object schema — health endpoint response. | Field | Type | Description | |----------|-------------------------------------|-----------------------------------------------| | `status` | `HealthStatus` | Aggregate service status | | `checks` | `Record` | Keyed map of subsystem check results | **Type export:** `type AdminHealthOutput = z.infer` ## Implementation Notes The aggregate `status` should be the worst of all individual check statuses — if any check is `"down"` the aggregate should be `"down"`; if any is `"degraded"` and none are `"down"` the aggregate should be `"degraded"`. This roll-up logic belongs in the route handler, not the schema. The `checks` record uses `z.record(z.string().min(1), ...)` to enforce non-empty subsystem names, preventing accidental empty-string keys that would make the map structure ambiguous.