# 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 spec’s “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.