TenantAtlas/specs/087-legacy-runs-removal/plan.md
ahmido d6e7de597a feat(spec-087): remove legacy runs (#106)
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
2026-02-12 12:40:51 +00:00

6.4 KiB

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)

/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.