TenantAtlas/specs/382-baseline-matching-canonicalization/tasks.md
ahmido 788efee1c2 feat(baselines): implement baseline matching canonicalization (#453)
Replaced legacy tenant and environment bindings in the BaselineDriftEngine with the new ProviderResourceIdentity framework as defined in Spec 382. This ensures cross-environment compatibility and deterministic baseline matching.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #453
2026-06-15 22:48:48 +00:00

151 lines
14 KiB
Markdown

# Tasks: Spec 382 - Baseline Matching Pipeline and Canonicalization v1
**Input**: Design documents from `/specs/382-baseline-matching-canonicalization/`
**Prerequisites**: `spec.md`, `plan.md`, Spec 381 implementation close-out
**Tests**: Runtime behavior changes require Pest unit and feature tests before or alongside implementation. Browser tests are not required because this spec has no UI surface impact.
## Test Governance Checklist
- [x] TGC001 Lane assignment is named and is the narrowest sufficient proof for the changed behavior.
- [x] TGC002 New or changed tests stay in the smallest honest family, and any heavy-governance or browser addition is explicit.
- [x] TGC003 Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default; any widening is isolated or documented.
- [x] TGC004 Planned validation commands cover the change without pulling in unrelated lane cost.
- [x] TGC005 The declared surface test profile or `standard-native-filament` relief is explicit.
- [x] TGC006 Any material budget, baseline, trend, or escalation note is recorded in the active spec or PR.
## Phase 1: Preparation And Guardrails
**Purpose**: Protect completed-spec history and confirm the implementation slice before runtime changes.
- [x] T001 Confirm `specs/381-provider-resource-identity-binding/implementation-close-out.md` exists and treat Spec 381 as completed dependency context only.
- [x] T002 Confirm no code changes are made to `specs/163-baseline-subject-resolution/`, `specs/380-management-report-pdf-staging-runtime-validation/`, or `specs/381-provider-resource-identity-binding/`.
- [x] T003 Re-read `apps/platform/app/Support/Resources/ResourceIdentity.php`, `apps/platform/app/Support/Resources/ProviderResourceDescriptor.php`, `apps/platform/app/Models/ProviderResourceBinding.php`, and `apps/platform/app/Services/Resources/ProviderResourceBindingService.php` before implementation.
- [x] T004 Re-read `apps/platform/app/Jobs/CompareBaselineToTenantJob.php`, `apps/platform/app/Support/Baselines/SubjectResolver.php`, `apps/platform/app/Support/Baselines/BaselineSubjectKey.php`, and `apps/platform/app/Support/Baselines/Compare/CompareStrategyRegistry.php` before implementation.
- [x] T005 Document in `specs/382-baseline-matching-canonicalization/implementation-close-out.md` that Spec 382 has no UI, Filament, Livewire, asset, migration, environment variable, queue-name, scheduler, or storage surface impact unless the spec is updated first.
---
## Phase 2: Tests First - Matching Core
**Purpose**: Lock the business truth before changing compare behavior.
- [x] T006 [P] [US1] Add `tests/Unit/Support/Baselines/Matching/BaselineSubjectDescriptorTest.php` covering provider identity, canonical subject key, display label as metadata, and source-reference sanitization.
- [x] T007 [P] [US1] Add `tests/Unit/Support/Baselines/Matching/MatchingOutcomeTest.php` covering resolved, ambiguous, missing-provider-resource, missing-local-evidence, unsupported, limited, excluded, and unresolved-identity outcomes.
- [x] T008 [P] [US1] Add `tests/Unit/Support/Baselines/Matching/SubjectMatchingPipelineTest.php` covering binding-first priority, exact provider identity, canonical provider-resource keys, duplicate provider-identity ambiguity, missing identity gaps, same-label/different-provider-id separation, and deterministic ordering.
- [x] T009 [P] [US2] Add built-in/default/virtual fake-provider proof in `tests/Unit/Support/Baselines/Matching/SubjectMatchingPipelineTest.php` without adding a production canonicalizer registry.
- [x] T010 [P] [US3] Add `tests/Unit/Services/Baselines/Matching/FoundationCoverageResolverTest.php` covering inventory-only, canonical-only, unsupported, and existing support-contract classification.
---
## Phase 3: Tests First - Integration And Regression
**Purpose**: Prove binding-aware compare behavior, isolation, and identity-required gaps before implementation.
- [x] T011 [P] [US4] Replace `tests/Feature/Baselines/BaselineCompareProviderResourceBindingNoOpTest.php` with canonical identity coverage so active provider resource bindings are expected to be consumed rather than ignored.
- [x] T012 [P] [US1] Confirm `tests/Feature/Baselines/BaselineCompareAmbiguousMatchGapTest.php` proves duplicate provider-resource identity candidates without active binding remain unresolved ambiguity, while same labels alone do not match.
- [x] T013 [P] [US3] Confirm `tests/Feature/Baselines/BaselineCompareGapClassificationTest.php` still proves inventory-only or unsupported foundation resources do not become false policy-missing blockers.
- [x] T014 [P] [US1] Extend `tests/Feature/ProviderResources/ProviderResourceBindingServiceTest.php` so arbitrary `canonical_subject_key` overrides are rejected unless generated or validated as provider-resource canonical keys.
- [x] T015 [P] [US1] Cover binding-aware compare behavior in `tests/Feature/Baselines/BaselineCompareProviderResourceBindingCanonicalIdentityTest.php` and matching proof/priority behavior in `tests/Unit/Support/Baselines/Matching/SubjectMatchingPipelineTest.php`.
- [x] T016 [P] [US2] Cover fake-provider built-ins and virtual targets in `tests/Unit/Support/Baselines/Matching/SubjectMatchingPipelineTest.php` without Microsoft label hardcoding or provider runtime calls.
- [x] T017 [P] [US4] Confirm `tests/Feature/Evidence/BaselineDriftPostureSourceTest.php` and `tests/Feature/ReviewPack/Spec349ReviewPackResolutionGuidanceTest.php` still prove no intentional evidence/review readiness behavior change.
---
## Phase 4: Canonical Key And Legacy Removal
**Purpose**: Prevent old display-name subject keys from masquerading as canonical provider-resource identity and remove legacy identity residue.
- [x] T018 [US1] Update `apps/platform/app/Support/Baselines/BaselineSubjectKey.php` with provider-resource canonical key validation helpers if existing generation helpers are insufficient.
- [x] T019 [US1] Update `apps/platform/app/Services/Resources/ProviderResourceBindingService.php` so supplied canonical keys are accepted only when validated as provider-resource canonical keys for the supplied subject scope and `ResourceIdentity`.
- [x] T020 [US1] Remove `legacy_subject_key` from `apps/platform/app/Services/Resources/ProviderResourceBindingService.php`, DTO/service inputs, factories, and active tests; add a Spec 382 migration that drops the column because Spec 381 already created it.
- [x] T021 [US1] Confirm `apps/platform/database/factories/ProviderResourceBindingFactory.php` generates provider-resource canonical keys by default and does not include legacy subject-key attributes.
---
## Phase 5: Matching Support Types
**Purpose**: Add the narrow runtime objects needed for pre-compare matching.
- [x] T022 [P] [US1] Add `apps/platform/app/Support/Baselines/Matching/BaselineSubjectDescriptor.php` for baseline-side subject identity and sanitized source references.
- [x] T023 [P] [US1] Add `apps/platform/app/Support/Baselines/Matching/MatchingOutcome.php` for resolved, ambiguous, missing, unsupported, limited, excluded, and unresolved-identity outcomes.
- [x] T024 [P] [US1] Keep confidence as derived strings inside `MatchingOutcome`; no separate `MatchingConfidence` class needed.
- [x] T025 [US1] Add descriptor-builder methods in `CompareBaselineToTenantJob` to derive baseline descriptors from `BaselineSnapshotItem` without making display labels authoritative.
- [x] T026 [US1] Add current provider descriptor collection helpers in `CompareBaselineToTenantJob` where existing `ProviderResourceDescriptor` construction was insufficient.
---
## Phase 6: Canonicalization And Foundation Coverage
**Purpose**: Keep provider-specific built-in/default/virtual logic behind narrow seams and avoid false policy-backed blockers.
- [x] T027 [P] [US2] Avoid adding a production canonicalizer interface/registry by default; use `ResourceIdentity` provider metadata and fake-provider coverage instead.
- [x] T028 [P] [US2] Add a minimal provider-owned built-in/default/virtual canonicalization seam through provider `ResourceIdentity` metadata, with fake-provider proof and no Microsoft label hardcoding in core.
- [x] T029 [P] [US2] Do not add `CanonicalizationResult`; `ResourceIdentity` plus `MatchingOutcome` is sufficient for v1 behavior and proof metadata.
- [x] T030 [US3] Add `apps/platform/app/Services/Baselines/Matching/FoundationCoverageResolver.php` that reuses `InventoryPolicyTypeMeta`, `BaselineSupportCapabilityGuard`, and existing support metadata before introducing any new classification source.
- [x] T031 [US2] Confirm any Microsoft/Intune canonicalization remains provider-owned, uses stable persisted provider metadata rather than display labels such as `All users`, `All devices`, or `Default`, and does not call `GraphClientInterface`, provider gateways, or provider runtime clients.
---
## Phase 7: Subject Matching Pipeline
**Purpose**: Implement the deterministic matching priority before payload comparison.
- [x] T032 [US1] Add `apps/platform/app/Services/Baselines/Matching/SubjectMatchingPipeline.php` with matching order: active binding, provider identity/canonical identity, unresolved duplicate ambiguity, identity-required gaps, and missing/unsupported/limitation. Fingerprints, legacy keys, and display labels are not matching sources.
- [x] T033 [US1] Ensure `SubjectMatchingPipeline` scopes active binding lookup by `workspace_id`, `managed_environment_id`, canonical subject key, and active binding status; provider key is embedded in the canonical key and rechecked through binding identity fields.
- [x] T034 [US1] Ensure `SubjectMatchingPipeline` never uses display names, fingerprints, or legacy subject keys as matching evidence.
- [x] T035 [US3] Ensure `SubjectMatchingPipeline` returns missing-local-evidence instead of missing-provider-resource when provider absence is not proven.
- [x] T036 [US4] Ensure `SubjectMatchingPipeline` treats identity resolution separately from drift/no-drift and does not mark matched resources healthy by itself.
---
## Phase 8: Baseline Compare Integration
**Purpose**: Consume matching outcomes in compare without broad result/UI/evidence scope.
- [x] T037 [US4] Integrate `SubjectMatchingPipeline` into `apps/platform/app/Jobs/CompareBaselineToTenantJob.php` before old `policy_type|subject_key` keying can collapse or discard candidates, remove the unused old keyed readers, and run before compare strategy payload comparison.
- [x] T038 [US4] Keep existing compare strategies in `apps/platform/app/Support/Baselines/Compare/` responsible for payload drift/no-drift after a successful comparable match.
- [x] T039 [US4] Leave `apps/platform/app/Support/Baselines/SubjectResolver.php` unchanged; matching outcomes are mapped in the compare job adapter, so SubjectResolver remains non-authoritative for identity.
- [x] T040 [US3] Store only sanitized matching proof metadata in existing compare result or operation context paths; no secrets, raw sensitive provider payloads, raw Graph errors, credentials, or operator notes are stored.
- [x] T041 [US4] Confirm no Evidence Snapshot readiness, Review Pack readiness, customer-facing report wording, or operator resolution UI behavior changes are introduced.
---
## Phase 9: Validation And Close-Out
**Purpose**: Prove the prepared scope and keep implementation reviewable.
- [x] T042 Run `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/Baselines/Matching`.
- [x] T043 Run `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/Baselines/BaselineSubjectKeyCanonicalIdentityTest.php tests/Unit/Support/Resources/ResourceIdentityTest.php tests/Unit/Support/Resources/ProviderResourceDescriptorTest.php`.
- [x] T044 Run `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Baselines/BaselineCompareProviderResourceBindingCanonicalIdentityTest.php tests/Feature/Baselines/BaselineCompareAmbiguousMatchGapTest.php tests/Feature/Baselines/BaselineCompareGapClassificationTest.php tests/Feature/Evidence/BaselineDriftPostureSourceTest.php tests/Feature/ReviewPack/Spec349ReviewPackResolutionGuidanceTest.php`.
- [x] T045 Run `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderResources/ProviderResourceBindingServiceTest.php tests/Feature/ProviderResources/ProviderResourceBindingAuthorizationTest.php`.
- [x] T046 Confirm the Spec 382 migration is limited to dropping `provider_resource_bindings.legacy_subject_key`; targeted database-backed tests run through Laravel migrations in the normal PostgreSQL-backed Sail test lane.
- [x] T047 Run `cd apps/platform && ./vendor/bin/sail bin pint --dirty --test --format agent`.
- [x] T048 Run `git diff --check`.
- [x] T049 Record `specs/382-baseline-matching-canonicalization/implementation-close-out.md` with Livewire v4 compliance, provider registration location, global search status, destructive/high-impact action status, asset strategy, tests run, and deployment impact.
## Dependencies
- Phase 1 must finish before implementation.
- Phases 2 and 3 should be written before or alongside Phases 4-8.
- Phase 4 must complete before active binding consumption can be trusted.
- Phase 5 and Phase 6 unblock Phase 7.
- Phase 7 unblocks Phase 8.
- Phase 9 validates the completed implementation.
## Parallel Opportunities
- T006-T010 can be drafted in parallel.
- T011-T017 can be drafted in parallel if each test file remains scoped.
- T022-T024 can be implemented in parallel with T027-T030 after Phase 4 is understood.
- T042-T045 can be run independently after implementation, but final close-out should use the complete targeted set.
## Explicit Non-Goals
- Do not add new persisted entities without updating spec and plan first. The only approved Spec 382 migration drops `provider_resource_bindings.legacy_subject_key`.
- Do not add or change Filament resources, pages, actions, Livewire components, Blade views, navigation, or assets.
- Do not add operator resolution UI.
- Do not change Evidence Snapshot readiness, Review Pack readiness, or customer-facing report semantics.
- Do not add historical payload mappers or OperationRun context readers.
- Do not create a generic provider workflow engine or broad multi-provider framework.