context) ? $run->context : []; $storedTranslation = is_array($context['reason_translation'] ?? null) ? $context['reason_translation'] : null; if ($storedTranslation !== null) { $storedEnvelope = ReasonResolutionEnvelope::fromArray($storedTranslation); if ($storedEnvelope instanceof ReasonResolutionEnvelope) { if ($storedEnvelope->nextSteps === [] && is_array($context['next_steps'] ?? null)) { return $storedEnvelope->withNextSteps(NextStepOption::collect($context['next_steps'])); } return $storedEnvelope; } } $contextReasonCode = data_get($context, 'execution_legitimacy.reason_code') ?? data_get($context, 'reason_code'); if (is_string($contextReasonCode) && trim($contextReasonCode) !== '') { return $this->translateOperationRunReason(trim($contextReasonCode), $surface, $context); } $failureReasonCode = data_get($run->failure_summary, '0.reason_code'); if (! is_string($failureReasonCode) || trim($failureReasonCode) === '') { return null; } $failureReasonCode = trim($failureReasonCode); if (! $this->isDirectlyTranslatableOperationReason($failureReasonCode)) { return null; } $envelope = $this->translateOperationRunReason($failureReasonCode, $surface, $context); if (! $envelope instanceof ReasonResolutionEnvelope) { return null; } if ($envelope->nextSteps !== []) { return $envelope; } $legacyNextSteps = is_array($context['next_steps'] ?? null) ? NextStepOption::collect($context['next_steps']) : []; return $legacyNextSteps !== [] ? $envelope->withNextSteps($legacyNextSteps) : $envelope; } /** * @param array $context */ private function translateOperationRunReason( string $reasonCode, string $surface, array $context, ): ?ReasonResolutionEnvelope { return $this->reasonTranslator->translate($reasonCode, surface: $surface, context: $context); } private function isDirectlyTranslatableOperationReason(string $reasonCode): bool { if ($reasonCode === ProviderReasonCodes::UnknownError) { return false; } return ProviderReasonCodes::isKnown($reasonCode) || ExecutionDenialReasonCode::tryFrom($reasonCode) instanceof ExecutionDenialReasonCode || TenantOperabilityReasonCode::tryFrom($reasonCode) instanceof TenantOperabilityReasonCode || RbacReason::tryFrom($reasonCode) instanceof RbacReason; } public function forProviderReason( Tenant $tenant, string $reasonCode, ?ProviderConnection $connection = null, string $surface = 'detail', ): ?ReasonResolutionEnvelope { return $this->reasonTranslator->translate( reasonCode: $reasonCode, artifactKey: ProviderReasonTranslator::ARTIFACT_KEY, surface: $surface, context: [ 'tenant' => $tenant, 'connection' => $connection, ], ); } public function forTenantOperabilityReason( TenantOperabilityReasonCode|string|null $reasonCode, string $surface = 'detail', ): ?ReasonResolutionEnvelope { $normalizedCode = $reasonCode instanceof TenantOperabilityReasonCode ? $reasonCode->value : $reasonCode; return $this->reasonTranslator->translate( reasonCode: $normalizedCode, artifactKey: ReasonTranslator::TENANT_OPERABILITY_ARTIFACT, surface: $surface, ); } public function forRbacReason(RbacReason|string|null $reasonCode, string $surface = 'detail'): ?ReasonResolutionEnvelope { $normalizedCode = $reasonCode instanceof RbacReason ? $reasonCode->value : $reasonCode; return $this->reasonTranslator->translate( reasonCode: $normalizedCode, artifactKey: ReasonTranslator::RBAC_ARTIFACT, surface: $surface, ); } public function diagnosticCode(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->diagnosticCode(); } public function primaryLabel(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->operatorLabel; } public function shortExplanation(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->shortExplanation; } public function guidance(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->guidanceText(); } /** * @return array */ public function bodyLines(?ReasonResolutionEnvelope $envelope, bool $includeGuidance = true): array { return $envelope?->toBodyLines($includeGuidance) ?? []; } }