lib/ - Núcleo P2P

La capa lib/ es el motor P2P. No depende de HTTP, WebSockets ni del servidor. Todo lo que hay aquí podría ejecutarse en otro contexto (CLI, pruebas, otro servidor) sin modificación.

Estructura de carpetas

Archivo

Función

quibble.ts

Nodo P2P central: conecta Corestore, Hyperswarm, salas y los protocolos de amistad/escritura

room.ts

Sala de chat multi-escritor respaldada por Autobase

identity.ts

Identidad criptográfica: frases semilla, pares de claves Ed25519, almacenamiento persistente

messages.ts

Funciones fábrica de mensajes para cada tipo de mensaje

file-transfer.ts

Almacenamiento de archivos en un Hypercore dedicado, referenciado por clave desde el registro de la sala

friend-protocol.ts

Primitivas criptográficas para solicitudes de amistad e intercambio de claves de MD

voice.ts

Constantes del protocolo de llamadas de voz y modelo de señalización

video.ts

Constante del protocolo de vídeo; ayudante ICE (delega en rtc-config.ts)

rtc-config.ts

Preajustes STUN/TURN, valores por defecto y buildIceServers(), compartido por el servidor y las pruebas

peerjs-bridge.ts

Ayudantes puros para tunelizar la señalización de PeerJS sobre la DHT y ordenar códecs

Modelo de sala

Una sala es un Autobase: un registro append-only multi-escritor construido sobre Hypercore. Cada participante tiene su propio Hypercore local (su “núcleo de escritura”) y se calcula una vista linealizada compartida entre todos los escritores.

Núcleo de escritura del Par A ─┐
Núcleo de escritura del Par B ─┼─→ Autobase apply() ─→ vista linealizada
Núcleo de escritura del Par C ─┘

Los mensajes son objetos JSON añadidos al núcleo local de un escritor. La función apply en room.ts procesa cada lote de nodos para producir la vista: la mayoría de los mensajes se pasan directamente, pero los mensajes system con acciones como add-writer, room-owner-set y room-admin-set modifican la membresía de Autobase o el estado de administración en su lugar.

Las salas se identifican por su clave de arranque (la clave de Autobase), codificada como un enlace de invitación pear://quibble/.... El enlace incluye 96 bytes de relleno determinista para dificultar los ataques de fuerza bruta sobre los enlaces de invitación.

Acceso de escritura

Unirse a una sala no concede automáticamente acceso de escritura: un par debe ser añadido como escritor por alguien que ya tenga acceso de escritura. El protocolo de sincronización de escritores gestiona esto sobre un canal Protomux:

Un nuevo par se une al tópico de Hyperswarm
  → anuncia (roomKey, writerKey, identityKey) firmado a los miembros existentes
  → un miembro existente verifica la firma y llama a room.addWriter(writerKey)
  → el nuevo par ya puede añadir mensajes

Para las salas de MD, el acceso de escritura se restringe al único amigo asociado a la sala mediante registerDmRoom(). El anuncio de escritor de cualquier otro es rechazado.

Modelo de identidad

La identidad es un par de claves Ed25519 derivado de una frase semilla BIP39 de 24 palabras. La frase semilla es el secreto portátil: importarla en otro dispositivo produce exactamente el mismo par de claves.

El estado de identidad se persiste en un almacén local respaldado por Autobase (no un archivo plano), de modo que puede evolucionar con las versiones del esquema sin dejar de ser append-only. Al arrancar, loadIdentity() lee el estado actual desde este almacén.

Protocolo de amistad

En desarrollo (WIP)