feat: pairing v2 — one-tap trusted devices over LAN and private relay (#2103)

Reworks how devices connect to an OpenChamber server, end to end.

Pairing v2:
- One-time pairing links/QR codes (openchamber://connect?v=2) carrying a set of transport candidates (LAN/tunnel/relay) and a single-use secret redeemed server-side; no tokens embedded in links
- Add-a-device dialog written for first-time users: intent-based transport choice (Anywhere / Home network only / This computer only) with plain-language descriptions, transparent fallback checkboxes, server-authoritative LAN detection, high-res QR dialog
- Private relay folded into pairing as a transport candidate with a demand-driven lifecycle (enables when a relay device is paired, disables when none remain)

Multi-transport devices:
- A saved device holds all its transports and one token; mobile re-probes on connect, resume, and network change and hot-switches LAN<->relay seamlessly (no re-pairing, no remount, session preserved)
- Desktop can import relay pairing links, switch to relay hosts through the E2EE tunnel, and restore a relay default host after relaunch

Device management:
- Device list (web + desktop) shows live per-device connectivity with the active transport (Connected - Local network / Relay) and platform badges (iOS/Android/macOS/Windows/Linux)
- One physical device = one record: stable per-install dedupe keys across pairing and password re-login; typed pairing label names the device, paired devices name the connection by the issuing server hostname
- Trusted desktop-local client manages all devices (list, revoke, clear revoked); relay host reaps dead client sockets after 3 missed keepalives

Android:
- LAN transport unblocked (cleartext + mixed content, mirroring iOS ATS exceptions); resume re-probe retries through network flux and silently auto-reconnects from a disconnected state
This commit is contained in:
Iuliia Ivashko
2026-07-10 00:12:33 +03:00
committed by GitHub
parent a1aae30e66
commit 91a95bfdaa
53 changed files with 4589 additions and 1369 deletions
@@ -246,21 +246,43 @@
'settings.remoteInstances.direct.state.empty': '尚無直接連線。',
'settings.remoteInstances.clientAuth.title': '用戶端存取 token',
'settings.remoteInstances.clientAuth.description': '建立與管理可讓桌面或遠端用戶端連線的 token。',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '裝置或用戶端名稱',
'settings.remoteInstances.clientAuth.field.labelPlaceholder': '裝置名稱 — 例如 My iPhone',
'settings.remoteInstances.clientAuth.actions.create': '建立 token',
'settings.remoteInstances.clientAuth.actions.pair': '配對裝置',
'settings.remoteInstances.clientAuth.actions.revoke': '撤銷',
'settings.remoteInstances.clientAuth.actions.clearRevoked': '清除已撤銷',
'settings.remoteInstances.clientAuth.qrAlt': '配對 QR code',
'settings.remoteInstances.clientAuth.qrEnlarge': '放大 QR code',
'settings.remoteInstances.clientAuth.qrScanHint': '用另一台裝置上的 OpenChamber 應用程式掃描。一次性使用且會過期。',
'settings.remoteInstances.clientAuth.qrDialogTitle': '掃碼連線',
'settings.remoteInstances.clientAuth.actions.addDevice': '新增裝置',
'settings.remoteInstances.clientAuth.actions.copied': '已複製',
'settings.remoteInstances.clientAuth.addDevice.transportLabel': '你會在哪裡使用這台裝置?',
'settings.remoteInstances.clientAuth.addDevice.subtitle': '建立一次性 QR 代碼,將另一台裝置連線到此伺服器。',
'settings.remoteInstances.clientAuth.addDevice.transport.local': '僅本機',
'settings.remoteInstances.clientAuth.addDevice.transport.localHint': '供同一台電腦上的應用程式使用。',
'settings.remoteInstances.clientAuth.addDevice.transport.lan': '僅家用網路',
'settings.remoteInstances.clientAuth.addDevice.transport.lanHint': '透過 Wi-Fi 直接連線。離開此網路後無法使用。',
'settings.remoteInstances.clientAuth.addDevice.transport.relay': '任何地方',
'settings.remoteInstances.clientAuth.addDevice.transport.relayHint': '在家與外出都可用。外出時流量經由 OpenChamber Private Relay(端對端加密隧道)傳輸,無需設定。',
'settings.remoteInstances.clientAuth.addDevice.fallback.relay': '外出時也允許透過加密中繼連線',
'settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal': '在家時優先使用直接連線',
'settings.remoteInstances.clientAuth.addDevice.create': '建立 QR 代碼',
'settings.remoteInstances.clientAuth.addDevice.done': '完成',
'settings.remoteInstances.clientAuth.pairingUrl': '配對 URL',
'settings.remoteInstances.clientAuth.createdToken': '已建立 token',
'settings.remoteInstances.clientAuth.state.loading': '正在載入用戶端 token...',
'settings.remoteInstances.clientAuth.state.empty': '尚無用戶端 token。',
'settings.remoteInstances.clientAuth.state.revoked': '已撤銷',
'settings.remoteInstances.clientAuth.state.thisDevice': '此裝置',
'settings.remoteInstances.clientAuth.state.pending': '等待連線…',
'settings.remoteInstances.clientAuth.state.viaRelay': 'Relay',
'settings.remoteInstances.clientAuth.state.connectedDirect': '已連線 · 區域網路',
'settings.remoteInstances.clientAuth.state.connectedRelay': '已連線 · 中繼',
'settings.remoteInstances.clientAuth.lastUsed': '上次使用:{date}',
'settings.remoteInstances.clientAuth.neverUsed': '從未使用',
'settings.remoteInstances.relay.title': 'OpenChamber Relay',
'settings.remoteInstances.relay.autoHint': '透過中繼配對裝置時自動開啟。',
'settings.remoteInstances.relay.description': '無需開放連接埠,即可讓你的其他裝置從任何地方連線。流量端對端加密,中繼無法讀取內容。',
'settings.remoteInstances.relay.enableHint': '在此伺服器上啟用中繼之前,不會共享任何內容。',
'settings.remoteInstances.relay.actions.enable': '啟用中繼',