refactor(console): remove hosted-context command blocking from Hermes Console (#66144)

The dashboard console previously ran under a 'hosted' context that
blocked most commands (auth add, config set model.*, mcp add --command,
cron --script, ...) behind an allowlist + line-policy layer. With the
full Hermes CLI now built into the dashboard, that policy layer is
redundant gatekeeping: the console gets the same command surface
everywhere.

Removed:
- ConsoleContext/contexts plumbing on ConsoleCommand + engine
- EXPECTED_HOSTED_PATHS allowlist + _mark_hosted
- _enforce_hosted_line_policy + HOSTED_CONFIG_* allow/block tables
- _dashboard_console_context() and the context field on the ready frame
- hosted-context tests; context badge in HermesConsoleModal

Kept (mechanical, not policy): shell-syntax rejection, the
interactive/server command blocks (gateway, dashboard, mcp serve, ...),
mutating-command confirmations, output caps, and command timeouts.
This commit is contained in:
Teknium 2026-07-17 04:33:34 -07:00 • committed by GitHub
parent 60419dfb4b
commit 6dcbcd0277
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 26 additions and 467 deletions

View file

@ -339,168 +339,6 @@ def test_console_registry_covers_non_admin_cli_surface():
assert missing == set()
EXPECTED_HOSTED_CONSOLE_COMMANDS = {
("status",),
("doctor",),
("logs",),
("version",),
("prompt-size",),
("insights",),
("security", "audit"),
("portal", "info"),
("portal", "tools"),
("send",),
("config", "show"),
("config", "path"),
("config", "env-path"),
("config", "check"),
("config", "migrate"),
("config", "set"),
("sessions", "list"),
("sessions", "stats"),
("sessions", "export"),
("sessions", "rename"),
("sessions", "optimize"),
("sessions", "repair"),
("cron", "list"),
("cron", "status"),
("cron", "create"),
("cron", "edit"),
("cron", "pause"),
("cron", "resume"),
("cron", "run"),
("cron", "remove"),
("cron", "tick"),
("profile",),
("profile", "list"),
("profile", "show"),
("profile", "info"),
("tools", "list"),
("tools", "enable"),
("tools", "disable"),
("tools", "post-setup"),
("skills", "browse"),
("skills", "search"),
("skills", "inspect"),
("skills", "list"),
("skills", "check"),
("skills", "list-modified"),
("skills", "diff"),
("skills", "install"),
("skills", "update"),
("skills", "audit"),
("skills", "uninstall"),
("skills", "reset"),
("skills", "opt-in"),
("skills", "opt-out"),
("skills", "repair-official"),
("skills", "snapshot", "export"),
("skills", "tap", "list"),
("mcp", "list"),
("mcp", "catalog"),
("mcp", "test"),
("mcp", "add"),
("mcp", "remove"),
("mcp", "install"),
("mcp", "login"),
("mcp", "reauth"),
("mcp", "configure"),
("mcp", "picker"),
("memory", "status"),
("auth", "list"),
("auth", "status"),
("auth", "reset"),
("auth", "spotify", "status"),
("pairing", "list"),
("pairing", "approve"),
("pairing", "revoke"),
("pairing", "clear-pending"),
("webhook", "list"),
("webhook", "subscribe"),
("webhook", "remove"),
("webhook", "test"),
}
def test_hosted_console_registry_exposes_only_hosted_safe_surface():
engine = HermesConsoleEngine(context="hosted")
hosted = {
path for path, command in engine.commands.items() if "hosted" in command.contexts
}
assert hosted == EXPECTED_HOSTED_CONSOLE_COMMANDS
@pytest.mark.parametrize(
"line",
[
"portal login",
"auth add nous --type oauth",
"auth logout nous",
"profile create tester",
"profile use default",
"plugins list",
"plugins install owner/repo",
"kanban list",
"hooks list",
"checkpoints clear",
"curator pause",
"pets install cat",
"backup --quick",
"import /tmp/hermes-console-test.zip",
"mcp serve",
"model",
"setup",
"dashboard",
"gateway restart",
"update",
"uninstall",
],
)
def test_hosted_console_rejects_local_only_or_dangerous_commands(line):
result = HermesConsoleEngine(context="hosted").execute(line)
assert result.status == "error"
assert result.output
@pytest.mark.parametrize(
"line",
[
"mcp add demo --url https://example.com/sse",
"mcp install n8n",
"mcp configure github",
"mcp picker",
"config set display.interface cli",
"cron create 'every 1h' 'say hello'",
],
)
def test_hosted_console_allows_guarded_useful_commands_before_confirmation(line):
result = HermesConsoleEngine(context="hosted").execute(line)
assert result.status == "confirm_required"
@pytest.mark.parametrize(
"line",
[
"mcp add local --command npx --args foo",
"mcp add local --preset unsafe",
"mcp add local --url file:///tmp/server",
"config set model.provider openrouter",
"config set portal.url https://evil.example",
"cron create 'every 1h' 'say hello' --script scripts/ping.py",
"cron create 'every 1h' 'say hello' --no-agent",
"cron edit abc123 --workdir /tmp/project",
],
)
def test_hosted_console_blocks_known_footgun_arguments_before_confirmation(line):
result = HermesConsoleEngine(context="hosted").execute(line)
assert result.status == "error"
assert result.output
@pytest.mark.parametrize(
"line",
[