dsh-mobile 0.6.7 → 0.6.9

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,26 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.6.9 - 2026-10-15
6
+
7
+ - Enable optional managed Caddy installation on Windows/Linux x64 with independently verified official component URLs, lengths and SHA-256 pins. Tencent Cloud DNSPod credentials, a domain and reachable public ingress are required; existing Cloudflared tunnels and external proxies remain available. Thanks @abworks-dev for the original managed-Caddy contributions in [#176](https://github.com/saya-ch/dsh-mobile/pull/176), [#184](https://github.com/saya-ch/dsh-mobile/pull/184), [#185](https://github.com/saya-ch/dsh-mobile/pull/185) and [#190](https://github.com/saya-ch/dsh-mobile/pull/190).
8
+ - Refresh managed Caddy component inputs to Caddy 2.11.7, Go 1.26.9 and an explicit golang.org/x/net 0.60.0 pin, retaining exact source, checksum and embedded dependency checks.
9
+ - Use explicit single-maintainer manual component publication instead of mandatory second-person approval. Preserve exact tag/source binding, same-run Windows/Linux native gates, draft/public asset verification and occupied-release protection; component publication does not publish npm or Android automatically.
10
+ - Cancel and drain accepted Caddy component work during plugin unload, retain recoverable files on failure, and wait for the owned Caddy process's actual close event before releasing it. Failed cleanup remains visible and retryable.
11
+ - Cover native CaddyController startup/shutdown and HTTP/1.1/HTTP/2 POST responses that remain quiet for more than 60 seconds, including exact response bytes and one upstream request per operation. These isolated checks do not establish public DNS-01 issuance or certificate renewal for the fixed component.
12
+ - Document scoped custom CSS selectors and same-page comparisons before applying older overrides. Current header behavior is retained rather than hiding working actions. Thanks @Void-LifeStream for [#219](https://github.com/saya-ch/dsh-mobile/issues/219).
13
+ - Android App remains the independently published 0.6.4 (build 80); these changes do not require another APK.
14
+
15
+ ## 0.6.8 - 2026-10-15
16
+
17
+ - Fix remote pairing on computers with the same default state path overwriting one another in the Android device list. Automatically identified entries without a pairing CA use their persisted random installation identifier for new pairings; explicit operator IDs, LAN CA fingerprints and self-signed FRP CA fingerprints remain unchanged.
18
+ - Read both device-state versions and write version 2 on the next mutation, preserving each new credential's pairing identity. Existing credentials keep their previous native renewal/probe identity during ordinary upgrades with the same state path and gateway configuration, with no wire-protocol change or required Android App update. See [upgrade and downgrade precautions](SECURITY.md#installation-identity-and-device-state-upgrades).
19
+ - Publish the complete installation identifier atomically without replacing an existing one, avoiding a concurrent starter reading an empty file. Refuse invalid identity files and unsupported initial publication rather than silently changing the identity.
20
+ - Keep working pairings without re-pairing. A local App credential already overwritten by the collision cannot be recovered automatically: update and restart the plugin, then pair each affected computer again. Usable old rows remain valid; any duplicate local row can be removed explicitly without computer-side revocation.
21
+ - Adapt compatibility checks to DSH 0.2.1-alpha.3's authenticated Host-backed settings while retaining the Remote/Connection dependency checks and earlier settings policies. Mobile typography remains local to its Origin. Extend the browser test matrix to alpha.3 and recognize its first-run account dialog without submitting credentials.
22
+ - Add bilingual remote-channel selection notes distinguishing the maintainer's long-term network experience from provider limits and conditional self-hosted deployment characteristics.
23
+ - At this plugin release, Android App 0.6.3 was still the published native version; Android 0.6.4 was published independently later on the same day. Its file-picker changes are not part of this plugin fix. Thanks @Yurzi for reporting [#213](https://github.com/saya-ch/dsh-mobile/issues/213).
24
+
5
25
  ## 0.6.7 - 2026-10-14
6
26
 
7
27
  - Add optional `cpolarSubdomain` and `cpolarRegion` profile settings for a reserved cpolar address. Omitted or blank values keep provider defaults; only the validated HTTPS origin reported by cpolar is used. Existing pairing and authorization checks are unchanged. [Configuration guide](docs/CPOLAR_SUBDOMAIN.en.md).
@@ -12,10 +32,12 @@ Notable changes are recorded here. GitHub Releases provide the downloadable pack
12
32
  - Clarify `/mobile` and both READMEs: detected files are not proof of page activation; ordinary DSH login or phone-sized preview does not establish mobile pairing. Thanks @Dantezcx for the detailed reports in [#209](https://github.com/saya-ch/dsh-mobile/issues/209) and [#210](https://github.com/saya-ch/dsh-mobile/issues/210).
13
33
  - Thanks @GavinQiEr for the request in [#207](https://github.com/saya-ch/dsh-mobile/issues/207) and implementation in [#208](https://github.com/saya-ch/dsh-mobile/pull/208); the original author commit is retained alongside maintainer corrections.
14
34
 
15
- ## Unreleased Android changes
35
+ ## Android 0.6.4 - 2026-10-15
16
36
 
17
37
  - Prefer the system Photo Picker on Android 13+ for supported image requests, with document selection for other requests or an unavailable picker. Preserve multi-selection, MIME filtering and selected URI results without adding storage permission or forcing a vendor gallery.
18
- - Bind standard file callbacks to the active WebView, Origin and document. Cancel them on navigation or teardown and prevent old results from consuming a newer request. These changes require a future App release; the published Android 0.6.3 APK is unchanged.
38
+ - Bind standard file callbacks to the active WebView, Origin and document. Cancel them on navigation or teardown and prevent old results from consuming a newer request. This native update is released independently from plugin 0.6.8 and preserves existing paired records.
39
+ - On WebViews with navigation-listener support, settle file requests before replacing their document and pause new selection until all in-flight document navigations finish, including cancelled and non-committing navigations. This prevents a late cancellation from disabling the new page's file input. Older providers retain their available callbacks; update WebView or reopen the paired computer if selection still fails after changing pages.
40
+ - Retain the package identity, established release signer, permission list and native pairing protocol. Thanks @Void-LifeStream for the attachment report in [#205](https://github.com/saya-ch/dsh-mobile/issues/205), and @xhwxt for the document-picker proposal in [#203](https://github.com/saya-ch/dsh-mobile/pull/203).
19
41
 
20
42
  ## 0.6.6 - 2026-10-14
21
43
 
package/CONTRIBUTORS.md CHANGED
@@ -64,6 +64,8 @@ GitHub's Contributors graph counts commits on the default branch; issue reports
64
64
 
65
65
  ## 问题反馈与建议 / Issue reports and ideas
66
66
 
67
+ 感谢 [@Yurzi](https://github.com/Yurzi) 在 [#213](https://github.com/saya-ch/dsh-mobile/issues/213) 报告不同电脑的远程配对记录互相覆盖。 / Thanks [@Yurzi](https://github.com/Yurzi) for reporting remote pairing records on different computers overwriting one another in [#213](https://github.com/saya-ch/dsh-mobile/issues/213).
68
+
67
69
  感谢 [@Dantezcx](https://github.com/Dantezcx) 在 [#209](https://github.com/saya-ch/dsh-mobile/issues/209) 和 [#210](https://github.com/saya-ch/dsh-mobile/issues/210) 提供侧栏命中、短屏布局和定制资源加载的详细诊断。 / Thanks [@Dantezcx](https://github.com/Dantezcx) for the detailed sidebar hit-testing, short-viewport and customization-loading diagnostics in [#209](https://github.com/saya-ch/dsh-mobile/issues/209) and [#210](https://github.com/saya-ch/dsh-mobile/issues/210).
68
70
 
69
71
  感谢 [@xhwxt](https://github.com/xhwxt) 在 [#203](https://github.com/saya-ch/dsh-mobile/pull/203) 中提出文档选择器改进方案,以及 [@Void-LifeStream](https://github.com/Void-LifeStream) 在 [#205](https://github.com/saya-ch/dsh-mobile/issues/205) 中提供附件选择与回传问题的详细反馈。
@@ -113,12 +115,12 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
113
115
  | [@sortjiajun](https://github.com/sortjiajun) | [#90](https://github.com/saya-ch/dsh-mobile/issues/90) |
114
116
  | [@StrawberryAO](https://github.com/StrawberryAO) | [#39](https://github.com/saya-ch/dsh-mobile/issues/39) |
115
117
  | [@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) |
116
- | [@Void-LifeStream](https://github.com/Void-LifeStream) | [#205](https://github.com/saya-ch/dsh-mobile/issues/205) |
118
+ | [@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) |
117
119
  | [@WalkerJay666](https://github.com/WalkerJay666) | [#201](https://github.com/saya-ch/dsh-mobile/issues/201) |
118
120
  | [@up-and-down-0618](https://github.com/up-and-down-0618) | [#115](https://github.com/saya-ch/dsh-mobile/issues/115) |
119
121
  | [@taki-ohh](https://github.com/taki-ohh) | [#19](https://github.com/saya-ch/dsh-mobile/issues/19) |
120
122
  | [@tianyimc](https://github.com/tianyimc) | [#126](https://github.com/saya-ch/dsh-mobile/issues/126) |
121
123
  | [@Xingcheng-wang](https://github.com/Xingcheng-wang) | [#76](https://github.com/saya-ch/dsh-mobile/issues/76) |
122
124
  | [@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) |
123
- | [@Yurzi](https://github.com/Yurzi) | [#17](https://github.com/saya-ch/dsh-mobile/issues/17) |
125
+ | [@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) |
124
126
  | [@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) |
package/README.en.md CHANGED
@@ -25,20 +25,20 @@
25
25
  <a href="#security">Security</a> ·
26
26
  <a href="#compatibility">Compatibility</a> ·
27
27
  <a href="#contributors">Contributors</a> ·
28
- <a href="CHANGELOG.md">Changelog</a> ·
28
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.9">Release notes</a> ·
29
29
  <a href="README.md">简体中文</a>
30
30
  </p>
31
31
 
32
32
  > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
33
33
  >
34
- > **Current stable release: 0.6.7**. Add reserved cpolar subdomain configuration, improve narrow-screen sidebar and overlay interaction, and clarify mobile customization ownership, failures and recovery. [Changelog](CHANGELOG.md) · [Release downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.7).
34
+ > **Current stable release: 0.6.9**. Enable optional managed Caddy installation on Windows/Linux x64, improve connection shutdown and component cleanup, and add custom-style troubleshooting guidance. Existing remote channels and pairings are retained; no Android app update is required. [Release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.9) · [Full changelog](CHANGELOG.md).
35
35
  >
36
36
  > **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).
37
37
 
38
38
  <p align="center">
39
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.3/dsh-mobile-android-v0.6.3.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
40
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.3/dsh-mobile-android-v0.6.3.apk"><strong>Download Android app 0.6.3</strong></a><br>
41
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.3">Release notes and checksums</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.4/dsh-mobile-android-v0.6.4.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.4/dsh-mobile-android-v0.6.4.apk"><strong>Download Android app 0.6.4</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.4">Release notes and checksums</a></sub>
42
42
  </p>
43
43
 
44
44
  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.
@@ -52,7 +52,7 @@ It also lets you customize the phone from a DSH conversation: `/mobile <what you
52
52
  - **Continue DSH work from a phone**: the same sessions, Workspaces, messages, and tools, in real time.
53
53
  - **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
54
  - **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.
55
- - **Several remote options**: Tailscale, cpolar, cloudflared quick/named tunnels, self-hosted FRP, or your own reverse proxy.
55
+ - **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
56
  - **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.
57
57
  - **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.
58
58
  - **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.
@@ -152,21 +152,24 @@ Remote providers may impose bandwidth and connection limits: the [cpolar Free pl
152
152
 
153
153
  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.
154
154
 
155
- | Channel | Prerequisites | Address and limitation |
156
- | --- | --- | --- |
157
- | cpolar | Account and Authtoken | An option to try on mainland networks; free temporary URLs may change |
158
- | cloudflared quick tunnel | No account or domain | Random temporary URL; no SSE, with [notification limits](docs/CLOUDFLARE_TUNNEL.en.md#quick-tunnel-feature-limits) |
159
- | cloudflared named tunnel | Cloudflare account and domain | Fixed hostname; [setup guide](docs/CLOUDFLARE_TUNNEL.en.md) |
160
- | Tailscale Funnel | Sign-in and Funnel authorization | May be unreliable on mainland-China networks |
161
- | Self-hosted FRP | VPS and domain or real public IPv4 | Server maintenance required; [deploy](docs/SELF_HOSTED_FRP.en.md) or [attach to existing frps](docs/ATTACH_EXISTING_FRPS.en.md) |
162
- | Own reverse proxy | Existing public HTTPS proxy | The plugin provides only its private authenticated backend; [guide](docs/SELF_HOSTED_ORIGIN.en.md) |
155
+ The usage notes below reflect the maintainer's long-term experience on a personal mainland-China network, not a universal comparison. Performance depends on the carrier, network and plan; verify the route on your own phone's network.
156
+
157
+ | Channel | Prerequisites | Address and limitation | Maintainer's usage notes |
158
+ | --- | --- | --- | --- |
159
+ | cpolar | Account and Authtoken | Free temporary URLs may change | The free plan's bandwidth limit noticeably slows everyday loading and synchronization |
160
+ | 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 |
161
+ | 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 |
162
+ | Tailscale Funnel | Sign-in and Funnel authorization | Availability depends on the network | This personal network often needs proxy assistance and may still fail to connect; not every user needs a proxy |
163
+ | Self-hosted FRP | VPS and domain or real public IPv4 | Server maintenance required; [deploy](docs/SELF_HOSTED_FRP.en.md) or [attach to existing frps](docs/ATTACH_EXISTING_FRPS.en.md) | More control over deployment and resources; long-term stability depends on the VPS route, configuration and maintenance |
164
+ | Own reverse proxy | Existing public HTTPS proxy | The plugin provides only its private authenticated backend; [guide](docs/SELF_HOSTED_ORIGIN.en.md) | Reuses your proxy infrastructure; stability depends on the proxy, network route and maintenance |
165
+ | Managed Caddy | Tencent Cloud DNSPod-managed domain and reachable public ingress | Plugin-managed HTTPS and certificates on Windows/Linux x64; [guide](docs/CADDY_MANAGED.en.md) | Does not traverse NAT; check inbound ports and forwarding. Existing Cloudflared users do not need to migrate |
163
166
 
164
167
  <p align="center">
165
168
  <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">
166
169
  </p>
167
170
 
168
171
  1. Open **Mobile Access → Remote** in the lower-left corner of DeepSeek Harness, choose a channel and complete its sign-in or configuration.
169
- 2. Once ready, select **Create remote pairing QR code**. Own reverse proxy reports only **Backend listening**, so verify public HTTPS and WebSocket access as well.
172
+ 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.
170
173
  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.
171
174
  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.
172
175
 
@@ -178,6 +181,7 @@ After selecting the channel in the panel:
178
181
  - **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.
179
182
  - **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.
180
183
  - **Own reverse proxy**: open **Self-hosted connection → Own reverse proxy**, enter the public HTTPS origin (custom ports supported), private listen IPv4, separate HTTP backend port (default 3444), and allowed 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).
184
+ - **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.
181
185
  - **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.
182
186
  - **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).
183
187
 
@@ -188,7 +192,7 @@ After selecting the channel in the panel:
188
192
 
189
193
  > **Remote notifications**: browser `Notification` permission is granted per Origin, and a web-page system toast appears only on the device running that page. Android task reminders are a separate 0.4.0 feature: enable them under DSH **Settings → General** in the app, and keep the WebView page alive; they are not a general background push service. For reliable background delivery, use a server-side webhook or bot channel you have configured.
190
194
 
191
- Tailscale Funnel has broad reach but may be unreliable from mainland China. Its runtime ties the public listener to the parent process and a bounded control channel; parent exit, channel closure, or an explicit stop ends the current generation and cleans up its resources. cpolar is better suited to mainland networks, while self-hosted FRP fits users who already have a VPS and want to avoid public-provider bandwidth quotas. cloudflared runs in two modes: a quick tunnel needs no account or sign-in, but its hostname is random, changes on every reconnect, and is [intended by Cloudflare for testing](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/trycloudflare/) without an uptime guarantee, so it suits temporary or verification use rather than a permanent channel; a named tunnel uses a Cloudflare account token and keeps one fixed public hostname across restarts. An unregistered domain on a mainland-China VPS may be intercepted by the cloud provider; public IPv4 mode avoids that dependency. The plugin validates pinned on-demand components; locally managed configuration and binaries live under `$DSH_HOME/mobile-access/` and can be cleaned up from the panel. VPS files require separate cleanup through the self-hosted connection guide.
195
+ The Funnel runtime ties the public listener to the parent process and a bounded control channel; parent exit, channel closure, or an explicit stop ends the current generation and cleans up its resources. An unregistered domain on a mainland-China VPS may be intercepted by the cloud provider; public IPv4 mode avoids that dependency. The plugin validates pinned on-demand components; locally managed configuration and binaries live under `$DSH_HOME/mobile-access/` and can be cleaned up from the panel. VPS files require separate cleanup through the self-hosted connection guide.
192
196
 
193
197
  Managed self-hosted FRP uses an HTTP vhost to the DSH loopback gateway. Its plaintext VPS listener must be loopback-only, with Caddy providing public HTTPS. Version 0.4.6 adds existing-frps attachment without installing or changing the server: its public-CA mode still needs a restricted HTTP vhost and Caddy, while its self-signed mode forwards raw TCP to a computer-side HTTPS gateway whose CA the 0.4.6 Android app pins during pairing. The self-signed mode currently uses public IPv4 and is unavailable to older apps. Neither mode exposes arbitrary FRP configuration. Because frps `proxyBindAddr` governs proxy listeners globally, do not change it for the new TCP entry without checking existing plaintext vhosts. See the [attachment guide](docs/ATTACH_EXISTING_FRPS.en.md).
194
198
 
@@ -216,6 +220,8 @@ Two kinds of changes are supported: the phone UI itself (theme, layout, buttons)
216
220
 
217
221
  Open customizations through the **Mobile Access pairing entry**. Opening an ordinary DSH page or selecting a phone-sized browser viewport is not mobile pairing, and a file's presence does not establish that the current page loaded it. If extension requests return `401`, check the entry and pairing state; do not enable anonymous access or share Cookies or Tokens.
218
222
 
223
+ An old `mobile.css` patch can override a newer built-in fix. Back up that file and compare the same session, orientation and font settings with and without its styles before adding more rules. Scope CSS Modules selectors to an inspected ancestor, such as `[data-dsh-mobile-header] [class*="_titleRow"]`, rather than matching bare class suffixes/substrings across the page. Hiding an action area with `display: none` removes access to its controls; it is not a collapsible presentation. Thanks for the controlled comparison in [#219](https://github.com/saya-ch/dsh-mobile/issues/219).
224
+
219
225
  Extension manifests, scripts, styles, and assets are revisioned. When the plugin observes a `/mobile` or extension-file change, it notifies authenticated phones to refresh immediately; 45-second visible and 5-minute hidden checks remain only as recovery fallbacks. A failed Host staging pass keeps the current version; if the Host has changed but the new phone UI cannot activate, that extension closes and retries instead of mixing generations.
220
226
 
221
227
  An extension action's `input` may use a callable Schemastery schema such as `api.schema.object(...)` or an adapter with `parse(value)`; mobile `api.host.invoke()` sends JSON explicitly, and the input is validated and normalized before the computer-side action runs.
@@ -239,6 +245,8 @@ The examples above, applied:
239
245
 
240
246
  The Android app lists computers and their LAN/remote records under **Paired computers**. The two authorization types remain separate, so one computer can have two rows. Upgrades migrate old credentials without re-pairing; after a changed address is verified, matching identities merge and keep their names. Self-signed FRP uses a separate CA fingerprint and may create another row. Android Keystore encrypts tokens and pinned CAs. A pairing QR code contains temporary pairing information, never a long-lived device token or CA private key.
241
247
 
248
+ Unless an identifier is configured manually, new pairings through a public-certificate remote entry use a random identifier saved on the computer, preventing identical installation paths from overwriting another computer's row. Working connections need no re-pairing or Android App update; LAN and self-signed FRP still use their respective CAs. Quit DSH normally and restart after updating; read the [state-backup precautions](SECURITY.md#installation-identity-and-device-state-upgrades) before downgrading.
249
+
242
250
  Each row shows its custom name, transport, Origin, periodically refreshed reachability, and last connection time. A green dot means **Reachable**; a gray dot means **Checking**, **Temporarily unreachable**, **Pairing expired**, or **Removed on computer**. The check validates the DSH Gateway over HTTPS instead of using ICMP, so a temporary network outage is not mistaken for computer-side revocation.
243
251
 
244
252
  - **Startup behavior → Open DSH directly** (default): one device connects directly; with multiple devices, the app tries the last-used device first, then the still-valid device with the most recent connection. A bounded connection budget returns to the list instead of spinning forever.
@@ -352,6 +360,7 @@ Three layers: the Host face for discovery, pairing, HTTPS, loopback proxying, an
352
360
  - A remote origin is publicly reachable, but unpaired requests cannot enter DSH; turn the remote switch off when it is not needed.
353
361
  - cpolar downloads a pinned official build only after confirmation and verifies its size and SHA-256. It installs no system service, PATH entry, or startup task, and plugin cleanup removes its managed files.
354
362
  - cloudflared likewise downloads a pinned build from the official GitHub Release only after confirmation and verifies the exact size and SHA-256, and it launches the client with automatic updates disabled so the running binary is always the verified one. A quick tunnel needs no account, token, or DNS record; a named tunnel token is stored only in the plugin private directory and reaches cloudflared through the environment, and cleanup deletes every file it manages.
363
+ - Managed Caddy downloads a fixed component reviewed and published by DSH Mobile, only after confirmation, and checks its size, SHA-256, core and DNS module versions. DNS credentials and certificates stay in a private directory; no system service, PATH entry or system trust certificate is added. Removing the component preserves other channels and paired devices.
355
364
  - Self-hosted FRP downloads pinned official `frpc` only after confirmation and verifies the origin, exact size, SHA-256, archive paths, and executable version. The shared token never appears in status, diagnostics, or attachment-plan responses. Copying a server template, or explicitly copying a token-bearing attach config after re-entering its token, places it on the system clipboard; clear it after use. Local cleanup removes only plugin-managed files. Managed VPS deployments require separate uninstall-script or one-click cleanup; attaching to an existing frps neither changes nor cleans up that VPS. Automatic deployment and server cleanup require SSH host-key verification against the VPS console.
356
365
  - A paired device is a fully trusted DeepSeek Harness operator and can run tools on the computer; revoke lost devices from the computer.
357
366
  - The mobile gateway proxies requests as a local DSH operator and supports `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, and `DELETE` on ordinary plugin routes; writes still require a paired Session, exact Origin, and CSRF validation. Third-party plugins must not treat the upstream loopback Host as proof that the client is physically local to the computer.
@@ -361,6 +370,7 @@ See [SECURITY.md](SECURITY.md).
361
370
 
362
371
  ## Troubleshooting
363
372
 
373
+ - **Pairing a second computer overwrites the first**: see [#213](https://github.com/saya-ch/dsh-mobile/issues/213). Update to plugin 0.6.8 or newer, restart DSH normally, then scan each affected computer's current QR code. An App credential already overwritten cannot be recovered automatically; working old rows need no re-pairing. If the same address has both an old and a new row, confirm the new one works, then delete only the extra local App row. Do not reset remote access. Read the [device-state backup and downgrade precautions](SECURITY.md#installation-identity-and-device-state-upgrades) before upgrading.
364
374
  - **Pairing succeeds but renewal returns `401` or repeatedly asks to pair again**: other services on the same hostname or stale Cookies may interfere with authentication. Update to the latest plugin and app, then retry through the current Mobile Access entry. In a browser, scanning the current QR code again refreshes this plugin's authentication Cookies without clearing all website data. If it still fails, inspect the failed request and sanitized logs; other authentication or proxy errors can also return `401`.
365
375
  - **The testing notice cannot be confirmed or settings cannot be saved**: open DSH directly at its local address on the computer, then inspect the terminal log or the failed settings request in the browser's Network panel. Connection diagnostics do not test settings writes. Keep the existing configuration and `settings.yaml.imported`, and investigate the specific error; the same UI message can have different causes. See [DSH #860](https://github.com/deepseek-ai/deepseek-harness/discussions/860).
366
376
  - **A settings request returns HTTP `403`**: first inspect DSH's Host/Origin trust checks and any proxy response. Check whether an iframe, proxy, or browser extension changes the request's origin, and verify direct local access. Keep the trust checks enabled.
@@ -387,6 +397,7 @@ Version 0.5.2 keeps the DSH host peer names but does not block installation by D
387
397
  | cloudflared quick/named tunnel | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) | Yes, x64/arm64 (on-demand) |
388
398
  | Self-hosted FRP | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) |
389
399
  | Own reverse proxy | Yes (config only) | Yes (config only) | Yes (config only) | Yes (config only) |
400
+ | Managed Caddy | Yes (on-demand) | Yes (on-demand) | No | No |
390
401
 
391
402
  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.
392
403
 
@@ -399,6 +410,7 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
399
410
  | `0.6.4` | `0.2.0-rc.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additionally 72 real public-slot composer layouts, Windows Desktop directory-picker composition and cross-platform regressions. The reported remote timeout in community Desktop 2.0.17 remains unclaimed as accepted |
400
411
  | `0.6.5` | Packed module-management and mobile-settings regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`; additionally Windows cpolar extraction and populated Trajectory layout with published `maid-atelier` 0.1.7. This does not establish acceptance of every third-party skin or reporter device |
401
412
  | `0.6.6` | Packed attachment intake and decoded-preview regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`, covering multiple images, cancellation, late results and superseded requests. Android system-picker changes are released independently, not through the npm update |
413
+ | `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 |
402
414
 
403
415
  <details>
404
416
  <summary>Historical version checks</summary>
package/README.md CHANGED
@@ -25,20 +25,20 @@
25
25
  <a href="#安全">安全</a> ·
26
26
  <a href="#兼容性">兼容性</a> ·
27
27
  <a href="#贡献者">贡献者</a> ·
28
- <a href="CHANGELOG.md">更新记录</a> ·
28
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.9">更新记录</a> ·
29
29
  <a href="README.en.md">English</a>
30
30
  </p>
31
31
 
32
32
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
33
33
  >
34
- > **当前正式版本:0.6.7**。支持 cpolar 预留子域名配置,改善窄屏侧栏与浮层交互,并补全移动定制的入口识别、失败提示和恢复处理。[更新记录](CHANGELOG.md) · [版本下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.7)。
34
+ > **当前正式版本:0.6.9**。开放 Windows/Linux x64 的托管 Caddy 按需安装,改善连接停止与组件清理,并补充自定义样式排障建议。已有远程通道和配对保留,无需更新 Android App。[更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.9) · [完整更新记录](CHANGELOG.md)。
35
35
  >
36
36
  > **版本说明**:自插件 **0.6.2** 起,Android App 与插件独立编号、独立发布,版本号无需一致;插件升级不代表 App 需要同步升级。[兼容说明](#兼容性)。
37
37
 
38
38
  <p align="center">
39
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.3/dsh-mobile-android-v0.6.3.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
40
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.3/dsh-mobile-android-v0.6.3.apk"><strong>下载 Android App 0.6.3</strong></a><br>
41
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.3">版本说明与校验文件</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.4/dsh-mobile-android-v0.6.4.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.4/dsh-mobile-android-v0.6.4.apk"><strong>下载 Android App 0.6.4</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.4">版本说明与校验文件</a></sub>
42
42
  </p>
43
43
 
44
44
  DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP 或自有反向代理远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
@@ -52,7 +52,7 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
52
52
  - **在手机上继续电脑端的工作**:同一份会话、工作区、消息和工具,实时同步。
53
53
  - **用对话定制手机端**:在 DSH 对话里提出布局、交互或功能需求;文件修改完成后,手机页面通常会自动刷新。
54
54
  - **专属触屏布局**:会话抽屉、工具详情、设置、提问卡片和输入栏都按手机重新组织;App 跟随系统语言(简/英/意),插件界面跟随 DSH 语言。
55
- - **多种远程通道**:Tailscale、cpolar、cloudflared 快速/命名隧道、自建 FRP、自有反向代理,按网络任选。
55
+ - **多种远程通道**:Tailscale、cpolar、cloudflared 快速/命名隧道、自建 FRP、自有反向代理,按网络任选;Windows/Linux x64 还可由插件托管 Caddy HTTPS 与证书。
56
56
  - **配对与多设备**:扫码、链接或密钥配对一次;切换 Wi-Fi、热点或 IP 后通常自动恢复;App 在一个列表中显示局域网和远程配对的电脑,定期检测可达状态,并支持切换、重新配对或删除本地记录。
57
57
  - **一键诊断与放行**:检查版本、网关、网卡、防火墙和远程通道,生成脱敏报告;被拦截的第三方插件连接按确切路径一键放行。
58
58
  - **任务系统通知**:任务完成与待输入以 Android 系统通知提醒,可在 App 内的 DSH“通用设置”中开启,锁屏文本脱敏。
@@ -152,21 +152,24 @@ dsh plugin --profile web add dshmarket
152
152
 
153
153
  页面能打开但一直“重连中”,应先区分 WebSocket 升级失败、慢速数据同步和心跳超时,操作见[慢链路与反复重连指南](docs/SLOW_CONNECTIONS.md)。0.5.4 还提供按确切路径启用的 WebSocket 压缩,默认关闭;长会话或计量网络可按指南尝试,并对比实际传输量。
154
154
 
155
- | 连接方式 | 需要准备 | 地址特点与注意事项 |
156
- | --- | --- | --- |
157
- | cpolar | cpolar 账号与 Authtoken | 国内网络可优先尝试;免费临时地址可能变化 |
158
- | cloudflared 快速隧道 | 无需账号或域名 | 临时随机地址;不支持 SSE,[即时通知存在限制](docs/CLOUDFLARE_TUNNEL.md#快速隧道的功能限制) |
159
- | cloudflared 命名隧道 | Cloudflare 账号与域名 | 固定域名;[配置指南](docs/CLOUDFLARE_TUNNEL.md) |
160
- | Tailscale Funnel | Tailscale 登录与 Funnel 授权 | 中国大陆网络可能不稳定 |
161
- | 自建 FRP | 已有 VPS,域名或真实公网 IPv4 | 需管理服务器;[部署](docs/SELF_HOSTED_FRP.md)或[接入既有 frps](docs/ATTACH_EXISTING_FRPS.md) |
162
- | 自有反向代理 | 已有公开 HTTPS 代理 | 插件只提供私有认证后端;[配置指南](docs/SELF_HOSTED_ORIGIN.md) |
155
+ 下表的使用参考来自维护者在中国大陆自用网络的长期体验,不是普适测评;实际表现受运营商、网络和套餐影响,请在自己的手机网络验证。
156
+
157
+ | 连接方式 | 需要准备 | 地址特点与注意事项 | 维护者使用参考 |
158
+ | --- | --- | --- | --- |
159
+ | cpolar | cpolar 账号与 Authtoken | 免费临时地址可能变化 | 免费方案限速明显,日常加载与同步体验较差 |
160
+ | cloudflared 快速隧道 | 无需账号或域名 | 临时随机地址;不支持 SSE,[即时通知存在限制](docs/CLOUDFLARE_TUNNEL.md#快速隧道的功能限制);[官方仅定位为开发测试用途](https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/) | 长期使用中经常断连,原因尚未确认;只作临时或测试选择 |
161
+ | cloudflared 命名隧道 | Cloudflare 账号与域名 | 固定域名;[配置指南](docs/CLOUDFLARE_TUNNEL.md) | 已长期使用的通道中最稳定;有账号和域名可优先尝试 |
162
+ | Tailscale Funnel | Tailscale 登录与 Funnel 授权 | 实际可用性取决于网络 | 自用网络常需代理辅助,仍可能连接失败;并非所有用户都需要代理 |
163
+ | 自建 FRP | 已有 VPS,域名或真实公网 IPv4 | 需管理服务器;[部署](docs/SELF_HOSTED_FRP.md)或[接入既有 frps](docs/ATTACH_EXISTING_FRPS.md) | 部署与资源更可控,长期稳定性取决于 VPS 线路、配置与运维 |
164
+ | 自有反向代理 | 已有公开 HTTPS 代理 | 插件只提供私有认证后端;[配置指南](docs/SELF_HOSTED_ORIGIN.md) | 可沿用自己的代理设施,稳定性取决于代理、线路与运维 |
165
+ | 托管 Caddy | 腾讯云 DNSPod 管理的域名与公网入站 | 插件管理 HTTPS 与证书;Windows/Linux x64;[配置指南](docs/CADDY_MANAGED.md) | 不提供内网穿透,需自行确认入站端口和映射;已有 Cloudflared 用户不必迁移 |
163
166
 
164
167
  <p align="center">
165
168
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/remote-access.png" width="82%" alt="DSH Mobile 远程访问与通道选择">
166
169
  </p>
167
170
 
168
171
  1. 在 DeepSeek Harness 左下角打开 **移动访问 → 远程**,按上表选择通道,完成登录或配置。
169
- 2. 状态变为“远程访问已就绪”后,点击 **生成远程配对二维码**。自有反向代理仅显示“后端已监听”,仍需确认公网 HTTPS 与 WebSocket 可用。
172
+ 2. 状态变为“远程访问已就绪”后,点击 **生成远程配对二维码**。自备代理模式的“后端已监听”不等于公网就绪,仍需确认公网 HTTPS 与 WebSocket 可用。
170
173
  3. 在 Android App 中选择 **远程访问**,扫描当前二维码完成配对;公开证书入口也可用手机浏览器打开配对链接。
171
174
  4. 以后 App 使用保存的地址与凭据自动重连。临时地址改变时,重新扫描电脑端当前二维码验证新地址,不需要清除 App 数据;旧设备 token 不会发送给新 Origin。
172
175
 
@@ -178,6 +181,7 @@ dsh plugin --profile web add dshmarket
178
181
  - **cpolar**:点击 **安装官方组件**,登录 cpolar 控制台取得 Authtoken,粘贴后点击 **保存并连接**。组件只会在确认后下载到插件私有目录;免费临时地址可能在 DSH 或 cpolar 重启后变化。
179
182
  - **自建 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)。
180
183
  - **自有反向代理**:展开 **自建连接 → 自有反向代理**,填写公网 HTTPS 地址(支持自定义端口)、私有监听 IPv4、独立 HTTP 后端端口(默认 3444)和代理来源 CIDR,再点击 **保存并启动后端**。适合已有 Lucky/Nginx/Caddy 的用户,无需隧道组件;需要 Android App 0.4.0 或更高版本。详见 [自有反向代理指南](docs/SELF_HOSTED_ORIGIN.md)。
184
+ - **托管 Caddy**:在 **自建连接 → 自有反向代理** 中选择 **托管 Caddy**,点击 **安装托管 Caddy** 并确认下载。填写公网 HTTPS 地址、腾讯云 DNSPod 凭据和本机 HTTPS 监听端口,再点击 **保存并启动 Caddy**。需要域名和可达的公网入站,不会替你穿透 CGNAT;端口映射与完整步骤见 [托管 Caddy 指南](docs/CADDY_MANAGED.md)。
181
185
  - **cloudflared 快速隧道**:点击 **安装官方组件**,插件在确认后从官方发布页下载固定版本到插件私有目录,随后自动申请一个临时公网地址(quick tunnel),**无需注册或登录**。适合不想注册账号的用户;quick tunnel 地址每次重连都会变化,官方定位为测试用途、有限流且无可用性保证,请勿用于必须长期可达的生产访问,只适合临时或验证场景。
182
186
  - **cloudflared 命名隧道**:已有 Cloudflare 账号和域名时,把隧道类型切到 **命名隧道**,填入连接器令牌、公网域名与本机转发端口,即可获得重启后不变的固定地址(令牌只存私有目录、只经环境变量传给 cloudflared)。步骤见 [Cloudflare 命名隧道](docs/CLOUDFLARE_TUNNEL.md)。
183
187
 
@@ -188,7 +192,7 @@ dsh plugin --profile web add dshmarket
188
192
 
189
193
  > **远程通知说明**:浏览器的 `Notification` 权限按 Origin 分别授权,网页系统通知只显示在运行该网页的设备上。Android App 的任务提醒是独立的 0.4.0 功能,需要在 App 内 DSH 的 **设置 → 通用设置** 中主动开启,且依赖 WebView 页面仍存活;它不是通用的后台推送。需要可靠的后台推送时,请使用你已配置的服务端 webhook 或机器人通道。
190
194
 
191
- Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。其运行组件把公开监听生命周期绑定到父进程和受限控制通道;父进程退出、控制通道关闭或显式停止时会结束当前代次并清理资源。cpolar 更适合国内网络;自建 FRP 适合已有 VPS、希望避开公共服务带宽限制的用户。cloudflared 有两种模式:快速隧道不需要账号或登录,但地址随机、每次重连都会变化,[官方定位为测试用途](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/trycloudflare/)且无可用性保证,因此只适合临时或验证场景;命名隧道使用 Cloudflare 账号令牌,能保留重启后不变的固定公网域名。中国大陆 VPS 上的未备案域名可能被云厂商拦截,此时可使用公网 IPv4 模式。插件会校验按需下载的固定版本组件;本机托管的配置与程序保存在 `$DSH_HOME/mobile-access/`,可在面板中清理。VPS 侧的文件须按自建连接指南单独清理。
195
+ Funnel 的运行组件把公开监听生命周期绑定到父进程和受限控制通道;父进程退出、控制通道关闭或显式停止时会结束当前代次并清理资源。中国大陆 VPS 上的未备案域名可能被云厂商拦截,此时可使用公网 IPv4 模式。插件会校验按需下载的固定版本组件;本机托管的配置与程序保存在 `$DSH_HOME/mobile-access/`,可在面板中清理。VPS 侧的文件须按自建连接指南单独清理。
192
196
 
193
197
  自建 FRP 的托管部署使用指向 DSH 回环网关的 HTTP vhost:VPS 上的明文 vhost 只允许回环访问,由 Caddy 提供公网 HTTPS。0.4.6 新增“接入既有 frps”,不会安装或改动服务器;公开 CA 档仍需受限 HTTP vhost 与 Caddy,自签档则用 frps TCP 透传至电脑端 HTTPS 网关,须由 0.4.6 Android App 在配对时固定 CA。自签档目前面向公网 IPv4,旧版 App 不支持;两档都不开放任意 FRP 配置。frps 的 `proxyBindAddr` 是全局代理监听设置,不能只为新增 TCP 入口调整而忽略已有明文 vhost。[接入指南](docs/ATTACH_EXISTING_FRPS.md)。
194
198
 
@@ -216,6 +220,8 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
216
220
 
217
221
  定制需要从 **移动访问的配对入口**进入。直接打开普通 DSH 网页或调整浏览器为手机视口,不等于完成移动配对;文件存在也不代表当前页面已加载。若扩展接口返回 `401`,先核对入口与配对状态,不要开放匿名访问或公开 Cookie、Token。
218
222
 
223
+ 旧的 `mobile.css` 补丁可能覆盖新版内置修复。排查布局时先备份文件,在同一会话、方向和字号下对比有无该样式的效果,不要先叠加更多规则。匹配 CSS Modules 类名时应限定到已核对的区域祖先,例如 `[data-dsh-mobile-header] [class*="_titleRow"]`,不要裸用后缀/子串选择器;用 `display: none` 隐藏操作区会移除其中功能,不等于折叠。感谢 [#219](https://github.com/saya-ch/dsh-mobile/issues/219) 提供的对照记录。
224
+
219
225
  扩展清单及其脚本、样式和资源按版本标识刷新。插件监听到 `/mobile` 或扩展文件变化后,会通过已认证连接通知手机立即更新;页面可见时每 45 秒、隐藏时每 5 分钟的检查只作为断线兜底。Host 暂存失败会继续使用现有版本;若 Host 已更新但新手机界面激活失败,则关闭该扩展并自动重试,避免混用新旧能力。
220
226
 
221
227
  扩展动作的 `input` 可以直接使用 `api.schema.object(...)` 等 Schemastery schema,也可以使用带 `parse(value)` 的适配器;手机端 `api.host.invoke()` 会按 JSON 请求发送,输入会在电脑端动作执行前完成校验和规范化。
@@ -239,6 +245,8 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
239
245
 
240
246
  Android App 在“已配对设备”中统一显示电脑及其局域网/远程连接记录。两种方式的授权彼此独立,同一台电脑可能有两条记录。升级会迁移旧凭据,无需重新配对;重新验证变化的地址后,相同身份的记录会合并并保留名称。自签 FRP 使用独立 CA 指纹,可能另成一条记录。Token 和固定的 CA 由 Android Keystore 加密;配对二维码含短期配对信息,不含长期设备 Token 或 CA 私钥。
241
247
 
248
+ 未手动指定标识时,公开证书远程入口的新配对使用电脑保存的随机标识,避免相同安装路径让两台电脑的记录互相覆盖。已有连接无需为此重新配对,也不需要更新 Android App;局域网和自签 FRP 仍按各自的 CA 区分。更新后正常退出并重启 DSH,降级前请先阅读[状态备份注意事项](SECURITY.md#installation-identity-and-device-state-upgrades)。
249
+
242
250
  每条记录显示自定义名称、连接方式、Origin、定期更新的可达状态和最近连接时间。绿色状态点表示“可达”,灰色状态点表示“检测中”“暂不可达”“配对已过期”或“电脑端已移除”;可达性检查直接验证 DSH Gateway,不依赖 ICMP,也不会把暂时断网误判成电脑端撤销。
243
251
 
244
252
  - **启动行为 → 直接进入 DSH**(默认):单设备直接连接;多设备优先连接上次使用的设备,其次按最近连接时间选择仍有效的设备。连接超过有限重试预算后自动回到列表,不会无限转圈。
@@ -353,6 +361,7 @@ flowchart LR
353
361
  - 远程地址可从公网到达,但未配对请求无法进入 DSH;不使用时应关闭远程开关。
354
362
  - cpolar 仅在用户确认后下载固定官方版本并校验大小和 SHA-256;不会安装系统服务、写入 PATH 或设置开机启动,插件清理会删除其托管文件。
355
363
  - cloudflared 同样仅在用户确认后从官方 GitHub Release 下载固定版本并校验精确大小和 SHA-256,且启动时关闭自动更新,以保证运行的始终是已校验的那份二进制;快速隧道不需要账号、Token 或 DNS 记录;命名隧道令牌只存插件私有目录、只经环境变量传给 cloudflared,清理时删除插件托管的全部文件。
364
+ - 托管 Caddy 从 DSH Mobile 审核发布的固定组件下载,安装前需确认,下载后校验大小、SHA-256、核心与 DNS 模块版本。DNS 凭据和证书保存在私有目录,不安装系统服务、不修改 PATH 或系统证书信任;移除组件不会删除其他通道和设备配对。
356
365
  - 自建 FRP 仅在用户确认后从官方 Release 下载固定版本 `frpc`,校验来源、精确大小、SHA-256、压缩包路径和可执行文件版本;共享 Token 不会出现在状态、诊断或接入清单响应中。复制服务器模板,或重新输入 Token 后显式复制含 Token 的接入配置时,它会进入系统剪贴板,请粘贴后及时清除。本机清理只删除插件管理的文件;托管部署的 VPS 需用面板卸载脚本或一键清理单独清除,接入既有 frps 则不会改动或清理你的 VPS。自动部署与一键清理前都需核对 SSH 主机指纹。
357
366
  - 配对设备拥有控制电脑端 DeepSeek Harness 的能力,应视为完全可信设备;丢失手机后应在电脑端撤销设备。
358
367
  - 移动网关以 DSH 本机操作者身份代理请求,支持普通插件路由的 `GET`、`HEAD`、`POST`、`PUT`、`PATCH`、`DELETE`;写请求仍校验配对 Session、精确 Origin 与 CSRF。第三方插件不能把上游回环 Host 当成请求来自电脑物理本机的证明。
@@ -362,6 +371,7 @@ flowchart LR
362
371
 
363
372
  ## 故障排查
364
373
 
374
+ - **配对第二台电脑后,第一台被覆盖**:见 [#213](https://github.com/saya-ch/dsh-mobile/issues/213);请升级至插件 0.6.8 或更新版本并正常重启 DSH,再分别扫描受影响电脑当前的二维码。已经被覆盖的 App 本地凭据不能自动找回;仍可连接的旧条目无需重配。若同一地址出现新旧两条记录,确认新条目正常后,只删除 App 中多余的本地条目,不要重置远程访问。升级前请阅读[设备状态备份与降级注意事项](SECURITY.md#installation-identity-and-device-state-upgrades)。
365
375
  - **配对成功后仍反复提示重新配对或续期 `401`**:同一域名上的其他服务或旧 Cookie 可能干扰认证。更新至最新插件及 App,再从当前移动访问入口重试;浏览器重新扫描当前二维码可更新本插件的认证 Cookie,无需清除所有网站数据。若仍失败,查看失败请求与脱敏日志,其他认证或代理错误也可能返回 `401`。
366
376
  - **内测声明无法确认或设置无法保存**:先在电脑端直接打开 DSH 的本机地址,查看终端日志或浏览器 Network 中失败的设置请求。连接诊断不检查设置写入;保留现有配置及 `settings.yaml.imported`,按具体错误排查。相同界面提示可能有不同原因,见 [DSH #860](https://github.com/deepseek-ai/deepseek-harness/discussions/860)。
367
377
  - **设置请求返回 HTTP `403`**:先检查 DSH 的 Host/Origin 信任校验及代理响应。检查 iframe、代理和浏览器扩展是否改变请求来源,使用本机直接访问验证;保持信任检查启用。
@@ -388,6 +398,7 @@ flowchart LR
388
398
  | cloudflared 快速/命名隧道 | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) | 支持 x64/arm64(按需下载) |
389
399
  | 自建 FRP | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) |
390
400
  | 自有反向代理 | 支持(纯配置) | 支持(纯配置) | 支持(纯配置) | 支持(纯配置) |
401
+ | 托管 Caddy | 支持(按需下载) | 支持(按需下载) | 不支持 | 不支持 |
391
402
 
392
403
  macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funnel 与 cpolar 暂未提供 macOS 组件。诊断页的防火墙检查目前仅覆盖 Windows,其他系统显示“不适用”。
393
404
 
@@ -400,6 +411,7 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
400
411
  | `0.6.4` | `0.2.0-rc.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证 72 组真实公共插槽输入栏布局、Windows Desktop 目录选择器组合及跨平台回归。社区 Desktop 2.0.17 的原报告远程超时仍未宣称验收 |
401
412
  | `0.6.5` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包模块管理与移动设置回归;另验证 Windows cpolar 解包及正式 `maid-atelier` 0.1.7 下有内容轨迹的布局修复。不代表全部第三方皮肤或报告者设备已验收 |
402
413
  | `0.6.6` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包附件接收与图片预览回归,覆盖多图、取消、迟到结果和旧请求;Android 系统选择器改进独立发布,不包含在 npm 更新中 |
414
+ | `0.6.8` | `0.2.1-alpha.3` 的打包移动页面、旧 WebView API 模拟、WebSocket 工作区读取、移动设置、模块管理、侧栏及输入栏回归;身份修复另有真实 HTTP/TLS 与旧凭据升级测试。本机官方 Desktop `0.2.0-rc.2` 已加载该版本插件,原配对保留;不代表手机 5G 或全部第三方插件组合已验收 |
403
415
 
404
416
  <details>
405
417
  <summary>历史版本验证记录</summary>
package/SECURITY.md CHANGED
@@ -27,6 +27,15 @@ The maintainer will acknowledge a complete report within seven days. Publication
27
27
  - The 0.4.6 existing-frps self-signed entry instead forwards raw TCP to the computer-side HTTPS gateway. Its QR link and bare App key carry a versioned `dsh2` CA-required marker, which Android 0.4.5 and earlier reject. During explicit remote pairing, the 0.4.6 app retrieves the gateway's public CA without sending a credential, checks its validity and SHA-256 fingerprint against the pairing key, and pins it to the exact Origin; HTTP 404, a missing, changed, or untrusted CA cannot downgrade this flow to platform trust. Re-pairing an existing pinned identity retains that CA requirement. The existing exact-Origin device-token restriction still applies: a CA fingerprint alone cannot renew a device credential. The CA is not installed in Android's system trust store. The 0.4.5 app lacks this remote CA-pinning path, and ordinary phone browsers will not trust the self-signed certificate.
28
28
  - Keep pairing closed except during a short local onboarding action.
29
29
  - Revoke a lost device immediately and rotate the device registry if credential theft is suspected.
30
+
31
+ ### Installation identity and device-state upgrades
32
+
33
+ - Automatically identified entries without a pairing CA use the random `installation-id` file in the active Mobile state directory for new pairings, not a hash of the state-file path. Explicit operator IDs and CA-bound LAN/self-signed FRP identities remain unchanged. The identifier is public, not an authentication secret. Copying the entire state directory also copies its identity and credentials; this fix does not distinguish cloned installations. Do not delete the identity file to troubleshoot a connection.
34
+ - Initial identity creation requires a filesystem that supports hard links within the Mobile state directory. A complete private candidate is published without replacing an existing identity, so concurrent starts cannot read a partially written identifier. Unsupported filesystems or invalid identity files fail explicitly; the plugin does not silently generate a replacement. Reading an existing valid identity does not require creating a hard link.
35
+ - Plugin 0.6.8 reads device-state versions 1 and 2 and writes version 2 on the next mutation. New records retain an optional `nativeInstanceId` binding, so authenticated native renewal and probe return the identity used for their pairing. Older unbound records keep the gateway's legacy identity during an ordinary upgrade with the same state path and gateway configuration; moving their state or changing their certificate/operator identity is not covered by this preservation. They are not reassigned from discovery metadata. The native response fields remain unchanged and the published Android App 0.6.3 needs no update for this fix.
36
+ - Stop the old Gateway normally before updating, then restart DSH. Do not run old and new plugins against the same state concurrently. Plugin 0.6.7 and earlier cannot read version 2; if downgrade may be necessary, stop DSH and back up the complete Mobile state directory before upgrading. There is no automatic rollback or data reset. Restoring a pre-upgrade backup is a separate operator action and can also restore credentials revoked since that backup: review and revoke those devices again before exposing the entry.
37
+ - Working pairings do not need to be recreated. A credential already overwritten in the App cannot be reconstructed by the plugin; pair each affected computer again after updating. A usable legacy row may remain beside a new row at the same Origin. Remove a redundant local row only after confirming the new one works; the upgrade does not automatically delete local rows or revoke their computer-side credentials.
38
+
30
39
  ### Remote components, diagnostics and cleanup
31
40
 
32
41
  - Do not expose the LAN gateway through router port forwarding. Funnel, cpolar, cloudflared, and FRP reach a separate loopback gateway through their selected remote path. The own reverse-proxy provider instead exposes a plugin-owned private HTTP origin restricted by its bind address and allowed source CIDRs; the operator's proxy must provide public HTTPS. Funnel, cpolar, cloudflared, Caddy, or the own proxy terminates public TLS in their respective modes; the 0.4.6 self-signed FRP entry terminates TLS on the computer. DSH pairing, device authentication, CSRF checks, and session revocation remain enforced by the plugin gateway.
@@ -14,7 +14,7 @@ The optional [FRP](https://github.com/fatedier/frp) client is not included in th
14
14
 
15
15
  The optional [cloudflared](https://github.com/cloudflare/cloudflared) client is not included in the npm package or Android App. When a user explicitly chooses cloudflared installation, DSH Mobile downloads the pinned official release asset for the supported host platform (version recorded in `src/cloudflared-component.ts`), verifies its exact size and SHA-256 digest, and stores it only under the user's DSH Mobile data directory. The client is started with automatic updates disabled. Quick tunnels do not require account credentials; named tunnels use an operator-supplied connector token stored in the plugin's private directory. cloudflared is distributed under the Apache License 2.0; use of Cloudflare's quick tunnels remains subject to Cloudflare's [website terms](https://www.cloudflare.com/website-terms/).
16
16
 
17
- The managed Caddy component is not included in the npm package or Android App. Version 0.6.0 has no published trusted pinned component, so installation remains unavailable. The reviewed build uses [Caddy v2.11.6](https://github.com/caddyserver/caddy/blob/v2.11.6/LICENSE), under Apache License 2.0, and [caddy-dns/tencentcloud v0.4.3](https://github.com/caddy-dns/tencentcloud/blob/v0.4.3/LICENSE), under the MIT License. Maintainer build artifacts record embedded dependency versions and licenses; they are not an automatically published or installed binary. Existing user-managed proxies are separate from this optional component.
17
+ The optional managed Caddy component is not included in the npm package or Android App. Since plugin 0.6.9, users on Windows/Linux x64 can explicitly confirm an on-demand download of 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); its source, exact size and SHA-256 are pinned in the plugin. This distribution builds [Caddy v2.11.7](https://github.com/caddyserver/caddy/blob/v2.11.7/LICENSE), under Apache License 2.0, with [caddy-dns/tencentcloud v0.4.3](https://github.com/caddy-dns/tencentcloud/blob/v0.4.3/LICENSE), under the MIT License. The component release supplies each platform's exact embedded dependency manifest, Go build metadata and complete third-party license/notice texts as separate assets. It is a DSH Mobile build, not an upstream Caddy release or a dynamically generated download. Existing user-managed proxies are separate from this optional component.
18
18
 
19
19
  The npm package declares direct runtime dependencies on [Schemastery](https://github.com/shigma/schemastery) `^3.18.1`, [@noble/hashes](https://github.com/paulmillr/noble-hashes) `1.8.0`, [bonjour-service](https://github.com/onlxltd/bonjour-service) `1.4.4`, [qrcode](https://github.com/soldair/node-qrcode) `^1.5.4`, [selfsigned](https://github.com/jfromaniello/selfsigned) `^5.5.0`, and [ws](https://github.com/websockets/ws) `8.22.0`. These packages are distributed under the MIT License; the release checkout's exact transitive versions appear in the attached CycloneDX npm SBOM.
20
20
 
@@ -6,11 +6,13 @@ DeepSeek Harness is the display name of this lightweight, community-maintained A
6
6
 
7
7
  Android is the only supported native target. The iOS client remains an unpublished local experiment and is outside the build, release, and support scope.
8
8
 
9
- The current stable app is **0.6.3** (build 79). The app and npm plugin update independently; plugin web UI or connection fixes do not require reinstalling the APK. Install a new signed release APK for native updates or when the app reports that its version is too old. Older official APKs with the same signer retain pairing during in-place upgrades; a differently signed Debug build cannot overwrite the official app.
9
+ The current stable app is **0.6.4** (build 80). The app and npm plugin update independently; plugin web UI or connection fixes do not require reinstalling the APK. Install a new signed release APK for native updates or when the app reports that its version is too old. Older official APKs with the same signer retain pairing during in-place upgrades; a differently signed Debug build cannot overwrite the official app.
10
10
 
11
- ### Attachment changes in development
11
+ ## 0.6.4 update
12
12
 
13
- Unreleased App code uses the system Photo Picker on Android 13+ when the webpage requests a single supported image MIME filter. Multiple selection follows the system limit; unavailable pickers, older systems, capture requests and filters that cannot be represented exactly use the document picker instead. Document requests start directly, retain MIME and multiple settings, and do not promise a particular manufacturer's gallery. Standard callbacks are bound to the current WebView, Origin and document; obsolete results cannot complete a newer request. These native changes are not in the published 0.6.3 APK, and need a future signed App update.
13
+ Build 80 uses the system Photo Picker on Android 13+ when the webpage requests a single supported image MIME filter. Multiple selection follows the system limit; unavailable pickers, older systems, capture requests and filters that cannot be represented exactly use the document picker instead. Document requests start directly and retain MIME and multiple settings. The App does not promise a particular manufacturer's gallery. Standard callbacks are bound to the current WebView, exact Origin and document; obsolete Activity results cannot complete a newer request. These native changes require App 0.6.4 or later and are released independently from the npm plugin.
14
+
15
+ WebViews with navigation-listener support cancel a pending standard file request before replacing the document and do not open another selector while a document navigation is in progress. Older providers use the available navigation callbacks; if file selection stops opening after changing pages, update WebView or return to the paired-computer list and reopen the page. Clearing App data is unnecessary.
14
16
 
15
17
  ## 0.6.3 update
16
18
 
@@ -93,7 +95,7 @@ Deleting a row removes the App's saved device token and pinned certificate, not
93
95
  | TLS | LAN pins its pairing-key CA privately. The self-signed FRP entry requires a remote CA pin in app 0.4.6 or later. Both accept only an otherwise-untrusted, valid leaf for the exact Origin. Public-CA remote entries use platform trust; every other TLS error is cancelled. |
94
96
  | Origin | Only scheme, normalized host, and port persist. Ordinary paths, queries, and fragments do not. |
95
97
  | Navigation | Same-origin main frames stay inside; user-initiated external HTTPS links open in the system browser. |
96
- | Permissions | File input uses the system document picker without storage permission. Camera permission is requested for QR scanning or photo capture; microphone permission is requested for DSH voice input. |
98
+ | Permissions | Standard file input uses the system Photo Picker or document picker according to Android version and the webpage's request, without storage permission. Camera permission is requested for QR scanning or photo capture; microphone permission is requested for DSH voice input. |
97
99
  | Downloads | Foreground GET from the exact origin only; authentication control paths are never downloads. |
98
100
  | Data | Android Keystore encrypts device records, including tokens, origins and pinned CAs; Web storage stays in the app sandbox. Deleting a device removes its record only; system clear-app-data removes all pairings and Web data. |
99
101
  | Backup | App backup is disabled; TLS private keys and signing keys must remain outside the repository. |
@@ -106,7 +108,7 @@ The authenticated page can call the Android bridge through `dshMobile` extension
106
108
 
107
109
  Available actions include `files.pick`, `camera.capture`, `share`, `clipboard.read`, `clipboard.write`, `notification.notify`, `notification.settings` and `mobile.switch-computer`. DSH keeps its file-attachment action in Add; Mobile adds camera capture there when the current attachment owner accepts images. The separate `files.pick` returns one file, follows the caller's MIME types and returns at most 8 MiB through the bridge; that is not a limit on DSH's file selector. Camera capture requests permission when used, writes a full-resolution JPEG through `FileProvider` and returns a browser `File`.
108
110
 
109
- For ordinary DSH attachments, the App forwards the webpage's multiple-selection and MIME settings to the system document picker and returns all selected items. Use its Images category or an available photo provider to choose pictures; the visible gallery entries depend on the device and installed providers. This path is independent of the extension `files.pick` action. File-selection acceptance on each physical device remains part of the checks described below.
111
+ For ordinary DSH attachments, App 0.6.4 selects the system Photo Picker or document picker as described above, preserves the webpage's MIME and multiple-selection settings, and returns all selected items within the system picker limits. Available galleries and document providers depend on the device. This standard WebView path is independent of the extension `files.pick` action and its Bridge size limit. File-selection acceptance remains specific to the checked device, WebView provider and APK.
110
112
 
111
113
  Task reminders use Host completion events and explicit pending-input cards while the page remains alive. Enable notifications or open system settings from DSH **Settings → General** inside the app. Lock-screen text is generic and tapping opens the app. Plugin 0.6.4 distinguishes full session and turn IDs, including long and non-ASCII IDs; earlier versions can replace notifications when their tags collide. Completion reminders require SSE and have no offline event replay; Cloudflare Quick Tunnels do not support the stream. See [channel limits](../../docs/CLOUDFLARE_TUNNEL.en.md#quick-tunnel-feature-limits).
112
114
 
@@ -135,11 +137,13 @@ Set-Location apps/mobile/android
135
137
  ./gradlew.bat :app:lintDebug :app:testDebugUnitTest :app:assembleDebug -x :app:lintAnalyzeDebugUnitTest -x :app:lintAnalyzeDebugAndroidTest
136
138
  ```
137
139
 
138
- The debug APK is written to `app/build/outputs/apk/debug/app-debug.apk`. GitHub Releases build a signed release APK with a stable signing key stored only in repository secrets; signing keys and passwords never enter the source tree or build artifacts. The current signed release is [Android 0.6.3](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.3), with SHA-256 `167b9447cf5b700b811b6b5279e2935b5aca250e5f1a3b59fa7cf13b1af9e497`.
140
+ The debug APK is written to `app/build/outputs/apk/debug/app-debug.apk`. GitHub Releases build a signed release APK with a stable signing key stored only in repository secrets; signing keys and passwords never enter the source tree or build artifacts. The current signed release is [Android 0.6.4](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.4), with SHA-256 `b28f2e832a8596df2fa1bfbad7dc36eef59d519c9e4875dd2be1ea4713804adf`.
139
141
 
140
142
  ## Acceptance
141
143
 
142
- Shared URL-policy tests cover origin normalization, pairing entry, same-origin navigation and download paths. PJW110 with Android 16 and WebView 151 was used to verify model-menu Back, rotation with draft/reference/image retention, known revocation through checks and restart, and re-pairing the same device. That evidence uses an isolated HTTPS instance over USB, not a public tunnel. A real VPS plus phone end-to-end test of the self-signed FRP entry has not been recorded; other devices, cutouts, font scaling, TLS failures, file input and downloads still require device-specific acceptance.
144
+ Shared URL-policy tests cover origin normalization, pairing entry, same-origin navigation and download paths. Local acceptance of the clean App 0.6.4 / build 80 Debug APK used PJW110 with Android 16 and Google WebView 153.0.8010.36. With the same retained WebView, the real DSH stock input reopened Documents after document replacement, rejected the old selection, and received the exact controlled PNG bytes with a decoded draft preview. A held main-document response also confirmed that selection was refused during navigation and reopened after HTTP 204 retained the old document. No model prompt was submitted. These USB-isolated Debug checks do not establish physical acceptance of the official-signer APK, public tunnels, HyperOS, older providers or other devices.
145
+
146
+ Earlier PJW110 checks with Android 16 and WebView 151 covered model-menu Back, rotation with draft/reference/image retention, known revocation through checks and restart, and re-pairing the same device. Those checks also used an isolated HTTPS instance over USB. A real VPS plus phone end-to-end test of the self-signed FRP entry has not been recorded; cutouts, font scaling, TLS failures, downloads and additional device/provider combinations still require their own acceptance.
143
147
 
144
148
  A 0.5.6 development build used to prepare 0.6.0 additionally verified in-place Debug upgrade with paired data retained, all seven Launcher choices, two isolated computers, explicit order surviving later connections, scanner buttons/double-tap zoom and camera release on this device. Physical pinch, real QR recognition, older-Android fallback and process-death restoration are not represented as completed device checks.
145
149
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.3",
3
- "versionCode": 79,
4
- "releaseTag": "android-v0.6.3"
2
+ "version": "0.6.4",
3
+ "versionCode": 80,
4
+ "releaseTag": "android-v0.6.4"
5
5
  }