feat(dev-server): opt-in Tailscale preview via dev.json config - #233
feat(dev-server): opt-in Tailscale preview via dev.json config#233theshwal wants to merge 1 commit into
Conversation
Add an optional Tailscale preview to dev servers, enabled per project through `tailscaleExpose` in `.openfox/dev.json`. The preview starts automatically after a successful dev server start, remains non-blocking on Tailscale errors, and is cleaned up on stop, crash, or stopAll without touching pre-existing Serve entries. Add config UI, read-only Tailnet status, unit coverage, and gated Playwright E2E verification for Tailscale-enabled environments.
CI status snapshot —
|
| Check | Status |
|---|---|
lint |
✅ pass |
typecheck |
✅ pass |
duplicate |
✅ pass |
test |
✅ pass |
ai-disclosure |
✅ pass |
windows |
❌ fail |
The only failing check is windows, on the pre-existing flaky test fires close event after killing process group — unrelated to this PR's diff. The test pass-rate on this runner is normally green; the failure is environmental (Windows process-group kill race).
QA_PASS and INT_PASS confirmed on f28999cf43234ec55b4d1796cbd8d1d334fabbfc.
A re-run of the windows job should target the same SHA (no new commit needed).
|
@theshwal My review : Review: consider generic
|
|
Je partage le problème de couplage, mais les hooks seuls perdent la gestion de process, l'URL, l'état et le cleanup sûr. Je propose de refactorer la PR autour d'une abstraction générique de preview/exposure provider, avec Tailscale comme première implémentation. |
Summary
Adds an optional Tailscale preview to the dev server, enabled per project through a new
tailscaleExposeboolean in.openfox/dev.json(defaultfalse).The preview starts automatically after a successful dev server start, remains non-blocking on Tailscale errors, and is cleaned up on stop, crash, or stopAll — without touching pre-existing Serve entries.
Feature
tailscaleExposein.openfox/dev.json— defaults tofalse; existing projects are unaffected.tailscaleExpose: true.stopAll(no orphan entries).tailscalePreview.status: 'error'and do not affect dev server state.Mechanism
foregroundtailscale serveonly — entry disappears naturally with the controlling process. No--bgfallback.stdoutURL is primary source for the Tailnet URL (matches Tailscale's actual exposed entry).tailscale serve status --jsonis used only to:Web/TCPand foreground-ownedForeground[*].Web/TCPentries).tailscale serve --https=<port> off) — neverreset. Pre-existing entries (e.g. 443 → 10369) are never touched.Tests
src/server/dev-server/tailscale-preview.test.ts) — 25 tests covering foreground spawn, stdout URL parsing,Foreground[*]status JSON normalization (with a host-agnostic redacted fixture), targeted inverse, never-reset guarantee, stopAll.src/server/dev-server/manager.test.ts) —tailscaleExposeconfig round-trip, auto-launch fire-and-forget (never blocks on Tailscale error), no auto-launch when absent orfalse, idempotent re-call, stop-coupled cleanup,stopAllcleanup.e2e-playwright/tailscale-preview.spec.tswith a hard gate: tests skip cleanly whenOPENFOX_TS_NODE_HOST/OPENFOX_TS_NODE_IPare unset or when thetailscalebinary / backend is unavailable, so the standard CI suite is not impacted.Blocked request ... allowedHosts(HTTP 403) as a Vite backend compat limitation, not a feature bug.Verification
ffmpeg x11grab— captured window screenshot showing the Tailscale URL in the address bar and the dev-server content (TAILSCALE_PREVIEW_TEST_A) loaded in the same image. Pre-existing 443 entry intact before/after. Screenshots persisted at/home/hermesy/openfox-verify/feature-tailscale-preview-v1.1/(not committed).f28999cf43234ec55b4d1796cbd8d1d334fabbfc.Known limitation (backend compat, not a feature bug)
allowedHosts: when the dev server is Vite (default since v5), Vite returns HTTP 403Blocked request. This host (...) is not allowedbecause theHostheader it sees is the Tailscale MagicDNS hostname. The Tailscale mechanism itself works correctly; users need to add the tailnet host toserver.allowedHostsinvite.config.{js,ts}. Example: seeweb/vite.config.local.ts.examplewhich is already in the repo.Out of scope
tailscale funnel(public HTTPS exposure)tailscaledrestartAI-Enhanced Development
Cache Impact