Files
hermes-agent/tests/hermes_cli/test_bot_desktop_screen_status.py
teknium1 bead012b91 fix(bot-screen): computer-use screen status redacts the lease holder's viewer id like every RPC surface
The CLI printed lease.get().as_dict() (--json) and "human (<viewer_id>)" while
display.status, the display.lease broadcast and both lease mutations replaced the
id with its 12-hex sha256 prefix. The viewer id is a capability (whoever presents
it co-drives or releases the lease), and the CLI leaked the one string the rest of
the feature deliberately hides.

The redaction now has one owner, tools.bot_desktop.lease.public_view(); the RPC
handlers, the lease watcher and the CLI all call it, so there is no second hash
implementation to drift. The human-readable line shows "human (viewer <hash>)".

Closes #110006
2026-09-18 19:20:01 -07:00

48 lines
1.9 KiB
Python

"""``hermes computer-use screen status`` shows the lease the way every RPC surface does: the holder's viewer
id is a capability (whoever presents it co-drives or releases the lease), so only its short hash leaves the
gateway. Regression for #110006."""
import argparse
import hashlib
import json
import pytest
from hermes_cli.subcommands import computer_use_screen
from tools.bot_desktop import lease, runtime
def _parse(argv):
parser = argparse.ArgumentParser()
computer_use_screen.build_screen_parser(
parser.add_subparsers(), lambda sub, help_text: sub.add_argument("--json", action="store_true"))
return parser.parse_args(argv)
@pytest.fixture
def running_screen(monkeypatch):
monkeypatch.setattr(runtime, "status", lambda profile=None: runtime.DesktopStatus(
profile="default", supported=True, installed=True, missing=[], running=True, pid=4242, display=":20",
socket="/x/rfb.sock", geometry="1440x900", install_command=None, browser=None))
yield
lease._reset_for_tests()
def test_status_never_prints_the_holders_raw_viewer_id(running_screen, capsys):
from tui_gateway import methods_display
secret = "secret-viewer-token-ABC123"
lease.acquire(secret, reason="typing a password")
rpc_view = methods_display._display_snapshot()["lease"] # what display.status / display.lease emit
assert secret not in json.dumps(rpc_view)
assert computer_use_screen.SCREEN_ACTIONS["status"](_parse(["screen", "status", "--json"])) == 0
payload = json.loads(capsys.readouterr().out)
assert secret not in json.dumps(payload)
assert payload["lease"] == rpc_view, "the CLI and the RPC surfaces emit one and the same redacted lease"
assert payload["lease"]["viewer_hash"] == hashlib.sha256(secret.encode()).hexdigest()[:12]
assert computer_use_screen.SCREEN_ACTIONS["status"](_parse(["screen", "status"])) == 0
human = capsys.readouterr().out
assert secret not in human and "control: human" in human