# Phase 0 — Research: Legacy Runs Removal (Spec 087) **Branch**: `087-legacy-runs-removal` **Date**: 2026-02-12 **Input Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/spec.md` ## What “Legacy Runs” Means In This Repo **Decision**: “Legacy runs” for this spec are the tenant-scoped run tables + UI surfaces that duplicate `operation_runs` for: - Inventory sync - Entra group sync - Backup schedule execution **Evidence (current repo state)**: - Legacy tables exist: - `inventory_sync_runs` ([database/migrations/2026_01_07_142719_create_inventory_sync_runs_table.php](../../database/migrations/2026_01_07_142719_create_inventory_sync_runs_table.php)) - `entra_group_sync_runs` ([database/migrations/2026_01_11_120004_create_entra_group_sync_runs_table.php](../../database/migrations/2026_01_11_120004_create_entra_group_sync_runs_table.php)) - `backup_schedule_runs` ([database/migrations/2026_01_05_011034_create_backup_schedule_runs_table.php](../../database/migrations/2026_01_05_011034_create_backup_schedule_runs_table.php)) - These legacy tables already have bridging columns to canonical runs (`operation_run_id` was added later), indicating an ongoing migration to `operation_runs`: - [database/migrations/2026_02_10_090213_add_operation_run_id_to_inventory_sync_runs_table.php](../../database/migrations/2026_02_10_090213_add_operation_run_id_to_inventory_sync_runs_table.php) - [database/migrations/2026_02_10_090214_add_operation_run_id_to_entra_group_sync_runs_table.php](../../database/migrations/2026_02_10_090214_add_operation_run_id_to_entra_group_sync_runs_table.php) - [database/migrations/2026_02_10_090215_add_operation_run_id_to_backup_schedule_runs_table.php](../../database/migrations/2026_02_10_090215_add_operation_run_id_to_backup_schedule_runs_table.php) ## Canonical Run Types: Spec vs Current Code ### Problem The spec mandates canonical `run_type` identifiers: - `inventory_sync` - `drift_generate_findings` - `entra_group_sync` - `backup_schedule_run` - `backup_schedule_retention` - `backup_schedule_purge` But the current code uses dotted `OperationRunType` values such as: - `inventory.sync` - `directory_groups.sync` - `drift.generate` - `backup_schedule.run_now` / `backup_schedule.retry` / `backup_schedule.scheduled` ([app/Support/OperationRunType.php](../../app/Support/OperationRunType.php)) ### Decision Adopt the spec’s underscore identifiers as the canonical stored values going forward. ### Rationale - The spec explicitly requires a standardized and enforced contract. - Stored `type` values are used across UI and notifications; a single canonical scheme reduces “type sprawl.” ### Backwards Compatibility Plan (for existing rows) - Provide a one-time data migration that rewrites existing `operation_runs.type` values from the old dotted values to the new underscore values *for the affected categories only*. - Keep a compatibility mapping in code (temporary) only if needed to avoid breaking filters/UI during rollout. ### Alternatives Considered - Keep dotted values and treat the spec’s list as “display labels.” Rejected because it violates FR-012’s explicit identifiers. - Introduce a parallel “canonical_type” column. Rejected because it increases complexity and duplication. ## Drift + Inventory References (FK Cutover) ### Problem Drift and inventory currently reference legacy run IDs: - Findings: `baseline_run_id` / `current_run_id` are FKs to `inventory_sync_runs` ([database/migrations/2026_01_13_223311_create_findings_table.php](../../database/migrations/2026_01_13_223311_create_findings_table.php)) - Inventory items: `last_seen_run_id` references `inventory_sync_runs` ([database/migrations/2026_01_07_142720_create_inventory_items_table.php](../../database/migrations/2026_01_07_142720_create_inventory_items_table.php)) But inventory items already have the new canonical field: - `last_seen_operation_run_id` ([database/migrations/2026_02_10_091433_add_last_seen_operation_run_id_to_inventory_items_table.php](../../database/migrations/2026_02_10_091433_add_last_seen_operation_run_id_to_inventory_items_table.php)) ### Decision Migrate drift + inventory references to `operation_runs` and drop the legacy FK columns. ### Migration Strategy - Add new nullable columns: - `findings.baseline_operation_run_id` - `findings.current_operation_run_id` - Backfill by joining through `inventory_sync_runs.operation_run_id` where available. - Update app code to read/write the new fields. - Drop old `*_run_id` FK columns. - Only after that, drop the legacy tables. ### Rationale - Required to drop legacy tables without breaking referential integrity. - Aligns with spec acceptance scenario: “historical drift findings where no safe mapping exists” remain functional (references can be null). ## Legacy UI Surfaces Found (To Remove) **Inventory sync runs**: - [app/Filament/Resources/InventorySyncRunResource.php](../../app/Filament/Resources/InventorySyncRunResource.php) **Entra group sync runs**: - [app/Filament/Resources/EntraGroupSyncRunResource.php](../../app/Filament/Resources/EntraGroupSyncRunResource.php) **Backup schedule run history** (RelationManager + modal): - [app/Filament/Resources/BackupScheduleResource/RelationManagers/BackupScheduleRunsRelationManager.php](../../app/Filament/Resources/BackupScheduleResource/RelationManagers/BackupScheduleRunsRelationManager.php) ## Architecture Guard (NoLegacyRuns) ### Decision Add a CI/architecture Pest test similar to existing “NoLegacy…” guards: - [tests/Feature/Guards/NoLegacyBulkOperationsTest.php](../../tests/Feature/Guards/NoLegacyBulkOperationsTest.php) ### Guard Scope (per spec clarification) Scan for forbidden tokens under: - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/database/` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/resources/` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/routes/` Exclude: - `vendor/`, `storage/`, `specs/`, `spechistory/`, `references/`, `bootstrap/cache/` ### Initial Forbidden Tokens (starting list) - `InventorySyncRun`, `inventory_sync_runs`, `InventorySyncRunResource` - `EntraGroupSyncRun`, `entra_group_sync_runs`, `EntraGroupSyncRunResource` - `BackupScheduleRun`, `backup_schedule_runs`, `BackupScheduleRunsRelationManager` ## Open Questions None remaining for planning. - “No backfill” is already clarified in the spec; the only data movement here is migrating *references* to existing `operation_runs`. - Authorization semantics for canonical operations pages are clarified (404 vs 403) and must be preserved.