| ... | @@ -304,9 +304,9 @@ describe("DesktopServerExposure", () => { | ... | @@ -304,9 +304,9 @@ describe("DesktopServerExposure", () => { |
| 304 | ); | 304 | ); |
| 305 | }); | 305 | }); |
| 306 | | 306 | |
| 307 | it.effect("resolves advertised endpoints from the scoped runtime state", () => | 307 | it.effect("keeps LAN and Tailscale endpoints distinct when Tailscale is enumerated first", () => |
| 308 | withHarness( | 308 | withHarness( |
| 309 | { ...lanNetworkInterfaces, ...tailnetNetworkInterfaces }, | 309 | { ...tailnetNetworkInterfaces, ...lanNetworkInterfaces }, |
| 310 | Effect.gen(function* () { | 310 | Effect.gen(function* () { |
| 311 | const serverExposure = yield* DesktopServerExposure.DesktopServerExposure; | 311 | const serverExposure = yield* DesktopServerExposure.DesktopServerExposure; |
| 312 | yield* serverExposure.configureFromSettings({ port: 4173 }); | 312 | yield* serverExposure.configureFromSettings({ port: 4173 }); |
| ... | @@ -321,6 +321,32 @@ describe("DesktopServerExposure", () => { | ... | @@ -321,6 +321,32 @@ describe("DesktopServerExposure", () => { |
| 321 | ), | 321 | ), |
| 322 | ); | 322 | ); |
| 323 | | 323 | |
| | 324 | it.effect("keeps Tailscale-only hosts network-accessible", () => |
| | 325 | withHarness( |
| | 326 | tailnetNetworkInterfaces, |
| | 327 | Effect.gen(function* () { |
| | 328 | const serverExposure = yield* DesktopServerExposure.DesktopServerExposure; |
| | 329 | const settings = yield* DesktopAppSettings.DesktopAppSettings; |
| | 330 | yield* settings.setServerExposureMode("network-accessible"); |
| | 331 | |
| | 332 | const state = yield* serverExposure.configureFromSettings({ port: 4173 }); |
| | 333 | assert.equal(state.mode, "network-accessible"); |
| | 334 | assert.equal(state.advertisedHost, null); |
| | 335 | assert.equal(state.endpointUrl, null); |
| | 336 | assert.equal((yield* serverExposure.backendConfig).bindHost, "0.0.0.0"); |
| | 337 | |
| | 338 | const endpoints = yield* serverExposure.getAdvertisedEndpoints; |
| | 339 | assert.deepEqual( |
| | 340 | endpoints.map((endpoint) => [endpoint.reachability, endpoint.httpBaseUrl]), |
| | 341 | [ |
| | 342 | ["loopback", "http://127.0.0.1:4173/"], |
| | 343 | ["private-network", "http://100.90.1.2:4173/"], |
| | 344 | ], |
| | 345 | ); |
| | 346 | }), |
| | 347 | ), |
| | 348 | ); |
| | 349 | |
| 324 | it.effect("does not spawn the tailscale CLI while server exposure is local-only", () => | 350 | it.effect("does not spawn the tailscale CLI while server exposure is local-only", () => |
| 325 | withHarness( | 351 | withHarness( |
| 326 | lanNetworkInterfaces, | 352 | lanNetworkInterfaces, |
| ... | @@ -342,7 +368,7 @@ describe("DesktopServerExposure", () => { | ... | @@ -342,7 +368,7 @@ describe("DesktopServerExposure", () => { |
| 342 | ), | 368 | ), |
| 343 | ); | 369 | ); |
| 344 | | 370 | |
| 345 | it.effect("uses ConfigProvider desktop exposure overrides", () => | 371 | it.effect("preserves explicit Tailscale exposure overrides", () => |
| 346 | withHarness( | 372 | withHarness( |
| 347 | lanNetworkInterfaces, | 373 | lanNetworkInterfaces, |
| 348 | Effect.gen(function* () { | 374 | Effect.gen(function* () { |
| ... | @@ -350,17 +376,17 @@ describe("DesktopServerExposure", () => { | ... | @@ -350,17 +376,17 @@ describe("DesktopServerExposure", () => { |
| 350 | yield* serverExposure.configureFromSettings({ port: 4173 }); | 376 | yield* serverExposure.configureFromSettings({ port: 4173 }); |
| 351 | const change = yield* serverExposure.setMode("network-accessible"); | 377 | const change = yield* serverExposure.setMode("network-accessible"); |
| 352 | | 378 | |
| 353 | assert.equal(change.state.advertisedHost, "10.0.0.7"); | 379 | assert.equal(change.state.advertisedHost, "100.90.1.2"); |
| 354 | assert.equal(change.state.endpointUrl, "http://10.0.0.7:4173"); | 380 | assert.equal(change.state.endpointUrl, "http://100.90.1.2:4173"); |
| 355 | | 381 | |
| 356 | const endpoints = yield* serverExposure.getAdvertisedEndpoints; | 382 | const endpoints = yield* serverExposure.getAdvertisedEndpoints; |
| 357 | assert.deepEqual( | 383 | assert.deepEqual( |
| 358 | endpoints.map((endpoint) => endpoint.httpBaseUrl), | 384 | endpoints.map((endpoint) => endpoint.httpBaseUrl), |
| 359 | ["http://127.0.0.1:4173/", "http://10.0.0.7:4173/", "https://public.example.test/"], | 385 | ["http://127.0.0.1:4173/", "http://100.90.1.2:4173/", "https://public.example.test/"], |
| 360 | ); | 386 | ); |
| 361 | }), | 387 | }), |
| 362 | { | 388 | { |
| 363 | T3CODE_DESKTOP_LAN_HOST: "10.0.0.7", | 389 | T3CODE_DESKTOP_LAN_HOST: "100.90.1.2", |
| 364 | T3CODE_DESKTOP_HTTPS_ENDPOINTS: "https://public.example.test", | 390 | T3CODE_DESKTOP_HTTPS_ENDPOINTS: "https://public.example.test", |
| 365 | }, | 391 | }, |
| 366 | ), | 392 | ), |