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.
109 lines
3.5 KiB
PHP
109 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support\Baselines;
|
|
|
|
use App\Support\Resources\ResourceIdentity;
|
|
|
|
final class BaselineSubjectKey
|
|
{
|
|
public static function workspaceSafeSubjectExternalId(string $policyType, string $subjectKey): string
|
|
{
|
|
return hash('sha256', $policyType.'|'.$subjectKey);
|
|
}
|
|
|
|
public static function forProviderResourceIdentity(
|
|
string $subjectDomain,
|
|
SubjectClass|string $subjectClass,
|
|
string $subjectTypeKey,
|
|
ResourceIdentity $identity,
|
|
): ?string {
|
|
$domain = self::canonicalSegment($subjectDomain);
|
|
$class = self::canonicalSegment($subjectClass instanceof SubjectClass ? $subjectClass->value : $subjectClass);
|
|
$type = self::canonicalSegment($subjectTypeKey);
|
|
$provider = self::canonicalSegment($identity->providerKey);
|
|
$resourceType = self::canonicalSegment($identity->providerResourceType ?? 'none');
|
|
$stableIdentity = $identity->stableIdentityValue();
|
|
|
|
if ($domain === null || $class === null || $type === null || $provider === null || $resourceType === null || $stableIdentity === null) {
|
|
return null;
|
|
}
|
|
|
|
return implode(':', [
|
|
'provider-resource',
|
|
'v1',
|
|
$domain,
|
|
$class,
|
|
$type,
|
|
$provider,
|
|
$resourceType,
|
|
$identity->identityKind,
|
|
hash('sha256', $stableIdentity),
|
|
]);
|
|
}
|
|
|
|
public static function fromProviderResourceIdentity(
|
|
string $subjectDomain,
|
|
SubjectClass|string $subjectClass,
|
|
string $subjectTypeKey,
|
|
string $providerKey,
|
|
?string $providerResourceType,
|
|
string $stableIdentity,
|
|
string $identityKind = 'provider_resource',
|
|
): ?string {
|
|
return self::forProviderResourceIdentity(
|
|
$subjectDomain,
|
|
$subjectClass,
|
|
$subjectTypeKey,
|
|
new ResourceIdentity(
|
|
providerKey: $providerKey,
|
|
identityKind: $identityKind,
|
|
providerResourceType: $providerResourceType,
|
|
providerResourceId: $identityKind === 'provider_resource' ? $stableIdentity : null,
|
|
canonicalDiscriminator: $identityKind === 'provider_resource' ? null : $stableIdentity,
|
|
),
|
|
);
|
|
}
|
|
|
|
public static function isProviderResourceCanonicalKey(?string $subjectKey): bool
|
|
{
|
|
if (! is_string($subjectKey) || trim($subjectKey) === '') {
|
|
return false;
|
|
}
|
|
|
|
$parts = explode(':', trim($subjectKey));
|
|
|
|
if (count($parts) !== 9) {
|
|
return false;
|
|
}
|
|
|
|
[$prefix, $version, $domain, $class, $type, $provider, $resourceType, $identityKind, $hash] = $parts;
|
|
|
|
if ($prefix !== 'provider-resource' || $version !== 'v1') {
|
|
return false;
|
|
}
|
|
|
|
foreach ([$domain, $class, $type, $provider, $resourceType, $identityKind] as $segment) {
|
|
if (! is_string($segment) || ! preg_match('/^[a-z0-9._-]+$/', $segment)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return preg_match('/^[a-f0-9]{64}$/', $hash) === 1;
|
|
}
|
|
|
|
private static function canonicalSegment(?string $value): ?string
|
|
{
|
|
if (! is_string($value)) {
|
|
return null;
|
|
}
|
|
|
|
$normalized = trim(mb_strtolower($value));
|
|
$normalized = preg_replace('/[^a-z0-9._-]+/', '-', $normalized);
|
|
$normalized = is_string($normalized) ? trim($normalized, '-') : null;
|
|
|
|
return $normalized !== null && $normalized !== '' ? $normalized : null;
|
|
}
|
|
}
|