158 lines
5.0 KiB
PHP
158 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support\PortfolioTriage;
|
|
|
|
use App\Support\BackupHealth\TenantBackupHealthAssessment;
|
|
use App\Support\Tenants\TenantRecoveryTriagePresentation;
|
|
use JsonException;
|
|
|
|
final class TenantTriageReviewFingerprint
|
|
{
|
|
/**
|
|
* @param array<string, mixed>|null $recoveryEvidence
|
|
* @return array{
|
|
* concern_family: string,
|
|
* concern_state: string,
|
|
* fingerprint: string,
|
|
* snapshot: array{
|
|
* concernFamily: string,
|
|
* concernState: string,
|
|
* reasonCode: ?string,
|
|
* severityKey: ?string,
|
|
* supportingKey: ?string
|
|
* }
|
|
* }|null
|
|
*/
|
|
public function forConcernFamily(
|
|
string $concernFamily,
|
|
?TenantBackupHealthAssessment $backupHealth,
|
|
?array $recoveryEvidence,
|
|
): ?array {
|
|
return match ($concernFamily) {
|
|
PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH => $this->forBackupHealth($backupHealth),
|
|
PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE => $this->forRecoveryEvidence($recoveryEvidence),
|
|
default => null,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @return array{
|
|
* concern_family: string,
|
|
* concern_state: string,
|
|
* fingerprint: string,
|
|
* snapshot: array{
|
|
* concernFamily: string,
|
|
* concernState: string,
|
|
* reasonCode: ?string,
|
|
* severityKey: ?string,
|
|
* supportingKey: ?string
|
|
* }
|
|
* }|null
|
|
*/
|
|
public function forBackupHealth(?TenantBackupHealthAssessment $assessment): ?array
|
|
{
|
|
if (! $assessment instanceof TenantBackupHealthAssessment) {
|
|
return null;
|
|
}
|
|
|
|
if (! in_array($assessment->posture, [
|
|
TenantBackupHealthAssessment::POSTURE_ABSENT,
|
|
TenantBackupHealthAssessment::POSTURE_STALE,
|
|
TenantBackupHealthAssessment::POSTURE_DEGRADED,
|
|
], true)) {
|
|
return null;
|
|
}
|
|
|
|
$snapshot = [
|
|
'concernFamily' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
|
|
'concernState' => $assessment->posture,
|
|
'reasonCode' => $assessment->primaryReason,
|
|
'severityKey' => $assessment->primaryReason,
|
|
'supportingKey' => $assessment->primaryReason,
|
|
];
|
|
|
|
return [
|
|
'concern_family' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
|
|
'concern_state' => $assessment->posture,
|
|
'fingerprint' => $this->hash($snapshot),
|
|
'snapshot' => $snapshot,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed>|null $recoveryEvidence
|
|
* @return array{
|
|
* concern_family: string,
|
|
* concern_state: string,
|
|
* fingerprint: string,
|
|
* snapshot: array{
|
|
* concernFamily: string,
|
|
* concernState: string,
|
|
* reasonCode: ?string,
|
|
* severityKey: ?string,
|
|
* supportingKey: ?string
|
|
* }
|
|
* }|null
|
|
*/
|
|
public function forRecoveryEvidence(?array $recoveryEvidence): ?array
|
|
{
|
|
$state = is_array($recoveryEvidence)
|
|
? TenantRecoveryTriagePresentation::recoveryEvidenceState($recoveryEvidence)
|
|
: null;
|
|
|
|
if (! in_array($state, [
|
|
TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED,
|
|
TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_UNVALIDATED,
|
|
], true)) {
|
|
return null;
|
|
}
|
|
|
|
$reason = is_string($recoveryEvidence['reason'] ?? null)
|
|
? $recoveryEvidence['reason']
|
|
: null;
|
|
$supportingKey = is_string($recoveryEvidence['latest_relevant_attention_state'] ?? null)
|
|
? $recoveryEvidence['latest_relevant_attention_state']
|
|
: $reason;
|
|
|
|
$snapshot = [
|
|
'concernFamily' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
|
|
'concernState' => $state,
|
|
'reasonCode' => $reason,
|
|
'severityKey' => $reason,
|
|
'supportingKey' => $supportingKey,
|
|
];
|
|
|
|
return [
|
|
'concern_family' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
|
|
'concern_state' => $state,
|
|
'fingerprint' => $this->hash($snapshot),
|
|
'snapshot' => $snapshot,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param array{
|
|
* concernFamily: string,
|
|
* concernState: string,
|
|
* reasonCode: ?string,
|
|
* severityKey: ?string,
|
|
* supportingKey: ?string
|
|
* } $snapshot
|
|
*/
|
|
private function hash(array $snapshot): string
|
|
{
|
|
try {
|
|
return hash('sha256', json_encode($snapshot, JSON_THROW_ON_ERROR));
|
|
} catch (JsonException) {
|
|
return hash('sha256', implode(':', array_map(
|
|
static fn (mixed $value): string => is_scalar($value) || $value === null
|
|
? (string) $value
|
|
: '',
|
|
$snapshot,
|
|
)));
|
|
}
|
|
}
|
|
}
|