TenantAtlas/apps/platform/app/Services/TenantConfiguration/ClaimGuard.php
ahmido 8cbf1f7fe3 feat: implement canonical identity engine (#484)
Automated PR provided by Codex via Gitea API.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #484
2026-06-26 06:50:25 +00:00

111 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\TenantConfiguration;
use App\Support\TenantConfiguration\ClaimState;
use App\Support\TenantConfiguration\CoverageLevel;
use App\Support\TenantConfiguration\IdentityState;
use App\Support\TenantConfiguration\RestoreTier;
use App\Support\TenantConfiguration\SourceClass;
final class ClaimGuard
{
public function evaluate(
?string $scopeKey,
CoverageLevel|string $requestedLevel,
CoverageLevel|string $actualLevel,
bool $scopeComplete,
bool $customerFacing = false,
bool $customerClaimsAllowed = true,
bool $unscoped = false,
?int $percentage = null,
SourceClass|string|null $sourceClass = null,
RestoreTier|string|null $restoreTier = null,
IdentityState|string|null $identityState = null,
bool $restoreClaim = false,
bool $allowsBetaClaims = false,
bool $allowsCertifiedClaims = false,
bool $allowsDerivedIdentityClaims = false,
): ClaimState {
$requested = $this->coverageLevel($requestedLevel);
$actual = $this->coverageLevel($actualLevel);
$source = $this->sourceClass($sourceClass);
$restore = $this->restoreTier($restoreTier);
$identity = $this->identityState($identityState);
if (($scopeKey === null || $unscoped) && $percentage === 100) {
return ClaimState::ClaimBlocked;
}
if (in_array($identity, [
IdentityState::IdentityConflict,
IdentityState::MissingExternalId,
IdentityState::UnsupportedIdentity,
], true)) {
return ClaimState::ClaimBlocked;
}
if ($identity === IdentityState::Derived && ! $allowsDerivedIdentityClaims) {
return $customerFacing ? ClaimState::ClaimBlocked : ClaimState::ClaimLimited;
}
if ($source?->isBetaExperimental() === true) {
if (! $allowsBetaClaims) {
return ClaimState::ClaimBlocked;
}
if ($requested === CoverageLevel::Certified && ! $allowsCertifiedClaims) {
return ClaimState::ClaimBlocked;
}
}
if (($restoreClaim || $requested->meets(CoverageLevel::Restorable)) && $restore !== RestoreTier::Restorable) {
return ClaimState::ClaimBlocked;
}
if ($customerFacing && (! $scopeComplete || ! $customerClaimsAllowed)) {
return ClaimState::ClaimBlocked;
}
if ($scopeKey === null || ! $actual->meets($requested)) {
return ClaimState::ClaimLimited;
}
return ClaimState::ClaimAllowed;
}
private function coverageLevel(CoverageLevel|string $level): CoverageLevel
{
return $level instanceof CoverageLevel ? $level : CoverageLevel::from($level);
}
private function sourceClass(SourceClass|string|null $sourceClass): ?SourceClass
{
if ($sourceClass === null || $sourceClass instanceof SourceClass) {
return $sourceClass;
}
return SourceClass::from($sourceClass);
}
private function restoreTier(RestoreTier|string|null $restoreTier): ?RestoreTier
{
if ($restoreTier === null || $restoreTier instanceof RestoreTier) {
return $restoreTier;
}
return RestoreTier::from($restoreTier);
}
private function identityState(IdentityState|string|null $identityState): ?IdentityState
{
if ($identityState === null || $identityState instanceof IdentityState) {
return $identityState;
}
return IdentityState::from($identityState);
}
}