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
110 lines
3.3 KiB
Markdown
110 lines
3.3 KiB
Markdown
# 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).
|