Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

01 - Product Overview (Health Module)

StudyLyon - multi-tenant ERP / School Management API. This package designs the Health module client (Flutter, forward-looking spec) against the implemented NestJS backend. All endpoints, indicator keys, wire contracts, rate limits and auth posture are derived directly from src/modules/health/**, src/app/app.module.ts, src/common/guards/rate-limit.constants.ts, src/common/interceptors/response-envelope.interceptor.ts, src/common/filters/http-exception.filter.ts, src/modules/rbac/permissions.constants.ts and docs/IMPLEMENTATION_PLAN.md. No feature is invented - anything not present in source is flagged (planned) / (proposed) / (forward-looking).

Heads-up: per the PRD, the mobile client is out of Phase 1 scope (PRODUCT_REQUIREMENTS_DOCUMENT.md:144 - "Native mobile apps (web-first)"); this package is the forward-looking spec the client will be built against later. The health endpoint itself is a machine-to-machine surface first: it exists for load balancers, orchestrators and uptime probes, and only secondarily for humans.


1. Purpose

The health module exposes a single Terminus-powered check endpoint that reports the reachability of the API's runtime dependencies in one round-trip:

  • GET /api/v1/health - combined check of four indicators (health.controller.ts:27-37): MongoDB ping, Redis PING, storage provider reachability probe, and BullMQ queue accessibility with pending-job counts.
  • Status model - Terminus HealthCheckResult shape: status (ok|error), info, error, details; individual dependencies report up/down (health.controller.spec.ts:21-36).
  • HTTP semantics - 200 when every dependency is up; 503 (ServiceUnavailableException raised by @HealthCheck) when any is down.
  • Public by design - @Public() bypasses the JWT/RBAC global guards (health.controller.ts:15, app.module.ts:129-131); rate-limited to 30 req/min on the public tier (health.controller.ts:16, rate-limit.constants.ts:4, IMPLEMENTATION_PLAN.md:48).
ResponsibilitySource
Terminus registrationhealth.module.ts:8-17 (imports TerminusModule, declares 3 custom indicators)
Combined check endpointhealth.controller.ts:27-37
MongoDB indicatorTerminus MongooseHealthIndicator.pingCheck('mongodb'), health.controller.ts:32
Redis indicator (PING)redis-health.indicator.ts:12-23
Storage indicator (provider probe)storage-health.indicator.ts:16-26, storage-provider.ts:21-27
BullMQ indicator (4 queues, job counts)bullmq-health.indicator.ts:19-37, queue.constants.ts:2,5,14, dlq.constants.ts:1
Module wiringapp.module.ts:87
Public tier rate limitrate-limit.constants.ts:4, IMPLEMENTATION_PLAN.md:48

2. Business goals

GoalMeasure
One-probe dependency visibilityall 4 indicators answered in a single request (health.controller.ts:31-36)
Orchestrator-ready signals200 on status: 'ok', 503 on any down (Terminus @HealthCheck behavior)
No auth overhead for probes@Public() bypass (health.controller.ts:15); load balancers need no tokens
Abuse containment30 req/min sliding-window, Redis-backed (rate-limit.constants.ts:4)
Partial-failure detailerror + details keys distinguish which dependency failed while others stay up (health.controller.spec.ts:29-35)

3. User goals

  • Platform / DevOps engineer: one curl-able endpoint that says whether the API, DB, Redis, object storage and background queues are reachable, and which one is not when something is.
  • Support engineer: a fast "is it us or is it them?" signal before opening tickets.
  • School admin (forward-looking): a visual "App Health" screen in the admin surface that mirrors the endpoint as status cards, with the option to re-check manually - (proposed) throughout this package.

4. Scope

4.1 In scope (implemented backend)

Single combined endpoint GET /api/v1/health (and /api/v2/health, both versions registered - health.controller.ts:28) with four indicators: mongodb, redis, storage, bullmq (health.controller.ts:31-36). Terminus HealthCheckResult response envelope (200/503). @Public() + public rate tier (30 req/min). Custom indicators carry extra payload: Redis reports its ping value (redis-health.indicator.ts:16), BullMQ reports per-queue pendingJobs counts (bullmq-health.indicator.ts:30).

4.2 Planned (not in source)

  • Liveness/readiness split - GET /api/v1/health/ready and GET /api/v1/health/live appear in docs/user-flows/END_TO_END_USER_FLOWS.md:738-740 but no such routes exist in health.controller.ts today; the single combined check covers both concerns - marked (planned) throughout.
  • Disk and memory indicators - Terminus ships DiskHealthIndicator / MemoryHealthIndicator but neither is wired; only mongodb, redis, storage, bullmq are checked (health.controller.ts:31-36).
  • Uptime / version fields - the response carries no uptime, process version, or build hash; HealthCheckResult is returned verbatim (health.controller.ts:30-37).

4.3 Forward-looking (client roadmap)

"App Health" admin screen (status cards for API, DB, Redis, Queues, Storage; last-check time; manual retry) - (proposed) in 05/06. Per PRD the native client itself is post-Phase 1 (PRODUCT_REQUIREMENTS_DOCUMENT.md:144).

4.4 Proposed (analytics)

Analytics events on screens (health.*.*) per 00-shared/10 §8 - (proposed).

5. Non-goals (this version)

  • Authenticated health variants - no health.* permission exists in permissions.constants.ts:1-97 (verified: zero matches for "health"); the endpoint is public and rate-limited only. A guarded admin variant is (proposed) for the future screen.
  • Per-tenant health - no tenantId scoping; health is a global infrastructure concern (AGENTS.md tenancy conventions do not apply).
  • Diagnostics depth - no latency metrics, no per-queue detail beyond summed pendingJobs (bullmq-health.indicator.ts:27-30), no DB query timing.
  • Historical availability - endpoint is stateless; no uptime history, no incident log, no alerting (alerting out of scope of this module).
  • Load-shedding - the check itself has no timeout budget; a hanging dependency hangs the probe until the global RequestTimeoutMiddleware (app.module.ts:141) or client-side timeout fires.