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

06 - Screen Specifications (Health Module)

Detailed specifications for each screen. All screens (proposed) - the implemented backend is endpoint-only (health.controller.ts:27-37). Wire data references 12_API_Mapping.md; state references 13_State_Management.md.


S1. App Health Screen (/ops/health) (proposed)

Purpose

Operational at-a-glance availability of the API and its four dependencies, mirroring the combined Terminus check. Read-only; the only action is Retry.

Layout (phone)

┌──────────────────────────────────────────────┐
│ ‹  App Health                      [⚙]      │  AppBar
├──────────────────────────────────────────────┤
│  ● All systems operational                   │  OverallBanner (live region)
│  (or) ● 1 of 5 degraded — Redis is down      │
├──────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐          │
│  │ API    ● up  │  │ DB     ● up  │          │  StatusCard grid
│  └──────────────┘  └──────────────┘          │
│  ┌──────────────┐  ┌──────────────┐          │
│  │ Redis  ● up  │  │ Storage ● up │          │
│  │ ping: PONG   │  └──────────────┘          │
│  └──────────────┘  ┌──────────────┐          │
│                    │ Queues  ● up │          │
│                    │ pending: 12  │          │  PendingJobsTile
│                    └──────────────┘          │
│  Last checked 12:04:31 · Retry               │  LastCheckedLabel + Retry
└──────────────────────────────────────────────┘

Behavior

#EventResult
1Enter screenHealthCubit.fetch() immediately (13 §2); 5 skeleton cards
2200, all upbanner "All systems operational"; cards green; last-check = now
3503, partialbanner "1 of 5 degraded — Redis is down"; red card + detail sheet affordance; healthy cards stay green (health.controller.spec.ts:29-35)
4503, all downbanner "All systems degraded"; all cards red; API card also red
5Network error / timeoutAppOfflineBanner + cards show last known state + "stale" badge; Retry prominent
6429 rate-limitedcountdown on Retry (remaining seconds from Retry-After-style client math); poll paused
7Retry tapimmediate single fetch (rate-safe: skips poll tick on success)
8Poll tick (30 s)silent refetch; only state changes animate (m-fast)
9App backgroundedpoll paused; resume → immediate refetch (13 §3)
10Tap red cardincident detail sheet (S2) from cached payload - no network

Data mapping

CardPayload keyExtraSource
APIimplicit (request reached server)-health.controller.ts:27-37
DBdata.info.mongodb.status / data.error.mongodb-health.controller.ts:32
Redisdata.info.redis.statusping value when upredis-health.indicator.ts:16
Storagedata.info.storage.status-storage-health.indicator.ts:19
Queuesdata.info.bullmq.statuspendingJobs (emails, in-app, webhook-deliver, dlq)bullmq-health.indicator.ts:30
Last-checkclient timestamp of 200/503 response--

States

idle → loading (skeletons) → success(all-up) / success(partial) / success(all-down) ↔ error(offline/timeout, stale data) ↔ rate-limited (429 countdown, poll paused).

Permissions

(proposed) — no health.* permission exists (permissions.constants.ts:1-97). Screen gated by admin role only; document the new permission (health.read, proposed) for the RBAC roadmap.

Accessibility

  • Overall banner is a live region announcing state changes.
  • Each card: Semantics(label: "Redis: up, ping PONG", button: true).
  • Red/green never the only signal - text "up"/"down" always present (00-shared/09).

Motion

State-change flash 150 ms (m-fast); banner swap slide 250 ms (m-base); loading skeletons per 00-shared/08.


S2. Incident Detail Sheet (proposed)

FieldSpec
Triggertap any card with down state
Contentfailed key, raw data.error.<key> payload rendered as monospace read-only, pendingJobs for bullmq, last-check time, "no additional detail reported" when payload is bare (redis failure, redis-health.indicator.ts:17-22)
CTAnone beyond close; Retry lives on S1 (avoid duplicate retry paths)
Notesrenders exclusively from the cached fetch - zero network calls; keeps parity with endpoint truth