> */ public array $calls = []; /** * @param list>|null $items */ public function __construct( private readonly string $scenario = self::SCENARIO_SUCCESS, private readonly ?array $items = null, ) {} public function run( ExchangePowerShellCommandContract $commandContract, ExchangePowerShellInvocationContext $context, ): ExchangePowerShellInvocationResult { $this->calls[] = [ 'operation_run_id' => $context->operationRunId, 'canonical_type' => $context->canonicalType, 'command_name' => $context->commandName, 'runner_mode' => $context->runnerMode, 'parameter_names' => $commandContract->parameterNames(), 'context' => $context->toArray(), ]; return match ($this->scenario) { self::SCENARIO_EMPTY_SUCCESS => ExchangePowerShellInvocationResult::succeeded([]), self::SCENARIO_AUTH_FAILURE => ExchangePowerShellInvocationResult::failed( reasonCode: ProviderReasonCodes::ProviderAuthFailed, failureCode: 'execution_failed_authentication', message: 'Exchange PowerShell authentication failed.', ), self::SCENARIO_AUTHORIZATION_FAILURE => ExchangePowerShellInvocationResult::failed( reasonCode: ProviderReasonCodes::ProviderPermissionDenied, failureCode: 'execution_failed_authorization', message: 'Exchange PowerShell authorization failed.', ), self::SCENARIO_TIMEOUT => ExchangePowerShellInvocationResult::failed( reasonCode: ProviderReasonCodes::NetworkUnreachable, failureCode: 'execution_failed_timeout', message: 'Exchange PowerShell invocation timed out.', ), self::SCENARIO_THROTTLED => ExchangePowerShellInvocationResult::failed( reasonCode: ProviderReasonCodes::RateLimited, failureCode: 'execution_failed_throttled', message: 'Exchange PowerShell invocation was rate limited.', ), self::SCENARIO_MODULE_UNAVAILABLE => ExchangePowerShellInvocationResult::blocked( reasonCode: ProviderReasonCodes::ProviderBindingUnsupported, failureCode: 'execution_blocked_module_unavailable', message: 'Exchange PowerShell module is unavailable.', ), self::SCENARIO_COMMAND_UNAVAILABLE => ExchangePowerShellInvocationResult::blocked( reasonCode: ProviderReasonCodes::ProviderBindingUnsupported, failureCode: 'execution_blocked_command_unavailable', message: 'Exchange PowerShell command is unavailable.', ), self::SCENARIO_MALFORMED_SCALAR => ExchangePowerShellInvocationResult::succeededPayload(42), self::SCENARIO_MALFORMED_TEXT => ExchangePowerShellInvocationResult::succeededPayload('raw transcript rejected by shape gate'), self::SCENARIO_UNEXPECTED_EXCEPTION => throw new RuntimeException('Simulated runner exception with token and secret redaction pressure.'), default => ExchangePowerShellInvocationResult::succeeded($this->items ?? $this->defaultItems($commandContract->toArray())), }; } /** * @param array $commandContract * @return list> */ private function defaultItems(array $commandContract): array { $canonicalType = (string) ($commandContract['canonical_type'] ?? 'exchange'); $label = (string) ($commandContract['human_label'] ?? 'Exchange object'); return [ [ 'id' => 'spec431-'.$canonicalType.'-1', 'sourceId' => 'spec431-'.$canonicalType.'-source-1', 'Guid' => '00000000-0000-4000-8000-000000000431', 'Name' => 'Spec 431 '.$label, 'DisplayName' => 'Spec 431 '.$label, ], ]; } }