lib/ - P2P Core

The lib/ layer is the P2P engine. It has no dependency on HTTP, WebSockets, or the server. Everything here could run in a different context (CLI, tests, another server) without modification.

Folder Structure

File

Role

quibble.ts

Core P2P node - wires together Corestore, Hyperswarm, rooms, and the friend/writer protocols

room.ts

Autobase-backed multi-writer chat room

identity.ts

Cryptographic identity - seed phrases, Ed25519 keypairs, persistent storage

messages.ts

Message factory functions for every message type

file-transfer.ts

File storage in a dedicated Hypercore, referenced by key from the room log

friend-protocol.ts

Cryptographic primitives for friend requests and DM key exchange

voice.ts

Voice call protocol constants and signaling model

video.ts

Video call protocol constant; ICE helper (delegates to rtc-config.ts)

rtc-config.ts

STUN/TURN presets, defaults, and buildIceServers() - shared by server and tests

peerjs-bridge.ts

Pure helpers for tunnelling PeerJS signaling over the DHT and ordering codecs

Room Model

A room is an Autobase - a multi-writer append-only log built on Hypercore. Each participant has their own local Hypercore (their “writer core”) and a shared linearized view is computed across all writers.

Peer A writer core ─┐
Peer B writer core ─┼─→ Autobase apply() ─→ linearized view
Peer C writer core ─┘

Messages are JSON objects appended to a writer’s local core. The apply function in room.ts processes each batch of nodes to produce the view - most messages are passed through directly, but system messages with actions like add-writer, room-owner-set, and room-admin-set mutate Autobase membership or admin state instead.

Rooms are identified by their bootstrap key (the Autobase key), encoded as a pear://quibble/... invite link. The link includes 96 bytes of deterministic padding to make invite links harder to brute-force.

Write Access

Joining a room doesn’t automatically grant write access - a peer must be added as a writer by someone who already has write access. The writer sync protocol handles this over a Protomux channel:

New peer joins Hyperswarm topic
  → announces signed (roomKey, writerKey, identityKey) to existing members
  → existing member verifies signature and calls room.addWriter(writerKey)
  → new peer can now append messages

For DM rooms, write access is restricted to the one friend associated with the room via registerDmRoom(). Anyone else’s writer announcement is rejected.

Identity Model

Identity is an Ed25519 keypair derived from a 24-word BIP39 seed phrase. The seed phrase is the portable secret - importing it on another device produces the exact same keypair.

Identity state is persisted in a local Autobase-backed store (not a flat file) so it can evolve with schema versions while remaining append-only. On startup, loadIdentity() reads the current state from this store.

Friend Protocol

WIP