resolve(spec415ResourceType('deviceAndAppManagementAssignmentFilter')); expect($decision->outcome)->toBe(CaptureOutcome::Captured) ->and($decision->contractKey)->toBe('assignmentFilter') ->and($decision->sourceEndpoint)->toBe('/deviceManagement/assignmentFilters') ->and($decision->sourceSchemaHash)->not->toBeNull(); }); it('blocks beta-backed resource types unless explicitly enabled', function (): void { $resolver = new CoverageSourceContractResolver(new GraphContractRegistry); $decision = $resolver->resolve(spec415ResourceType( canonicalType: 'roleScopeTag', sourceClass: SourceClass::GraphBetaExperimental, supportState: SupportState::Experimental, )); expect($decision->outcome)->toBe(CaptureOutcome::BlockedBeta) ->and($decision->reasonCode)->toBe('beta_capture_disabled'); }); it('blocks resource types without explicit graph contract mappings', function (): void { $resolver = new CoverageSourceContractResolver(new GraphContractRegistry); $decision = $resolver->resolve(spec415ResourceType('appProtectionPolicyAndroid')); expect($decision->outcome)->toBe(CaptureOutcome::BlockedMissingContract) ->and($decision->reasonCode)->toBe('missing_source_contract_mapping'); }); it('blocks unsupported and out-of-scope resource types', function (): void { $resolver = new CoverageSourceContractResolver(new GraphContractRegistry); $unsupported = $resolver->resolve(spec415ResourceType( canonicalType: 'unsupportedResource', supportState: SupportState::Unsupported, )); $outOfScope = $resolver->resolve(spec415ResourceType( canonicalType: 'outOfScopeResource', supportState: SupportState::OutOfScope, )); expect($unsupported->outcome)->toBe(CaptureOutcome::BlockedUnsupported) ->and($outOfScope->outcome)->toBe(CaptureOutcome::BlockedUnsupported); }); function spec415ResourceType( string $canonicalType, SourceClass $sourceClass = SourceClass::Tcm, SupportState $supportState = SupportState::Supported, ): TenantConfigurationResourceType { return new TenantConfigurationResourceType([ 'canonical_type' => $canonicalType, 'display_name' => $canonicalType, 'source_class' => $sourceClass->value, 'workload' => Workload::Intune->value, 'resource_class' => ResourceClass::Configuration->value, 'support_state' => $supportState->value, 'default_coverage_level' => CoverageLevel::ContentBacked->value, 'default_evidence_state' => EvidenceState::ContentBacked->value, 'default_identity_state' => IdentityState::Stable->value, 'default_claim_state' => ClaimState::ClaimAllowed->value, 'restore_tier' => RestoreTier::PreviewOnly->value, 'is_active' => true, ]); }