10 KiB
| description |
|---|
| Executable task list for Spec 091 implementation |
Tasks: BackupSchedule Retention & Lifecycle (Archive/Restore/Force Delete)
Input: Design documents from /specs/091-backupschedule-retention-lifecycle/
Prerequisites: plan.md (required), spec.md (user stories), research.md, data-model.md, contracts/, quickstart.md
Tests: REQUIRED (Pest) for runtime behavior changes.
Phase 1: Setup (Shared Infrastructure)
Purpose: Confirm baseline assumptions and align with repo conventions before changing runtime behavior.
- T001 Confirm SoftDeletes + lifecycle conventions in app/Filament/Resources/BackupSetResource.php
- T002 Confirm RBAC-UX helper usage patterns in app/Support/Rbac/UiEnforcement.php
- T003 Confirm BackupSchedule scheduling flow touchpoints in app/Services/BackupScheduling/BackupScheduleDispatcher.php and app/Jobs/RunBackupScheduleJob.php
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Introduce the archived lifecycle state at the data/model layer.
⚠️ CRITICAL: No user story work should begin until this phase is complete.
- T004 Add SoftDeletes to app/Models/BackupSchedule.php
- T005 Create migration to add deleted_at to backup_schedules in database/migrations/ (new migration file)
- T006 [P] Update BackupSchedule model query expectations/tests to account for soft-deleted records in tests/Feature/BackupScheduling/BackupScheduleCrudTest.php
Checkpoint: BackupSchedule supports archived state (deleted_at).
Phase 3: User Story 1 — Archive a schedule safely (Priority: P1) 🎯 MVP
Goal: Tenant admins can archive schedules (soft delete) with confirmation; archived schedules are excluded from the default list and MUST never execute.
Independent Test: Create an active schedule, archive it, verify it disappears from the default list, is visible under an “Archived” filter, audit entry exists, and scheduler/job do not dispatch/execute archived schedules.
Tests (write first)
- T007 [P] [US1] Add archive lifecycle tests in tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php
- T008 [P] [US1] Add scheduler safety test (archived schedules not dispatched) in tests/Feature/BackupScheduling/DispatchIdempotencyTest.php
- T009 [P] [US1] Add job safety test (archived schedule skipped) in tests/Feature/BackupScheduling/RunBackupScheduleJobTest.php
- T009 [P] [US1] Add job safety test (archived schedule skipped) in tests/Feature/BackupScheduling/RunBackupScheduleJobTest.php (assert
OperationRuniscompletedwith outcomeblocked,summary_counts.skipped=1, andfailure_summaryincludescode=schedule_archived)
Implementation
- T010 [US1] Add “Archived” filter to BackupSchedule table in app/Filament/Resources/BackupScheduleResource.php
- T011 [US1] Remove/disable bulk destructive actions for schedules in app/Filament/Resources/BackupScheduleResource.php
- T012 [US1] Replace hard-delete semantics with “Archive” action (soft delete) in app/Filament/Resources/BackupScheduleResource.php
- T013 [US1] Enforce RBAC-UX (non-member→404; member missing capability→403) for archive action using app/Support/Rbac/UiEnforcement.php in app/Filament/Resources/BackupScheduleResource.php
- T014 [US1] Emit audit event backup_schedule.archived via app/Services/Intune/AuditLogger.php from app/Filament/Resources/BackupScheduleResource.php
- T015 [US1] Ensure dispatcher excludes archived schedules in app/Services/BackupScheduling/BackupScheduleDispatcher.php
- T016 [US1] Add execution-time guard to skip archived schedules in app/Jobs/RunBackupScheduleJob.php
- T016 [US1] Add execution-time guard to skip archived schedules in app/Jobs/RunBackupScheduleJob.php (set
OperationRuntocompleted+ outcomeblocked,summary_counts.skipped=1,failure_summary.code=schedule_archived, and emitbackup_schedule.run_skippedwithreason=schedule_archived)
Checkpoint: Archive works end-to-end; archived schedules never execute.
Phase 4: User Story 2 — Restore an archived schedule (Priority: P2)
Goal: Tenant admins can restore archived schedules (no confirmation required) without changing enabled/disabled state.
Independent Test: Archive a schedule, restore it, verify it returns to the default list, is_enabled is unchanged, and audit entry exists.
Tests (write first)
- T017 [P] [US2] Add restore lifecycle tests (no confirmation required; is_enabled unchanged) in tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php
Implementation
- T018 [US2] Add “Restore” action (only for archived records) in app/Filament/Resources/BackupScheduleResource.php
- T019 [US2] Enforce RBAC-UX for restore action using app/Support/Rbac/UiEnforcement.php in app/Filament/Resources/BackupScheduleResource.php
- T020 [US2] Emit audit event backup_schedule.restored via app/Services/Intune/AuditLogger.php from app/Filament/Resources/BackupScheduleResource.php
Checkpoint: Restore is functional and independently testable.
Phase 5: User Story 3 — Force delete as a privileged retention tool (Priority: P3)
Goal: Highly privileged tenant admins can force delete archived schedules with confirmation, but only when no historical runs exist.
Independent Test: Archive a schedule, attempt force delete without TENANT_DELETE (403), attempt force delete with historical runs (blocked), force delete with no historical runs (success), and audit entry exists.
Tests (write first)
- T021 [P] [US3] Add force delete tests (capability gated; only archived; blocked when historical runs exist) in tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php
Implementation
- T022 [US3] Add “Force delete” action (only for archived records; requires confirmation) in app/Filament/Resources/BackupScheduleResource.php
- T023 [US3] Enforce RBAC-UX for force delete using app/Support/Rbac/UiEnforcement.php in app/Filament/Resources/BackupScheduleResource.php
- T024 [US3] Block force delete when historical runs exist using BackupSchedule::operationRuns() in app/Models/BackupSchedule.php and enforce in app/Filament/Resources/BackupScheduleResource.php
- T024 [US3] Block force delete when historical runs exist using BackupSchedule::operationRuns() in app/Models/BackupSchedule.php and enforce in app/Filament/Resources/BackupScheduleResource.php (danger notification: title “Cannot force delete backup schedule”, body “Backup schedules referenced by historical runs cannot be removed.”; do not delete; do not emit
backup_schedule.force_deleted) - T025 [US3] Emit audit event backup_schedule.force_deleted via app/Services/Intune/AuditLogger.php from app/Filament/Resources/BackupScheduleResource.php
Checkpoint: Force delete is safe (blocked when history exists) and audited.
Phase 6: Polish & Cross-Cutting Concerns
Purpose: Ensure contract compliance, update impacted tests, and validate via quickstart.
- T026 [P] Update bulk delete test to match “no bulk destructive actions” rule in tests/Feature/BackupScheduling/BackupScheduleBulkDeleteTest.php
- T027 Ensure BackupSchedule list inspect affordance opens Edit page in app/Filament/Resources/BackupScheduleResource.php
- T028 Ensure “max 2 visible row actions; everything else in More ActionGroup” in app/Filament/Resources/BackupScheduleResource.php
- T029 Run formatting in repo using vendor/bin/sail bin pint --dirty
- T030 Run focused test suite using vendor/bin/sail artisan test --compact tests/Feature/BackupScheduling
- T031 Run Spec 091 manual checklist from specs/091-backupschedule-retention-lifecycle/quickstart.md
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1): No dependencies.
- Foundational (Phase 2): Depends on Setup completion; BLOCKS all user stories.
- User Stories (Phase 3–5): Depend on Foundational completion.
- Polish (Phase 6): Depends on all desired user stories being complete.
User Story Dependencies
- US1 (Archive): First; enables “Archived” state and execution safety.
- US2 (Restore): Depends on US1 (requires archived records to exist).
- US3 (Force delete): Depends on US1 (force delete only applies to archived records).
Parallel Execution Examples
US1 (after Phase 2)
- T007 (lifecycle tests), T008 (dispatcher safety test), and T009 (job safety test) can be written in parallel.
- T015 (dispatcher exclusion) and T016 (job guard) can be implemented in parallel.
US3 (after US1)
- T021 (force delete tests) can be written while UI action scaffolding is prepared (T022–T023).
Implementation Strategy
MVP First (US1 Only)
- Complete Phase 1 and Phase 2.
- Implement US1 (archive + execution safety + audit) and pass US1 tests.
- Validate via Phase 6 tasks T029–T031.
Incremental Delivery
- Add US2 (restore) once US1 is stable.
- Add US3 (force delete) last, with strict capability gating and history blocking.
Additions (Consistency + Constitution Coverage)
Purpose: Close remaining gaps found by the consistency analysis (terminology, FR-012 coverage, and explicit server-side RBAC enforcement + tests).
- T032 [US1] Allow editing archived schedules (SoftDeletes) in app/Filament/Resources/BackupScheduleResource/Pages/EditBackupSchedule.php
- T033 [P] [US1] Add test asserting an authorized tenant member can open Edit for a soft-deleted schedule in tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php
- T034 [US1] Enforce server-side authorization (Policy/Gate) for Archive action in app/Filament/Resources/BackupScheduleResource.php
- T035 [US2] Enforce server-side authorization (Policy/Gate) for Restore action in app/Filament/Resources/BackupScheduleResource.php
- T036 [US3] Enforce server-side authorization (Policy/Gate) for Force delete action in app/Filament/Resources/BackupScheduleResource.php
- T037 [P] [US1] Add explicit RBAC-UX tests for 404 vs 403 semantics in tests/Feature/BackupScheduling/BackupScheduleLifecycleAuthorizationTest.php
- T038 [P] [US1] Add idempotency tests for Archive/Restore (already archived / already active) in tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php