TenantAtlas/specs/054-unify-runs-suitewide/tasks.md

210 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
description: "Task list for feature implementation"
---
# Tasks: Unified Operations Runs Suitewide (054)
**Input**: Design documents from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/054-unify-runs-suitewide/`
**Prerequisites**: `specs/054-unify-runs-suitewide/plan.md`, `specs/054-unify-runs-suitewide/spec.md`, `specs/054-unify-runs-suitewide/data-model.md`, `specs/054-unify-runs-suitewide/research.md`, `specs/054-unify-runs-suitewide/quickstart.md`, `specs/054-unify-runs-suitewide/contracts/`
**Tests**: Required (Pest) for runtime behavior changes.
**Operations**: Long-running/queued/remote/scheduled actions MUST create/reuse a canonical `OperationRun` and link to Monitoring → Operations. Monitoring pages MUST be DB-only at render time (no remote calls).
## Format: `[ID] [P?] [Story?] Description`
- **[P]**: Can run in parallel (different files, no blocking dependencies)
- **[Story]**: User story label (e.g., `[US1]`, `[US2]`, `[US3]`) — REQUIRED for story phases only
- Each task includes at least one concrete file path
## Path Conventions (Laravel Monolith)
- Source: `app/`, `routes/`, `resources/`, `config/`, `database/`
- Tests: `tests/Feature/`, `tests/Unit/`
---
## Phase 1: Setup (Spec + Contract Alignment)
**Purpose**: Resolve ambiguity before implementation starts
- [x] T001 Validate Phase 1 run type set is consistent (adoption set + FR-003 + identity rules) in `specs/054-unify-runs-suitewide/spec.md`
- [x] T002 Validate Monitoring Operations routes match Filament surface + OpenAPI contract in `specs/054-unify-runs-suitewide/contracts/routes.md` and `specs/054-unify-runs-suitewide/contracts/admin-pages.openapi.yaml`
- [x] T003 Validate `OperationRunService` contract + quickstart usage examples align with intended API in `specs/054-unify-runs-suitewide/contracts/service_interface.md` and `specs/054-unify-runs-suitewide/quickstart.md`
- [x] T004 Confirm FR-019 (Audit-only) is out-of-scope for 054 unless an audit-only action is touched; if touched, add AuditLog implementation + tests per `specs/054-unify-runs-suitewide/spec.md` in `specs/054-unify-runs-suitewide/tasks.md`
---
## Phase 2: Foundational (Canonical Run Primitive)
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
- [x] T005 Create `operation_runs` migration (columns + indexes + partial unique index) in `database/migrations/*_create_operation_runs_table.php`
- [x] T006 Create `OperationRun` Eloquent model (casts + relationships + helpers) in `app/Models/OperationRun.php`
- [x] T007 [P] Add `OperationRunStatus` enum in `app/Support/OperationRunStatus.php`
- [x] T008 [P] Add `OperationRunOutcome` enum (stored tokens vs UI labels; `cancelled` reserved) in `app/Support/OperationRunOutcome.php`
- [x] T009 [P] Add `OperationRunType` enum (Phase 1 run types) in `app/Support/OperationRunType.php`
- [x] T010 [P] Add `OperationRunFactory` for tests in `database/factories/OperationRunFactory.php`
- [x] T011 Implement idempotent create/reuse + lifecycle updates + failure sanitization in `app/Services/OperationRunService.php` (depends on T005T010)
- [x] T012 Centralize “View run” + deep links in `app/Support/OperationRunLinks.php` (depends on T011)
- [x] T013 [P] Implement tenant-scoped authorization policy in `app/Policies/OperationRunPolicy.php`
- [x] T014 Register `OperationRun` policy with Gate in `app/Providers/AppServiceProvider.php`
- [x] T015 Implement job middleware lifecycle tracking in `app/Jobs/Middleware/TrackOperationRun.php` (depends on T011)
- [x] T016 Implement 90-day retention pruning job in `app/Jobs/PruneOldOperationRunsJob.php`
- [x] T017 Schedule pruning job daily with non-overlapping lock (`withoutOverlapping` or equivalent cache lock) in `routes/console.php`
- [x] T018 Add scheduled pruning non-overlap regression test (if feasible) in `tests/Feature/Scheduling/PruneOldOperationRunsScheduleTest.php`
- [x] T019 Add `OperationRunService` tests (hash stability, idempotency, unique-index race, sanitization) in `tests/Feature/OperationRunServiceTest.php`
- [x] T020 Add `TrackOperationRun` middleware lifecycle tests in `tests/Feature/TrackOperationRunMiddlewareTest.php`
---
## Phase 3: User Story 1 - See Every Supported Operation in Monitoring (Priority: P1)
**Goal**: Monitoring → Operations shows all canonical runs (tenant-scoped) with list + detail, filters, and safe failures.
**Independent Test**: Trigger at least one run of each Phase 1 run producer, then verify list/detail in Monitoring render DB-only and are tenant-scoped per `specs/054-unify-runs-suitewide/spec.md`.
### Tests for User Story 1
- [x] T021 [US1] Add Monitoring list/detail authorization + tenant isolation tests in `tests/Feature/MonitoringOperationsTest.php`
- [x] T022 [P] [US1] Add Monitoring DB-only render test (mock Graph client; assert never called) in `tests/Feature/MonitoringOperationsTest.php`
- [x] T023 [P] [US1] Add restore adapter visibility tests (created/visible from `previewed` onward; `previewed` maps to `queued/pending`) in `tests/Feature/RestoreAdapterTest.php`
### Implementation for User Story 1
- [x] T024 [US1] Create Filament Monitoring resource (list + view-only) in `app/Filament/Resources/OperationRunResource.php`
- [x] T025 [US1] Implement list columns + default sort + default last-30-days window in `app/Filament/Resources/OperationRunResource.php`
- [x] T026 [US1] Implement list filters (type, state bucket, time range, initiator) in `app/Filament/Resources/OperationRunResource.php`
- [x] T027 [US1] Implement run detail view (meta, summary_counts, failures, context, links) in `app/Filament/Resources/OperationRunResource/Pages/ViewOperationRun.php`
- [x] T028 [US1] Implement related links for each Phase 1 run type in `app/Support/OperationRunLinks.php`
- [x] T029 [US1] Implement RestoreRun → OperationRun adapter create/update (from `previewed` onward; `previewed` maps to `status=queued`, `outcome=pending`) in `app/Listeners/SyncRestoreRunToOperationRun.php`
- [x] T030 [US1] Wire RestoreRun lifecycle events to adapter in `app/Observers/RestoreRunObserver.php`
- [x] T031 [US1] Register RestoreRun observer in `app/Providers/AppServiceProvider.php`
---
## Phase 4: User Story 2 - Start Operations Without Blocking (Priority: P2)
**Goal**: Start surfaces are enqueue-only, return immediate confirmation + “View run”, and jobs update canonical run lifecycle.
**Independent Test**: Start each Phase 1 operation from its owning UI and confirm the request returns quickly, includes “View run”, and the run progresses queued → running → terminal outcome.
### Tests for User Story 2
- [x] T032 [P] [US2] Add Inventory “Sync now” start-surface tests in `tests/Feature/Inventory/InventorySyncStartSurfaceTest.php`
- [x] T033 [P] [US2] Add Policies “Sync now” start-surface tests in `tests/Feature/PolicySyncStartSurfaceTest.php`
- [x] T034 [P] [US2] Add Directory Groups “Sync groups” start-surface tests in `tests/Feature/DirectoryGroups/StartSyncFromGroupsPageTest.php`
- [x] T035 [P] [US2] Add Drift “Generate drift” start-surface tests in `tests/Feature/Drift/DriftGenerationDispatchTest.php`
- [x] T036 [P] [US2] Add Backup Set “Add policies” start-surface tests in `tests/Feature/BackupSets/AddPoliciesStartSurfaceTest.php`
- [x] T037 [P] [US2] Add Backup Schedule “Run now/Retry” start-surface tests in `tests/Feature/BackupScheduling/RunNowRetryActionsTest.php`
- [x] T067 [P] [US2] Add Backup Set “Remove policies” (row + bulk) start-surface tests in `tests/Feature/BackupSets/RemovePoliciesStartSurfaceTest.php` and `tests/Feature/Filament/BackupItemsBulkRemoveTest.php`
- [x] T038 [P] [US2] Add “queued + terminal” notification tests (initiator only; safe content) in `tests/Feature/Notifications/OperationRunNotificationTest.php`
### Implementation for User Story 2
- [x] T039 [P] [US2] Refactor Inventory “Sync now” to ensure run + dispatch + “View run” in `app/Filament/Pages/InventoryLanding.php`
- [x] T040 [P] [US2] Refactor Policies “Sync now” to ensure run + dispatch + “View run” in `app/Filament/Resources/PolicyResource/Pages/ListPolicies.php`
- [x] T041 [P] [US2] Refactor Directory Groups “Sync groups” to ensure run + dispatch + “View run” in `app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php`
- [x] T042 [P] [US2] Refactor Drift “Generate drift” (manual + auto-on-open) to ensure run + dispatch + “View run” in `app/Filament/Pages/DriftLanding.php`
- [x] T043 [P] [US2] Refactor Backup Set “Add policies” Livewire action to ensure run + dispatch + “View run” in `app/Livewire/BackupSetPolicyPickerTable.php`
- [x] T044 [P] [US2] Refactor Backup Schedule “Run now/Retry” actions to ensure run + dispatch + “View run” in `app/Filament/Resources/BackupScheduleResource.php`
- [x] T068 [P] [US2] Refactor Backup Set “Remove policies” actions (row + bulk) to ensure run + dispatch + “View run” in `app/Filament/Resources/BackupSetResource/RelationManagers/BackupItemsRelationManager.php` and `app/Jobs/RemovePoliciesFromBackupSetJob.php`
- [x] T045 [P] [US2] Instrument inventory sync job run lifecycle + summary/failures in `app/Jobs/RunInventorySyncJob.php`
- [x] T046 [P] [US2] Instrument policy sync job run lifecycle + summary/failures in `app/Jobs/SyncPoliciesJob.php`
- [x] T047 [P] [US2] Instrument groups sync job run lifecycle + summary/failures in `app/Jobs/EntraGroupSyncJob.php`
- [x] T048 [P] [US2] Instrument drift generation job run lifecycle + summary/failures in `app/Jobs/GenerateDriftFindingsJob.php`
- [x] T049 [P] [US2] Instrument backup set “add policies” job run lifecycle + summary/failures in `app/Jobs/AddPoliciesToBackupSetJob.php`
- [x] T050 [P] [US2] Instrument backup schedule job run lifecycle + summary/failures in `app/Jobs/RunBackupScheduleJob.php`
- [x] T051 [US2] Implement queued notification (after successful dispatch) in `app/Notifications/OperationRunQueued.php`
- [x] T052 [US2] Implement terminal outcome notification (succeeded/partial/failed) in `app/Notifications/OperationRunCompleted.php`
- [x] T053 [US2] Emit notifications from canonical lifecycle updates (initiator only) in `app/Services/OperationRunService.php`
- [x] T054 [US2] Handle queue dispatch failures (fail fast; no misleading queued runs) in `app/Services/OperationRunService.php`
---
## Phase 5: User Story 3 - Duplicate Starts Reuse the Same Active Run (Priority: P3)
**Goal**: Duplicate starts reuse the same active run (dedupe), enforced at DB level and validated by tests.
**Independent Test**: Start the same operation twice with identical effective inputs while the first is queued/running and verify the system reuses the active run.
### Tests for User Story 3
- [x] T055 [US3] Add service-level dedupe + race-collision tests in `tests/Feature/OperationRunServiceTest.php`
- [x] T056 [US3] Add end-to-end “reuse active run” test for at least one producer in `tests/Feature/PolicySyncStartSurfaceTest.php`
### Implementation for User Story 3
- [x] T057 [US3] Normalize identity inputs before hashing (stable JSON; ignore initiator) in `app/Services/OperationRunService.php`
- [x] T058 [P] [US3] Ensure `inventory.sync` identity inputs follow FR-010 in `app/Filament/Pages/InventoryLanding.php`
- [x] T059 [P] [US3] Ensure `policy.sync` identity inputs follow FR-010 in `app/Filament/Resources/PolicyResource/Pages/ListPolicies.php`
- [x] T060 [P] [US3] Ensure `directory_groups.sync` identity inputs follow FR-010 in `app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php`
- [x] T061 [P] [US3] Ensure `drift.generate` identity inputs follow FR-010 in `app/Filament/Pages/DriftLanding.php`
- [x] T062 [P] [US3] Ensure `backup_set.add_policies` identity inputs follow FR-010 in `app/Livewire/BackupSetPolicyPickerTable.php`
- [x] T063 [P] [US3] Ensure `backup_schedule.run_now`/`backup_schedule.retry` identity inputs follow FR-010 in `app/Filament/Resources/BackupScheduleResource.php`
---
## Phase 6: Polish & Cross-Cutting Concerns
- [x] T064 [P] Run formatter on changed files via `./vendor/bin/pint --dirty`
- [x] T065 Run targeted tests for this feature via `./vendor/bin/sail artisan test tests/Feature/MonitoringOperationsTest.php`
- [x] T066 Run quickstart scenarios and update docs if needed in `specs/054-unify-runs-suitewide/quickstart.md`
---
## Dependencies & Execution Order
### Phase Dependencies
- Setup (Phase 1) → blocks Foundational
- Foundational (Phase 2) → blocks US1/US2/US3
- US1/US2/US3 can proceed after Phase 2 (parallel if staffed, or sequential P1 → P2 → P3)
- Polish (Phase 6) depends on the desired user stories being complete
### User Story Dependencies (Graph)
```text
Foundational
├─ US1 (Monitoring UI)
├─ US2 (Start surfaces + lifecycle + notifications)
└─ US3 (Dedupe + identity + race handling)
```
---
## Parallel Execution Examples
After Phase 2, these can run in parallel (different files/modules):
### US1 (Monitoring UI)
- `T023` (restore adapter tests) + `T024` (resource scaffold) + `T029` (restore adapter listener)
### US2 (Start surfaces + lifecycle + notifications)
- Tests: `T032``T038`
- Producers/start surfaces: `T039``T044`
- Workers/job instrumentation: `T045``T050`
- Notification classes: `T051` + `T052`
### US3 (Dedupe + identity + race handling)
- Identity review per producer: `T058``T063`
---
## Implementation Strategy
### MVP First (US1 Only)
1. Complete Phase 12 (canonical run primitive)
2. Complete US1 (Monitoring list/detail + tenant isolation)
3. Validate Monitoring renders DB-only and is tenant-scoped
### Incremental Delivery
1. Add US2 producers/workers + notifications
2. Add US3 dedupe + race validation
3. Polish (formatting, targeted tests, quickstart validation)