TenantAtlas/specs/091-backupschedule-retention-lifecycle/tasks.md
ahmido 1c098441aa feat(spec-091): BackupSchedule lifecycle + create-CTA placement rule (#109)
Implements Spec 091 “BackupSchedule Retention & Lifecycle (Archive/Restore/Force Delete)”.

- BackupSchedule lifecycle:
  - Archive (soft delete) with confirmation; restores via Restore action; Force delete with confirmation and strict gating.
  - Force delete blocked when historical runs exist.
  - Archived schedules never dispatch/execute (dispatcher + job guard).
  - Audit events emitted for archive/restore/force delete.
  - RBAC UX semantics preserved (non-member hidden/404; member w/o capability disabled + server-side 403).

- Filament UX contract update:
  - Create CTA placement rule across create-enabled list pages:
    - Empty list: only large centered empty-state Create CTA.
    - Non-empty list: only header Create action.
  - Tests added/updated to enforce the rule.

Verification:
- `vendor/bin/sail bin pint --dirty`
- Focused tests: BackupScheduling + RBAC enforcement + EmptyState CTAs + Create CTA placement

Notes:
- Filament v5 / Livewire v4 compliant.
- Manual quickstart verification in `specs/091-backupschedule-retention-lifecycle/quickstart.md` remains to be checked (T031).

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #109
2026-02-14 13:46:06 +00:00

10 KiB
Raw Permalink Blame History

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 OperationRun is completed with outcome blocked, summary_counts.skipped=1, and failure_summary includes code=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 OperationRun to completed + outcome blocked, summary_counts.skipped=1, failure_summary.code=schedule_archived, and emit backup_schedule.run_skipped with reason=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 35): 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 (T022T023).

Implementation Strategy

MVP First (US1 Only)

  1. Complete Phase 1 and Phase 2.
  2. Implement US1 (archive + execution safety + audit) and pass US1 tests.
  3. Validate via Phase 6 tasks T029T031.

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