Summary Consolidates the “Tenant Operate Hub” work (Spec 085) and the follow-up adjustments from the 086 session merge into a single branch ready to merge into dev. Primary focus: stabilize Ops/Operate Hub UX flows, tighten/align authorization semantics, and make the full Sail test suite green. Key Changes Ops UX / Verification Readonly members can view verification operation runs (reports) while starting verification remains restricted. Normalized failure reason-code handling and aligned UX expectations with the provider reason-code taxonomy. Onboarding wizard UX “Start verification” CTA is hidden while a verification run is active; “Refresh” is shown during in-progress runs. Treats provider_permission_denied as a blocking reason (while keeping legacy compatibility). Test + fixture hardening Standardized use of default provider connection fixtures in tests where sync/restore flows require it. Fixed multiple Filament URL/tenant-context test cases to avoid 404s and reduce tenancy routing brittleness. Policy sync / restore safety Enrollment configuration type collision classification tests now exercise the real sync path (with required provider connection present). Restore edge-case safety tests updated to reflect current provider-connection requirements. Testing vendor/bin/sail artisan test --compact (green) vendor/bin/sail bin pint --dirty (green) Notes Includes merged 086 session work already (no separate PR needed). Co-authored-by: Ahmed Darrazi <ahmeddarrazi@ebc83aaa-d947-4a08-b88e-bd72ac9645f7.fritz.box> Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.fritz.box> Reviewed-on: #103
110 lines
5.7 KiB
Markdown
110 lines
5.7 KiB
Markdown
# Implementation Plan: Retire Legacy Runs Into Operation Runs
|
|
|
|
**Branch**: `086-retire-legacy-runs-into-operation-runs` | **Date**: 2026-02-10 | **Spec**: `specs/086-retire-legacy-runs-into-operation-runs/spec.md`
|
|
**Input**: Feature specification from `specs/086-retire-legacy-runs-into-operation-runs/spec.md`
|
|
|
|
## Summary
|
|
|
|
Retire legacy “run tracking” tables as the primary execution tracker for in-scope operations (inventory sync, directory groups sync, backup schedule runs, restore execution, and directory role definitions sync) and make `operation_runs` the canonical source of truth.
|
|
|
|
Key implementation approach:
|
|
- Use the existing tenantless canonical viewer `/admin/operations/{run}` (Filament page `TenantlessOperationRunViewer`) and ensure it remains DB-only at render time.
|
|
- Enforce the clarified 404/403 semantics for run viewing: non-members 404, members missing capability 403, where the view capability equals the start capability.
|
|
- Enforce dispatch-time OperationRun creation for every start surface; jobs never fallback-create.
|
|
- Apply explicit run identity rules per operation type (dedupe vs unique-per-click vs strict schedule dedupe), including strict scheduled backup idempotency: at most one canonical run ever per (schedule_id, intended fire-time).
|
|
- Remove Graph calls from UI render/search/label callbacks by using cached directory data (groups + role definitions) and “Sync now” operations.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15
|
|
**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4
|
|
**Storage**: PostgreSQL (via Sail)
|
|
**Testing**: Pest v4 (PHPUnit v12 runner)
|
|
**Target Platform**: Web application (Laravel + Filament admin panel)
|
|
**Project Type**: web
|
|
**Performance Goals**: Operations viewer + Monitoring pages render from DB state only; canonical viewer loads in ~2s under normal conditions
|
|
**Constraints**: No outbound HTTP in Monitoring/Operations rendering/search/label callbacks (OPS-EX-AUTH-001); dispatch-time OperationRun creation; jobs must never fallback-create; strict 404/403 isolation semantics
|
|
**Scale/Scope**: TenantPilot admin workflows; multiple operation families; staged cutover with legacy history preserved
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
|
|
- Inventory-first: No change to the meaning of inventory vs snapshots/backups; this spec only changes execution tracking.
|
|
- Read/write separation: Start surfaces remain enqueue-only; destructive-like actions are not added here; audit logging remains required for mutations.
|
|
- Graph contract path: UI render/search/label callbacks must become DB-only; any remaining Graph calls stay behind `GraphClientInterface` + `config/graph_contracts.php`.
|
|
- Deterministic capabilities: Run viewing must be capability-gated using the existing capability registry (no raw strings).
|
|
- RBAC-UX: Enforce clarified semantics for run viewing: non-members 404, members missing capability 403; authorization enforced server-side via Policy/Gate.
|
|
- Workspace isolation: Canonical tenantless `/admin/operations/{run}` continues to enforce workspace membership (deny-as-not-found).
|
|
- Global search: `OperationRunResource` stays non-globally-searchable; no new global-search surfaces introduced.
|
|
- Run observability: All in-scope long-running/scheduled/remote operations are tracked via `OperationRun`; Monitoring pages remain DB-only.
|
|
- Automation: Scheduled backup run creation uses strict idempotency per schedule + intended fire-time.
|
|
- Badge semantics (BADGE-001): Run status/outcome badges already use `BadgeRenderer`; do not introduce ad-hoc mappings.
|
|
- Filament UI Action Surface Contract: Legacy resources remain read-only; canonical operations pages already define inspection affordances.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/086-retire-legacy-runs-into-operation-runs/
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── contracts/
|
|
│ └── README.md
|
|
└── tasks.md # To be created by /speckit.tasks
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
app/
|
|
├── Filament/
|
|
│ ├── Pages/
|
|
│ │ ├── Monitoring/
|
|
│ │ └── Operations/
|
|
│ └── Resources/
|
|
├── Http/
|
|
│ └── Middleware/
|
|
├── Jobs/
|
|
├── Models/
|
|
├── Policies/
|
|
├── Services/
|
|
└── Support/
|
|
|
|
config/
|
|
├── graph.php
|
|
└── graph_contracts.php
|
|
|
|
database/
|
|
└── migrations/
|
|
|
|
tests/
|
|
├── Feature/
|
|
└── Unit/
|
|
```
|
|
|
|
**Structure Decision**: Laravel web application (monolith) with Filament admin panel.
|
|
|
|
## Complexity Tracking
|
|
|
|
No constitution violations are required for this feature.
|
|
|
|
## Phase Plan
|
|
|
|
Phase 0/1 deliverables are already captured in:
|
|
- `specs/086-retire-legacy-runs-into-operation-runs/research.md`
|
|
- `specs/086-retire-legacy-runs-into-operation-runs/data-model.md`
|
|
- `specs/086-retire-legacy-runs-into-operation-runs/contracts/README.md`
|
|
- `specs/086-retire-legacy-runs-into-operation-runs/quickstart.md`
|
|
|
|
Phase 2 (tasks) will be produced via `/speckit.tasks` and should slice work by operation family:
|
|
1) Authorization: capability-gate canonical run viewing (404 vs 403 semantics).
|
|
2) Backup schedules: add `backup_schedule.scheduled` + strict idempotency; make manual runs unique-per-click.
|
|
3) Directory groups: stop writing legacy rows; keep legacy pages read-only; ensure dispatch-time OperationRun creation.
|
|
4) Inventory sync: stop writing legacy rows; ensure dispatch-time OperationRun creation and no UI Graph calls.
|
|
5) Tenant configuration: remove Graph calls from render/search/labels; add role definitions cache + “Sync now” operation.
|
|
6) Restore: ensure execution tracking uses OperationRun only; legacy restore domain records remain as domain entities.
|