From 5159355c9822ee099ae68b8daf711ff7f173a30b Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Fri, 23 Jan 2026 09:53:12 -0500 Subject: [PATCH] Change to unlimited session persistence until explicitly locked --- public/src/languages/en.js | 2 +- public/src/vault.js | 27 ++++++--------------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/public/src/languages/en.js b/public/src/languages/en.js index 1a02ef7..455f676 100644 --- a/public/src/languages/en.js +++ b/public/src/languages/en.js @@ -140,7 +140,7 @@ export const en = { vaultWelcome: "Your settings (model, voice, API keys) are saved safely behind a password of your choice. This keeps them private on this device.", vaultWelcomeBack: "Welcome back! Enter your password to access your saved settings.", vaultCreateInfo: "Choose a password to protect your settings. Your preferences and API keys will be encrypted and stored locally.", - vaultSessionInfo: "You'll stay logged in for {days} days.", + vaultSessionInfo: "You'll stay logged in until you lock your settings.", vaultChangePassword: "Change Password", vaultDeleteVault: "Delete Settings", vaultDeleteConfirm: "Are you sure? This will remove all your saved settings from this device.", diff --git a/public/src/vault.js b/public/src/vault.js index 428735e..d044e66 100644 --- a/public/src/vault.js +++ b/public/src/vault.js @@ -3,6 +3,7 @@ * * All settings are encrypted with a user-chosen password using AES-256. * Session persistence allows staying unlocked across page navigations. + * Sessions persist indefinitely until the user explicitly locks. * * Requires CryptoJS library. * @@ -10,8 +11,8 @@ * 1. User creates vault with password (first time) * 2. Settings encrypted with password, stored in localStorage * 3. Session key derived and stored (encrypted) for auto-unlock - * 4. On page load, session key auto-unlocks if not expired - * 5. User can explicitly lock or session expires after TTL + * 4. On page load, session key auto-unlocks (persists until locked) + * 5. User can explicitly lock to end session */ const UncloseVault = { @@ -20,9 +21,6 @@ const UncloseVault = { SALT_KEY: 'uncloseai_device_salt', SESSION_KEY: 'uncloseai_session', - // Session TTL (7 days in milliseconds) - SESSION_TTL_MS: 7 * 24 * 60 * 60 * 1000, - // In-memory state _settings: null, _password: null, @@ -128,6 +126,7 @@ const UncloseVault = { /** * Create session for auto-unlock persistence * Stores the password encrypted with a random session key + * Session persists indefinitely until explicitly locked */ createSession(password) { if (!this.isAvailable()) return; @@ -139,11 +138,10 @@ const UncloseVault = { // Encrypt password with session key const encryptedPassword = CryptoJS.AES.encrypt(password, sessionKey).toString(); - // Store session data + // Store session data (no expiry - persists until locked) const sessionData = { key: sessionKey, data: encryptedPassword, - expires: Date.now() + this.SESSION_TTL_MS, created: Date.now() }; @@ -156,6 +154,7 @@ const UncloseVault = { /** * Try to restore session (auto-unlock) * Returns true if session was valid and vault unlocked + * Sessions persist indefinitely until explicitly locked */ tryRestoreSession() { if (!this.isAvailable()) return false; @@ -167,12 +166,6 @@ const UncloseVault = { const session = JSON.parse(sessionJson); - // Check expiry - if (Date.now() > session.expires) { - this.clearSession(); - return false; - } - // Decrypt password from session const bytes = CryptoJS.AES.decrypt(session.data, session.key); const password = bytes.toString(CryptoJS.enc.Utf8); @@ -186,9 +179,6 @@ const UncloseVault = { const result = this._unlockWithPassword(password, false); // Don't recreate session if (result.success) { - // Refresh session expiry on successful restore - session.expires = Date.now() + this.SESSION_TTL_MS; - localStorage.setItem(this.SESSION_KEY, JSON.stringify(session)); return true; } @@ -217,13 +207,8 @@ const UncloseVault = { if (!sessionJson) return null; const session = JSON.parse(sessionJson); - const now = Date.now(); - - if (now > session.expires) return null; return { - expiresAt: new Date(session.expires), - expiresIn: session.expires - now, createdAt: new Date(session.created) }; } catch (e) {