TenantAtlas/apps/platform/app/Support/Governance/Controls/CanonicalControlResolver.php
2026-04-24 14:15:50 +02:00

70 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Governance\Controls;
final readonly class CanonicalControlResolver
{
/**
* @var list<string>
*/
private const SUPPORTED_CONTEXTS = ['baseline', 'drift', 'finding', 'evidence', 'exception', 'review', 'report'];
public function __construct(
private CanonicalControlCatalog $catalog,
) {}
public function resolve(CanonicalControlResolutionRequest $request): CanonicalControlResolutionResult
{
if ($request->provider !== 'microsoft') {
return CanonicalControlResolutionResult::unresolved('unsupported_provider', $request);
}
if (! in_array($request->consumerContext, self::SUPPORTED_CONTEXTS, true)) {
return CanonicalControlResolutionResult::unresolved('unsupported_consumer_context', $request);
}
if (! $request->hasDiscriminator()) {
return CanonicalControlResolutionResult::unresolved('insufficient_context', $request);
}
$bindings = array_values(array_filter(
$this->catalog->microsoftBindings(),
static fn (MicrosoftSubjectBinding $binding): bool => $binding->matches($request),
));
if ($bindings === []) {
return CanonicalControlResolutionResult::unresolved('missing_binding', $request);
}
$primaryBindings = array_values(array_filter(
$bindings,
static fn (MicrosoftSubjectBinding $binding): bool => $binding->primary,
));
if ($primaryBindings !== []) {
$bindings = $primaryBindings;
}
$candidateControlKeys = array_values(array_unique(array_map(
static fn (MicrosoftSubjectBinding $binding): string => $binding->controlKey,
$bindings,
)));
sort($candidateControlKeys, SORT_STRING);
if (count($candidateControlKeys) !== 1) {
return CanonicalControlResolutionResult::ambiguous($candidateControlKeys, $request);
}
$definition = $this->catalog->find($candidateControlKeys[0]);
if (! $definition instanceof CanonicalControlDefinition) {
return CanonicalControlResolutionResult::unresolved('missing_binding', $request);
}
return CanonicalControlResolutionResult::resolved($definition);
}
}