feat(backup): add scheduler alerts and recovery notifications

This commit is contained in:
William Valentin
2026-02-16 13:46:35 -08:00
parent ce621d1b72
commit 8684c3a07d
11 changed files with 349 additions and 72 deletions
+25
View File
@@ -15,6 +15,26 @@ function makeBaseConfig(): Config {
backends: { native: { enabled: true }, opencode: { enabled: false }, claude_code: { enabled: false } },
hooks: { confirm: [], log: [], silent: [] },
mcp: { servers: [] },
backup: {
enabled: false,
schedule: undefined,
interval: '24h',
run_on_start: false,
notify: undefined,
failure_threshold: 1,
notify_recovery: true,
local_dir: '~/.local/share/flynn/backups',
include_vectors: true,
minio: {
enabled: false,
endpoint: undefined,
access_key: undefined,
secret_key: undefined,
bucket: undefined,
prefix: 'flynn',
secure: true,
},
},
automation: {
cron: [],
webhooks: [],
@@ -61,6 +81,7 @@ describe('discoverServices', () => {
expect.objectContaining({ name: 'zalo', status: 'not_configured' }),
expect.objectContaining({ name: 'cron', status: 'not_configured' }),
expect.objectContaining({ name: 'daily_briefing', status: 'not_configured' }),
expect.objectContaining({ name: 'backup', status: 'not_configured' }),
expect.objectContaining({ name: 'mcp', status: 'not_configured' }),
expect.objectContaining({ name: 'web_search', status: 'configured' }),
expect.objectContaining({ name: 'audio_transcription', status: 'not_configured' }),
@@ -105,6 +126,8 @@ describe('discoverServices', () => {
output: { channel: 'webchat', peer: 'x' },
};
cfg.mcp.servers = [{ name: 'srv', command: 'x', args: [] }];
cfg.backup.enabled = true;
cfg.backup.schedule = '0 2 * * *';
const reg = new ChannelRegistry();
const services = discoverServices(cfg, reg);
@@ -112,6 +135,8 @@ describe('discoverServices', () => {
expect(services.find(s => s.name === 'cron')?.status).toBe('configured');
expect(services.find(s => s.name === 'cron')?.itemCount).toBe(2);
expect(services.find(s => s.name === 'daily_briefing')?.status).toBe('configured');
expect(services.find(s => s.name === 'backup')?.status).toBe('configured');
expect(services.find(s => s.name === 'backup')?.metadata).toMatchObject({ schedule: '0 2 * * *' });
expect(services.find(s => s.name === 'mcp')?.metadata).toEqual({ serverCount: 1 });
});
+13
View File
@@ -121,6 +121,19 @@ export function discoverServices(
},
});
services.push({
name: 'backup',
type: 'automation',
status: config.backup?.enabled ? 'configured' : 'not_configured',
description: 'Snapshot backup scheduler',
metadata: {
schedule: config.backup?.schedule,
interval: config.backup?.interval,
run_on_start: config.backup?.run_on_start,
minio_enabled: config.backup?.minio?.enabled ?? false,
},
});
const automation = config.automation;
const dailyBriefingEnabled = Boolean(automation.daily_briefing?.enabled && automation.daily_briefing.output);
const totalCronJobs = automation.cron.length + (dailyBriefingEnabled ? 1 : 0);