Commit graph

2 commits

Author SHA1 Message Date
hermes-seaeye[bot]
bcc3396b25
fmt(js): npm run fix on merge (#69503)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-22 16:30:14 +00:00
Ben Barclay
49423f8084 fix(desktop-auth): make RFC 8252 native login work end-to-end at runtime
The native-app (RFC 8252) login passed its unit tests but failed in real
Electron runtime — the tests mocked the exact seams that were broken. Four
runtime defects, each proven against a live gated gateway:

1. Lockfile drift: apps/desktop declared @assistant-ui/react +
   @assistant-ui/react-streamdown but package-lock.json didn't place them, so
   `npm ci` (CI + every fresh checkout) failed to install them → Vite
   "Failed to resolve @assistant-ui/react". Reconcile the lockfile.

2. Double JSON encoding: postJsonNoAuth pre-JSON.stringify'd the body before
   fetchJson (which stringifies again), so /auth/native/token received a JSON
   string, not an object → gateway 422 "Input should be a valid dictionary" →
   native login silently fell back to the embedded webview.

3. Cookie-only liveness gate: buildRemoteConnection (and the Settings
   connected indicator) treated "signed in" as "has OAuth cookie". The native
   flow stores a bearer and sets no cookie, so a completed native login looped
   the UI into needsOauthLogin. Accept native token OR cookie.

4. Cookie-only REST path: the hermes:api handler routed oauth-mode REST through
   the cookie partition only. A cookieless native session → 401 no_cookie on
   every API call. Prefer the native bearer (with transparent refresh), else
   cookie — mirroring mintGatewayWsTicket, which was already bearer-aware.

The three decision points (2–4) are extracted into a pure
native-auth-decisions.ts with regression tests, since the mocked flow tests
could not catch them. Verified live: system-browser login → cookieless bearer
→ connected chat, no embedded webview.
2026-07-22 06:50:50 -07:00