TenantAtlas/specs/032-backup-scheduling-mvp/plan.md
ahmido 4d3fcd28a9 feat/032-backup-scheduling-mvp (#34)
What
Implements tenant-scoped backup scheduling end-to-end: schedules CRUD, minute-based dispatch, queued execution, run history, manual “Run now/Retry”, retention (keep last N), and auditability.

Key changes

Filament UI: Backup Schedules resource with tenant scoping + SEC-002 role gating.
Scheduler + queue: tenantpilot:schedules:dispatch command wired in scheduler (runs every minute), creates idempotent BackupScheduleRun records and dispatches jobs.
Execution: RunBackupScheduleJob syncs policies, creates immutable backup sets, updates run status, writes audit logs, applies retry/backoff mapping, and triggers retention.
Run history: Relation manager + “View” modal rendering run details.
UX polish: row actions grouped; bulk actions grouped (run now / retry / delete). Bulk dispatch writes DB notifications (shows in notifications panel).
Validation: policy type hard-validation on save; unknown policy types handled safely at runtime (skipped/partial).
Tests: comprehensive Pest coverage for CRUD/scoping/validation, idempotency, job outcomes, error mapping, retention, view modal, run-now/retry notifications, bulk delete (incl. operator forbidden).
Files / Areas

Filament: BackupScheduleResource.php and app/Filament/Resources/BackupScheduleResource/*
Scheduling/Jobs: app/Console/Commands/TenantpilotDispatchBackupSchedules.php, app/Jobs/RunBackupScheduleJob.php, app/Jobs/ApplyBackupScheduleRetentionJob.php, console.php
Models/Migrations: app/Models/BackupSchedule.php, app/Models/BackupScheduleRun.php, database/migrations/backup_schedules, backup_schedule_runs
Notifications: BackupScheduleRunDispatchedNotification.php
Specs: specs/032-backup-scheduling-mvp/* (tasks/checklist/quickstart updates)
How to test (Sail)

Run tests: ./vendor/bin/sail artisan test tests/Feature/BackupScheduling
Run formatter: ./vendor/bin/sail php ./vendor/bin/pint --dirty
Apply migrations: ./vendor/bin/sail artisan migrate
Manual dispatch: ./vendor/bin/sail artisan tenantpilot:schedules:dispatch
Notes

Uses DB notifications for queued UI actions to ensure they appear in the notifications panel even under queue fakes in tests.
Checklist gate for 032 is PASS; tasks updated accordingly.

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local>
Reviewed-on: #34
2026-01-05 04:22:13 +00:00

3.6 KiB

Implementation Plan: Backup Scheduling MVP (032)

Branch: feat/032-backup-scheduling-mvp | Date: 2026-01-05 | Spec: specs/032-backup-scheduling-mvp/spec.md Input: Feature specification from specs/032-backup-scheduling-mvp/spec.md

Summary

Implement tenant-scoped backup schedules that dispatch idempotent runs every minute via Laravel scheduler and queue workers. Each run syncs selected policy types from Graph into the local DB (via existing PolicySyncService) and creates an immutable BackupSet snapshot (via existing BackupService), with strict audit logging, fail-safe handling for unknown policy types, retention (keep last N), and Filament UI for managing schedules and viewing run history.

Technical Context

Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12, Filament v4, Livewire v3
Storage: PostgreSQL (Sail locally)
Testing: Pest v4
Target Platform: Containerized (Sail local), Dokploy deploy (staging/prod)
Project Type: Web application (Laravel monolith + Filament admin)
Performance Goals: Scheduler runs every minute; per-run work is queued; avoid long locks
Constraints: Idempotent dispatch (unique slot), per-schedule concurrency lock, no secrets/tokens in logs, “no catch-up” policy
Scale/Scope: Multi-tenant MSP use; schedules per tenant; runs stored for audit/history

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Safety-First Restore: PASS (feature is backup-only; no restore scheduling)
  • Auditability & Tenant Isolation: PASS (tenant_id everywhere; audit log entries for dispatch/run/retention)
  • Graph Abstraction & Contracts: PASS (sync uses GraphClientInterface via PolicySyncService; unknown policy types fail-safe; no hardcoded endpoints)
  • Least Privilege: PASS (authorization via TenantRole matrix; no new scopes required beyond existing backup/sync)
  • Spec-First Workflow: PASS (spec/plan/tasks/checklist in specs/032-backup-scheduling-mvp/)
  • Quality Gates: PASS (tasks include Pest coverage per constitution and Pint)

Project Structure

Documentation (this feature)

specs/032-backup-scheduling-mvp/
├── plan.md              # This file (/speckit.plan output)
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output
├── quickstart.md        # Phase 1 output
├── contracts/           # Phase 1 output
└── tasks.md             # Phase 2 output (already present)

Source Code (repository root)

app/
├── Console/Commands/
├── Filament/Resources/
├── Jobs/
├── Models/
└── Services/

config/
database/migrations/
routes/console.php
tests/

Expected additions for this feature (at implementation time):

app/Console/Commands/TenantpilotDispatchBackupSchedules.php
app/Jobs/RunBackupScheduleJob.php
app/Jobs/ApplyBackupScheduleRetentionJob.php
app/Models/BackupSchedule.php
app/Models/BackupScheduleRun.php
app/Filament/Resources/BackupScheduleResource.php
database/migrations/*_create_backup_schedules_table.php
database/migrations/*_create_backup_schedule_runs_table.php
tests/Feature/BackupScheduling/*
tests/Unit/BackupScheduling/*

Structure Decision: Laravel monolith (Filament admin + queued jobs). No new top-level app folders.

Phase Outputs

  • Phase 0 (Outline & Research): research.md
  • Phase 1 (Design & Contracts): data-model.md, contracts/*, quickstart.md
  • Phase 2 (Tasks): tasks.md already exists; will be refined later via /speckit.tasks if needed
  • Phase 1 (Design & Contracts): data-model.md, contracts/*, quickstart.md