Skip to content

Type Deep Dive — Provider Token And Conference Runtime

1. Token actions của Stringee và Twilio không cùng contract

Stringee

stringeeToken:

  • guard ctx.Stringee == nil -> errUnsupported (action/stringee.go:20),
  • luôn tạo user token theo ctx.Access.UserID,
  • nếu có room, tạo thêm room_token với quyền Publish/Subscribe/ControlRoom/Record (action/stringee.go:42).

Twilio

twilioToken:

  • guard ctx.Twilio == nil -> errUnsupported (action/twilio.go:18),
  • tạo identity dạng userID:random8 (action/twilio.go:33),
  • nếu có room, add VideoGrant(room) rồi trả token (action/twilio.go:36).

Điều này có nghĩa Twilio token mang identity per session/call, còn Stringee token gắn trực tiếp user identity.

2. FE wrappers

Stringee

SurfaceVai trò
StringeeProviderWrapperquery GetStringeeToken rồi mount provider (StringeeProviderWrapper.tsx:20)
StringeeProviderconnect client khi lazy = false, reconnect trên requestnewtoken, emit chat events (StringeeProvider.ts:48)
StringeeConferenceDialogrequest room_token theo roomId, map participants từ useUser() (StringeeConferenceDialog.tsx:86)
StringeeConferencepreview mặc định trước khi join, sau đó mới mount room runtime (StringeeConference/index.tsx:255)

Twilio

SurfaceVai trò
TwilioVideoPreviewpreview media local trước khi join
TwilioVideogọi getTwilioToken(room), rồi Video.connect(token, { name: room })
TwilioVideo/index.tsxbật overlay khi currentConversation.video_room_id có giá trị

3. Twilio preview payload mismatch

Parent TwilioVideo/index.tsx chờ:

ts
{ videoEnabled, microphoneEnabled }

handleAccept() (TwilioVideo/index.tsx:27)

Nhưng TwilioVideoPreview lại emit:

ts
{ videoEnabled, audioEnabled }

(TwilioVideoPreview.tsx:69)

Kết quả là values.microphoneEnabled ở parent có thể luôn là undefined, khiến preview mic state không truyền đúng sang room runtime.

4. createConference có contract drift mạnh

Logic hiện tại

  1. parse type = meet | stringee (action/type.go:28),
  2. meet -> tạo Google Calendar event và Hangout link (conference.go:88),
  3. stringee -> tạo room Stringee bằng conversation_id hoặc UUID mới (conference.go:143),
  4. nếu conversation_id != nil -> mutate conversation _set: { external_call_id: conference_url } (conference.go:60).

Drift 1: update sai field contract

FE overlay Twilio đọc conversation.video_room_id (TwilioVideo/index.tsx:14) và metadata permission cũng chỉ expose video_room_id / video_room_provider (public_conversation.yaml:62, public_conversation_admin.yaml:43).

Nhưng backend lại update external_call_id, field không nằm trong permission columns đã thấy ở metadata search hiện tại. Đây là lệch contract rõ giữa action layer và runtime FE/read model.

Drift 2: mutate conversation có thể fail ngầm

createConference dùng ctx.Controller, tức access client theo session user (action/action.go:39), không phải admin client. Nếu field _set.external_call_id bị role schema hoặc permission chặn, Mutate() sẽ lỗi. Nhưng code chỉ log:

ctx.Logger.Err(err).Msgf("failed to update conversation: %s", err)

và vẫn return success output (conference.go:79).

Drift 3: Stringee create path không guard nil provider

Trong khi stringeeToken có guard ctx.Stringee == nil, nhánh createConference -> createStringeeRoom gọi thẳng:

ctx.Stringee.Room.Create(...)

(conference.go:149)

Nếu env thiếu config Stringee và env.NewConfig() để Stringee = nil, nhánh này sẽ là điểm rủi ro runtime.

5. Findings kỹ thuật

IDMức độMô tả
PR-F01CaoTwilio preview emit audioEnabled nhưng parent đọc microphoneEnabled, làm lệch media state transfer (TwilioVideoPreview.tsx:69, TwilioVideo/index.tsx:27).
PR-F02Rất caocreateConference update external_call_id thay vì video_room_id/video_room_provider, trái với contract FE/read model (conference.go:60, public_conversation_current.yaml:23).
PR-F03CaocreateConference swallow lỗi mutate conversation và vẫn trả output success, tạo trạng thái “conference created nhưng conversation chưa link” (conference.go:79).
PR-F04CaoNhánh createConference -> stringee không check ctx.Stringee == nil, khác chuẩn guard của stringeeToken (action/stringee.go:20, conference.go:149).