TenantAtlas/specs/087-legacy-runs-removal/data-model.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

3.3 KiB

Phase 1 — Data Model: Legacy Runs Removal (Spec 087)

Branch: 087-legacy-runs-removal
Date: 2026-02-12

Canonical Entity: OperationRun

Table: operation_runs
Model: App\\Models\\OperationRun

Key fields (existing):

  • id
  • workspace_id (required)
  • tenant_id (nullable; tenant-scoped runs use this)
  • user_id (nullable)
  • initiator_name
  • type (canonical run_type)
  • status / outcome
  • run_identity_hash (idempotency)
  • summary_counts (JSON)
  • failure_summary (JSON)
  • context (JSON)
  • started_at / completed_at
  • created_at / updated_at

Spec impact:

  • type must be standardized to the underscore identifiers listed in FR-012.

Legacy Entities (To Remove)

InventorySyncRun

Table: inventory_sync_runs
Model: App\\Models\\InventorySyncRun

Notes:

  • Acts as a legacy duplicate run store.
  • Has operation_run_id bridge column (added later).

Plan: remove model + table, and rely on operation_runs.

EntraGroupSyncRun

Table: entra_group_sync_runs
Model: App\\Models\\EntraGroupSyncRun

Notes:

  • Legacy duplicate run store.
  • Has operation_run_id bridge column.

Plan: remove model + table, and rely on operation_runs.

BackupScheduleRun

Table: backup_schedule_runs
Model: App\\Models\\BackupScheduleRun

Notes:

  • Currently used for schedule run history + retention/purge selection.
  • Has operation_run_id bridge column.

Plan: remove model + table and replace schedule “run history” with querying operation_runs by type + context.

Drift Findings: References Must Become Canonical

Table: findings
Model: App\\Models\\Finding

Current fields (relevant):

  • baseline_run_id → FK to inventory_sync_runs (nullable)
  • current_run_id → FK to inventory_sync_runs (nullable)

Planned fields:

  • baseline_operation_run_id → FK to operation_runs (nullable)
  • current_operation_run_id → FK to operation_runs (nullable)

Backfill rule:

  • If baseline_run_id points to an inventory_sync_runs row with a non-null operation_run_id, and that operation_runs row exists, copy it.
  • Same for current_run_id.
  • Otherwise leave null (matches spec edge-case expectations).

Inventory Items: Last Seen Run Reference Must Become Canonical

Table: inventory_items
Model: App\\Models\\InventoryItem

Current fields (relevant):

  • last_seen_run_id → FK to inventory_sync_runs (nullable)
  • last_seen_operation_run_id → FK to operation_runs (nullable; already exists)

Plan:

  • Backfill last_seen_operation_run_id via inventory_sync_runs.operation_run_id where possible.
  • Drop last_seen_run_id after code is migrated.

Backup Schedules: Run History

Table: backup_schedules
Model: App\\Models\\BackupSchedule

Planned behavior:

  • Remove runs() relationship that points to backup_schedule_runs.
  • For UI/history, query operation_runs using:
    • type = backup_schedule_run|backup_schedule_retention|backup_schedule_purge
    • context->backup_schedule_id = {id} (and optionally scheduled time metadata)

Validation Rules (from spec)

  • All new run records created by this feature must have type in the FR-012 allow-list.
  • Run visibility is workspace-scoped; non-members must be deny-as-not-found (404).