Skip to content

fix(web): Tailscale HTTPS can be turned on while Network access is off - #26170

Closed
juliusmarminge wants to merge 3 commits into
mainfrom
fix/issue-26136
Closed

juliusmarminge wants to merge 3 commits into
mainfrom
fix/issue-26136

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Problem

In the desktop app, Settings → Sharing & access, the Tailscale HTTPS row shows "Turn on Network access to detect Tailscale." and no switch while Network access is off. To get tailnet HTTPS without exposing the backend on LAN, a user has to turn Network access on (binds 0.0.0.0, relaunch), enable Tailscale HTTPS, then turn Network access off again (another relaunch). Reproduced on main 5808469018 in the Linux Electron app on a fresh database, with Tailscale running with MagicDNS and HTTPS.

Change

When the desktop skipped Tailscale detection (Network access off, Serve off), the row now shows an unchecked switch. It opens the existing "Set up Tailscale HTTPS?" dialog without an endpoint, which shows its existing "Pending MagicDNS endpoint" fallback. Confirming calls the existing setTailscaleServeEnabled({ enabled: true, port }). Detection still only runs after that explicit action, so the no-prompt-by-default behaviour from https://git.cafe/pingdotgg/t3code/pulls/2745 is unchanged.

So that turning it on is not a one-way door: when Serve is on but no Tailscale HTTPS endpoint is found (Tailscale stopped), the row keeps a checked switch that opens the existing disable dialog. On main that state had no switch at all.

The row's decision lives in a pure helper, missingTailscaleEndpointRow, in ConnectionsSettings.logic.ts, replacing missingTailscaleEndpointDescription. The setup dialog's open state no longer depends on having an endpoint. The branch where an endpoint exists is unchanged. No contract, IPC or desktop change.

Scope and approval

Fixes #26136

Follow-up to the accepted scope on https://git.cafe/pingdotgg/t3code/issues/18753 ("offer an explicit on-demand action … keeps the no-prompt-by-default guarantee").

Verification

  • vp test run apps/web/src/components/settings/ConnectionsSettings.logic.test.ts: 11 pass. The four missingTailscaleEndpointRow cases cover detection skipped (unchecked switch, Serve copy), state unknown (no switch), Serve on with no endpoint (checked switch), and Network access on with nothing found (no switch, as on main).
  • vp run check:changed: format, lint, knip, typecheck and tests pass.
  • Real Linux desktop (Electron under Xvfb), fresh database per side, Tailscale running with MagicDNS. Before = 5808469018, after = d437f84d37 (this branch before merging main).

Evidence (1440×1000 dark; light and 840×620 in the full evidence index)

R3: Network access off, Serve off (the reported state)

Viewport / theme Before After Diff0 DiffT
1440x1000-dark R3-before-1440x1000-dark
5808469018
R3-after-1440x1000-dark
d437f84d37
R3-1440x1000-dark-diff0
5808469018 → d437f84d37
R3-1440x1000-dark-diffT
5808469018 → d437f84d37

S1: switch → setup dialog without an endpoint

Viewport / theme Before After Diff0 DiffT
1440x1000-dark cancel-before-1440x1000-dark-no-control
5808469018
cancel-after-1440x1000-dark-dialog
d437f84d37
S1-1440x1000-dark-diff0
5808469018 → d437f84d37
S1-1440x1000-dark-diffT
5808469018 → d437f84d37

R5: Serve on, no Tailscale endpoint (stopped-Tailscale CLI stub on PATH, real app). Before there is no way to turn Serve off; after there is a checked switch

Viewport / theme Before After Diff0 DiffT
1440x1000-dark R5-before-1440x1000-dark
5808469018
R5-after-1440x1000-dark
d437f84d37
R5-1440x1000-dark-diff0
5808469018 → d437f84d37
R5-1440x1000-dark-diffT
5808469018 → d437f84d37

O1: the checked switch opens the disable confirmation

Viewport / theme Before After Diff0 DiffT
1440x1000-dark disable-cancel-before-1440x1000-dark-no-control
5808469018
disable-cancel-after-1440x1000-dark-dialog
d437f84d37
O1-1440x1000-dark-diff0
5808469018 → d437f84d37
O1-1440x1000-dark-diffT
5808469018 → d437f84d37

R6 control: endpoint present (unavailable), unchanged code path. 0 changed pixels at threshold 0 in all four viewport/theme variants

Viewport / theme Before After Diff0 DiffT
1440x1000-dark R6-before-1440x1000-dark
5808469018
R6-after-1440x1000-dark
d437f84d37
R6-1440x1000-dark-diff0
5808469018 → d437f84d37
R6-1440x1000-dark-diffT
5808469018 → d437f84d37

Recordings (1440×1000 dark)

Scripts: launch.sh · driver.mjs · flows.mjs · seed.mjs. Environment: Electron 44.9.3 / Chromium 152, Xvfb, DPR 1, no emulation; 840×620 is Electron's minimum usable window.

What else changed: at 840 px the new switch stacks under the row text, moving Permissions and Authorized clients down 30 px and adding a scrollbar. S12's post-Cancel frames differ by 1–2/255 on 22–29 panel-corner pixels, which disappear at threshold 8.

Not verified:

  • cannot-verify macos: the macOS privacy prompt itself. By code, the CLI is spawned only after Enable sets tailscaleServeEnabled.
  • A successful Serve proxy: the VM user is not the Tailscale operator, so tailscale serve fails with permission-denied and the detected endpoint stays unavailable.
  • Not captured, because these paths reuse unchanged dialog code: invalid port, pending and rejected setup/disable states, a completed disable from the no-endpoint state, reopen-after-edit reset, and the sub-640 px dialog layout.

Implemented with Claude Opus 5.5, reviewed with GPT-6.1 Sol and Claude Opus 5.5, evidence by GPT-6.1 Sol, coordinated by Claude Opus 5.5 in T3 Code (Claude Code harness).

🤖 Generated with Claude Code

juliusmarminge and others added 3 commits October 27, 2026 21:12
With Network access off and Tailscale Serve never enabled, the desktop
skips Tailscale detection, so the Tailscale HTTPS row showed "Turn on
Network access to detect Tailscale." and no switch. Enabling HTTPS meant
toggling Network access on and off again.

The row now shows an unchecked switch in that state, and the setup dialog
can open without a detected endpoint. While Serve is enabled but no
endpoint is found, a checked switch stays so Serve can be turned off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 27, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 8250c90

Macroscope's review found this PR approvable — Tailscale HTTPS can now be explicitly enabled while Network access is off, even before endpoint discovery. Existing confirmation and authorization checks remain, and access defaults are unchanged.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 3b22620 and 8250c90.

Files selected for processing: 3
  • apps/web/src/components/settings/ConnectionsSettings.logic.test.ts
  • apps/web/src/components/settings/ConnectionsSettings.logic.ts
  • apps/web/src/components/settings/ConnectionsSettings.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

Walkthrough

The Tailscale HTTPS settings row can now start setup when no advertised endpoint is available. A fallback helper supplies the row description and switch state, and the setup flow tracks a nullable endpoint.

Changes: Tailscale HTTPS setup

Layer / File(s) Summary
Fallback description and switch state
apps/web/src/components/settings/ConnectionsSettings.logic.ts, apps/web/src/components/settings/ConnectionsSettings.logic.test.ts
The fallback helper returns a description and switch state. Tests cover local-only, unknown, Serve-enabled, and network-accessible states.
Endpoint-optional settings flow
apps/web/src/components/settings/ConnectionsSettings.tsx
Pending setup now stores a nullable endpoint. When no endpoint exists, the row uses the fallback description and switch state, and the setup dialog opens from the pending setup state.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

Suggested labels: bugfix, size:M

Suggested reviewers: mnigos, maria-rcks

Merge Risk: Minimal · up to 8250c

Users can open Tailscale HTTPS setup while Network access is off and confirm it without an endpoint. No merge-blocking issue was identified.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title follows the conventional commit format and names the primary change: Tailscale HTTPS can now be turned on while Network access is off. It matches the raw summary, which adds an unchecked swi…
Description check Passed The description follows the repository template. It has Problem, Change, Scope and approval, and Verification sections. The Problem section gives the observed behavior, the environment, and the reprod…
Linked Issues check Passed For #26136, the whole-PR diff adds missingTailscaleEndpointRow and tests the skipped-detection, unknown-state, Serve-enabled, and network-accessible cases. In ConnectionsSettings.tsx, the skipped-…
Out of Scope Changes check Passed The whole-PR diff changes only the Tailscale row logic, its dialog state needed for a nullable endpoint, and focused automated tests. These changes directly support #26136. No unrelated behavior, cont…
Full details: Title check

Explanation

The title follows the conventional commit format and names the primary change: Tailscale HTTPS can now be turned on while Network access is off. It matches the raw summary, which adds an unchecked switch that opens the setup dialog without an endpoint when Network access and Serve are off. The title is 70 characters, within a reasonable length for a commit subject.

Full details: Description check

Explanation

The description follows the repository template. It has Problem, Change, Scope and approval, and Verification sections. The Problem section gives the observed behavior, the environment, and the reproduction steps. The Change section explains the fix and why detection stays behind an explicit action. The Scope section links the issue and the accepted scope. The Verification section lists focused tests, the check run, and the Linux Electron evidence with before and after screenshots. It also lists what was not verified. The description states that the macOS privacy prompt and a successful Serve proxy were not verified. The template asks for a model and harness line, and the description includes one. Minor point: the Scope section links an issue (#26136) and a follow-up scope issue, which satisfies the requirement for a linked triaged issue.

Full details: Linked Issues check

Explanation

For #26136, the whole-PR diff adds missingTailscaleEndpointRow and tests the skipped-detection, unknown-state, Serve-enabled, and network-accessible cases. In ConnectionsSettings.tsx, the skipped-detection case renders an unchecked switch, passes a nullable endpoint to the existing setup dialog, and keeps the existing Serve enable path. The diff does not change detection or add a contract, IPC, or desktop change. This preserves the explicit-action requirement and the no-prompt-by-default behavior from the contextual #18753 scope.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff changes only the Tailscale row logic, its dialog state needed for a nullable endpoint, and focused automated tests. These changes directly support #26136. No unrelated behavior, contract, IPC, or desktop changes are present.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge juliusmarminge added bugfix Fix PR opened by an issue lead; enters the PR loop pr:needs-julius Needs Julius: route gate, unverifiable surface, or blocked labels Oct 28, 2026
@t3dotgg

t3dotgg commented Oct 29, 2026

Copy link
Copy Markdown
Member

Note

🤖 Claude Opus 5.5 responding on behalf of Theo

Superseded by #26757, which folds in turning on Tailscale HTTPS while Network access is off. You are credited with a Co-authored-by trailer. Closing this so the two don't conflict.

@t3dotgg t3dotgg closed this Oct 29, 2026
@juliusmarminge juliusmarminge removed the pr:needs-julius Needs Julius: route gate, unverifiable surface, or blocked label Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tailscale HTTPS still can't be turned on without first turning on Network access (follow-up to #18753)

2 participants