TenantAtlas/specs/032-backup-scheduling-mvp/plan.md
2026-01-05 00:23:12 +01:00

57 lines
2.4 KiB
Markdown

# Plan: Backup Scheduling MVP (032)
**Date**: 2026-01-05
**Input**: spec.md
## Architecture / Reuse
- Reuse existing services:
- `PolicySyncService::syncPoliciesWithReport()` for selected policy types
- `BackupService::createBackupSet()` to create immutable snapshots + items (include_foundations supported)
- Store selection as `policy_types` (config keys), not free-form categories.
- Use tenant scoping (`tenant_id`) consistent with existing tables (`backup_sets`, `backup_items`).
## Scheduling Mechanism
- Add Artisan command: `tenantpilot:schedules:dispatch`.
- Scheduler integration (Laravel 12): schedule the command every minute via `routes/console.php` + ops configuration (Dokploy cron `schedule:run` or long-running `schedule:work`).
- Dispatcher algorithm:
1) load enabled schedules
2) compute whether due for the current minute in schedule timezone
3) create run with `scheduled_for` slot (minute precision) using DB unique constraint
4) dispatch `RunBackupScheduleJob(schedule_id, run_id)`
- Concurrency:
- Cache lock per schedule (`lock:backup_schedule:{id}`) plus DB unique slot constraint for idempotency.
## Run Execution
- `RunBackupScheduleJob`:
1) load schedule + tenant
2) preflight: tenant active; Graph/auth errors mapped to error_code
3) sync policies for selected types (collect report)
4) select policy IDs from local DB for those types (exclude ignored)
5) create backup set:
- name: `{schedule_name} - {Y-m-d H:i}`
- includeFoundations: schedule flag
6) set run status:
- success if backup_set.status == completed
- partial if backup_set.status == partial OR sync had failures but backup succeeded
- failed if nothing backed up / hard error
7) update schedule last_run_* and compute/persist next_run_at
8) dispatch retention job
## Retention
- `ApplyBackupScheduleRetentionJob(schedule_id)`:
- identify runs ordered newest→oldest
- keep last N runs that created a backup_set_id
- for older ones: soft-delete referenced BackupSets (and cascade soft-delete items)
## Filament UX
- Tenant-scoped resources:
- `BackupScheduleResource`
- Runs UI via RelationManager under schedule (or a dedicated resource if needed)
- Actions: enable/disable, run now, retry
- Notifications: persist via `->sendToDatabase($user)` for the DB info panel.
## Ops / Deployment Notes
- Requires queue worker.
- Requires scheduler running.
- Missed runs policy (MVP): no catch-up.