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

147 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature Specification: Legacy Runs Removal
**Feature Branch**: `087-legacy-runs-removal`
**Created**: 2026-02-12
**Status**: Draft
**Input**: User description: "Spec 087 — Legacy Runs Removal (RIGOROS)"
## Clarifications
### Session 2026-02-12
- Q: Should we backfill legacy run history into the canonical run system before dropping legacy tables? → A: No backfill (accept losing pre-existing legacy run history)
- Q: Should backup schedule retention/purge produce canonical run records? → A: Yes — retention and purge each produce their own canonical runs
- Q: Which canonical run_type contract should be enforced? → A: Use the explicit list: inventory_sync, drift_generate_findings, entra_group_sync, backup_schedule_run, backup_schedule_retention, backup_schedule_purge
- Q: For canonical run URLs, should access be 404 for non-members and 403 for members missing capability? → A: Yes — non-member/not entitled → 404; member missing capability → 403
- Q: How broad should the “NoLegacyRuns” architecture guard scan be? → A: Scan app/, database/, resources/, and routes/ (exclude specs/ and references/)
## Redirect Scope
This specs “no redirects” requirement applies to legacy *run* pages and legacy run UI surfaces.
The existing convenience route that redirects the tenant-scoped operations index to the canonical operations index (for example: `/admin/t/{tenant}/operations``/admin/operations`) is not considered a legacy run page.
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Single canonical run history (Priority: P1)
As a workspace member, I can see and open run history for inventory sync, Entra group sync, and backup schedules in a single, consistent place, without having to navigate multiple legacy run screens.
**Why this priority**: Removes duplicated tracking and inconsistent UX, and reduces confusion about which “run” is authoritative.
**Independent Test**: Trigger each run type once and verify it appears in the canonical Operations run list and can be opened via the canonical run detail view.
**Acceptance Scenarios**:
1. **Given** a workspace member with permission to view operations, **When** a new inventory sync run starts and finishes, **Then** a corresponding canonical run exists and is viewable via the canonical Operations UI.
2. **Given** a workspace member with permission to view operations, **When** a new Entra group sync run starts and finishes, **Then** a corresponding canonical run exists and is viewable via the canonical Operations UI.
3. **Given** a workspace member with permission to view operations, **When** a backup schedule run starts and finishes, **Then** a corresponding canonical run exists and is viewable via the canonical Operations UI.
---
### User Story 2 - Legacy run UI is intentionally gone (Priority: P1)
As a workspace member, I cannot access legacy run pages anymore. Old links intentionally fail, so there is no ambiguity about where runs are viewed.
**Why this priority**: Prevents “run sprawl” and ensures there is exactly one canonical run UI.
**Independent Test**: Attempt to access any known legacy run route and verify it is not available.
**Acceptance Scenarios**:
1. **Given** a user (any role), **When** they attempt to access a legacy run URL, **Then** the application responds as not found.
2. **Given** the application navigation, **When** a user browses the admin UI, **Then** no legacy run resources appear in navigation.
---
### User Story 3 - Drift references canonical runs (Priority: P1)
As a workspace member using drift-related features, I see baseline/current references tied to canonical runs, and drift logic does not depend on a legacy run store.
**Why this priority**: Drift currently has structural coupling to a legacy run concept; removing it reduces risk and complexity.
**Independent Test**: Create drift findings that reference baseline/current runs and confirm the references use canonical runs (or are empty if historical data cannot be mapped).
**Acceptance Scenarios**:
1. **Given** drift findings created after this feature ships, **When** a user views baseline/current references, **Then** the references point to canonical runs.
2. **Given** historical drift findings where no safe mapping exists, **When** a user views baseline/current references, **Then** the UI remains functional and references are empty rather than erroring.
---
### Edge Cases
- Historical runs exist with details that were only stored in legacy run records, and this history will not be backfilled into canonical runs.
- A user is a non-member of the workspace and attempts to view a run.
- A user is a workspace member but lacks the capability to view operations.
- A scheduled backup run is skipped/cancelled and still needs a canonical run record with a clear final outcome.
- Retention/purge runs remove old data; the user expects runs to remain auditable and consistent.
## Requirements *(mandatory)*
**Constitution alignment (required):** This feature changes long-running work and run tracking. It MUST ensure run observability via the canonical run system, consistent identity, and workspace-scoped visibility.
**Constitution alignment (RBAC-UX):** This feature changes run visibility and removes legacy pages. It MUST explicitly define not-found vs forbidden behavior and enforce authorization server-side.
**Constitution alignment (BADGE-001):** Any run status-like badges MUST be derived from canonical run status/outcome to keep semantics centralized.
**Constitution alignment (Filament Action Surfaces):** This feature removes legacy run resources and updates run links to point to the canonical operations views.
### Functional Requirements
- **FR-001**: The system MUST treat the canonical run system as the single source of truth for all run tracking and display.
- **FR-002**: The system MUST NOT create or update legacy run records for inventory sync, Entra group sync, or backup schedule runs.
- **FR-003**: The system MUST remove all legacy run UI surfaces (resources/pages/relation managers/badges) so that runs are only accessible from the canonical Operations UI.
- **FR-004**: Requests to legacy run pages MUST behave as not found (no redirects).
- **FR-005**: Drift-related entities MUST reference canonical runs for baseline/current/last-seen run linkage.
- **FR-006**: Backup schedule retention/purge workflows MUST operate without relying on legacy run stores.
- **FR-007**: Entra group sync run history and links MUST reference canonical runs only.
- **FR-008**: The system MUST enforce workspace-first access rules for canonical run list and detail views:
- non-member or not entitled to the workspace scope → not found (404)
- member but missing capability → forbidden (403)
- **FR-009**: Automated architecture checks MUST prevent reintroduction of legacy run concepts by failing CI if legacy tokens are found anywhere in: `app/`, `database/`, `resources/`, `routes/`.
- **FR-010**: The system MUST NOT backfill historical legacy run records into the canonical run system; only new runs are guaranteed to be represented as canonical runs.
- **FR-011**: Backup schedule retention and purge executions MUST each create their own canonical run records, observable in the canonical Operations UI.
- **FR-012**: The system MUST standardize and enforce the canonical `run_type` identifiers for runs created by this feature:
- `inventory_sync`
- `drift_generate_findings`
- `entra_group_sync`
- `backup_schedule_run`
- `backup_schedule_retention`
- `backup_schedule_purge`
## UI Action Matrix *(mandatory when Filament is changed)*
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Operations run list | Admin UI | None | Filtered list + open run | View | None | None | N/A | N/A | Yes (via canonical runs) | All run types converge here |
| Operations run detail | Admin UI | None | N/A | N/A | None | None | None | N/A | Yes (via canonical runs) | Single canonical view for run details |
| Backup schedule detail | Admin UI | None | Links to canonical runs | View | None | None | N/A | N/A | Yes | Legacy run tab removed |
### Key Entities *(include if feature involves data)*
- **Operation Run**: A canonical record representing a long-running operation, including type, status, timestamps, context, and summary.
- **Drift Finding**: A drift detection result that may reference baseline and current runs.
- **Inventory Item**: An inventory record that may reference the last run in which it was observed.
- **Backup Schedule**: A recurring configuration that triggers backup operations and may trigger retention/purge operations.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: 100% of new inventory sync, Entra group sync, and backup schedule executions produce exactly one canonical run record that is visible in the canonical Operations run list.
- **SC-002**: Legacy run pages are not accessible (attempts to access legacy run URLs result in not found).
- **SC-003**: Drift creation and drift UI flows do not depend on legacy run stores; baseline/current references resolve to canonical runs when mappings exist.
- **SC-004**: The automated architecture guard blocks reintroduction of legacy run concepts and fails the build when legacy tokens reappear.
- **SC-005**: Backup schedule retention/purge workflows complete successfully without legacy run stores and are observable through canonical runs.
- **SC-006**: Each retention and each purge execution produces a canonical run record (independent from the associated backup schedule run).
## Assumptions
- Historical legacy-only run details do not need to be preserved; pre-existing legacy run history may be lost after legacy tables are removed.
- The canonical Operations UI already exists and is the single supported run viewer.
## Dependencies
- Workspace-scoped run access rules remain enforced consistently across list and detail views.