Skip to content

Platform Status Dashboard — Design Document ​

ADR: 0034

ADO: Feature "Admin Platform Status Dashboard" (under Epic AB#3074)

Status: Accepted

Last updated: 2026-06-23


Overview ​

The platform status dashboard is an admin-only page at /app/admin/status that shows the current health of the Heritage Virginia platform by querying the enriched /health API endpoint. It is the first stop for an administrator investigating a reported outage or degraded experience.


Data Model ​

/health API Response ​

typescript
interface HealthResponse {
  status: 'ok' | 'degraded' | 'error';
  version: string;           // npm_package_version from package.json
  commit: string;            // COMMIT_SHA env var injected at Docker build time
  uptime: number;            // process.uptime() in seconds
  timestamp: string;         // ISO 8601
  services: {
    api: {
      status: 'ok' | 'degraded' | 'error';
    };
    database: {
      status: 'ok' | 'error';
      latencyMs: number | null;  // round-trip latency of SELECT 1 probe
    };
  };
}

Status roll-up rules:

ConditionTop-level status
All services okok
Any service errordegraded
API itself failederror (returned by load balancer)

API Contract ​

GET /health ​

  • Auth: None (public endpoint; consumed by Azure health probes and CI smoke checks)
  • Rate limiting: Subject to global rate limiter (100 req/min per IP)
  • Response: HealthResponse (see above)
  • Implementation: apps/api/src/app.ts/health route

Database probe: SELECT 1 via Prisma $queryRaw. Failure sets services.database.status = 'error' and rolls top-level status to degraded. The route does not throw — health is always returned.

COMMIT_SHA injection:

# Dockerfile (runtime stage)
ARG COMMIT_SHA=unknown
ENV COMMIT_SHA=$COMMIT_SHA

# deploy.yml (docker/build-push-action)
build-args: |
  COMMIT_SHA=${{ github.sha }}

The full SHA is stored in process.env.COMMIT_SHA; the UI displays only the first 7 characters.


UI Layout ​

Route ​

/app/admin/status — protected by user.role !== 'admin' redirect to /app/profile.

Component ​

apps/web/src/pages/admin/AdminStatusPage.tsx

Layout structure ​

<div maxWidth=640 centered>
  <h1>Platform Status</h1>

  <!-- Overall status card -->
  <card>
    label: "Overall"
    value: dot-indicator + status string (OK / DEGRADED / ERROR)
  </card>

  <!-- Services card -->
  <card>
    header: "Services"
    row: API    | dot + status
    row: Database | dot + status (+ latencyMs if available)
  </card>

  <!-- Deployment card -->
  <card>
    header: "Deployment"
    row: Version | npm_package_version
    row: Commit  | first 7 chars of SHA (monospace)
    row: Uptime  | Xh Ym format
    row: Last checked | toLocaleTimeString of timestamp
  </card>

  <!-- App Insights link -->
  <a href="Azure Portal App Insights resource">Open App Insights →</a>
</div>

Status indicators &ZeroWidthSpace;

StatusIndicator
okGreen circle
degradedYellow circle
error / unknownRed circle

States &ZeroWidthSpace;

  • Loading: "Loading..." text while fetch is in flight
  • Error: "Could not reach API health endpoint." — shown when the fetch rejects
  • Loaded: Full card layout as above

Vite dev proxy &ZeroWidthSpace;

In development, fetch('/api/health') resolves via the Vite dev server proxy:

typescript
// vite.config.ts — server.proxy
'/api': {
  target: 'http://localhost:3000',
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/api/, ''),
}

In production (Azure SWA), the SWA routing config proxies /api/* to the Container App API endpoint at https://api.heritageva.app.


Access Control &ZeroWidthSpace;

  • Route guard: AdminHubPage pattern — if (user && user.role !== 'admin') return <Navigate to="/app/profile" replace />
  • The /health endpoint itself is public (no auth) to support Azure health probes and the CI smoke check.

App Insights Integration &ZeroWidthSpace;

The status page links to the App Insights resource in Azure Portal:

  • Resource: appi-heritageva-prod
  • Resource Group: rg-heritageva-prod-eus
  • Subscription: be069ae1-fc96-4a07-9f8e-5994d83a137d
  • Region: East US

Direct portal link format:

https://portal.azure.com/#resource/subscriptions/{subscriptionId}/resourceGroups/{rg}/providers/microsoft.insights/components/{name}/overview

The status page does NOT embed App Insights charts — it links out. Embedding would require MSAL authentication which adds complexity inconsistent with ADR 0003.


AdminHubPage Integration &ZeroWidthSpace;

A "Platform Operations" ListSection is added to AdminHubPage with two rows:

LabelDestination
Platform Status/app/admin/status
CLI Tools/app/admin/cli-tools

  • ADR 0034 — governing decision
  • ADR 0005 — observability (App Insights as primary telemetry)
  • docs/internal/design/platform-management-cli.md — CLI tool design
  • apps/api/src/schemas/responses.tsHealthResponseSchema (Zod, AB#4326)

Heritage Community Hub — Internal. Access restricted via Cloudflare Access + Entra ID.