feat: redesign remote tunnel settings and named tunnel workflow (#546)

* feat: add Cloudflare Tunnel settings for desktop app

Add a 'Remote Tunnel' section in Settings (desktop-only) that lets users
start/stop a Cloudflare quick tunnel on demand, with auto-generated
password protection and a QR code for easy mobile access.

- Server: 4 new API endpoints (check/status/start/stop) reusing the
  existing cloudflare-tunnel module
- UI: TunnelSettings component with full state machine
  (checking → idle/not-available → starting → active → stopping)
- QR code rendered via the qrcode package for in-app display
- Hidden from VS Code extension (desktop/web only)

* fix: use ?token= instead of ?p= in tunnel password URLs

REST API endpoints were building passwordUrl with ?p=<token> but
SessionAuthGate reads the ?token= query param, causing QR code
auto-login to fail — the password was never extracted from the URL.

Standardize all three tunnel URL construction sites to use ?token=
so scanning the QR code correctly pre-fills and submits the password.

* feat: secure remote tunnel access with one-time connect links

* feat: redesign remote tunnel settings and access flow

* fix: cleaned up unused desktop close code path

* feat: overhaul named tunnel setup and persistence flow

* chore: align codemirror language dependency resolution

---------

Co-authored-by: Brian-Hwang <brian.hwang@cornelisnetworks.com>
This commit is contained in:
Iuliia Ivashko
2026-02-28 04:21:46 +02:00
committed by GitHub
co-authored by Brian-Hwang
parent a505378d79
commit d5d0d35083
15 changed files with 2853 additions and 150 deletions
@@ -8,6 +8,7 @@ import { GitSettings } from './GitSettings';
import { NotificationSettings } from './NotificationSettings';
import { GitHubSettings } from './GitHubSettings';
import { VoiceSettings } from './VoiceSettings';
import { TunnelSettings } from './TunnelSettings';
import { OpenCodeCliSettings } from './OpenCodeCliSettings';
import { KeyboardShortcutsSettings } from './KeyboardShortcutsSettings';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
@@ -75,6 +76,8 @@ export const OpenChamberPage: React.FC<OpenChamberPageProps> = ({ section }) =>
return <NotificationSectionContent />;
case 'voice':
return <VoiceSectionContent />;
case 'tunnel':
return <TunnelSectionContent />;
default:
return null;
}
@@ -157,3 +160,10 @@ const VoiceSectionContent: React.FC = () => {
}
return <VoiceSettings />;
};
const TunnelSectionContent: React.FC = () => {
if (isVSCodeRuntime()) {
return null;
}
return <TunnelSettings />;
};
File diff suppressed because it is too large Load Diff
@@ -6,4 +6,5 @@ export type OpenChamberSection =
| 'git'
| 'github'
| 'notifications'
| 'voice';
| 'voice'
| 'tunnel';