Appearance
Shared Rules — Conversation Runtime And Provider Boundary
1. Thuật ngữ chuẩn
| Thuật ngữ | Tên kỹ thuật | Ý nghĩa |
|---|---|---|
| Hội thoại | conversation | Header conversation |
| Thành viên hội thoại | conversation_member | Membership + read/mute/in_call state |
| Tin nhắn | conversation_message | Message body và metadata |
| Mention | conversation_message_mention | Mapping message -> người được nhắc + read_at |
| Feed runtime | conversation_current | Read model denormalized cho list |
| Unread search | search_unread_conversation_messages | Function lấy unread feed |
| Overlay call | TwilioVideo | Full-screen call runtime dựa vào store |
| Conference dialog | StringeeConferenceDialog | Modal conference runtime Stringee |
2. Runtime matrix
| Lớp | Source of truth | Ghi chú |
|---|---|---|
| Conversation list | conversation_current + store conversations | FE list nên đọc từ read model, không từ raw tables |
| Message list | conversation_message + store messages[cid] | merge bằng mergeSortedConversationMessages() |
| Read state | conversation_member.read_at | FE intent có, nhưng mutation đang stub |
| Stringee auth | action stringeeToken | provider optional, có guard unsupported |
| Twilio auth | action twilioToken | provider optional, có guard unsupported |
| Conference create | action createConference | contract update conversation hiện đang drift |
3. Invariants hệ thống đang ngầm dùng
- User chỉ đọc được
conversationnếu là member (public_conversation.yaml:36). - User chỉ tự update
conversation_member.read_at,mute_until,in_callcủa chính mình (public_conversation_member.yaml:72). - User chỉ insert message khi conversation chưa
closedvà có member record (public_conversation_message.yaml:33). - Twilio overlay chỉ bật khi
conversationStore.currentConversation.video_room_idcó giá trị (TwilioVideo/index.tsx:14). ConversationListkỳ vọng có mutation update membership, nhưng implementation thực hiện tại chưa tồn tại (ConversationList.tsx:54,:188).
4. Provider matrix
| Provider | Action backend | FE entrypoint | Rủi ro | |---|---|---| | Stringee user token | stringeeToken | StringeeProviderWrapper | provider có thể unsupported nếu env thiếu | | Stringee room token | stringeeToken(data.room, record) | StringeeConferenceDialog | phụ thuộc room id và action GraphQL sống | | Twilio room token | twilioToken(data.room) | useTwilio / TwilioVideo | preview payload mismatch làm lệch audio state | | Conference create | createConference(type) | bất kỳ surface gọi action này | đang update contract field không khớp FE/runtime list |
5. Rules cho unread / search
conversation_currentchứa sẵnlast_message_*,unread_messages_count,read_at,video_room_id,video_room_provider(public_conversation_current.yaml:23).search_conversation_currentvàsearch_unread_conversation_messagesđều nhậnhasura_sessionlàm session argument, nên kết quả là user-scoped read model (public_search_conversation_current.yaml:1,public_search_unread_conversation_messages.yaml:1).- FE store merge conversations theo
idvà sort giảm dần theolast_message_created_at(useConversationStore.ts:23). - Message merge không append mù; utility cố merge theo
created_atvàidđể tránh duplicate (utils.ts:1).
6. Findings ưu tiên cao
| ID | Mức độ | Mô tả |
|---|---|---|
| SR-F01 | Cao | ConversationList click item sẽ gọi mutation stub và có thể throw ngay trong UI (ConversationList.tsx:188). |
| SR-F02 | Cao | ConversationMessages có composer nhưng không gửi message thật (ConversationMessages.tsx:92). |
| SR-F03 | Cao | ROUTE_CONVERSATION_CONFERENCE không có route record mounted, dù được push từ detail page (ConversationDetail.tsx:13, module.ts:12). |
| SR-F04 | Rất cao | createConference update external_call_id thay vì video_room_id/video_room_provider, rất dễ lệch hẳn với FE Twilio overlay contract (conference.go:60, TwilioVideo/index.tsx:14). |
| SR-F05 | Cao | createConference nuốt lỗi update conversation bằng log-only path, nên FE có thể nhận success dù DB không cập nhật (conference.go:79). |
| SR-F06 | Trung bình | useConversation.ts và ConversationProvider đều gần như pass-through, cho thấy orchestration layer của module chưa tồn tại (useConversation.ts:1, ConversationProvider.tsx:12). |
7. QA checklist tối thiểu
- Click vào 1 item trong conversation list, xác nhận app có throw vì mutation stub hay không.
- Bấm icon video từ detail workspace, xác nhận route conference có thật hay fail router.
- Tạo conference type
stringeevà kiểm tra conversation record có update field nào hữu ích cho FE hay không. - Chạy Twilio preview với mic tắt, xác nhận room runtime có nhận đúng trạng thái microphone không.
- Insert message / mention / reaction bằng role
user, xác nhận Hasura permission chặn đúng ngoài scope member/owner.