test: trim Codex write-through tests to two invariants on the real profile layout

The picked tests monkeypatched _auth_file_path/_global_auth_file_path
directly and leaned on a HOME override to dodge the pytest seat belt.
Isolate the way the rest of tests/hermes_cli does instead: Path.home ->
tmp_path and HERMES_HOME -> <root>/profiles/<name>, so the fixture drives
the same get_default_hermes_root() resolution production uses. Drop the
classic-mode test (no new behaviour: source == active store is the
pre-existing save path). Two invariants remain: root-borrowed refresh
lands in root (singleton + pool) with no profile shadow; profile-owned
grant stays local with root untouched.
This commit is contained in:
kshitijk4poor
2026-09-13 20:10:18 +05:30
committed by kshitij
parent 6bd29f26f6
commit 0ff20dc98a

View File

@@ -1,19 +1,13 @@
"""Regression tests for Codex OAuth refresh write-through to the global root.
"""Codex OAuth refresh writes back to the store the grant was resolved FROM (#87503).
Mirrors ``test_xai_oauth_writethrough.py`` for the Codex family (#87503):
Codex refresh tokens are single-use with rotation-family reuse detection,
so when a profile that has no own ``providers.openai-codex`` block refreshes
the grant it resolved from the root fallback, the rotated chain must land
back in root — including the ``credential_pool`` entries the runtime selects
credentials from. Otherwise root keeps the consumed refresh token, the next
process to read it replays it, and OpenAI revokes the whole rotation family.
The tests drive the real ``_save_codex_tokens`` against real on-disk auth
stores (profile + root under ``tmp_path``). All token values are synthetic
placeholders assembled by ``_pair`` — no real credentials are involved.
Codex refresh tokens are single-use with rotation-family reuse detection: a profile that refreshed
a root-borrowed grant must land the rotated chain in root — singleton AND ``credential_pool`` —
or root keeps the consumed refresh token and the next reader gets the whole family revoked.
Token values are synthetic placeholders.
"""
import json
from pathlib import Path
import pytest
@@ -21,133 +15,60 @@ from hermes_cli import auth
def _pair(prefix: str) -> dict:
"""Synthetic OAuth pair for fixtures/assertions (not credentials)."""
return {
"access_token": f"{prefix}-at",
"refresh_token": f"{prefix}-rt",
}
return {"access_token": f"{prefix}-at", "refresh_token": f"{prefix}-rt"}
def _write_store(path, store):
def _write(path: Path, store: dict) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(store), encoding="utf-8")
def _read_store(path):
def _read(path: Path) -> dict:
return json.loads(path.read_text(encoding="utf-8"))
@pytest.fixture
def profile_and_root(tmp_path, monkeypatch):
"""Wire a profile auth store + a distinct global-root auth store on disk."""
profile_path = tmp_path / "profiles" / "work" / "auth.json"
root_path = tmp_path / "root" / "auth.json"
monkeypatch.setattr(auth, "_auth_file_path", lambda: profile_path)
monkeypatch.setattr(auth, "_global_auth_file_path", lambda: root_path)
# Keep the pytest write seat belt from matching our tmp root.
monkeypatch.setenv("HOME", str(tmp_path / "not-the-root"))
return profile_path, root_path
def profile_env(tmp_path, monkeypatch):
"""Global root at tmp/.hermes, active profile at tmp/.hermes/profiles/work (real on-disk layout)."""
monkeypatch.setattr(Path, "home", lambda: tmp_path)
root = tmp_path / ".hermes"
profile = root / "profiles" / "work"
profile.mkdir(parents=True)
monkeypatch.setenv("HERMES_HOME", str(profile))
return profile / "auth.json", root / "auth.json"
def test_profile_refresh_of_root_grant_writes_through(profile_and_root):
"""#87503: rotating the root-resolved grant must reach the root store —
singleton AND credential-pool entries — without forking a shadowing
profile key."""
profile_path, root_path = profile_and_root
_write_store(
root_path,
{
"version": 1,
"providers": {
"openai-codex": {
"auth_mode": "chatgpt",
"tokens": _pair("old"),
}
},
"credential_pool": {
"openai-codex": [
{
"provider": "openai-codex",
"source": "device_code",
**_pair("old"),
}
]
},
},
)
_write_store(profile_path, {"version": 1, "providers": {}})
def test_profile_refresh_of_root_grant_writes_through_to_root(profile_env):
profile_path, root_path = profile_env
_write(root_path, {
"version": 1,
"providers": {"openai-codex": {"auth_mode": "chatgpt", "tokens": _pair("old")}},
"credential_pool": {"openai-codex": [
{"provider": "openai-codex", "source": "device_code", **_pair("old")}]},
})
_write(profile_path, {"version": 1, "providers": {}})
rotated = _pair("new")
auth._save_codex_tokens(
rotated,
last_refresh="2026-08-16T00:00:00Z",
)
auth._save_codex_tokens(rotated, last_refresh="2026-08-16T00:00:00Z")
root = _read_store(root_path)
assert (
root["providers"]["openai-codex"]["tokens"]["refresh_token"]
== rotated["refresh_token"]
), "root singleton must hold the rotated refresh token"
pool_entry = root["credential_pool"]["openai-codex"][0]
assert pool_entry["refresh_token"] == rotated["refresh_token"]
assert pool_entry["access_token"] == rotated["access_token"]
profile = _read_store(profile_path)
assert "openai-codex" not in profile.get("providers", {}), (
"profile must not gain a shadowing providers.openai-codex key — "
"it would disable the write-through on the next refresh (#74339)"
)
root = _read(root_path)
assert root["providers"]["openai-codex"]["tokens"] == rotated
assert root["credential_pool"]["openai-codex"][0]["refresh_token"] == rotated["refresh_token"]
assert root["credential_pool"]["openai-codex"][0]["access_token"] == rotated["access_token"]
# A profile copy would shadow root and disable the write-through on the next refresh (#74339).
assert "openai-codex" not in _read(profile_path).get("providers", {})
def test_profile_owned_state_saves_to_profile_only(profile_and_root):
"""A profile with its own openai-codex block keeps the existing
profile-local save; root is untouched."""
profile_path, root_path = profile_and_root
_write_store(
profile_path,
{
"version": 1,
"providers": {
"openai-codex": {
"auth_mode": "chatgpt",
"tokens": _pair("prof"),
}
},
},
)
_write_store(root_path, {"version": 1, "providers": {}})
def test_profile_owned_grant_stays_local(profile_env):
profile_path, root_path = profile_env
_write(profile_path, {
"version": 1,
"providers": {"openai-codex": {"auth_mode": "chatgpt", "tokens": _pair("prof")}},
})
_write(root_path, {"version": 1, "providers": {}})
rotated = _pair("next")
auth._save_codex_tokens(
rotated,
last_refresh="2026-08-16T00:00:00Z",
)
auth._save_codex_tokens(rotated, last_refresh="2026-08-16T00:00:00Z")
profile = _read_store(profile_path)
assert (
profile["providers"]["openai-codex"]["tokens"]["refresh_token"]
== rotated["refresh_token"]
)
root = _read_store(root_path)
assert "openai-codex" not in root.get("providers", {})
def test_classic_mode_still_saves_single_store(tmp_path, monkeypatch):
"""Classic mode (profile == root): unchanged single-store save."""
profile_path = tmp_path / "auth.json"
monkeypatch.setattr(auth, "_auth_file_path", lambda: profile_path)
monkeypatch.setattr(auth, "_global_auth_file_path", lambda: None)
_write_store(profile_path, {"version": 1, "providers": {}})
rotated = _pair("classic")
auth._save_codex_tokens(
rotated,
last_refresh="2026-08-16T00:00:00Z",
)
store = _read_store(profile_path)
assert (
store["providers"]["openai-codex"]["tokens"]["refresh_token"]
== rotated["refresh_token"]
)
assert _read(profile_path)["providers"]["openai-codex"]["tokens"] == rotated
assert "openai-codex" not in _read(root_path).get("providers", {})