Files
hermes-agent/tests/tools/test_profile_gate_env_shape.py
teknium1 ebb9bc5699 fix(env-policy): a profile gate is a platform prefix plus a gate suffix, not a bare name shape
is_profile_gate_env matched any name containing _ALLOWED_ / _ALLOW_ALL_ / ... so an operator's own
DEMO_ALLOWED_SENDER (script data, not a Hermes authorization gate) was deleted from every routed
child env built with strip_launch_profile=True, breaking no_agent cron scripts under the host
gateway. The owner prefix now has to be a platform: built-in Platform values, bundled platform
plugins (directory names and manifest aliases), runtime-registered plugin adapters, plus GATEWAY_
(pairing) and QQ_ (qqbot). Every gate the adapters read still strips; operator variables survive.

Fixes #119539
2026-09-23 06:46:02 -07:00

44 lines
2.2 KiB
Python

"""A profile gate is a PLATFORM prefix plus a gate-shaped suffix; an operator's own variable that
merely contains ``_ALLOWED_`` is script data and must survive the routed-child strip (#119539)."""
import os
from tools.environments.local import build_subprocess_env
from tools.environments.local_env_policy import is_profile_gate_env
def test_operator_allowlist_shaped_vars_are_not_gates_but_platform_gates_are():
# Same suffix shape on both sides — only the owner prefix decides.
assert not is_profile_gate_env("DEMO_ALLOWED_SENDER")
assert not is_profile_gate_env("ACCESS_ALLOWED_CALLBACK_ACE_TYPE")
assert not is_profile_gate_env("HERMES_MEDIA_ALLOW_DIRS")
for gate in ("DISCORD_ALLOWED_CHANNELS", "TELEGRAM_GROUP_ALLOWED_CHATS", "GATEWAY_ALLOW_ALL_USERS",
"WHATSAPP_GROUP_ALLOW_FROM", "QQ_GROUP_ALLOWED_USERS", "IRC_ALLOW_ALL_USERS"):
assert is_profile_gate_env(gate), gate
def test_routed_no_agent_script_env_keeps_operator_allowlist_and_drops_platform_gate(tmp_path, monkeypatch):
"""The cron ``no_agent`` spawn seam: a child built for ANOTHER profile drops Hermes gates but
keeps the operator's script data, whatever its name looks like."""
from agent.secret_scope import build_profile_secret_scope, reset_secret_scope, set_secret_scope
from hermes_constants import reset_hermes_home_override, set_hermes_home_override
launch = tmp_path / ".hermes"
other = launch / "profiles" / "other"
other.mkdir(parents=True)
(other / ".env").write_text("OTHER_MARKER=1\n", encoding="utf-8")
monkeypatch.setenv("HERMES_HOME", str(launch))
monkeypatch.setenv("DEMO_ALLOWED_SENDER", "someone@example.com")
monkeypatch.setenv("DISCORD_ALLOWED_CHANNELS", "111")
ht = set_hermes_home_override(str(other))
st = set_secret_scope(build_profile_secret_scope(other), profile_home=str(other))
try:
env = build_subprocess_env(strip_launch_profile=True)
finally:
reset_secret_scope(st)
reset_hermes_home_override(ht)
assert env.get("DEMO_ALLOWED_SENDER") == "someone@example.com"
assert "DISCORD_ALLOWED_CHANNELS" not in env
assert os.environ["DISCORD_ALLOWED_CHANNELS"] == "111" # the strip never mutates the process env