fix(mobile-pairing): isolate auth notification failures

This commit is contained in:
Brennan Benson
2026-07-21 19:02:14 -07:00
parent 6bc4483995
commit ae2dc1d2f8
2 changed files with 27 additions and 9 deletions
@@ -139,12 +139,16 @@ describe('MobileSocketWiring', () => {
expect(wiring.connectionCount).toBe(0)
})
it('reports an unknown device token on the direct path and closes 4001', () => {
it('closes an unknown-token socket even when reporting the failure throws', () => {
const desktop = generateKeyPair()
const phone = generateKeyPair()
const ws = new FakeSocket()
const transport = new FakeTransport()
const onUnpairedDeviceAuthFailure = vi.fn()
const notificationError = new Error('renderer exited')
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
const onUnpairedDeviceAuthFailure = vi.fn(() => {
throw notificationError
})
const wiring = new MobileSocketWiring({
deviceRegistry: registryFor('device-1', 'valid-token'),
e2eeKeypair: {
@@ -167,15 +171,23 @@ describe('MobileSocketWiring', () => {
})
)
const sharedKey = deriveSharedKey(phone.secretKey, desktop.publicKey)
transport.receive(
ws,
encrypt(JSON.stringify({ type: 'e2ee_auth', deviceToken: 'stale-token' }), sharedKey)
)
expect(() =>
transport.receive(
ws,
encrypt(JSON.stringify({ type: 'e2ee_auth', deviceToken: 'stale-token' }), sharedKey)
)
).not.toThrow()
expect(onUnpairedDeviceAuthFailure).toHaveBeenCalledOnce()
expect(onUnpairedDeviceAuthFailure).toHaveBeenCalledWith({ transport: 'direct' })
expect(consoleError).toHaveBeenCalledWith(
'[mobile] Failed to report unpaired-device auth failure:',
notificationError
)
expect(transport.setClientId).not.toHaveBeenCalled()
expect(ws.close).toHaveBeenCalledWith(4001, 'Unauthorized')
expect(wiring.channelCount).toBe(0)
consoleError.mockRestore()
})
it('reports auth encrypted to a stale desktop key on the direct path', () => {
+9 -3
View File
@@ -155,12 +155,18 @@ export class MobileSocketWiring {
this.onReady?.(socket)
},
onError: (code, reason) => {
if (code === 4001 && reason === 'Unauthorized') {
this.onUnpairedDeviceAuthFailure?.(metadata)
}
const reportUnpairedDevice = code === 4001 && reason === 'Unauthorized'
this.channels.get(ws)?.destroy()
this.channels.delete(ws)
ws.close(code, reason)
if (reportUnpairedDevice) {
try {
this.onUnpairedDeviceAuthFailure?.(metadata)
} catch (error) {
// Why: renderer teardown can make UI delivery throw; auth cleanup must remain authoritative.
console.error('[mobile] Failed to report unpaired-device auth failure:', error)
}
}
}
})
channel.onMessage((plaintext, reply, sendBinary) => {