TenantAtlas/specs/203-baseline-compare-strategy/data-model.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

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_profiles
  • baseline_snapshots
  • baseline_snapshot_items
  • Canonical Baseline Scope V2 from Spec 202

These remain the reference truth that compare reads.

Tenant-owned operational truth

  • operation_runs for baseline_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 CompareStrategyCapability belongs to one CompareStrategyKey.
  • One CompareStrategySelection is produced for each compare start attempt.
  • One CompareOrchestrationContext contains exactly one supported CompareStrategySelection when a compare run is allowed to start.
  • One strategy processes many CompareSubjectIdentity values and emits many CompareSubjectResult values for one CompareOrchestrationContext.
  • One CompareSubjectResult may yield zero or one CompareFindingCandidate.
  • Existing finding and summary writers consume CompareSubjectResult and CompareFindingCandidate without needing to inspect strategy internals directly.

Validation Rules

Strategy selection

  1. Canonical scope must already be normalized to Baseline Scope V2.
  2. Exactly one active strategy family must support all included scope entries.
  3. Inactive or unsupported subject types fail selection before compare is enqueued.
  4. Mixed strategy families fail selection before compare is enqueued.
  5. No implicit fallback to intune_policy is allowed.

Compare-subject result contract

  1. Every processed subject must return one CompareSubjectResult.
  2. Every result must include identity, projection, availability, compare state, trust, evidence quality, and diagnostics.
  3. finding_candidate may be omitted only when the compare state does not warrant finding persistence.
  4. The platform must not need raw strategy-private fields to build summaries, findings, or run diagnostics.

Transition Rules

Compare start to strategy selection

  1. Receive canonical scope from the baseline profile plus any compare narrowing already allowed by the current workflow.
  2. Resolve the compatible strategy family from the registry.
  3. Reject unsupported or mixed scope before creating subject work.
  4. Persist the selected strategy family and compatibility diagnostics into existing compare run context only when a run is created.

Strategy selection to subject processing

  1. Build CompareOrchestrationContext from existing baseline, tenant, snapshot, and run truth.
  2. Hand domain-specific subject discovery and classification work to the selected strategy.
  3. Reuse generic current-state and hashing helpers where they remain strategy-neutral.

Subject results to existing run and finding truth

  1. Aggregate CompareSubjectResult values into existing compare summary counts and trust semantics.
  2. Write or update findings through the existing unified finding lifecycle using CompareFindingCandidate.
  3. Persist strategy diagnostics only as secondary run or evidence detail inside existing persistence shapes.
  4. Preserve existing run outcome ownership and current operator-visible compare semantics.