Summary Kurz: Implementiert Feature 054 — canonical OperationRun-flow, Monitoring UI, dispatch-safety, notifications, dedupe, plus small UX safety clarifications (RBAC group search delegated; Restore group mapping DB-only). What Changed Core service: OperationRun lifecycle, dedupe and dispatch helpers — OperationRunService.php. Model + migration: OperationRun model and migration — OperationRun.php, 2026_01_16_180642_create_operation_runs_table.php. Notifications: queued + terminal DB notifications (initiator-only) — OperationRunQueued.php, OperationRunCompleted.php. Monitoring UI: Filament list/detail + Livewire pieces (DB-only render) — OperationRunResource.php and related pages/views. Start surfaces / Jobs: instrumented start surfaces, job middleware, and job updates to use canonical runs — multiple app/Jobs/* and app/Filament/* updates (see tests for full coverage). RBAC + Restore UX clarifications: RBAC group search is delegated-Graph-based and disabled without delegated token; Restore group mapping remains DB-only (directory cache) and helper text always visible — TenantResource.php, RestoreRunResource.php. Specs / Constitution: updated spec & quickstart and added one-line constitution guideline about Graph usage: spec.md quickstart.md constitution.md Tests & Verification Unit / Feature tests added/updated for run lifecycle, notifications, idempotency, and UI guards: see tests/Feature/* (notably OperationRunServiceTest, MonitoringOperationsTest, OperationRunNotificationTest, and various Filament feature tests). Full test run locally: ./vendor/bin/sail artisan test → 587 passed, 5 skipped. Migrations Adds create_operation_runs_table migration; run php artisan migrate in staging after review. Notes / Rationale Monitoring pages are explicitly DB-only at render time (no Graph calls). Start surfaces enqueue work only and return a “View run” link. Delegated Graph access is used only for explicit user actions (RBAC group search); restore mapping intentionally uses cached DB data only to avoid render-time Graph calls. Dispatch wrapper marks runs failed immediately if background dispatch throws synchronously to avoid misleading “queued” states. Upgrade / Deploy Considerations Run migrations: ./vendor/bin/sail artisan migrate. Background workers should be running to process queued jobs (recommended to monitor queue health during rollout). No secret or token persistence changes. PR checklist Tests updated/added for changed behavior Specs updated: 054-unify-runs-suitewide docs + quickstart Constitution note added (.specify) Pint formatting applied Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #63
14 KiB
| 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
- T001 Validate Phase 1 run type set is consistent (adoption set + FR-003 + identity rules) in
specs/054-unify-runs-suitewide/spec.md - T002 Validate Monitoring Operations routes match Filament surface + OpenAPI contract in
specs/054-unify-runs-suitewide/contracts/routes.mdandspecs/054-unify-runs-suitewide/contracts/admin-pages.openapi.yaml - T003 Validate
OperationRunServicecontract + quickstart usage examples align with intended API inspecs/054-unify-runs-suitewide/contracts/service_interface.mdandspecs/054-unify-runs-suitewide/quickstart.md - 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.mdinspecs/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
- T005 Create
operation_runsmigration (columns + indexes + partial unique index) indatabase/migrations/*_create_operation_runs_table.php - T006 Create
OperationRunEloquent model (casts + relationships + helpers) inapp/Models/OperationRun.php - T007 [P] Add
OperationRunStatusenum inapp/Support/OperationRunStatus.php - T008 [P] Add
OperationRunOutcomeenum (stored tokens vs UI labels;cancelledreserved) inapp/Support/OperationRunOutcome.php - T009 [P] Add
OperationRunTypeenum (Phase 1 run types) inapp/Support/OperationRunType.php - T010 [P] Add
OperationRunFactoryfor tests indatabase/factories/OperationRunFactory.php - T011 Implement idempotent create/reuse + lifecycle updates + failure sanitization in
app/Services/OperationRunService.php(depends on T005–T010) - T012 Centralize “View run” + deep links in
app/Support/OperationRunLinks.php(depends on T011) - T013 [P] Implement tenant-scoped authorization policy in
app/Policies/OperationRunPolicy.php - T014 Register
OperationRunpolicy with Gate inapp/Providers/AppServiceProvider.php - T015 Implement job middleware lifecycle tracking in
app/Jobs/Middleware/TrackOperationRun.php(depends on T011) - T016 Implement 90-day retention pruning job in
app/Jobs/PruneOldOperationRunsJob.php - T017 Schedule pruning job daily with non-overlapping lock (
withoutOverlappingor equivalent cache lock) inroutes/console.php - T018 Add scheduled pruning non-overlap regression test (if feasible) in
tests/Feature/Scheduling/PruneOldOperationRunsScheduleTest.php - T019 Add
OperationRunServicetests (hash stability, idempotency, unique-index race, sanitization) intests/Feature/OperationRunServiceTest.php - T020 Add
TrackOperationRunmiddleware lifecycle tests intests/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
- T021 [US1] Add Monitoring list/detail authorization + tenant isolation tests in
tests/Feature/MonitoringOperationsTest.php - T022 [P] [US1] Add Monitoring DB-only render test (mock Graph client; assert never called) in
tests/Feature/MonitoringOperationsTest.php - T023 [P] [US1] Add restore adapter visibility tests (created/visible from
previewedonward;previewedmaps toqueued/pending) intests/Feature/RestoreAdapterTest.php
Implementation for User Story 1
- T024 [US1] Create Filament Monitoring resource (list + view-only) in
app/Filament/Resources/OperationRunResource.php - T025 [US1] Implement list columns + default sort + default last-30-days window in
app/Filament/Resources/OperationRunResource.php - T026 [US1] Implement list filters (type, state bucket, time range, initiator) in
app/Filament/Resources/OperationRunResource.php - T027 [US1] Implement run detail view (meta, summary_counts, failures, context, links) in
app/Filament/Resources/OperationRunResource/Pages/ViewOperationRun.php - T028 [US1] Implement related links for each Phase 1 run type in
app/Support/OperationRunLinks.php - T029 [US1] Implement RestoreRun → OperationRun adapter create/update (from
previewedonward;previewedmaps tostatus=queued,outcome=pending) inapp/Listeners/SyncRestoreRunToOperationRun.php - T030 [US1] Wire RestoreRun lifecycle events to adapter in
app/Observers/RestoreRunObserver.php - 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
- T032 [P] [US2] Add Inventory “Sync now” start-surface tests in
tests/Feature/Inventory/InventorySyncStartSurfaceTest.php - T033 [P] [US2] Add Policies “Sync now” start-surface tests in
tests/Feature/PolicySyncStartSurfaceTest.php - T034 [P] [US2] Add Directory Groups “Sync groups” start-surface tests in
tests/Feature/DirectoryGroups/StartSyncFromGroupsPageTest.php - T035 [P] [US2] Add Drift “Generate drift” start-surface tests in
tests/Feature/Drift/DriftGenerationDispatchTest.php - T036 [P] [US2] Add Backup Set “Add policies” start-surface tests in
tests/Feature/BackupSets/AddPoliciesStartSurfaceTest.php - T037 [P] [US2] Add Backup Schedule “Run now/Retry” start-surface tests in
tests/Feature/BackupScheduling/RunNowRetryActionsTest.php - T067 [P] [US2] Add Backup Set “Remove policies” (row + bulk) start-surface tests in
tests/Feature/BackupSets/RemovePoliciesStartSurfaceTest.phpandtests/Feature/Filament/BackupItemsBulkRemoveTest.php - T038 [P] [US2] Add “queued + terminal” notification tests (initiator only; safe content) in
tests/Feature/Notifications/OperationRunNotificationTest.php
Implementation for User Story 2
- T039 [P] [US2] Refactor Inventory “Sync now” to ensure run + dispatch + “View run” in
app/Filament/Pages/InventoryLanding.php - T040 [P] [US2] Refactor Policies “Sync now” to ensure run + dispatch + “View run” in
app/Filament/Resources/PolicyResource/Pages/ListPolicies.php - T041 [P] [US2] Refactor Directory Groups “Sync groups” to ensure run + dispatch + “View run” in
app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php - T042 [P] [US2] Refactor Drift “Generate drift” (manual + auto-on-open) to ensure run + dispatch + “View run” in
app/Filament/Pages/DriftLanding.php - T043 [P] [US2] Refactor Backup Set “Add policies” Livewire action to ensure run + dispatch + “View run” in
app/Livewire/BackupSetPolicyPickerTable.php - T044 [P] [US2] Refactor Backup Schedule “Run now/Retry” actions to ensure run + dispatch + “View run” in
app/Filament/Resources/BackupScheduleResource.php - T068 [P] [US2] Refactor Backup Set “Remove policies” actions (row + bulk) to ensure run + dispatch + “View run” in
app/Filament/Resources/BackupSetResource/RelationManagers/BackupItemsRelationManager.phpandapp/Jobs/RemovePoliciesFromBackupSetJob.php - T045 [P] [US2] Instrument inventory sync job run lifecycle + summary/failures in
app/Jobs/RunInventorySyncJob.php - T046 [P] [US2] Instrument policy sync job run lifecycle + summary/failures in
app/Jobs/SyncPoliciesJob.php - T047 [P] [US2] Instrument groups sync job run lifecycle + summary/failures in
app/Jobs/EntraGroupSyncJob.php - T048 [P] [US2] Instrument drift generation job run lifecycle + summary/failures in
app/Jobs/GenerateDriftFindingsJob.php - T049 [P] [US2] Instrument backup set “add policies” job run lifecycle + summary/failures in
app/Jobs/AddPoliciesToBackupSetJob.php - T050 [P] [US2] Instrument backup schedule job run lifecycle + summary/failures in
app/Jobs/RunBackupScheduleJob.php - T051 [US2] Implement queued notification (after successful dispatch) in
app/Notifications/OperationRunQueued.php - T052 [US2] Implement terminal outcome notification (succeeded/partial/failed) in
app/Notifications/OperationRunCompleted.php - T053 [US2] Emit notifications from canonical lifecycle updates (initiator only) in
app/Services/OperationRunService.php - 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
- T055 [US3] Add service-level dedupe + race-collision tests in
tests/Feature/OperationRunServiceTest.php - 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
- T057 [US3] Normalize identity inputs before hashing (stable JSON; ignore initiator) in
app/Services/OperationRunService.php - T058 [P] [US3] Ensure
inventory.syncidentity inputs follow FR-010 inapp/Filament/Pages/InventoryLanding.php - T059 [P] [US3] Ensure
policy.syncidentity inputs follow FR-010 inapp/Filament/Resources/PolicyResource/Pages/ListPolicies.php - T060 [P] [US3] Ensure
directory_groups.syncidentity inputs follow FR-010 inapp/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php - T061 [P] [US3] Ensure
drift.generateidentity inputs follow FR-010 inapp/Filament/Pages/DriftLanding.php - T062 [P] [US3] Ensure
backup_set.add_policiesidentity inputs follow FR-010 inapp/Livewire/BackupSetPolicyPickerTable.php - T063 [P] [US3] Ensure
backup_schedule.run_now/backup_schedule.retryidentity inputs follow FR-010 inapp/Filament/Resources/BackupScheduleResource.php
Phase 6: Polish & Cross-Cutting Concerns
- T064 [P] Run formatter on changed files via
./vendor/bin/pint --dirty - T065 Run targeted tests for this feature via
./vendor/bin/sail artisan test tests/Feature/MonitoringOperationsTest.php - 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)
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)
- Complete Phase 1–2 (canonical run primitive)
- Complete US1 (Monitoring list/detail + tenant isolation)
- Validate Monitoring renders DB-only and is tenant-scoped
Incremental Delivery
- Add US2 producers/workers + notifications
- Add US3 dedupe + race validation
- Polish (formatting, targeted tests, quickstart validation)