feat(phase-09): Text Chat full backend + WebSocket
Phase 09 Chat — KEEP per JIRA. P09-V11-T01 Activity Match source compatibility.
New chat module (11 files):
- Entity: Conversation, ConversationMember (复合主键), Message
- Mapper: ConversationMapper, ConversationMemberMapper, MessageMapper
- Service: ChatService (getOrCreateConversation/sendText/loadMessages/markAsRead/syncFromMatch)
- Controller: ConversationController (POST /from-match, GET /{id}, GET list)
MessageController (POST send, GET load history, PUT mark read)
- WebSocket: WebSocketConfig + ChatWebSocketHandler (/ws/chat, JSON protocol)
Core invariants:
- INV-005: ChatService requires Match status active/getting_to_know
- Conversation.status sync with Match.status (syncFromMatch)
- Member.canSend + Conversation.status + sender membership all validated
- Client-side idempotency via client_message_id
- P09-V11-T01: Conversation binds only match_id — works identically for
user_like / activity_mutual / matchmaker Match sources
WebSocket note: Memory-based session map; multi-node will need Redis Pub/Sub.