Skip to content

docs(dashboard): correct the stale session-storage description of sign-in - #451

Merged
njbrake merged 1 commit into
mainfrom
docs/dashboard-session-cookie
Jul 30, 2026
Merged

docs(dashboard): correct the stale session-storage description of sign-in#451
njbrake merged 1 commit into
mainfrom
docs/dashboard-session-cookie

Conversation

@njbrake

@njbrake njbrake commented Jul 30, 2026

Copy link
Copy Markdown
Member

Description

Split out of #450, where reviewing a nearby change turned this up.

The dashboard guide still described the pre-cookie sign-in, and both halves of what it said are now backwards:

The guide said What actually happens
The master key "is held only in this browser tab's session storage" The key is POSTed once to /v1/auth/session and exchanged for an HttpOnly cookie. The browser never stores the key; only a non-secret otari.dashboard.hasSession marker lands in localStorage, so the app can render signed-in without probing the server first.
It "does not persist across tabs or survive closing the tab" The cookie is persistent, with a dashboard_session_ttl_hours lifetime (168 hours by default), and sessions are rows in dashboard_sessions, so a sign-in deliberately survives closing the tab and restarting the gateway.

Three places said it, and all three are corrected: the two-key table's "Where it lives" row, first-run step 4, and the security note. The security note is retitled "A session cookie, not a stored key" and now records the cookie's actual attributes (HttpOnly, SameSite=Strict, Secure when the request arrives over HTTPS) along with what sign-out revokes and the fact that rotating the master key logs other browsers out.

Checked against the implementation rather than the old prose: dashboard_session_service.py:142 for the cookie attributes, core/config.py:207 for the 168-hour default, web/src/auth/AuthContext.tsx:12 for what the browser actually retains, and api/routes/settings.py:412 for the rotation behavior. Swept the repo for the same claim elsewhere; the only other hit is web/src/components/Login.test.tsx:49, a test asserting the key is not in session storage, which agrees with the corrected text.

The guide is bundled into the dashboard (DocsPage imports it with ?raw), so the committed bundle is rebuilt alongside it. That means this PR and #450 both touch the built bundle: whichever lands second will need a rebase and a rebuild.

PR Type

  • New Feature
  • Bug Fix
  • Refactor
  • Documentation
  • Infrastructure / CI

Relevant issues

None filed. Noticed while reviewing #450.

Checklist

  • I understand the code I am submitting.
  • I have added or updated tests that cover my change (tests/unit, tests/integration). Documentation only, so no behavior to test; the existing suites and the bundle staleness check pass.
  • I ran the Definition of Done checks locally (make lint, make typecheck, make test).
  • Documentation was updated where necessary.
  • If the API contract changed, I regenerated the OpenAPI spec (uv run python scripts/generate_openapi.py). No API change.

AI Usage

  • No AI was used.
  • AI was used for drafting/refactoring.
  • This is fully AI-generated.

AI Model/Tool used:

Claude Code (Opus 5)

Any additional AI details you'd like to share:

Claude spotted the stale text while reviewing #450, verified the current behavior against the source files cited above, and wrote the correction and this description. The reasoning and decisions are @njbrake's.

  • I am an AI Agent filling out this form (check box if true)

Summary

  • Updated dashboard documentation to accurately describe cookie-based sign-in, session persistence, revocation, and security guidance.
  • Clarified master-key handling and browser storage behavior.
  • Rebuilt the committed dashboard bundle to include the updated documentation.

Benefits

  • Gives users accurate guidance about dashboard sessions and security.
  • Explains how to revoke sessions and protect access on shared machines.

@njbrake
njbrake temporarily deployed to integration-tests July 30, 2026 01:20 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@njbrake, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 28e125d3-7157-4343-b5b0-2dc391d81142

📥 Commits

Reviewing files that changed from the base of the PR and between f87cd2c and 84a7c8e.

📒 Files selected for processing (18)
  • docs/dashboard.md
  • src/gateway/static/dashboard/assets/ActivityPage-BngVFI4f.js
  • src/gateway/static/dashboard/assets/AliasesPage-0BMZtDwo.js
  • src/gateway/static/dashboard/assets/BudgetsPage-DSFlTi1s.js
  • src/gateway/static/dashboard/assets/ConfirmDialog-BFS2k4X_.js
  • src/gateway/static/dashboard/assets/DocsPage-DneryjqV.js
  • src/gateway/static/dashboard/assets/KeysPage-C0dFnjAw.js
  • src/gateway/static/dashboard/assets/ModelScopeControl-hWii6vSv.js
  • src/gateway/static/dashboard/assets/ModelsPage-CDwjz2Xn.js
  • src/gateway/static/dashboard/assets/OverviewPage-D2MB34d0.js
  • src/gateway/static/dashboard/assets/ProvidersPage-Los10ECT.js
  • src/gateway/static/dashboard/assets/SettingsPage-DJbI5U1N.js
  • src/gateway/static/dashboard/assets/TablePagination-BtDO5gaH.js
  • src/gateway/static/dashboard/assets/ToolsGuardrailsPage-BuyJANrn.js
  • src/gateway/static/dashboard/assets/UsagePage-D99w-NDh.js
  • src/gateway/static/dashboard/assets/UsersPage-m0ebv2w3.js
  • src/gateway/static/dashboard/assets/index-BP-wLuMr.js
  • src/gateway/static/dashboard/index.html

Walkthrough

The dashboard guide now documents master-key exchange into cookie-backed sessions. Generated dashboard assets were rebuilt with updated hashed chunk references, a new bundled DocsPage, and an updated application entrypoint.

Changes

Dashboard documentation and bundle refresh

Layer / File(s) Summary
Session documentation and DocsPage bundle
docs/dashboard.md, src/gateway/static/dashboard/assets/DocsPage-DZcl3jJe.js
The guide documents runtime secret-key handling and HttpOnly session behavior; DocsPage renders the embedded markdown with customized links, tables, and code blocks.
Dashboard bundle entrypoint
src/gateway/static/dashboard/index.html, src/gateway/static/dashboard/assets/index-Ca6Q-liL.js
The entrypoint and Vite dependency map reference the rebuilt dashboard chunks.
Rebuilt dashboard asset imports
src/gateway/static/dashboard/assets/*
Generated page and shared-component bundles reference updated hashed dependencies while preserving their existing component logic and exports.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: khaledosman

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is relevant, but it does not use the required Conventional Commit prefix. Change it to a Conventional Commit title such as docs: correct the stale session-storage description of sign-in.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description follows the repository template and includes the required sections, checklist, and AI usage details.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/dashboard-session-cookie
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch docs/dashboard-session-cookie

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the bundled admin-dashboard guide (docs/dashboard.md) so it accurately reflects the current dashboard sign-in behavior (master key exchanged once for an HttpOnly session cookie with a configurable TTL, plus a non-secret localStorage marker), and rebuilds the committed dashboard bundle so the in-app docs match.

Changes:

  • Corrects the dashboard guide’s “where the master key lives” and sign-in persistence descriptions to match the cookie-based session implementation.
  • Updates the security note to describe the actual session cookie attributes and revocation behavior (sign-out and master-key rotation).
  • Rebuilds and commits the dashboard static bundle so the shipped UI includes the updated guide.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/gateway/static/dashboard/index.html Updates the built dashboard entrypoint to reference the newly built hashed JS bundle.
src/gateway/static/dashboard/assets/UsersPage-7LqE-NgO.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/UsagePage-ERarDcgx.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/ToolsGuardrailsPage-CS19b3Ji.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/TablePagination-Gcdv1tY0.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/SettingsPage-9ZoEiKHk.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/ProvidersPage-CuxkpteE.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/OverviewPage-DQPI4_pY.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/ModelScopeControl-DZ334hCb.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/KeysPage-9JGzsx7l.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/ConfirmDialog-C27eWF-P.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/BudgetsPage-DPDuyKZo.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/AliasesPage-B8ZSDZeI.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
src/gateway/static/dashboard/assets/ActivityPage-Bh1uAn4D.js Rebuilt bundle artifact reflecting the new main bundle hash / imports.
docs/dashboard.md Corrects the sign-in/session documentation to reflect cookie-based sessions and their TTL/revocation behavior.

@khaledosman khaledosman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked every claim against the implementation and they hold: dashboard_session_service.py:157-163 sets httponly=True, samesite="strict", and secure from the request scheme; core/config.py:207 defaults dashboard_session_ttl_hours to 168. The old text was wrong in both directions and the correction is accurate.

Two optional wording notes inline; neither blocks.

Heads up on landing order: this, #450, and #449 all edit docs/dashboard.md and therefore rewrite the same hashed bundle assets. Whoever lands second needs a rebase plus npm --prefix web run build or the staleness check fails. This one is docs-only and cheapest to rebase, so it is the natural one to land first.

🤖 Generated with Claude Code

Comment thread docs/dashboard.md Outdated
Comment thread docs/dashboard.md
…n-in

The guide still described the pre-cookie sign-in: master key held in the tab's
session storage, gone when the tab closes. Sign-in has since become an exchange
for an HttpOnly session cookie (dashboard_session_ttl_hours, a week by default),
so the key is never kept in the browser at all and the session deliberately does
outlive the tab. Readers were being told the opposite of both halves.

Correct the three places that said it: the two-key table, the first-run sign-in
step, and the security note, which now also records the cookie's attributes and
that rotating the master key logs other browsers out.

Surviving a gateway restart is qualified rather than claimed outright, since
sessions are rows in the gateway's database and a container on the default
sqlite:///./otari.db with no mounted volume starts every run signed out. A second
security note covers what the correction otherwise removed: a session runs its
full TTL with no idle timeout (is_valid_dashboard_session compares expires_at and
never extends it), so an unattended browser stays signed in, and the old wrong
text at least implied a tab close logged you out.

The guide is bundled into the dashboard (DocsPage imports it with ?raw), so the
committed bundle is rebuilt alongside it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@njbrake
njbrake force-pushed the docs/dashboard-session-cookie branch from f87cd2c to 84a7c8e Compare July 30, 2026 10:38
@njbrake
njbrake temporarily deployed to integration-tests July 30, 2026 10:39 — with GitHub Actions Inactive
@njbrake
njbrake merged commit f5836f5 into main Jul 30, 2026
7 checks passed
@njbrake
njbrake deleted the docs/dashboard-session-cookie branch July 30, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants