TenantAtlas/apps/platform/app/Support/Providers/Capabilities/ProviderCapabilityRegistry.php
ahmido 1debe40ced feat: implement provider capability registry (#342)
## Summary
- implement the provider capability registry and derived capability evaluation flow
- update provider connections, onboarding, required-permissions diagnostics, and provider blocker translation to use capability-first summaries
- add bounded unit, feature, and browser test coverage plus the prepared Spec 283 artifacts

## Notes
- branch: `283-provider-capability-registry`
- commit: `74e75c3e`
- no additional validation commands were run in this git/PR flow step

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #342
2026-05-08 21:17:05 +00:00

115 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Providers\Capabilities;
use App\Support\Providers\ProviderReasonCodes;
use InvalidArgumentException;
final class ProviderCapabilityRegistry
{
/**
* @return array<string, ProviderCapabilityDefinition>
*/
public function definitions(): array
{
return [
'provider_connection_check' => new ProviderCapabilityDefinition(
key: 'provider_connection_check',
label: 'Provider connection check',
operationTypes: ['provider.connection.check'],
providerRequirementKeys: ['permissions.admin_consent'],
defaultReasonCode: ProviderReasonCodes::ProviderConsentMissing,
),
'inventory_read' => new ProviderCapabilityDefinition(
key: 'inventory_read',
label: 'Inventory read',
operationTypes: ['inventory.sync'],
providerRequirementKeys: ['permissions.intune_configuration', 'permissions.intune_apps'],
defaultReasonCode: ProviderReasonCodes::ProviderPermissionMissing,
),
'configuration_read' => new ProviderCapabilityDefinition(
key: 'configuration_read',
label: 'Configuration read',
operationTypes: ['compliance.snapshot'],
providerRequirementKeys: ['permissions.intune_configuration'],
defaultReasonCode: ProviderReasonCodes::ProviderPermissionMissing,
),
'restore_execute' => new ProviderCapabilityDefinition(
key: 'restore_execute',
label: 'Restore execute',
operationTypes: ['restore.execute'],
providerRequirementKeys: ['permissions.intune_configuration', 'permissions.intune_rbac_assignments'],
defaultReasonCode: ProviderReasonCodes::IntuneRbacPermissionMissing,
),
'directory_groups_read' => new ProviderCapabilityDefinition(
key: 'directory_groups_read',
label: 'Directory groups read',
operationTypes: ['directory.groups.sync'],
providerRequirementKeys: ['permissions.directory_groups'],
defaultReasonCode: ProviderReasonCodes::ProviderPermissionMissing,
),
'directory_role_definitions_read' => new ProviderCapabilityDefinition(
key: 'directory_role_definitions_read',
label: 'Directory role definitions read',
operationTypes: ['directory.role_definitions.sync'],
providerRequirementKeys: ['provider.directory_role_definitions', 'permissions.admin_consent'],
defaultReasonCode: ProviderReasonCodes::ProviderPermissionMissing,
),
];
}
/**
* @return array<string, ProviderCapabilityDefinition>
*/
public function all(): array
{
return $this->definitions();
}
/**
* @return array<int, string>
*/
public function keys(): array
{
return array_keys($this->definitions());
}
public function get(string $key): ProviderCapabilityDefinition
{
$key = trim($key);
$definition = $this->definitions()[$key] ?? null;
if (! $definition instanceof ProviderCapabilityDefinition) {
throw new InvalidArgumentException("Unknown provider capability key: {$key}");
}
return $definition;
}
/**
* @return array<int, ProviderCapabilityDefinition>
*/
public function forOperationType(string $operationType): array
{
$operationType = trim($operationType);
return array_values(array_filter(
$this->definitions(),
static fn (ProviderCapabilityDefinition $definition): bool => in_array($operationType, $definition->operationTypes, true),
));
}
/**
* @return array<int, string>
*/
public function keysForOperationType(string $operationType): array
{
return array_map(
static fn (ProviderCapabilityDefinition $definition): string => $definition->key,
$this->forOperationType($operationType),
);
}
}