"""Regression tests for the credential-pool provider-mismatch guard with custom providers (Bernard's Fireworks report, June 2026). Custom endpoints carry two naming conventions for the same provider: the agent's ``provider`` attribute is the generic ``"custom"`` label while the pool is keyed ``custom:`` (``CUSTOM_POOL_PREFIX``). The defensive guard in ``recover_with_credential_pool`` compared the two literally, logged "Credential pool provider mismatch: pool=custom:, agent=custom", and skipped recovery — so 401/429 recovery (refresh, rotation) never ran for ANY custom-provider user. The fix accepts the pair only when the agent's current base_url resolves to the same pool key, preserving the guard's original purpose (#33088/#33163: never mutate the primary's pool while a fallback provider is active). """ from unittest.mock import MagicMock, patch import pytest from agent.agent_runtime_helpers import recover_with_credential_pool from agent.error_classifier import FailoverReason FIREWORKS_URL = "https://api.fireworks.ai/inference/v1" def _agent(provider, base_url, pool_provider): agent = MagicMock() agent.provider = provider agent.base_url = base_url pool = MagicMock() pool.provider = pool_provider agent._credential_pool = pool return agent, pool class TestCustomPoolMismatchGuard: def test_unrelated_custom_pool_still_guarded(self): """agent=custom pointed at a DIFFERENT endpoint than the pool's custom provider must still skip pool mutation.""" agent, pool = _agent( "custom", "https://other-endpoint.example/v1", "custom:fireworks" ) with patch( "agent.credential_pool.get_custom_provider_pool_key", return_value="custom:other", ): recovered, _ = recover_with_credential_pool( agent, status_code=401, has_retried_429=False, classified_reason=FailoverReason.auth, ) assert recovered is False assert not pool.method_calls def test_fallback_provider_still_guarded(self): """Original #33088/#33163 contract: when a fallback provider is active (agent.provider != pool.provider, non-custom), the pool is never mutated.""" agent, pool = _agent("openai-codex", "https://chatgpt.com/backend-api", "custom:fireworks") recovered, _ = recover_with_credential_pool( agent, status_code=401, has_retried_429=False, classified_reason=FailoverReason.auth, ) assert recovered is False assert not pool.method_calls