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
186 lines
8.4 KiB
Markdown
186 lines
8.4 KiB
Markdown
# Implementation Plan: Legacy Purge (Runs / Routes / UI / Test Shims)
|
|
|
|
**Branch**: `092-legacy-purge-final` | **Date**: 2026-02-14 | **Spec**: `/specs/092-legacy-purge-final/spec.md`
|
|
**Input**: Feature specification from `/specs/092-legacy-purge-final/spec.md`
|
|
|
|
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
|
|
|
|
## Summary
|
|
|
|
Remove remaining legacy “run world” artifacts across routes, UI copy, redirect-only pages, and tests. Enforce permanence with guard tests and deliver the queued-job payload shape change via a staged rollout (compatibility release → final purge).
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.x (Laravel 12)
|
|
**Primary Dependencies**: Filament v5, Livewire v4, Pest v4, Laravel Sail
|
|
**Storage**: PostgreSQL
|
|
**Testing**: Pest (run via `vendor/bin/sail artisan test`)
|
|
**Target Platform**: Web application (Docker/Sail locally; Dokploy containers in staging/prod)
|
|
**Project Type**: Laravel monolith
|
|
**Performance Goals**: No new performance goals (cleanup-only change).
|
|
**Constraints**: Must not change historical migrations; must preserve RBAC semantics; queued-job payload change must be staged to avoid unserialize failures.
|
|
**Scale/Scope**: Repo-wide purge + guard rails; small number of routes/views touched; staged deploy A/B for the job payload.
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
|
|
- Inventory-first: clarify what is “last observed” vs snapshots/backups
|
|
- Read/write separation: any writes require preview + confirmation + audit + tests
|
|
- Graph contract path: Graph calls only via `GraphClientInterface` + `config/graph_contracts.php`
|
|
- Deterministic capabilities: capability derivation is testable (snapshot/golden tests)
|
|
- RBAC-UX: two planes (/admin vs /system) remain separated; cross-plane is 404; non-member tenant access is 404; member-but-missing-capability is 403; authorization checks use Gates/Policies + capability registries (no raw strings, no role-string checks)
|
|
- Workspace isolation: non-member workspace access is 404; tenant-plane routes require an established workspace context; workspace context switching is separate from Filament Tenancy
|
|
- RBAC-UX: destructive-like actions require `->requiresConfirmation()` and clear warning text
|
|
- RBAC-UX: global search is tenant-scoped; non-members get no hints; inaccessible results are treated as not found (404 semantics)
|
|
- Tenant isolation: all reads/writes tenant-scoped; cross-tenant views are explicit and access-checked
|
|
- Run observability: long-running/remote/queued work creates/reuses `OperationRun`; start surfaces enqueue-only; Monitoring is DB-only; DB-only <2s actions may skip runs but security-relevant ones still audit-log; auth handshake exception OPS-EX-AUTH-001 allows synchronous outbound HTTP on `/auth/*` without `OperationRun`
|
|
- Automation: queued/scheduled ops use locks + idempotency; handle 429/503 with backoff+jitter
|
|
- Data minimization: Inventory stores metadata + whitelisted meta; logs contain no secrets/tokens
|
|
- Badge semantics (BADGE-001): status-like badges use `BadgeCatalog` / `BadgeRenderer`; no ad-hoc mappings; new values include tests
|
|
- Filament UI Action Surface Contract: for any new/modified Filament Resource/RelationManager/Page, define Header/Row/Bulk/Empty-State actions, ensure every List/Table has a record inspection affordance (prefer `recordUrl()` clickable rows; do not render a lone View row action), keep max 2 visible row actions with the rest in “More”, group bulk actions, require confirmations for destructive actions (typed confirmation for large/bulk where applicable), write audit logs for mutations, enforce RBAC via central helpers (non-member 404, member missing capability 403), and ensure CI blocks merges if the contract is violated or not explicitly exempted
|
|
|
|
**Gate status (pre-Phase 0)**: PASS
|
|
|
|
- Inventory-first: no changes to inventory modeling; only removes a redirect-only landing page and ensures canonical entry points.
|
|
- Read/write separation: no new writes introduced.
|
|
- Graph contract path: no new Graph calls.
|
|
- Deterministic capabilities: unchanged.
|
|
- RBAC-UX + workspace/tenant isolation: routes removed are legacy shims; behavior for unauthorized access remains deny-as-not-found (404) where applicable.
|
|
- Run observability: unchanged.
|
|
- Filament Action Surface Contract: only copy/navigation/heuristic removal; no new resources/pages or actions.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/092-legacy-purge-final/
|
|
├── plan.md # This file (/speckit.plan command output)
|
|
├── research.md # Phase 0 output (/speckit.plan command)
|
|
├── data-model.md # Phase 1 output (/speckit.plan command)
|
|
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
|
├── contracts/ # Phase 1 output (/speckit.plan command)
|
|
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
```text
|
|
app/
|
|
├── Filament/
|
|
├── Http/
|
|
├── Jobs/
|
|
├── Models/
|
|
├── Providers/
|
|
├── Support/
|
|
└── ...
|
|
|
|
routes/
|
|
├── web.php
|
|
└── console.php
|
|
|
|
resources/
|
|
├── views/
|
|
└── ...
|
|
|
|
database/
|
|
├── migrations/ # immutable
|
|
└── factories/
|
|
|
|
tests/
|
|
├── Feature/
|
|
└── Unit/
|
|
|
|
specs/092-legacy-purge-final/
|
|
├── spec.md
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
└── contracts/
|
|
```
|
|
|
|
**Structure Decision**: Laravel monolith. Changes are localized to routing (`routes/web.php`), UI views (Blade), Filament pages/helpers, and Pest feature tests.
|
|
|
|
## Complexity Tracking
|
|
|
|
No constitution violations are required for this feature.
|
|
|
|
## Phase 0 — Outline & Research
|
|
|
|
### Goals
|
|
|
|
- Translate spec requirements into concrete code locations and guard patterns.
|
|
- Decide how to deliver the queued-job payload change safely (Deploy A/B).
|
|
|
|
### Research tasks (from spec + repo reality)
|
|
|
|
- Identify all legacy redirect shims and legacy endpoints still present (routes + UI links + tests).
|
|
- Identify all legacy identifiers that must be purged (class names, field names, copy).
|
|
- Confirm which routes should return `404 Not Found` after removal (per spec Clarifications).
|
|
|
|
### Output
|
|
|
|
- `specs/092-legacy-purge-final/research.md`
|
|
|
|
## Phase 1 — Design & Contracts
|
|
|
|
### Data model
|
|
|
|
No new entities. Document impacted payload/fields and removal timeline:
|
|
|
|
- Background job payload: remove legacy `backupScheduleRunId` using staged rollout.
|
|
- UI/route artifacts: remove redirect-only landing page and legacy route shims.
|
|
|
|
### Contracts
|
|
|
|
This feature is not an external API feature, but it does define deterministic HTTP semantics for legacy endpoints.
|
|
|
|
- Provide a minimal OpenAPI contract that documents legacy URLs returning `404` (deny-by-absence).
|
|
|
|
### Output
|
|
|
|
- `specs/092-legacy-purge-final/data-model.md`
|
|
- `specs/092-legacy-purge-final/contracts/*`
|
|
- `specs/092-legacy-purge-final/quickstart.md`
|
|
|
|
### Agent context update
|
|
|
|
Run:
|
|
|
|
- `.specify/scripts/bash/update-agent-context.sh copilot`
|
|
|
|
## Constitution Check (post-Phase 1)
|
|
|
|
**Gate status (post-Phase 1)**: PASS
|
|
|
|
- No new Graph calls.
|
|
- No new mutations/actions.
|
|
- Route removals preserve deny-as-not-found semantics for legacy deep links.
|
|
- Staged rollout plan prevents queued-payload failures.
|
|
|
|
## Phase 2 — Implementation Planning (Deploy/PR sequence)
|
|
|
|
### Deploy A (compatibility release)
|
|
|
|
- Make the legacy job field optional / ignorable so older queued payloads still deserialize.
|
|
- Stop passing/creating dummy legacy run IDs at dispatch sites.
|
|
- Add/adjust tests ensuring both payload shapes are accepted.
|
|
|
|
### Deploy B (final purge)
|
|
|
|
- Remove the legacy job field entirely once the compatibility window has passed and queues are drained.
|
|
- Remove any remaining references + guard against reintroduction.
|
|
|
|
### PR breakdown (recommended)
|
|
|
|
1. **Routing + tests**: remove legacy redirect routes (e.g., `/admin/t/{tenant}/operations` shim) and update tests to assert `404`.
|
|
2. **UI cleanup**: remove redirect-only Inventory landing + dead view; update Drift copy to “operation runs”; remove context-bar URL heuristic.
|
|
3. **Job staged rollout**: implement Deploy A compatibility changes with tests.
|
|
4. **Final purge**: implement Deploy B removal + tighten guards.
|
|
|
|
### Test strategy (minimum)
|
|
|
|
- Focused: run the feature test files that assert legacy URLs return 404 and any job serialization tests added for Deploy A/B.
|
|
- Repo hygiene: run `vendor/bin/sail bin pint --dirty`.
|