# JAM Protocol v0.1 ## Transport - WebSocket (ws:// or wss://) at `/ws` - REST API at `/api/*` - Federation at `/federation/receive` ## WebSocket Packet Format ```json { "op": , "d": , "s": // sequence number } ``` ## Opcodes | Op | Name | Direction | Description | |----|------|-----------|-------------| | 0 | Heartbeat | C↔S | Keepalive | | 1 | Hello | S→C | Server greeting | | 2 | Authenticate | C→S | Login/register | | 3 | Authenticated | S→C | Auth success | | 4 | Error | S→C | Error response | | 10 | MessageCreate | C↔S | Send message | | 11 | MessageUpdate | C↔S | Edit message | | 12 | MessageDelete | C↔S | Delete message | | 13 | MessageReaction | C↔S | Add/remove reaction | | 20 | ChannelCreate | S→C | New channel | | 21 | ChannelUpdate | S→C | Channel updated | | 22 | ChannelDelete | S→C | Channel deleted | | 30 | GuildCreate | S→C | New guild | | 31 | GuildUpdate | S→C | Guild updated | | 40 | VoiceStateUpdate | C↔S | Voice channel join/leave | | 50 | StreamStart | C↔S | Start stream | | 51 | StreamEnd | C↔S | End stream | | 60 | TypingStart | C↔S | User typing | | 70 | UserPresence | S→C | Presence update | | 80 | FederationPacket | S↔S | Server-to-server data | | 90 | CallOffer | C↔S | WebRTC offer | | 91 | CallAnswer | C↔S | WebRTC answer | | 92 | CallICE | C↔S | ICE candidate | | 93 | CallEnd | C↔S | End call | ## Encryption - Algorithm: XChaCha20-Poly1305 - Key exchange: X25519 - Key derivation: Argon2id - Nonce: 24 bytes random - Messages with `encrypted: true` have content encrypted with the channel's session key ## Compression - Algorithm: zstd (level: best compression) - Window size: 16MB - Deduplication: 64KB chunks, SHA256 hash - Only files > 1KB are compressed - Ratio target: 10MB → 512KB-2MB ## Federation - HTTP POST to `https:///federation/receive` - Headers: `X-JAM-Domain`, `X-JAM-Signature` (ed25519) - Body: `FederationData` JSON - Peers discovered via manual configuration ## REST API ### Health `GET /api/health` ### Guilds `GET /api/guilds?user_id=` `POST /api/guilds` body: `{name, owner_id, description}` `GET /api/guilds/` returns guild + channels + roles + categories `DELETE /api/guilds/` ### Channels `POST /api/channels` body: `{guild_id, category_id, name, type, topic, position}` `GET /api/channels/` `PUT /api/channels/` body: `{name, topic, position}` `DELETE /api/channels/` ### Messages `GET /api/messages?channel_id=&limit=50&before=` ### Users `GET /api/users/` ### Upload `POST /api/upload` (multipart/form-data, field: file) `GET /api/files/` ### Roles `POST /api/roles/` body: `{guild_id, name, color, permissions}`