## Summary - rebuild the public Tenantial homepage around an evidence-first Microsoft tenant governance narrative - replace the old hero visual with a new static dashboard preview and add dedicated Trust Bar and Feature Pillars sections - update the shared public shell, navigation, footer, dark design tokens, assets, and homepage content to match the new brand direction - align website smoke coverage and Spec 400 artifacts with the rebuilt homepage ## Testing - not run in this pass - updated website smoke specs under apps/website/tests/smoke ## Note - `website-dev` was pushed to `origin` so the requested PR base exists remotely - the remote `website-dev` branch is an ancestor of `origin/dev`, so this PR may also show upstream `dev` history relative to that base Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #387
89 lines
2.4 KiB
PHP
89 lines
2.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support\Governance\Controls;
|
|
|
|
final readonly class CanonicalControlResolutionResult
|
|
{
|
|
/**
|
|
* @param list<string> $candidateControlKeys
|
|
*/
|
|
private function __construct(
|
|
public string $status,
|
|
public ?CanonicalControlDefinition $control,
|
|
public ?string $reasonCode,
|
|
public array $bindingContext,
|
|
public array $candidateControlKeys = [],
|
|
) {}
|
|
|
|
public static function resolved(CanonicalControlDefinition $definition): self
|
|
{
|
|
return new self(
|
|
status: 'resolved',
|
|
control: $definition,
|
|
reasonCode: null,
|
|
bindingContext: [],
|
|
);
|
|
}
|
|
|
|
public static function unresolved(string $reasonCode, CanonicalControlResolutionRequest $request): self
|
|
{
|
|
return new self(
|
|
status: 'unresolved',
|
|
control: null,
|
|
reasonCode: $reasonCode,
|
|
bindingContext: $request->bindingContext(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param list<string> $candidateControlKeys
|
|
*/
|
|
public static function ambiguous(array $candidateControlKeys, CanonicalControlResolutionRequest $request): self
|
|
{
|
|
sort($candidateControlKeys, SORT_STRING);
|
|
|
|
return new self(
|
|
status: 'ambiguous',
|
|
control: null,
|
|
reasonCode: 'ambiguous_binding',
|
|
bindingContext: $request->bindingContext(),
|
|
candidateControlKeys: array_values(array_unique($candidateControlKeys)),
|
|
);
|
|
}
|
|
|
|
public function isResolved(): bool
|
|
{
|
|
return $this->status === 'resolved' && $this->control instanceof CanonicalControlDefinition;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
if ($this->isResolved()) {
|
|
return [
|
|
'status' => 'resolved',
|
|
'control' => $this->control?->toArray(),
|
|
];
|
|
}
|
|
|
|
if ($this->status === 'ambiguous') {
|
|
return [
|
|
'status' => 'ambiguous',
|
|
'reason_code' => $this->reasonCode,
|
|
'candidate_control_keys' => $this->candidateControlKeys,
|
|
'binding_context' => $this->bindingContext,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'status' => 'unresolved',
|
|
'reason_code' => $this->reasonCode,
|
|
'binding_context' => $this->bindingContext,
|
|
];
|
|
}
|
|
}
|