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