Files
2026-05-27 23:29:53 +01:00

4.7 KiB

Tasks: enterprise-server-health-check

Change ID: enterprise-server-health-check Package: @suaveplan/health-check Target path: server/infra/health-check Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/logger


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree per proposal.md.
  • package.json at 0.1.0, "sideEffects": false, exports "." + registry + server subpaths.
  • Deps: @suaveplan/error workspace:^, @suaveplan/types workspace:^, @suaveplan/logger workspace:^, zod catalog:forms, @opentelemetry/api catalog:observability, tslib catalog:build.
  • DevDeps: vitest catalog:testing, @vitest/coverage-istanbul catalog:testing, @suaveplan/testing workspace:^.
  • tsconfig.json extending library-node.json; vitest.config.ts with createTestConfig().
  • Scripts: lint, typecheck, test, test:coverage, build, docs:check.

2. Types and errors

  • Define all interfaces and Zod schemas in src/types/health-check.types.ts.
  • Write health-check.types.md (≥200 words, both examples, API reference).
  • src/error-codes.ts: three codes; registerHealthCheckErrorCodes(); eager call.

3. Health registry

  • Implement HealthRegistry in src/registry/health-registry/health-registry.ts:
    • register(name, check, options): store in internal Map; throw if name already registered.
    • unregister(name): remove; throw HEALTH_CHECK_NOT_FOUND if absent.
    • runAll(): run all registered checks concurrently (via Promise.allSettled); each with AbortSignal tied to timeout; collect CheckResult; compute overall status (any critical failure → unhealthy; any non-critical failure → degraded; all pass → healthy). Return HealthReport.
    • runCheck(name): run single check with timeout; update cache; return CheckResult.
    • Cache: store last CheckResult per check; on runCheck/runAll return cached if within cacheTtlMs.
    • OTel counter health_check.runs_total with check_name and status; histogram health_check.duration_ms.
  • Write health-registry.types.ts.
  • Write health-registry.test.ts (≤500 lines): all checks healthy; one critical fails; one non-critical fails (degraded); timeout triggers; cache TTL respected with FakeClock; unregister removes.
  • Write health-registry.md (≥200 words, simple + advanced, API reference).

4. Health server

  • Implement HealthServer in src/server/health-server/health-server.ts:
    • Use Bun.serve to create a minimal HTTP server.
    • GET /health: run all checks; return JSON HealthReport; HTTP 200 if healthy/degraded, 503 if unhealthy.
    • GET /ready: same logic but only return 503 if any critical check fails.
    • GET /live: always return 200 { status: 'alive' } (liveness = process is running).
    • start() / stop() lifecycle.
    • OTel counter health_server.requests_total with endpoint and status_code.
  • Write health-server.types.ts.
  • Write health-server.test.ts (≤500 lines): HTTP 200 on all healthy; HTTP 503 on critical failure; custom paths; /live always 200; stop closes server; { timeout: 10000 }.
  • Write health-server.md (≥200 words, simple + advanced, API reference).

5. Integration tests

  • tests/integration.test.ts: real server on random port; fetch /health, /ready, /live; register a DB check that simulates failure; verify 503 on /health; { timeout: 15000 }.

6. Docs + verify + publish

  • Root README.md: Kubernetes probe configuration snippet, quick-start, API table.
  • bunx turbo lint --filter=@suaveplan/health-check — zero errors.
  • bunx turbo typecheck --filter=@suaveplan/health-check — zero errors.
  • bunx turbo test --filter=@suaveplan/health-check — all pass.
  • bunx turbo test:coverage --filter=@suaveplan/health-check — 100%.
  • bun scripts/publish.ts --package @suaveplan/health-check.
  • Update CLAUDE.md; archive to openspec/archive/2026-04-24-enterprise-server-health-check/.