*/ public static function forReason(?string $reasonCode): array { if (! is_string($reasonCode) || trim($reasonCode) === '') { return []; } $normalized = RunFailureSanitizer::normalizeReasonCode($reasonCode); return match ($normalized) { RunFailureSanitizer::REASON_PERMISSION_DENIED => [ 'Confirm admin consent is granted for all required Microsoft Graph permissions.', 'Verify the Azure app registration has the correct API permissions assigned.', 'Re-run “Verify permissions” after updating consent/permissions.', ], RunFailureSanitizer::REASON_PROVIDER_AUTH_FAILED => [ 'Confirm the client secret is valid and not expired.', 'Verify the tenant ID and client ID are correct for this connection.', 'Re-save credentials and re-run the task.', ], RunFailureSanitizer::REASON_GRAPH_THROTTLED, RunFailureSanitizer::REASON_GRAPH_TIMEOUT => [ 'Wait a few minutes and try again (transient Graph errors are common).', 'Run the task during off-peak hours if throttling persists.', ], RunFailureSanitizer::REASON_PROVIDER_OUTAGE => [ 'Check Microsoft 365 service health / Graph status and try again later.', ], RunFailureSanitizer::REASON_VALIDATION_ERROR => [ 'Double-check the selected provider connection and tenant settings.', 'Review the error message for which input is invalid (no secrets are shown).', ], RunFailureSanitizer::REASON_CONFLICT_DETECTED => [ 'Review what changed in the tenant before rerunning.', 'If a conflicting configuration exists, resolve it and re-run the task.', ], default => [ 'Retry the task and review the latest evidence message.', 'If the issue persists, ask an Owner to review tenant access and connection settings.', ], }; } }