## 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.