Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m12s
Replaced legacy tenant and environment bindings in the BaselineDriftEngine with the new ProviderResourceIdentity framework as defined in Spec 382.
222 lines
6.0 KiB
PHP
222 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support\Baselines\Matching;
|
|
|
|
use App\Support\Resources\ProviderResourceDescriptor;
|
|
use Illuminate\Contracts\Support\Arrayable;
|
|
use JsonSerializable;
|
|
|
|
/**
|
|
* @implements Arrayable<string, mixed>
|
|
*/
|
|
final readonly class MatchingOutcome implements Arrayable, JsonSerializable
|
|
{
|
|
public const string Resolved = 'resolved';
|
|
|
|
public const string Ambiguous = 'ambiguous';
|
|
|
|
public const string MissingProviderResource = 'missing_provider_resource';
|
|
|
|
public const string MissingLocalEvidence = 'missing_local_evidence';
|
|
|
|
public const string UnresolvedIdentity = 'unresolved_identity';
|
|
|
|
public const string Unsupported = 'unsupported';
|
|
|
|
public const string Limited = 'limited';
|
|
|
|
public const string Excluded = 'excluded';
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public function __construct(
|
|
public string $status,
|
|
public string $reasonCode,
|
|
public BaselineSubjectDescriptor $subject,
|
|
public ?ProviderResourceDescriptor $matchedDescriptor = null,
|
|
public ?string $matchedSubjectKey = null,
|
|
public string $trust = 'none',
|
|
public array $proof = [],
|
|
) {}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function resolved(
|
|
BaselineSubjectDescriptor $subject,
|
|
ProviderResourceDescriptor $matchedDescriptor,
|
|
string $matchedSubjectKey,
|
|
string $reasonCode,
|
|
string $trust,
|
|
array $proof = [],
|
|
): self {
|
|
return new self(
|
|
status: self::Resolved,
|
|
reasonCode: $reasonCode,
|
|
subject: $subject,
|
|
matchedDescriptor: $matchedDescriptor,
|
|
matchedSubjectKey: $matchedSubjectKey,
|
|
trust: $trust,
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function ambiguous(BaselineSubjectDescriptor $subject, array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::Ambiguous,
|
|
reasonCode: 'ambiguous_match',
|
|
subject: $subject,
|
|
trust: 'none',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function missingLocalEvidence(BaselineSubjectDescriptor $subject, array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::MissingLocalEvidence,
|
|
reasonCode: 'missing_local_evidence',
|
|
subject: $subject,
|
|
trust: 'none',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function missingProviderResource(BaselineSubjectDescriptor $subject, array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::MissingProviderResource,
|
|
reasonCode: 'missing_provider_resource',
|
|
subject: $subject,
|
|
trust: 'none',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function unresolvedIdentity(BaselineSubjectDescriptor $subject, array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::UnresolvedIdentity,
|
|
reasonCode: 'identity_required',
|
|
subject: $subject,
|
|
trust: 'none',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function unsupported(BaselineSubjectDescriptor $subject, array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::Unsupported,
|
|
reasonCode: 'unsupported_subject',
|
|
subject: $subject,
|
|
trust: 'none',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function limited(BaselineSubjectDescriptor $subject, string $reasonCode = 'accepted_limitation', array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::Limited,
|
|
reasonCode: $reasonCode,
|
|
subject: $subject,
|
|
trust: 'limited',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public static function excluded(BaselineSubjectDescriptor $subject, array $proof = []): self
|
|
{
|
|
return new self(
|
|
status: self::Excluded,
|
|
reasonCode: 'excluded_non_governed',
|
|
subject: $subject,
|
|
trust: 'none',
|
|
proof: $proof,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string|int|float|bool|null> $proof
|
|
*/
|
|
public function isComparable(): bool
|
|
{
|
|
return $this->status === self::Resolved;
|
|
}
|
|
|
|
public function isGap(): bool
|
|
{
|
|
return ! $this->isComparable();
|
|
}
|
|
|
|
public function requiresWarning(): bool
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'status' => $this->status,
|
|
'reason_code' => $this->reasonCode,
|
|
'subject' => $this->subject->toArray(),
|
|
'matched_descriptor' => $this->matchedDescriptor?->toArray(),
|
|
'matched_subject_key' => $this->matchedSubjectKey,
|
|
'trust' => $this->trust,
|
|
'proof' => $this->safeProof($this->proof),
|
|
];
|
|
}
|
|
|
|
public function jsonSerialize(): array
|
|
{
|
|
return $this->toArray();
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $proof
|
|
* @return array<string, string|int|float|bool|null>
|
|
*/
|
|
private function safeProof(array $proof): array
|
|
{
|
|
$safe = [];
|
|
|
|
foreach ($proof as $key => $value) {
|
|
if (! is_string($key) || trim($key) === '' || (! is_scalar($value) && $value !== null)) {
|
|
continue;
|
|
}
|
|
|
|
$safe[$key] = $value;
|
|
}
|
|
|
|
ksort($safe);
|
|
|
|
return $safe;
|
|
}
|
|
}
|