portal: default sessions to 7 days rolling, 30 days absolute - #1025
Merged
Conversation
The portal's own cookie was the only session a browser held once the built-in email auth broker replaced an upstream identity provider, so the 8-hour rolling / 24-hour absolute defaults meant a fresh emailed sign-in link nearly every day. The rolling default is now 604800 s (7 days) and the absolute cap floors at 2592000 s (30 days); the renewal point stays at half the rolling TTL. PORTAL_SESSION_TTL_S and PORTAL_SESSION_MAX_TTL_S still override both. The Fly templates pinned PORTAL_SESSION_TTL_S=28800 into every derived machine env, which would have silently kept the old lifetime on those deployments; the pin is removed so the code default governs and operators set the knob through the deployment config's env map when they want a different value. Tests that exercised sliding renewal against the implicit default now pin their own TTL, and the boot-check test that probes a TTL above the default cap uses a value above the new cap.
Review noted that after the renewal tests pinned their own TTL, nothing would fail if the 7-day default silently reverted. The local-auth-bypass login test runs with PORTAL_SESSION_TTL_S unset, so it now checks the minted cookie's Max-Age against the default.
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.
What changed
The portal's default browser-session lifetimes go up.
PORTAL_SESSION_TTL_S(rolling; renewed on activity after half elapses)28800(8 h)604800(7 d)PORTAL_SESSION_MAX_TTL_Sdefault (absolute cap from authentication)max(86400, TTL)(24 h)max(2592000, TTL)(30 d)floor(TTL / 2)Both env vars still override the defaults exactly as before, and boot still refuses a max below the rolling TTL.
Why
With the built-in email auth broker there is no upstream identity-provider session behind the portal cookie, so every portal expiry costs the user a fresh emailed sign-in link. At 8 h / 24 h that is a link nearly every day, which is too aggressive for a default. Seven days rolling with a 30-day hard cap keeps the absolute bound while making the common case (daily use) stay signed in.
Every instance, not just the constant
plugins/portal/src/index.ts— the two defaults.deploy/portal/fly.tomlandcli/templates/fly/portal.toml— both templates pinnedPORTAL_SESSION_TTL_S = "28800"into the[env]block, and the CLI copies that block verbatim into every derived Fly machine env. Left in place, the old lifetime would have survived on every Fly deployment regardless of the code default. The pin is removed so the code default governs; operators who want a different value setenv.portal.PORTAL_SESSION_TTL_Sin their deployment config, which already flows into the derived toml.plugins/portal/README.md— the two places that documented 8 h / 24 h / "one day".plugins/portal/test/router.test.ts,plugins/portal/test/playground.test.ts— the sliding-renewal tests aged a cookie past 4 h assuming the implicit 8 h default; they now pinPORTAL_SESSION_TTL_Sthemselves and derive their fixtures from it, so they test the renewal mechanism rather than whichever default is current.plugins/portal/test/local-auth-bypass.test.ts— runs with the TTL unset, so it now asserts the minted cookie'sMax-Age=604800; a silent revert of the default fails a test.plugins/portal/test/entry.test.ts— the boot check that probes "TTL above the default max cap still boots" used 604800, which is no longer above the cap; it now uses 5184000.Unrelated
86400/28800occurrences (favicon cache max-age, playground mint window, turn wall-clock bounds, OAuth token fixtures, microvm durations) were reviewed and left alone.Trade-offs surfaced in review (unchanged here, flagged for the maintainer)
OIDC_ALLOWED_EMAILS/ domain) is checked only at sign-in, so removing someone now leaves an existing session valid for up to 7 days rolling / 30 days absolute instead of 8 h / 24 h. Re-checking the rule at renewal would close that, but the session subject is not always an email (OIDC_PRINCIPAL_CLAIM=sub, Slack team pins, playground guests), so it is left as a follow-up rather than folded in.Verification
plugins/portal:npm run typecheckclean,npm test124/124.cli:npm run typecheckclean,npm test539/539 (includes the derive-byte-for-byte check against the checked-in Fly tomls).prettier --check,eslint,oxlint --deny-warningsclean on the touched paths.