Serveur mode île (Island-Mode Server)
Un petit serveur Node s'exécute sur le site physique et maintient une réplication RxDB en direct de la tranche Firestore propre à ce site. Tant que la connexion Internet fonctionne, il reste invisible ; lorsque la connexion est perdue, les terminaux kiosk/personnel sur le LAN basculent vers lui et le site continue de prendre des commandes, de déplacer des stocks et de contrôler le matériel. À la reconnexion, le travail hors ligne est vidangé vers le cloud. L'idée directrice qui façonne tout : la synchronisation repose sur deux systèmes, pas un seul — la réplication RxDB au niveau document pour l'état, plus une vidange HTTP des événements métiers que le cloud doit appliquer avec sa propre logique (incréments de stock, ingestion d'audit). Aucun des deux ne suffit seul.
Quand l'utiliser
- Un site doit survivre à des coupures Internet avec des écritures réelles (réservations, stocks, contrôle matériel), pas seulement des lectures en cache.
- Les terminaux sont basés sur un navigateur (PWA/kiosk) et doivent basculer de manière transparente.
- Firestore est la source de vérité cloud et le reste.
Quand NE PAS l'utiliser
- Cache de lecture pur ou PWA qui n'a besoin que de la persistance hors ligne intégrée de Firestore — le SDK Firebase le fait déjà ; aucun serveur n'est nécessaire.
- Une base de données cloud différente (Supabase/Postgres) : le concept de niveau de réplication est transférable, mais chaque modèle ici est spécifique à Firestore.
- Synchronisation multi-maître entre sites pairs — cette conception est strictement en étoile, avec le cloud comme source de vérité et un conflit résolu par la dernière écriture.
Architecture
Internet
|
+--------+---------+
| Cloud (SSoT) | Firestore + API publique + marqueur d'état cron
+--------+---------+
| |
Réplication RxDB Vidange HTTP (reconnexion)
| |
+-+-------------+-+
| Serveur local | Node/NestJS + RxDB, LAN :443 via nginx TLS
+--------+--------+
|
LAN — PWA kiosk, PWA personnel, contrôleurs matériels
Faits critiques
- Chaque écriture cloud vers une collection répliquée DOIT ajouter le champ de point de contrôle (
serverTimestamp: FieldValue.serverTimestamp()) et_deleted: false— le plugin RxDB Firestore interroge parserverTimestamp > checkpoint; un document sans estampille n'est jamais récupéré par la réplication. - Trois niveaux de réplication, choisis par collection : pull-only (configuration consommée par le site), bidirectionnel (état opérationnel que le site modifie), push-only (logs produits par le site). Choisir le mauvais niveau pour une collection est la principale erreur de conception.
- Le stockage RxDB en mémoire signifie qu'un redémarrage hors ligne perd tout le travail hors ligne. La réplique se repeuple depuis Firestore, mais les documents créés hors ligne sont perdus. Décidez explicitement du compromis de stockage — voir replication.md.
- La vidange est au moins une fois, donc l'ingestion cloud doit être idempotente — clé chaque application sur l'ID généré par le client et ignore celles déjà appliquées.
- Les filtres push empêchent l'écho : les poussées bidirectionnelles ne concernent que les documents marqués
_offlineCreated/_locallyModified, afin que les documents cloud récupérés ne rebondissent pas. - Les terminaux préfèrent le cloud — la bascule ne s'enclenche qu'après N échecs de santé consécutifs, et hors ligne, ils doivent continuer de rechercher le serveur local, pas seulement une fois lors de la transition.
Règles strictes
N'exposez jamais les points de terminaison de synchronisation cloud sans authentification. Ils appliquent des incréments de stock et injectent des commandes. Un en-tête à secret partagé est le minimum.
Ne vérifiez jamais les jetons du personnel hors ligne de manière laxiste en ligne. Le repli de décodage sans vérification est un compromis accepté uniquement sur le LAN ; il doit être conditionné au fait que le serveur soit réellement hors ligne, sinon il devient un contournement de la vérification de signature.
Ne réinitialisez jamais les deltas de stock locaux pour des transactions qui n'ont pas été confirmées comme synchronisées. Réinitialisez par ID sur accusé de réception, sinon les ventes hors ligne sont comptées en double ou disparaissent de la disponibilité.
Ne laissez jamais le serveur local inventer des règles métier que le cloud possède (heures d'ouverture, tarification). Répliquez la configuration et calculez à partir de celle-ci, sinon le comportement du mode île diverge du site web.
Démarrage rapide
- Modélisez les collections en niveaux et nommez les jointures — architecture.md.
- Mettez en place RxDB + la réplication avec authentification par jeton personnalisé et règles de sécurité — replication.md.
- Ajoutez la vidange à la reconnexion et l'ingestion cloud idempotente — sync-flush.md.
- Câblez la chaîne heartbeat/état et la bascule client — network-failover.md.
- Protégez l'API locale (personnel / kiosk / matériel HMAC / jeton statique) — auth.md.
- Miroitez les points de terminaison cloud dont les terminaux ont besoin — local-api.md.
- Déployez sur site : systemd, nginx TLS, mDNS, supervision — operations.md.
Répertoire de références
| Scénario | Mots-clés déclencheurs | Référence |
|---|---|---|
| Topologie, niveaux, jointures, table de renommage | pull-only, bidirectionnel, push-only, double-chemin, locationId, conflit | architecture.md |
| Configuration de la réplique, schémas, piège de point de contrôle | RxDB, replicateFirestore, serverTimestamp, jeton personnalisé, storage-memory, firestore.rules | replication.md |
| Vidange à la reconnexion, deltas de stock, ingestion | flushAll, idempotent, FieldValue.increment, localDelta, syncedIds | sync-flush.md |
| Détection de panne et changement d'API | heartbeat, lastHeartbeatAt, cron, NetworkManager, apiBaseUrl, bascule | network-failover.md |
| Authentification de l'API locale | AuthGuard, HMAC, fenêtre de rejeu, repli JWT hors ligne, clé kiosk | auth.md |
| Points de terminaison et écritures hors ligne | disponibilité, mutex, réservation hors ligne, enregistrement, filtre de stock tarifaire | local-api.md |
| Déploiement sur site et manuel d'exploitation | systemd, nginx, TLS auto-signé, mDNS, avahi, journalctl, rollback | operations.md |
| Le registre : ce que l'audit a modifié, conservé, ajouté | provenance, audit, écarts, conservé délibérément | provenance.md |
Suite vitest pour la logique critique de confiance (vérification HMAC, décodage de jeton hors ligne, dépliage de delta sur RxDB réel, nouvelle recherche de bascule) : assets/behavior.test.ts — importez-la dans le projet cible comme couverture de régression.