Real-Time Communication
WebRTC Mesh Topology
For live video/audio calls, TalentSync uses a Mesh Topology for 1-on-1 interviews.
- Every peer connects directly to every other peer
- Low latency, no central media server
- Suitable for 1-on-1 sessions (scales poorly beyond ~4-5 participants — acceptable for interview use case)
Signaling Flow
- Join: Client emits
JOIN_ROOMvia Socket.io - Discovery: Server returns list of existing peers in the room
- Offer: Joining client creates a WebRTC Offer → Server → Target peer
- Answer: Target peer creates Answer → Server → Initiator
- ICE Candidates: Exchanged asynchronously to traverse NATs
- Connected: Direct P2P media stream established
Socket.io Events (Live Room)
Signaling events (existing)
| Event | Direction | Payload |
|---|---|---|
JOIN_ROOM | Client → Server | { roomId, userInfo } |
OFFER | Client → Server → Client | { sdp, targetId } |
ANSWER | Client → Server → Client | { sdp, targetId } |
ICE_CANDIDATE | Client → Server → Client | { candidate, targetId } |
USER_JOINED | Server → Client | { userId, userInfo } |
USER_LEFT | Server → Client | { userId } |
Question push (Phase 1B)
| Event | Direction | Payload |
|---|---|---|
push_question | Client (interviewer) → Server → Client (candidate) | { questionText: string } |
The push_question event is emitted from the interviewer's "My Questions" panel. The server broadcasts it to all other participants in the room. The candidate's screen renders the question text in a visible card.
Security
The push_question event only carries questionText. The interviewerHints and expectedAnswerGuide fields from InterviewQuestion are never sent to or rendered on the candidate's browser.
Collaborative Code Editor
Uses Yjs for Conflict-free Replicated Data Types (CRDTs).
- Binding:
y-codemirror.nextbinds the Yjs document to the CodeMirror editor - Provider: Custom WebRTC provider (or
y-webrtc) syncs document updates directly between peers via WebRTC Data Channels - Awareness: Cursor positions and selections synced via the
awarenessprotocol - Persistence: Yjs state can be persisted server-side for session replay (future feature)
Whiteboard
Integration with Excalidraw.
- State is serialized and broadcast to all peers in the room
- Real-time sync ensures a shared canvas experience
- Whiteboard visibility controlled by
StageTypeConfig.toolsConfig.whiteboard— only rendered whentrue
Webcam Proctoring (Phase 3)
Used in technical_dsa stages when dsaConfig.proctoringEnabled: true.
- Webcam stream captured but not transmitted to peers (no live video call for async stages)
- Periodic snapshots taken and stored (implementation TBD — Phase 3)
- Visible indicator shown to candidate so they know proctoring is active
DSA Session: Code Execution (Phase 3)
The DSA session sends code to a sandboxed execution service:
POST /v1/dsa/:token/run — run against visible test cases (non-final)
POST /v1/dsa/:token/submit — run against all test cases (final)The execution service (Judge0 self-hosted or equivalent) returns:
{
testCaseId: string;
passed: boolean;
executionTimeMs: number;
memoryUsedKB: number;
stdout?: string;
stderr?: string;
}The aggregate score (% test cases passed) is stored on Interview.stageData.dsaSubmissions[].score — recruiter-only. Candidates see per-test pass/fail but not the overall %.