*/ public function definitions(): array { return [ 'provider.connection.check' => [ 'operation_type' => 'provider.connection.check', 'module' => 'health_check', 'label' => 'Provider connection check', 'required_capability' => Capabilities::PROVIDER_RUN, ], 'inventory_sync' => [ 'operation_type' => 'inventory_sync', 'module' => 'inventory', 'label' => 'Inventory sync', 'required_capability' => Capabilities::PROVIDER_RUN, ], 'compliance.snapshot' => [ 'operation_type' => 'compliance.snapshot', 'module' => 'compliance', 'label' => 'Compliance snapshot', 'required_capability' => Capabilities::PROVIDER_RUN, ], 'restore.execute' => [ 'operation_type' => 'restore.execute', 'module' => 'restore', 'label' => 'Restore execution', 'required_capability' => Capabilities::TENANT_MANAGE, ], 'entra_group_sync' => [ 'operation_type' => 'entra_group_sync', 'module' => 'directory_groups', 'label' => 'Directory groups sync', 'required_capability' => Capabilities::TENANT_SYNC, ], 'directory_role_definitions.sync' => [ 'operation_type' => 'directory_role_definitions.sync', 'module' => 'directory_role_definitions', 'label' => 'Role definitions sync', 'required_capability' => Capabilities::TENANT_MANAGE, ], ]; } /** * @return array */ public function all(): array { return $this->definitions(); } /** * @return array> */ public function providerBindings(): array { return [ 'provider.connection.check' => [ 'microsoft' => $this->activeMicrosoftBinding( operationType: 'provider.connection.check', handlerNotes: 'Uses the current Microsoft Graph provider connection health-check workflow.', exceptionNotes: 'Current-release provider binding remains Microsoft-only until a real second provider case exists.', ), ], 'inventory_sync' => [ 'microsoft' => $this->activeMicrosoftBinding( operationType: 'inventory_sync', handlerNotes: 'Uses the current Microsoft Intune inventory sync workflow.', exceptionNotes: 'Inventory collection is currently Microsoft Intune-specific provider behavior.', ), ], 'compliance.snapshot' => [ 'microsoft' => $this->activeMicrosoftBinding( operationType: 'compliance.snapshot', handlerNotes: 'Uses the current Microsoft compliance snapshot workflow.', exceptionNotes: 'Compliance snapshot runtime remains bounded to the Microsoft provider.', ), ], 'restore.execute' => [ 'microsoft' => $this->activeMicrosoftBinding( operationType: 'restore.execute', handlerNotes: 'Uses the current Microsoft restore execution workflow.', exceptionNotes: 'Restore execution remains Microsoft-only and must preserve dry-run and audit safeguards.', ), ], 'entra_group_sync' => [ 'microsoft' => $this->activeMicrosoftBinding( operationType: 'entra_group_sync', handlerNotes: 'Uses the current Microsoft Entra group synchronization workflow.', exceptionNotes: 'The operation type keeps current Entra vocabulary until the identity-neutrality follow-up.', ), ], 'directory_role_definitions.sync' => [ 'microsoft' => $this->activeMicrosoftBinding( operationType: 'directory_role_definitions.sync', handlerNotes: 'Uses the current Microsoft directory role definition synchronization workflow.', exceptionNotes: 'Directory role definitions are Microsoft-owned provider semantics.', ), ], ]; } public function isAllowed(string $operationType): bool { return array_key_exists(trim($operationType), $this->definitions()); } /** * @return array{operation_type: string, module: string, label: string, required_capability: string} */ public function get(string $operationType): array { $operationType = trim($operationType); $definition = $this->definitions()[$operationType] ?? null; if (! is_array($definition)) { throw new InvalidArgumentException("Unknown provider operation type: {$operationType}"); } return $definition; } /** * @return array{operation_type: string, provider: string, binding_status: string, handler_notes: string, exception_notes: string}|null */ public function bindingFor(string $operationType, string $provider): ?array { $operationType = trim($operationType); $provider = trim($provider); if ($operationType === '' || $provider === '') { return null; } $bindings = $this->providerBindings()[$operationType] ?? []; return $bindings[$provider] ?? null; } /** * @return array{operation_type: string, provider: string, binding_status: string, handler_notes: string, exception_notes: string}|null */ public function activeBindingFor(string $operationType): ?array { $operationType = trim($operationType); $bindings = $this->providerBindings()[$operationType] ?? []; foreach ($bindings as $binding) { if (($binding['binding_status'] ?? null) === self::BINDING_ACTIVE) { return $binding; } } return null; } /** * @return array{ * definition: array{operation_type: string, module: string, label: string, required_capability: string}, * binding: array{operation_type: string, provider: string, binding_status: string, handler_notes: string, exception_notes: string} * } */ public function boundaryOperation(string $operationType, ?string $provider = null): array { $definition = $this->get($operationType); $binding = is_string($provider) && trim($provider) !== '' ? $this->bindingFor($operationType, $provider) : $this->activeBindingFor($operationType); return [ 'definition' => $definition, 'binding' => $binding ?? $this->unsupportedBinding($operationType, $provider ?? 'unknown'), ]; } /** * @return array{operation_type: string, provider: string, binding_status: string, handler_notes: string, exception_notes: string} */ public function unsupportedBinding(string $operationType, string $provider): array { return [ 'operation_type' => trim($operationType), 'provider' => trim($provider) !== '' ? trim($provider) : 'unknown', 'binding_status' => self::BINDING_UNSUPPORTED, 'handler_notes' => 'No explicit provider binding exists for this operation/provider combination.', 'exception_notes' => 'Unsupported combinations must block explicitly instead of inheriting Microsoft behavior.', ]; } /** * @return array{operation_type: string, provider: string, binding_status: string, handler_notes: string, exception_notes: string} */ private function activeMicrosoftBinding(string $operationType, string $handlerNotes, string $exceptionNotes): array { return [ 'operation_type' => $operationType, 'provider' => 'microsoft', 'binding_status' => self::BINDING_ACTIVE, 'handler_notes' => $handlerNotes, 'exception_notes' => $exceptionNotes, ]; } }