feat(KB-327): add automatic database backup system

- Add backup settings to ProjectSettings with schedule, retention, and directory config
- Create BackupManager with create, list, cleanup, and restore operations
- Add CLI backup commands: --create, --list, --restore, --cleanup
- Implement backup validation and automation sync for scheduled backups
- Add dashboard backup settings UI with stats and 'Backup Now' button
- Add backup API routes for settings management and manual operations
- Include comprehensive backup tests and changeset for patch release
- Document backup configuration and recovery in AGENTS.md
This commit is contained in:
gsxdsm
2026-03-31 15:40:25 -07:00
parent a4f80a743d
commit 1608efa7a2
11 changed files with 1395 additions and 3 deletions

View File

@@ -42,6 +42,7 @@ const { runDashboard } = await import("./commands/dashboard.js");
const { runTaskCreate, runTaskList, runTaskMove, runTaskMerge, runTaskUpdate, runTaskLog, runTaskLogs, runTaskShow, runTaskAttach, runTaskPause, runTaskUnpause, runTaskImportFromGitHub, runTaskDuplicate, runTaskArchive, runTaskUnarchive, runTaskRefine, runTaskPlan, runTaskDelete, runTaskRetry, runTaskComment, runTaskComments, runTaskSteer, runTaskPrCreate } = await import("./commands/task.js");
const { runSettingsShow, runSettingsSet } = await import("./commands/settings.js");
const { runGitStatus, runGitFetch, runGitPull, runGitPush } = await import("./commands/git.js");
const { runBackupCreate, runBackupList, runBackupRestore, runBackupCleanup } = await import("./commands/backup.js");
const HELP = `
fn — AI-orchestrated task board
@@ -83,6 +84,10 @@ Usage:
fn git push Push current branch
fn git pull Pull current branch
fn git fetch [remote] Fetch from remote (default: origin)
fn backup --create Create a database backup immediately
fn backup --list List all database backups
fn backup --restore <file> Restore database from a backup file
fn backup --cleanup Remove old backups exceeding retention limit
Options:
--port, -p <port> Dashboard port (default: 4040)
@@ -463,6 +468,28 @@ async function main() {
break;
}
case "backup": {
const create = args.includes("--create");
const list = args.includes("--list");
const cleanup = args.includes("--cleanup");
const restoreIdx = args.indexOf("--restore");
const restoreFile = restoreIdx !== -1 && restoreIdx + 1 < args.length ? args[restoreIdx + 1] : undefined;
if (create) {
await runBackupCreate();
} else if (list) {
await runBackupList();
} else if (cleanup) {
await runBackupCleanup();
} else if (restoreFile) {
await runBackupRestore(restoreFile);
} else {
console.error("Usage: fn backup --create | --list | --cleanup | --restore <filename>");
process.exit(1);
}
break;
}
default:
console.error(`Unknown command: ${command}`);
console.log(HELP);