- Add `lib/constants.ts` exporting `DATA_DIR`, `DATABASE_URL`, `CACHE_DIR`,
`BACKUP_DIR`, `AVATAR_DIR`, `TMDB_API_BASE_URL`, and `TMDB_IMAGE_BASE_URL`
- Replace inline `process.env` derivations in `db/client`, `backup`,
`image-cache`, `system-health`, `tmdb/client`, `actions/settings`,
and `api/avatars` with imports from the new module
- New `lists` service fetches Sonarr/Radarr library via their REST APIs
and auto-imports matching titles from TMDB into the user's watchlist
- `app/api/lists/[token]/route.ts` webhook endpoint triggers a list sync
- Unified `IntegrationCard` component replaces `WebhookCard`, handling
both webhook-style (Plex/Jellyfin/Emby) and list-style (Sonarr/Radarr)
integrations with per-type config forms
- Schema migration adds `sonarr` and `radarr` to the integration type
enum and a `listConnections` table for list-based integrations
- 212 tests added for the lists service covering import, deduplication,
and error handling
- 211 tests across 15 files covering services (tracking, discovery,
metadata, backup, credits, webhooks, settings, update-check, colors,
person), utilities (config, cron, providers, title-theme), and TMDB
image URL helpers
- `lib/test-preload.ts` + `bunfig.toml` wire up a global in-memory
SQLite DB with migrations for all DB-backed tests
- `lib/test-utils.ts` provides `clearAllTables()` and seed helpers
(insertUser, insertTitle, insertTvShow, insertMovieWatch, etc.)
- Export `getBackupSource`, `isKnownBackup`, `isValidBackupFilename`,
`buildBackupCron`, `performUpdateCheck` internals for direct testing
- GitHub Actions workflow runs `bun test --coverage` on push/PR to main
Serialize all backup operations through a promise-based queue
(`withBackupLock`) to prevent race conditions under concurrent
requests. Extract internal helpers so `pruneBackups` and
`deleteBackup` can participate in the same lock.
Strengthen `restoreFromBackup`: write the temp file alongside the
live database (`dbDir`), validate it with a full integrity check,
foreign key check, and a required-tables list before touching the
live DB, then use a synchronous `renameSync` for an atomic swap.
Clear WAL/SHM files synchronously in the same tick to avoid
interleaving. Run migrations after restore so older backups are
brought up-to-date automatically.
Add milliseconds to all backup timestamps (`HHmmssSSS`) to avoid
filename collisions when backups are created in rapid succession.
Update filename regexes to accept both the old and new formats.
- Add "unlimited" (value 0) to the keeping-last dropdown
- Skip pruning when retention is set to unlimited
- Show toast confirmation when changing retention
- Update description to read "Keeping unlimited backups" or "Keeping last N backups"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make backup frequency (6h/12h/1d/7d), time, and day-of-week
configurable via settings, stored in appSettings key-value table
- Add rescheduleBackup() to dynamically update cron job at runtime
- Differentiate manual (sofa-manual-*) vs scheduled (sofa-scheduled-*)
backup filenames with source icons and tooltips in the backup list
- Pruning now only targets scheduled backups, leaving manual ones intact
- Merge backup-actions.ts into actions.ts, use shadcn DropdownMenu for
all selectors (consistent with dashboard stats cards)
- Fix hydration mismatch on relative backup timestamps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backup service using VACUUM INTO for WAL-safe atomic snapshots
- Server-side storage in DATA_DIR/backups with download/upload API routes
- Restore with integrity validation and automatic pre-restore safety backup
- Scheduled daily backups via cron with configurable retention
- Admin-only settings UI consolidated under single Server section
- Clean up account section sign-out button, fix switch sub-pixel rendering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>