fix(desktop): boot relay-paired default hosts without the recovery wall

The startup path probed a relay host's stored direct URL — often the
pairing creator's own loopback — and any failure landed on the Remote
Server Unreachable screen before the renderer's relay restore could run.
A relay-capable default host now boots to main on the local substrate for
any failed direct probe (unreachable, wrong-service, incompatible), skips
the 10s second probe, and lets the renderer's existing restore pick
direct-or-relay.
This commit is contained in:
Bohdan Triapitsyn
2026-08-26 23:10:37 +03:00
parent 11dd8c4eb0
commit 4b0fcfaa7b
2 changed files with 25 additions and 2 deletions
+23 -2
View File
@@ -1770,6 +1770,15 @@ const computeBootOutcome = ({ envTargetUrl, probe, config, localAvailable }) =>
: probe?.status === 'wrong-service'
? 'wrong-service'
: 'ok';
// A relay-capable host is not a recovery case just because its stored
// direct URL failed the http probe — that URL is often the pairing
// creator's own loopback (unreachable here, or worse, someone else's
// service). The relay leg is activated in the renderer's relay restore,
// which cannot run from a recovery screen: boot to main on the local
// substrate and let it pick direct-or-relay.
if (status !== 'ok' && sanitizeHostRelayForStorage(host.relay)) {
return { target: 'remote', status: 'ok', hostId: host.id, url: host.apiUrl || host.url, ...availability };
}
return { target: 'remote', status, hostId: host.id, url: host.apiUrl || host.url, ...availability };
};
@@ -3025,12 +3034,24 @@ const resolveInitialUrl = async () => {
}
}
const defaultHostRelayCapable = Boolean(
config.defaultHostId
&& config.defaultHostId !== LOCAL_HOST_ID
&& sanitizeHostRelayForStorage(config.hosts.find((entry) => entry.id === config.defaultHostId)?.relay),
);
if (apiBaseUrl && apiBaseUrl !== localUrl) {
remoteProbe = await probeHostWithTimeout(apiBaseUrl, 2_000, clientToken, requestHeaders);
if (remoteProbe.status === 'unreachable') {
if (remoteProbe.status === 'unreachable' && !defaultHostRelayCapable) {
remoteProbe = await probeHostWithTimeout(apiBaseUrl, 10_000, clientToken, requestHeaders);
}
if (remoteProbe.status === 'unreachable') {
// The renderer's relay restore owns transport selection for relay-capable
// hosts; any failed direct probe falls back to the local substrate.
if (remoteProbe.status !== 'ok' && defaultHostRelayCapable) {
apiBaseUrl = localUrl || '';
clientToken = localUrl ? readDesktopLocalClientToken() : '';
requestHeaders = {};
initialUrl = localUiUrl;
} else if (remoteProbe.status === 'unreachable') {
state.unreachableHosts.add(apiBaseUrl);
apiBaseUrl = localUrl || '';
clientToken = localUrl ? readDesktopLocalClientToken() : '';