mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
feat(dashboard-auth): Nous plugin always-on; default portal URL; specific error messages
The Nous OAuth provider plugin (plugins/dashboard_auth/nous) is bundled
and auto-loaded — same as before — but previously refused to register
unless BOTH HERMES_DASHBOARD_OAUTH_CLIENT_ID and HERMES_DASHBOARD_PORTAL_URL
were set, then the gate's fail-closed branch told the operator 'install
the default Nous provider'. That message is misleading: the provider IS
installed; it's just unconfigured. And the contract only really needs
the per-instance client_id — the portal URL is the same for everyone
in production.
Three changes:
1. plugins/dashboard_auth/nous/__init__.py:
- HERMES_DASHBOARD_PORTAL_URL is now optional and defaults to
'https://portal.nousresearch.com'. Override only for staging
(portal.rewbs.uk) or a custom deployment. Empty string also
falls back to the default so an empty Fly secret can't point
the dashboard at nowhere.
- Plugin exposes a module-level LAST_SKIP_REASON: str that the gate
reads when no providers register. Cleared on each register() call.
Skip reasons are human-readable and actionable
('HERMES_DASHBOARD_OAUTH_CLIENT_ID is not set. The Nous Portal
provisions this env var…').
2. plugins/dashboard_auth/nous/plugin.yaml:
- requires_env drops HERMES_DASHBOARD_PORTAL_URL; only the client_id
is mandatory. Description updated to reflect this.
3. hermes_cli/web_server.py:
- When the gate fail-closes for 'no providers', it now reads each
bundled plugin's LAST_SKIP_REASON and embeds them in the SystemExit
message. Operator sees the specific config fix needed:
Bundled providers reported these issues:
• nous: HERMES_DASHBOARD_OAUTH_CLIENT_ID is not set. …
instead of the prior generic 'Install the default Nous provider'.
Tests:
- TestPluginRegister rewritten to assert the new defaults +
LAST_SKIP_REASON contents (6 tests, +1 new for empty-string env).
- New gate test test_start_server_surfaces_nous_skip_reason_when_unconfigured.
- test_get_method_is_not_allowed widened to handle the SPA-shell 200
path explicitly — assertion now verifies no JSON ticket leaks
rather than asserting a specific status code (covers all four of
401/404/405/200).
Docs updated: web-dashboard.md's 'Default provider' section now shows
the env-var table with required/optional columns and embeds the
fail-closed error message verbatim so operators can match what they
see at the prompt.
This commit is contained in:
parent
af3d4a687f
commit
b3dc539304
7 changed files with 219 additions and 56 deletions
|
|
@ -4850,15 +4850,44 @@ def start_server(
|
|||
# provider to be registered, else fail closed".
|
||||
from hermes_cli.dashboard_auth import list_providers
|
||||
if not list_providers():
|
||||
# Surface the *specific* reason any bundled provider declined
|
||||
# to register (e.g. missing HERMES_DASHBOARD_OAUTH_CLIENT_ID).
|
||||
# Each provider plugin that ships with Hermes Agent exposes a
|
||||
# module-level ``LAST_SKIP_REASON`` string for this purpose;
|
||||
# without it the operator would only see "no providers" which
|
||||
# is misleading when the provider IS installed but unconfigured.
|
||||
skip_reasons: list[str] = []
|
||||
try:
|
||||
from plugins.dashboard_auth import nous as _nous_plugin
|
||||
|
||||
if _nous_plugin.LAST_SKIP_REASON:
|
||||
skip_reasons.append(
|
||||
f" • nous: {_nous_plugin.LAST_SKIP_REASON}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if skip_reasons:
|
||||
raise SystemExit(
|
||||
f"Refusing to bind dashboard to {host} — the OAuth auth "
|
||||
f"gate engages on non-loopback binds, but no auth "
|
||||
f"providers are registered.\n"
|
||||
f"\n"
|
||||
f"Bundled providers reported these issues:\n"
|
||||
+ "\n".join(skip_reasons)
|
||||
+ "\n"
|
||||
f"\n"
|
||||
f"Or pass --insecure to skip the auth gate (NOT "
|
||||
f"recommended on untrusted networks)."
|
||||
)
|
||||
raise SystemExit(
|
||||
f"Refusing to bind dashboard to {host} — the OAuth auth "
|
||||
f"gate engages on non-loopback binds, but no auth providers "
|
||||
f"are registered.\n"
|
||||
f"Install the default Nous provider "
|
||||
f"(plugins/dashboard-auth-nous) or another "
|
||||
f"DashboardAuthProvider plugin.\n"
|
||||
f"Or pass --insecure to skip the auth gate (NOT recommended "
|
||||
f"on untrusted networks)."
|
||||
f"are registered and no bundled plugin reported a reason "
|
||||
f"(was the dashboard_auth/nous plugin removed?).\n"
|
||||
f"Install a DashboardAuthProvider plugin, or pass --insecure "
|
||||
f"to skip the auth gate (NOT recommended on untrusted "
|
||||
f"networks)."
|
||||
)
|
||||
_log.info(
|
||||
"Dashboard binding to %s with OAuth auth gate enabled. "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue