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; } }