···204204 CREATE INDEX IF NOT EXISTS idx_subscriptions_customer_id ON subscriptions(customer_id);
205205 `,
206206 },
207207+ {
208208+ version: 7,
209209+ name: "Create ghost user for deleted accounts",
210210+ sql: `
211211+ -- Create a ghost user account for orphaned transcriptions
212212+ INSERT OR IGNORE INTO users (id, email, password_hash, name, avatar, role, created_at)
213213+ VALUES (0, 'ghosty@thistle.internal', NULL, 'Ghosty', '👻', 'user', strftime('%s', 'now'));
214214+ `,
215215+ },
207216];
208217209218function getCurrentVersion(): number {
+17
src/lib/auth.ts
···183183}
184184185185export async function deleteUser(userId: number): Promise<void> {
186186+ // Prevent deleting the ghost user
187187+ if (userId === 0) {
188188+ throw new Error("Cannot delete ghost user account");
189189+ }
190190+186191 // Get user's subscription if they have one
187192 const subscription = db
188193 .query<{ id: string }, [number]>(
···210215 }
211216 }
212217218218+ // Reassign class transcriptions to ghost user (id=0)
219219+ // Delete personal transcriptions (no class_id)
220220+ db.run(
221221+ "UPDATE transcriptions SET user_id = 0 WHERE user_id = ? AND class_id IS NOT NULL",
222222+ [userId],
223223+ );
224224+ db.run(
225225+ "DELETE FROM transcriptions WHERE user_id = ? AND class_id IS NULL",
226226+ [userId],
227227+ );
228228+229229+ // Delete user (CASCADE will handle sessions, passkeys, subscriptions, class_members)
213230 db.run("DELETE FROM users WHERE id = ?", [userId]);
214231}
215232