TenantAtlas/specs/086-retire-legacy-runs-into-operation-runs/plan.md
ahmido 2bf5de4663 085-tenant-operate-hub (#103)
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
2026-02-11 13:02:03 +00:00

5.7 KiB

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)

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)

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.