···33# See README for setup instructions
44WHISPER_SERVICE_URL=http://localhost:8000
5566-# Gemini API Key (optional)
77-# For cleaning transcripts - removes tags and improves grammar
88-# Get your key from: https://aistudio.google.com/app/apikey
99-# GEMINI_API_KEY=your_api_key_here
66+# LLM API Configuration (Required for VTT cleaning)
77+# Configure your LLM service endpoint and credentials
88+LLM_API_KEY=your_api_key_here
99+LLM_API_BASE_URL=https://api.openai.com/v1
1010+LLM_MODEL=gpt-4o-mini
1111+1212+# WebAuthn/Passkey Configuration (Production Only)
1313+# In development, these default to localhost values
1414+# Only needed when deploying to production
1515+1616+# Relying Party ID - your domain name
1717+# Must match the domain where your app is hosted
1818+# RP_ID=thistle.app
1919+2020+# Origin - full URL of your app
2121+# Must match exactly where users access your app
2222+# ORIGIN=https://thistle.app
···100100 CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
101101 `,
102102 },
103103+ {
104104+ version: 7,
105105+ name: "Add WebAuthn passkey support",
106106+ sql: `
107107+ CREATE TABLE IF NOT EXISTS passkeys (
108108+ id TEXT PRIMARY KEY,
109109+ user_id INTEGER NOT NULL,
110110+ credential_id TEXT NOT NULL UNIQUE,
111111+ public_key TEXT NOT NULL,
112112+ counter INTEGER NOT NULL DEFAULT 0,
113113+ transports TEXT,
114114+ name TEXT,
115115+ created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
116116+ last_used_at INTEGER,
117117+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
118118+ );
119119+120120+ CREATE INDEX IF NOT EXISTS idx_passkeys_user_id ON passkeys(user_id);
121121+ CREATE INDEX IF NOT EXISTS idx_passkeys_credential_id ON passkeys(credential_id);
122122+123123+ -- Make password optional for users who only use passkeys
124124+ CREATE TABLE users_new (
125125+ id INTEGER PRIMARY KEY AUTOINCREMENT,
126126+ email TEXT UNIQUE NOT NULL,
127127+ password_hash TEXT,
128128+ name TEXT,
129129+ avatar TEXT DEFAULT 'd',
130130+ created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
131131+ role TEXT NOT NULL DEFAULT 'user'
132132+ );
133133+134134+ INSERT INTO users_new SELECT * FROM users;
135135+ DROP TABLE users;
136136+ ALTER TABLE users_new RENAME TO users;
137137+138138+ CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
139139+ `,
140140+ },
103141];
104142105143function getCurrentVersion(): number {