{
  "$comment": "Single source of truth for WebSocket protocol message-type constants. Server/ws/message_types.go and Client/tauri-client/src/lib/protocolTypes.ts are generated from this file — edit here, then run `make protocol-generate` in Server/. CI runs `make protocol-verify` to reject drift.",
  "version": 1,
  "client_to_server": [
    { "wire": "auth", "go": "MsgTypeAuth", "ts": "AUTH" },
    { "wire": "chat_send", "go": "MsgTypeChatSend", "ts": "CHAT_SEND" },
    { "wire": "chat_edit", "go": "MsgTypeChatEdit", "ts": "CHAT_EDIT" },
    { "wire": "chat_delete", "go": "MsgTypeChatDelete", "ts": "CHAT_DELETE" },
    { "wire": "reaction_add", "go": "MsgTypeReactionAdd", "ts": "REACTION_ADD" },
    { "wire": "reaction_remove", "go": "MsgTypeReactionRemove", "ts": "REACTION_REMOVE" },
    { "wire": "typing_start", "go": "MsgTypeTypingStart", "ts": "TYPING_START" },
    { "wire": "channel_focus", "go": "MsgTypeChannelFocus", "ts": "CHANNEL_FOCUS" },
    { "wire": "mark_read", "go": "MsgTypeMarkRead", "ts": "MARK_READ" },
    { "wire": "presence_update", "go": "MsgTypePresenceUpdate", "ts": "PRESENCE_UPDATE" },
    { "wire": "voice_join", "go": "MsgTypeVoiceJoin", "ts": "VOICE_JOIN" },
    { "wire": "voice_leave", "go": "MsgTypeVoiceLeave", "ts": "VOICE_LEAVE" },
    { "wire": "voice_mute", "go": "MsgTypeVoiceMute", "ts": "VOICE_MUTE" },
    { "wire": "voice_deafen", "go": "MsgTypeVoiceDeafen", "ts": "VOICE_DEAFEN" },
    { "wire": "voice_camera", "go": "MsgTypeVoiceCamera", "ts": "VOICE_CAMERA" },
    { "wire": "voice_screenshare", "go": "MsgTypeVoiceScreenshare", "ts": "VOICE_SCREENSHARE" },
    { "wire": "voice_mod_mute", "go": "MsgTypeVoiceModMute", "ts": "VOICE_MOD_MUTE" },
    { "wire": "voice_mod_deafen", "go": "MsgTypeVoiceModDeafen", "ts": "VOICE_MOD_DEAFEN" },
    { "wire": "voice_mod_move", "go": "MsgTypeVoiceModMove", "ts": "VOICE_MOD_MOVE" },
    { "wire": "voice_mod_kick", "go": "MsgTypeVoiceModKick", "ts": "VOICE_MOD_KICK" },
    { "wire": "ping", "go": "MsgTypePing", "ts": "PING" },
    {
      "wire": "voice_token_refresh",
      "go": "MsgTypeVoiceTokenRefresh",
      "ts": "VOICE_TOKEN_REFRESH",
      "go_trailing_comment": "//nolint:gosec // G101: false positive — message type constant, not a credential"
    },
    { "wire": "voice_e2ee_announce", "go": "MsgTypeVoiceE2EEAnnounce", "ts": "VOICE_E2EE_ANNOUNCE" },
    { "wire": "voice_e2ee_offer", "go": "MsgTypeVoiceE2EEOffer", "ts": "VOICE_E2EE_OFFER" },
    { "wire": "call_ring", "go": "MsgTypeCallRing", "ts": "CALL_RING" },
    { "wire": "call_decline", "go": "MsgTypeCallDecline", "ts": "CALL_DECLINE" },
    {
      "wire": "chat_command",
      "go": "MsgTypeChatCommand",
      "ts": "CHAT_COMMAND",
      "note": "plugin slash-command dispatch (Phase C)"
    }
  ],
  "server_to_client": [
    { "wire": "auth_ok", "go": "MsgTypeAuthOK", "ts": "AUTH_OK" },
    { "wire": "auth_error", "go": "MsgTypeAuthError", "ts": "AUTH_ERROR" },
    { "wire": "ready", "go": "MsgTypeReady", "ts": "READY" },
    { "wire": "chat_message", "go": "MsgTypeChatMessage", "ts": "CHAT_MESSAGE" },
    { "wire": "chat_send_ok", "go": "MsgTypeChatSendOK", "ts": "CHAT_SEND_OK" },
    { "wire": "chat_edited", "go": "MsgTypeChatEdited", "ts": "CHAT_EDITED" },
    { "wire": "chat_deleted", "go": "MsgTypeChatDeleted", "ts": "CHAT_DELETED" },
    { "wire": "chat_bulk_deleted", "go": "MsgTypeChatBulkDeleted", "ts": "CHAT_BULK_DELETED" },
    { "wire": "reaction_update", "go": "MsgTypeReactionUpdate", "ts": "REACTION_UPDATE" },
    { "wire": "typing", "go": "MsgTypeTyping", "ts": "TYPING" },
    { "wire": "presence", "go": "MsgTypePresence", "ts": "PRESENCE" },
    { "wire": "channel_create", "go": "MsgTypeChannelCreate", "ts": "CHANNEL_CREATE" },
    { "wire": "channel_update", "go": "MsgTypeChannelUpdate", "ts": "CHANNEL_UPDATE" },
    { "wire": "channel_delete", "go": "MsgTypeChannelDelete", "ts": "CHANNEL_DELETE" },
    { "wire": "voice_state", "go": "MsgTypeVoiceState", "ts": "VOICE_STATE" },
    { "wire": "voice_config", "go": "MsgTypeVoiceConfig", "ts": "VOICE_CONFIG" },
    { "wire": "voice_token", "go": "MsgTypeVoiceToken", "ts": "VOICE_TOKEN" },
    { "wire": "voice_speakers", "go": "MsgTypeVoiceSpeakers", "ts": "VOICE_SPEAKERS" },
    {
      "wire": "voice_leave",
      "go": "MsgTypeVoiceLeaveBC",
      "ts": "VOICE_LEAVE",
      "note": "broadcast (same string as client msg)"
    },
    { "wire": "voice_moved", "go": "MsgTypeVoiceMoved", "ts": "VOICE_MOVED" },
    { "wire": "voice_disconnected", "go": "MsgTypeVoiceDisconnected", "ts": "VOICE_DISCONNECTED" },
    { "wire": "member_join", "go": "MsgTypeMemberJoin", "ts": "MEMBER_JOIN" },
    { "wire": "member_leave", "go": "MsgTypeMemberLeave", "ts": "MEMBER_LEAVE" },
    { "wire": "member_update", "go": "MsgTypeMemberUpdate", "ts": "MEMBER_UPDATE" },
    { "wire": "user_update", "go": "MsgTypeUserUpdate", "ts": "USER_UPDATE" },
    { "wire": "member_ban", "go": "MsgTypeMemberBan", "ts": "MEMBER_BAN" },
    { "wire": "roles_update", "go": "MsgTypeRolesUpdate", "ts": "ROLES_UPDATE" },
    { "wire": "emoji_update", "go": "MsgTypeEmojiUpdate", "ts": "EMOJI_UPDATE" },
    { "wire": "server_restart", "go": "MsgTypeServerRestart", "ts": "SERVER_RESTART" },
    { "wire": "error", "go": "MsgTypeError", "ts": "ERROR" },
    { "wire": "pong", "go": "MsgTypePong", "ts": "PONG" },
    { "wire": "dm_channel_open", "go": "MsgTypeDMChannelOpen", "ts": "DM_CHANNEL_OPEN" },
    { "wire": "dm_channel_close", "go": "MsgTypeDMChannelClose", "ts": "DM_CHANNEL_CLOSE" },
    { "wire": "call_incoming", "go": "MsgTypeCallIncoming", "ts": "CALL_INCOMING" },
    { "wire": "call_declined", "go": "MsgTypeCallDeclined", "ts": "CALL_DECLINED" },
    {
      "wire": "voice_e2ee_announce",
      "go": "MsgTypeVoiceE2EEAnnounceBC",
      "ts": "VOICE_E2EE_ANNOUNCE",
      "note": "broadcast (same string as client msg)"
    },
    {
      "wire": "voice_e2ee_offer",
      "go": "MsgTypeVoiceE2EEOfferRelay",
      "ts": "VOICE_E2EE_OFFER",
      "note": "relay (same string as client msg)"
    },
    {
      "wire": "command_reply",
      "go": "MsgTypeCommandReply",
      "ts": "COMMAND_REPLY",
      "note": "ephemeral plugin reply, sent only to the invoking client"
    },
    {
      "wire": "plugin_broadcast",
      "go": "MsgTypePluginBroadcast",
      "ts": "PLUGIN_BROADCAST",
      "note": "plugin channel broadcast, gated by the sender's SEND_MESSAGES"
    }
  ]
}
