Automated PR for spec 427 Exchange Teams verified source contract enablement. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #494
86 lines
4.2 KiB
PHP
86 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\TenantConfigurationResourceType;
|
|
use App\Services\Graph\GraphContractRegistry;
|
|
use App\Services\TenantConfiguration\CoverageSourceContractDecision;
|
|
use App\Services\TenantConfiguration\CoverageSourceContractResolver;
|
|
use App\Services\TenantConfiguration\ResourceTypeRegistry;
|
|
use App\Support\TenantConfiguration\CaptureOutcome;
|
|
|
|
it('Spec427 maps the bounded source-contract state vocabulary without adding parallel truth', function (): void {
|
|
expect(CoverageSourceContractDecision::sourceContractStates())->toBe([
|
|
'contract_verified_pending_capture',
|
|
'contract_blocked_missing_source',
|
|
'contract_blocked_permission_unclear',
|
|
'contract_blocked_beta_only',
|
|
'contract_blocked_response_shape_unsafe',
|
|
'contract_blocked_repo_adapter_missing',
|
|
'contract_blocked_identity_unsafe',
|
|
'contract_blocked_redaction_unsafe',
|
|
]);
|
|
});
|
|
|
|
it('Spec427 resolves every target type to an exact non-capturable source-contract blocker', function (string $canonicalType): void {
|
|
$decision = (new CoverageSourceContractResolver(new GraphContractRegistry))
|
|
->resolve(spec427StateResourceType($canonicalType));
|
|
|
|
expect($decision->outcome)->toBe(CaptureOutcome::BlockedMissingContract)
|
|
->and($decision->reasonCode)->toBe(CoverageSourceContractDecision::CONTRACT_BLOCKED_REPO_ADAPTER_MISSING)
|
|
->and($decision->sourceContractState)->toBe(CoverageSourceContractDecision::CONTRACT_BLOCKED_REPO_ADAPTER_MISSING)
|
|
->and($decision->sourceMetadata['source_contract_state'])->toBe(CoverageSourceContractDecision::CONTRACT_BLOCKED_REPO_ADAPTER_MISSING)
|
|
->and($decision->sourceMetadata['capture_eligibility_state'])->toBe('blocked')
|
|
->and($decision->sourceMetadata['provider_adapter_state'])->toBe('missing')
|
|
->and($decision->capturable())->toBeFalse()
|
|
->and($decision->contractKey)->toBeNull()
|
|
->and($decision->sourceEndpoint)->toBeNull()
|
|
->and(config("graph_contracts.types.{$canonicalType}", []))->toBe([]);
|
|
})->with([
|
|
'transportRule',
|
|
'acceptedDomain',
|
|
'appPermissionPolicy',
|
|
'meetingPolicy',
|
|
]);
|
|
|
|
it('Spec427 keeps non-target missing-contract resource types on the existing generic blocker', function (): void {
|
|
$decision = (new CoverageSourceContractResolver(new GraphContractRegistry))
|
|
->resolve(spec427StateResourceType('dlpCompliancePolicy'));
|
|
|
|
expect($decision->outcome)->toBe(CaptureOutcome::BlockedMissingContract)
|
|
->and($decision->reasonCode)->toBe('missing_source_contract_mapping')
|
|
->and($decision->sourceContractState)->toBeNull()
|
|
->and($decision->sourceMetadata['reason_code'])->toBe('missing_source_contract_mapping');
|
|
});
|
|
|
|
it('Spec427 does not assign source-contract state to unsupported non-target resource types', function (): void {
|
|
$decision = (new CoverageSourceContractResolver(new GraphContractRegistry))
|
|
->resolve(spec427StateResourceType('application'));
|
|
|
|
expect($decision->outcome)->toBe(CaptureOutcome::BlockedUnsupported)
|
|
->and($decision->reasonCode)->toBe('resource_type_unsupported')
|
|
->and($decision->sourceContractState)->toBeNull()
|
|
->and($decision->sourceMetadata['reason_code'])->toBe('resource_type_unsupported')
|
|
->and($decision->sourceMetadata)->not->toHaveKey('source_contract_state');
|
|
});
|
|
|
|
it('Spec427 does not relabel already enabled non-target source contracts', function (): void {
|
|
$decision = (new CoverageSourceContractResolver(new GraphContractRegistry))
|
|
->resolve(spec427StateResourceType('conditionalAccessPolicy'));
|
|
|
|
expect($decision->outcome)->toBe(CaptureOutcome::Captured)
|
|
->and($decision->contractKey)->toBe('conditionalAccessPolicy')
|
|
->and($decision->sourceContractState)->toBeNull()
|
|
->and($decision->sourceMetadata)->not->toHaveKey('source_contract_state');
|
|
});
|
|
|
|
function spec427StateResourceType(string $canonicalType): TenantConfigurationResourceType
|
|
{
|
|
$definition = collect(ResourceTypeRegistry::defaultDefinitions())
|
|
->firstWhere('canonical_type', $canonicalType);
|
|
|
|
expect($definition)->not->toBeNull("Missing default resource type definition for {$canonicalType}.");
|
|
|
|
return new TenantConfigurationResourceType($definition);
|
|
}
|