fix(desktop): route global remote profile REST calls (#47011)

* fix(desktop): route global remote profile REST calls

* fix(dashboard): scope oauth provider routes by profile

* test(tui): isolate notification poller queue
This commit is contained in:
Gille
2026-06-15 23:24:55 -05:00
committed by GitHub
parent 7cd71de1f4
commit 0441b7f19f
8 changed files with 478 additions and 126 deletions
+133
View File
@@ -34,6 +34,13 @@ client = TestClient(app)
HEADERS = {"X-Hermes-Session-Token": _SESSION_TOKEN}
def _make_profile_home(tmp_path, monkeypatch, profile="coder"):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
profile_home = tmp_path / "profiles" / profile
profile_home.mkdir(parents=True)
return profile_home
def _fake_nous_device_data():
return {
"device_code": "device-code",
@@ -127,6 +134,67 @@ def test_nous_dashboard_device_flow_ignores_legacy_scope_override(monkeypatch):
ws._oauth_sessions.pop(result["session_id"], None)
def test_oauth_provider_status_uses_profile_query(tmp_path, monkeypatch):
from hermes_cli import web_server as ws
from hermes_constants import get_hermes_home
profile_home = _make_profile_home(tmp_path, monkeypatch)
observed_homes = []
def fake_status():
observed_homes.append(get_hermes_home())
return {"logged_in": False, "source": None}
fake_catalog = ({
"id": "fake-oauth",
"name": "Fake OAuth",
"flow": "pkce",
"cli_command": "hermes auth add fake-oauth",
"docs_url": "https://example.com",
"status_fn": fake_status,
},)
monkeypatch.setattr(ws, "_OAUTH_PROVIDER_CATALOG", fake_catalog)
resp = client.get("/api/providers/oauth?profile=coder", headers=HEADERS)
assert resp.status_code == 200, resp.text
assert observed_homes == [profile_home]
def test_oauth_start_stores_profile_for_background_completion(tmp_path, monkeypatch):
from hermes_cli import web_server as ws
_make_profile_home(tmp_path, monkeypatch)
fake_user_code_resp = {
"user_code": "ABCD-1234",
"verification_uri": "https://api.minimax.io/oauth/verify",
"expired_in": 600,
"interval": 2000,
"state": "stub-state",
}
with patch(
"hermes_cli.auth._minimax_request_user_code",
return_value=fake_user_code_resp,
), patch(
"hermes_cli.auth._minimax_pkce_pair",
return_value=("verifier-stub", "challenge-stub", "stub-state"),
), patch(
"hermes_cli.web_server._minimax_poller",
return_value=None,
):
resp = client.post(
"/api/providers/oauth/minimax-oauth/start?profile=coder",
headers=HEADERS,
)
assert resp.status_code == 200, resp.text
session_id = resp.json()["session_id"]
try:
assert ws._oauth_sessions[session_id]["profile"] == "coder"
finally:
ws._oauth_sessions.pop(session_id, None)
def test_nous_dashboard_device_flow_does_not_retry_legacy_scope_on_invoke_refusal(monkeypatch):
from hermes_cli import auth as auth_mod
from hermes_cli import web_server as ws
@@ -207,6 +275,71 @@ def test_codex_dashboard_worker_persists_runtime_provider(tmp_path, monkeypatch)
ws._oauth_sessions.pop(sid, None)
def test_codex_dashboard_worker_persists_inside_session_profile(tmp_path, monkeypatch):
from hermes_cli import auth as auth_mod
from hermes_cli import web_server as ws
from hermes_constants import get_hermes_home
profile_home = _make_profile_home(tmp_path, monkeypatch)
class _Resp:
def __init__(self, status_code, payload):
self.status_code = status_code
self._payload = payload
def json(self):
return self._payload
class _Client:
def __init__(self, *args, **kwargs):
pass
def __enter__(self):
return self
def __exit__(self, *args):
return False
def post(self, url, **kwargs):
if url.endswith("/deviceauth/usercode"):
return _Resp(200, {
"device_auth_id": "device-auth-id",
"interval": 3,
"user_code": "CODEX-1234",
})
if url.endswith("/deviceauth/token"):
return _Resp(200, {
"authorization_code": "authorization-code",
"code_verifier": "code-verifier",
})
return _Resp(200, {
"access_token": "codex-access",
"refresh_token": "codex-refresh",
})
saved_homes = []
monkeypatch.setattr(httpx, "Client", _Client)
monkeypatch.setattr(ws.time, "sleep", lambda _: None)
monkeypatch.setattr(
auth_mod,
"_save_codex_tokens",
lambda tokens: saved_homes.append(get_hermes_home()),
)
sid, _ = ws._new_oauth_session(
"openai-codex",
"device_code",
profile="coder",
)
try:
ws._codex_full_login_worker(sid)
assert ws._oauth_sessions[sid]["status"] == "approved"
assert saved_homes == [profile_home]
finally:
ws._oauth_sessions.pop(sid, None)
def test_nous_dashboard_poller_preserves_effective_scope_when_token_omits_scope(monkeypatch):
from hermes_cli import auth as auth_mod
from hermes_cli import web_server as ws