Skip to content

feat(dashboard): hermes dashboard register for self-hosted OAuth client - #38771

Closed
benbarclay wants to merge 2 commits into
mainfrom
feat/dashboard-register
Closed

feat(dashboard): hermes dashboard register for self-hosted OAuth client#38771
benbarclay wants to merge 2 commits into
mainfrom
feat/dashboard-register

Conversation

@benbarclay

Copy link
Copy Markdown
Collaborator

What

Adds hermes dashboard register — a CLI command that registers this install as a self-hosted dashboard with the user's Nous Portal account and writes the resulting OAuth client ID into ~/.hermes/.env.

This is the CLI half of a two-lane feature. The NAS half (the portal endpoint it calls) is NousResearch/nous-account-service#324 and must merge + deploy first.

Why

Today a self-hosting user who wants Nous OAuth on their dashboard has to: open portal.nousresearch.com/local-dashboards in a browser → click register → copy the agent:{id} client ID → paste it into .env by hand. This command does that round trip from the terminal.

How it works

hermes dashboard register [--name NAME] [--redirect-uri https://…/auth/callback] [--portal-url URL]
  1. Resolves a fresh Nous access token from auth.json (reuses resolve_nous_access_token, which auto-refreshes). Fast-fails with a hermes setup hint when not logged in.
  2. POSTs to {portal}/api/oauth/self-hosted-client (the fix: key priority based on active endpoint, not fixed order #324 endpoint).
  3. Writes HERMES_DASHBOARD_OAUTH_CLIENT_ID into ~/.hermes/.env idempotently (via the existing save_env_value).
  4. Prints a hint that the OAuth gate only engages on a non-loopback bind (otherwise a localhost dashboard stays unauthenticated — by design).

Details:

  • Docker-style auto-naming (adjective_noun, e.g. dreamy_tesla); --name overrides. No uniqueness constraint server-side (row id is the key), so no collision retry.
  • --redirect-uri for users exposing a public HTTPS dashboard — forwarded to the portal's existing validateCustomRedirectUri.
  • --portal-url / HERMES_DASHBOARD_PORTAL_URL override the request target (precedence: flag > env > stored login portal > prod default). The token must be valid at the overridden portal. Persists a non-default portal into .env so the dashboard's gate talks to the same portal at serve time.
  • Refuses in managed/hosted installs — the orchestrator (NAS) stamps the client ID into the container env there; save_env_value refuses anyway.
  • Nested register subparser leaves bare hermes dashboard unchanged.

Tests

  • 12 unit tests: name gen, not-logged-in fast-fail, managed refusal, POST shape, env writes, custom redirect URI, portal-URL override precedence, 401/403 error mapping.
  • Existing dashboard lifecycle tests still green (no regression from the nested subparser).

Live E2E (verified)

Run against the #324 Vercel preview build with a real token:

  • CLI → preview /api/oauth/self-hosted-client → returned a real agent:{cuid} client_id → written to .env. Full chain (auth → org resolution → row creation → env write) confirmed end-to-end, not just mocked.

Lane / review

Touches hermes_cli/main.py, so this needs review (not Docker-lane). Do not merge before #324 is deployed — the endpoint must exist.

…ient

Adds a CLI command that registers this install as a self-hosted dashboard
with the user's Nous Portal account, automating the manual browser flow on
/local-dashboards.

- New hermes_cli/dashboard_register.py: resolves a fresh Nous access token
  from auth.json (fast-fails with a `hermes setup` hint when not logged in),
  POSTs to {portal}/api/oauth/self-hosted-client, and writes
  HERMES_DASHBOARD_OAUTH_CLIENT_ID into ~/.hermes/.env idempotently.
- Docker-style adjective_noun auto-naming; --name and --redirect-uri overrides.
- Persists HERMES_DASHBOARD_PORTAL_URL only when non-default and unset (so a
  Vercel preview / staging portal sticks, prod default stays implicit).
- Refuses in managed/hosted installs (the orchestrator stamps the client_id).
- Post-register hint explains the OAuth gate only engages on a non-loopback bind.
- Nested 'register' subparser leaves bare `hermes dashboard` unchanged.
- 9 unit tests (name gen, fast-fails, POST shape, env writes, redirect URI,
  portal-URL persistence, 401/403 mapping); dashboard lifecycle tests still green.

Depends on NousResearch/nous-account-service#324 (the portal endpoint).
…ride in register

The register command resolved the portal base URL purely from the stored
login, ignoring any override. That meant `HERMES_DASHBOARD_PORTAL_URL` (and
the absence of any flag) gave no way to point registration at a staging or
preview portal — the request always hit the login's portal, returning 404
against a branch that wasn't deployed there.

- _resolve_portal_base_url now takes an optional override (precedence:
  override > stored login portal > prod default).
- New --portal-url flag; falls back to HERMES_DASHBOARD_PORTAL_URL env.
- Documents that the access token must be valid at the overridden portal
  (it's minted by whoever you logged into).
- 3 new tests for override precedence.

Verified live against the PR #324 Vercel preview: CLI -> preview endpoint ->
real agent:{id} client_id written to .env.
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: feat/dashboard-register vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9783 on HEAD, 9781 on base (🆕 +2)

🆕 New issues (2):

Rule Count
invalid-argument-type 1
unresolved-import 1
First entries
tests/hermes_cli/test_dashboard_register.py:194: [invalid-argument-type] invalid-argument-type: Argument to `HTTPError.__init__` is incorrect: Expected `Message[str, str]`, found `None`
tests/hermes_cli/test_dashboard_register.py:24: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`

✅ Fixed issues: none

Unchanged: 5074 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard area/auth Authentication, OAuth, credential pools P3 Low — cosmetic, nice to have labels Jun 4, 2026
@teknium1

teknium1 commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Merged via PR #38802 — your two commits were cherry-picked onto current main with your authorship preserved in git log (commits bb291b6 + c2ca3f0). Thanks Ben! #38802

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants