## 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
10 KiB
Data Model: Baseline Compare Engine Strategy Extraction
Overview
This feature introduces no new top-level persisted entity. It reuses the existing baseline compare start path, compare run persistence, finding lifecycle, and evidence storage, but inserts a new internal strategy boundary between platform compare orchestration and domain-specific compare logic.
Existing Persisted Truth Reused Without Change
Workspace-owned baseline truth
baseline_profilesbaseline_snapshotsbaseline_snapshot_items- Canonical Baseline Scope V2 from Spec 202
These remain the reference truth that compare reads.
Tenant-owned operational truth
operation_runsforbaseline_compare- existing drift findings and recurrence tracking
- existing evidence and compare diagnostics stored in current finding and run payloads
These remain the long-lived operator truth written by compare.
Existing subject and evidence inputs
- inventory-backed current state
- policy version and baseline snapshot evidence used by the current Intune path
- compare coverage and trust context already stored in the run and summary layers
This feature changes how domain logic is organized, not where those truths live.
New Internal Contracts
CompareStrategyKey
Type: string enum or equivalent value object
Purpose: identify one compare strategy family
| Value | Status | Notes |
|---|---|---|
intune_policy |
active | First explicit compare strategy family |
| future values | reserved | Additional families may be added later without changing the platform orchestration shape |
CompareStrategyCapability
Type: derived registry record
Purpose: declare which canonical scope families a strategy supports
| Field | Type | Notes |
|---|---|---|
strategy_key |
string | CompareStrategyKey value |
domain_keys |
array | Supported governance domains |
subject_classes |
array | Supported canonical subject classes |
subject_type_keys |
array or all |
Optional narrowing to known subject families |
compare_supported |
boolean | Whether compare may be started for the declared family |
active |
boolean | Whether the strategy is currently available |
StrategySelectionState
Type: internal enum
Purpose: capture compare preflight compatibility outcome
| Value | Meaning |
|---|---|
supported |
Exactly one compatible strategy family matches the requested scope |
unsupported |
No compatible strategy supports the requested scope |
mixed |
More than one strategy family would be required by the requested scope |
This is an orchestration contract, not a new top-level persisted domain status family.
CompareStrategySelection
Type: internal orchestration record
Purpose: represent preflight strategy resolution for a compare start
| Field | Type | Notes |
|---|---|---|
selection_state |
StrategySelectionState |
Required |
strategy_key |
string or null |
Present only when selection_state = supported |
matched_scope_entries |
array | Canonical scope entries accepted by the selected strategy |
rejected_scope_entries |
array | Scope entries rejected as unsupported or mixed |
operator_reason |
string | Short operator-safe explanation |
diagnostics |
array<string, mixed> | Secondary detail for logs and run detail |
CompareOrchestrationContext
Type: internal execution record
Purpose: represent the platform-owned inputs to one compare run
| Field | Type | Notes |
|---|---|---|
workspace_id |
integer | Required |
tenant_id |
integer | Required for tenant-owned compare runs |
baseline_profile_id |
integer | Required |
baseline_snapshot_id |
integer | Required reference snapshot |
operation_run_id |
integer | Required |
normalized_scope |
canonical scope document | Required |
strategy_selection |
CompareStrategySelection |
Required |
coverage_context |
array<string, mixed> | Existing compare coverage truth |
launch_context |
array<string, mixed> | Existing start-surface context such as tenant or matrix origin |
CompareSubjectIdentity
Type: internal value object
Purpose: represent one subject being compared without assuming policy-only semantics
| Field | Type | Notes |
|---|---|---|
domain_key |
string | Canonical governance domain |
subject_class |
string | Canonical subject class |
subject_type_key |
string | Domain-owned subject family discriminator |
external_subject_id |
string | Stable external identifier where available |
subject_key |
string | Stable compare key used for deduplication and finding identity |
CompareSubjectProjection
Type: internal value object
Purpose: provide the platform with operator-safe subject metadata for findings and summaries
| Field | Type | Notes |
|---|---|---|
platform_subject_class |
string | Canonical class for platform writers |
domain_key |
string | Canonical governance domain |
subject_type_key |
string | Strategy-owned subject family |
operator_label |
string | Operator-facing subject label |
summary_kind |
string or null |
Optional summary discriminator |
additional_labels |
array<string, string> | Optional secondary labels for diagnostics or detail surfaces |
CompareState
Type: internal enum
Purpose: represent per-subject compare outcome
| Value | Meaning |
|---|---|
no_drift |
Subject compared successfully and no drift was confirmed |
drift |
Subject compared successfully and drift was confirmed |
unsupported |
Subject or family is not supported by the selected strategy |
incomplete |
Evidence was insufficient to classify the subject fully |
ambiguous |
Identity or evidence ambiguity prevented a trustworthy compare decision |
failed |
Processing failed for this subject |
These values map to existing compare truth and do not imply a new top-level persisted run state family.
CompareSubjectResult
Type: internal orchestration contract
Purpose: one structured output row from a compare strategy back to platform orchestration
| Field | Type | Notes |
|---|---|---|
subject_identity |
CompareSubjectIdentity |
Required |
projection |
CompareSubjectProjection |
Required |
baseline_availability |
string | Required; e.g. available, missing, not_applicable |
current_state_availability |
string | Required; e.g. available, missing, unknown |
compare_state |
CompareState |
Required |
trust_level |
string | Required; maps to current trust semantics |
evidence_quality |
string | Required; maps to existing evidence completeness semantics |
severity_recommendation |
string or null |
Optional |
finding_candidate |
CompareFindingCandidate or null |
Present when a finding should be written or updated |
diagnostics |
array<string, mixed> | Secondary detail for run context and troubleshooting |
CompareFindingCandidate
Type: internal value object
Purpose: provide the unified finding writer with strategy-neutral mutation input
| Field | Type | Notes |
|---|---|---|
change_type |
string | Existing finding change type or equivalent classification |
severity |
string | Existing severity family |
fingerprint_basis |
array<string, mixed> | Stable values used by finding recurrence logic |
evidence_payload |
array<string, mixed> | Strategy-owned evidence detail |
auto_close_eligible |
boolean | Whether absence in the current run should close the finding |
Relationships
- One
CompareStrategyCapabilitybelongs to oneCompareStrategyKey. - One
CompareStrategySelectionis produced for each compare start attempt. - One
CompareOrchestrationContextcontains exactly one supportedCompareStrategySelectionwhen a compare run is allowed to start. - One strategy processes many
CompareSubjectIdentityvalues and emits manyCompareSubjectResultvalues for oneCompareOrchestrationContext. - One
CompareSubjectResultmay yield zero or oneCompareFindingCandidate. - Existing finding and summary writers consume
CompareSubjectResultandCompareFindingCandidatewithout needing to inspect strategy internals directly.
Validation Rules
Strategy selection
- Canonical scope must already be normalized to Baseline Scope V2.
- Exactly one active strategy family must support all included scope entries.
- Inactive or unsupported subject types fail selection before compare is enqueued.
- Mixed strategy families fail selection before compare is enqueued.
- No implicit fallback to
intune_policyis allowed.
Compare-subject result contract
- Every processed subject must return one
CompareSubjectResult. - Every result must include identity, projection, availability, compare state, trust, evidence quality, and diagnostics.
finding_candidatemay be omitted only when the compare state does not warrant finding persistence.- The platform must not need raw strategy-private fields to build summaries, findings, or run diagnostics.
Transition Rules
Compare start to strategy selection
- Receive canonical scope from the baseline profile plus any compare narrowing already allowed by the current workflow.
- Resolve the compatible strategy family from the registry.
- Reject unsupported or mixed scope before creating subject work.
- Persist the selected strategy family and compatibility diagnostics into existing compare run context only when a run is created.
Strategy selection to subject processing
- Build
CompareOrchestrationContextfrom existing baseline, tenant, snapshot, and run truth. - Hand domain-specific subject discovery and classification work to the selected strategy.
- Reuse generic current-state and hashing helpers where they remain strategy-neutral.
Subject results to existing run and finding truth
- Aggregate
CompareSubjectResultvalues into existing compare summary counts and trust semantics. - Write or update findings through the existing unified finding lifecycle using
CompareFindingCandidate. - Persist strategy diagnostics only as secondary run or evidence detail inside existing persistence shapes.
- Preserve existing run outcome ownership and current operator-visible compare semantics.