fix(dashboard): env credentials enable a platform on the profile-scoped messaging status path

The scoped branch of _platform_enablement consulted only config.yaml's
platforms: section, but the `hermes gateway setup` wizard writes .env
credentials and never a platforms: entry. The desktop always sends
?profile=default (normalizeProfileKey maps the primary profile to
`default`), so the Settings - Messaging page showed a working bot as
"Disabled" while /api/status reported it connected (#104614).

Mirror _enable_from_env (gateway/config_env.py): env credentials alone
enable a platform, an explicit enabled: false still wins. Only the
profile's own .env (env_on_disk) is consulted, so the root install's
os.environ credentials still never leak into a profile's state.

Fixes #104614
This commit is contained in:
liuhao1024
2026-09-07 07:25:36 +08:00
committed by Teknium
parent 454a7af89c
commit 5dfa2f8374
2 changed files with 54 additions and 1 deletions

View File

@@ -170,7 +170,18 @@ def _platform_enablement(
plat_cfg = (load_config().get("platforms") or {}).get(platform_id)
plat_cfg = plat_cfg if isinstance(plat_cfg, dict) else {}
hc = plat_cfg.get("home_channel")
enabled, home_channel = bool(plat_cfg.get("enabled")), (hc if isinstance(hc, dict) else None)
# Credential fallback mirrors _enable_from_env (gateway/config_env.py): env
# credentials alone enable a platform — `hermes gateway setup` only writes
# .env and never a platforms: entry (#104614) — while an explicit
# enabled: false still wins, exactly like the real gateway config. Only the
# profile's own .env (env_on_disk) is consulted; os.environ would leak the
# root install's credentials into this profile's state.
raw_enabled = plat_cfg.get("enabled")
if raw_enabled is False:
enabled = False
else:
enabled = bool(raw_enabled) or all(env_on_disk.get(key) for key in required)
home_channel = hc if isinstance(hc, dict) else None
except Exception:
enabled, home_channel = False, None
return enabled, all(env_on_disk.get(key) for key in required), home_channel

View File

@@ -773,6 +773,48 @@ class TestWebServerEndpoints:
assert seen["status_path"] == worker_home / "gateway_state.json"
assert seen["expected_home"] == worker_home
def test_messaging_platforms_profile_scoped_env_credentials_enable(self, monkeypatch):
"""Env credentials alone must enable a platform on the profile-scoped path.
``hermes gateway setup`` writes the token to .env and never a ``platforms:``
entry, but the desktop always sends ``?profile=default``; the scoped branch
consulted only config.yaml's ``platforms:`` section, so the Messaging page
showed "Disabled" for a connected bot (#104614). An explicit
``enabled: false`` must still win, mirroring ``_enable_from_env`` in
gateway/config_env.py.
"""
import hermes_cli.web_server as web_server
from hermes_cli import profiles as profiles_mod
worker_home = profiles_mod.get_profile_dir("worker")
worker_home.mkdir(parents=True)
(worker_home / ".env").write_text("DISCORD_BOT_TOKEN=tok\n", encoding="utf-8")
monkeypatch.setattr(_gw_status, "get_running_pid_cached", lambda pid_path=None, **kw: None)
monkeypatch.setattr(_gw_status, "get_running_pid", lambda pid_path=None, **kw: None)
monkeypatch.setattr(_gw_status, "read_runtime_status", lambda path=None: None)
monkeypatch.setattr(_gw_status, "get_runtime_status_running_pid", lambda runtime=None, **kw: None)
monkeypatch.setattr(web_server, "_GATEWAY_HEALTH_URL", None)
resp = self.client.get("/api/messaging/platforms?profile=worker")
assert resp.status_code == 200
platforms = {p["id"]: p for p in resp.json()["platforms"]}
assert platforms["discord"]["enabled"] is True
assert platforms["discord"]["configured"] is True
assert platforms["discord"]["state"] != "disabled"
# Explicit platforms.discord.enabled: false wins over the .env credentials.
(worker_home / "config.yaml").write_text(
"platforms:\n discord:\n enabled: false\n", encoding="utf-8"
)
resp = self.client.get("/api/messaging/platforms?profile=worker")
assert resp.status_code == 200
platforms = {p["id"]: p for p in resp.json()["platforms"]}
assert platforms["discord"]["enabled"] is False
assert platforms["discord"]["state"] == "disabled"