import type { FastifyInstance } from 'fastify'; import { getSystemMetrics, getDockerStats, dockerCleanup } from './repository.js'; import { DockerCleanupParamsSchema } from './types.js'; import { requireAdmin } from '../../lib/auth.js'; import { createAuditLog } from '../audit/repository.js'; import { productId } from '../../lib/config.js'; export async function systemRoutes(fastify: FastifyInstance) { // Get system metrics (admin only) fastify.get('/system/metrics', { preHandler: async (req) => requireAdmin(req), }, async (req, reply) => { try { const metrics = await getSystemMetrics(); return reply.send(metrics); } catch (error) { fastify.log.error(error, 'Failed to get system metrics'); return reply.code(500).send({ error: 'Failed to get system metrics' }); } }); // Get Docker stats (admin only) fastify.get('/docker/stats', { preHandler: async (req) => requireAdmin(req), }, async (req, reply) => { try { const stats = await getDockerStats(); return reply.send(stats); } catch (error) { fastify.log.error(error, 'Failed to get Docker stats'); return reply.code(500).send({ error: 'Failed to get Docker stats' }); } }); // Docker cleanup (admin only). Privileged shell-out → audit-logged. fastify.post('/docker/cleanup', { preHandler: async (req) => requireAdmin(req), }, async (req, reply) => { try { const params = DockerCleanupParamsSchema.parse(req.body); const result = await dockerCleanup(params.type, params.force); // Phase 5 P2 mitigation: every privileged shell-out lands in the audit // log so a leaked admin token's actions are reconstructable from // Cosmos, not only from container stdout. Best-effort — don't fail // the request if audit write breaks. const authReq = req as unknown as { authUserId?: string; authRole?: string }; await createAuditLog({ action: 'shell-exec', entityType: 'host', entityId: `docker-cleanup:${params.type}`, userId: authReq.authUserId ?? 'unknown', role: authReq.authRole ?? 'unknown', productId, details: { type: params.type, force: params.force, freedSpace: result.freedSpace }, }).catch((err) => fastify.log.warn({ err }, 'audit log write failed')); return reply.send(result); } catch (error: any) { fastify.log.error(error, 'Docker cleanup failed'); return reply.code(500).send({ error: error.message || 'Docker cleanup failed' }); } }); }