Skip to content

feat(web): keep users signed in for 7 days instead of 24 hours - #687

Merged
dash0-dev[bot] merged 1 commit into
mainfrom
feat/web-week-long-sign-in
Oct 11, 2026
Merged

dash0-dev[bot] merged 1 commit into
mainfrom
feat/web-week-long-sign-in

Conversation

@dash0-dev

@dash0-dev dash0-dev Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Dashboard users were signed out after 24 hours without a server-side session refresh, because the middleware capped the Supabase auth cookies at maxAge: 86400. This raises that window to 7 days. It still slides: every refresh re-issues the cookies, so anyone who opens the dashboard at least once a week stays signed in.

Changes

  • New packages/web/src/lib/auth/session-cookie.ts, dependency-free so it is edge-safe. It exports SESSION_MAX_AGE_SECONDS = 7 days and sessionCookieMaxAge(). Co-located spec included.
  • middleware.ts uses it instead of the inline 24 h constant.
  • The middleware now passes supabase-ssr's cookie deletions (value: "", maxAge: 0, written on sign-out and when a session cookie is re-chunked) through unchanged. Until now the override turned them into 24 h empty cookies; with a 7-day window they would have stayed in the browser for a week.

Context

  • The access token lifetime (jwt_expiry: 1 h hosted per the CI comment, 24 h in supabase/config.toml) is unchanged. The cookie only needs to outlive it so the refresh token is still there when it expires.
  • Not covered here: refreshes done by the browser client in an open tab write cookies with supabase-ssr's 400-day default. They never went through the middleware cap, so this PR doesn't change them.
  • If the hosted project has Time-box user sessions or Inactivity timeout set under Supabase Auth → Sessions, that setting still caps sessions server-side. It isn't in config.toml, so it can't be checked from the repo.
  • Docs: no user-facing doc or llms.txt section describes how long a sign-in lasts, so neither needed an update.
  • Verification: the new spec passes (4/4) and the new module typechecks in isolation. The full web typecheck/lint/test is left to CI. The repo's /polish and review-loop steps were not run.

The middleware capped the Supabase auth cookies at 24 hours, so a browser
that went a day without a server-side session refresh was signed out.
Raise the window to 7 days; it still slides with each refresh.

Also pass supabase-ssr's cookie deletions (maxAge 0) through unchanged.
The override previously turned them into 24-hour empty cookies, which a
7-day window would have stretched to a week.

Co-authored-by: dash0-dev[bot] <257284812+dash0-dev[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

The dashboard preview for this PR — redeployed on each push that changes the web app.

Project Deployment Actions Updated
lorekit Ready Ready Preview Oct 11, 2026 5:49am UTC

Preview always points at this PR's latest commit; Deployment is the immutable build of ac8ccf5. · Comment /web-preview to force a redeploy. · Workflow logs

@dash0-dev

dash0-dev Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

✅ No issues found

Raises the middleware's Supabase auth-cookie max-age from 24 h to 7 days and passes supabase-ssr's maxAge:0 deletions through unchanged. Checked against @supabase/ssr 0.6.1; nothing actionable found.

Checked: 3 of 3 changed files read · 2 of 2 dependent files traced · 4 possible issues → 0 confirmed → 0 posted

What this change reaches — 2 changed exports · 2 dependent files · 2 checked
flowchart LR
  subgraph pr["Changed in this PR"]
    s1["sessionCookieMaxAge<br/>added"]:::changed
    s2["SESSION_MAX_AGE_SECONDS<br/>added"]:::changed
  end
  s1c1["packages/web/src/middleware.ts<br/>✓ checked"]:::ok
  s1c2["packages/web/src/lib/auth/session-cookie.spec.ts<br/>✓ checked"]:::ok
  s2c1["packages/web/src/lib/auth/session-cookie.spec.ts<br/>✓ checked"]:::ok
  s1 --> s1c1
  s1 --> s1c2
  s2 --> s2c1
  classDef changed fill:#eef2ff,stroke:#6366f1,color:#1e1b4b
  classDef ok fill:#e7f6ec,stroke:#16a34a,color:#14532d
  classDef partial fill:#fef9c3,stroke:#ca8a04,color:#713f12
  classDef unknown fill:#f3f4f6,stroke:#9ca3af,stroke-dasharray:4 3,color:#374151
  classDef bad fill:#fde8e8,stroke:#dc2626,color:#7f1d1d
  classDef warn fill:#fff4e5,stroke:#d97706,color:#78350f
  classDef imports fill:#f8fafc,stroke:#64748b,stroke-dasharray:4 3,color:#1e293b
Loading
  • sessionCookieMaxAge (packages/web/src/lib/auth/session-cookie.ts) — added change · 2 consumer files · 2 verified unaffected
  • SESSION_MAX_AGE_SECONDS (packages/web/src/lib/auth/session-cookie.ts) — added change · 1 consumer file · 1 verified unaffected
Review details
Gate Status Details
Description vs. code ✅ Claims verified: ssr 0.6.1 400-day default, maxAge:0 deletions, jwt_expiry 86400 local / 3600 hosted.
Prior review feedback ✅ Earlier review comments are resolved.
Documentation ✅ JSDoc states the window, the jwt_expiry invariant and the deletion pass-through; PR body names the gaps.
Self-review signals ✅ No debug logs, leftover TODOs, or unreviewed stubs.
Code review ✅ The multi-lens review found no blocking issues.

Found

Quality — produced 4 → posted inline 0 · cleared 0 · carried forward 0 · deferred 0 · below-bar 0
Dropped — 2 below-bar
Optimality — ran — 0 proposals; alternative cookieOptions.maxAge rejected: @supabase/ssr 0.6.1 forces the 400-day default on set (cookies.js:168-172, 325-329)
Standards — ran — 2 docs, 59 bullets, 0 findings; process conflict surfaced: CLAUDE.md:189/215 steps (/polish, review-loop) disclosed as not run in PR body
Measurability — ran — quiet: gate 1 pass (web), gate 2 fail (no new action, operation, failure mode or perf claim)

Run

full · 65 lines in delta · tier deep · depth checkout
⚠️ no sub-agent dispatch available — the intent finder ran in-context with the other finders at effective thoroughness 0.95, instead of as its own sub-agent — 2 prepare-time anomalies (reviewer identity unknown (no --reviewer-login / PR_REVIEWER_LOGIN; /user 401s here) — relation defaulted to cross, +1 more)
Memories — 48 indexed · 0 used

Nothing to report — integrations (not activated), severity, 0 files skipped.

pr-reviewer · commit ac8ccf5 · full review · how these findings are produced · updated Oct 11, 2026 5:58am UTC

@dash0-dev
dash0-dev Bot marked this pull request as ready for review October 11, 2026 06:00
@dash0-dev
dash0-dev Bot requested a review from mthines as a code owner October 11, 2026 06:00
@dash0-dev
dash0-dev Bot merged commit dd991d3 into main Oct 11, 2026
18 checks passed
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.

1 participant