# Implementation Plan: Legacy Runs Removal (Spec 087) **Branch**: `087-legacy-runs-removal` | **Date**: 2026-02-12 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/spec.md` **Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/spec.md` ## Summary Remove the “legacy run” worlds for inventory sync, Entra group sync, and backup schedules so that `operation_runs` is the only run tracking source. Migrate drift + inventory references away from `inventory_sync_runs`, remove legacy Filament run UI surfaces (no redirects), drop legacy run tables, and add an architecture guard test (`NoLegacyRuns`) to prevent regressions. ## Technical Context **Language/Version**: PHP 8.4.15 **Primary Dependencies**: Laravel 12, Filament v5, Livewire v4 **Storage**: PostgreSQL (Sail), SQLite in tests **Testing**: Pest v4 (PHPUnit 12) **Target Platform**: Containerized web app (Sail locally, Dokploy deploy) **Project Type**: Web application (Laravel + Filament) **Performance Goals**: Monitoring/Operations pages render DB-only; avoid N+1 when listing runs **Constraints**: Legacy run URLs must be not found (no redirects). This does not apply to the existing tenant-scoped operations index convenience redirect (`/admin/t/{tenant}/operations` → `/admin/operations`). Non-member workspace access is 404; member missing capability is 403 **Scale/Scope**: TenantPilot admin app; operations visibility + drift references are core operational surfaces ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Workspace isolation / RBAC-UX (404 vs 403): PASS (required by spec FR-008) - Run observability: PASS (this feature eliminates duplicate run stores) - Monitoring pages DB-only: PASS (no new render-time Graph calls) - Badge semantics (BADGE-001): PASS (legacy run badge mappings are removed, not expanded) - Filament action surface contract: PASS (feature mostly removes surfaces; modified surfaces must preserve inspection affordance + RBAC) ## Project Structure ### Documentation (this feature) ```text /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/ ├── spec.md ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ │ └── operations-runs.openapi.yaml └── checklists/ └── requirements.md ### Source Code (repository root) ```text /Users/ahmeddarrazi/Documents/projects/TenantAtlas/ ├── app/ │ ├── Filament/ │ ├── Jobs/ │ ├── Models/ │ ├── Services/ │ └── Support/ ├── database/ │ ├── migrations/ │ ├── factories/ │ └── seeders/ ├── resources/ ├── routes/ └── tests/ └── Feature/ └── Guards/ ``` **Structure Decision**: Laravel monolith with Filament resources/pages; this feature touches `app/`, `database/migrations/`, `resources/`, `routes/`, and `tests/Feature/`. ## Phase 0 — Outline & Research (COMPLETE) Output: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/research.md` Research resolves remaining planning unknowns: - Identifies legacy run tables and UI surfaces to remove. - Resolves the `run_type` contract mismatch (spec underscore values vs current dotted enum values). - Defines an FK cutover plan for drift + inventory references so legacy tables can be dropped safely. ## Phase 1 — Design & Contracts (COMPLETE) Outputs: - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/data-model.md` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/contracts/operations-runs.openapi.yaml` - `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/087-legacy-runs-removal/quickstart.md` Post-design constitution re-check: PASS (no new Graph/render concerns; run observability strengthened). ## Phase 2 — Implementation Plan ### Ordering constraints - Drift + inventory FKs currently point at legacy run tables; migrate those references before dropping tables. - Legacy run pages must be removed without redirects; verify with 404 tests. ### Step A — Canonical run types (FR-012) - Align stored `operation_runs.type` values with the underscore allow-list for the affected workflows. - Provide a migration that rewrites existing dotted values used today into the canonical underscore forms where safe. ### Step B — Stop legacy writes + remove legacy read dependencies - Inventory sync: eliminate writes to `inventory_sync_runs` and use `operation_runs` only. - Entra group sync: eliminate writes to `entra_group_sync_runs` and use `operation_runs` only. - Backup schedule: - Eliminate writes to `backup_schedule_runs`. - Persist schedule metadata in `operation_runs.context` (e.g., `backup_schedule_id`, `scheduled_for`, `reason`). - Ensure retention and purge each create their own canonical runs (FR-011). ### Step C — Drift + inventory reference cutover - Add `findings.baseline_operation_run_id` / `findings.current_operation_run_id` and backfill via `inventory_sync_runs.operation_run_id`. - Backfill `inventory_items.last_seen_operation_run_id` where only `last_seen_run_id` exists. - Update app code to use the canonical columns and tolerate null mappings. - Drop legacy run ID columns after cutover. ### Step D — Remove legacy UI surfaces (FR-003/FR-004) - Remove Filament resources/pages: - `InventorySyncRunResource` - `EntraGroupSyncRunResource` - Remove backup schedule legacy run history relation manager + modal. - Update links in drift/finding/inventory surfaces to use the canonical operations viewer. - Keep (or explicitly remove) the tenant-scoped operations index convenience redirect separately; it is not a legacy *run* page. ### Step E — Drop legacy tables - Drop `inventory_sync_runs`, `entra_group_sync_runs`, and `backup_schedule_runs` after FK cutover. ### Step F — Architecture guard (FR-009) - Add a guard test under `tests/Feature/Guards/` scanning `app/`, `database/`, `resources/`, and `routes/` for legacy run tokens. ### Test plan (minimum) - New: `NoLegacyRunsTest` (architecture guard) - Legacy routes: assert old run URLs return 404 (no redirects) - Drift + inventory: - new records store canonical run references - historical records without safe mapping render with null references ## Complexity Tracking No constitution violations are required for this plan.