# 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