TenantAtlas/specs/092-legacy-purge-final/spec.md
ahmido 5770c7b76b Spec 092: Legacy Purge (runs/routes/UI/test shims) (#110)
Implements Spec 092 legacy purge.

Key changes:
- Remove legacy Inventory landing page + view; link Inventory entry directly to Inventory Items.
- Update Drift landing copy to "operation runs"; remove URL heuristic from context bar.
- Remove legacy redirect shim route and assert 404 for old bookmarks.
- Staged job payload change: remove legacy ctor arg; keep legacy field for deserialization compatibility; new payload omits field.
- Remove legacy notification artifact.
- Remove legacy test shim + update tests; strengthen guard suite with scoped exception for job compat field.
- Add spec/plan/tasks/checklist artifacts under specs/092-legacy-purge-final.

Tests:
- Focused Pest suite for guards, legacy routes, redirect behavior, job compatibility, drift copy.
- Pint run: `vendor/bin/sail bin pint --dirty`.

Notes:
- Deploy B final removal of `backupScheduleRunId` should occur only after the compatibility window defined in the spec.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #110
2026-02-14 18:43:56 +00:00

12 KiB

Feature Specification: Legacy Purge (Runs / Routes / UI / Test Shims)

Feature Branch: 092-legacy-purge-final
Created: 2026-02-14
Status: Draft
Input: User description: "Spec 092 — Legacy Purge: Runs / Routes / UI / Test-Shims vollständig entfernen"

Clarifications

Session 2026-02-14

  • Q: For legacy tenant-scoped deep links that were previously served via redirect shims under /admin/t/{tenant:external_id}/... (e.g. /admin/t/{tenant}/operations), what response semantics do you want? → A: Always 404 Not Found.
  • Q: For guard tests scanning for legacy patterns, which paths should be excluded? → A: Exclude database/migrations/** + references/** + docs/**.
  • Q: For Inventory entry after removing the redirect-only landing page, what should be the canonical target? → A: Inventory Items.
  • Q: For Drift landing copy, what exact phrase should replace the legacy text “inventory sync runs”? → A: Use “operation runs”.

User Scenarios & Testing (mandatory)

User Story 1 - Operate without legacy concepts (Priority: P1)

As a platform maintainer, I can use the application without encountering legacy run concepts (URLs, labels, redirect-only pages, or test shims), so the system has a single canonical mental model.

Why this priority: Removing legacy remnants reduces refactor risk, prevents onboarding confusion, and eliminates hidden compatibility logic.

Independent Test: Navigate through Inventory, Drift, Operations/run history, and Provider Connections using the primary UI entry points; verify no legacy URLs or legacy wording appear and no compatibility shims are required.

Acceptance Scenarios:

  1. Given a user navigates via the canonical UI navigation, When they open Inventory and Drift entry points, Then they land on canonical pages (not redirect-only landing pages) and see canonical operations terminology.
  2. Given a user is in the admin UI, When the context/navigation chrome renders, Then it derives its state from the current workspace/tenant context only (not from legacy URL heuristics).

User Story 2 - Legacy deep links fail fast (Priority: P2)

As a tenant admin with old bookmarks, I get a clear failure (not a redirect) when accessing legacy tenant-scoped admin paths, so the system enforces a single set of canonical URLs.

Why this priority: Removing redirects is an intentional breaking change; we want predictable behavior and to avoid ongoing maintenance of compatibility shims.

Independent Test: Attempt to access representative legacy tenant-scoped admin URLs and confirm they are not handled by the application.

Acceptance Scenarios:

  1. Given an old bookmark to a legacy tenant-scoped admin path, When it is requested, Then the request returns 404 Not Found and is not redirected by the application.

User Story 3 - Prevent reintroduction (Priority: P3)

As a developer, I get fast feedback if I accidentally reintroduce removed legacy patterns (identifiers, parameters, route prefixes, or UI copy), so the cleanup remains permanent.

Why this priority: Cleanup work regresses easily during refactors; guard tests turn “tribal knowledge” into enforceable rules.

Independent Test: Introduce a known legacy identifier in a non-migration file and confirm automated guards fail reliably; remove it and confirm the suite is green again.

Acceptance Scenarios:

  1. Given a change introduces a removed legacy identifier in non-migration code, When the automated guard suite runs, Then the build fails with an actionable message.

Edge Cases

  • Legacy tenant-scoped paths may still exist in browser history or external references; the application must not rely on redirects to function.
  • Previously enqueued background work must continue to process safely during the compatibility window; removal of legacy job fields must not cause noisy runtime behavior.
  • Automated legacy scans must explicitly exclude database migration history (migrations are immutable).
  • Authorization semantics must not change as a side-effect of cleanup.

Requirements (mandatory)

Constitution alignment (required): This feature does not introduce new external calls. It does change long-running/queued work APIs (background job payload shape), so it MUST be delivered using a staged rollout to avoid compatibility issues with previously queued payloads.

Constitution alignment (RBAC-UX): This feature does not change authorization rules. It removes legacy routes and UI heuristics; access semantics must remain consistent and must not introduce new information leaks.

Constitution alignment (OPS-EX-AUTH-001): Not applicable.

Constitution alignment (BADGE-001): Not applicable.

Constitution alignment (Filament Action Surfaces): This feature changes admin UI content and navigation/landing behavior but does not introduce new mutation actions. The Action Surface Contract remains satisfied by existing surfaces.

Scope (bounded)

  • In scope: removal of legacy run artifacts in code, routes, UI copy/heuristics, and tests; addition/extension of guard tests that prevent reintroduction.
  • Out of scope: any changes to the canonical operations data model; any new features; any modifications to historical database migrations.

Assumptions & Dependencies

  • Release process supports two deployments/releases for the staged job payload change (compatibility window → final purge).
  • Migration history is immutable and excluded from legacy-scanning guards.
  • Release notes will communicate removal of legacy deep links.

Functional Requirements

  • FR-001 (Dead notification removal): The unused legacy notification for “backup schedule run dispatched” MUST not exist in active code.

    • Verification: A repository-wide scan of non-migration code finds no references to the removed notification artifact.
  • FR-002 (Job API cleanup, staged): The backup schedule execution job MUST not require a legacy run identifier at dispatch sites.

    • FR-002.A (Compatibility release): During a compatibility window, older queued payloads MUST still deserialize safely while new dispatches no longer include a dummy legacy run id.
    • FR-002.B (Final purge): After the compatibility window, the legacy parameter/property MUST be removed entirely.
    • Compatibility window definition: The compatibility window MUST be considered complete only after Deploy A has been in production for at least 7 calendar days, and the operations team confirms there is no remaining backlog of previously queued backup schedule execution jobs.
    • Verification: After final purge, no non-migration code references the legacy run-id field, and dispatch sites do not include placeholder arguments.
  • FR-003 (Inventory landing removal): Inventory navigation MUST not rely on redirect-only landing pages or dead views.

    • Verification: Inventory entry points route directly to Inventory Items (canonical index), without using a redirect-only landing page.
  • FR-004 (Drift landing copy): Drift UI copy MUST not use legacy terminology such as “inventory sync runs”; it MUST use “operation runs”.

    • Verification: Drift landing content shows “operation runs” and no legacy phrase remains visible.
  • FR-005 (Legacy redirect routes removal): The application MUST not define redirect shims for removed legacy tenant-scoped admin endpoints (e.g. /admin/t/{tenant:external_id}/operations).

    • Verification: Routing definitions contain no legacy tenant-scoped redirect shims, and requests to the removed legacy endpoints return 404 Not Found.
    • Scope note: At the time of writing, the only known legacy tenant-scoped redirect shim endpoint in routes/** is /admin/t/{tenant:external_id}/operations. If additional legacy redirect shim endpoints are discovered during implementation, they MUST be added to this spec and covered by tests.
  • FR-006 (Context chrome heuristic removal): Context/navigation chrome MUST not infer state from legacy URL patterns.

    • Verification: Context chrome behavior is correct without any legacy URL detection logic.
  • FR-007 (Test shim removal): Automated tests MUST not rely on legacy model shims or bootstrap hacks that simulate removed legacy domain concepts.

    • Verification: Test suite passes without any legacy shim files or bootstrapping.
  • FR-008 (Guard suite): Guard tests MUST fail if removed legacy identifiers/patterns are reintroduced outside migration history.

    • Verification: Guard suite reliably fails on reintroduction and passes when removed. Scans MUST exclude database/migrations/**, references/**, and docs/**.
  • FR-009 (Migration immutability): Database migrations MUST remain unchanged.

    • Verification: No migration files are modified as part of this feature.

Legacy identifiers (verification-only glossary)

The following legacy identifiers/patterns are considered removed and are used only for verification/guarding (outside migrations):

  • Notification artifact name: BackupScheduleRunDispatchedNotification
  • Legacy shim model name: InventorySyncRun
  • Legacy job field name: backupScheduleRunId
  • Legacy tenant-scoped deep-link endpoint(s) served by redirect shims (current known set):
    • /admin/t/{tenant:external_id}/operations
  • Non-legacy note: the tenant-plane prefix /admin/t/{tenant:external_id}/... is canonical by itself; only explicitly listed legacy deep-link shim endpoints are treated as removed.
  • Legacy UI copy phrase: inventory sync runs

Acceptance Criteria (Definition of Done)

  • No active code (excluding database migration history) contains the removed legacy identifiers/patterns.
  • No legacy redirect routes exist; legacy tenant-scoped deep links are not supported and return 404 Not Found.
  • Inventory entry points are canonical (no redirect-only landing UI).
  • Drift landing copy uses canonical operations terminology.
  • Test suite is green; guard tests prevent reintroduction.
  • Guard scans explicitly exclude database/migrations/**, references/**, and docs/**.

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
Drift landing content Drift entry UI No change No change No change No change No change No change No change No Copy-only change; no action surface impact
Inventory navigation entry Inventory entry UI No change No change No change No change No change No change No change No Remove redirect-only landing behavior
Context/navigation chrome Admin UI chrome No change No change No change No change No change No change No change No Remove legacy URL detection; no actions affected

Key Entities (include if feature involves data)

  • Background job payloads: Existing queued payloads may contain legacy fields; staged rollout must maintain compatibility until payloads are drained.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: A canonical navigation walkthrough (Inventory → Drift → Operations/run history → Provider connections) shows no legacy deep-link endpoints/redirect shims and no legacy run terminology.
  • SC-002: The application defines zero legacy tenant-scoped redirect shim routes, and removed legacy deep links return 404 Not Found.
  • SC-003: The automated test suite passes; guard tests fail deterministically when any removed legacy identifier is reintroduced outside migration history.
  • SC-004: The staged rollout completes with no emergency rollback due to queued job payload incompatibilities.