---
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 T005–T010)
- [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 1–2 (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)

