Database lock (the reported 0.10.0 regression):
- tauri-plugin-sql loads SQLite through a default multi-connection sqlx pool
(Pool::connect => max_connections = 10) and exposes no JS transaction
primitive. BEGIN and COMMIT issued as separate db.execute calls could land on
different pooled connections, stranding an open write transaction on an idle
connection — a permanent write lock until app restart. Triggered when the
Bilan page's concurrent reads interleaved with an in-flight snapshot save.
- Fix: funnel every db operation through one FIFO lock in db.ts; withTransaction
holds it across the whole BEGIN..COMMIT so a transaction's statements never
span connections (and the saves become genuinely atomic). A reentrancy guard
lets nested getDb() calls run directly instead of deadlocking. Applied to all
5 transaction sites (saveSnapshotAtomic, upsertSnapshotLines,
proposeStarterAccounts, applyKeywordWithReassignment, applyMigration) via
in-place helper extraction. New db.test.ts covers serialization,
cross-transaction non-interleaving, reentrancy, and lock release on error.
Log console (Settings -> Systems -> Journaux):
- getLogs returned the same mutated array reference, so useSyncExternalStore
(identity comparison) never re-rendered on a new log -> the console never
updated live. getLogs now returns an immutable snapshot rebuilt on each
mutation (stable between mutations, new identity after each).
- Add logInfo/logWarn/logError app-logging API and instrument the snapshot save
(info on success, error on failure) so DB issues surface in the console.
tsc + 635 vitest + vite build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>