# OpenSpec Change: enterprise-server-health-check - **Change ID**: enterprise-server-health-check - **Package**: `@suaveplan/health-check` - **Category**: server/infra - **Target path**: `server/infra/health-check` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/health-check.md` --- ## Summary Deliver `@suaveplan/health-check` on the genesis branch from scratch at enterprise quality. The package provides a framework-agnostic health check system that exposes `/health`, `/ready`, and `/live` HTTP endpoints following Kubernetes probe conventions. A `HealthRegistry` holds named `HealthCheck` functions; an `HealthServer` runs a lightweight HTTP server returning structured JSON responses. Individual checks can have configurable timeouts, retry counts, and cache TTLs. Genesis adds Zod schemas, `@suaveplan/error` codes, OTel counters per check result, structured logging, and 100% test coverage via both unit and integration tests. --- ## Current-state audit (genesis) Does not exist on genesis — fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | Typed `HEALTH_CHECK.*` error codes | | `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock` | | `@suaveplan/logger` (`workspace:^`) | Structured logs | | `zod` (`catalog:forms`) | Options validation | | `@opentelemetry/api` (`catalog:observability`) | Counters + histograms | | `tslib` (`catalog:build`) | Runtime helpers | --- ## Public API surface ```ts class HealthRegistry { register(name: string, check: HealthCheckFn, options?: CheckOptions): void unregister(name: string): void runAll(): Promise runCheck(name: string): Promise } class HealthServer { constructor(registry: HealthRegistry, options?: HealthServerOptions) start(): Promise stop(): Promise address(): { host: string; port: number } | undefined } function createHealthRegistry(): HealthRegistry function createHealthServer(registry: HealthRegistry, options?: HealthServerOptions): HealthServer type HealthCheckFn = (signal: AbortSignal) => Promise // throws = unhealthy interface CheckOptions { timeout?: number // ms, default: 5000 critical?: boolean // if true, failure marks overall status 'unhealthy' cacheTtlMs?: number // reuse last result for this duration } interface CheckResult { name: string status: 'healthy' | 'unhealthy' | 'degraded' duration: number // ms error?: string cachedAt?: number } interface HealthReport { status: 'healthy' | 'unhealthy' | 'degraded' checks: CheckResult[] timestamp: number } interface HealthServerOptions { port?: number // default: 3001 host?: string // default: '0.0.0.0' path?: { health?: string // default: '/health' ready?: string // default: '/ready' live?: string // default: '/live' } logger?: LoggerLike } type HealthCheckErrorCode = | 'HEALTH_CHECK_TIMEOUT' | 'HEALTH_CHECK_NOT_FOUND' | 'HEALTH_SERVER_START_FAILED' function registerHealthCheckErrorCodes(): void ``` --- ## File layout ```text server/infra/health-check/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/index.ts types/ health-check.types.ts health-check.types.md registry/ health-registry/ health-registry.ts health-registry.md health-registry.types.ts health-registry.test.ts index.ts server/ health-server/ health-server.ts health-server.md health-server.types.ts health-server.test.ts index.ts tests/ integration.test.ts ``` --- ## Impact Downstream: all server packages use `@suaveplan/health-check` to register their own checks. This is a core infrastructure primitive. **Prerequisites on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`.