"""Hermes chat codex broker contracts.""" from __future__ import annotations from test_hermes_chat_support import ( ModuleType, Path, _load_broker_module, base64, json, sys, time, ) def test_codex_broker_refreshes_and_persists_first_party_oauth( tmp_path: Path, monkeypatch ): """Expired ChatGPT OAuth refreshes in the canonical Codex CLI store.""" module = _load_broker_module( "hermes_codex_refresh_broker", "codex_broker.py", monkeypatch ) auth_dir = tmp_path / ".codex" auth_dir.mkdir() def jwt(expires_at: float) -> str: payload = base64.urlsafe_b64encode( json.dumps({"exp": expires_at}).encode() ).decode().rstrip("=") return f"header.{payload}.signature" expired = jwt(time.time() - 60) live = jwt(time.time() + 3600) auth_path = auth_dir / "auth.json" auth_path.write_text( json.dumps( { "auth_mode": "chatgpt", "tokens": { "access_token": expired, "refresh_token": "refresh-old", }, } ) ) calls = [] auth_module = ModuleType("hermes_cli.auth") def refresh(access_token, refresh_token, *, timeout_seconds): calls.append((access_token, refresh_token, timeout_seconds)) return { "access_token": live, "refresh_token": "refresh-new", "last_refresh": "2026-08-12T20:00:00Z", } auth_module.refresh_codex_oauth_pure = refresh package = ModuleType("hermes_cli") package.auth = auth_module monkeypatch.setitem(sys.modules, "hermes_cli", package) monkeypatch.setitem(sys.modules, "hermes_cli.auth", auth_module) monkeypatch.setenv("CODEX_HOME", str(auth_dir)) assert module._access_token() == live persisted = json.loads(auth_path.read_text()) assert persisted["tokens"]["access_token"] == live assert persisted["tokens"]["refresh_token"] == "refresh-new" assert persisted["last_refresh"] == "2026-08-12T20:00:00Z" assert calls == [(expired, "refresh-old", 30.0)] assert auth_path.stat().st_mode & 0o777 == 0o600 # A healthy token is reused, so repeated routed turns do not spend a # refresh token or create a second billing/authentication path. assert module._access_token() == live assert len(calls) == 1