feat(005): Generate task breakdown for Bulk Operations feature

98 tasks across 10 phases organized by user story:
- Phase 1-2: Setup + Foundational (13 tasks)
- Phase 3-4: US1 Bulk Delete + US2 Export (22 tasks) - MVP
- Phase 5: US5 Type-to-Confirm (7 tasks)
- Phase 6: US6 Progress Tracking (12 tasks)
- Phase 7-9: US3 Prune + US4 Delete Runs + Backup Sets (31 tasks)
- Phase 10: Polish + QA (13 tasks)

MVP Scope: 35 tasks (16-22 hours)
Full P1/P2: 85 tasks (26-34 hours)
Production Ready: 98 tasks (30-40 hours)

Each user story independently testable:
- US1: Bulk delete policies (local, ignored_at flag)
- US2: Bulk export to backup set
- US3: Prune old policy versions (eligibility checks)
- US4: Delete restore runs (skip running)
- US5: Type-to-confirm for ≥20 items
- US6: Progress tracking with Livewire polling

Parallel opportunities identified:
- All tests per story can run parallel
- User stories can be worked on by different devs
- Models/jobs in different files can be created parallel

Critical path to MVP: T001→T007→T014→T024 (12-16 hours)
This commit is contained in:
Ahmed Darrazi 2025-12-22 01:32:05 +01:00
parent 673fbd6b22
commit 9eb3a849e2

View File

@ -0,0 +1,485 @@
# Tasks: Feature 005 - Bulk Operations
**Branch**: `feat/005-bulk-operations` | **Date**: 2025-12-22
**Input**: [spec.md](./spec.md), [plan.md](./plan.md), [data-model.md](./data-model.md), [research.md](./research.md)
## Task Format
- **Checkbox**: `- [ ]` for incomplete, `- [x]` for complete
- **Task ID**: Sequential T001, T002, T003...
- **[P] marker**: Task can run in parallel (different files, no blocking dependencies)
- **[Story] label**: User story tag (US1, US2, US3...) - omit for Setup/Foundational/Polish phases
- **File path**: Always include exact file path in description
## Phase 1: Setup (Project Initialization)
**Purpose**: Database schema and base infrastructure for bulk operations
- [ ] T001 Create migration for `bulk_operation_runs` table in database/migrations/YYYY_MM_DD_HHMMSS_create_bulk_operation_runs_table.php
- [ ] T002 Create migration to add `ignored_at` column to policies table in database/migrations/YYYY_MM_DD_HHMMSS_add_ignored_at_to_policies_table.php
- [ ] T003 [P] Create BulkOperationRun model in app/Models/BulkOperationRun.php
- [ ] T004 [P] Create BulkOperationService in app/Services/BulkOperationService.php
- [ ] T005 Run migrations and verify schema: `./vendor/bin/sail artisan migrate`
- [ ] T006 Run Pint formatting: `./vendor/bin/sail composer pint`
**Checkpoint**: Database ready, base models created
---
## Phase 2: Foundational (Shared Components)
**Purpose**: Core components used by ALL bulk operations - MUST complete before user stories
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
- [ ] T007 Extend Policy model with `ignored_at` scope and methods in app/Models/Policy.php
- [ ] T008 [P] Extend PolicyVersion model with `pruneEligible()` scope in app/Models/PolicyVersion.php
- [ ] T009 [P] Extend RestoreRun model with `deletable()` scope in app/Models/RestoreRun.php
- [ ] T010 Extend AuditLogger service to support bulk operation events in app/Services/Audit/AuditLogger.php (or equivalent)
- [ ] T011 Update SyncPoliciesJob to filter by `ignored_at IS NULL` in app/Jobs/SyncPoliciesJob.php
- [ ] T012 Create BulkOperationRun factory in database/factories/BulkOperationRunFactory.php
- [ ] T013 Create test seeder BulkOperationsTestSeeder in database/seeders/BulkOperationsTestSeeder.php
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
---
## Phase 3: User Story 1 - Bulk Delete Policies (Priority: P1) 🎯 MVP
**Goal**: Enable admins to soft-delete multiple policies locally with `ignored_at` flag, preventing re-sync
**Independent Test**: Select 15 policies → bulk delete → verify `ignored_at` set, policies hidden from listings, audit log created, Intune unchanged
### Tests for User Story 1
- [ ] T014 [P] [US1] Write unit test for BulkPolicyDeleteJob in tests/Unit/BulkPolicyDeleteJobTest.php
- [ ] T015 [P] [US1] Write feature test for bulk delete <20 items (sync) in tests/Feature/BulkDeletePoliciesTest.php
- [ ] T016 [P] [US1] Write feature test for bulk delete ≥20 items (async) in tests/Feature/BulkDeletePoliciesAsyncTest.php
- [ ] T017 [P] [US1] Write permission test for bulk delete in tests/Unit/BulkActionPermissionTest.php
### Implementation for User Story 1
- [ ] T018 [P] [US1] Create BulkPolicyDeleteJob in app/Jobs/BulkPolicyDeleteJob.php
- [ ] T019 [US1] Add bulk delete action to PolicyResource in app/Filament/Resources/PolicyResource.php
- [ ] T020 [US1] Implement type-to-confirm modal (≥20 items) in PolicyResource bulk action
- [ ] T021 [US1] Wire BulkOperationService to create tracking record and dispatch job
- [ ] T022 [US1] Test bulk delete with 10 policies (sync, manual QA)
- [ ] T023 [US1] Test bulk delete with 25 policies (async, manual QA)
- [ ] T024 [US1] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkDeletePoliciesTest.php`
- [ ] T025 [US1] Verify audit log entry created with correct metadata
**Checkpoint**: Bulk delete policies working (sync + async), audit logged, tests passing
---
## Phase 4: User Story 2 - Bulk Export Policies to Backup (Priority: P1)
**Goal**: Enable admins to export multiple policies to a new Backup Set with progress tracking
**Independent Test**: Select 25 policies → export to backup → verify BackupSet created, 25 BackupItems exist, progress notification shown
### Tests for User Story 2
- [ ] T026 [P] [US2] Write unit test for BulkPolicyExportJob in tests/Unit/BulkPolicyExportJobTest.php
- [ ] T027 [P] [US2] Write feature test for bulk export in tests/Feature/BulkExportToBackupTest.php
- [ ] T028 [P] [US2] Write test for export with failures (3/25 fail) in tests/Feature/BulkExportFailuresTest.php
### Implementation for User Story 2
- [ ] T029 [P] [US2] Create BulkPolicyExportJob in app/Jobs/BulkPolicyExportJob.php
- [ ] T030 [US2] Add bulk export action to PolicyResource in app/Filament/Resources/PolicyResource.php
- [ ] T031 [US2] Create export form with backup_name and include_assignments fields
- [ ] T032 [US2] Implement export logic (create BackupSet, capture BackupItems)
- [ ] T033 [US2] Handle partial failures (some policies fail to backup)
- [ ] T034 [US2] Test export with 30 policies (manual QA)
- [ ] T035 [US2] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkExportToBackupTest.php`
**Checkpoint**: Bulk export working, BackupSets created, failures handled gracefully
---
## Phase 5: User Story 5 - Type-to-Confirm (Priority: P1)
**Goal**: Require typing "DELETE" for destructive operations with ≥20 items
**Independent Test**: Bulk delete 25 policies → modal requires "DELETE" → button disabled until correct input → operation proceeds
**Note**: This is implemented within US1 (T020) but tested separately here
### Tests for User Story 5
- [ ] T036 [P] [US5] Write test for type-to-confirm with correct input in tests/Feature/BulkTypeToConfirmTest.php
- [ ] T037 [P] [US5] Write test for type-to-confirm with incorrect input (lowercase "delete")
- [ ] T038 [P] [US5] Write test for type-to-confirm disabled for <20 items
### Validation for User Story 5
- [ ] T039 [US5] Manual test: Bulk delete 10 policies → confirm without typing (should work)
- [ ] T040 [US5] Manual test: Bulk delete 25 policies → type "delete" → button stays disabled
- [ ] T041 [US5] Manual test: Bulk delete 25 policies → type "DELETE" → button enables, operation proceeds
- [ ] T042 [US5] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkTypeToConfirmTest.php`
**Checkpoint**: Type-to-confirm working correctly for all thresholds
---
## Phase 6: User Story 6 - Progress Tracking (Priority: P2)
**Goal**: Show real-time progress for queued bulk operations with Livewire polling
**Independent Test**: Bulk delete 100 policies → progress notification updates every 5s → final notification shows outcomes
### Tests for User Story 6
- [ ] T043 [P] [US6] Write test for progress updates in BulkOperationRun in tests/Unit/BulkOperationRunProgressTest.php
- [ ] T044 [P] [US6] Write feature test for progress notification in tests/Feature/BulkProgressNotificationTest.php
- [ ] T045 [P] [US6] Write test for circuit breaker (abort >50% fail) in tests/Unit/CircuitBreakerTest.php
### Implementation for User Story 6
- [ ] T046 [P] [US6] Create Livewire progress component in app/Livewire/BulkOperationProgress.php
- [ ] T047 [P] [US6] Create progress view in resources/views/livewire/bulk-operation-progress.blade.php
- [ ] T048 [US6] Update BulkPolicyDeleteJob to emit progress after each chunk
- [ ] T049 [US6] Update BulkPolicyExportJob to emit progress after each chunk
- [ ] T050 [US6] Implement circuit breaker logic (abort if >50% fail) in jobs
- [ ] T051 [US6] Add progress polling to Filament notifications or sidebar widget
- [ ] T052 [US6] Test progress with 100 policies (manual QA, observe updates)
- [ ] T053 [US6] Test circuit breaker with mock failures (manual QA)
- [ ] T054 [US6] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkProgressNotificationTest.php`
**Checkpoint**: Progress tracking working, polling updates UI, circuit breaker aborts high-failure jobs
---
## Phase 7: User Story 3 - Bulk Delete Policy Versions (Priority: P2)
**Goal**: Enable admins to prune old policy versions that are NOT referenced and meet retention threshold (>90 days)
**Independent Test**: Select 30 old versions → bulk prune → verify eligible deleted, ineligible skipped with reasons
### Tests for User Story 3
- [ ] T055 [P] [US3] Write unit test for pruneEligible() scope in tests/Unit/PolicyVersionEligibilityTest.php
- [ ] T056 [P] [US3] Write unit test for BulkPolicyVersionPruneJob in tests/Unit/BulkPolicyVersionPruneJobTest.php
- [ ] T057 [P] [US3] Write feature test for bulk prune in tests/Feature/BulkPruneVersionsTest.php
- [ ] T058 [P] [US3] Write test for skip reasons (referenced, too recent, current) in tests/Feature/BulkPruneSkipReasonsTest.php
### Implementation for User Story 3
- [ ] T059 [P] [US3] Create BulkPolicyVersionPruneJob in app/Jobs/BulkPolicyVersionPruneJob.php
- [ ] T060 [US3] Add bulk delete action to PolicyVersionResource in app/Filament/Resources/PolicyVersionResource.php
- [ ] T061 [US3] Implement eligibility check per version in job (reuse pruneEligible scope)
- [ ] T062 [US3] Collect skip reasons for ineligible versions
- [ ] T063 [US3] Add type-to-confirm for ≥20 versions
- [ ] T064 [US3] Test prune with 30 versions (15 eligible, 15 ineligible) - manual QA
- [ ] T065 [US3] Verify skip reasons in notification and audit log
- [ ] T066 [US3] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkPruneVersionsTest.php`
**Checkpoint**: Policy versions pruning working, eligibility enforced, skip reasons logged
---
## Phase 8: User Story 4 - Bulk Delete Restore Runs (Priority: P2)
**Goal**: Enable admins to delete completed/failed restore runs to declutter history
**Independent Test**: Select 20 completed runs → bulk delete → verify soft-deleted, running runs skipped
### Tests for User Story 4
- [ ] T067 [P] [US4] Write unit test for deletable() scope in tests/Unit/RestoreRunDeletableTest.php
- [ ] T068 [P] [US4] Write unit test for BulkRestoreRunDeleteJob in tests/Unit/BulkRestoreRunDeleteJobTest.php
- [ ] T069 [P] [US4] Write feature test for bulk delete restore runs in tests/Feature/BulkDeleteRestoreRunsTest.php
- [ ] T070 [P] [US4] Write test for mixed statuses (skip running) in tests/Feature/BulkDeleteMixedStatusTest.php
### Implementation for User Story 4
- [ ] T071 [P] [US4] Create BulkRestoreRunDeleteJob in app/Jobs/BulkRestoreRunDeleteJob.php
- [ ] T072 [US4] Add bulk delete action to RestoreRunResource in app/Filament/Resources/RestoreRunResource.php
- [ ] T073 [US4] Filter by deletable() scope (completed, failed, aborted only)
- [ ] T074 [US4] Skip running restore runs with warning
- [ ] T075 [US4] Add type-to-confirm for ≥20 runs
- [ ] T076 [US4] Test delete with 20 completed + 5 running (manual QA, verify 5 skipped)
- [ ] T077 [US4] Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkDeleteRestoreRunsTest.php`
**Checkpoint**: Restore runs bulk delete working, running runs protected, skip warnings shown
---
## Phase 9: Additional Resource - Bulk Delete Backup Sets (Priority: P2)
**Goal**: Enable admins to delete backup sets with cascade-delete of backup items
**Independent Test**: Select 10 backup sets → bulk delete → verify sets deleted, items cascade-deleted
### Tests for Additional Resource
- [ ] T078 [P] Write unit test for BulkBackupSetDeleteJob in tests/Unit/BulkBackupSetDeleteJobTest.php
- [ ] T079 [P] Write feature test for bulk delete backup sets in tests/Feature/BulkDeleteBackupSetsTest.php
### Implementation for Additional Resource
- [ ] T080 [P] Create BulkBackupSetDeleteJob in app/Jobs/BulkBackupSetDeleteJob.php
- [ ] T081 Add bulk delete action to BackupSetResource in app/Filament/Resources/BackupSetResource.php
- [ ] T082 Verify cascade-delete logic for backup items (should be automatic via foreign key)
- [ ] T083 Add type-to-confirm for ≥10 sets
- [ ] T084 Test delete with 15 backup sets (manual QA)
- [ ] T085 Run tests: `./vendor/bin/sail artisan test tests/Feature/BulkDeleteBackupSetsTest.php`
**Checkpoint**: Backup sets bulk delete working, cascade-delete verified
---
## Phase 10: Polish & Cross-Cutting Concerns
**Purpose**: Documentation, cleanup, performance optimization
- [ ] T086 [P] Update README.md with bulk operations feature description
- [ ] T087 [P] Update quickstart.md with manual testing scenarios (already done in planning)
- [ ] T088 Code cleanup: Remove debug statements, refactor duplicated logic
- [ ] T089 Performance test: Bulk delete 500 policies (should complete <5 minutes)
- [ ] T090 Load test: Concurrent bulk operations (2-3 admins, different resources)
- [ ] T091 [P] Security review: Verify tenant isolation in all jobs
- [ ] T092 [P] Permission audit: Verify all bulk actions respect RBAC
- [ ] T093 Run full test suite: `./vendor/bin/sail artisan test`
- [ ] T094 Run Pint formatting: `./vendor/bin/sail composer pint`
- [ ] T095 Manual QA checklist: Complete all scenarios from quickstart.md
- [ ] T096 Document configuration options (chunk size, polling interval, retention days)
- [ ] T097 Create BulkOperationRun resource page in Filament (view progress, retry failed)
- [ ] T098 Add bulk operation metrics to dashboard (total runs, success rate)
**Checkpoint**: Feature polished, tested, documented, ready for staging deployment
---
## Dependencies & Execution Order
### Phase Dependencies
```
Setup (Phase 1)
Foundational (Phase 2) ← BLOCKS all user stories
┌───────────────────────────────────┐
│ User Stories (Parallel Capable) │
├───────────────────────────────────┤
│ US1: Bulk Delete Policies (P1) │ ← MVP
│ US2: Bulk Export (P1) │ ← MVP
│ US5: Type-to-Confirm (P1) │ ← Embedded in US1
├───────────────────────────────────┤
│ US6: Progress Tracking (P2) │ ← Enhances US1, US2
│ US3: Prune Versions (P2) │
│ US4: Delete Runs (P2) │
│ Additional: Delete Sets (P2) │
└───────────────────────────────────┘
Polish (Phase 10)
```
### User Story Dependencies
- **US1 (P1)**: Depends on Foundational (T007, T010, T011). Fully independent after that.
- **US2 (P1)**: Depends on Foundational (T010). Fully independent after that.
- **US5 (P1)**: Implemented within US1 (T020), tested separately.
- **US6 (P2)**: Depends on US1 and US2 (adds progress to existing jobs). Can be implemented after US1/US2 are functional.
- **US3 (P2)**: Depends on Foundational (T008, T010). Fully independent.
- **US4 (P2)**: Depends on Foundational (T009, T010). Fully independent.
- **Additional (P2)**: Depends on Foundational (T010). Fully independent.
### Parallel Opportunities Within Phases
**Setup (Phase 1)**:
- T003, T004 can run in parallel (different files)
**Foundational (Phase 2)**:
- T008, T009, T012 can run in parallel (different files)
- T007, T010, T011 must be sequential (modify same services)
**User Story 1 Tests (T014-T017)**: All parallel (different test files)
**User Story 1 Implementation**:
- T018 parallel with T019-T021 (different files initially)
- T019-T021 sequential (same file edits)
- T022-T025 sequential (testing/validation)
**User Story 2 Tests (T026-T028)**: All parallel
**User Story 2 Implementation**:
- T029 parallel with T030-T031 (different files)
- T030-T035 sequential (same file, progressive features)
**User Story 3-4 and Additional**: Can all run in parallel after Foundational complete (different resources, no overlap)
### Critical Path (Fastest Route to MVP)
```
T001 → T002 → T005 (Setup migrations, run)
T007 → T010 → T011 (Foundational: Policy scope, AuditLogger, SyncJob)
T014-T017 (US1 tests) → T018 → T019 → T020 (US1 core) → T024 (verify)
MVP Ready: Bulk delete policies with type-to-confirm
```
**Estimated MVP Time**: ~12-16 hours (Setup + Foundational + US1)
---
## Parallel Example: User Story 1 Implementation
If working with a team, these tasks can run concurrently:
**Developer A**:
```bash
# Write tests first (TDD)
tests/Unit/BulkPolicyDeleteJobTest.php (T014)
tests/Feature/BulkDeletePoliciesTest.php (T015)
```
**Developer B** (after foundational complete):
```bash
# Implement job
app/Jobs/BulkPolicyDeleteJob.php (T018)
```
**Developer C** (after T018 complete):
```bash
# Wire up Filament UI
app/Filament/Resources/PolicyResource.php (T019-T021)
```
**Developer A** (after implementation complete):
```bash
# Run tests, verify passing
./vendor/bin/sail artisan test tests/Feature/BulkDeletePoliciesTest.php (T024)
```
---
## Parallel Example: Multiple User Stories
After Foundational phase completes, these can proceed in parallel (different team members):
**Team Member 1**: US1 Bulk Delete Policies (T014-T025)
**Team Member 2**: US2 Bulk Export (T026-T035)
**Team Member 3**: US3 Prune Versions (T055-T066)
**Team Member 4**: US6 Progress Tracking (T043-T054)
All integrate at the end without conflicts (different resources/files).
---
## Testing Strategy
### Unit Tests (tests/Unit/)
- BulkPolicyDeleteJob
- BulkPolicyExportJob
- BulkPolicyVersionPruneJob
- BulkBackupSetDeleteJob
- BulkRestoreRunDeleteJob
- BulkActionPermission
- PolicyVersion::pruneEligible scope
- RestoreRun::deletable scope
- BulkOperationRun progress helpers
- Circuit breaker logic
### Feature Tests (tests/Feature/)
- BulkDeletePolicies (sync, async)
- BulkExportToBackup
- BulkTypeToConfirm
- BulkProgressNotification
- BulkPruneVersions (eligibility, skip reasons)
- BulkDeleteRestoreRuns (mixed statuses)
- BulkDeleteBackupSets (cascade)
### Manual QA Scenarios (from quickstart.md)
1. Bulk delete 10 policies (sync, no type-to-confirm)
2. Bulk delete 25 policies (async, type-to-confirm)
3. Bulk export 30 policies (progress tracking)
4. Bulk prune 30 versions (eligibility checks)
5. Circuit breaker with mock failures (>50% fail)
---
## Implementation Strategy
### MVP First (P1 Features Only)
**Goal**: Ship minimal viable feature to get user feedback
**Scope**:
- Setup (T001-T006)
- Foundational (T007-T013)
- US1: Bulk Delete Policies (T014-T025)
- US2: Bulk Export (T026-T035)
- US5: Type-to-Confirm (T036-T042) - already in US1
**Estimated Time**: 16-22 hours
**Deliverable**: Admins can bulk delete and export policies with safety gates
### Iteration 2 (P2 Features)
**Goal**: Add progress tracking and additional resources
**Scope**:
- US6: Progress Tracking (T043-T054)
- US3: Prune Versions (T055-T066)
- US4: Delete Runs (T067-T077)
- Additional: Delete Sets (T078-T085)
**Estimated Time**: 10-12 hours
**Deliverable**: Full feature set with progress UI and all resources
### Iteration 3 (Polish)
**Goal**: Production readiness
**Scope**:
- Polish (T086-T098)
- Performance testing
- Security audit
- Documentation finalization
**Estimated Time**: 4-6 hours
**Deliverable**: Production-ready feature
---
## Success Criteria
- ✅ All P1 tests passing (US1, US2, US5)
- ✅ Bulk delete 100 policies in <2 minutes
- ✅ Type-to-confirm prevents accidents (≥20 items)
- ✅ Progress updates every 5-10s for queued jobs
- ✅ Audit log captures per-item outcomes
- ✅ Circuit breaker aborts at >50% failure rate
- ✅ Tenant isolation enforced (verified via tests)
- ✅ Manual QA checklist complete (5 scenarios)
---
## Total Task Count
- **Setup**: 6 tasks (T001-T006)
- **Foundational**: 7 tasks (T007-T013)
- **US1**: 12 tasks (T014-T025)
- **US2**: 10 tasks (T026-T035)
- **US5**: 7 tasks (T036-T042)
- **US6**: 12 tasks (T043-T054)
- **US3**: 12 tasks (T055-T066)
- **US4**: 11 tasks (T067-T077)
- **Additional**: 8 tasks (T078-T085)
- **Polish**: 13 tasks (T086-T098)
**Total**: 98 tasks
**MVP Scope**: 35 tasks (Setup + Foundational + US1 + US2 + US5)
**Full P1/P2 Scope**: 85 tasks (all user stories)
**Production Ready**: 98 tasks (including polish)
---
**Status**: Tasks Ready for Implementation
**Next Step**: Begin Phase 1 (Setup) → Run migrations → Start US1 tests