TenantAtlas/specs/264-cross-tenant-promotion-execution/tasks.md
Ahmed Darrazi 983abb18a1
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 3m22s
chore: commit workspace changes (automated)
2026-05-02 16:36:21 +02:00

18 KiB

description
Task list for Cross-Tenant Promotion Execution v1

Tasks: Cross-Tenant Promotion Execution v1

Input: Design documents from specs/264-cross-tenant-promotion-execution/
Prerequisites: specs/264-cross-tenant-promotion-execution/spec.md, specs/264-cross-tenant-promotion-execution/plan.md, specs/264-cross-tenant-promotion-execution/checklists/requirements.md

Tests: REQUIRED (Pest plus one bounded Browser smoke). Keep proof bounded to PortfolioCompare unit and feature families plus one new Browser/PortfolioCompare smoke file only. Operations: Introduce one canonical promotion.execute OperationRun type and reuse the shared OperationRun start UX, Monitoring links, and current provider-write seams. No promotion-draft table, no compare-snapshot table, no second queue family, and no second promotion dashboard are allowed. RBAC: Non-members and out-of-scope tenants remain 404. Compare-view permissions stay inherited from Spec 043. Execution adds target-tenant manage plus workspace baseline-manage enforcement, with disabled affordance guidance and server-side 403 on forced execution. No new capability family may be introduced. Shared Pattern Reuse: Reuse CrossTenantComparePage, current launch and return context, CrossTenantComparePreviewBuilder, CrossTenantPromotionPreflight, OperationRunService, OperationUxPresenter, ProviderOperationStartResultPresenter, OperationRunLinks, OpsUxBrowserEvents, WorkspaceAuditLogger, AuditActionId, and current provider-write seams. Do not create persisted promotion drafts or a local run-start UX. Filament / Panel Guardrails: Filament remains v5 on Livewire v4. Laravel or Filament service-provider registration remains unchanged in apps/platform/bootstrap/providers.php. No new panel, no new globally searchable resource, and no new asset strategy are allowed. Organization: Tasks are grouped by user story so the execution contract, Monitoring continuity, and safety boundaries remain independently testable and implementable. This package is an explicit delta follow-up over Spec 043 and current code.

Test Governance Checklist

  • Lane assignment stays fast-feedback, confidence, plus one bounded browser smoke and remains the narrowest sufficient proof.
  • New or changed tests stay in apps/platform/tests/Unit/Support/PortfolioCompare/, apps/platform/tests/Feature/PortfolioCompare/, and one new apps/platform/tests/Browser/PortfolioCompare/ smoke file only.
  • Existing portfolio-compare fixtures and current OperationRun assertions are reused; no new heavy provider or browser fixture domain is introduced.
  • Planned validation commands stay consistent across spec, plan, and tasks.
  • The declared surface test profile remains standard-native-filament with explicit real-browser confirmation coverage.
  • Any drift toward persisted drafts, approvals, rollback, or batch promotion is handled as reject-or-split rather than hidden inside this feature.

Phase 1: Setup (Shared Context)

Purpose: Confirm the current compare, preflight, run UX, and provider-write seams before any implementation change.

  • T001 Review specs/264-cross-tenant-promotion-execution/spec.md, specs/264-cross-tenant-promotion-execution/plan.md, specs/264-cross-tenant-promotion-execution/checklists/requirements.md, specs/043-cross-tenant-compare-and-promotion/spec.md, docs/product/spec-candidates.md, docs/product/roadmap.md, and docs/product/implementation-ledger.md together so the slice stays on the current execution gap only.
  • T002 [P] Confirm the current compare-page and launch-context seams in apps/platform/app/Filament/Pages/CrossTenantComparePage.php, apps/platform/tests/Feature/PortfolioCompare/CrossTenantComparePageTest.php, and apps/platform/tests/Feature/PortfolioCompare/CrossTenantCompareLaunchContextTest.php.
  • T003 [P] Confirm the current compare-preview and preflight seams in apps/platform/app/Support/PortfolioCompare/CrossTenantComparePreviewBuilder.php, apps/platform/app/Support/PortfolioCompare/CrossTenantPromotionPreflight.php, and the current PortfolioCompare test coverage.
  • T004 [P] Confirm the current shared run-start, Monitoring-link, and operation-vocabulary seams in apps/platform/app/Services/OperationRunService.php, apps/platform/app/Support/OperationCatalog.php, apps/platform/app/Support/OperationRunType.php, apps/platform/app/Support/OperationRunLinks.php, apps/platform/app/Support/Operations/OperationRunCapabilityResolver.php, apps/platform/app/Support/OperationalControls/OperationalControlCatalog.php, and apps/platform/app/Services/Providers/ProviderOperationRegistry.php only to determine whether app-level operation-registry wiring is required by the chosen shared start-result seam.
  • T005 [P] Confirm the current target-write seam and its constraints in apps/platform/app/Services/Intune/RestoreService.php, apps/platform/app/Jobs/BulkPolicyVersionRestoreJob.php, and apps/platform/app/Jobs/Operations/PolicyVersionRestoreWorkerJob.php, especially the current rule that foreign-tenant policy versions cannot be executed directly.

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Lock the bounded execution contract before surface-level implementation begins.

Critical: No user-story work should begin until this phase is complete.

  • T006 [P] Add apps/platform/tests/Unit/Support/PortfolioCompare/CrossTenantPromotionExecutionPlannerTest.php to require ready-only execution planning, blocked and manual exclusion, stable run-identity inputs, and no-ready rejection.
  • T007 [P] Add apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionAuthorizationTest.php to require 404 for out-of-scope tenants, disabled execution affordance for compare-only actors, and 403 for forced execution without target-manage or workspace-manage access.
  • T008 [P] Add apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionRunUxTest.php to require one canonical promotion.execute run type, shared start-result statuses, and active-run dedupe for the same executable plan.
  • T009 Implement the foundational execution contract in apps/platform/app/Support/OperationCatalog.php, apps/platform/app/Support/OperationRunType.php, apps/platform/app/Support/Operations/OperationRunCapabilityResolver.php, apps/platform/app/Support/OperationalControls/OperationalControlCatalog.php, apps/platform/app/Services/Providers/ProviderOperationRegistry.php only if the shared start-result seam requires app-level operation-registry wiring, apps/platform/app/Support/Audit/AuditActionId.php, and the bounded PortfolioCompare execution planner or bridge chosen for v1 so the feature has one canonical operation vocabulary and no draft persistence. No ProviderOperationRegistry change was required because the shared start-result seam worked through the existing presenter/link contract.

Checkpoint: The canonical run vocabulary, control wiring, audit ids, and ready-only execution plan are locked before page and job work begins.


Phase 3: User Story 1 - Queue one bounded promotion from the current preflight (Priority: P1)

Goal: An authorized operator can confirm and queue a target mutation for ready subjects only from the current compare and preflight context.

Independent Test: Open the compare page, generate a preflight with ready work, confirm Execute promotion, and verify that one promotion.execute run is queued with ready subjects only.

Tests for User Story 1

  • T010 [P] [US1] Add apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionActionTest.php to assert that preflight is required, only ready subjects enter the queued run context, blocked and manual subjects stay excluded, and no-ready execution is blocked.
  • T011 [P] [US1] Extend apps/platform/tests/Feature/PortfolioCompare/CrossTenantComparePageTest.php only where needed to prove the compare page keeps one dominant next action at a time and does not regress the current same-tenant or stale-selection safeguards once execution exists.

Implementation for User Story 1

  • T012 [US1] Add one bounded PortfolioCompare execution planner or bridge plus one execution service in apps/platform/app/Support/PortfolioCompare/ and or apps/platform/app/Services/PortfolioCompare/ that translates the current ready subjects into target-safe mutation inputs without creating a persisted promotion draft.
  • T013 [US1] Update apps/platform/app/Filament/Pages/CrossTenantComparePage.php so the page exposes Execute promotion with explicit confirmation, preserves one-primary-action discipline, and keeps source, target, governed-subject filters, and return-state context intact after queueing.
  • T014 [US1] Add one queued promotion execution job under apps/platform/app/Jobs/Operations/ that consumes OperationRun.context, performs target mutation for ready subjects only, and records canonical summary counts (total, processed, succeeded, failed, skipped, created, updated) instead of inventing a new summary-key family.

Checkpoint: The canonical compare page can queue one bounded target mutation without persisting a draft or mutating blocked subjects.


Phase 4: User Story 2 - Follow the queued promotion through Monitoring with truthful run UX (Priority: P1)

Goal: The operator receives shared queued feedback, one canonical Monitoring link, and truthful run summary after starting a promotion.

Independent Test: Queue a promotion run from the compare page and verify that the start result, Monitoring link, and run-summary truth all stay on the shared OperationRun contract.

Tests for User Story 2

  • T015 [P] [US2] Extend apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionRunUxTest.php to assert queued, deduped, blocked, and Monitoring-link outcomes plus canonical run-context fields for the new operation type.
  • T016 [P] [US2] Add apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionAuditTest.php to assert queued and terminal audit metadata and the absence of any persisted promotion-draft or compare-snapshot writes.
  • T017 [P] [US2] Add apps/platform/tests/Browser/PortfolioCompare/CrossTenantPromotionExecutionSmokeTest.php to prove the live compare page can move from generated preflight to confirmation to queued Open operation handoff without breaking the existing action hierarchy.

Implementation for User Story 2

  • T018 [US2] Wire the shared start-result UX through apps/platform/app/Services/OperationRunService.php, apps/platform/app/Support/OperationRunLinks.php, apps/platform/app/Support/OpsUx/OperationUxPresenter.php, apps/platform/app/Services/Providers/ProviderOperationStartResultPresenter.php, and apps/platform/app/Support/OpsUx/OpsUxBrowserEvents.php so compare-page execution uses canonical queued, deduped, blocked, and run-link messaging. No additional OperationRunService or OperationUxPresenter changes were required beyond compare-page reuse of the shared presenter, link, and browser-event seams.
  • T019 [US2] Extend apps/platform/app/Support/OperationRunLinks.php, apps/platform/app/Support/Navigation/RelatedNavigationResolver.php, and any minimal Monitoring label surface only as needed so promotion.execute opens the current Monitoring viewer without a promotion-specific detail screen. Existing OperationRunLinks::tenantlessView() continuity already satisfied this path without further runtime changes.
  • T020 [US2] Extend apps/platform/app/Services/Audit/WorkspaceAuditLogger.php and apps/platform/app/Support/Audit/AuditActionId.php only as needed so promotion execution records start and terminal audit truth with source-tenant, target-tenant, selection, and outcome metadata.

Checkpoint: The execution path starts, dedupes, blocks, links, and audits on the shared OperationRun seams only.


Phase 5: User Story 3 - Preserve portfolio context and safety boundaries (Priority: P2)

Goal: Execution preserves compare and return-state context while enforcing target-safe control and capability boundaries.

Independent Test: Launch compare from the tenant registry, queue or attempt to queue a promotion, and verify that source, target, return-state, and safety boundaries all remain intact.

Tests for User Story 3

  • T021 [P] [US3] Extend apps/platform/tests/Feature/PortfolioCompare/CrossTenantCompareLaunchContextTest.php to prove queued promotion keeps source-tenant, target-tenant, governed-subject, and return-state continuity. The stable proof now uses the mounted compare-page instance on the exact-two registry launch path, which avoids the flaky secondary Livewire snapshot hop while still exercising the same launched page state and queued promotion contract.
  • T022 [P] [US3] Extend apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionAuthorizationTest.php only where needed to prove stale-preflight, operational-control, and inaccessible-tenant execution attempts never create a run.

Implementation for User Story 3

  • T023 [US3] Preserve compare-page launch and return context after queueing, and add any secondary Open operation continuity only where it does not compete with the primary action. No additional runtime change was required in the bounded slice beyond the existing compare-page state handling and shared operation link seams; T021 now provides the explicit queued launch-context continuity proof.
  • T024 [US3] Integrate operational-control and legitimacy blocking for promotion.execute so blocked, stale, or inaccessible execution attempts fail safely without widening into approvals, rollback, or batch controls.

Checkpoint: The execution path stays usable inside the portfolio workflow and still fails closed at every safety boundary.


Phase 6: Polish & Cross-Cutting Validation

Purpose: Validate the bounded slice and stop without widening scope.

  • T025 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/PortfolioCompare/CrossTenantPromotionExecutionPlannerTest.php.
  • T026 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionActionTest.php tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionAuthorizationTest.php tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionAuditTest.php tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionRunUxTest.php tests/Feature/PortfolioCompare/CrossTenantComparePageTest.php tests/Feature/PortfolioCompare/CrossTenantCompareLaunchContextTest.php.
  • T027 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/PortfolioCompare/CrossTenantPromotionExecutionSmokeTest.php.
  • T028 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent.
  • T029 [P] Review touched code to confirm Filament stays on Livewire v4, Laravel or Filament service-provider registration remains unchanged in apps/platform/bootstrap/providers.php, no globally searchable resource contract changes appear, and the mutating compare-page action uses explicit confirmation.
  • T030 [P] Review touched code to confirm the feature introduces no promotion-draft persistence, no compare-snapshot persistence, no second queue family, no second promotion surface, no approval workflow, and no rollback workflow.
  • T031 [P] Record the final guardrail, smoke, and scope-boundary outcomes in the active feature close-out without reopening batch promotion, approvals, rollback, or multi-provider follow-up work.

Dependencies & Execution Order

Phase Dependencies

  • Phase 1 (Setup): no dependencies; start immediately.
  • Phase 2 (Foundational): depends on Phase 1 and blocks all user stories.
  • Phase 3 (US1): depends on Phase 2 and establishes the bounded execution path.
  • Phase 4 (US2): depends on Phase 2 and should land with US1 so the start-result UX and Monitoring truth do not drift from the queued path.
  • Phase 5 (US3): depends on Phase 2 and hardens context and safety behavior after the execution path exists.
  • Phase 6 (Polish): depends on all desired user stories being complete.

User Story Dependencies

  • US1 (P1): independently testable after Phase 2 and delivers the core execution value.
  • US2 (P1): independently testable after Phase 2 and should ship with US1 so the operator gets truthful Monitoring handoff.
  • US3 (P2): independently testable after Phase 2 and hardens the bounded execution path.

Within Each User Story

  • Write the listed Pest coverage first and make it fail for the intended gap.
  • Keep implementation inside the compare page, bounded PortfolioCompare execution seam, shared OperationRun UX, and current provider-write paths named above.
  • Re-run the narrowest relevant validation command after each story checkpoint before moving on.

Implementation Strategy

Suggested MVP Scope

  • MVP = US1 + US2 together. The feature is only useful when the compare page can both queue promotion and hand the operator into truthful Monitoring continuity.

Incremental Delivery

  1. Complete Phase 1 and Phase 2.
  2. Deliver US1 and US2 together on the current compare page and shared run UX.
  3. Add US3 to keep return-state and safety boundaries intact.
  4. Finish with the focused validation and guardrail review tasks in Phase 6.

Team Strategy

  1. Settle the bounded execution bridge first.
  2. Parallelize failing tests within each story before runtime edits.
  3. Serialize merges around CrossTenantComparePage, operation-catalog wiring, and shared Monitoring links so operator vocabulary stays coherent.

Deferred Follow-Ups / Non-Goals

  • persisted promotion drafts or compare snapshots
  • approval workflow before execution
  • rollback or replay workflow after execution
  • batch or multi-target promotion
  • automated manual-mapping resolution
  • customer-facing promotion surfaces
  • multi-provider execution framework