diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-15 02:16:39 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-15 02:21:01 +0200 |
| commit | 73ad8e4eb566fe682107fa7e50ef624591199e99 (patch) | |
| tree | ff0017d014d46d8835487c080dca55c6def7fd6b /packages/meshbay-hub/src/meshbay_hub/hub_settings.py | |
| parent | bdefcd025604f2c3009fe5e0cc01213c2ba62a6a (diff) | |
| download | meshbay-73ad8e4eb566fe682107fa7e50ef624591199e99.tar.gz | |
feat(hub): session lifetime is an admin setting, and a browser signs out when idle
Browser idle sign-out (media playback counts as activity; not the desktop app),
refresh idle window and maximum session length, in hours. Sign-out now revokes
on the hub, and the profile has "sign out everywhere".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XuNrwLf5EFWCMHzfoEvnpm
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/hub_settings.py')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/hub_settings.py | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/hub_settings.py b/packages/meshbay-hub/src/meshbay_hub/hub_settings.py index 1dcff84..c397f58 100644 --- a/packages/meshbay-hub/src/meshbay_hub/hub_settings.py +++ b/packages/meshbay-hub/src/meshbay_hub/hub_settings.py @@ -116,6 +116,46 @@ async def login_limits(db: AsyncSession) -> dict[str, int]: for k in LOGIN_KEYS} +# ── Session lifetime ───────────────────────────────────────────────────────── +# +# `browser_idle_hours`: a browser tab signs itself out after this long with no +# input and nothing playing (`static/idle.js`). The hub cannot measure that — it +# hears a renewal from any open tab, attended or not — so the page does, and +# reads the number from `/v1/hub/info`. The desktop application is exempt: it is +# its owner's machine and signs back in with its device key. +# +# `refresh_idle_hours`: a refresh token unused for this long stops renewing. The +# hub's own backstop, for a token that left the browser it was issued to. +# +# `max_hours`: no session renews past this since its sign-in, used or not. + +SESSION_KEYS = ("browser_idle_hours", "refresh_idle_hours", "max_hours") + +SESSION_DEFAULTS: dict[str, int] = { + "browser_idle_hours": 1, + "refresh_idle_hours": 24, + "max_hours": 720, +} + +SESSION_BOUNDS: dict[str, tuple[int, int]] = { + "browser_idle_hours": (1, 168), # a week + "refresh_idle_hours": (1, 720), # 30 days + "max_hours": (1, 8_760), # a year +} + + +def clamp_session_value(key: str, value: int) -> int: + low, high = SESSION_BOUNDS[key] + return max(low, min(high, int(value))) + + +async def session_limits(db: AsyncSession) -> dict[str, int]: + """The three session numbers, stored value or built-in default.""" + return {k: clamp_session_value( + k, await get_int(db, f"session.{k}", SESSION_DEFAULTS[k])) + for k in SESSION_KEYS} + + async def get_raw(db: AsyncSession, key: str) -> str | None: row = await db.get(HubSetting, key) return row.value if row else None |