Construire un client de base de données desktop en 2025 signifie choisir un runtime. Electron domine le segment : VS Code, Slack, 1Password le prouvent. Mais Electron embarque Chromium et Node.js dans chaque binaire, ce qui se paye en mémoire et en taille dès le premier lancement. QoreDB a pris un parti différent, celui de Tauri 2.
La prémisse est simple : déléguer le rendu à la WebView native du système d'exploitation plutôt que d'en embarquer une. Ce qui suit explique ce que ce choix implique concrètement dans l'architecture de QoreDB.
La WebView native : un binaire léger, une dépendance OS
Tauri ne bundle pas Chromium. Il utilise ce que l'OS fournit : WKWebView sur macOS, WebView2 sur Windows, WebKitGTK sur Linux. Le résultat sur la taille du binaire est immédiat : un binaire QoreDB en release fait quelques mégaoctets, là où un équivalent Electron pèse facilement 100 à 200 MB.
Cette légèreté vient avec une contrepartie : le moteur de rendu n'est pas contrôlé par l'application. Sur Linux par exemple, WebKitGTK 2.42+ avec certains pilotes GPU (notamment AMD/Radeon) causait une consommation mémoire vidéo non bornée, pouvant geler la machine. La correction dans main.rs est directe : désactiver le renderer DMA-BUF via la variable d'environnement WEBKIT_DISABLE_DMABUF_RENDERER avant toute initialisation WebKit. C'est le genre d'adaptation de plateforme qu'Electron, avec son Chromium figé, ne requiert pas.
L'IPC Tauri : le contrat entre React et Rust
Le frontend React et le backend Rust ne partagent pas de mémoire. Leur seul canal de communication est l'IPC de Tauri, exposé côté JavaScript via invoke de @tauri-apps/api/core. Côté Rust, chaque point d'entrée est une fonction annotée #[tauri::command]. Il n'y a pas de découverte automatique : chaque commande doit être listée explicitement dans le builder via tauri::generate_handler![].
Pour QoreDB, cela représente plusieurs dizaines de commandes, organisées par domaine : connexions, requêtes, vault, export, intercepteur, snapshots, licences, fédération. Cette liste explicite est utile : elle forme un contrat de surface clairement visible entre les deux couches. Une commande non enregistrée échoue silencieusement côté JS - c'est une incitation à maintenir le registre à jour.
La sérialisation est assurée par Serde. Les types Rust marqués #[derive(Serialize, Deserialize)] traversent le pont en JSON automatiquement. Les erreurs retournées comme Result<T, E> sont reçues côté TypeScript comme des rejets de Promise, avec le message sérialisé. Les bindings dans src/lib/tauri.ts encapsulent chaque appel avec ses types TypeScript : vérification statique de bout en bout.
La gestion d'état partagé entre les commandes
Tauri expose un système de managed state qui permet d'injecter des objets partagés dans les handlers de commandes. Dans QoreDB, l'état global est encapsulé dans AppState - un struct qui regroupe le DriverRegistry, le SessionManager, le VaultLock, la SafetyPolicy, l'InterceptorPipeline, et une dizaine d'autres composants. L'ensemble est wrappé dans Arc<Mutex<AppState>> et enregistré au démarrage via .manage().
La granularité du verrou mérite attention : un Mutex global sur tout l'état crée une sérialisation potentielle si plusieurs requêtes arrivent en parallèle. Dans la pratique, les drivers DB gèrent leur propre concurrence via des pools de connexions (SQLx pour PostgreSQL, MySQL, SQLite ; bb8 pour SQL Server). Le verrou global n'est tenu que le temps d'accéder aux composants partagés, pas pendant l'exécution effective de la requête.
Les plugins et le mécanisme de mise à jour
Tauri 2 a déplacé plusieurs fonctionnalités historiquement intégrées vers des plugins optionnels. QoreDB en utilise cinq : tauri-plugin-dialog pour les boîtes de dialogue natives, tauri-plugin-fs pour l'accès au système de fichiers, tauri-plugin-opener pour ouvrir des URLs dans le navigateur système, tauri-plugin-updater pour les mises à jour automatiques, et tauri-plugin-process pour la gestion du processus. Cette modularité réduit la surface d'attaque : seules les capacités explicitement déclarées sont disponibles.
Le mécanisme de mise à jour mérite une mention particulière. tauri-plugin-updater interroge un endpoint de release sur GitHub, puis vérifie une signature minisign sur l'artefact avant de l'appliquer. Aucune mise à jour ne s'installe sans vérification d'intégrité cryptographique. La clé publique est embarquée dans la configuration de l'application, ce qui rend une mise à jour forgée par un tiers impossible sans compromission de la clé privée.
La sécurité par le CSP et le modèle de processus
Tauri configure une Content Security Policy sur la WebView. Pour QoreDB, aucun script externe ne peut s'exécuter (script-src 'self'), les connexions réseau sont limitées aux endpoints connus (IPC local, PostHog pour la télémétrie anonyme), et les images externes sont bloquées par défaut. Ce modèle vient du fait que le frontend React tourne dans une WebView : sans contraintes, une injection XSS pourrait déclencher des appels IPC vers des commandes Rust sensibles.
L'autre point structurel est que le backend Rust n'expose pas de serveur HTTP. La communication passe uniquement par le canal ipc:// interne à Tauri. Pas de port ouvert, pas de surface d'attaque depuis d'autres processus locaux ou depuis le réseau.
Choisir Tauri 2 pour QoreDB, c'est choisir un runtime minimal, cohérent avec l'approche local-first : aucune donnée en transit, aucun service cloud requis, un binaire signé et vérifié. L'IPC fortement typé, le managed state partagé entre commandes Rust, et le modèle de plugins discrets donnent une base solide pour un outil desktop. La dépendance à la WebView système implique quelques adaptations de plateforme, mais c'est un compromis acceptable pour garder le binaire léger et l'architecture simple.
Restez informé des nouveautés
Rejoignez notre newsletter pour recevoir les mises à jour majeures, les nouveaux drivers et nos coulisses techniques.

