# Dashboard overview

`GET /api/v1/dashboard/overview` requires an active application session (all roles). It uses the normal success/data/meta envelope and private no-store response. No query parameters are supported; unknown filters return 422.

- `period` is the current facility calendar month, with inclusive start and exclusive end, expressed in UTC; `asOf` is captured once per request.
- PM compliance = on-time completions / released non-cancelled PMs due this month whose deadline has been reached. Completion exactly at dueAt qualifies. Late completion does not. A zero denominator yields null, not 100%. Missing dueAt is excluded; missing completedAt cannot qualify as on-time.
- PM overdue and active corrective cover current backlog across all months. Overdue means OPEN/IN_PROGRESS and dueAt strictly before asOf. Corrective covers pilot plant and warehouse quarantine.
- WO type chart uses creation month. PM status chart uses due month and includes already-released future deadlines. Its completed segment includes late completions; it is not the compliance numerator.
- Inventory uses non-archived Part records and all their balances. Available = physical - quarantined. Pending checkout is not deducted again. Empty and low are disjoint; zero-minimum and quarantined SKU buckets can overlap them. Quantity charts separate group and stored unit.
- Five selected WO rows rank active overdue (dueAt ascending, priority, createdAt descending, ID descending), active urgent, then latest. Target relations are fetched only for these rows and retain archived history. No technician, calibration, financial, or user identity fields are included.
- Reads run in RepeatableRead with no mutations or notification publishing. PM projections not materialized as WO records are excluded; the Home page discloses this scope. There is no cronjob or schema migration in this feature.

Verification: `node --env-file=.env prisma/verify-dashboard.cjs` creates a randomly named isolated test database, applies existing migrations there, runs contract/aggregation/integration tests, and drops only that database. It requires create/drop database permission on the configured development MySQL server. Add `--browser` to build a same-origin frontend fixture and run Chrome acceptance as well; use PILOT_CHROME to override the local Chrome executable. Browser tests accelerate only the 60-second polling timer. Never point tests at production credentials.
