TenantAtlas/specs/086-retire-legacy-runs-into-operation-runs/tasks.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

12 KiB
Raw Permalink Blame History

description
Task list for Spec 086 implementation

Tasks: Retire Legacy Runs Into Operation Runs (086)

Input: Design documents from specs/086-retire-legacy-runs-into-operation-runs/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/, quickstart.md

Tests: REQUIRED (Pest) — runtime behavior changes must be covered.

Phase 1: Setup (Shared Infrastructure)

  • T001 Confirm baseline green test subset via tests/Feature/Operations/TenantlessOperationRunViewerTest.php, tests/Feature/Monitoring/OperationsDbOnlyTest.php, and tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php
  • T002 Confirm Filament v5 + Livewire v4 constraints are respected for any touched pages/resources in app/Filament/**

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Shared primitives required by all stories.

  • T003 Add centralized “run type → required capability” resolver in app/Support/Operations/OperationRunCapabilityResolver.php
  • T004 Update app/Policies/OperationRunPolicy.php to enforce clarified 404/403 semantics (non-member 404; member missing capability 403) using T003
  • T005 [P] Add/extend operation type registry for new types in app/Support/OperationRunType.php
  • T006 [P] Add/extend operation labels/catalog entries in app/Support/OperationCatalog.php
  • T007 Add tests covering view authorization semantics in tests/Feature/Operations/TenantlessOperationRunViewerTest.php (404 vs 403 + capability-gated view)

Checkpoint: Canonical viewer authorization matches spec; new run types exist in registries.


Phase 3: User Story 1 — Start an operation with an immediate canonical run link (Priority: P1)

Goal: All start surfaces create an operation_runs record at dispatch time; no job fallback-create; “View run” link is stable.

Independent Test: Start each in-scope operation and assert the operation_runs row exists before work begins, with correct type/identity/context and a stable tenantless view URL.

Tests (US1)

  • T008 [P] [US1] Add/extend tests for OperationRun dispatch-time creation in tests/Feature/OperationRunServiceTest.php
  • T009 [P] [US1] Add/extend tests for start-surface authorization (403 prevents run creation) in tests/Feature/RunStartAuthorizationTest.php

Implementation (US1)

  • T010 [US1] Ensure inventory sync start surface creates OperationRun before dispatch and uses canonical link in app/Filament/Resources/InventoryItemResource/Pages/ListInventoryItems.php
  • T011 [US1] Ensure directory groups sync start surface creates OperationRun before dispatch and uses canonical link in app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php
  • T012 [US1] Ensure backup schedule manual run-now creates OperationRun before dispatch with unique-per-click identity (nonce) in app/Filament/Resources/BackupScheduleResource.php
  • T013 [US1] Ensure backup schedule retry creates OperationRun before dispatch with unique-per-click identity (nonce) in app/Filament/Resources/BackupScheduleResource.php
  • T014 [US1] Ensure scheduled backup dispatcher creates OperationRun before dispatch with strict identity by (schedule_id, scheduled_for) and type backup_schedule.scheduled in app/Services/BackupScheduling/BackupScheduleDispatcher.php
  • T014a [US1] Enforce strict scheduled backup idempotency (at most one canonical run ever per schedule_id + intended fire-time), using an explicit DB constraint and/or lock strategy aligned with OperationRunService identities
  • T015 [US1] Enforce “no job fallback-create” by validating required OperationRun context is present; fail fast if missing in app/Jobs/RunInventorySyncJob.php, app/Jobs/EntraGroupSyncJob.php, and app/Jobs/RunBackupScheduleJob.php

Restore (US1)

  • T015a [P] [US1] Add/extend tests that starting a restore execution creates an OperationRun at dispatch time (target existing restore execution tests under tests/Feature/RestoreRunWizardExecuteTest.php and/or tests/Feature/ExecuteRestoreRunJobTest.php)
  • T015b [US1] Ensure the restore execution start surface creates OperationRun before dispatch and surfaces the stable canonical “View run” link (adjust the Filament restore execution action/page used in the wizard flow)
  • T015c [US2] Ensure restore domain records link to canonical OperationRuns for observability (align with FR-014; no legacy fallback-create)

Checkpoint: Starting operations always yields a stable /admin/operations/{run} link immediately.


Phase 4: User Story 2 — Monitor executions from a single canonical viewer (Priority: P2)

Goal: Canonical viewer and Monitoring pages remain DB-only; legacy run history pages are read-only and redirect only when a deterministic mapping exists.

Independent Test: Load canonical viewer and legacy view pages while asserting no outbound Graph calls occur during render/search/label callbacks.

Tests (US2)

  • T016 [P] [US2] Add tests asserting Monitoring pages render DB-only (no Graph calls) in tests/Feature/Monitoring/MonitoringOperationsTest.php
  • T017 [P] [US2] Add tests for legacy-to-canonical redirect when mapping exists and no redirect when mapping absent in tests/Feature/Operations/ (new file: tests/Feature/Operations/LegacyRunRedirectTest.php)

Implementation (US2)

  • T018 [US2] Add nullable operation_run_id mapping column + FK/index to legacy table inventory_sync_runs (new migration in database/migrations/**_add_operation_run_id_to_inventory_sync_runs_table.php)
  • T019 [US2] Add nullable operation_run_id mapping column + FK/index to legacy table entra_group_sync_runs (new migration in database/migrations/**_add_operation_run_id_to_entra_group_sync_runs_table.php)
  • T020 [US2] Add nullable operation_run_id mapping column + FK/index to legacy table backup_schedule_runs (new migration in database/migrations/**_add_operation_run_id_to_backup_schedule_runs_table.php)
  • T021 [US2] Stop writing NEW legacy run rows for inventory sync and use operation_runs only for execution tracking (adjust service + callers in app/Services/Inventory/InventorySyncService.php and any start surfaces)
  • T022 [US2] Stop writing NEW legacy run rows for directory group sync and use operation_runs only for execution tracking (adjust service + callers in app/Services/Directory/EntraGroupSyncService.php and any start surfaces)
  • T023 [US2] Stop writing NEW legacy run rows for backup schedule executions and use operation_runs only for execution tracking; keep legacy table strictly read-only history for existing rows (adjust dispatcher and UI surfaces in app/Services/BackupScheduling/BackupScheduleDispatcher.php and app/Filament/Resources/BackupScheduleResource.php)
  • T023a [US2] Update Backup Schedule UI to show new executions from operation_runs (query by type + context like schedule_id) and link to canonical viewer; legacy runs list remains history-only
  • T024 [US2] Implement deterministic redirect on legacy “view” pages when operation_run_id exists in app/Filament/Resources/InventorySyncRunResource/Pages/ViewInventorySyncRun.php and app/Filament/Resources/EntraGroupSyncRunResource/Pages/ViewEntraGroupSyncRun.php
  • T025 [US2] Ensure legacy run history pages remain strictly read-only (remove/disable start/retry actions) in app/Filament/Resources/InventorySyncRunResource.php, app/Filament/Resources/EntraGroupSyncRunResource.php, and app/Filament/Resources/BackupScheduleResource/RelationManagers/BackupScheduleRunsRelationManager.php

Checkpoint: Canonical viewer is the only execution-tracker UI; legacy is view-only and redirects only when mapped.


Phase 5: User Story 3 — Use cached directory data in forms without blocking calls (Priority: P3)

Goal: Tenant configuration selectors use cached directory groups + cached role definitions; “Sync now” triggers async sync with an immediate canonical run link; no outbound calls during render/search/label callbacks.

Independent Test: Render Tenant configuration forms and exercise search/label callbacks while asserting Graph client is not called.

Tests (US3)

  • T026 [P] [US3] Add tests that TenantResource role definition selectors render/search DB-only (no Graph calls) in tests/Feature/Filament/ (new file: tests/Feature/Filament/TenantRoleDefinitionsSelectorDbOnlyTest.php)
  • T027 [P] [US3] Add tests that “Sync now” creates an OperationRun and returns a canonical view link in tests/Feature/DirectoryGroups/ or tests/Feature/TenantRBAC/ (choose closest existing folder)
  • T027a [P] [US3] Add tests that directory group selectors render/search DB-only (no Graph calls) and use cached DB tables (new file under tests/Feature/DirectoryGroups/ or tests/Feature/Filament/)

Implementation (US3)

  • T028 [US3] Create cached role definitions table + model + factory (new migration in database/migrations/**_create_entra_role_definitions_table.php, model in app/Models/EntraRoleDefinition.php, factory in database/factories/EntraRoleDefinitionFactory.php)
  • T029 [US3] Add “role definitions sync” operation type directory_role_definitions.sync to app/Support/OperationRunType.php and label in app/Support/OperationCatalog.php (if not already completed in T005/T006)
  • T030 [US3] Implement role definitions sync service + job that updates the cache and records progress/failures on the OperationRun (service in app/Services/Directory/RoleDefinitionsSyncService.php, job in app/Jobs/SyncRoleDefinitionsJob.php)
  • T030a [US3] Register/verify Graph contract entries required for role definitions sync in config/graph_contracts.php and ensure the sync uses GraphClientInterface only (no ad-hoc endpoints)
  • T031 [US3] Update app/Filament/Resources/TenantResource.php roleDefinitions search/label callbacks to query cached DB tables only (remove Graph calls from callbacks)
  • T032 [US3] Add a non-destructive “Sync now” Filament action that dispatches directory_role_definitions.sync and provides a canonical “View run” link (in app/Filament/Resources/TenantResource.php)

Checkpoint: Tenant configuration selectors are DB-only; cache sync is async and observable via canonical run.


Phase 6: Polish & Cross-Cutting Concerns

  • T033 Ensure new/modified destructive-like actions (if any) use Action::make(...)->action(...)->requiresConfirmation() and are authorized server-side (audit existing touched Filament actions under app/Filament/**)
  • T034 Run Pint on changed files via vendor/bin/sail bin pint --dirty
  • T035 Run targeted test subset per quickstart: vendor/bin/sail artisan test --compact --filter=OperationRun and the new/changed test files
  • T036 Allow re-running onboarding verification while status is in_progress (prevents dead-end when a prior run is stuck and the current connection would immediately block with next steps) in app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php
  • T037 Auto-fail stale queued provider operation runs to allow rerun (prevents permanent dedupe when a worker isnt running) in app/Services/Providers/ProviderOperationStartGate.php

Dependencies & Execution Order

Phase Dependencies

  • Setup (Phase 1) → Foundational (Phase 2) → US1 (Phase 3) → US2 (Phase 4) → US3 (Phase 5) → Polish (Phase 6)

User Story Dependencies

  • US1 is the MVP: it enables stable canonical run creation + links.
  • US2 depends on Foundational + US1 (viewer/auth semantics), but can be implemented in parallel once viewer auth is stable.
  • US3 depends on Foundational + cache primitives, but can proceed after Foundational even if US2 is in progress.

Parallel Execution Examples

  • US1 parallelizable: T008 + T009 (tests) can be written in parallel; start-surface patches T010T014 can be split across different files.
  • US2 parallelizable: migrations T018T020 can be done in parallel; legacy resource updates T024T025 can be split by resource.
  • US3 parallelizable: schema/model/factory T028 can be done while tests T026T027 are being drafted.