Implements Spec 087: Legacy Runs Removal (rigorous). ### What changed - Canonicalized run history: **`operation_runs` is the only run system** for inventory sync, Entra group sync, backup schedule execution/retention/purge. - Removed legacy UI surfaces (Filament Resources / relation managers) for legacy run models. - Legacy run URLs now return **404** (no redirects), with RBAC semantics preserved (404 vs 403 as specified). - Canonicalized affected `operation_runs.type` values (dotted → underscore) via migration. - Drift + inventory references now point to canonical operation runs; includes backfills and then drops legacy FK columns. - Drops legacy run tables after cutover. - Added regression guards to prevent reintroducing legacy run tokens or “backfilling” canonical runs from legacy tables. ### Migrations - `2026_02_12_000001..000006_*` canonicalize types, add/backfill operation_run_id references, drop legacy columns, and drop legacy run tables. ### Tests Focused pack for this spec passed: - `tests/Feature/Guards/NoLegacyRunsTest.php` - `tests/Feature/Guards/NoLegacyRunBackfillTest.php` - `tests/Feature/Operations/LegacyRunRoutesNotFoundTest.php` - `tests/Feature/Monitoring/MonitoringOperationsTest.php` - `tests/Feature/Jobs/RunInventorySyncJobTest.php` ### Notes / impact - Destructive cleanup is handled via migrations (drops legacy tables) after code cutover; deploy should run migrations in the same release. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #106
13 KiB
| description |
|---|
| Task list for Spec 087 implementation |
Tasks: Legacy Runs Removal (Spec 087)
Input: Design documents from /specs/087-legacy-runs-removal/
Tests: REQUIRED (Pest) because this feature changes runtime behavior.
Phase 1: Setup (Docs + Local Validation)
- T001 Validate and (if needed) update specs/087-legacy-runs-removal/quickstart.md with the exact focused test commands for this spec
- T002 Capture the final run_type allow-list in specs/087-legacy-runs-removal/spec.md (FR-012) and ensure tasks below only create those values
Phase 2: Foundational (Blocking Prerequisites)
⚠️ CRITICAL: Complete this phase before starting any user story work.
- T003 Update canonical run type identifiers to underscore values for this feature only:
- Update app/Support/OperationRunType.php (enum App\Support\OperationRunType) so new runs store the underscore identifiers from FR-012
- Change ONLY the affected enum case values (leave unrelated run types unchanged):
- InventorySync
- DirectoryGroupsSync
- DriftGenerate
- BackupScheduleRunNow
- BackupScheduleRetry
- BackupScheduleScheduled
- Scope note: OperationRun creation accepts a raw string type; enforcement is via standardized usage + tests in this spec (no global renames)
- T004 Create migration database/migrations/2026_02_12_000001_canonicalize_operation_run_types.php to rewrite existing operation_runs.type values (dotted → underscore) for affected workflows (FR-012). Acceptance criteria: perform these rewrites (and only these):
- inventory.sync → inventory_sync
- directory_groups.sync → entra_group_sync
- drift.generate → drift_generate_findings
- backup_schedule.run_now → backup_schedule_run
- backup_schedule.retry → backup_schedule_run
- backup_schedule.scheduled → backup_schedule_run
- T005 [P] Add/adjust OperationRun RBAC semantics tests (404 vs 403) in tests/Feature/Monitoring/MonitoringOperationsTest.php and/or tests/Feature/Operations/ (FR-008)
- T006 [P] Add architecture guard test tests/Feature/Guards/NoLegacyRunsTest.php scanning app/, database/, resources/, routes/ for legacy run tokens (FR-009). Use this initial forbidden token list:
- InventorySyncRun, inventory_sync_runs, InventorySyncRunResource
- EntraGroupSyncRun, entra_group_sync_runs, EntraGroupSyncRunResource
- BackupScheduleRun, backup_schedule_runs, BackupScheduleRunsRelationManager Exclusions (minimum): vendor/, storage/, specs/, spechistory/, references/, bootstrap/cache/
- T007 [P] Remove legacy run badge domains/mappers and rely on OperationRun status/outcome badge domains by updating app/Support/Badges/BadgeDomain.php, app/Support/Badges/BadgeCatalog.php, and tests/Unit/Badges/RunStatusBadgesTest.php (BADGE-001)
- T043 [P] Add explicit “no backfill of legacy run history” regression coverage:
- Confirm no migration/job creates new operation_runs by reading legacy run tables (reference/FK backfills are allowed)
- Add a focused test under tests/Feature/Guards/ or tests/Feature/Database/ to enforce this (FR-010)
NOTE: routes/web.php currently has a legacy convenience redirect (/admin/t/{tenant}/operations → /admin/operations). It is not a legacy run page; keep or change it explicitly as part of US2 decisions.
Checkpoint: Canonical run types are stable, guard exists, and operations RBAC semantics are enforced by tests.
Phase 3: User Story 1 — Single canonical run history (Priority: P1) 🎯 MVP
Goal: New inventory sync, Entra group sync, and backup schedule executions produce exactly one canonical OperationRun each, visible in Operations UI.
Independent Test: Trigger each run type once and verify it appears in the Operations run list and can be opened in the canonical run viewer.
Tests (write first)
- T008 [P] [US1] Update inventory sync run creation expectations in tests/Feature/Inventory/InventorySyncServiceTest.php to assert an operation_runs row exists with type inventory_sync
- T009 [P] [US1] Update Entra group sync expectations in tests/Feature/DirectoryGroups/StartSyncTest.php and tests/Feature/DirectoryGroups/ScheduledSyncDispatchTest.php to assert an operation_runs row exists with type entra_group_sync
- T010 [P] [US1] Update backup schedule run expectations in tests/Feature/BackupScheduling/RunBackupScheduleJobTest.php to assert an operation_runs row exists with type backup_schedule_run
- T011 [P] [US1] Add tests for retention + purge creating independent canonical runs in tests/Feature/BackupScheduling/ApplyRetentionJobTest.php and tests/Feature/Console/PurgeNonPersistentDataCommandTest.php (backup_schedule_retention / backup_schedule_purge)
- T044 [P] [US1] Add/adjust backup schedule tests to cover skipped/canceled schedule runs still producing a canonical operation_run with a clear terminal outcome (spec Edge Case)
Implementation
- T012 [US1] Refactor app/Services/Inventory/InventorySyncService.php to stop creating InventorySyncRun rows and instead create/update a canonical OperationRun (FR-001/FR-002)
- T013 [US1] Refactor app/Jobs/EntraGroupSyncJob.php to stop updating EntraGroupSyncRun and instead create/update a canonical OperationRun (FR-001/FR-002)
- T014 [US1] Refactor app/Jobs/RunBackupScheduleJob.php to stop reading/updating BackupScheduleRun status as the canonical record and instead use a canonical OperationRun with schedule metadata stored in operation_runs.context (FR-001/FR-002)
- T015 [US1] Refactor app/Jobs/ApplyBackupScheduleRetentionJob.php to remove BackupScheduleRun dependency and track retention via a canonical OperationRun (FR-006/FR-011)
- T016 [US1] Refactor app/Console/Commands/TenantpilotPurgeNonPersistentData.php to track purge via a canonical OperationRun and remove BackupScheduleRun queries (FR-006/FR-011)
- T017 [US1] Refactor app/Console/Commands/TenantpilotReconcileBackupScheduleOperationRuns.php to reconcile based on operation_runs only (remove BackupScheduleRun reads) (FR-001/FR-006)
- T018 [US1] Update run status notifications/links to point to canonical run viewer by editing app/Notifications/RunStatusChangedNotification.php and app/Notifications/OperationRunQueued.php (FR-001)
- T019 [US1] Update inventory run “last run” widget links to canonical runs by editing app/Filament/Widgets/Inventory/InventoryKpiHeader.php (FR-001)
Checkpoint: US1 tests pass and every new execution yields a canonical OperationRun of the correct underscore run_type.
Phase 4: User Story 2 — Legacy run UI is intentionally gone (Priority: P1)
Goal: Legacy run pages/resources are removed; old links return 404; no legacy run resources appear in navigation.
Independent Test: Request known legacy run URLs and verify 404; verify navigation has no legacy run resources.
Tests (write first)
- T020 [P] [US2] Replace redirect-based legacy tests with 404 assertions in tests/Feature/Operations/LegacyRunRedirectTest.php (FR-004)
- T021 [P] [US2] Add explicit “legacy run routes not found” coverage in tests/Feature/Operations/LegacyRunRoutesNotFoundTest.php for inventory/entra/backup schedule legacy run URLs (FR-004)
Implementation
- T022 [US2] Remove legacy Inventory Sync run Filament resource by deleting app/Filament/Resources/InventorySyncRunResource.php and app/Filament/Resources/InventorySyncRunResource/Pages/ (FR-003)
- T023 [US2] Remove legacy Entra Group Sync run Filament resource by deleting app/Filament/Resources/EntraGroupSyncRunResource.php and app/Filament/Resources/EntraGroupSyncRunResource/Pages/ (FR-003)
- T024 [US2] Remove legacy backup schedule run history relation manager by deleting app/Filament/Resources/BackupScheduleResource/RelationManagers/BackupScheduleRunsRelationManager.php (FR-003)
- T025 [US2] Remove navigation links to legacy run resources by updating app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php and any other references found under app/Filament/ (FR-003)
- T026 [US2] Remove legacy run UI tests and replace with canonical Operations coverage by updating/deleting tests/Feature/Filament/InventorySyncRunResourceTest.php, tests/Feature/Filament/EntraGroupSyncRunResourceTest.php, and tests/Feature/BackupScheduling/BackupScheduleRunViewModalTest.php (FR-003)
- T027 [US2] Remove legacy run badge mappers now unused by UI by deleting app/Support/Inventory/InventorySyncStatusBadge.php and app/Support/Badges/Domains/EntraGroupSyncRunStatusBadge.php (FR-003/BADGE-001)
NOTE: Badge cleanup is handled by T007. If any legacy badge mapper is still referenced, remove it as part of T007 and treat this note as satisfied.
Checkpoint: Legacy run URLs are 404 (no redirects) and legacy run resources no longer exist.
Phase 5: User Story 3 — Drift references canonical runs (Priority: P1)
Goal: Drift baseline/current/last-seen references use canonical OperationRuns; historical records without a safe mapping render without errors.
Independent Test: Generate drift findings and confirm baseline/current reference canonical run IDs; verify null-safe behavior when mapping is absent.
Tests (write first)
- T028 [P] [US3] Update drift baseline/current selection tests under tests/Feature/Drift/ (directory) to create OperationRun records instead of InventorySyncRun
- T029 [P] [US3] Update RBAC drift landing UI enforcement in tests/Feature/Rbac/DriftLandingUiEnforcementTest.php to avoid InventorySyncRunResource and assert canonical run links
Data model + migrations
- T030 [US3] Create migration database/migrations/2026_02_12_000002_add_operation_run_ids_to_findings_table.php adding findings.baseline_operation_run_id and findings.current_operation_run_id (nullable FKs to operation_runs)
- T031 [US3] Create migration database/migrations/2026_02_12_000003_backfill_findings_operation_run_ids.php that backfills the new findings columns by joining through inventory_sync_runs.operation_run_id (null-safe)
- T032 [US3] Create migration database/migrations/2026_02_12_000004_backfill_inventory_items_last_seen_operation_run_id.php backfilling inventory_items.last_seen_operation_run_id from inventory_items.last_seen_run_id via inventory_sync_runs.operation_run_id
Application changes
- T033 [US3] Refactor drift run selection to use OperationRuns by updating app/Services/Drift/DriftRunSelector.php and app/Services/Drift/DriftScopeKey.php (FR-005)
- T034 [US3] Refactor drift finding generation to accept/use OperationRuns by updating app/Services/Drift/DriftFindingGenerator.php (FR-005)
- T035 [US3] Update drift landing UI to link to canonical OperationRuns (not legacy resources) by updating app/Filament/Pages/DriftLanding.php (FR-003/FR-005)
Cutover + cleanup
- T036 [US3] Create migration database/migrations/2026_02_12_000005_drop_legacy_run_id_columns_from_findings_and_inventory_items.php dropping findings.baseline_run_id/current_run_id and inventory_items.last_seen_run_id after code cutover (FR-005)
Checkpoint: Drift reads/writes canonical operation run references and remains functional with null mappings.
Phase 6: Drop legacy tables (Data + Code)
Purpose: Remove legacy run storage permanently after all cutovers.
- T037 Create migration database/migrations/2026_02_12_000006_drop_legacy_run_tables.php dropping inventory_sync_runs, entra_group_sync_runs, and backup_schedule_runs (FR-001)
- T038 [P] Delete legacy run Eloquent models app/Models/InventorySyncRun.php, app/Models/EntraGroupSyncRun.php, and app/Models/BackupScheduleRun.php (FR-001)
- T039 [P] Delete legacy factories database/factories/InventorySyncRunFactory.php and database/factories/EntraGroupSyncRunFactory.php and update any references in tests/Feature/ (FR-001)
- T040 Update any remaining references to legacy run tables (tokens caught by the guard) under app/, database/, resources/, routes/ until tests/Feature/Guards/NoLegacyRunsTest.php passes (FR-009)
Phase 7: Polish & Cross-Cutting Concerns
- T041 Run formatting for touched files with vendor/bin/sail bin pint --dirty and fix any style issues in app/ and tests/
- T042 Run focused test pack for this spec (at minimum): tests/Feature/Guards/NoLegacyRunsTest.php, tests/Feature/Operations/LegacyRunRoutesNotFoundTest.php, tests/Feature/Monitoring/MonitoringOperationsTest.php, tests/Feature/Drift/ (directory)
Dependencies & Execution Order
Story dependency graph
- Phase 2 blocks everything.
- US1 (canonical run creation) should land before US2 (removing UI) to avoid removing the only user-visible run history.
- US3 (drift cutover) can proceed after Phase 2, but MUST complete before Phase 6 (dropping legacy tables).
Parallel opportunities (examples)
- After Phase 2:
- US1 implementation tasks in app/Services/Inventory/InventorySyncService.php and app/Jobs/EntraGroupSyncJob.php can be done in parallel.
- US2 removal tasks (Filament resource deletion) can proceed in parallel with US3 migrations/code, as long as any shared files are coordinated.
Implementation Strategy (MVP)
- MVP = Phase 2 + US1 + the minimum of US2 needed to remove navigation entry points.
- Then complete US3 cutover and only then drop legacy tables.