## Implementation Plan ### Objective - Seed a daily database-only backup schedule with 14‑day retention on first install. - Add disk‑usage threshold monitoring with an admin dashboard warning banner. - Integrate automated workspace directory cleanup and dangling image pruning into the container reconcile loop. - Ensure all changes pass the project’s verification pipeline and do not break existing tests. --- ### Required Code Changes #### 1. Seed Default Backup Schedule - **File:** `services/backup/store.py` - **Action:** Add function `seed_default_schedule(db_session)`. It checks if any row exists in `backup_schedules` table. If none, inserts a schedule with: - `cron = "0 3 * * *"` - `target = "database"` - `keep_last = 14` - `enabled = True` - **Idempotency:** Only inserts when the table is empty; subsequent calls are no‑ops. - **File:** `services/backup/service.py` (or `services/backup/__init__.py`) - **Action:** In `BackupService.__init__` (after database setup), call `store.seed_default_schedule(self.db_session)`. #### 2. Disk Usage Threshold Monitoring & Alert Banner - **File:** `services/backup/store.py` - **Action:** Add function `get_disk_warnings(storage_paths: dict, threshold: int) -> list[dict]`. Compares `used_pct` per path (from `compute_storage_stats()`) against the threshold. Returns a list of dicts with keys: `path`, `used_pct`, `total_gb`, `used_gb`. - **File:** `schemas/backups.py` - **Action:** Add Pydantic model `DiskWarningOut(path=str, used_pct=float, total_gb=float, used_gb=float)`. - **File:** `routers/admin/backups.py` - **Action:** In the route handler that serves the admin backup page (likely `GET /admin/backups`): - Read environment variable `DISK_WARNING_PERCENT` (default `85`). - Call `store.get_disk_warnings(storage, threshold)`. - Include `disk_warnings` in the template context. - **File:** `templates/admin_backups.html` - **Action:** Before the main backup table, add a block that iterates over `disk_warnings` and renders a warning banner (e.g., `
Disk usage on {{w.path}} is {{w.used_pct}}% – above {{DISK_WARNING_PERCENT}}% threshold.
`). Style can be added via existing CSS classes; add a new `.disk-warning` style if needed. #### 3. Automated Workspace & Image Cleanup - **File:** `services/containers/service.py` - **Action:** Add private async method `_cleanup_stale_workspaces(self, backend)`: - List subdirectories of `self.settings.container_workspaces_dir`. - For each directory, check if its name matches any active container instance (query backend for status of that instance ID). - If no active container, remove the directory with `shutil.rmtree`. - After processing all directories, call `backend.image_prune()` to remove dangling images. - **Integration:** In the `run_once()` coroutine, after the existing orphan container reap (around line 110–121), add `await self._cleanup_stale_workspaces(backend)`. - **Imports:** Ensure `shutil`, `os`, and any needed backend methods are imported at top of `service.py`. #### 4. Verification & Testing - **Existing tests** must continue to pass. The changes add new functionality but should not break existing tests in: - `tests/api/admin/backups/` - `tests/e2e/admin/backups/` - **New unit tests** (optional but recommended) for: - `seed_default_schedule` (covers empty vs non‑empty table). - `get_disk_warnings` (covers above/below threshold). - `_cleanup_stale_workspaces` (mock file system and backend; verify rmtree and image_prune are called). --- ### Definition of Done - [ ] All modified files pass syntax check (`py_compile` or Python import). - [ ] `pip install -e '.[dev]' -q && make test-unit` exits with code 0 (all unit tests pass). - [ ] `pip install -q ruff && ruff check .` exits with code 0 (no lint errors). - [ ] Manually (or via integration test) verify: - A fresh install (empty database) automatically creates a daily database backup schedule. - Disk usage above 85% (default threshold) displays a warning banner on `/admin/backups`. - After running the container reconcile loop, stale workspace directories and dangling images are removed (disk usage report reflects cleanup). - [ ] No existing backup schedules, rotation logic, or CLI cleanup commands are inadvertently broken.