aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/hub_settings.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-15 02:16:39 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-15 02:21:01 +0200
commit73ad8e4eb566fe682107fa7e50ef624591199e99 (patch)
treeff0017d014d46d8835487c080dca55c6def7fd6b /packages/meshbay-hub/src/meshbay_hub/hub_settings.py
parentbdefcd025604f2c3009fe5e0cc01213c2ba62a6a (diff)
downloadmeshbay-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.py40
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