From 9eb3a849e2db89a216f96df5c025775a3f9d0121 Mon Sep 17 00:00:00 2001 From: Ahmed Darrazi Date: Mon, 22 Dec 2025 01:32:05 +0100 Subject: [PATCH] feat(005): Generate task breakdown for Bulk Operations feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- specs/005-bulk-operations/tasks.md | 485 +++++++++++++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 specs/005-bulk-operations/tasks.md diff --git a/specs/005-bulk-operations/tasks.md b/specs/005-bulk-operations/tasks.md new file mode 100644 index 0000000..1e5ff4d --- /dev/null +++ b/specs/005-bulk-operations/tasks.md @@ -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