import type { FastifyPluginAsync } from 'fastify' import { hasPermission, type UiSummary } from '@evofw/shared' /** Authentication comes from the protected API scope; each section is independent. */ export const uiSummaryRoutes: FastifyPluginAsync = async (app) => { app.get('/ui/summary', async (req) => { const now = new Date() const summary: UiSummary = { updated_at: now.toISOString() } const permissions = req.authUser?.permissions ?? [] const allowed = (section: string) => req.authUser?.isAdmin || hasPermission(permissions, `fw:${section}:read`) const agentsAllowed = allowed('agents'), dashboardAllowed = allowed('dashboard') let counts: { total: number; approved: number; online: number; pending: number; dropped: number; accepted: number } | undefined if (agentsAllowed || dashboardAllowed) { counts = app.sqlite.prepare(`SELECT count(*) AS total, coalesce(sum(status='approved'),0) AS approved, coalesce(sum(status='approved' AND last_seen_at >= ?),0) AS online, coalesce(sum(status='pending'),0) AS pending, coalesce(sum(total_packets_dropped),0) AS dropped, coalesce(sum(total_packets_accepted),0) AS accepted FROM agents`).get(new Date(now.getTime() - 5 * 60_000).toISOString()) as typeof counts } let lists: { total: number; failed: number } | undefined if (allowed('lists') || dashboardAllowed) lists = app.sqlite.prepare("SELECT count(*) AS total, coalesce(sum(last_error IS NOT NULL AND last_error != ''),0) AS failed FROM ip_lists").get() as typeof lists if (agentsAllowed && counts) summary.agents = { approved: counts.approved, online: counts.online, pending: counts.pending, offline: counts.approved - counts.online } if (allowed('lists') && lists) summary.lists = lists if (dashboardAllowed && counts && lists) summary.dashboard = { agents_total: counts.total, agents_approved: counts.approved, agents_online: counts.online, agents_pending: counts.pending, packets_dropped: counts.dropped, packets_accepted: counts.accepted, lists_total: lists.total, } if (allowed('policies')) summary.policies = app.sqlite.prepare('SELECT (SELECT count(*) FROM policy_sets) AS sets_total, (SELECT count(*) FROM policy_rules) AS rules_total').get() as UiSummary['policies'] return summary }) }