Files
OwnCord/docs/protocol-schema.json
T
Claude 2e7a80171b feat(server,client): protocol codegen + audit quick-wins batch
Protocol codegen (decision D4, audit A-2026-07-08):
- Add docs/protocol-schema.json as the real single source of truth for
  WS message-type constants, making the long-standing 'generated from'
  comment in both constant files true.
- Add Server/scripts/genprotocol, a generator emitting both
  Server/ws/message_types.go and Client .../lib/protocolTypes.ts
  (constants byte-for-byte value-identical to before; only headers,
  ordering alignment, and provenance comments changed).
- Add make protocol-generate / protocol-verify and wire protocol-verify
  into CI next to sqlc-verify.

Quick wins (decision D8):
- admin: log LogAudit write failures in the backup handlers instead of
  discarding them (prior audit #10).
- api: fix self-contradictory upload Cache-Control to 'private,
  no-cache' per remediation plan W3-4; drop the now-unused
  fileCacheMaxAgeSeconds constant; update test.
- ws: route the hub settings cache through db.GetSetting instead of
  inline SQL.
- ws: fix a latent data race — main.go wires SetEventPersister and
  SetEventStore after NewRouter has already started the hub Run loop,
  which reads those fields on the broadcast/replay paths. They (and
  pluginSink, which one test sets post-Run) are now atomic pointers;
  the remaining pre-Run-only setters reject late calls with an error
  log instead of racing silently.

Update the audit closure table and decisions doc statuses accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UA17KPvqGBX3XbXYnMf1rA
2026-07-19 13:32:58 +00:00

78 lines
4.6 KiB
JSON

{
"$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": "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": "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" }
],
"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": "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": "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": "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": "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)"
}
]
}