From c62efff20144833a9ffaf44cc97c4aa7b25e1f9c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Aug 2026 21:24:23 +0000 Subject: [PATCH] test: add replay-protection coverage for WebRTC signaling envelopes Co-authored-by: muke1908 <20297989+muke1908@users.noreply.github.com> --- service/src/sdk.test.ts | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/service/src/sdk.test.ts b/service/src/sdk.test.ts index a36a4fe..be49e70 100644 --- a/service/src/sdk.test.ts +++ b/service/src/sdk.test.ts @@ -436,6 +436,78 @@ describe('receiving chat-message', () => { }); }); +// --------------------------------------------------------------------------- +// receiving a webrtc signal +// --------------------------------------------------------------------------- +describe('receiving webrtc signal', () => { + it('decrypts the envelope and delivers it to call-invite subscribers', async () => { + const instance = await buildInitializedInstance(); + await instance.setChannel(ROOM_ID, SECRET, USER_ID); + const cb = jest.fn(); + instance.on('call-invite', cb); + + const envelope = await sealWithDefaultStrategy('signaling', { type: 'call-invite', callId: 'call-1', seq: 1, timestamp: 1 }); + + wireHandlerFor('webrtc-session-description')({ envelope }); + await flushAsync(); + + expect(cb).toHaveBeenCalledWith(expect.objectContaining({ callId: 'call-1' })); + }); + + it('drops a replayed/duplicate signal (same sequence number twice for the same call)', async () => { + const instance = await buildInitializedInstance(); + await instance.setChannel(ROOM_ID, SECRET, USER_ID); + const cb = jest.fn(); + instance.on('call-invite', cb); + + const envelope = await sealWithDefaultStrategy('signaling', { type: 'call-invite', callId: 'call-1', seq: 5, timestamp: 1 }); + const handler = wireHandlerFor('webrtc-session-description'); + + handler({ envelope }); + await flushAsync(); + handler({ envelope }); + await flushAsync(); + + expect(cb).toHaveBeenCalledTimes(1); + }); + + it('drops an out-of-order/lower sequence number signal for the same call', async () => { + const instance = await buildInitializedInstance(); + await instance.setChannel(ROOM_ID, SECRET, USER_ID); + const cb = jest.fn(); + instance.on('call-invite', cb); + const handler = wireHandlerFor('webrtc-session-description'); + + const newer = await sealWithDefaultStrategy('signaling', { type: 'call-invite', callId: 'call-1', seq: 5, timestamp: 1 }); + const older = await sealWithDefaultStrategy('signaling', { type: 'call-invite', callId: 'call-1', seq: 3, timestamp: 1 }); + + handler({ envelope: newer }); + await flushAsync(); + handler({ envelope: older }); + await flushAsync(); + + expect(cb).toHaveBeenCalledTimes(1); + }); + + it('does not drop a signal for a different call id, even with a lower/equal sequence number', async () => { + const instance = await buildInitializedInstance(); + await instance.setChannel(ROOM_ID, SECRET, USER_ID); + const cb = jest.fn(); + instance.on('call-invite', cb); + const handler = wireHandlerFor('webrtc-session-description'); + + const callOne = await sealWithDefaultStrategy('signaling', { type: 'call-invite', callId: 'call-1', seq: 5, timestamp: 1 }); + const callTwo = await sealWithDefaultStrategy('signaling', { type: 'call-invite', callId: 'call-2', seq: 1, timestamp: 1 }); + + handler({ envelope: callOne }); + await flushAsync(); + handler({ envelope: callTwo }); + await flushAsync(); + + expect(cb).toHaveBeenCalledTimes(2); + }); +}); + // --------------------------------------------------------------------------- // createChatInstance() encryption strategy selection // ---------------------------------------------------------------------------