# lib/ - Cœur P2P La couche `lib/` est le moteur P2P. Elle ne dépend ni de HTTP, ni des WebSockets, ni du serveur. Tout ce qui s'y trouve pourrait s'exécuter dans un autre contexte (CLI, tests, un autre serveur) sans modification. ## Structure des dossiers | Fichier | Rôle | |---|---| | `quibble.ts` | Nœud P2P central : relie Corestore, Hyperswarm, les salons et les protocoles d'amis/d'écriture | | `room.ts` | Salon de discussion multi-écrivains adossé à Autobase | | `identity.ts` | Identité cryptographique : phrases de récupération, paires de clés Ed25519, stockage persistant | | `messages.ts` | Fonctions fabriques de messages pour chaque type de message | | `file-transfer.ts` | Stockage de fichiers dans un Hypercore dédié, référencé par clé depuis le journal du salon | | `friend-protocol.ts` | Primitives cryptographiques pour les demandes d'amis et l'échange de clés de MP | | `voice.ts` | Constantes du protocole d'appel audio et modèle de signalisation | | `video.ts` | Constante du protocole vidéo ; assistant ICE (délègue à `rtc-config.ts`) | | `rtc-config.ts` | Préréglages STUN/TURN, valeurs par défaut et `buildIceServers()`, partagés par le serveur et les tests | | `peerjs-bridge.ts` | Assistants purs pour faire transiter la signalisation PeerJS sur la DHT et ordonner les codecs | ## Modèle de salon Un salon est un **Autobase** : un journal append-only multi-écrivains construit sur Hypercore. Chaque participant possède son propre Hypercore local (son « cœur d'écriture ») et une vue linéarisée partagée est calculée sur l'ensemble des écrivains. ``` Cœur d'écriture du Pair A ─┐ Cœur d'écriture du Pair B ─┼─→ Autobase apply() ─→ vue linéarisée Cœur d'écriture du Pair C ─┘ ``` Les messages sont des objets JSON ajoutés au cœur local d'un écrivain. La fonction `apply` dans `room.ts` traite chaque lot de nœuds pour produire la vue : la plupart des messages sont transmis directement, mais les messages `system` avec des actions telles que `add-writer`, `room-owner-set` et `room-admin-set` modifient plutôt l'appartenance à l'Autobase ou l'état d'administration. Les salons sont identifiés par leur **clé d'amorçage** (la clé de l'Autobase), encodée sous forme de lien d'invitation `pear://quibble/...`. Le lien inclut 96 octets de remplissage déterministe pour rendre les liens d'invitation plus difficiles à attaquer par force brute. ## Accès en écriture Rejoindre un salon n'accorde pas automatiquement l'accès en écriture : un pair doit être ajouté comme écrivain par quelqu'un qui possède déjà l'accès en écriture. Le protocole de synchronisation des écrivains gère cela sur un canal Protomux : ``` Un nouveau pair rejoint le topic Hyperswarm → annonce (roomKey, writerKey, identityKey) signé aux membres existants → un membre existant vérifie la signature et appelle room.addWriter(writerKey) → le nouveau pair peut désormais ajouter des messages ``` Pour les salons de MP, l'accès en écriture est restreint à l'unique ami associé au salon via `registerDmRoom()`. L'annonce d'écrivain de toute autre personne est rejetée. ## Modèle d'identité L'identité est une **paire de clés Ed25519** dérivée d'une phrase de récupération BIP39 de 24 mots. La phrase de récupération est le secret portable : l'importer sur un autre appareil produit exactement la même paire de clés. L'état d'identité est conservé dans un stockage local adossé à Autobase (et non un fichier plat), afin qu'il puisse évoluer avec les versions de schéma tout en restant append-only. Au démarrage, `loadIdentity()` lit l'état actuel depuis ce stockage. ## Protocole d'amis En cours de développement (WIP)