fix(pairing): include the request origin as a direct candidate in pairing links

Creating a device key while the UI is open through a public https domain
(reverse proxy) dropped that domain from the QR payload whenever the
dialog passed a preferred LAN URL, leaving only the local IP and relay
as transports. Carry the non-loopback request origin as an additional
direct candidate (priority 20, between LAN and relay) so paired devices
can keep using the same domain on any network.
This commit is contained in:
Bohdan Triapitsyn
2026-08-12 10:36:59 +03:00
parent 069d9ad5c9
commit 9e43b9ae46
3 changed files with 64 additions and 10 deletions
@@ -331,12 +331,42 @@ describe('core-routes', () => {
});
});
it('advertises the caller-supplied serverUrl as the direct candidate over the request origin', async () => {
it('advertises the caller-supplied serverUrl first and keeps the request origin as a fallback candidate', async () => {
const { app } = createPairingRouteApp();
const response = await request(app)
.post('/api/client-auth/pairing/sessions')
.set('Host', 'runtime.example')
.set('Host', 'chamber.example.com')
.set('X-Forwarded-Proto', 'https')
.send({ label: 'Pair phone', serverUrl: 'http://192.168.1.20:2606' })
.expect(201);
expect(response.body.server.candidates).toEqual([
{ type: 'lan', url: 'http://192.168.1.20:2606', priority: 10 },
{ type: 'tunnel', url: 'https://chamber.example.com', priority: 20 },
]);
});
it('does not duplicate the request origin when it matches the caller-supplied serverUrl', async () => {
const { app } = createPairingRouteApp();
const response = await request(app)
.post('/api/client-auth/pairing/sessions')
.set('Host', '192.168.1.20:2606')
.send({ label: 'Pair phone', serverUrl: 'http://192.168.1.20:2606' })
.expect(201);
expect(response.body.server.candidates).toEqual([
{ type: 'lan', url: 'http://192.168.1.20:2606', priority: 10 },
]);
});
it('skips a loopback request origin as the fallback candidate', async () => {
const { app } = createPairingRouteApp();
const response = await request(app)
.post('/api/client-auth/pairing/sessions')
.set('Host', '127.0.0.1:2606')
.send({ label: 'Pair phone', serverUrl: 'http://192.168.1.20:2606' })
.expect(201);