TenantAtlas/specs/203-baseline-compare-strategy/tasks.md
ahmido d644265d30 Spec 203: extract baseline compare strategy (#233)
## Summary
- extract baseline compare orchestration behind an explicit strategy contract and registry
- preserve the current Intune compare path through a dedicated `IntuneCompareStrategy`
- harden compare launch and review surfaces for mixed, unsupported, incomplete, and strategy-failure truth
- add Spec 203 artifacts, focused regression coverage, and future-domain strategy proof tests

## Testing
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Baselines/CompareStrategyRegistryTest.php tests/Unit/Baselines/CompareSubjectResultContractTest.php tests/Feature/Baselines/BaselineCompareStrategySelectionTest.php tests/Feature/Baselines/BaselineComparePreconditionsTest.php tests/Feature/Baselines/BaselineCompareExecutionGuardTest.php tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php tests/Feature/Filament/BaselineCompareLandingWhyNoFindingsTest.php tests/Feature/Filament/BaselineCompareMatrixPageTest.php tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

## Notes
- no new Filament panel/provider registration changes
- no global-search resource changes
- no new asset registration or deployment step changes

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #233
2026-04-13 21:17:04 +00:00

246 lines
21 KiB
Markdown

# Tasks: Baseline Compare Engine Strategy Extraction
**Input**: Design documents from `/specs/203-baseline-compare-strategy/`
**Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `contracts/baseline-compare-strategy.logical.openapi.yaml`, `quickstart.md`
**Tests**: Required. This feature changes runtime compare orchestration, existing Filament start surfaces, and canonical `baseline_compare` run truth, so Pest unit, feature, Filament, and existing browser smoke coverage must be added or extended.
**Operations**: This feature reuses the existing `baseline_compare` `OperationRun` lifecycle only. No new run type, queued notification channel, or alternate monitoring surface should be introduced.
**RBAC**: Existing workspace and tenant compare capabilities remain authoritative. Tasks must preserve `404` vs `403` semantics while treating unsupported or mixed scope as compare truth rather than authorization.
**Operator Surfaces**: The affected surfaces are the existing baseline profile detail, baseline compare matrix, tenant baseline compare landing, and canonical operation run detail.
**Filament UI Action Surfaces**: Existing `Compare now` and `Compare assigned tenants` actions remain the primary launch actions. No new destructive action is added.
**Proportionality**: Add only the narrow compare-support namespace under `apps/platform/app/Support/Baselines/Compare/` and avoid a broader compare plugin framework.
**Organization**: Tasks are grouped by user story so each slice stays independently testable. Recommended delivery order is `US1 -> US2 -> US3 -> US4`, with `US1` as the MVP cut after the shared compare-contract foundation is in place.
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Prepare focused test seams for compare strategy selection, compare-result contracts, and future-domain proof coverage.
- [X] T001 Create the compare strategy registry unit test scaffold in `apps/platform/tests/Unit/Baselines/CompareStrategyRegistryTest.php`
- [X] T002 [P] Create the compare subject result contract unit test scaffold in `apps/platform/tests/Unit/Baselines/CompareSubjectResultContractTest.php`
- [X] T003 [P] Create the future-domain compare strategy support fixture and feature test scaffold in `apps/platform/tests/Feature/Baselines/Support/FakeCompareStrategy.php` and `apps/platform/tests/Feature/Baselines/BaselineCompareStrategySelectionTest.php`
**Checkpoint**: Dedicated Spec 203 test entry points exist and the compare extraction can proceed without mixing this slice into unrelated suites.
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Establish the shared compare strategy, selection, and subject-result contracts before any story-specific behavior lands.
**CRITICAL**: No user story work should start before this phase is complete.
- [X] T004 [P] Add foundational capability, selection-state, and result-contract expectations in `apps/platform/tests/Unit/Baselines/CompareStrategyRegistryTest.php` and `apps/platform/tests/Unit/Baselines/CompareSubjectResultContractTest.php`
- [X] T005 [P] Add shared preflight selection and single-strategy handoff coverage in `apps/platform/tests/Feature/Baselines/BaselineComparePreconditionsTest.php` and `apps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php`
- [X] T006 [P] Extend compare run lifecycle and summary-count guard coverage in `apps/platform/tests/Feature/Guards/OperationLifecycleOpsUxGuardTest.php`, `apps/platform/tests/Feature/OpsUx/OperationSummaryKeysSpecTest.php`, and `apps/platform/tests/Feature/OpsUx/SummaryCountsWhitelistTest.php`
- [X] T007 Implement compare selection enums and subject-result value objects in `apps/platform/app/Support/Baselines/Compare/CompareStrategyKey.php`, `apps/platform/app/Support/Baselines/Compare/StrategySelectionState.php`, `apps/platform/app/Support/Baselines/Compare/CompareState.php`, `apps/platform/app/Support/Baselines/Compare/CompareSubjectIdentity.php`, `apps/platform/app/Support/Baselines/Compare/CompareSubjectProjection.php`, `apps/platform/app/Support/Baselines/Compare/CompareFindingCandidate.php`, and `apps/platform/app/Support/Baselines/Compare/CompareSubjectResult.php`
- [X] T008 Implement the compare strategy contract, capability record, selection record, orchestration context, and registry in `apps/platform/app/Support/Baselines/Compare/CompareStrategy.php`, `apps/platform/app/Support/Baselines/Compare/CompareStrategyCapability.php`, `apps/platform/app/Support/Baselines/Compare/CompareStrategySelection.php`, `apps/platform/app/Support/Baselines/Compare/CompareOrchestrationContext.php`, and `apps/platform/app/Support/Baselines/Compare/CompareStrategyRegistry.php`
- [X] T009 Wire shared strategy bootstrap and run-context handoff into `apps/platform/app/Services/Baselines/BaselineCompareService.php` and `apps/platform/app/Jobs/CompareBaselineToTenantJob.php`
**Checkpoint**: The repo can model one supported compare strategy family, reject non-deterministic selection at the contract layer, preserve Ops-UX lifecycle guards, and hand a structured compare context into the existing compare job.
---
## Phase 3: User Story 1 - Preserve current Intune compare through an explicit boundary (Priority: P1) MVP
**Goal**: Keep the current supported Intune compare behavior stable while moving domain-specific compare logic behind one explicit strategy boundary.
**Independent Test**: Start supported Intune compare from the existing tenant and workspace surfaces and verify findings, summaries, and trust semantics remain unchanged through the extracted strategy path.
### Tests for User Story 1
> **NOTE**: Write these tests first and confirm they fail before implementation.
- [X] T010 [P] [US1] Extend supported Intune compare classification and finding parity coverage in `apps/platform/tests/Feature/Baselines/BaselineCompareFindingsTest.php`, `apps/platform/tests/Feature/Baselines/BaselineCompareGapClassificationTest.php`, and `apps/platform/tests/Feature/Baselines/BaselineCompareRbacRoleDefinitionsTest.php`
- [X] T011 [P] [US1] Extend supported-scope launch, run-outcome, and summary parity coverage in `apps/platform/tests/Feature/Baselines/BaselineCompareExecutionGuardTest.php`, `apps/platform/tests/Feature/Baselines/BaselineCompareSummaryAssessmentTest.php`, `apps/platform/tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php`, and `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php`
- [X] T012 [P] [US1] Extend explanation, why-no-findings, and evidence-contract parity coverage in `apps/platform/tests/Feature/Baselines/BaselineCompareWhyNoFindingsReasonCodeTest.php`, `apps/platform/tests/Feature/Baselines/BaselineCompareExplanationFallbackTest.php`, `apps/platform/tests/Feature/Baselines/BaselineCompareDriftEvidenceContractTest.php`, and `apps/platform/tests/Feature/Baselines/BaselineCompareDriftEvidenceContractRbacTest.php`
### Implementation for User Story 1
- [X] T013 [US1] Implement the explicit `IntuneCompareStrategy` and register its supported capability family in `apps/platform/app/Support/Baselines/Compare/IntuneCompareStrategy.php` and `apps/platform/app/Support/Baselines/Compare/CompareStrategyRegistry.php`
- [X] T014 [US1] Route supported compare starts through deterministic strategy selection and record the chosen strategy in `apps/platform/app/Services/Baselines/BaselineCompareService.php` and `apps/platform/app/Jobs/CompareBaselineToTenantJob.php`
- [X] T015 [US1] Move Intune-only subject discovery, normalizer selection, RBAC role-definition branching, and projection shaping behind the strategy boundary in `apps/platform/app/Support/Baselines/Compare/IntuneCompareStrategy.php` and `apps/platform/app/Jobs/CompareBaselineToTenantJob.php`
- [X] T016 [US1] Feed existing finding, summary, explanation, and badge semantics from `CompareSubjectResult` without changing supported Intune outcomes in `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/Baselines/BaselineCompareSummaryAssessor.php`, `apps/platform/app/Support/Baselines/BaselineCompareExplanationRegistry.php`, `apps/platform/app/Support/Badges/BadgeDomain.php`, and `apps/platform/app/Support/Badges/BadgeCatalog.php`
**Checkpoint**: Supported Intune compare remains independently functional and regression-protected through the new explicit strategy seam.
---
## Phase 4: User Story 2 - Reject unsupported or mixed-domain compare scope honestly (Priority: P1)
**Goal**: Fail unsupported or mixed compare scope before enqueue so operators never launch misleading compare work.
**Independent Test**: Attempt tenant and workspace fan-out compare with unsupported, inactive, and mixed-family canonical scope and confirm the start surfaces reject the work before any compare run is started.
### Tests for User Story 2
> **NOTE**: Write these tests first and confirm they fail before implementation.
- [X] T017 [P] [US2] Extend unsupported, mixed-family, and inactive-type compare gating coverage in `apps/platform/tests/Feature/Baselines/BaselineComparePreconditionsTest.php` and `apps/platform/tests/Feature/Baselines/BaselineCompareMatrixCompareAllActionTest.php`
- [X] T018 [P] [US2] Extend start-surface rejection truth and authorization continuity in `apps/platform/tests/Feature/Filament/BaselineProfileCompareStartSurfaceTest.php`, `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php`, and `apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php`
### Implementation for User Story 2
- [X] T019 [US2] Enforce supported, unsupported, and mixed selection outcomes before run creation in `apps/platform/app/Services/Baselines/BaselineCompareService.php` and `apps/platform/app/Support/Baselines/Compare/CompareStrategyRegistry.php`
- [X] T020 [US2] Add operator-safe compare rejection reason codes and diagnostics mapping in `apps/platform/app/Support/Baselines/BaselineCompareReasonCode.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, and `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`
- [X] T021 [US2] Surface truthful unsupported and mixed-scope launch messaging on the existing compare pages in `apps/platform/app/Filament/Resources/BaselineProfileResource.php`, `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php`, `apps/platform/app/Filament/Pages/BaselineCompareMatrix.php`, and `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`
**Checkpoint**: Unsupported or mixed compare scope is independently blocked before run creation and explained truthfully on the existing launch surfaces.
---
## Phase 5: User Story 3 - Keep one platform compare story while allowing domain-specific logic (Priority: P2)
**Goal**: Prove that a future non-Intune strategy can participate in the same compare lifecycle without forcing policy-only platform defaults.
**Independent Test**: Register a non-Intune test strategy against canonical scope and confirm the entrypoint resolves it deterministically, executes the shared lifecycle, and emits structured compare results without Intune fallbacks.
### Tests for User Story 3
> **NOTE**: Write these tests first and confirm they fail before implementation.
- [X] T022 [P] [US3] Add unit coverage for future-domain capability matching, deterministic selection, and no-implicit-fallback behavior in `apps/platform/tests/Unit/Baselines/CompareStrategyRegistryTest.php`
- [X] T023 [P] [US3] Add non-Intune strategy lifecycle coverage using `apps/platform/tests/Feature/Baselines/Support/FakeCompareStrategy.php` and `apps/platform/tests/Feature/Baselines/BaselineCompareStrategySelectionTest.php`
### Implementation for User Story 3
- [X] T024 [US3] Register strategy-owned domain, subject-class, and subject-type capability declarations without policy-only defaults in `apps/platform/app/Support/Baselines/Compare/CompareStrategyCapability.php`, `apps/platform/app/Support/Baselines/Compare/CompareStrategyRegistry.php`, and `apps/platform/app/Support/Baselines/Compare/IntuneCompareStrategy.php`
- [X] T025 [US3] Keep platform summary and explanation aggregation domain-neutral by consuming strategy projections instead of policy defaults in `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/Baselines/BaselineCompareSummaryAssessor.php`, and `apps/platform/app/Support/Baselines/BaselineCompareExplanationRegistry.php`
- [X] T026 [US3] Keep the unified finding lifecycle strategy-neutral by consuming `CompareFindingCandidate` and `CompareSubjectProjection` in `apps/platform/app/Jobs/CompareBaselineToTenantJob.php` and `apps/platform/app/Support/Baselines/Compare/CompareSubjectResult.php`
**Checkpoint**: The compare lifecycle is independently capable of resolving and consuming a non-Intune strategy without cloning the platform orchestration path.
---
## Phase 6: User Story 4 - Preserve truthful degraded and failed states (Priority: P2)
**Goal**: Keep unsupported, incomplete, ambiguous, and failed compare outcomes distinct so the new boundary does not blur operator trust semantics.
**Independent Test**: Exercise unsupported-subject, incomplete-evidence, ambiguous-match, and strategy-failure cases and verify the compare landing and canonical run detail keep those outcomes distinct from no drift.
### Tests for User Story 4
> **NOTE**: Write these tests first and confirm they fail before implementation.
- [X] T027 [P] [US4] Extend ambiguous, incomplete, unsupported-subject, and strategy-failure coverage in `apps/platform/tests/Feature/Baselines/BaselineCompareAmbiguousMatchGapTest.php`, `apps/platform/tests/Feature/Baselines/BaselineCompareGapClassificationTest.php`, and `apps/platform/tests/Feature/Baselines/BaselineCompareExecutionGuardTest.php`
- [X] T028 [P] [US4] Extend operator truth coverage for degraded and failed compare states in `apps/platform/tests/Feature/Filament/BaselineCompareLandingWhyNoFindingsTest.php`, `apps/platform/tests/Feature/Filament/BaselineCompareLandingAdminTenantParityTest.php`, `apps/platform/tests/Feature/Filament/BaselineCompareExplanationSurfaceTest.php`, and `apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`
### Implementation for User Story 4
- [X] T029 [US4] Map strategy `unsupported`, `incomplete`, `ambiguous`, and `failed` states to stable compare reasons and summary counts in `apps/platform/app/Support/Baselines/BaselineCompareReasonCode.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, and `apps/platform/app/Support/Baselines/BaselineCompareSummaryAssessor.php`
- [X] T030 [US4] Persist secondary strategy diagnostics and degraded-state evidence without collapsing run outcome truth in `apps/platform/app/Jobs/CompareBaselineToTenantJob.php`, `apps/platform/app/Support/Baselines/BaselineCompareEvidenceGapDetails.php`, and `apps/platform/app/Support/Baselines/BaselineCompareExplanationRegistry.php`
- [X] T031 [US4] Update compare landing and canonical run-detail review surfaces for unsupported, incomplete, ambiguous, and failed states in `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`, `apps/platform/app/Filament/Resources/OperationRunResource.php`, and `apps/platform/resources/views/filament/pages/baseline-compare-landing.blade.php`
**Checkpoint**: Degraded and failed compare states remain independently reviewable and never collapse into calm no-drift semantics.
---
## Phase 7: Polish & Cross-Cutting Concerns
**Purpose**: Lock the slice down with operator-copy review, performance and browser smoke regression guards, and explicit Sail verification.
- [X] T032 [P] Recheck launch-surface operator copy and naming consistency in `apps/platform/app/Filament/Resources/BaselineProfileResource.php`, `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php`, and `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`
- [X] T033 [P] Recheck matrix and run-detail diagnostic wording plus scope-language consistency in `apps/platform/app/Filament/Pages/BaselineCompareMatrix.php`, `apps/platform/app/Filament/Resources/OperationRunResource.php`, and `apps/platform/resources/views/filament/pages/baseline-compare-landing.blade.php`
- [X] T034 [P] Extend compare performance and enqueue-only regression coverage in `apps/platform/tests/Feature/Baselines/BaselineComparePerformanceGuardTest.php` and `apps/platform/tests/Feature/Operations/BaselineQueueRuntimeGuardTest.php`
- [X] T035 [P] Extend matrix browser smoke, no-silent-fallback assertions, and final launch-truth regressions in `apps/platform/tests/Browser/Spec190BaselineCompareMatrixSmokeTest.php`, `apps/platform/tests/Feature/Baselines/BaselineCompareExecutionGuardTest.php`, and `apps/platform/tests/Feature/Baselines/BaselineComparePreconditionsTest.php`
- [X] T036 Run the focused Sail test pack from `specs/203-baseline-compare-strategy/quickstart.md` against the changed unit, feature, Filament, and browser files
- [X] T037 Run formatting and final Ops-UX guard verification in `apps/platform/tests/Feature/Guards/OperationLifecycleOpsUxGuardTest.php`, `apps/platform/tests/Feature/OpsUx/OperationSummaryKeysSpecTest.php`, `apps/platform/tests/Feature/OpsUx/SummaryCountsWhitelistTest.php`, and `apps/platform/tests/Feature/OpsUx/NoQueuedDbNotificationsTest.php`
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: No dependencies; can start immediately.
- **Foundational (Phase 2)**: Depends on Setup completion; blocks all user stories.
- **User Story 1 (Phase 3)**: Depends on Foundational completion; this is the recommended MVP cut.
- **User Story 2 (Phase 4)**: Depends on Foundational completion and is easiest to review after US1 proves the supported strategy path stays stable.
- **User Story 3 (Phase 5)**: Depends on Foundational completion and on the extracted result contract from US1.
- **User Story 4 (Phase 6)**: Depends on Foundational completion and benefits from US1 and US2 because degraded truth builds on the extracted strategy path and explicit rejection semantics.
- **Polish (Phase 7)**: Depends on all desired user stories being complete.
### User Story Dependencies
- **US1**: No dependencies beyond Foundational.
- **US2**: No hard dependency beyond Foundational, but it should follow US1 so the supported path is already stable before rejected paths are hardened.
- **US3**: Depends on the shared compare contract from Foundational and the extracted strategy path from US1.
- **US4**: Depends on the shared compare contract from Foundational and should follow US1 and US2 so run truth and rejection truth are already explicit.
### Within Each User Story
- Write the story tests first and confirm they fail before implementation.
- Keep compare start orchestration in `BaselineCompareService.php` and execution in `CompareBaselineToTenantJob.php`; story work should not introduce a parallel compare workflow.
- Finish each story's focused verification before moving to the next priority.
### Parallel Opportunities
- `T002` and `T003` can run in parallel after `T001`.
- `T004`, `T005`, and `T006` can run in parallel before `T007` through `T009`.
- Within US1, `T010`, `T011`, and `T012` can run in parallel.
- Within US2, `T017` and `T018` can run in parallel.
- Within US3, `T022` and `T023` can run in parallel.
- Within US4, `T027` and `T028` can run in parallel.
- `T032`, `T033`, `T034`, and `T035` can run in parallel once implementation is complete.
---
## Parallel Example: User Story 1
```bash
# Parallel test pass for US1
T010 Extend supported Intune compare classification and finding parity coverage
T011 Extend supported-scope launch, run-outcome, and summary parity coverage
T012 Extend explanation, why-no-findings, and evidence-contract parity coverage
```
## Parallel Example: User Story 2
```bash
# Parallel test pass for US2
T017 Extend unsupported, mixed-family, and inactive-type compare gating coverage
T018 Extend start-surface rejection truth and authorization continuity
```
## Parallel Example: User Story 3
```bash
# Parallel test pass for US3
T022 Add unit coverage for future-domain capability matching and deterministic selection
T023 Add non-Intune strategy lifecycle coverage with FakeCompareStrategy
```
## Parallel Example: User Story 4
```bash
# Parallel test pass for US4
T027 Extend ambiguous, incomplete, unsupported-subject, and strategy-failure coverage
T028 Extend operator truth coverage for degraded and failed compare states
```
---
## Implementation Strategy
### MVP First
1. Finish Setup and Foundational work.
2. Deliver US1 to prove Intune compare survives the extraction behind one explicit strategy.
3. Validate US1 independently before widening the slice.
### Incremental Delivery
1. Add US2 to reject unsupported or mixed scope honestly before enqueue.
2. Add US3 to prove future-domain strategy participation without policy-only defaults.
3. Add US4 to harden degraded and failed compare truth on the existing review surfaces.
4. Finish with copy review, performance and browser smoke guards, and the explicit Sail verification pack from Phase 7.
### Parallel Team Strategy
1. One contributor completes Setup and Foundational tasks.
2. After Foundation is green:
- Contributor A takes US1.
- Contributor B prepares US2 test coverage and launch-surface hardening.
- Contributor C prepares US3 registry and fake-strategy proof work.
- Contributor D prepares US4 degraded-truth coverage and review-surface hardening.
3. Merge back for Phase 7 guard, performance, browser smoke, formatting, and focused Sail verification.