hermes-agent/web/src/lib
Ben Barclay 7857d8737c feat(dashboard-auth): RFC 8252 native desktop sign-in (system browser + PKCE, no webview/cookies)
The Desktop app can now sign in to a gated gateway using the user's SYSTEM
browser and OAuth 2.0 for Native Apps (RFC 8252) instead of an embedded
Electron BrowserWindow, and authenticates with bearer tokens it holds itself
instead of relying on HttpOnly browser session cookies.

Why brokered: the upstream IDP (Nous Portal) binds client_id to the gateway
instance and only permits redirect_uris on the gateway's own origin, so a
desktop loopback redirect can't be a direct Portal client. The gateway
therefore acts as the authorization server TO the desktop and an OAuth client
TO the Portal, reusing the existing PKCE start_login/complete_login provider
path unchanged.

Server (Ben's dashboard-auth lane):
- native_flow.py: in-memory broker — binds the desktop's PKCE challenge to a
  completed Session, mints a single-use, short-TTL, PKCE-verified gateway
  authorization code. Constant-time compare, single-use (consumed before the
  PKCE check so a wrong verifier can't be retried), capacity-bounded.
- routes.py: GET /auth/native/authorize (starts the brokered PKCE login,
  loopback-only redirect_uri, S256-only), POST /auth/native/token (loopback
  code + verifier -> tokens in the JSON body, never Set-Cookie), POST
  /auth/native/refresh (desktop-held RT rotation). /auth/callback branches to
  mint a loopback code + 302 to 127.0.0.1 when a broker_state rides the PKCE
  cookie; the cookie/SPA path is untouched.
- middleware.py: the gate accepts Authorization: Bearer <access_token>,
  verified via the same verify_session provider stack (no cookie set/read),
  with the same "provider unreachable -> 503, not logout" semantics.
- web_server.py /api/status: advertise auth_flows (["cookie","native_pkce"])
  so clients can detect the capability; native_pkce only when a brokerable
  OAuth provider is registered.

Desktop (Ben's lane):
- native-oauth.ts: pure PKCE/capability/URL/callback/token helpers.
- native-oauth-login.ts: loopback-listener orchestration (system browser via
  openExternal, ephemeral 127.0.0.1 listener, state/PKCE verification), all
  I/O injected for testability.
- main.ts: capability-gated oauth-login IPC — native flow when advertised,
  automatic fallback to the existing embedded-webview cookie flow otherwise;
  tokens stored encrypted (safeStorage/OS keychain), REST + ws-ticket
  authenticated by bearer, transparent refresh, logout clears both shapes.

Tests: 18 server pytest (broker unit + full authorize->callback->token E2E +
cookieless bearer auth of a gated route + ws-ticket mint + capability
advertisement + refresh); desktop node --test/vitest for both pure modules
(PKCE, capability detection, callback CSRF, loopback round trip, timeout,
browser-open failure). Electron project typechecks clean.

Docs: website/docs/guides/desktop-native-signin.md.
2026-07-22 06:50:50 -07:00
..
api.test.ts fix(dashboard): support mobile OAuth login 2026-07-09 12:21:16 +05:30
api.ts feat(dashboard-auth): RFC 8252 native desktop sign-in (system browser + PKCE, no webview/cookies) 2026-07-22 06:50:50 -07:00
chat-activation.test.ts fix(dashboard): only open the chat PTY once the chat tab is active (#59551) 2026-07-18 00:50:13 -04:00
chat-activation.ts fix(dashboard): only open the chat PTY once the chat tab is active (#59551) 2026-07-18 00:50:13 -04:00
chat-sidebar-session-params.test.ts test: port JS/package.json invariant tests from Python to vitest 2026-07-15 17:24:12 -04:00
chat-title.test.ts fix dashboard chat session titles 2026-06-21 22:44:02 -07:00
chat-title.ts fix dashboard chat session titles 2026-06-21 22:44:02 -07:00
chatImagePaste.test.ts fix(web): paste/drop images into dashboard Chat via HERMES_HOME/images 2026-07-10 02:20:04 -05:00
chatImagePaste.ts fix(web): paste/drop images into dashboard Chat via HERMES_HOME/images 2026-07-10 02:20:04 -05:00
clipboard.test.ts fix(dashboard): support mobile OAuth login 2026-07-09 12:21:16 +05:30
clipboard.ts fix(dashboard): support mobile OAuth login 2026-07-09 12:21:16 +05:30
cron-job.test.ts feat(dashboard): expose cron job execution fields 2026-06-27 03:20:32 -07:00
cron-job.ts refactor(dashboard): tighten cron-job form helpers 2026-06-27 03:20:32 -07:00
dashboard-flags.ts feat(dashboard): always enable embedded chat; remove dashboard --tui flag 2026-06-04 03:03:35 -07:00
dashboard-modal-shell.test.ts fix(dashboard): opaque MoA presets modal (stop page bleed-through) (#67410) 2026-07-19 19:09:12 -04:00
dashboard-modal-shell.ts fix(dashboard): opaque MoA presets modal (stop page bleed-through) (#67410) 2026-07-19 19:09:12 -04:00
format.ts feat(web): add context window support to dashboard config 2026-04-13 22:04:35 -07:00
fuzzy.ts feat: fuzzy search for the model picker (WebUI + TUI) 2026-06-01 16:58:58 -07:00
gatewayClient.ts fix(docker): include apps/shared in dashboard image build 2026-06-28 21:43:56 -05:00
mcp-dashboard-oauth.test.ts fix(mcp): close hosted OAuth lifecycle gaps 2026-07-17 04:50:47 -07:00
mcp-dashboard-oauth.ts fix(mcp): close hosted OAuth lifecycle gaps 2026-07-17 04:50:47 -07:00
mcp-server-create.test.ts fix(dashboard): add MCP auth to profile builder (#65163) 2026-07-16 02:05:04 +05:30
mcp-server-create.ts fix(dashboard): add MCP auth to profile builder (#65163) 2026-07-16 02:05:04 +05:30
model-picker-filter.test.ts fix(dashboard): don't let a provider-name query hide the selected provider's models (#65374) (#65413) 2026-07-19 19:05:44 -04:00
model-picker-filter.ts fix(dashboard): don't let a provider-name query hide the selected provider's models (#65374) (#65413) 2026-07-19 19:05:44 -04:00
nested.ts feat: web UI dashboard for managing Hermes Agent (#8756) 2026-04-12 22:26:28 -07:00
pty-mobile-input.test.ts fix(dashboard): harden PTY reconnect race, wedged-connect recovery, IME guard 2026-07-09 13:50:17 +05:30
pty-mobile-input.ts fix(web): resolve all eslint errors, downgrade react-hooks v7 to warnings 2026-07-16 01:42:02 +05:30
pty-reconnect.test.ts fix(dashboard): harden PTY reconnect race, wedged-connect recovery, IME guard 2026-07-09 13:50:17 +05:30
pty-reconnect.ts fix(dashboard): harden PTY reconnect race, wedged-connect recovery, IME guard 2026-07-09 13:50:17 +05:30
reasoning-effort.test.ts feat(reasoning): add max and ultra effort levels (#62650) 2026-07-12 00:26:49 -07:00
reasoning-effort.ts feat(reasoning): add max and ultra effort levels (#62650) 2026-07-12 00:26:49 -07:00
resolve-page-title.ts fix(dashboard): UI polish — modals, layout, consistency, test fixes 2026-05-12 13:59:22 -04:00
schedule.test.ts feat(dashboard): expose cron job execution fields 2026-06-27 03:20:32 -07:00
schedule.ts feat(dashboard): expose cron job execution fields 2026-06-27 03:20:32 -07:00
session-import.test.ts feat(dashboard): add session import flow 2026-07-13 15:41:00 +05:30
session-import.ts feat(dashboard): add session import flow 2026-07-13 15:41:00 +05:30
session-refresh.test.ts fix(dashboard): refresh Sessions list in real time when new sessions are created 2026-06-19 17:26:11 +05:30
session-refresh.ts fix(dashboard): refresh Sessions list in real time when new sessions are created 2026-06-19 17:26:11 +05:30
slashExec.ts feat(web): add /api/pty WebSocket bridge to embed TUI in dashboard 2026-04-24 10:51:49 -04:00
utils.ts refactor(web): dashboard typography & contrast pass 2026-05-22 19:50:32 -07:00