| 01-data-foundation |
01 |
database |
| supabase |
| postgresql |
| migrations |
| typescript |
| monitoring |
| health-checks |
| alerts |
|
|
| service_health_checks table with status CHECK constraint, JSONB probe_details, checked_at column |
| alert_events table with alert_type/status CHECK constraints, lifecycle timestamps |
| HealthCheckModel TypeScript class with CRUD static methods |
| AlertEventModel TypeScript class with CRUD static methods |
| Barrel exports for both models and their types from models/index.ts |
|
| 01-02 (Phase 1 Plan 2 — next data foundation plan) |
| Phase 2 (health probe services will write to service_health_checks) |
| Phase 2 (alert service will write to alert_events and use findRecentByService for deduplication) |
| Phase 3 (API endpoints will query both tables) |
|
| added |
patterns |
|
|
| Static class model pattern (no instantiation — all methods are static async) |
| getSupabaseServiceClient() called per-method, never cached at module level |
| PGRST116 error code handled as null return (not an exception) |
| Input validation in model create() methods before any DB call |
| Record<string, unknown> for JSONB fields (no any types) |
| Named Winston logger import |
| import { logger } from '../utils/logger' |
|
| IF NOT EXISTS on all DDL (idempotent forward-only migrations) |
| TEXT + CHECK constraint pattern for enums (not PostgreSQL ENUM types) |
|
|
| created |
modified |
| backend/src/models/migrations/012_create_monitoring_tables.sql |
| backend/src/models/HealthCheckModel.ts |
| backend/src/models/AlertEventModel.ts |
|
| backend/src/models/index.ts |
|
|
| TEXT + CHECK constraint used for status/alert_type columns (not PostgreSQL ENUM types) — consistent with existing project pattern |
| getSupabaseServiceClient() called per-method (not module-level singleton) — follows Research finding about Cloud Function cold start issues |
| checked_at column added to service_health_checks separate from created_at — records actual probe run time, not DB insert time |
| Forward-only migration only (no rollback scripts) — per user decision documented in CONTEXT.md |
| RLS enabled on both tables with no explicit policies — service role key bypasses RLS; user-facing policies deferred to Phase 3 |
|
| Model static class: all methods static async, getSupabaseServiceClient() per-method, PGRST116 → null |
| Input validation before Supabase call: non-empty string check, union type allowlist check |
| Error re-throw with method prefix: 'HealthCheckModel.create: ...' for log traceability |
| deleteOlderThan(days): compute cutoff in JS then filter with .lt() — Supabase client does not support date arithmetic in filters |
|
|
8min |
2026-02-24 |