TenantAtlas/specs/382-baseline-matching-canonicalization/spec.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

37 KiB

Feature Specification: Spec 382 - Baseline Matching Pipeline and Canonicalization v1

Feature Branch: 382-baseline-matching-canonicalization Created: 2026-06-15 Status: Draft / Ready for implementation preparation review Input: User-provided draft candidate "Spec 382 - Baseline Matching Pipeline & Canonicalization v1" from /Users/ahmeddarrazi/.codex/attachments/a49d917f-b4a7-4fd7-9add-b5a242fb0afc/pasted-text.txt.

Repo-Truth Adjustment

The user supplied a complete numbered draft for Spec 382. Repo truth confirms that specs/381-provider-resource-identity-binding/ is implemented and closed out, and that Spec 381 explicitly lists Spec 382 as the follow-up that consumes resource identities, provider resource descriptors, canonical subject keys, and active provider resource bindings in baseline matching.

This prepared Spec 382 narrows the draft to the smallest implementation-ready runtime slice:

  • V1 consumes the Spec 381 identity and binding foundation inside baseline compare matching only.
  • V1 removes display-name and legacy subject-key matching completely. Display labels remain UI/descriptive metadata only.
  • V1 uses active scoped provider_resource_bindings before heuristics.
  • V1 introduces only the narrow matching/canonicalization abstractions needed to support current baseline compare behavior.
  • V1 does not add a resolution UI, customer-facing report rewrite, evidence/review readiness mapping, generic workflow engine, or historical payload support layer.
  • V1 does not add a new persisted entity. If implementation discovers new durable truth is required, the spec and plan must be updated before code changes continue.

Candidate Selection Gate

  • Selected candidate: Spec 382 - Baseline Matching Pipeline and Canonicalization v1.
  • Source: Direct user-provided candidate attachment, plus Spec 381 follow-up references in specs/381-provider-resource-identity-binding/spec.md and implementation-close-out.md.
  • Why selected: It is the next numbered manual candidate after completed Spec 381 and unlocks safer compare semantics before the proposed Specs 383-385 can be prepared or implemented.
  • Roadmap relationship: Supports provider-neutral baseline identity, governance truth, and anti-drift hardening by replacing mutable display-label identity with durable provider/resource identity before final result semantics and operator resolution surfaces are added.
  • Close alternatives deferred:
    • Spec 383 - Baseline Compare Result Semantics & Gap Classification v1: depends on matching outcomes produced by Spec 382.
    • Spec 384 - Baseline Subject Resolution UI & Operator Decisions v1: depends on matching outcomes and binding consumption from Spec 382.
    • Spec 385 - Evidence & Review Readiness Integration v1: depends on stable matching and result semantics.
    • Broader report, management PDF, or productization candidates are unrelated to the immediate baseline identity blocker.
  • Completed-spec guardrail result:
    • specs/381-provider-resource-identity-binding/ is completed and validated. It is dependency context only and must not be rewritten.
    • specs/163-baseline-subject-resolution/ has completed implementation history referenced by Spec 381. It is historical context only.
    • specs/380-management-report-pdf-staging-runtime-validation/ is completed validation context and is not modified.
    • No local or remote 382-* spec or branch collision was found before the create script ran.
  • Smallest viable implementation slice: Binding-aware baseline subject matching and canonicalization consumed by baseline compare before payload comparison, with identity-required gaps for subjects lacking provider-resource identity and follow-up result/UI/evidence work excluded.
  • Gate result: PASS. The candidate is user-provided, unspecced, not completed, directly follows completed Spec 381, and can be narrowed to a bounded runtime slice.

Spec Candidate Check (mandatory - SPEC-GATE-001)

  • Problem: Baseline compare can still treat mutable display labels or legacy policy_type + subject_key values as authoritative subject identity even after Spec 381 added provider resource identity and bindings.
  • Today's failure: Duplicate tenant-owned objects, copied/restored/test resources, provider built-ins, virtual assignment targets, and foundation objects can still collapse into ambiguous or false compare states when display names or legacy subject keys drive matching.
  • User-visible improvement: Operators receive fewer false blockers and fewer false green matches because compare resolves known subjects only by provider identity or active binding, preserves real ambiguity, and records identity-required gaps when durable identity is absent.
  • Smallest enterprise-capable version: Add a narrow matching pipeline for baseline compare, consume active provider resource bindings first, add provider-neutral descriptor/outcome objects, add a minimal provider-owned canonicalization seam with fake-provider proof, classify foundation coverage from existing metadata where possible, and integrate the pipeline before existing compare strategies.
  • Explicit non-goals: No resolution UI, no customer-facing report copy rewrite, no Evidence Snapshot readiness change, no Review Pack readiness change, no Spec 383 result taxonomy rewrite, no generic workflow engine, no new persistent table, no historical OperationRun payload reader, no old-payload mapper, and no broad Microsoft built-in catalog.
  • Permanent complexity imported: One matching pipeline service, one baseline-side descriptor, one matching outcome object, a small provider-owned canonicalization seam, a narrow foundation coverage resolver, tests for binding priority and provider neutrality, and updated compare tests. No new persistence is approved in this spec. A production canonicalizer registry/interface is not part of V1 unless implementation proves a current-release security, isolation, or correctness need that must be recorded in this spec/plan before continuing.
  • Why now: Spec 381 deliberately left bindings passive. Keeping them passive would leave the main baseline compare workflow exposed to the same display-name identity risk that Spec 381 was created to remove.
  • Why not local: A one-off compare patch would either preserve display-name identity or bury provider-specific matching inside compare strategy code. The current workflow needs one deterministic matching step before drift comparison so strategies compare the right subjects.
  • Approval class: Core Enterprise.
  • Red flags triggered: New resolver/pipeline, outcome object, foundation language, canonicalization seam, and a multi-spec sequence. Defense: the scope is runtime-only, has no new persistence or UI, reuses Spec 381 persistence, uses fake-provider proof without a production registry/interface, and leaves result semantics/UI/evidence readiness to explicit follow-ups.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | Gesamt: 11/12
  • Decision: approve as a narrowed Core Enterprise runtime slice.

Problem Statement

Baseline compare needs to answer "which current provider resource corresponds to this baseline subject?" before it answers "does the payload drift?" Today, compare can still encounter local/dev records that only carry display-name-derived subject keys or policy-centric identity assumptions. Those records are invalid for Spec 382 matching and must become identity-required gaps unless they contain ResourceIdentity or a valid provider-resource canonical subject key. Display labels are mutable and non-unique, and some governed subjects are provider built-ins, virtual assignment targets, inventory-only foundations, or accepted limitations rather than ordinary tenant-owned policies.

Spec 381 added durable identity primitives and managed-environment-scoped binding decisions. Spec 382 makes baseline compare consume that foundation so matching is stable, provider-neutral, and honest about unresolved ambiguity.

Business / Product Value

  • Reduces false compare blockers caused by expected provider defaults or virtual targets.
  • Reduces false green matches caused by duplicate names.
  • Makes active manual bindings operationally meaningful instead of passive records.
  • Keeps identity resolution separate from drift/no-drift judgment.
  • Creates clean input for later result semantics, resolution UI, and evidence/review readiness specs.

Primary Users / Operators

  • MSP or tenant operator reviewing baseline compare outcomes.
  • Workspace manager responsible for baseline governance accuracy across managed environments.
  • Support/platform operator diagnosing why a baseline subject matched, failed to match, or remained ambiguous.
  • Release reviewer validating that compare matching remains provider-neutral and tenant-safe.

Spec Scope Fields (mandatory)

  • Scope: tenant-owned baseline compare runtime within established workspace and managed-environment boundaries.
  • Primary Routes: No new route, page, or navigation entry. Existing baseline compare start/detail/operation surfaces are regression surfaces only.
  • Data Ownership: Existing provider_resource_bindings rows remain tenant-owned operational truth. Existing baseline snapshots, baseline snapshot items, inventory items, policy versions, findings, evidence snapshots, review packs, and operation runs keep their current ownership. No new persisted entity is approved.
  • RBAC: Baseline compare continues to require established workspace and managed-environment entitlement. Non-members are denied as not found. Entitled users missing compare capability receive forbidden. Binding-aware reads must not reveal bindings or candidate resources outside the current workspace/environment.

For canonical-view specs:

  • Default filter behavior when tenant-context is active: Not applicable. Spec 382 adds no canonical-view route.
  • Explicit entitlement checks preventing cross-tenant leakage: Matching queries must scope binding and candidate descriptor reads by workspace and managed environment before returning outcomes.

UI Surface Impact (mandatory - UI-COV-001)

Does this spec add, remove, rename, or materially change any reachable UI surface?

  • No UI surface impact
  • Existing page changed
  • New page/route added
  • Navigation changed
  • Filament panel/provider surface changed
  • New modal/drawer/wizard/action added
  • New table/form/state added
  • Customer-facing surface changed
  • Dangerous action changed
  • Status/evidence/review presentation changed
  • Workspace/environment context presentation changed

UI/Productization Coverage

N/A - no reachable UI surface impact. Spec 382 changes backend matching behavior consumed by an existing baseline compare operation. It does not add or materially refactor pages, routes, navigation, actions, modals, tables, forms, customer-facing output, status presentation, Evidence Snapshot readiness, Review Pack readiness, or operator resolution UI. Follow-up Specs 383-385 own result semantics, UI decisions, and customer-facing readiness.

Cross-Cutting / Shared Pattern Reuse

  • Cross-cutting feature?: yes.
  • Interaction class(es): no UI interaction class. Backend shared families include baseline subject identity, provider resource identity, compare strategy input, binding decisions, OperationRun proof context, and provider boundary vocabulary.
  • Systems touched: BaselineSubjectKey, ResourceIdentity, ProviderResourceDescriptor, ProviderResourceBinding, ProviderResourceBindingService, SubjectResolver, CompareBaselineToTenantJob item loading/keying, CompareStrategyRegistry, InventoryPolicyTypeMeta, and baseline compare tests.
  • Existing pattern(s) to extend: Spec 381 identity and binding foundation, existing compare strategy registry, existing subject/resolution support, existing OperationRun compare job, existing capability and audit semantics.
  • Shared contract / presenter / builder / renderer to reuse: no UI renderer. Reuse existing compare strategy output and OperationRun lifecycle paths; do not create a local operation UX contract.
  • Why the existing shared path is sufficient or insufficient: Existing compare strategies are sufficient for payload drift comparison after identity has been resolved. They are insufficient as the primary identity resolver because they still operate too close to policy type/display-label assumptions.
  • Allowed deviation and why: one new matching pipeline is allowed because it replaces scattered legacy identity decisions and makes active bindings consumeable before compare strategies run.
  • Consistency impact: Matching outcome truth must not become a second result taxonomy. Spec 383 owns final compare result semantics if more operator-facing distinctions are needed.
  • Review focus: binding-first priority, no Microsoft label hardcoding in core, no display-name authoritative path, no cross-environment binding leakage, and no evidence/review behavior change.

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: no.
  • Shared OperationRun UX contract/layer reused: Existing baseline compare start/completion behavior remains unchanged.
  • Delegated start/completion UX behaviors: N/A - no queued toast/link/event/notification semantics are added or changed.
  • Local surface-owned behavior that remains: N/A.
  • Queued DB-notification policy: N/A - no new queued DB notifications.
  • Terminal notification path: Existing baseline compare operation lifecycle only.
  • Exception required?: none.

Spec 382 may add sanitized matching proof metadata to existing compare operation context or compare result payloads. It must not transition OperationRun.status or OperationRun.outcome outside the existing service-owned lifecycle.

Provider Boundary / Platform Core Check

  • Shared provider/platform boundary touched?: yes.
  • Boundary classification: mixed. Matching priority, canonical subject keys, descriptors, bindings, and outcomes are platform-core. Provider-specific built-in/default/virtual detection stays provider-owned behind a canonicalizer seam.
  • Seams affected: baseline subject identity, provider resource descriptors, binding lookup, compare strategy input, foundation coverage classification, outcome proof metadata.
  • Neutral platform terms preserved or introduced: provider, managed environment, governed subject, baseline subject descriptor, provider resource descriptor, canonical subject key, binding, matching outcome, foundation coverage.
  • Provider-specific semantics retained and why: provider key, provider resource type, provider resource ID, and canonical discriminator remain necessary provider-owned identity fields. Microsoft/Intune labels and Graph endpoint assumptions must not enter platform-core matching logic.
  • Why this does not deepen provider coupling accidentally: A fake-provider seam test is required. Core matching must accept provider descriptors and canonicalization results without branching on Microsoft display labels such as All users, All devices, or Default, and without adding a production provider registry only for test proof.
  • Follow-up path: Spec 383 may refine result/gap semantics. Spec 384 may add operator resolution UI. Spec 385 may map outcomes into evidence/review readiness.

UI / Surface Guardrail Impact

Surface / Change Operator-facing surface change? Native vs Custom Shared-Family Relevance State Layers Touched Exception Needed? Low-Impact / N/A Note
Baseline matching pipeline consumed by compare job no N/A baseline identity, provider boundary, compare runtime backend runtime truth only no Existing UI surfaces render existing compare/operation channels; no page, action, navigation, or presentation contract changes in v1

Decision-First Surface Role

N/A - no operator-facing surface change.

Audience-Aware Disclosure

N/A - no customer/operator-facing detail or status surface change. Later disclosure of matching detail belongs to Spec 383/384/385.

UI/UX Surface Classification

N/A - no operator-facing list, detail, queue, audit, config, report, or workflow surface is added or materially changed.

Operator Surface Contract

N/A - no new operator-facing page or material page refactor.

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: no new persisted truth. Matching outcomes are derived runtime/result truth from existing baseline snapshots, inventory/current provider descriptors, and active provider_resource_bindings.
  • New persisted entity/table/artifact?: no.
  • New abstraction?: yes. SubjectMatchingPipeline, baseline subject descriptor, matching outcome, provider-owned canonicalization seam, and foundation coverage resolver are introduced narrowly for baseline compare matching.
  • New enum/state/reason family?: possibly a small matching outcome/reason family. Each value must change matching behavior, result proof, or follow-up operator action; presentation-only labels are forbidden.
  • New cross-domain UI framework/taxonomy?: no.
  • Current operator problem: Operators need baseline compare to stop treating names as identity while still preserving real ambiguity and limitations.
  • Existing structure is insufficient because: SubjectResolver and compare strategies classify existing compare states, but they do not consume active provider resource bindings first or isolate provider-specific canonicalization away from platform-core compare logic.
  • Narrowest correct implementation: A deterministic pre-compare matching layer that reuses Spec 381 persistence, feeds existing compare strategies, and avoids UI/evidence/report scope.
  • Ownership cost: A focused service/object family and tests must be maintained alongside compare strategy tests. Reviewers must prevent it from growing into a generic provider workflow framework.
  • Alternative intentionally rejected: Patch display-name matching inside each compare strategy. That would duplicate priority rules, keep provider-specific logic scattered, and make active bindings inconsistently consumed.
  • Release truth: Current-release runtime truth. Spec 381 is already implemented; this spec activates that foundation for the existing baseline compare workflow.

Compatibility posture

TenantPilot is pre-production. V1 must not add legacy identity aliases, dual old/new identity readers, historical OperationRun context readers, old compare payload mappers, legacy subject-key matching, display-name matching, or display-name-derived canonical keys. Existing local/dev compare data may be invalidated or reset during implementation. legacy_subject_key is removed from active code paths and dropped from provider_resource_bindings by a Spec 382 migration because Spec 381 already introduced the column.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Unit for descriptor/outcome/pipeline/canonicalizer behavior; Feature for compare integration, binding consumption, workspace/environment isolation, and rejected canonical override behavior.
  • Validation lane(s): fast-feedback and confidence. PostgreSQL lane only if implementation changes migrations, indexes, constraints, or PostgreSQL-specific query behavior.
  • Why this classification and these lanes are sufficient: The feature changes deterministic runtime matching and existing DB-backed compare behavior, not UI, browser behavior, or new persistence.
  • New or expanded test families: focused tests/Unit/Support/Baselines/Matching and tests/Feature/Baselines coverage. No browser or heavy-governance family.
  • Fixture / helper cost impact: fake-provider descriptors/canonicalizers must stay local to matching tests or explicit fixtures. No global default provider/workspace setup may be widened.
  • Heavy-family visibility / justification: none.
  • Special surface test profile: N/A - no Filament or operator surface.
  • Standard-native relief or required special coverage: no UI coverage required.
  • Reviewer handoff: verify binding-first order before existing compare item keying can discard candidates, identity-required gaps for display-only/old subject-key data, duplicate provider-identity ambiguity, provider-neutral fake-provider proof without a production registry/interface, no Microsoft literals in core, no Graph/provider runtime calls, no new persisted entity, and no evidence/review/customer output changes.
  • Budget / baseline / trend impact: expected small increase in unit/feature runtime only. Escalate as follow-up-spec if implementation requires broad compare suite restructuring.
  • Escalation needed: document-in-feature for contained provider-boundary exceptions; follow-up-spec for result semantics, resolution UI, evidence/review readiness, or new persistence.
  • Active feature PR close-out entry: Baseline Matching Pipeline / Provider Identity Consumption.
  • Planned validation commands:
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/Baselines/Matching
    • 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
    • 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
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderResources/ProviderResourceBindingServiceTest.php tests/Feature/ProviderResources/ProviderResourceBindingAuthorizationTest.php
    • cd apps/platform && ./vendor/bin/sail bin pint --dirty --test --format agent
    • git diff --check

User Scenarios & Testing (mandatory)

User Story 1 - Resolve known subjects by provider identity or binding (Priority: P1)

As a baseline governance operator, I need compare to match a baseline subject to the right current provider resource using stable provider identity or an active binding before names are considered, so duplicate names and renamed objects do not create false results.

Why this priority: This is the core trust gap and the reason Spec 381 must be consumed.

Independent Test: A feature test creates duplicate display labels, one active binding, and current descriptors. Compare resolves the bound subject first and leaves the unbound duplicate ambiguous.

Acceptance Scenarios:

  1. Given an active binding for a baseline subject canonical key, When baseline compare evaluates candidates, Then the binding is consumed before provider identity/canonical identity matching.
  2. Given two tenant-owned candidates with the same display label but different provider resource IDs, When compare runs, Then they are treated as different resources and no name match is selected.
  3. Given a resource with a stable provider resource ID, When the display label changes, Then compare still resolves by provider identity.

User Story 2 - Canonicalize provider built-ins and virtual targets without hardcoding core labels (Priority: P1)

As a release reviewer, I need built-ins, defaults, and virtual targets to resolve through provider-specific canonicalization behind a provider-neutral seam, so platform-core matching does not become Microsoft-label-specific.

Why this priority: Built-ins and virtual targets are common false blockers and provider coupling hotspots.

Independent Test: A fake-provider canonicalization test double resolves a built-in and a virtual target without Microsoft labels, while core matching remains provider-neutral.

Acceptance Scenarios:

  1. Given a provider built-in represented by stable provider metadata, When matching runs, Then it can resolve through canonicalization without display-name matching.
  2. Given a virtual assignment target, When matching runs, Then it resolves as a canonical virtual resource without requiring a directory group record.
  3. Given unsupported provider labels only, When core matching runs, Then it does not branch on Microsoft display strings.

User Story 3 - Classify foundations and missing evidence honestly (Priority: P2)

As an operator reviewing compare health, I need inventory-only, identity-only, unsupported, and missing-local-evidence subjects to avoid false policy-missing blockers, so I can distinguish real drift from coverage limitations.

Why this priority: It prevents false red output without pretending that limited evidence is healthy.

Independent Test: Foundation coverage cases produce limitation or unsupported outcomes without entering policy-backed payload comparison.

Acceptance Scenarios:

  1. Given an inventory-only foundation resource, When matching evaluates it, Then it returns a limitation outcome rather than a missing policy result. Existing internal reason codes such as foundation_not_policy_backed may remain only if they continue to mean inventory-only limitation.
  2. Given missing local evidence without proven provider absence, When matching cannot find a current descriptor, Then it records missing local evidence rather than missing provider resource.
  3. Given an unsupported resource class, When matching evaluates it, Then it records unsupported coverage and does not attempt payload comparison.

User Story 4 - Preserve existing compare strategy behavior after matching (Priority: P2)

As a release owner, I need existing compare strategies to keep producing drift/no-drift results after subject matching succeeds, so identity matching does not become a false "healthy" signal.

Why this priority: Matching proves the compared subject, not the payload outcome.

Independent Test: Existing drift and no-drift compare tests pass after a successful matching outcome, and Spec 381 no-op tests are inverted so binding consumption is expected.

Acceptance Scenarios:

  1. Given a successfully matched comparable subject with payload drift, When compare strategy runs, Then drift is still detected.
  2. Given a successfully matched comparable subject without payload drift, When compare strategy runs, Then no drift is still reported through existing result semantics.
  3. Given an active provider resource binding, When the old no-op regression is run, Then the expected behavior is binding consumption, not ignoring the binding.

Edge Cases

  • Active binding exists but the referenced current provider descriptor is absent.
  • Binding exists for the same canonical subject key in another managed environment.
  • Candidate descriptors have identical display labels but different provider resource IDs.
  • Provider canonicalizer returns no result for a supported provider.
  • Fingerprints collide or produce multiple candidates; matching must not select a fingerprint winner because fingerprints are not an active matching source.
  • Display labels match exactly but provider identity is missing or different.
  • Legacy subject_key values are present in older local/dev records and must become identity_required gaps when no ResourceIdentity or valid provider-resource canonical subject key exists.
  • Existing compare strategy expects policy-shaped input for a foundation resource.

Requirements (mandatory)

Functional Requirements

  • FR-382-001: TenantPilot MUST run a baseline subject matching pipeline before payload comparison for baseline compare.
  • FR-382-002: The pipeline MUST consume active scoped provider_resource_bindings before heuristic matching.
  • FR-382-003: Binding lookup MUST respect workspace, managed environment, provider key, canonical subject key, active binding status, and provider connection where applicable.
  • FR-382-004: ResourceIdentity and provider-resource canonical subject keys MUST be primary matching primitives.
  • FR-382-005: Arbitrary canonical_subject_key override strings MUST be rejected unless they are generated or validated as provider-resource canonical keys.
  • FR-382-006: legacy_subject_key MUST be removed from service inputs, DTOs, factories, tests, and active matching. If a committed prior migration created the column, Spec 382 MUST add a migration that drops it.
  • FR-382-007: BaselineSubjectKey::fromDisplayName() and related display-name-derived canonical key generation MUST be removed from baseline matching/canonical key generation. Display labels may only be stored or rendered as UI/descriptive labels.
  • FR-382-008: A baseline subject without ResourceIdentity or a valid provider-resource canonical subject key MUST produce an explicit non-comparable identity_required/unresolved_identity gap. Display-name-only or old subject-key-only data MUST NOT resolve successfully.
  • FR-382-009: Tenant-owned duplicate candidates without active binding MUST remain unresolved ambiguity.
  • FR-382-010: Provider built-ins/defaults/virtual targets MUST resolve only through provider-specific canonicalization behind a provider-neutral seam. V1 MUST NOT introduce a production canonicalizer registry/interface solely for fake-provider tests.
  • FR-382-011: Core matching logic MUST NOT hardcode Microsoft/Intune display names, Graph endpoint strings, or Intune-only policy type assumptions.
  • FR-382-012: Virtual targets MUST be representable as canonical virtual resources and must not require normal directory group identity.
  • FR-382-013: Foundation resource classes MUST be classified by coverage capability rather than forced into policy-backed comparison.
  • FR-382-014: Matching MUST distinguish missing provider resource from missing local evidence when the available proof supports that distinction.
  • FR-382-015: Existing compare strategies MUST continue to own payload drift/no-drift decisions after successful matching.
  • FR-382-016: Spec 381 tests that assert provider resource bindings are not consumed MUST be deleted or inverted so consumption is expected.
  • FR-382-017: No operator resolution UI, customer-facing report rewrite, evidence readiness change, review readiness change, or historical payload mapper may be introduced by this spec.
  • FR-382-018: A fake-provider seam test MUST prove the matching and canonicalization seam works without Microsoft-specific logic.

Non-Functional Requirements

  • NFR-382-001: Matching MUST be deterministic for the same baseline, descriptor, binding, and coverage inputs.
  • NFR-382-002: Matching outcomes MUST be tenant-safe and workspace-safe; no cross-environment binding or candidate may influence another environment.
  • NFR-382-003: Matching proof metadata MUST be sanitized and must not include secrets, credential payloads, raw sensitive provider payloads, or raw Graph error bodies.
  • NFR-382-004: No Graph call may happen during UI rendering or matching. Canonicalization and matching MUST NOT call GraphClientInterface, provider gateways, or provider runtime clients; any provider data consumed by matching must come from existing persisted inventory, snapshots, policy versions, bindings, or provider descriptors.
  • NFR-382-005: Matching identity resolution MUST NOT be treated as no drift.
  • NFR-382-006: The implementation MUST avoid broad provider frameworks until real provider variance proves the need beyond the fake-provider seam test and the current Microsoft provider.
  • NFR-382-007: Test fixtures must keep provider/workspace/member setup opt-in and must not widen global defaults.

UI Action Matrix (mandatory when Filament is changed)

N/A - no Filament Resource, RelationManager, Page, action, table, form, modal, navigation, or panel provider is changed by this spec.

Key Entities (include if feature involves data)

  • Baseline subject descriptor: Derived runtime representation of a baseline-side governed subject, including stable identity where available, canonical subject key, subject class/type, provider key, display label as metadata, and source references.
  • Provider resource descriptor: Existing Spec 381 descriptor for current provider/inventory-side resources used as candidate matches.
  • Matching outcome: Derived runtime/result object indicating resolved, ambiguous, missing, unsupported, excluded, limited, or unresolved-identity outcome plus source proof.
  • Canonicalization result: Derived provider-owned result that maps built-ins/defaults/virtual targets to provider-resource canonical identity. In V1 this is a direct seam/result shape, not a required production registry.
  • Foundation coverage classification: Derived support level for resource classes such as fully comparable, identity-only, inventory-only, canonical-only, unsupported, requires manual binding, or excluded by profile.

No new persisted entity is approved.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-382-001: In automated tests, active scoped provider resource bindings resolve before canonical/provider identity matching in 100% of covered binding-first cases.
  • SC-382-002: In automated tests, duplicate tenant-owned provider-resource identity candidates without active binding remain unresolved ambiguity in 100% of covered duplicate-identity cases, while same-label resources with different provider IDs remain distinct.
  • SC-382-003: In automated tests, built-in and virtual fake-provider subjects resolve without Microsoft display-label literals in core matching.
  • SC-382-004: Existing drift and no-drift compare tests still pass after matching integration.
  • SC-382-005: Targeted static or unit assertions show no core matching branch depends on literal Microsoft display labels such as All users, All devices, or Default.
  • SC-382-006: No new route, navigation entry, Filament resource/page/action, Livewire component, Blade view, migration, or customer-facing report surface is introduced.

Acceptance Criteria

  • AC-382-001: Baseline compare calls the matching pipeline before compare strategy payload comparison and before legacy policy_type|subject_key keyed maps can collapse or discard duplicate candidates.
  • AC-382-002: Active scoped bindings are first-class matching input.
  • AC-382-003: Legacy/display-name subject keys are not matching inputs and produce identity-required gaps when no provider-resource identity exists.
  • AC-382-004: Built-ins/defaults/virtual targets are canonicalized behind provider-owned seams.
  • AC-382-005: Foundation resources return honest limitation/unsupported outcomes instead of false policy-missing blockers.
  • AC-382-006: Existing compare strategies still own drift/no-drift.
  • AC-382-007: Fake-provider tests pass and prove provider neutrality.
  • AC-382-008: No application UI implementation is included.

Assumptions

  • Spec 381 remains the source of truth for provider resource binding persistence.
  • BaselineSubjectKey remains the canonical-key helper unless implementation proves a value object is required; adding such a value object requires updating this spec/plan first.
  • Foundation coverage v1 should reuse InventoryPolicyTypeMeta, BaselineSupportCapabilityGuard, or existing capability metadata before adding new classification sources.
  • Canonicalization v1 should use a direct provider-owned seam/service or existing dependency-injection pattern. A production registry/interface must not be added solely to support fake-provider tests.
  • Microsoft-specific canonicalization in v1 is limited to stable existing metadata if available. A broad Microsoft built-in catalog is out of scope.
  • Existing local/dev compare payloads do not require old-payload readers.

Risks

  • Silent false resolution: Mitigated by binding-first priority, provider-resource identity only, identity-required gaps, and unresolved duplicate ambiguity.
  • Provider coupling: Mitigated by fake-provider tests and a ban on Microsoft label hardcoding in core.
  • Layer growth: Mitigated by no new persistence, narrow runtime scope, and explicit follow-up boundaries.
  • Broken compare strategies: Mitigated by integrating matching before strategies and preserving strategy-owned drift/no-drift behavior.
  • False green output: Mitigated by treating identity resolution separately from drift/no-drift.

Open Questions

None blocking. Implementation must stop and update this spec if it needs new persistence, new UI surfaces, broad result taxonomy changes, or evidence/review readiness behavior.

Follow-up Spec Candidates

  • Spec 383 - Baseline Compare Result Semantics & Gap Classification v1.
  • Spec 384 - Baseline Subject Resolution UI & Operator Decisions v1.
  • Spec 385 - Evidence & Review Readiness Integration v1.