TenantAtlas/apps/platform/app/Support/Baselines/CompareSemantics/CompareSubjectOutcome.php
ahmido ea77c8c718 feat(baselines): implement baseline compare result semantics (#454)
Implemented deterministic Baseline Result Semantics (Spec 383), introducing CompareSubjectResult and CompareEvidenceResult. Replaced generic arrays with strict Data Transfer Objects for Baseline engine output.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #454
2026-06-16 20:20:27 +00:00

114 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Baselines\CompareSemantics;
use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;
/**
* @implements Arrayable<string, mixed>
*/
final readonly class CompareSubjectOutcome implements Arrayable, JsonSerializable
{
/**
* @param array<string, mixed> $subject
* @param array<string, mixed> $proof
*/
public function __construct(
public CompareResultReason $reason,
public CompareResultCategory $category,
public CompareResultActionability $actionability,
public CompareResultReadinessImpact $readinessImpact,
public CompareResultIdentityStatus $identityStatus,
public CompareResultComparisonStatus $comparisonStatus,
public CompareResultCoverageStatus $coverageStatus,
public CompareResultTrustLevel $trustLevel,
public array $subject = [],
public array $proof = [],
) {}
public function isBlocking(): bool
{
return in_array($this->readinessImpact, [
CompareResultReadinessImpact::CustomerBlocker,
CompareResultReadinessImpact::InternalBlocker,
], true);
}
public function toArray(): array
{
return [
'reason' => $this->reason->value,
'category' => $this->category->value,
'actionability' => $this->actionability->value,
'readiness_impact' => $this->readinessImpact->value,
'identity_status' => $this->identityStatus->value,
'comparison_status' => $this->comparisonStatus->value,
'coverage_status' => $this->coverageStatus->value,
'trust_level' => $this->trustLevel->value,
'subject' => $this->safeArray($this->subject),
'proof' => $this->safeArray($this->proof),
];
}
public function jsonSerialize(): array
{
return $this->toArray();
}
/**
* @param array<array-key, mixed> $value
* @return array<array-key, mixed>
*/
private function safeArray(array $value, bool $topLevel = true): array
{
$safe = [];
foreach ($value as $key => $item) {
if (! $this->isSafeArrayKey($key, $topLevel)) {
continue;
}
$safe[$key] = $this->safeValue($item);
}
return $safe;
}
private function safeValue(mixed $value): mixed
{
if (is_scalar($value) || $value === null) {
return $value;
}
if (is_array($value)) {
return $this->safeArray($value, false);
}
if ($value instanceof \Stringable) {
return (string) $value;
}
if (is_object($value)) {
return get_debug_type($value);
}
if (is_resource($value)) {
return 'resource:'.get_resource_type($value);
}
return get_debug_type($value);
}
private function isSafeArrayKey(string|int $key, bool $topLevel): bool
{
if (is_string($key)) {
return $key !== '';
}
return ! $topLevel;
}
}