76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
"""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
|