From 60f425a4fc99afa7d8a24522d5d2fd20a66b1a97 Mon Sep 17 00:00:00 2001 From: Stefano Fiorini Date: Thu, 12 Mar 2026 02:28:57 -0500 Subject: [PATCH] fix: stabilize mac nordvpn state reporting --- .../nordvpn-client/scripts/nordvpn-client.js | 29 ++++++++++++++- .../scripts/nordvpn-client.test.js | 35 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/skills/nordvpn-client/scripts/nordvpn-client.js b/skills/nordvpn-client/scripts/nordvpn-client.js index 33ae311..fc73fa9 100644 --- a/skills/nordvpn-client/scripts/nordvpn-client.js +++ b/skills/nordvpn-client/scripts/nordvpn-client.js @@ -371,6 +371,32 @@ function shouldAttemptMacWireguardDisconnect(wireguardState) { return Boolean(wireguardState.configPath || wireguardState.endpoint || wireguardState.lastConnection); } +function normalizeSuccessfulConnectState(state, connectResult, verified) { + if ( + !state || + state.platform !== "darwin" || + state.controlMode !== "wireguard" || + !connectResult || + connectResult.backend !== "wireguard" || + !verified || + !verified.ok + ) { + return state; + } + + return { + ...state, + connected: true, + wireguard: state.wireguard + ? { + ...state.wireguard, + active: true, + endpoint: connectResult.server && connectResult.server.hostname ? `${connectResult.server.hostname}:51820` : state.wireguard.endpoint, + } + : state.wireguard, + }; +} + function fetchJson(url, headers = {}) { return new Promise((resolve) => { const targetUrl = new URL(url); @@ -1311,6 +1337,7 @@ async function main() { const verified = await verifyConnectionWithRetry(target, { attempts: 6, delayMs: 2000 }); const refreshed = await probeInstallation(platform); + const connectState = normalizeSuccessfulConnectState(buildStateSummary(refreshed, verified.ipInfo), connectResult, verified); printJson( { action, @@ -1318,7 +1345,7 @@ async function main() { connectResult, verified: verified.ok, verification: verified.ipInfo, - state: buildStateSummary(refreshed, verified.ipInfo), + state: connectState, }, verified.ok ? 0 : 1, !verified.ok diff --git a/skills/nordvpn-client/scripts/nordvpn-client.test.js b/skills/nordvpn-client/scripts/nordvpn-client.test.js index 0fd608f..70ce46d 100644 --- a/skills/nordvpn-client/scripts/nordvpn-client.test.js +++ b/skills/nordvpn-client/scripts/nordvpn-client.test.js @@ -21,6 +21,8 @@ module.exports = { typeof getMacTailscalePath === "function" ? getMacTailscalePath : undefined, isMacTailscaleActive: typeof isMacTailscaleActive === "function" ? isMacTailscaleActive : undefined, + normalizeSuccessfulConnectState: + typeof normalizeSuccessfulConnectState === "function" ? normalizeSuccessfulConnectState : undefined, shouldAttemptMacWireguardDisconnect: typeof shouldAttemptMacWireguardDisconnect === "function" ? shouldAttemptMacWireguardDisconnect : undefined, detectMacWireguardActiveFromIfconfig: @@ -167,6 +169,39 @@ test("shouldAttemptMacWireguardDisconnect does not trust active=false when resid ); }); +test("normalizeSuccessfulConnectState marks the connect snapshot active after verified macOS wireguard connect", () => { + const { normalizeSuccessfulConnectState } = loadInternals(); + assert.equal(typeof normalizeSuccessfulConnectState, "function"); + + const state = normalizeSuccessfulConnectState( + { + platform: "darwin", + controlMode: "wireguard", + connected: false, + wireguard: { + active: false, + endpoint: null, + }, + }, + { + backend: "wireguard", + server: { + hostname: "de1227.nordvpn.com", + }, + }, + { + ok: true, + ipInfo: { + country: "Germany", + }, + } + ); + + assert.equal(state.connected, true); + assert.equal(state.wireguard.active, true); + assert.equal(state.wireguard.endpoint, "de1227.nordvpn.com:51820"); +}); + test("isMacTailscaleActive treats Running backend as active", () => { const { isMacTailscaleActive } = loadInternals(); assert.equal(typeof isMacTailscaleActive, "function");