| ... | ... | @@ -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 | 308 | withHarness( |
| 309 | | { ...lanNetworkInterfaces, ...tailnetNetworkInterfaces }, |
| 309 | { ...tailnetNetworkInterfaces, ...lanNetworkInterfaces }, |
| 310 | 310 | Effect.gen(function* () { |
| 311 | 311 | const serverExposure = yield* DesktopServerExposure.DesktopServerExposure; |
| 312 | 312 | yield* serverExposure.configureFromSettings({ port: 4173 }); |
| ... | ... | @@ -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 | 350 | it.effect("does not spawn the tailscale CLI while server exposure is local-only", () => |
| 325 | 351 | withHarness( |
| 326 | 352 | lanNetworkInterfaces, |
| ... | ... | @@ -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 | 372 | withHarness( |
| 347 | 373 | lanNetworkInterfaces, |
| 348 | 374 | Effect.gen(function* () { |
| ... | ... | @@ -350,17 +376,17 @@ describe("DesktopServerExposure", () => { |
| 350 | 376 | yield* serverExposure.configureFromSettings({ port: 4173 }); |
| 351 | 377 | const change = yield* serverExposure.setMode("network-accessible"); |
| 352 | 378 | |
| 353 | | assert.equal(change.state.advertisedHost, "10.0.0.7"); |
| 354 | | assert.equal(change.state.endpointUrl, "http://10.0.0.7:4173"); |
| 379 | assert.equal(change.state.advertisedHost, "100.90.1.2"); |
| 380 | assert.equal(change.state.endpointUrl, "http://100.90.1.2:4173"); |
| 355 | 381 | |
| 356 | 382 | const endpoints = yield* serverExposure.getAdvertisedEndpoints; |
| 357 | 383 | assert.deepEqual( |
| 358 | 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 | 390 | T3CODE_DESKTOP_HTTPS_ENDPOINTS: "https://public.example.test", |
| 365 | 391 | }, |
| 366 | 392 | ), |