/** * RPC handlers for the server alerting / webhook system. */ import * as validation from '../utils/validation.js' import { getAlertsConfig, getAlertsConfigRaw, updateAlertsConfig, upsertAlertChannel, deleteAlertChannel, upsertAlertRule, deleteAlertRule, listAlertHistory, getAlertsStatus, testAlertChannel, fireManualAlert, getAlertsFilePath, ALERT_CHANNEL_TYPES, ALERT_RULE_KINDS, ALERT_SEVERITIES, } from '../services/alerts.js' export function registerAlertHandlers(session) { session.respond('getAlertsConfig', async () => { return { success: true, config: getAlertsConfig(), meta: { channelTypes: ALERT_CHANNEL_TYPES, ruleKinds: ALERT_RULE_KINDS, severities: ALERT_SEVERITIES, }, } }) /** * Admin-only full export including webhook secrets — for backup / client cache. */ session.respond('exportAlertsConfig', async () => { return { success: true, config: getAlertsConfigRaw(), path: getAlertsFilePath(), exportedAt: new Date().toISOString(), } }) session.respond('getAlertsStatus', async () => { return { success: true, status: getAlertsStatus() } }) session.respond('listAlertHistory', async (args = {}) => { const limit = Math.max(1, Math.min(200, Number(args.limit) || 50)) return { success: true, history: listAlertHistory(limit) } }) session.respond('updateAlertsConfig', async (args = {}) => { const replace = Boolean(args.replace) const partial = args.config && typeof args.config === 'object' ? args.config : args const config = updateAlertsConfig(partial, { replace }) return { success: true, config } }) session.respond('upsertAlertChannel', async (args = {}) => { const channel = upsertAlertChannel(args.channel || args) return { success: true, channel } }) session.respond('deleteAlertChannel', async (args = {}) => { const id = validation.sanitizeString(args.id || '', 64) if (!id) throw Object.assign(new Error('id required'), { code: 'INVALID_ARGS' }) const ok = deleteAlertChannel(id) if (!ok) throw Object.assign(new Error('Channel not found'), { code: 'NOT_FOUND' }) return { success: true, id, deleted: true } }) session.respond('upsertAlertRule', async (args = {}) => { const rule = upsertAlertRule(args.rule || args) return { success: true, rule } }) session.respond('deleteAlertRule', async (args = {}) => { const id = validation.sanitizeString(args.id || '', 64) if (!id) throw Object.assign(new Error('id required'), { code: 'INVALID_ARGS' }) const ok = deleteAlertRule(id) if (!ok) throw Object.assign(new Error('Rule not found'), { code: 'NOT_FOUND' }) return { success: true, id, deleted: true } }) session.respond('testAlertChannel', async (args = {}) => { const id = validation.sanitizeString(args.id || args.channelId || '', 64) if (!id) throw Object.assign(new Error('id required'), { code: 'INVALID_ARGS' }) const result = await testAlertChannel(id) return { success: true, ...result } }) session.respond('fireManualAlert', async (args = {}) => { const title = validation.sanitizeString(args.title || '', 200) if (!title) throw Object.assign(new Error('title required'), { code: 'INVALID_ARGS' }) const record = await fireManualAlert({ title, message: validation.sanitizeString(args.message || '', 2000), severity: args.severity, details: args.details, }) return { success: true, record } }) } export default { registerAlertHandlers }