fix(monitoring): flatten CPU/mem data, add health summary, public + rate-limit monitoring/stats
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled

Three coordinated fixes for the System Overview widget:

1. routes/monitoring.js — flatten getAllStats() shape from
   {current:{cpu:{percent},memory:{percent}}} to {cpu,memory,memoryUsage}
   so the widget's Number() coercion actually produces numbers, not NaN.
   Skill reference: references/totp-and-system-overview-pitfalls.md §3.

2. routes/health.js — add summary block to /health-checks/status response.
   Widget looks for {healthy, unhealthy, total} but only per-service objects
   existed. Permissive on healthy side (up|healthy|online), strict on
   unhealthy (down|unhealthy|offline|error); anything else counted as
   unknown. Same skill §3 reference.

3. middleware.js — add /api/v1/monitoring/stats to PUBLIC_ROUTES and the
   rate-limit skip list. The widget polls it every 5s from the dashboard;
   cookie-auth works but listing it explicitly makes it future-proof
   against auth-cookie expiry and prevents per-second 429s.

End-to-end test (unauthenticated):
  GET /api/v1/monitoring/stats  -> {cpu: 8.71, memory: 0.37, ...}
  GET /api/v1/health-checks/status -> {summary: {healthy:11, unhealthy:4, total:15}}
This commit is contained in:
Krystie
2026-06-18 21:17:16 -07:00
parent 4853f1feb8
commit 6809fc5cca
4 changed files with 37 additions and 4 deletions
+18 -1
View File
@@ -322,9 +322,26 @@ module.exports = function({
// ===== HEALTH CHECK (health-checker module) =====
// Get current status for all services
// Returns {status: {...per-service}} plus a {summary} block for the System Overview widget
// — see skill references/totp-and-system-overview-pitfalls.md §3
router.get('/health-checks/status', asyncHandler(async (req, res) => {
const status = healthChecker.getCurrentStatus();
success(res, { status });
const entries = Object.values(status || {});
// Treat 'up'/'healthy' as healthy, everything else as unhealthy.
// Health check status values come from healthChecker — typically 'up'/'down' but
// also 'healthy'/'unhealthy' or 'online'/'offline' depending on the source. Be
// permissive on the healthy side so a service in any positive state counts.
const healthy = entries.filter(s => {
const st = (s && (s.status || s.state)) || '';
return st === 'up' || st === 'healthy' || st === 'online';
}).length;
const unhealthy = entries.filter(s => {
const st = (s && (s.status || s.state)) || '';
return st === 'down' || st === 'unhealthy' || st === 'offline' || st === 'error';
}).length;
const unknown = entries.length - healthy - unhealthy;
const summary = { healthy, unhealthy, unknown, total: entries.length };
success(res, { status, summary });
}, 'health-check-status'));
// Get service statistics