Je te remercie de prendre finalement le temps de développer pourquoi tu tiens tant au local-first. Cela m’aide à mieux comprendre pourquoi, mais je ne suis toujours pas convaincu par tes arguments. La plupart des avantages que tu vois au local-first peuvent déjà être obtenus sans, et certains avantages n’en sont pas vraiment en situation réelle.
Je partage l’objectif du « fork social », mais Dunipod résout déjà ce problème avec une séparation plus simple entre les faits, leur réplication et leur interprétation.
Dans Dunipod, le réseau n’essaie pas d’obtenir un consensus global sur une vue unique du monde. Il fait converger les pods vers un corpus commun de documents signés et immuables. Chaque document possède un identifiant dérivé du hash de sa représentation canonique.
La couche P2P réconcilie ensuite les ensembles de documents entre pods. Elle utilise RIBLT pour découvrir et transférer les différences, jusqu’à ce que les pods convergent vers l’union de leurs documents. Il n’existe pas de suppression au niveau de cet ensemble : lorsqu’un document devient obsolète, est effacé ou rejeté par l’indexation, son identifiant reste connu, éventuellement sous forme de tombstone accompagné de sa preuve.
Chaque pod applique ensuite ses propres règles d’admission, d’indexation et de modération à ce corpus. Avec le même corpus et les mêmes règles, deux pods construisent la même vue grâce à des règles déterministes et indépendantes de l’ordre de réception. Par exemple, les versions concurrentes d’un même auteur sont départagées selon un ordre canonique fondé sur l’epoch et le doc_id, tandis que les décisions qui nécessitent une référence objective utilisent l’état on-chain finalisé. En revanche, deux pods peuvent choisir des modérateurs, des règles ou des packages différents et produire volontairement des vues différentes.
C’est précisément là que vit le fork social dans Dunipod : non pas dans l’obligation de maintenir un index complet sur chaque appareil, mais dans la liberté de choisir le pod et les règles qui interprètent les faits. Une personne peut créer une clé, signer et soumettre immédiatement ses documents à son propre pod. Elle n’a pas besoin d’être préalablement reconnue par une autorité globale. Les autres pods peuvent répliquer ces documents tout en décidant localement de les indexer, de les rendre visibles ou de les classer différemment.
Autrement dit, le fork social est essentiellement une propriété du modèle de confiance et de projection, pas nécessairement du lieu où s’exécute la base de données. Le rendre possible ne nécessite pas d’embarquer toute la couche de stockage et de requête dans chaque application.
D’ailleurs, le problème posé par la création libre de clés n’est pas réellement la taille mathématique de l’espace Ed25519. Le problème concret est celui des attaques Sybil : un acteur peut créer à faible coût un grand nombre de clés et publier un grand volume de données. Ce problème existe aussi bien dans un système local-first que dans un réseau de pods et doit être traité par des quotas, des limites de ressources et des politiques d’admission.
Je nuancerais également certains autres avantages que tu attribue au local-first.
L’expérience hors ligne peut effectivement être excellente pour les données déjà présentes localement, les brouillons ou un petit corpus. Mais ce modèle ne passe pas à l’échelle pour une recherche exhaustive dans un corpus important : il faudrait d’abord télécharger, stocker et indexer une quantité potentiellement considérable de données sur chaque appareil. À partir d’un certain volume, l’utilisateur n’a plus réellement toutes les données en local ; il doit sélectionner un sous-ensemble, et on retrouve alors les limites ordinaires d’un cache.
De même, une requête locale n’est pas automatiquement plus performante. Elle évite la latence réseau, mais transfère le stockage, l’indexation et le calcul vers la machine de l’utilisateur, qui sera souvent moins puissante et moins bien optimisée qu’un serveur spécialisé. Un index serveur correctement conçu répond normalement en moins d’une seconde, hors latence réseau.
Le déplacement du coût des requêtes vers le client ne supprime pas non plus le problème des abus. La couche P2P doit malgré tout se protéger contre les identités Sybil, les volumes excessifs, les documents ou blobs surdimensionnés, les connexions lentes, les demandes coûteuses et l’épuisement du disque. J’ai précisément travaillé sur ces protections dans Dunipod, et elles sont loin d’être triviales. Le local-first déplace une partie du coût, mais ne dispense pas de quotas ni de mécanismes d’admission.
Enfin, il existe un coût de complexité applicative important. Notre écosystème utilise plusieurs stacks : JavaScript/TypeScript, Flutter/Dart, Python, etc. Pour que Ğeopod soit réellement accessible à toutes les app, il faudrait fournir, maintenir, sécuriser et tester un client complet (stockage, réplication, indexation et moteur de requêtes) pour chacune de ces stacks, ou imposer une technologie particulière aux applications. Cela augmente fortement le coût d’intégration et limite les applications capables d’utiliser la couche off-chain.
Dunipod place cette complexité dans des services interopérables exposant des API HTTP et GraphQL ordinaires. N’importe quelle application peut ainsi l’utiliser avec son langage et son architecture actuels, tout en conservant la possibilité de choisir son pod, d’en exploiter plusieurs ou d’héberger le sien.
En conclusion, je comprends que le modèle local-first puisse paraître plus élégant et plus décentralisé sur le papier, mais je maintiens que ce n’est pas le cas en pratique. Le modèle de confiance reste le même, et cela apporte d’autres problèmes qui sont évitables avec d’autres approches, sans avoir besoin de perdre les avantages qui comptent vraiment.