TenantAtlas/apps/platform/tests/Unit/Support/TenantConfiguration/Spec431ExchangePowerShellOperationRegistrationTest.php
ahmido 9374260ae1 feat: add Exchange PowerShell invocation gate (#498)
## Summary
- Adds the Spec 431 Exchange PowerShell invocation gate and operation registration slice.
- Introduces trusted provider operation start handling and read-only Exchange PowerShell runner abstractions.
- Updates provider capability/readiness evaluation and coverage for Exchange PowerShell invocation safety.

## Verification
- `cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Providers/ProviderCapabilityEvaluationTest.php tests/Feature/Providers/ProviderOperationCapabilityGateTest.php tests/Feature/TenantConfiguration/Spec431ExchangePowerShellInvocationGateTest.php tests/Unit/Providers/ProviderCapabilityRegistryTest.php tests/Unit/Providers/ProviderOperationStartGateTest.php tests/Unit/Support/TenantConfiguration/Spec430ExchangePowerShellCommandAllowlistTest.php tests/Unit/Support/TenantConfiguration/Spec431ExchangePowerShellOperationRegistrationTest.php tests/Unit/Verification/ManagedEnvironmentPermissionCapabilityMappingTest.php`
- Result: 80 passed, 685 assertions.

## Product Surface / Ops
- Rendered UI surface changed: N/A.
- Filament/Livewire surface changed: N/A.
- Deployment impact: config/runtime service changes only; no migrations, queues, or assets added.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #498
2026-07-07 15:23:29 +00:00

52 lines
2.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Services\Providers\ProviderOperationRegistry;
use App\Services\TenantConfiguration\ExchangePowerShellInvocationGate;
use App\Support\Auth\Capabilities;
use App\Support\OperationCatalog;
use App\Support\OperationRunType;
use App\Support\Operations\OperationRunCapabilityResolver;
use App\Support\Providers\Capabilities\ProviderCapabilityRegistry;
it('Spec431 registers one internal Exchange PowerShell invocation operation boundary', function (): void {
$providerOperations = app(ProviderOperationRegistry::class);
$providerCapabilities = app(ProviderCapabilityRegistry::class);
expect(OperationRunType::TenantConfigurationExchangePowerShellInvocation->value)
->toBe('tenant_configuration.exchange_powershell_invocation')
->and(OperationRunType::values())->toContain('tenant_configuration.exchange_powershell_invocation')
->and(OperationCatalog::canonicalCode('tenant_configuration.exchange_powershell_invocation'))
->toBe('tenant_configuration.exchange_powershell_invocation')
->and(OperationCatalog::label('tenant_configuration.exchange_powershell_invocation'))
->toBe('Exchange PowerShell invocation')
->and(app(OperationRunCapabilityResolver::class)->requiredExecutionCapabilityForType('tenant_configuration.exchange_powershell_invocation'))
->toBe(Capabilities::PROVIDER_RUN);
expect($providerOperations->get('tenant_configuration.exchange_powershell_invocation'))
->toMatchArray([
'operation_type' => 'tenant_configuration.exchange_powershell_invocation',
'module' => 'exchange_powershell',
'required_capability' => Capabilities::PROVIDER_RUN,
'provider_capability_keys' => ['exchange_powershell_invoke'],
])
->and($providerOperations->bindingFor('tenant_configuration.exchange_powershell_invocation', 'microsoft')['binding_status'])
->toBe(ProviderOperationRegistry::BINDING_ACTIVE)
->and($providerCapabilities->get('exchange_powershell_invoke')->operationTypes)
->toBe(['tenant_configuration.exchange_powershell_invocation'])
->and($providerCapabilities->get('exchange_powershell_invoke')->providerRequirementKeys)
->toBe(['provider.exchange_powershell_invocation', 'permissions.admin_consent']);
});
it('Spec431 defaults the invocation feature gate off', function (): void {
putenv('TENANTPILOT_EXCHANGE_POWERSHELL_INVOCATION_ENABLED');
unset($_ENV['TENANTPILOT_EXCHANGE_POWERSHELL_INVOCATION_ENABLED'], $_SERVER['TENANTPILOT_EXCHANGE_POWERSHELL_INVOCATION_ENABLED']);
$config = require config_path('tenantpilot.php');
expect($config['features']['exchange_powershell_invocation'])->toBeFalse()
->and(ExchangePowerShellInvocationGate::FEATURE_CONFIG_PATH)
->toBe('tenantpilot.features.exchange_powershell_invocation');
});