fix(auth): tolerate legacy Codex suppression data

This commit is contained in:
Daniel Magro
2026-08-10 11:20:44 -04:00
committed by Teknium
parent c28114a5f8
commit 590d547b40
2 changed files with 60 additions and 5 deletions
+30 -5
View File
@@ -1753,11 +1753,29 @@ def write_credential_pool(
def suppress_credential_source(provider_id: str, source: str) -> None:
"""Mark a credential source as suppressed so it won't be re-seeded."""
"""Mark a credential source as suppressed so it won't be re-seeded.
Older auth stores may represent a provider's suppressed sources as a
mapping. Treat its keys as source names and migrate the value to the
canonical list form before appending the requested source.
"""
with _auth_store_lock():
auth_store = _load_auth_store()
suppressed = auth_store.setdefault("suppressed_sources", {})
provider_list = suppressed.setdefault(provider_id, [])
suppressed = auth_store.get("suppressed_sources")
if not isinstance(suppressed, dict):
suppressed = {}
auth_store["suppressed_sources"] = suppressed
raw_sources = suppressed.get(provider_id)
if isinstance(raw_sources, list):
provider_list = raw_sources
elif isinstance(raw_sources, dict):
provider_list = [str(name) for name in raw_sources]
suppressed[provider_id] = provider_list
else:
provider_list = []
suppressed[provider_id] = provider_list
if source not in provider_list:
provider_list.append(source)
_save_auth_store(auth_store)
@@ -1783,8 +1801,15 @@ def unsuppress_credential_source(provider_id: str, source: str) -> bool:
suppressed = auth_store.get("suppressed_sources")
if not isinstance(suppressed, dict):
return False
provider_list = suppressed.get(provider_id)
if not isinstance(provider_list, list) or source not in provider_list:
raw_sources = suppressed.get(provider_id)
if isinstance(raw_sources, dict):
provider_list = [str(name) for name in raw_sources]
suppressed[provider_id] = provider_list
elif isinstance(raw_sources, list):
provider_list = raw_sources
else:
return False
if source not in provider_list:
return False
provider_list.remove(source)
if not provider_list:
+30
View File
@@ -521,6 +521,36 @@ def test_auth_remove_reindexes_priorities(tmp_path, monkeypatch):
assert entries[0]["priority"] == 0
def test_auth_remove_codex_migrates_legacy_dict_suppression(tmp_path, monkeypatch):
"""Removing a Codex credential must tolerate legacy dict suppression data."""
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
store = _codex_pool_only_store()
primary = store["credential_pool"]["openai-codex"][0]
primary.update({"id": "codex-qb", "label": "qb"})
store["suppressed_sources"] = {"openai-codex": {"legacy": True}}
_write_auth_store(tmp_path, store)
from hermes_cli.auth_commands import auth_remove_command
class _Args:
provider = "openai-codex"
target = "qb"
auth_remove_command(_Args())
payload = json.loads((tmp_path / "hermes" / "auth.json").read_text(encoding="utf-8"))
assert payload.get("credential_pool", {}).get("openai-codex", []) == []
assert payload["suppressed_sources"]["openai-codex"] == [
"legacy",
"device_code",
"manual:device_code",
]
from agent.credential_pool import load_pool
assert load_pool("openai-codex").peek() is None
def test_clear_provider_auth_removes_provider_pool_entries(tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
_write_auth_store(