Change to unlimited session persistence until explicitly locked

This commit is contained in:
russell@unturf.com 2026-01-23 09:53:12 -05:00
parent 9944d8f757
commit 5159355c98
2 changed files with 7 additions and 22 deletions

View file

@ -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.",

View file

@ -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) {