syntax = "proto3"; package lnex; // ─── HANDSHAKE ────────────────────────────────────────────────────────────── // Server → Client on TCP connect (packet_id = 0x0001) message Hello { string lnex_version = 1; // "v1" bytes server_pubkey = 2; // 32-byte Ed25519 public key bytes challenge_nonce = 3; // 32-byte random challenge string node_name = 4; } // Client → Server (packet_id = 0x0002) message Auth { bytes client_pubkey = 1; // 32-byte Ed25519 public key string nickname = 2; string lnex_version = 3; bytes signature = 4; // Ed25519 sig over challenge_nonce } // Server → Client on success (packet_id = 0x0003) message Session { string session_id = 1; string token = 2; int64 expires_at = 3; // Unix ms, 0 = no expiry } // ─── KEEPALIVE ────────────────────────────────────────────────────────────── // Either direction (0x0004 / 0x0005) message Ping { int64 timestamp = 1; // Unix ms } message Pong { int64 timestamp = 1; // Echo of Ping.timestamp } // ─── CHANNELS ─────────────────────────────────────────────────────────────── // Client → Gateway (0x0030) message JoinChannel { string channel_id = 1; } // Client → Gateway (0x0031) message LeaveChannel { string channel_id = 1; } // Gateway → Client (0x0032) — full channel snapshot on join message ChannelState { string channel_id = 1; string channel_name = 2; ChannelKind kind = 3; repeated Member members = 4; string voice_endpoint = 5; // host:port of voice-node UDP enum ChannelKind { TEXT = 0; VOICE = 1; } message Member { string user_id = 1; string nickname = 2; bool in_voice = 3; } } // Broadcast → all channel members (0x0040 / 0x0041) message UserJoin { string channel_id = 1; string user_id = 2; string nickname = 3; } message UserLeave { string channel_id = 1; string user_id = 2; } // ─── CHAT ─────────────────────────────────────────────────────────────────── // Client → Gateway, broadcast to channel (0x0020) message ChatMessage { string message_id = 1; // UUID v4, generated by client string channel_id = 2; string sender_id = 3; // sender pubkey short form string content = 4; int64 timestamp = 5; // Unix ms } // Gateway → Client on join (0x0021) — recent history message ChatHistory { string channel_id = 1; repeated ChatMessage messages = 2; } // ─── VOICE STATE ──────────────────────────────────────────────────────────── // Broadcast on voice state change (0x0011) message VoiceState { string user_id = 1; string channel_id = 2; enum State { SILENT = 0; SPEAKING = 1; MUTED = 2; DEAFENED = 3; } State state = 3; } // ─── ERRORS ───────────────────────────────────────────────────────────────── // Any direction (0x00F0) message Error { uint32 code = 1; // ErrorCode enum value string message = 2; } // ─── DISCONNECT ───────────────────────────────────────────────────────────── // Any direction (0x00FF) — graceful close message Disconnect { string reason = 1; // optional human-readable reason }