fix(server): make Workspace sessions work against a cookie-gated dashboard#692
Open
SherubabaFBC wants to merge 1 commit into
Open
fix(server): make Workspace sessions work against a cookie-gated dashboard#692SherubabaFBC wants to merge 1 commit into
SherubabaFBC wants to merge 1 commit into
Conversation
…board
On remote/Tailscale deployments the dashboard runs behind interactive cookie
login. `dashboard.available` came from the public `/api/status` probe, so the
session adapters routed dashboard-first and failed with
`401 {"reason":"no_cookie"}` — the fork's only dashboard auth was the removed
inline session-token scrape. Separately, the gateway fallback returned
`resp.items` for the OpenAI-shape `{object:"list", data:[...]}` body, crashing
callers with `.map` on undefined.
- capabilities: split `dashboard.available` (reachable) from
`dashboard.authenticated` (auth-gated endpoint probe); dashboard-backed
composites require authenticated, with the legacy gateway probes as fallback
- claude-dashboard-api: typed `DashboardAuthError` on 401/403
- claude-api: `sessionCall()` routes dashboard-first only when authenticated,
degrades via `markDashboardUnauthenticated()` on mid-flight 401 and falls back
to the gateway; `asArray()` normalizes sessions/items/data so list adapters
never return undefined; applied to all eight session adapters
- gateway-capabilities: `dashboardLogin()` authenticates via the built-in
`basic` provider (POST `/auth/password-login` -> session cookie), reused and
refreshed on 401, with a failure cooldown; credentials from
`HERMES_DASHBOARD_USERNAME`/`HERMES_DASHBOARD_PASSWORD` (unset = legacy behavior)
- tests: reachable-vs-authenticated split, cookie login success/reuse/reject,
gateway fallback, and response-shape normalization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On remote deployments (Docker / Tailscale) the Hermes dashboard runs behind interactive cookie login. Workspace's
dashboard.availablecapability comes from the public/api/statusprobe, so it'strueeven when the dashboard's session APIs are cookie-gated. All eight session adapters route dashboard-first on that flag, so the Sessions tab fails with:The fork's only dashboard-auth path was the inline session-token scrape, which upstream Hermes removed — so it always yields nothing. Separately, the gateway fallback returned
resp.itemsfor the OpenAI-compatible{object:"list", data:[...]}shape, crashing callers withCannot read properties of undefined (reading 'map').Fix
dashboard.available(reachable) fromdashboard.authenticated— the latter probed againstGET /api/sessions?limit=1throughdashboardFetch. Dashboard-backed composites (sessions/skills/config/jobs, mcpFallback) now requireauthenticated, with the legacy gateway probes as fallback.dashboardLogin()): authenticate via the built-inbasicprovider —POST /auth/password-login-> session cookie — reused and refreshed on 401, with a failure cooldown to avoid lockout. Credentials viaHERMES_DASHBOARD_USERNAME/HERMES_DASHBOARD_PASSWORD; unset preserves the legacy behavior.DashboardAuthError(typed) on 401/403;sessionCall()routes dashboard-first only when authenticated, degrades viamarkDashboardUnauthenticated()on a mid-flight 401 and falls back to the gateway;asArray()normalizessessions/items/dataso list adapters never returnundefined. Applied to all eight session adapters.Not in scope
~50 other
dashboard.availableconsumers insrc/routes/api/*share the reachable-vs-usable assumption; left unchanged here to keep the diff focused — they behave exactly as before.Testing
npx tsc --noEmit: adds 0 new errors (identical count with and without this change).vitest: 34 tests covering the split, cookie login (success/reuse/reject), gateway fallback, and shape normalization — all pass.