dsh-mobile 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.7.1 - 2026-10-29
6
+
7
+ - Reorganize **Mobile access** into a compact channel list and configuration pane, stacked on narrow screens. Device management has its own LAN/remote tabs beside Diagnostics; keyboard focus and Escape follow the open panel.
8
+ - Keep the three main actions in one row, including iroh link copying. Copy remains visible but disabled without valid pairing data; component-dependent actions stay hidden before installation.
9
+ - Improve cloudflared quick/named tunnel switching, expandable settings and tunnel notes. **Save and connect** saves and enables the selected provider in one queued operation; connection readiness remains visible separately. Protect pending edits from duplicate actions and stale reads, and keep incomplete named settings editable.
10
+ - Show the server-issued expiry for LAN and HTTPS remote pairing codes, remove expired QR codes, and reuse the displayed code when copying its link. Generating another code still invalidates the previous one. Thanks @jackfocus15-spec for [#285](https://github.com/saya-ch/dsh-mobile/issues/285).
11
+ - Keep the collapsed navigation rail clear of the conversation between the phone and wide-layout breakpoints, without taking 56 px away from phone content. A collapsed phone drawer no longer leaves a transparent strip intercepting conversation input. Thanks @wintekk for [#306](https://github.com/saya-ch/dsh-mobile/issues/306).
12
+ - Allow removal of the plugin-downloaded iroh component after remote access is turned off. The authenticated Host route also refuses removal while enabled; identities, pairings and external companion installations are retained.
13
+ - Display published APK sizes when available. This optional lookup runs independently of release status and package installation and is cancelled when the plugin stops.
14
+ - Add practical Android VPN/proxy troubleshooting for iroh, including per-app bypass and the limits of domain-only rules. Thanks @ZinChl for [#308](https://github.com/saya-ch/dsh-mobile/issues/308).
15
+
5
16
  ## 0.7.0 - 2026-10-28
6
17
 
7
18
  - Distribute the iroh sidecar from this plugin. **Install official component** downloads the pinned `dsh-mobile-iroh 0.1.0-alpha.1` release per platform, verifies byte length and SHA-256, and promotes it into the plugin private directory with backup and rollback; a verified companion copy is reused without downloading during the transition, and switching the channel on alone never downloads. The panel names the download size, reports verification progress, and identifies the exact missing/invalid/offline failure instead of a generic not-ready message.
package/CONTRIBUTORS.md CHANGED
@@ -159,6 +159,7 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
159
159
  | [@hpsks416](https://github.com/hpsks416) | [#132](https://github.com/saya-ch/dsh-mobile/issues/132) |
160
160
  | [@idoall](https://github.com/idoall) | [#42](https://github.com/saya-ch/dsh-mobile/issues/42), [#45](https://github.com/saya-ch/dsh-mobile/issues/45), [#46](https://github.com/saya-ch/dsh-mobile/issues/46), [#47](https://github.com/saya-ch/dsh-mobile/issues/47), [#62](https://github.com/saya-ch/dsh-mobile/issues/62), [#64](https://github.com/saya-ch/dsh-mobile/issues/64) |
161
161
  | [@IvyC-zz](https://github.com/IvyC-zz) | [#58](https://github.com/saya-ch/dsh-mobile/issues/58), [#78](https://github.com/saya-ch/dsh-mobile/issues/78) |
162
+ | [@jackfocus15-spec](https://github.com/jackfocus15-spec) | [#285](https://github.com/saya-ch/dsh-mobile/issues/285) |
162
163
  | [@jillkayat](https://github.com/jillkayat) | [#10](https://github.com/saya-ch/dsh-mobile/issues/10) |
163
164
  | [@jonaskilli](https://github.com/jonaskilli) | [#198](https://github.com/saya-ch/dsh-mobile/issues/198) |
164
165
  | [@jueruibo](https://github.com/jueruibo) | [#101](https://github.com/saya-ch/dsh-mobile/issues/101) |
@@ -184,6 +185,7 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
184
185
  | [@Surpass567](https://github.com/Surpass567) | [#80](https://github.com/saya-ch/dsh-mobile/issues/80), [#81](https://github.com/saya-ch/dsh-mobile/issues/81) |
185
186
  | [@Void-LifeStream](https://github.com/Void-LifeStream) | [#205](https://github.com/saya-ch/dsh-mobile/issues/205), [#219](https://github.com/saya-ch/dsh-mobile/issues/219), [#225](https://github.com/saya-ch/dsh-mobile/issues/225), [#234](https://github.com/saya-ch/dsh-mobile/issues/234) |
186
187
  | [@WalkerJay666](https://github.com/WalkerJay666) | [#201](https://github.com/saya-ch/dsh-mobile/issues/201) |
188
+ | [@wintekk](https://github.com/wintekk) | [#306](https://github.com/saya-ch/dsh-mobile/issues/306) |
187
189
  | [@up-and-down-0618](https://github.com/up-and-down-0618) | [#115](https://github.com/saya-ch/dsh-mobile/issues/115) |
188
190
  | [@taki-ohh](https://github.com/taki-ohh) | [#19](https://github.com/saya-ch/dsh-mobile/issues/19) |
189
191
  | [@tianyimc](https://github.com/tianyimc) | [#126](https://github.com/saya-ch/dsh-mobile/issues/126) |
@@ -191,3 +193,4 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
191
193
  | [@xhwxt](https://github.com/xhwxt) | [#107](https://github.com/saya-ch/dsh-mobile/issues/107), [#108](https://github.com/saya-ch/dsh-mobile/issues/108), [#145](https://github.com/saya-ch/dsh-mobile/issues/145), [#146](https://github.com/saya-ch/dsh-mobile/issues/146), [#149](https://github.com/saya-ch/dsh-mobile/issues/149), [#171](https://github.com/saya-ch/dsh-mobile/issues/171) |
192
194
  | [@Yurzi](https://github.com/Yurzi) | [#17](https://github.com/saya-ch/dsh-mobile/issues/17), [#213](https://github.com/saya-ch/dsh-mobile/issues/213) |
193
195
  | [@Ztyss](https://github.com/Ztyss) | [#22](https://github.com/saya-ch/dsh-mobile/issues/22), [#23](https://github.com/saya-ch/dsh-mobile/issues/23) |
196
+ | [@ZinChl](https://github.com/ZinChl) | [#308](https://github.com/saya-ch/dsh-mobile/issues/308) |
package/README.en.md CHANGED
@@ -26,13 +26,13 @@
26
26
  <a href="#compatibility">Compatibility</a> ·
27
27
  <a href="docs/README.md">Documentation</a> ·
28
28
  <a href="#contributors">Contributors</a> ·
29
- <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18">Release notes</a> ·
29
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.1">Release notes</a> ·
30
30
  <a href="README.md">简体中文</a>
31
31
  </p>
32
32
 
33
33
  > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
34
34
  >
35
- > **Current stable release: 0.7.0**. Add experimental iroh connections, improve sidebars under translucent skins, third-party menu layering and fullscreen-panel exit, and offer recovery feedback when mobile customization fails to load. Existing HTTPS channels and older Apps remain usable; iroh requires the full App with native transport. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.0) · [Full changelog](CHANGELOG.md).
35
+ > **Current stable release: 0.7.1**. Reorganize Mobile access and device management, improve cloudflared settings, pairing expiry and folded sidebars, and add iroh component cleanup and VPN troubleshooting. The independently released Android App remains at 0.7.0; existing pairings are kept. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.1) · [Full changelog](CHANGELOG.md).
36
36
  >
37
37
  > **Version policy**: since plugin **0.6.2**, the Android app and plugin use independent version numbers and releases. Their numbers do not need to match, and a plugin update does not imply an app update. [Compatibility notes](#compatibility).
38
38
 
@@ -42,7 +42,7 @@
42
42
  <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0-iroh.apk">64-bit full APK (experimental iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0">Release notes and checksums</a></sub>
43
43
  </p>
44
44
 
45
- DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. Both routes reach the same sessions, Workspaces, messages, and tools. The computer manages their switches and pairing authorizations separately; the Android app lists paired computers together. The plugin does not modify DeepSeek Harness source.
45
+ DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. The full Android App also supports experimental iroh encrypted direct connections with relay fallback. The phone reaches the computer's sessions, Workspaces, messages and tools. The computer manages LAN and remote switches and pairing authorizations separately; the Android app lists paired computers together. The plugin does not modify DeepSeek Harness source.
46
46
 
47
47
  Mobile access uses a dedicated HTTPS origin and device pairing. The Android app pins the private LAN CA; public remote paths use platform-trusted certificates. The self-signed FRP entry additionally requires the 0.4.6 app to pin a remote CA during pairing.
48
48
 
@@ -51,9 +51,9 @@ It also lets you customize the phone from a DSH conversation: `/mobile <what you
51
51
  ## What it does
52
52
 
53
53
  - **Continue DSH work from a phone**: the same sessions, Workspaces, messages, and tools, in real time.
54
- - **Customize the phone UI by talking to DSH**: request layout, interaction, or feature changes in a conversation; open pages usually refresh after the files have been changed.
54
+ - **Customize the phone UI by talking to DSH**: request layout, interaction, or feature changes in a conversation; changed customization resources are usually picked up automatically.
55
55
  - **A dedicated touch layout**: session drawer, tool details, settings, question cards, and composer reorganized for phones; the app follows the system locale (Chinese/English/Italian), plugin UI follows DSH's locale.
56
- - **Several remote options**: Tailscale, cpolar, cloudflared quick/named tunnels, self-hosted FRP, or your own reverse proxy; Windows/Linux x64 can also let the plugin manage Caddy HTTPS and certificates.
56
+ - **Several remote options**: Tailscale, cpolar, cloudflared quick/named tunnels, self-hosted FRP, your own reverse proxy, and experimental iroh without a domain or public port; Windows/Linux x64 can also let the plugin manage Caddy HTTPS and certificates.
57
57
  - **Pairing and multi-device**: pair once via QR code, link, or key; Wi-Fi, hotspot, or IP changes normally recover automatically; the app lists LAN and remote paired computers together, checks their reachability periodically, and lets you switch, re-pair, or delete a local record.
58
58
  - **One-click diagnostics and approval**: check versions, gateway, network interface, firewall, and the remote path with a redacted report; approve blocked third-party plugin connections per exact path.
59
59
  - **Task system notifications**: completion and pending-input alerts via Android system notifications, enabled from DSH General settings inside the app, with redacted lock-screen text.
@@ -124,10 +124,12 @@ Use this when the phone and computer share Wi-Fi, Ethernet, or a phone hotspot.
124
124
  </p>
125
125
 
126
126
  1. Connect the phone and computer to the same local network, then open **Mobile Access → Local network** in the lower-left corner of DeepSeek Harness.
127
- 2. If needed, select **Enable local access**, then select **Create and copy key**. The panel displays a pairing QR code.
127
+ 2. If needed, select **Enable local access**, then select **Generate pairing QR code**. The panel displays a pairing QR code.
128
128
  3. In the Android app, open **Local network**, scan for computers, select the device, then scan the QR code or paste the pairing key.
129
129
  4. Pairing creates persistent device trust. Later app launches discover and connect automatically; Wi-Fi, hotspot, and DHCP address changes normally do not require pairing again.
130
130
 
131
+ LAN and HTTPS remote pairing codes show their expiry time. Generate a new code after expiry; doing so invalidates the previous code. **Copy pairing link** reuses the current valid code instead of invalidating the displayed QR. The computer-side **Device** entry lists and revokes LAN and remote authorizations in separate tabs; it does not manage the saved computer list in the App.
132
+
131
133
  When other plugin entries share the sidebar footer, **Mobile access** becomes a phone-icon button. Hover to read its name; clicking opens the same panel. Its text label returns when the entry is alone.
132
134
 
133
135
  Port note: `dsh web --port` changes the DSH Web upstream port (3080 by default), which the plugin follows automatically. `dsh-mobile setup --port` changes the Mobile HTTPS listener (3443 by default), and the pairing QR code includes the selected port. When DSH Desktop starts with `--port 0`, the gateway follows the **actual port in use**; `upstreamOrigin` in `mobile-access/setup.json` is only the snapshot from the first setup, and the plugin refreshes it at startup — do not read it as the upstream the gateway uses.
@@ -151,6 +153,8 @@ For manual browser pairing, enter the 43-character pairing code shown on the com
151
153
 
152
154
  Use this after the phone leaves the computer's network. Remote access is disabled by default, and the phone needs no separate Tailscale, cpolar, cloudflared, or FRP app.
153
155
 
156
+ **Without a domain or public inbound access, you can also try iroh (experimental).** Install the pinned computer component and the **full Android App 0.7.0** to connect through encrypted direct links with relay fallback. Computer support is currently Windows/Linux x64; the compatibility APK and mobile browsers cannot use iroh. This is not a guaranteed connectivity or acceleration service: VPNs, proxies and both networks can affect it. See [iroh setup and troubleshooting](docs/IROH.en.md).
157
+
154
158
  Remote providers may impose bandwidth and connection limits: the [cpolar Free plan](https://svip.cpolar.com/pricing) currently lists 1 Mbps, while [Tailscale Funnel](https://tailscale.com/docs/features/tailscale-funnel#requirements-and-limitations) has non-configurable bandwidth limits, and a cloudflared quick tunnel is a free Cloudflare address with randomized hostnames and rate limiting. DSH Mobile uses gzip for static assets, persistent WebSockets, and load-on-scroll history to improve loading; DSH controls the Session history window and page sizes, and the plugin cannot raise provider quotas.
155
159
 
156
160
  If the page opens but stays on “Reconnecting,” distinguish WebSocket upgrade failures, slow synchronization, and heartbeat deadlines using the [slow-link and reconnection guide](docs/SLOW_CONNECTIONS.en.md). Version 0.5.4 also offers opt-in WebSocket compression per exact path, disabled by default; for long Sessions or metered links, follow the guide and compare actual transfer volume.
@@ -159,6 +163,7 @@ The usage notes below reflect the maintainer's long-term experience on a persona
159
163
 
160
164
  | Channel | Prerequisites | Address and limitation | Maintainer's usage notes |
161
165
  | --- | --- | --- | --- |
166
+ | iroh (experimental) | Windows/Linux x64 computer component and full Android App 0.7.0 | No domain, port forwarding or tunnel account; encrypted direct links with relay fallback; [setup and VPN troubleshooting](docs/IROH.en.md) | An option without public ingress, not a stability ranking; verify on both actual networks. Mobile browsers are unsupported |
162
167
  | cpolar | Account and Authtoken | Free temporary URLs may change | The free plan's bandwidth limit noticeably slows everyday loading and synchronization |
163
168
  | cloudflared quick tunnel | No account or domain | Random temporary URL; no SSE, with [notification limits](docs/CLOUDFLARE_TUNNEL.en.md#quick-tunnel-feature-limits); [officially intended only for development and testing](https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/) | Frequent disconnections in long-term use, with the cause still unconfirmed; a temporary or testing choice |
164
169
  | cloudflared named tunnel | Cloudflare account and domain | Fixed hostname; [setup guide](docs/CLOUDFLARE_TUNNEL.en.md) | The most stable of the channels used long-term; worth trying first if you have an account and domain |
@@ -171,8 +176,10 @@ The usage notes below reflect the maintainer's long-term experience on a persona
171
176
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/remote-access-en.png" width="82%" alt="DSH Mobile remote access and provider selection">
172
177
  </p>
173
178
 
174
- 1. Open **Mobile Access → Remote** in the lower-left corner of DeepSeek Harness, choose a channel and complete its sign-in or configuration.
175
- 2. Once ready, select **Create remote pairing QR code**. External proxy mode's **Backend listening** does not establish public readiness; verify public HTTPS and WebSocket access as well.
179
+ The following steps cover HTTPS remote channels. **iroh uses its own “Generate iroh pairing QR code” action and the full App, as described below.** Do not open its descriptor as an ordinary browser URL.
180
+
181
+ 1. Open **Mobile Access** in the lower-left corner of DeepSeek Harness, choose an HTTPS channel and complete its sign-in or configuration.
182
+ 2. Once ready, select **Generate pairing QR code**. External proxy mode's **Backend listening** does not establish public readiness; verify public HTTPS and WebSocket access as well.
176
183
  3. Select **Remote access** in the Android app and scan the current QR code. A publicly trusted certificate also permits pairing from a mobile browser.
177
184
  4. Later launches reconnect using the saved address and credential. If a temporary address changes, scan the current computer QR code to verify it. Do not clear app data; the stored device token never goes to a new Origin.
178
185
 
@@ -180,11 +187,12 @@ The usage notes below reflect the maintainer's long-term experience on a persona
180
187
  <summary>Installation and sign-in for each channel</summary>
181
188
 
182
189
  After selecting the channel in the panel:
190
+ - **iroh (experimental)**: select iroh, choose **Install official component**, then enable remote access after installation and verification. Once ready, choose **Generate iroh pairing QR code** and scan it through the full Android App's iroh flow, or copy the pairing link. Main actions stay hidden before installation; afterwards all three share one row, with Copy disabled until valid pairing data exists. After stopping the channel, component details let you remove the downloaded program without deleting identity or pairings. See the [iroh guide](docs/IROH.en.md) for the full procedure and limits.
183
191
  - **Tailscale Funnel**: select **Enable remote access**, complete the one-time Tailscale sign-in on the official page, follow the panel prompt to allow Funnel, then return to DSH and wait until the connection is ready.
184
192
  - **cpolar**: select **Install official component**, sign in to the cpolar dashboard and obtain an Authtoken, paste it, then select **Save and connect**. The component is downloaded into the plugin's private directory only after confirmation; free temporary addresses may change after DSH or cpolar restarts.
185
- - **Self-hosted FRP (advanced)**: if you have a VPS, expand **Self-hosted connection** and enter its frps details and a public HTTPS domain or real public IPv4 address. Apply the restricted frps + Caddy template manually, or deploy with an SSH key on Ubuntu/Debian with systemd. Password login is unsupported. Use manual deployment and merge the import as described in the guide when custom Caddy sites already exist. Verify the VPS host keys against its console before deployment or cleanup. The local `frpc` is downloaded and verified on demand; VPS cleanup is separate. Android app 0.3.3 or later is required. The [self-hosted FRP guide](docs/SELF_HOSTED_FRP.en.md) covers certificates, ports, and the complete procedure.
186
- - **Own reverse proxy**: open **Self-hosted connection → Own reverse proxy**, enter the public HTTPS origin (custom ports supported), private listen IP (IPv4 or IPv6 loopback/ULA), separate HTTP backend port (default 3444), and allowed direct proxy source CIDRs, then select **Save and start backend**. This uses your existing Lucky/Nginx/Caddy without a tunnel component and requires Android app 0.4.0 or later. See the [own reverse proxy guide](docs/SELF_HOSTED_ORIGIN.en.md).
187
- - **Managed Caddy**: under **Self-hosted connection → Own reverse proxy**, select **Managed Caddy**, choose **Install managed Caddy**, and confirm the download. Enter the public HTTPS origin, Tencent Cloud DNSPod credentials and local HTTPS listen port, then choose **Save and start Caddy**. A domain and reachable public ingress are required; this does not bypass CGNAT. See the [managed Caddy guide](docs/CADDY_MANAGED.en.md) for forwarding and complete steps.
193
+ - **Self-hosted FRP (advanced)**: if you have a VPS, select **Self-hosted FRP** under **Mobile access** and enter its frps details and a public HTTPS domain or real public IPv4 address. Apply the restricted frps + Caddy template manually, or deploy with an SSH key on Ubuntu/Debian with systemd. Password login is unsupported. Use manual deployment and merge the import as described in the guide when custom Caddy sites already exist. Verify the VPS host keys against its console before deployment or cleanup. The local `frpc` is downloaded and verified on demand; VPS cleanup is separate. Android app 0.3.3 or later is required. The [self-hosted FRP guide](docs/SELF_HOSTED_FRP.en.md) covers certificates, ports, and the complete procedure.
194
+ - **Own reverse proxy**: open **Mobile access → Own reverse proxy**, enter the public HTTPS origin (custom ports supported), private listen IP (IPv4 or IPv6 loopback/ULA), separate HTTP backend port (default 3444), and allowed direct proxy source CIDRs, then select **Save and start backend**. This uses your existing Lucky/Nginx/Caddy without a tunnel component and requires Android app 0.4.0 or later. See the [own reverse proxy guide](docs/SELF_HOSTED_ORIGIN.en.md).
195
+ - **Managed Caddy**: under **Mobile access → Own reverse proxy**, select **Managed Caddy**, choose **Install managed Caddy**, and confirm the download. Enter the public HTTPS origin, Tencent Cloud DNSPod credentials and local HTTPS listen port, then choose **Save and start Caddy**. A domain and reachable public ingress are required; this does not bypass CGNAT. See the [managed Caddy guide](docs/CADDY_MANAGED.en.md) for forwarding and complete steps.
188
196
  - **cloudflared quick tunnel**: select **Install official component**. After you confirm, the plugin downloads a pinned build from the official release page into its private directory and requests a temporary public address (a quick tunnel) with **no sign-up or sign-in**. Choose this when you would rather not create an account. The quick-tunnel hostname changes on every reconnect, and Cloudflare positions quick tunnels for testing: they are rate-limited and carry no uptime guarantee, so do not rely on one for production access that must stay reachable; it suits temporary or verification use.
189
197
  - **cloudflared named tunnel**: with a Cloudflare account and domain, switch **Tunnel type** to **Named**, then supply a connector token, a public hostname and a local forward port to get an address that survives restarts. The token is stored only in the private directory and reaches cloudflared through the environment rather than the command line; see [Cloudflare named tunnel](docs/CLOUDFLARE_TUNNEL.en.md).
190
198
 
@@ -207,11 +215,11 @@ See [Compatibility](#compatibility) for the supported components and platforms.
207
215
 
208
216
  ### Experimental iroh connection
209
217
 
210
- Plugin 0.7.0 integrates the experimental connection from [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh): encrypted direct or relayed access without a public domain, port forwarding or a tunnel account. Select **Mobile access → Remote → iroh (Experimental)** on the computer, install and verify the official component, enable it, then scan its dedicated QR code with the full App. LAN and existing HTTPS channels remain available; mobile browsers cannot connect through iroh directly. See the [iroh guide](docs/IROH.en.md) for platforms, pairing and troubleshooting.
218
+ Since plugin 0.7.0, the experimental transport from [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh) is integrated into this repository. Its computer component, native Android transport and full APK are maintained here. The standalone repository retains the design and prototype records; normal installation uses this project's plugin and App, without maintaining two Apps. See the [iroh guide](docs/IROH.en.md) for setup, platform limits and troubleshooting.
211
219
 
212
220
  ## Extend and customize
213
221
 
214
- Type `/mobile <what you want>` in a DSH conversation to hand the request to the current agent. Once the files have been changed, the phone page usually refreshes within a few seconds. For example:
222
+ Type `/mobile <what you want>` in a DSH conversation to hand the request to the current agent. Changed customization resources are usually picked up within a few seconds. For example:
215
223
 
216
224
  ```text
217
225
  /mobile turn the phone UI into an old CRT terminal, with messages scrolling like terminal output
@@ -414,6 +422,13 @@ The plugin retains DSH host peer declarations without rejecting installation or
414
422
 
415
423
  On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy work; Funnel and cpolar have no managed macOS component yet. The diagnostics firewall check currently covers Windows only and reports “not applicable” elsewhere.
416
424
 
425
+ | DSH Mobile plugin | Verified DeepSeek Harness version |
426
+ | --- | --- |
427
+ | `0.7.1` | Isolated packed installation, mobile sidebar and breakpoint hit tests on `0.2.1-rc.3`, plus access-panel, pairing-expiry and component-cleanup checks. See [CI](https://github.com/saya-ch/dsh-mobile/actions/workflows/ci.yml) for the automated matrix; browser checks do not establish every phone, plugin or public route |
428
+
429
+ <details>
430
+ <summary>Earlier release checks</summary>
431
+
417
432
  | DSH Mobile plugin | Verified DeepSeek Harness version |
418
433
  | --- | --- |
419
434
  | `0.6.11` | Isolated packed-browser CI on `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.2` and `0.2.1-alpha.3`; additional real history-pagination, viewport-preservation and manual-loading checks on `0.2.0-rc.2` and `0.2.1-alpha.3`. Browser checks do not establish acceptance of every phone engine, third-party plugin or public route |
@@ -426,9 +441,6 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
426
441
  | `0.6.18` | `0.2.1-rc.2`: 18 real packed Chromium directory-picker checks, including compact layout, folder creation and cancellation; the candidate was installed in local official Desktop `0.2.1-rc.3` with LAN and Cloudflare gateways running |
427
442
  | `0.7.0` | Packed-browser CI across eight DSH versions (`0.1.7-alpha.2`–`0.2.1-rc.2`), Windows/Linux Gateway and iroh Host checks, both Android ABIs and compatibility APK checks. See the [iroh guide](docs/IROH.en.md) for device and network limits |
428
443
 
429
- <details>
430
- <summary>Historical version checks</summary>
431
-
432
444
  | DSH Mobile plugin | Verified DeepSeek Harness version |
433
445
  | --- | --- |
434
446
  | `0.6.8` | Packed mobile boot, legacy-WebView API simulation, WebSocket Workspace reads, mobile settings, module management, sidebar and composer regressions on `0.2.1-alpha.3`; separate real HTTP/TLS and legacy-credential upgrade tests cover the identity fix. The local official Desktop `0.2.0-rc.2` loads this plugin version with existing pairings preserved. This does not establish phone cellular or every third-party plugin combination |
package/README.md CHANGED
@@ -26,13 +26,13 @@
26
26
  <a href="#兼容性">兼容性</a> ·
27
27
  <a href="docs/README.md">文档</a> ·
28
28
  <a href="#贡献者">贡献者</a> ·
29
- <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18">更新记录</a> ·
29
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.1">更新记录</a> ·
30
30
  <a href="README.en.md">English</a>
31
31
  </p>
32
32
 
33
33
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
34
34
  >
35
- > **当前正式版本:0.7.0**。新增实验性 iroh 连接,改善透明皮肤下的侧栏、第三方菜单层级和全屏面板退出,并在移动定制加载失败时提供恢复提示。现有 HTTPS 通道和旧版 App 仍可使用;iroh 需要含原生传输的完整版 App。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.0) · [完整更新记录](CHANGELOG.md)。
35
+ > **当前正式版本:0.7.1**。整理移动访问面板与设备管理,改善 cloudflared 配置、配对码有效期和折叠侧栏;新增 iroh 下载组件清理与 VPN 排障说明。Android App 继续使用独立发布的 0.7.0,现有配对无需重建。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.1) · [完整更新记录](CHANGELOG.md)。
36
36
  >
37
37
  > **版本说明**:自插件 **0.6.2** 起,Android App 与插件独立编号、独立发布,版本号无需一致;插件升级不代表 App 需要同步升级。[兼容说明](#兼容性)。
38
38
 
@@ -42,7 +42,7 @@
42
42
  <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0-iroh.apk">64 位完整版(含实验性 iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0">版本说明与校验文件</a></sub>
43
43
  </p>
44
44
 
45
- DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP 或自有反向代理远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
45
+ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP、自有反向代理远程通道连接电脑;Android 完整版还支持实验性 iroh 加密直连与中继。手机可以继续使用电脑上的会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
46
46
 
47
47
  移动访问使用独立 HTTPS 与设备配对;Android App 固定局域网私有 CA,公开远程通道使用系统信任的证书;自签 FRP 入口还需由 0.4.6 App 在配对时固定远程 CA。
48
48
 
@@ -51,9 +51,9 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
51
51
  ## 能做什么
52
52
 
53
53
  - **在手机上继续电脑端的工作**:同一份会话、工作区、消息和工具,实时同步。
54
- - **用对话定制手机端**:在 DSH 对话里提出布局、交互或功能需求;文件修改完成后,手机页面通常会自动刷新。
54
+ - **用对话定制手机端**:在 DSH 对话里提出布局、交互或功能需求;文件修改完成后,自定义资源通常会自动更新。
55
55
  - **专属触屏布局**:会话抽屉、工具详情、设置、提问卡片和输入栏都按手机重新组织;App 跟随系统语言(简/英/意),插件界面跟随 DSH 语言。
56
- - **多种远程通道**:Tailscale、cpolar、cloudflared 快速/命名隧道、自建 FRP、自有反向代理,按网络任选;Windows/Linux x64 还可由插件托管 Caddy HTTPS 与证书。
56
+ - **多种远程通道**:Tailscale、cpolar、cloudflared 快速/命名隧道、自建 FRP、自有反向代理,以及无需域名和公网端口的实验性 iroh;Windows/Linux x64 还可由插件托管 Caddy HTTPS 与证书。
57
57
  - **配对与多设备**:扫码、链接或密钥配对一次;切换 Wi-Fi、热点或 IP 后通常自动恢复;App 在一个列表中显示局域网和远程配对的电脑,定期检测可达状态,并支持切换、重新配对或删除本地记录。
58
58
  - **一键诊断与放行**:检查版本、网关、网卡、防火墙和远程通道,生成脱敏报告;被拦截的第三方插件连接按确切路径一键放行。
59
59
  - **任务系统通知**:任务完成与待输入以 Android 系统通知提醒,可在 App 内的 DSH“通用设置”中开启,锁屏文本脱敏。
@@ -124,10 +124,12 @@ dsh plugin --profile web add dshmarket
124
124
  </p>
125
125
 
126
126
  1. 让手机和电脑连接同一个局域网,在 DeepSeek Harness 左下角打开 **移动访问 → 局域网**。
127
- 2. 如果尚未开启,点击 **开启局域网访问**;随后点击 **生成并复制密钥**,面板会显示配对二维码。
127
+ 2. 如果尚未开启,点击 **开启局域网访问**;随后点击 **生成配对二维码**,面板会显示配对二维码。
128
128
  3. 在 Android App 中进入 **局域网访问**,扫描发现电脑并点击设备,再扫描二维码或粘贴配对密钥。
129
129
  4. 配对完成后会建立持久设备信任。以后打开 App 会自动发现并连接,切换 Wi-Fi、热点或 DHCP 地址通常不需要重新配对。
130
130
 
131
+ 局域网和 HTTPS 远程配对码会显示有效截止时间;超时后重新生成即可。生成新码会使旧码失效,**复制配对链接**复用当前有效码,不会另行作废二维码。电脑端的 **设备** 入口可查看和撤销局域网、远程两组授权;这与 App 中保存的电脑列表是不同的管理对象。
132
+
131
133
  侧栏底部有其他插件入口时,**移动访问**会收起为手机图标;悬停可查看名称,点击仍打开原面板。独占该区域时恢复文字显示。
132
134
 
133
135
  端口说明:`dsh web --port` 修改 DSH Web 上游端口(默认 3080),插件会自动跟随;`dsh-mobile setup --port` 修改 Mobile HTTPS 监听端口(默认 3443),配对二维码会包含实际端口。若 DSH Desktop 以 `--port 0` 随机端口启动,网关跟随的是**当前实际端口**,`mobile-access/setup.json` 里的 `upstreamOrigin` 只是首次配置的快照,插件启动时会把它更新为当前端口——排查时不要把它当成网关实际使用的上游。
@@ -151,6 +153,8 @@ dsh plugin --profile web add dshmarket
151
153
 
152
154
  适合手机离开电脑所在网络后使用。远程访问默认关闭,手机不需要另外安装 Tailscale、cpolar、cloudflared 或 FRP。
153
155
 
156
+ **没有域名或公网入站,也可以尝试 iroh(实验性)**:电脑安装固定版本的 iroh 组件,手机安装 **Android App 0.7.0 完整版**,即可通过加密直连、必要时中继连接电脑。电脑端目前支持 Windows/Linux x64;兼容版 APK 和手机浏览器不能使用 iroh。它不是保证连通的加速线路,VPN、代理和两端网络仍可能影响连接。详见 [iroh 使用与排障](docs/IROH.md)。
157
+
154
158
  远程服务可能受带宽和连接限额影响:[cpolar 免费方案](https://svip.cpolar.com/pricing) 当前为 1 Mbps,[Tailscale Funnel](https://tailscale.com/docs/features/tailscale-funnel#requirements-and-limitations) 也存在不可配置的带宽限制,cloudflared 的 quick tunnel 由 Cloudflare 免费提供、地址随机且有限流。DSH Mobile 使用静态资源 gzip、WebSocket 长连接和顶部按需加载改善体验;会话的历史窗口与分页大小由 DSH 决定,插件无法提高服务商限额。
155
159
 
156
160
  页面能打开但一直“重连中”,应先区分 WebSocket 升级失败、慢速数据同步和心跳超时,操作见[慢链路与反复重连指南](docs/SLOW_CONNECTIONS.md)。0.5.4 还提供按确切路径启用的 WebSocket 压缩,默认关闭;长会话或计量网络可按指南尝试,并对比实际传输量。
@@ -159,6 +163,7 @@ dsh plugin --profile web add dshmarket
159
163
 
160
164
  | 连接方式 | 需要准备 | 地址特点与注意事项 | 维护者使用参考 |
161
165
  | --- | --- | --- | --- |
166
+ | iroh(实验性) | Windows/Linux x64 电脑组件与 Android 0.7.0 完整版 | 无需域名、端口映射或隧道账号;加密直连、中继兜底;[使用与 VPN 排障](docs/IROH.md) | 可作为没有公网入口时的选择;不作稳定性排名,需在两端实际网络验证,手机浏览器不支持 |
162
167
  | cpolar | cpolar 账号与 Authtoken | 免费临时地址可能变化 | 免费方案限速明显,日常加载与同步体验较差 |
163
168
  | cloudflared 快速隧道 | 无需账号或域名 | 临时随机地址;不支持 SSE,[即时通知存在限制](docs/CLOUDFLARE_TUNNEL.md#快速隧道的功能限制);[官方仅定位为开发测试用途](https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/) | 长期使用中经常断连,原因尚未确认;只作临时或测试选择 |
164
169
  | cloudflared 命名隧道 | Cloudflare 账号与域名 | 固定域名;[配置指南](docs/CLOUDFLARE_TUNNEL.md) | 已长期使用的通道中最稳定;有账号和域名可优先尝试 |
@@ -171,8 +176,10 @@ dsh plugin --profile web add dshmarket
171
176
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/remote-access.png" width="82%" alt="DSH Mobile 远程访问与通道选择">
172
177
  </p>
173
178
 
174
- 1. 在 DeepSeek Harness 左下角打开 **移动访问 → 远程**,按上表选择通道,完成登录或配置。
175
- 2. 状态变为“远程访问已就绪”后,点击 **生成远程配对二维码**。自备代理模式的“后端已监听”不等于公网就绪,仍需确认公网 HTTPS 与 WebSocket 可用。
179
+ 下面的扫码步骤适用于 HTTPS 远程通道;**iroh 使用独立的「生成 iroh 配对二维码」和完整版 App,按下方 iroh 步骤操作**,不要把其描述符当成普通网址在浏览器打开。
180
+
181
+ 1. 在 DeepSeek Harness 左下角打开 **移动访问**,按上表选择 HTTPS 通道,完成登录或配置。
182
+ 2. 状态变为“远程访问已就绪”后,点击 **生成配对二维码**。自备代理模式的“后端已监听”不等于公网就绪,仍需确认公网 HTTPS 与 WebSocket 可用。
176
183
  3. 在 Android App 中选择 **远程访问**,扫描当前二维码完成配对;公开证书入口也可用手机浏览器打开配对链接。
177
184
  4. 以后 App 使用保存的地址与凭据自动重连。临时地址改变时,重新扫描电脑端当前二维码验证新地址,不需要清除 App 数据;旧设备 token 不会发送给新 Origin。
178
185
 
@@ -180,11 +187,12 @@ dsh plugin --profile web add dshmarket
180
187
  <summary>各通道的安装与登录步骤</summary>
181
188
 
182
189
  在面板选择对应通道后:
190
+ - **iroh(实验性)**:选择 iroh,点击 **安装官方组件**,安装并校验完成后打开远程访问;就绪后点 **生成 iroh 配对二维码**,用 Android 完整版 App 的 iroh 流程扫码,也可以复制配对链接。未安装组件时不显示主操作按钮;安装后三个按钮保持同排,没有有效配对内容时复制按钮置灰。关闭通道后,可从组件详情移除插件下载的程序,不删除配对和身份。完整步骤与限制见 [iroh 指南](docs/IROH.md)。
183
191
  - **Tailscale Funnel**:点击 **启用远程访问**,在打开的官方页面完成一次 Tailscale 登录;按面板提示继续允许 Funnel,然后返回 DSH 等待连接就绪。
184
192
  - **cpolar**:点击 **安装官方组件**,登录 cpolar 控制台取得 Authtoken,粘贴后点击 **保存并连接**。组件只会在确认后下载到插件私有目录;免费临时地址可能在 DSH 或 cpolar 重启后变化。
185
- - **自建 FRP(高级)**:已有 VPS 时,展开 **自建连接**,填写 frps 信息和公开 HTTPS 域名或真实公网 IPv4。可以复制受限的 frps + Caddy 模板手动部署,也可以在 Ubuntu/Debian + systemd 上用 SSH 密钥一键部署;不支持密码登录。已有自定义 Caddy 站点时,请按指南手动部署并合并 import。部署或清理前须到 VPS 控制台核对主机指纹。本机 `frpc` 按需下载校验,VPS 需单独清理。需要 Android App 0.3.3 或更新版本;证书、端口和操作步骤见 [自建 FRP 使用指南](docs/SELF_HOSTED_FRP.md)。
186
- - **自有反向代理**:展开 **自建连接 → 自有反向代理**,填写公网 HTTPS 地址(支持自定义端口)、私有监听 IP(IPv4 或 IPv6 回环/ULA)、独立 HTTP 后端端口(默认 3444)和代理直连来源 CIDR,再点击 **保存并启动后端**。适合已有 Lucky/Nginx/Caddy 的用户,无需隧道组件;需要 Android App 0.4.0 或更高版本。详见 [自有反向代理指南](docs/SELF_HOSTED_ORIGIN.md)。
187
- - **托管 Caddy**:在 **自建连接 → 自有反向代理** 中选择 **托管 Caddy**,点击 **安装托管 Caddy** 并确认下载。填写公网 HTTPS 地址、腾讯云 DNSPod 凭据和本机 HTTPS 监听端口,再点击 **保存并启动 Caddy**。需要域名和可达的公网入站,不会替你穿透 CGNAT;端口映射与完整步骤见 [托管 Caddy 指南](docs/CADDY_MANAGED.md)。
193
+ - **自建 FRP(高级)**:已有 VPS 时,在 **移动访问** 中选择 **自建 FRP**,填写 frps 信息和公开 HTTPS 域名或真实公网 IPv4。可以复制受限的 frps + Caddy 模板手动部署,也可以在 Ubuntu/Debian + systemd 上用 SSH 密钥一键部署;不支持密码登录。已有自定义 Caddy 站点时,请按指南手动部署并合并 import。部署或清理前须到 VPS 控制台核对主机指纹。本机 `frpc` 按需下载校验,VPS 需单独清理。需要 Android App 0.3.3 或更新版本;证书、端口和操作步骤见 [自建 FRP 使用指南](docs/SELF_HOSTED_FRP.md)。
194
+ - **自有反向代理**:展开 **移动访问 → 自有反向代理**,填写公网 HTTPS 地址(支持自定义端口)、私有监听 IP(IPv4 或 IPv6 回环/ULA)、独立 HTTP 后端端口(默认 3444)和代理直连来源 CIDR,再点击 **保存并启动后端**。适合已有 Lucky/Nginx/Caddy 的用户,无需隧道组件;需要 Android App 0.4.0 或更高版本。详见 [自有反向代理指南](docs/SELF_HOSTED_ORIGIN.md)。
195
+ - **托管 Caddy**:在 **移动访问 → 自有反向代理** 中选择 **托管 Caddy**,点击 **安装托管 Caddy** 并确认下载。填写公网 HTTPS 地址、腾讯云 DNSPod 凭据和本机 HTTPS 监听端口,再点击 **保存并启动 Caddy**。需要域名和可达的公网入站,不会替你穿透 CGNAT;端口映射与完整步骤见 [托管 Caddy 指南](docs/CADDY_MANAGED.md)。
188
196
  - **cloudflared 快速隧道**:点击 **安装官方组件**,插件在确认后从官方发布页下载固定版本到插件私有目录,随后自动申请一个临时公网地址(quick tunnel),**无需注册或登录**。适合不想注册账号的用户;quick tunnel 地址每次重连都会变化,官方定位为测试用途、有限流且无可用性保证,请勿用于必须长期可达的生产访问,只适合临时或验证场景。
189
197
  - **cloudflared 命名隧道**:已有 Cloudflare 账号和域名时,把隧道类型切到 **命名隧道**,填入连接器令牌、公网域名与本机转发端口,即可获得重启后不变的固定地址(令牌只存私有目录、只经环境变量传给 cloudflared)。步骤见 [Cloudflare 命名隧道](docs/CLOUDFLARE_TUNNEL.md)。
190
198
 
@@ -207,11 +215,11 @@ Funnel 的运行组件把公开监听生命周期绑定到父进程和受限控
207
215
 
208
216
  ### 实验中的 iroh 连接
209
217
 
210
- 插件 0.7.0 整合了 [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh) 的实验性连接:通过加密直连或中继访问电脑,不要求公网域名、端口映射或隧道账号。电脑端选择 **移动访问 → 远程 → iroh(实验性)**,安装并校验官方组件后启用,再用完整版 App 扫描专属二维码。局域网和既有 HTTPS 通道不受影响;手机浏览器不能直接使用 iroh。平台要求、配对与排障见 [iroh 使用说明](docs/IROH.md)。
218
+ 从插件 0.7.0 起,[dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh) 的实验性传输已整合进本仓库,电脑端组件、Android 原生传输和完整版 APK 随本项目维护。独立仓库保留方案与原型记录;日常安装使用本仓库的插件和 App 即可,不必再维护两套 App。连接步骤、平台限制与排障以 [iroh 使用说明](docs/IROH.md) 为准。
211
219
 
212
220
  ## 扩展与自定义
213
221
 
214
- 在 DSH 对话里输入 `/mobile <需求>`,当前会话的 agent 会处理定制请求;文件修改完成后,手机端通常会在几秒内刷新。例如:
222
+ 在 DSH 对话里输入 `/mobile <需求>`,当前会话的 agent 会处理定制请求;文件修改完成后,自定义资源通常会在几秒内更新。例如:
215
223
 
216
224
  ```text
217
225
  /mobile 把手机端做成老式终端的样子,让消息像终端输出一样逐行滚动
@@ -414,6 +422,13 @@ flowchart LR
414
422
 
415
423
  macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funnel 与 cpolar 暂未提供 macOS 组件。诊断页的防火墙检查目前仅覆盖 Windows,其他系统显示“不适用”。
416
424
 
425
+ | DSH Mobile 插件 | 已验证的 DeepSeek Harness 版本与范围 |
426
+ | --- | --- |
427
+ | `0.7.1` | `0.2.1-rc.3` 的隔离打包安装、手机侧栏与断点命中回归;另验证访问面板、配对有效期和组件清理。自动检查范围见 [CI](https://github.com/saya-ch/dsh-mobile/actions/workflows/ci.yml);浏览器检查不代表所有手机、第三方插件或公网线路已验收 |
428
+
429
+ <details>
430
+ <summary>较早版本的验证记录</summary>
431
+
417
432
  | DSH Mobile 插件 | 已验证的 DeepSeek Harness 版本与范围 |
418
433
  | --- | --- |
419
434
  | `0.6.11` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.2`、`0.2.1-alpha.3` 的隔离打包浏览器 CI;`0.2.0-rc.2` 与 `0.2.1-alpha.3` 另通过真实历史分页、滚动位置保持和手动加载检查。浏览器检查不代表所有手机内核、第三方插件或公网线路已验收 |
@@ -426,9 +441,6 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
426
441
  | `0.6.18` | `0.2.1-rc.2` 上的 18 项真实打包 Chromium 目录选择检查,含紧凑布局、目录创建和取消;本机官方 Desktop `0.2.1-rc.3` 已装入候选并启用局域网与 Cloudflare 网关 |
427
442
  | `0.7.0` | 8 个 DSH 版本(`0.1.7-alpha.2`–`0.2.1-rc.2`)的打包浏览器 CI;Windows/Linux Gateway 与 iroh Host、Android 双 ABI 和兼容版包检查。设备与网络范围见 [iroh 说明](docs/IROH.md) |
428
443
 
429
- <details>
430
- <summary>历史版本验证记录</summary>
431
-
432
444
  | DSH Mobile 插件 | 验证支持的 DeepSeek Harness 版本 |
433
445
  | ----------------------------------------- | -------------------------------------------------------------- |
434
446
  | `0.6.8` | `0.2.1-alpha.3` 的打包移动页面、旧 WebView API 模拟、WebSocket 工作区读取、移动设置、模块管理、侧栏及输入栏回归;身份修复另有真实 HTTP/TLS 与旧凭据升级测试。本机官方 Desktop `0.2.0-rc.2` 已加载该版本插件,原配对保留;不代表手机 5G 或全部第三方插件组合已验收 |
package/SECURITY.md CHANGED
@@ -61,6 +61,13 @@ The maintainer will acknowledge a complete report within seven days. Publication
61
61
  - Automatic VPS deployment and one-click VPS cleanup first read the server's SSH host keys and require the operator to confirm every `SHA256:` fingerprint against the VPS console before any authenticated connection. All SSH/SCP channels pin `StrictHostKeyChecking=yes` to a temporary known_hosts file built from the confirmed keys; unknown, rotated, or extra keys abort the operation instead of being silently accepted. SSH credentials themselves are key-or-agent only, never passwords; the private key path is convenience state in the current browser profile, and key material is never uploaded or logged.
62
62
  - Disabling remote access stops the selected provider without affecting LAN or pairing records. Resetting remote access also clears the shared remote-device registry, so all remote devices must pair again. A Funnel reset additionally removes the plugin's private Tailscale node login state and requires authorization again. Other providers retain settings and components until their separate removal actions are used.
63
63
 
64
+ ### Experimental iroh transport
65
+
66
+ - iroh carries traffic over encrypted direct connections or relays to the computer's loopback Mobile Gateway. Its endpoint identity and short-lived transport-pairing code do not replace the Gateway's one-time pairing token, device authorization, CSRF checks or revocation. Transport and Gateway device authorizations remain distinct; revoking a DSH Mobile device still prevents authenticated Gateway access.
67
+ - The full Android App pins the Gateway CA supplied through explicit iroh pairing and uses an App-local `*.iroh.localhost` entry. This local entry is not a public hostname or a browser-compatible tunnel. Keep its loopback traffic out of remote proxies; never bypass certificate validation to repair VPN or DNS interference. The compatibility APK and ordinary mobile browsers do not contain this native transport.
68
+ - The computer component is downloaded only after confirmation, from the fixed source with pinned size and SHA-256. It runs under the current user's authority without a system service. Component removal requires iroh remote access to be disabled and deletes only the plugin-downloaded program, retaining saved identity, Gateway pairings and external companion installations. Uninstalling a binary is not revoking authorization.
69
+ - Current component targets are Windows/Linux x64; the full App packages arm64-v8a and x86_64. Network reachability, direct versus relayed traffic and background delivery are not guaranteed. VPN bypass is an operator choice, not a reason to disable system security policy. See [iroh setup and troubleshooting](docs/IROH.en.md).
70
+
64
71
  ### Device authority, Android and extensions
65
72
 
66
73
  - Treat every paired device as a fully trusted operator. The authenticated proxy forwards ordinary DSH and community-plugin routes using GET, HEAD, POST, PUT, PATCH, or DELETE; writes require the gateway's exact Origin, valid Session, and Session-bound CSRF token. Upstream requests use DSH's loopback Host and the gateway's own DSH authentication, so a plugin cannot distinguish a paired phone from the computer user merely by checking that Host. Routes may read configuration, save settings, or run tools with the desktop user's authority; pairing is not a read-only sandbox. The separate `/api/mobile-access` admin API remains inaccessible through the mobile listener.
@@ -40,7 +40,7 @@ Deleting a local record removes its saved token and pinned CA, not the computer'
40
40
 
41
41
  App 0.7.0/build 85 adds optional experimental iroh pairing and native transport in the full APK, working with plugin 0.7.0 or later. The compatibility APK retains existing HTTPS channels without native libraries, including on 32-bit devices. Legacy updates download compatibility by default; choose the full APK explicitly when using iroh. Both retain the device list, HTTPS pairings and established signer. Records from the separate experimental App do not migrate automatically.
42
42
 
43
- iroh is off by default. The computer installs a verified component, then generates a dedicated pairing QR code under **Mobile access → Remote → iroh (Experimental)**. Direct/relayed connectivity depends on both networks; mobile browsers cannot use this transport directly. See the [iroh guide](../../docs/IROH.en.md).
43
+ iroh is off by default. Select **iroh (Experimental)** in the computer's **Mobile access** connection list, install the verified component, then enable it and generate a dedicated pairing QR code. Direct/relayed connectivity depends on both networks; mobile browsers cannot use this transport directly. See the [iroh guide](../../docs/IROH.en.md).
44
44
 
45
45
  ## 0.6.8 update
46
46
 
@@ -40,7 +40,7 @@ DeepSeek Harness 是这个社区维护的 Android WebView App 的显示名称。
40
40
 
41
41
  App 0.7.0/构建 85 在完整版中增加可选的实验性 iroh 配对和原生传输,配合插件 0.7.0 及以上版本使用。兼容版不含原生库,保留现有 HTTPS 通道并继续支持 32 位设备。旧版更新入口默认下载兼容版;使用 iroh 时请主动选择完整版。两包均保留设备列表、HTTPS 配对和原有正式签名。独立实验 App 的记录不会自动迁移。
42
42
 
43
- iroh 默认关闭。电脑端安装经过校验的组件后,在 **移动访问 → 远程 → iroh(实验性)** 中生成专属配对二维码。直连和中继可用性取决于两端网络,手机浏览器不能直接使用这条传输,详见 [iroh 使用说明](../../docs/IROH.md)。
43
+ iroh 默认关闭。电脑端在 **移动访问** 的连接列表选择 **iroh(实验性)**,安装经过校验的组件并开启通道后,生成专属配对二维码。直连和中继可用性取决于两端网络,手机浏览器不能直接使用这条传输,详见 [iroh 使用说明](../../docs/IROH.md)。
44
44
 
45
45
  ## 0.6.8 更新
46
46
 
@@ -24,7 +24,7 @@ Configure the public HTTPS origin, DNS-01 credentials and local HTTPS port separ
24
24
 
25
25
  ## Installation, startup, and readiness
26
26
 
27
- 1. On the computer, open **Mobile Access → Remote → Self-hosted connection → Own reverse proxy** and choose **Managed Caddy**.
27
+ 1. On the computer, open **Mobile Access → Own reverse proxy** and choose **Managed Caddy**.
28
28
  2. Choose **Install managed Caddy** and confirm the download. The plugin downloads the fixed [DSH Mobile component distribution](https://github.com/saya-ch/dsh-mobile/releases/tag/caddy-component-2.11.7-tencentcloud-0.4.3-r1), checking its exact length, SHA-256, core and DNS module versions. Unavailable or invalid assets are not executed.
29
29
  3. Enter the public HTTPS origin, such as `https://dsh.example.com`, select Tencent Cloud DNSPod, supply a `SecretId` and `SecretKey` with the required zone permissions, and set the local HTTPS port, such as `8443`. Point the domain at the public ingress and, where needed, forward public TCP 443 to port 8443 on the computer.
30
30
  4. Choose **Save and start Caddy**. Installed is not ready: the panel reports readiness only after a computer-side public HTTPS probe validates the certificate and confirms that the entry belongs to the current DSH instance. That probe still does not prove phone-network reachability.
@@ -24,7 +24,7 @@ Android App / 浏览器 → 公网 HTTPS 域名(Caddy 终止 TLS)
24
24
 
25
25
  ## 安装、启动与就绪
26
26
 
27
- 1. 在电脑端打开 **移动访问 → 远程 → 自建连接 → 自有反向代理**,选择 **托管 Caddy**。
27
+ 1. 在电脑端打开 **移动访问 → 自有反向代理**,选择 **托管 Caddy**。
28
28
  2. 点击 **安装托管 Caddy** 并确认下载。插件从固定的 [DSH Mobile 组件分发](https://github.com/saya-ch/dsh-mobile/releases/tag/caddy-component-2.11.7-tencentcloud-0.4.3-r1) 下载,核对完整大小、SHA-256、Caddy 核心与 DNS 模块版本;来源不可用或校验失败时不会执行文件。
29
29
  3. 填写公网 HTTPS 地址,例如 `https://dsh.example.com`,选择腾讯云 DNSPod,填写具有所需区域权限的 `SecretId` 和 `SecretKey`,再设置本机 HTTPS 端口,例如 `8443`。让域名解析到你的公网入口,并按需将公网 TCP 443 映射至电脑的 8443。
30
30
  4. 点击 **保存并启动 Caddy**。组件已安装不等于连接就绪:只有电脑端经公网 HTTPS 验证证书,并确认入口属于当前 DSH 实例后,面板才显示已就绪。这个探测仍不能证明手机网络可达。
@@ -4,7 +4,7 @@
4
4
 
5
5
  > Already running cloudflared or a system service? Use the [own-reverse-proxy mode](SELF_HOSTED_ORIGIN.en.md#when-you-already-run-cloudflared-yourself) and route that tunnel to the protected HTTP backend shown in the panel, without another component installation or a tunnel Token stored by the plugin. The instructions below describe the separate plugin-managed option.
6
6
 
7
- The built-in cloudflared provider runs in one of two modes, chosen in the panel under **Mobile access → Remote → cloudflared → Tunnel type**:
7
+ The built-in cloudflared provider runs in one of two modes, chosen through the Quick/Named tabs under **Mobile access → cloudflared**:
8
8
 
9
9
  | | Quick tunnel (default) | Named tunnel |
10
10
  | --- | --- | --- |
@@ -43,13 +43,13 @@ These labels follow [Cloudflare's current official guide](https://developers.clo
43
43
 
44
44
  ## Fill in the DSH Mobile panel
45
45
 
46
- 1. **Mobile access → Remote → cloudflared**.
47
- 2. Set the tunnel type to **Named**.
46
+ 1. Select **cloudflared** in the **Mobile access** connection list.
47
+ 2. Select **Named**, then **Show settings** to expand the form. For an existing saved configuration, choose **Edit** first.
48
48
  3. Enter:
49
49
  - **Public hostname**: `dsh.example.com`
50
50
  - **Local forward port**: `3444`, matching the Service port from step 3
51
51
  - **Connector token**: the token you copied
52
- 4. Choose **Save and connect**.
52
+ 4. Choose **Save and connect** and read the actual connection status above. Saved settings do not establish public reachability. Switching tunnel type while connected first requires confirming disconnection.
53
53
 
54
54
  Once saved, leaving the token field blank keeps the stored token, and the field never echoes a saved token back. **Remove the saved token** also **stops the cloudflared channel** and returns the provider to a quick tunnel. Nothing reconnects on its own: switch the channel back on afterwards.
55
55
 
@@ -57,7 +57,7 @@ Once saved, leaving the token field blank keeps the stored token, and the field
57
57
 
58
58
  Moving to a fixed hostname means **an already paired phone must pair again**: the App does not send a saved device token to a changed Origin without new pairing. This client-side exact-address policy does not mean the server token automatically expires by hostname; remote channels share the device registry. Use a trusted entry you control and revoke a device on the computer if credential theft is suspected.
59
59
 
60
- 1. On the computer, open **Remote** in the panel and choose **Create remote pairing QR code**. That is what opens the pairing window, which is time-limited; while it is closed nothing can pair.
60
+ 1. On the computer, open **Mobile access → cloudflared**, wait for readiness, then choose **Generate pairing QR code**. The panel shows the expiry time; generate a new code after expiry. Closing the pairing window does not revoke existing devices.
61
61
  2. In the app, **open the Remote entry first** (the remote access setup page in the connection center), then scan the code.
62
62
 
63
63
  > **A named tunnel must be scanned from inside the Remote flow.** The app treats platform suffixes such as `.ts.net`, cpolar and `.trycloudflare.com` as remote without asking. A domain you own is recognised as a remote candidate too, but the Local network flow accepts only non-candidate addresses, so scanning there is rejected as **Invalid QR code** and looks exactly like "cannot connect". Enter the Remote flow first, then scan.
@@ -4,7 +4,7 @@
4
4
 
5
5
  > 已经自己运行 cloudflared 或使用系统服务?可改用[自备反向代理模式](SELF_HOSTED_ORIGIN.md#已经自己运行-cloudflared-时),将现有隧道指向面板展示的受保护 HTTP 后端,无需再安装组件或在插件保存隧道 Token。以下步骤介绍由插件管理 cloudflared 的另一种方式。
6
6
 
7
- 内置的 cloudflared 通道有两种模式,在面板 **移动访问 → 远程 → cloudflared → 隧道类型** 中切换:
7
+ 内置的 cloudflared 通道有两种模式,在 **移动访问 → cloudflared** 的快速/命名隧道标签中切换:
8
8
 
9
9
  | | 快速隧道(默认) | 命名隧道 |
10
10
  | --- | --- | --- |
@@ -43,13 +43,13 @@ Cloudflare 提供公网域名与 TLS,插件在本机运行 `cloudflared`,把
43
43
 
44
44
  ## 在 DSH Mobile 面板中填写
45
45
 
46
- 1. **移动访问 → 远程 → cloudflared**。
47
- 2. 隧道类型选 **命名隧道**。
46
+ 1. 在 **移动访问** 的连接列表选择 **cloudflared**。
47
+ 2. 选择 **命名隧道**,点击 **展开配置** 打开表单;已保存的配置先点击 **编辑**。
48
48
  3. 依次填写:
49
49
  - **公网域名**:`dsh.example.com`
50
50
  - **本机转发端口**:`3444`(与第 3 步的 Service 端口一致)
51
51
  - **连接器令牌**:粘贴上一步复制的令牌
52
- 4. 点击 **保存并连接**。
52
+ 4. 点击 **保存并连接**,以上方实际连接状态判断是否就绪;保存成功不等于公网已经可达。切换隧道类型时若有连接,先确认断开当前通道。
53
53
 
54
54
  已保存后令牌输入框留空表示不更改;输入框里不会再回显已保存的令牌。「移除已保存的令牌」会**同时停止 cloudflared 通道**并把配置改回快速隧道。不会自动重连,之后需要手动重新打开开关。
55
55
 
@@ -57,7 +57,7 @@ Cloudflare 提供公网域名与 TLS,插件在本机运行 `cloudflared`,把
57
57
 
58
58
  切到固定域名后,**已经配对过的手机必须重新配对**:App 不会把已存设备令牌发送给未经新配对验证的 Origin。这是客户端的精确地址发送策略,不代表服务端令牌自动按域名失效;远程通道共用设备注册表。请使用可信且由你控制的入口,怀疑凭据泄漏时在电脑端撤销设备。
59
59
 
60
- 1. 电脑面板 → **远程** → 点 **生成远程配对二维码**。这一步打开有时限的配对窗口;未打开时不能新增配对,已有配对不受影响。
60
+ 1. 电脑端在 **移动访问 → cloudflared** 中等待连接就绪,再点 **生成配对二维码**。面板显示有效截止时间;超时后须重新生成,已有设备授权不受配对窗口关闭影响。
61
61
  2. 手机 App → **先进入「远程」入口**(连接中心的远程访问设置页)→ 再扫描二维码。
62
62
 
63
63
  > **命名隧道必须在「远程」入口里扫码。** App 只把 `.ts.net`、cpolar、`.trycloudflare.com` 这类平台后缀当作「无需询问即为远程」;你自己的域名同样会被识别为可远程的候选地址,但「局域网」流程只接受非候选地址,所以在局域网界面扫码会被判为无效并提示**无效二维码 / Invalid QR code**,看起来就像「连不上」。先进入「远程」流程再扫即可。
@@ -12,7 +12,7 @@ The public entry still reaches the DSH Mobile Gateway with HTTPS, device pairing
12
12
 
13
13
  1. Check that your cpolar plan supports reserving a secondary subdomain. The [official tutorial](https://www.cpolar.com/blog/cpolar-quick-start-tutorial-raspberry-pi-series) uses Basic plans or above; your account dashboard is the authority for current eligibility, available regions and naming rules.
14
14
  2. Reserve a name under **Reserved → Reserve a secondary subdomain** in the [cpolar dashboard](https://dashboard.cpolar.com), and record the selected region.
15
- 3. Install the component and save the Authtoken under **Mobile access → Remote → cpolar** in DSH.
15
+ 3. Install the component and save the Authtoken under **Mobile access → cpolar** in DSH.
16
16
 
17
17
  The region must match the reservation. The official command example uses `cn_vip`, but do not copy it for a reservation in another region; confirm other identifiers against cpolar's current instructions. This guide does not maintain a fixed region or domain-suffix mapping.
18
18
 
@@ -52,7 +52,7 @@ If you already customize paths, listeners, TLS or other settings, **keep your cu
52
52
 
53
53
  Leading and trailing whitespace is removed. The plugin only bounds the requested name's syntax: it starts with a letter or digit, contains letters, digits, `.`, `_`, `-`, and is at most 63 characters long. This is not a DNS-label specification or a guarantee of server acceptance. The account, region and cpolar's actual rules determine whether the reservation is valid. The [official subdomain instructions](https://www.cpolar.com/docs#configure-secondary-subdomain) and tutorial describe the `-subdomain` and `-region` arguments.
54
54
 
55
- After checking that no tasks are running, quit DSH completely and reopen it, then connect under **Mobile access → Remote → cpolar**. Use the actual HTTPS address shown by the panel; do not construct a domain suffix yourself.
55
+ After checking that no tasks are running, quit DSH completely and reopen it, then connect under **Mobile access → cpolar**. Use the actual HTTPS address shown by the panel; do not construct a domain suffix yourself.
56
56
 
57
57
  ## Verification and pairing
58
58
 
@@ -12,7 +12,7 @@ cpolar 默认分配临时公网地址。账号预留子域名后,可请求使
12
12
 
13
13
  1. 确认 cpolar 套餐支持保留二级子域名。[官方教程](https://www.cpolar.com/blog/cpolar-quick-start-tutorial-raspberry-pi-series)以基础套餐及以上为例;当前资格、可用地区及命名规则以你的账号控制台为准。
14
14
  2. 在 [cpolar 控制台](https://dashboard.cpolar.com)的 **预留 → 保留二级子域名** 中保留名字,记录对应地区。
15
- 3. 在 DSH **移动访问 → 远程 → cpolar** 中安装组件并保存 Authtoken。
15
+ 3. 在 DSH **移动访问 → cpolar** 中安装组件并保存 Authtoken。
16
16
 
17
17
  地区必须与预留记录一致。官方命令示例使用 `cn_vip`,但不要将它照抄到其他地区的预留记录;其他地区的配置值请按 cpolar 当前说明确认。本指南不提供固定地区或域名后缀对照表。
18
18
 
@@ -52,7 +52,7 @@ DSH 加载器会整体替换条目的 `config`,不是逐键合并。因此不
52
52
 
53
53
  配置值会去除首尾空白。插件的名字检查仅限制请求格式:以字母或数字开头,只含字母、数字、`.`、`_`、`-`,长度不超过 63 字符;这不是 DNS 标签规范,也不代表 cpolar 服务端会接受。预留是否有效仍取决于账号、地区和 cpolar 的实际规则。[官方子域名配置说明](https://www.cpolar.com/docs#configure-secondary-subdomain)与教程说明了 `-subdomain`、`-region` 参数。
54
54
 
55
- 确认没有正在运行的任务后,完整退出并重开 DSH,再在 **移动访问 → 远程 → cpolar** 中连接。连接后使用面板实际显示的 HTTPS 地址,不要自行拼接域名后缀。
55
+ 确认没有正在运行的任务后,完整退出并重开 DSH,再在 **移动访问 → cpolar** 中连接。连接后使用面板实际显示的 HTTPS 地址,不要自行拼接域名后缀。
56
56
 
57
57
  ## 验证与配对
58
58
 
package/docs/IROH.en.md CHANGED
@@ -10,16 +10,20 @@ iroh replaces public domains and tunnel accounts with an encrypted direct connec
10
10
  - Windows x64 or Linux x64 (the only published sidecar targets).
11
11
  - Android 10+ with the full `-iroh.apk`, supporting arm64-v8a and x86_64. The ordinary `.apk` is the compatibility build without native libraries: it retains existing HTTPS connections and serves older automatic-update links, but cannot use iroh. Mobile browsers cannot connect directly through iroh either. Both APKs have the same application ID and official signer; install only one.
12
12
  - Press **Install official component** once to fetch the sidecar: the plugin downloads the pinned `dsh-mobile-iroh 0.1.0-alpha.1` release per platform (about 15 MB on Windows x64, 24 MB on Linux x64), verifies its SHA-256, and stores it in the plugin private directory. An installed companion plugin with a verified copy is reused instead, with no download. The Rust source lives with the main repository under `native/iroh-host` (shared core under `native/iroh-core`) and is built per platform in CI.
13
- - DSH Mobile stays enabled; the iroh channel is off by default and never disturbs LAN or other remote channels.
13
+ - DSH Mobile stays enabled; iroh is off by default. LAN runs independently, but only one remote provider is active: switching to iroh stops the previous remote channel.
14
14
 
15
15
  ## Usage
16
16
 
17
- 1. Under **Mobile access → Remote**, pick `iroh (Experimental)`.
18
- 2. Press **Prepare iroh → Install official component** (labelled with the download size): the first run downloads and verifies the sidecar; later runs reuse the verified copy. A hash mismatch or an unsupported platform stops here with a reason instead of a half-started channel. Merely switching the channel on never triggers a download.
17
+ 1. Under **Mobile access**, pick `iroh (Experimental)`.
18
+ 2. Press **Install official component** (labelled with the download size): the first run downloads and verifies the sidecar; later runs reuse the verified copy. A hash mismatch or an unsupported platform stops here with a reason instead of a half-started channel. Merely switching the channel on never triggers a download.
19
19
  3. Turn remote access on: the plugin resolves the endpoint identity, issues the endpoint gateway certificate (own CA, 90-day leaf, 30-day renewal headroom), starts a dedicated gateway, launches the sidecar, and waits for `ready`. `ready` means the sidecar is connected and the gateway serves its loopback socket.
20
20
  4. Press **Generate iroh pairing QR code** and scan it with the full App. The descriptor binds the sidecar's six-digit code, the Gateway's one-time token and pinned CA. Generating another descriptor replaces the previous pairing window; pairing a phone redeems the Gateway token through the normal pair endpoint over iroh.
21
21
  5. Switching off or switching providers stops the owned process and Gateway without deleting stored pairings. The independent App has a different package identity; its Keystore credentials are not automatically migrated into this App.
22
22
 
23
+ Main actions stay hidden before component installation. Afterwards, the toggle, QR generation and Copy pairing link buttons share one row. Copy stays visible but disabled without valid pairing data; copying an existing descriptor does not generate another pairing code.
24
+
25
+ To reclaim component storage, turn off iroh remote access, expand the component details and choose **Remove the downloaded iroh component**. This removes only the pinned program downloaded by this plugin, keeping identities, pairings and external companion packages. Later use can reinstall it or reuse a verified external copy. Removal while enabled is refused by the management API as well as the panel.
26
+
23
27
  ## Security boundaries
24
28
 
25
29
  - The sidecar proxies only to a `127.0.0.1`/`::1` loopback gateway with end-to-end TLS; commands and events are versioned, bounded, and rejected closed on unknown fields.
@@ -41,4 +45,21 @@ Before a component release, verify first use with the exact catalog-pinned execu
41
45
  | `iroh_start_timeout` | Inspect iroh errors in the DSH log and network connectivity, and verify that the pinned component runs; repeated pairing is not a substitute for process diagnosis |
42
46
  | Channel `ready` but no phone connects | Check that the App is the full build, the device supports a packaged ABI and the descriptor is fresh. Computer readiness does not establish phone connectivity; a relay-service connection alone does not establish that data uses the relay |
43
47
 
48
+ ## VPN, proxies and network environments
49
+
50
+ iroh prefers direct connections with relay fallback. Direct connections use QUIC/UDP; discovery and relays also need their network services to be reachable. The following environment factors **can** interfere; they are troubleshooting directions, not confirmed failure mechanisms for every VPN or network:
51
+
52
+ - **Global VPN/TUN** (system-level virtual adapters) may take over UDP and DNS so that neither direct nor relay handshakes complete. One user on Win11 + WSL2 mirrored networking over mobile data reported ~6 s to connect after disabling the global VPN, and recovery after excluding DSH Mobile from the VPN. This is community evidence, not a statement about every VPN/network combination or both ABIs.
53
+ - **DNS policy** (fake-IP, filtering): discovery depends on DNS resolution; fake-IP modes may resolve discovery domains to a proxy virtual IP.
54
+ - **Loopback entry**: the app reaches the local gateway via `*.iroh.localhost`; this loopback address should not be handed to a remote proxy/DNS.
55
+
56
+ Things to try (voluntary, subject to your own security policy):
57
+
58
+ 1. Add DSH Mobile (package `io.github.sayach.dshmobile`) to a per-app bypass/exclusion list in your VPN/proxy client; debug builds and the standalone experimental app use different package names. This is the community Android App, not the official DSH Desktop application; configure the one you actually installed.
59
+ 2. If your client supports per-domain rules, set discovery/relay domains to direct. Clash Meta example (illustrative; use your client's syntax): `DOMAIN-SUFFIX,iroh.link,DIRECT`; with fake-ip, add `+.iroh.link` to `fake-ip-filter`. Domain rules only cover client-side resolution — they **cannot** cover all direct peer IPs, relay services and loopback paths, and must not be summarized as "no UDP means it can never work".
60
+ 3. `*.iroh.localhost` is the app's local entry point and must not be sent to a remote proxy/DNS.
61
+ 4. Always-on/lockdown VPN policies may not allow per-app bypass; this plugin will not bypass system security policy, disable certificate verification, or force network switches.
62
+
63
+ A native "detect VPN and warn" is only an optional follow-up; the current version has no such feature, and whether to run a VPN remains the user's decision.
64
+
44
65
  Chinese version: [IROH.md](IROH.md).