dsh-mobile 0.6.2 → 0.6.4

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/CONTRIBUTORS.md +19 -4
  3. package/README.en.md +16 -8
  4. package/README.md +16 -8
  5. package/SECURITY.md +3 -2
  6. package/THIRD_PARTY_NOTICES.md +29 -1
  7. package/apps/mobile/README.md +25 -5
  8. package/apps/mobile/release.json +3 -3
  9. package/cordis.patch.yml +7 -3
  10. package/docs/ATTACH_EXISTING_FRPS.en.md +1 -1
  11. package/docs/ATTACH_EXISTING_FRPS.md +2 -2
  12. package/docs/CADDY_MANAGED.en.md +15 -1
  13. package/docs/CADDY_MANAGED.md +15 -1
  14. package/docs/CLOUDFLARE_TUNNEL.en.md +2 -2
  15. package/docs/CLOUDFLARE_TUNNEL.md +3 -3
  16. package/docs/EXTENSION_WORKERS.en.md +49 -0
  17. package/docs/EXTENSION_WORKERS.md +49 -0
  18. package/docs/MOBILE_COMPOSER_TOOLBAR.en.md +27 -0
  19. package/docs/MOBILE_COMPOSER_TOOLBAR.md +27 -0
  20. package/docs/README.md +2 -0
  21. package/docs/SELF_HOSTED_FRP.en.md +4 -2
  22. package/docs/SELF_HOSTED_FRP.md +4 -2
  23. package/docs/SLOW_CONNECTIONS.en.md +6 -0
  24. package/docs/SLOW_CONNECTIONS.md +6 -0
  25. package/docs/TRUSTED_NETWORKS.en.md +1 -1
  26. package/docs/TRUSTED_NETWORKS.md +1 -1
  27. package/lib/cli.js +140 -19
  28. package/lib/cli.js.map +1 -1
  29. package/lib/client.js +1264 -106
  30. package/lib/client.js.map +1 -1
  31. package/lib/extension-worker-runtime.mjs +1646 -0
  32. package/lib/extension-worker-runtime.mjs.map +1 -0
  33. package/lib/index.d.mts +209 -12
  34. package/lib/index.mjs +2152 -811
  35. package/lib/index.mjs.map +1 -1
  36. package/lib/mobile-layout.js.map +1 -1
  37. package/package.json +17 -6
  38. package/packages/question-fixes/LICENSE +201 -0
  39. package/packages/question-fixes/package.json +9 -2
  40. package/node_modules/dsh-mobile-question-fixes/lib/client.js +0 -78
  41. package/node_modules/dsh-mobile-question-fixes/lib/client.js.map +0 -1
  42. package/node_modules/dsh-mobile-question-fixes/lib/index.mjs +0 -14
  43. package/node_modules/dsh-mobile-question-fixes/lib/index.mjs.map +0 -1
  44. package/node_modules/dsh-mobile-question-fixes/package.json +0 -25
package/CHANGELOG.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.6.4 - 2026-10-12
6
+
7
+ - Release 0.6.4 improves the mobile composer, Windows Desktop startup composition and connection/data reliability. The Android App remains independently versioned; its current candidate is 0.6.3 (build 79), while the public App download remains 0.6.2 (build 78).
8
+ - Integrate the focused composer overflow fix from [PR #200](https://github.com/saya-ch/dsh-mobile/pull/200): public-slot wrappers around compact non-switch buttons reserve the mobile 44px touch target without resizing switches, dialogs, menus, nested controls or wide layouts. The packed real-slot smoke covers the new geometry and activation cases; optional third-party services remain outside this presentation check. Thanks @abworks-dev.
9
+ - Detect the Windows Desktop profile service as well as its later runtime marker before enabling the in-page directory picker, avoiding competing picker providers during early Windows Desktop boot while retaining the portable picker on macOS/Linux. This covers an early-boot composition risk relevant to [#199](https://github.com/saya-ch/dsh-mobile/issues/199); the reported community Desktop 2.0.17 failure and remote timeout still require acceptance in that environment.
10
+ - Preserve custom Caddy sites during VPS deployment and cleanup. Recognize the complete stock file rather than matching a few default-site lines or a legacy comment; other configurations require an explicit manual merge.
11
+ - Persist remote enable/disable settings before changing the running provider, so a failed save retains the confirmed state and can be retried. Repair missing or mismatched FRP leaf keys under the pinned CA, stage certificate/key replacements with rollback, and use the shared pinned downloader for FRP response cleanup.
12
+ - Stop an owned Funnel process and gateway even when its private state directory becomes invalid, keep the failure retryable, and apply the same durable-before-stop rule to Managed Origin reconnects and disables. Reuse quoted extension-script ETags separately from local content digests and retain them across 304 responses.
13
+ - Honor configured Worker activation budgets through public loading and recovery while retaining cancellation. Match root prefix extension routes correctly without widening other path prefixes.
14
+ - Distinguish task notifications using complete session/question IDs and per-turn tags, including long and non-ASCII identifiers. Reuse the existing maintained SHA-256 dependency in the browser bundle; update the development source-map parser to its patched release.
15
+ - Prepare Android App 0.6.3 (build 79): keep authentic expired-CA records readable for per-device repair while TLS still rejects expiry, share a pairing owner across button/IME/scanned submissions, deduplicate slow device probes without consuming all connection capacity, improve dark primary-button contrast, update English/Chinese/Italian TLS recovery guidance, and exclude encrypted data from cloud backup and device transfer. Formal downloads still point to 0.6.2 (build 78).
16
+ - Require administrator approval bypass to be disabled before official Caddy component distribution. Reconcile an occupied npm version with the candidate tarball integrity before continuing publication, and require final cleanup receipts for legacy negative browser checks.
17
+ - Explain browser pairing-code input next to the field in Chinese, English and Italian. Recognize Android App keys locally without submitting them as codes, retain entered values, prevent duplicate one-time submissions, and distinguish invalid/expired codes, rate limits, device limits and connection failures. Thanks @sznyhgm for [#96](https://github.com/saya-ch/dsh-mobile/issues/96).
18
+ - Correct authenticated resource ETag syntax, GET/HEAD weak/list/wildcard matching and 304 metadata. Preserve usable upstream validators across streaming gzip and keep encoding variants distinct. Upstream resources without validators and actual WebView cache reuse remain separate checks; this does not establish a complete fix for [#107](https://github.com/saya-ch/dsh-mobile/issues/107).
19
+ - Report Windows private-file permission failures by SID-query or ACL-apply stage and full wait duration, without logging raw command output, SID arguments or private paths. Hand freshly prepared inactive-provider state to initialization rather than reading and applying its ACL twice. Secure control-state temporary files before replacement and await every startup preparation write before reporting failure. Keep permission-before-use, existing timeout and retry behavior; the reported long startup contention in [#128](https://github.com/saya-ch/dsh-mobile/issues/128) remains under investigation.
20
+ - Add isolated real-DSH transport recovery and cross-client question regression checks, distinguishing healthy HTTP from a ready WebSocket and retaining the existing document and draft. These checks do not establish acceptance of a reporter's public tunnel or original device.
21
+ - Capture redacted module, batch and script-response evidence for browser startup failures, including HTTP-successful scripts that fail during execution or registration. Copy package files in isolated test profiles so another pnpm import cannot change their shared file metadata and trigger a DSH resource revision. Negative checks require the intended fault and completed cleanup; failed evidence capture or persistence cannot count as passing.
22
+ - Release discarded component-download response bodies before returning a rejection or following a validated redirect, and release reader locks after completion or failure. Keep the original validation error when cleanup fails instead of treating it as a retryable transport fault. Pinned sources, size/hash checks and redirect restrictions are unchanged; this does not establish the original cause of [#114](https://github.com/saya-ch/dsh-mobile/issues/114).
23
+ - Close extension response streams when invalid HTTP metadata or a response-header write fails before pipeline ownership. Preserve normal streaming, HEAD and client-disconnection cleanup.
24
+ - Cancel previous Android automatic-recovery ownership when opening LAN, remote or pairing configuration. Late renewal/cookie callbacks and queued retries cannot replace the user's form or take over a newer retry. This native correction requires a future App update; the already published APK is unchanged. Thanks @sznyhgm for [#96](https://github.com/saya-ch/dsh-mobile/issues/96).
25
+ - Plugin and native App releases remain independent. This release does not replace the public Android App download; the 0.6.3 App candidate requires a separate signed Android release.
26
+
27
+ ## 0.6.3 - 2026-10-10
28
+
29
+ - Add opt-in, per-local-extension Worker execution with bounded threads/V8/IPC, cooperative cancellation followed by termination, fair streaming credit and explicit recovery without replay. The default remains in-process; Workers expose a logger-only context and are not a security sandbox. Retain @chintoleung's three original prototype commits from [#189](https://github.com/saya-ch/dsh-mobile/issues/189), with integration and lifecycle corrections. [Guide](docs/EXTENSION_WORKERS.en.md).
30
+ - Integrate @abworks-dev's [PR #192](https://github.com/saya-ch/dsh-mobile/pull/192) with plugin-only compact/overflow corrections. Keep native InputBar ownership, model width observation, original handlers, menus and live activity nodes; Send/Stop remain reachable. This is not the proposed shared upper scrollport, which still requires an upstream parent-toolbar seam. [Layout scope](docs/MOBILE_COMPOSER_TOOLBAR.en.md).
31
+ - Protect Android paired-record writes and legacy migration from unreadable encrypted data; retain old ciphertext rather than treating it as an empty list. Prevent cancelled SDK calls from starting queued Native operations after disposal.
32
+ - Correct audit regressions: preserve third-party HTML/iframe routes, reject unknown raw TLS modes, guard managed parent links and cleanup ownership, retain rollback backups, contain file-log failures and stop unverified authenticated SSH fallback before fingerprint confirmation. Await owned process/cleanup completion and align the guides with actual logging, permissions and independent versioning.
33
+ - Fix fresh installation and upgrades through DSH's plugin manager, including hoisted pnpm profiles. The question-card component remains inside the plugin package and independently switchable, without a separate package installation or user workaround. Thanks @MLYR for [#193](https://github.com/saya-ch/dsh-mobile/issues/193).
34
+ - Follow DSH 0.2.1-alpha.2 typography: mobile General settings retain device-local body size and add collapsed body/code font controls and a reset action. Preferences do not change the computer or other devices; existing mobile font settings are retained. Terminal fonts remain owned by DSH.
35
+ - Add Android App 0.6.2 (build 78), separately from plugin 0.6.3. Keep web content inside the native system-bar, cutout and keyboard area; add native-only page zoom in General settings, with 80–125% scaling and a 100% reset, without reloading the conversation. Older App versions and browsers do not show this control.
36
+ - Add a nonblocking update reminder for WebViews reporting Chromium below 100. Users may continue; unknown engine versions are not treated as obsolete, and each detected build is warned about once. This does not promise full compatibility with unsupported old engines.
37
+ - Improve bounded Windows retries and rollback for managed Caddy preparation while keeping official managed installation disabled. Thanks @abworks-dev for [PR #190](https://github.com/saya-ch/dsh-mobile/pull/190).
38
+ - Hide the duplicate passive pin marker on narrow mobile session lists while retaining pin actions and desktop presentation. Thanks @chintoleung for [PR #191](https://github.com/saya-ch/dsh-mobile/pull/191).
39
+ - Add a repository-local Agent maintenance skill and discovery entrypoint covering compatibility, packaging, runtime/ADB, collaboration and independent releases, with guidance for updating demonstrated reusable lessons.
40
+
5
41
  ## 0.6.2 - 2026-10-08
6
42
 
7
43
  - Supply missing `AbortSignal.throwIfAborted()` and cancellation reasons before DSH starts on older WebViews. Preserve native implementations, cancellation and the first supplied reason, fixing the reported model/provider and other client API failures caused by the missing method. Thanks @luoyangchan for [#187](https://github.com/saya-ch/dsh-mobile/issues/187).
package/CONTRIBUTORS.md CHANGED
@@ -1,8 +1,20 @@
1
1
  # 贡献者 / Contributors
2
2
 
3
- GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按截至 2026-10-08 的实际参与方式感谢社区成员;仓库维护者与自动依赖更新仍可在 GitHub 历史记录中查看。
3
+ GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按截至 2026-10-12 的实际参与方式感谢社区成员;仓库维护者与自动依赖更新仍可在 GitHub 历史记录中查看。
4
4
 
5
- GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-10-08. The repository maintainer and automated dependency updates remain visible in GitHub's history.
5
+ GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-10-12. The repository maintainer and automated dependency updates remain visible in GitHub's history.
6
+
7
+ ## 0.6.4 候选贡献 / Contributions to the 0.6.4 candidate
8
+
9
+ [@abworks-dev](https://github.com/abworks-dev) 的 [#200](https://github.com/saya-ch/dsh-mobile/pull/200) 提供窄屏输入栏包装层与按钮点击区域的尺寸修正及回归测试,已纳入本地候选,尚未合并至默认分支或发布。
10
+
11
+ [@abworks-dev](https://github.com/abworks-dev)'s [#200](https://github.com/saya-ch/dsh-mobile/pull/200) supplies the narrow-screen composer wrapper sizing fix and regression checks. It is included in the local candidate, not yet merged into the default branch or released.
12
+
13
+ ## 0.6.3 代码贡献 / Code contributions in 0.6.3
14
+
15
+ [@abworks-dev](https://github.com/abworks-dev) 的 [#190](https://github.com/saya-ch/dsh-mobile/pull/190)、[#192](https://github.com/saya-ch/dsh-mobile/pull/192),以及 [@chintoleung](https://github.com/chintoleung) 的 [#191](https://github.com/saya-ch/dsh-mobile/pull/191) 和在 [#189](https://github.com/saya-ch/dsh-mobile/issues/189) 提供的三个 Worker 原型提交参与本版,保留原始提交并追加适配与修正。具体范围见 [更新记录](CHANGELOG.md#063---2026-10-10)。
16
+
17
+ [@abworks-dev](https://github.com/abworks-dev)'s [#190](https://github.com/saya-ch/dsh-mobile/pull/190) and [#192](https://github.com/saya-ch/dsh-mobile/pull/192), plus [@chintoleung](https://github.com/chintoleung)'s [#191](https://github.com/saya-ch/dsh-mobile/pull/191) and three Worker prototype commits supplied through [#189](https://github.com/saya-ch/dsh-mobile/issues/189), contribute to this release with original history and maintainer corrections. See the [release scope](CHANGELOG.md#063---2026-10-10).
6
18
 
7
19
  ## 已合并 PR / Merged PRs
8
20
 
@@ -51,13 +63,14 @@ GitHub's Contributors graph counts commits on the default branch; issue reports
51
63
  | 反馈贡献者 / Issue reporter | 提交的问题 / Issues |
52
64
  | --- | --- |
53
65
  | [@1624318455](https://github.com/1624318455) | [#92](https://github.com/saya-ch/dsh-mobile/issues/92) |
66
+ | [@2647954284](https://github.com/2647954284) | [#199](https://github.com/saya-ch/dsh-mobile/issues/199) |
54
67
  | [@abworks-dev](https://github.com/abworks-dev) | [#174](https://github.com/saya-ch/dsh-mobile/issues/174) |
55
68
  | [@Ann-luo](https://github.com/Ann-luo) | [#150](https://github.com/saya-ch/dsh-mobile/issues/150) |
56
69
  | [@azri57806-design](https://github.com/azri57806-design) | [#97](https://github.com/saya-ch/dsh-mobile/issues/97) |
57
70
  | [@BrainZombie](https://github.com/BrainZombie) | [#128](https://github.com/saya-ch/dsh-mobile/issues/128) |
58
71
  | [@CESAEREE](https://github.com/CESAEREE) | [#1](https://github.com/saya-ch/dsh-mobile/issues/1) |
59
72
  | [@CharlesLueng](https://github.com/CharlesLueng) | [#68](https://github.com/saya-ch/dsh-mobile/issues/68) |
60
- | [@chintoleung](https://github.com/chintoleung) | [#103](https://github.com/saya-ch/dsh-mobile/issues/103), [#166](https://github.com/saya-ch/dsh-mobile/issues/166) |
73
+ | [@chintoleung](https://github.com/chintoleung) | [#103](https://github.com/saya-ch/dsh-mobile/issues/103), [#166](https://github.com/saya-ch/dsh-mobile/issues/166), [#189](https://github.com/saya-ch/dsh-mobile/issues/189) |
61
74
  | [@chmzs](https://github.com/chmzs) | [#73](https://github.com/saya-ch/dsh-mobile/issues/73) |
62
75
  | [@gjzbbs](https://github.com/gjzbbs) | [#123](https://github.com/saya-ch/dsh-mobile/issues/123) |
63
76
  | [@hairyf](https://github.com/hairyf) | [#114](https://github.com/saya-ch/dsh-mobile/issues/114) |
@@ -66,10 +79,12 @@ GitHub's Contributors graph counts commits on the default branch; issue reports
66
79
  | [@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) |
67
80
  | [@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) |
68
81
  | [@jillkayat](https://github.com/jillkayat) | [#10](https://github.com/saya-ch/dsh-mobile/issues/10) |
82
+ | [@jonaskilli](https://github.com/jonaskilli) | [#198](https://github.com/saya-ch/dsh-mobile/issues/198) |
69
83
  | [@jueruibo](https://github.com/jueruibo) | [#101](https://github.com/saya-ch/dsh-mobile/issues/101) |
70
84
  | [@KMGTPEZY](https://github.com/KMGTPEZY) | [#95](https://github.com/saya-ch/dsh-mobile/issues/95) |
71
85
  | [@luoyangchan](https://github.com/luoyangchan) | [#187](https://github.com/saya-ch/dsh-mobile/issues/187) |
72
86
  | [@LWping](https://github.com/LWping) | [#94](https://github.com/saya-ch/dsh-mobile/issues/94) |
87
+ | [@MLYR](https://github.com/MLYR) | [#193](https://github.com/saya-ch/dsh-mobile/issues/193) |
73
88
  | [@oliverwan97](https://github.com/oliverwan97) | [#26](https://github.com/saya-ch/dsh-mobile/issues/26) |
74
89
  | [@optttt](https://github.com/optttt) | [#111](https://github.com/saya-ch/dsh-mobile/issues/111) |
75
90
  | [@qjjer](https://github.com/qjjer) | [#156](https://github.com/saya-ch/dsh-mobile/issues/156) |
@@ -77,7 +92,7 @@ GitHub's Contributors graph counts commits on the default branch; issue reports
77
92
  | [@reducm](https://github.com/reducm) | [#127](https://github.com/saya-ch/dsh-mobile/issues/127) |
78
93
  | [@rgshendong](https://github.com/rgshendong) | [#87](https://github.com/saya-ch/dsh-mobile/issues/87) |
79
94
  | [@RonaldinhoL](https://github.com/RonaldinhoL) | [#89](https://github.com/saya-ch/dsh-mobile/issues/89) |
80
- | [@rushpixy](https://github.com/rushpixy) | [#165](https://github.com/saya-ch/dsh-mobile/issues/165) |
95
+ | [@rushpixy](https://github.com/rushpixy) | [#165](https://github.com/saya-ch/dsh-mobile/issues/165), [#194](https://github.com/saya-ch/dsh-mobile/issues/194) |
81
96
  | [@sanmaoAI1432](https://github.com/sanmaoAI1432) | [#169](https://github.com/saya-ch/dsh-mobile/issues/169) |
82
97
  | [@shengyvself](https://github.com/shengyvself) | [#13](https://github.com/saya-ch/dsh-mobile/issues/13), [#14](https://github.com/saya-ch/dsh-mobile/issues/14) |
83
98
  | [@snailium](https://github.com/snailium) | [#144](https://github.com/saya-ch/dsh-mobile/issues/144) |
package/README.en.md CHANGED
@@ -31,14 +31,14 @@
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.2**. Improve loading and scrolling on older WebViews, with independent plugin and app updates. [Release notes](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.2).
34
+ > **Current stable release: 0.6.4**. Improve narrow-screen composer hit targets, Windows Desktop startup composition, plugin installation, and connection/data reliability while retaining optional extension Workers. [Changelog](CHANGELOG.md) · [Release downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.4).
35
35
  >
36
- > **Upgrade reminder**: the plugin and Android app update independently. Web UI and connection fixes usually require only a plugin update; update the app for native changes or when it reports that its version is too old. [Compatibility notes](#compatibility).
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/v0.6.1/dsh-mobile-android-v0.6.1.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/v0.6.1/dsh-mobile-android-v0.6.1.apk"><strong>Download Android app 0.6.1</strong></a><br>
41
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.1">Release notes and checksums</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.2/dsh-mobile-android-v0.6.2.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.2/dsh-mobile-android-v0.6.2.apk"><strong>Download Android app 0.6.2</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.2">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.
@@ -68,7 +68,7 @@ Install the plugin on the computer, then pair the Android app or a mobile browse
68
68
 
69
69
  Install and enable `dsh-mobile` from the app's **Plugins** page, then open **Mobile Access** to configure LAN or a remote channel. The app manages its Desktop profile; the `--profile web` commands below do not apply to it.
70
70
 
71
- After installing or updating, quit Desktop from the application menu and reopen it. If it reports `dsh-mobile-question-fixes: failed to import`, complete this restart so Desktop reads the bundled component again. You do not need to clear sessions or pairing data.
71
+ After installing or updating, quit Desktop from the application menu and reopen it without clearing sessions or pairing data. If it still reports `dsh-mobile-question-fixes: failed to import`, check the installation log; a component-resolution failure may not be fixed by restarting alone.
72
72
 
73
73
  ### DSH Web
74
74
 
@@ -142,6 +142,8 @@ The app is optional: select **Copy pairing link** and open it in a mobile browse
142
142
 
143
143
  Browser pairing and reauthentication pages use the browser's `Accept-Language` to show Simplified Chinese, English, or Italian. Android screens follow the system language, while the DSH plugin control panel follows the language selected by DSH.
144
144
 
145
+ For manual browser pairing, enter the 43-character pairing code shown on the computer. Keys starting with `dsh1.` or `dsh2.` belong in the Android app, not the browser field. Prefer the pairing link copied from the computer, which fills the code automatically; generate a new link when it expires.
146
+
145
147
  ### Remote access
146
148
 
147
149
  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.
@@ -174,7 +176,7 @@ If the page opens but stays on “Reconnecting,” distinguish WebSocket upgrade
174
176
  After selecting the channel in the panel:
175
177
  - **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.
176
178
  - **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.
177
- - **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, and the plugin does not overwrite Caddy configuration it does not manage. 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.
179
+ - **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.
178
180
  - **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).
179
181
  - **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.
180
182
  - **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).
@@ -216,6 +218,8 @@ Extension manifests, scripts, styles, and assets are revisioned. When the plugin
216
218
 
217
219
  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.
218
220
 
221
+ The 0.6.3 release adds optional [Worker execution](docs/EXTENSION_WORKERS.en.md) for trusted local JavaScript hosts. It is disabled by default, selectable by extension, and recovers explicitly without replaying interrupted actions. It is not a permission sandbox and does not require a matching App version.
222
+
219
223
  <sub>You can even use an extension to connect to SillyTavern running on the same computer, give it a lightweight mobile frontend, and open it from the same app.</sub>
220
224
 
221
225
  > `host.mjs` has the same privileges as a local program. Create and run only computer-side extensions that you understand and trust.
@@ -359,6 +363,7 @@ See [SECURITY.md](SECURITY.md).
359
363
  - **The error contains `profile reload requires the root Include entry`**: this error occurs while DSH reloads the profile. [Issue #132](https://github.com/saya-ch/dsh-mobile/issues/132) reports it after two copies of `dsh-app-boot` were loaded, but the message alone does not establish that cause. Compare the versions and installation paths used by the running DSH command and the active profile; keep the configuration and follow the [official DSH documentation](https://deepseek-harness.github.io/deepseek-harness/) to repair the dependencies. If it still fails, report the versions, module paths, and full sanitized error upstream.
360
364
  - **The settings error contains `EACCES`, `EPERM`, or a lock-file failure**: inspect the reported file's permissions and any file-operation tools injected into the launch environment. Lock cleanup can fail after a write, so check what was actually saved.
361
365
  - **The phone shows another plugin’s pairing-code page**: `dsh-remote-web-ui` and DSH Mobile have separate remote channels and pairing codes; they cannot be mixed. If DSH Mobile diagnostics warn about a competing remote plugin, turn off that plugin’s remote access on the computer, refresh, and scan the current DSH Mobile QR code. Merely installing the other plugin without enabling its remote channel does not trigger this warning.
366
+ - **Windows initialization waits on permissions or fails**: `sid-query` identifies the current-account SID lookup and `acl-apply` identifies private-file permission setup; failures also report the full wait duration for that stage. Do not disable permission checks or make sensitive files readable by everyone. Share the redacted stage, duration, error code and DSH version for diagnosis. These diagnostics do not establish a fix for the startup-contention problem in [#128](https://github.com/saya-ch/dsh-mobile/issues/128).
362
367
  - **Remote diagnostics say “reachable through the computer's proxy”**: the check tries a direct request first, then an HTTP proxy from the DSH process environment only if direct access fails; `NO_PROXY` may exclude the target. This proves only that the computer completed an HTTPS probe through the proxy, not that the phone or actual tunnel can connect. Test from the phone's mobile network. If both paths fail, diagnostics continue to report the endpoint unreachable instead of treating an offline route as ready.
363
368
  - **LAN access stops after switching networks**: if the log reports `saved LAN interface "XXX" is not connected`, the saved adapter is unavailable. DSH keeps running while Mobile Access stays dormant and retries when the adapter returns. If you have moved to a different adapter, configure LAN again or re-run `setup`. If mobile access is not needed, disable `mobile-access` in `cordis.patch.yml`.
364
369
 
@@ -385,6 +390,9 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
385
390
  | --- | --- |
386
391
  | `0.5.5` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2` (npm installation, isolated pairing, mobile-page boot, and WebSocket Workspace baseline) |
387
392
  | `0.6.0` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1` and `0.2.0-rc.2` (packed installation, pairing, mobile-page boot and WebSocket Workspace reads); additional checks cover the mobile composer, module settings and component loading after a normal official Desktop restart |
393
+ | `0.6.2` | Packed legacy-WebView boot, touch scrolling and missing-API/viewport negative controls passed on `0.2.0-rc.2`, with release CI passing. The reporter's physical old devices in #187 were not claimed as accepted |
394
+ | `0.6.3` | `0.2.0-rc.2` and `0.2.1-alpha.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additional checks cover the composer, settings and extension Worker timeout, streaming and explicit recovery |
395
+ | `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 |
388
396
 
389
397
  <details>
390
398
  <summary>Historical version checks</summary>
@@ -415,7 +423,7 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
415
423
 
416
424
  Existing apps (0.3.3 and later) do not need re-pairing. cpolar users should use app 0.3.15 or later because earlier apps may time out before a slow first load over the free route finishes; earlier apps also use a different status-bar strategy. The 0.4.0 app adds the multi-device list, startup behavior, and computer-side revocation status; older apps continue to connect to their saved single device. App 0.1.3 or earlier requires reinstalling and pairing again.
417
425
 
418
- The current stable Android app is 0.6.1 (build 77), retaining 0.6.0's native features and pairing/renewal protocol without requiring re-pairing. Plugin and app version numbers do not need to match; connections check protocol and minimum-version requirements. Features with additional native requirements state the app version they need.
426
+ The current stable Android app is 0.6.2 (build 78), adding page zoom and improving system-area handling and encrypted-record reliability. Package identity, signing and the pairing/renewal protocol remain compatible without requiring re-pairing. Plugin and app version numbers do not need to match; connections check protocol and minimum-version requirements. Features with additional native requirements state the app version they need.
419
427
 
420
428
  GitHub Release APKs use a stable signing certificate, so an older official APK with the same signer can be upgraded in place while retaining pairings. A locally built Debug APK with a different signer cannot be overwritten by the official APK; plan to pair again when switching between them.
421
429
 
package/README.md CHANGED
@@ -31,14 +31,14 @@
31
31
 
32
32
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
33
33
  >
34
- > **当前正式版本:0.6.2**。补齐旧 WebView 的加载与滚动兼容,插件与 App 独立更新。[更新记录](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.2)。
34
+ > **当前正式版本:0.6.4**。改善窄屏输入栏触摸区域、Windows Desktop 启动适配、插件安装与连接数据可靠性,并保留可选扩展 Worker 模式。[更新记录](CHANGELOG.md) · [版本下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.4)。
35
35
  >
36
- > **升级提醒**:插件与 Android App 独立更新。网页与连接修复通常只需更新插件;涉及原生功能或提示 App 版本过旧时,再更新 App。[兼容说明](#兼容性)。
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/v0.6.1/dsh-mobile-android-v0.6.1.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/v0.6.1/dsh-mobile-android-v0.6.1.apk"><strong>下载 Android App 0.6.1</strong></a><br>
41
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.1">版本说明与校验文件</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.2/dsh-mobile-android-v0.6.2.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.2/dsh-mobile-android-v0.6.2.apk"><strong>下载 Android App 0.6.2</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.2">版本说明与校验文件</a></sub>
42
42
  </p>
43
43
 
44
44
  DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP 或自有反向代理远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
@@ -68,7 +68,7 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
68
68
 
69
69
  在应用的 **插件** 页面安装并启用 `dsh-mobile`,再打开 **移动访问** 配置局域网或远程通道。Desktop 的 profile 由应用管理,不适用下面的 `--profile web` 命令。
70
70
 
71
- 安装或更新后,请从应用菜单正常退出并重新打开 Desktop。若提示 `dsh-mobile-question-fixes: failed to import`,先完成这次重启,让 Desktop 重新读取附带组件;无需清除会话或配对数据。
71
+ 安装或更新后,请从应用菜单正常退出并重新打开 Desktop,无需清除会话或配对数据。若仍提示 `dsh-mobile-question-fixes: failed to import`,请检查安装日志;这也可能是组件解析问题,单纯重启不一定能解决。
72
72
 
73
73
  ### DSH Web
74
74
 
@@ -142,6 +142,8 @@ dsh plugin --profile web add dshmarket
142
142
 
143
143
  手机浏览器中的配对和重新连接页面会按浏览器的 `Accept-Language` 显示简体中文、英文或意大利文;Android App 则跟随系统语言。DSH 内的插件控制面板继续跟随 DSH 当前语言。
144
144
 
145
+ 浏览器手动配对时填写电脑端显示的 43 位配对码;以 `dsh1.` 或 `dsh2.` 开头的是 Android App 密钥,不要填入浏览器配对框。优先打开电脑端复制的配对链接,它会自动填写配对码;过期后在电脑端重新生成。
146
+
145
147
  ### 远程访问
146
148
 
147
149
  适合手机离开电脑所在网络后使用。远程访问默认关闭,手机不需要另外安装 Tailscale、cpolar、cloudflared 或 FRP。
@@ -174,7 +176,7 @@ dsh plugin --profile web add dshmarket
174
176
  在面板选择对应通道后:
175
177
  - **Tailscale Funnel**:点击 **启用远程访问**,在打开的官方页面完成一次 Tailscale 登录;按面板提示继续允许 Funnel,然后返回 DSH 等待连接就绪。
176
178
  - **cpolar**:点击 **安装官方组件**,登录 cpolar 控制台取得 Authtoken,粘贴后点击 **保存并连接**。组件只会在确认后下载到插件私有目录;免费临时地址可能在 DSH 或 cpolar 重启后变化。
177
- - **自建 FRP(高级)**:已有 VPS 时,展开 **自建连接**,填写 frps 信息和公开 HTTPS 域名或真实公网 IPv4。可以复制受限的 frps + Caddy 模板手动部署,也可以在 Ubuntu/Debian + systemd 上用 SSH 密钥一键部署;不支持密码登录,也不会覆盖非 DSH Mobile 管理的 Caddy 配置。部署或清理前须到 VPS 控制台核对主机指纹。本机 `frpc` 按需下载校验,VPS 需单独清理。需要 Android App 0.3.3 或更新版本;证书、端口和操作步骤见 [自建 FRP 使用指南](docs/SELF_HOSTED_FRP.md)。
179
+ - **自建 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)。
178
180
  - **自有反向代理**:展开 **自建连接 → 自有反向代理**,填写公网 HTTPS 地址(支持自定义端口)、私有监听 IPv4、独立 HTTP 后端端口(默认 3444)和代理来源 CIDR,再点击 **保存并启动后端**。适合已有 Lucky/Nginx/Caddy 的用户,无需隧道组件;需要 Android App 0.4.0 或更高版本。详见 [自有反向代理指南](docs/SELF_HOSTED_ORIGIN.md)。
179
181
  - **cloudflared 快速隧道**:点击 **安装官方组件**,插件在确认后从官方发布页下载固定版本到插件私有目录,随后自动申请一个临时公网地址(quick tunnel),**无需注册或登录**。适合不想注册账号的用户;quick tunnel 地址每次重连都会变化,官方定位为测试用途、有限流且无可用性保证,请勿用于必须长期可达的生产访问,只适合临时或验证场景。
180
182
  - **cloudflared 命名隧道**:已有 Cloudflare 账号和域名时,把隧道类型切到 **命名隧道**,填入连接器令牌、公网域名与本机转发端口,即可获得重启后不变的固定地址(令牌只存私有目录、只经环境变量传给 cloudflared)。步骤见 [Cloudflare 命名隧道](docs/CLOUDFLARE_TUNNEL.md)。
@@ -216,6 +218,8 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
216
218
 
217
219
  扩展动作的 `input` 可以直接使用 `api.schema.object(...)` 等 Schemastery schema,也可以使用带 `parse(value)` 的适配器;手机端 `api.host.invoke()` 会按 JSON 请求发送,输入会在电脑端动作执行前完成校验和规范化。
218
220
 
221
+ 0.6.3 新增可选的 [Worker 执行模式](docs/EXTENSION_WORKERS.md),用于约束可信本地扩展的 JavaScript 阻塞;默认关闭,按扩展选择,故障后显式恢复,不自动重放操作。这不是权限沙箱,也不要求 App 同步版本。
222
+
219
223
  <sub>你甚至可以通过扩展连接电脑上运行的酒馆,并从同一 App 打开它的简易移动前端。</sub>
220
224
 
221
225
  > `host.mjs` 与本机程序拥有相同权限;仅创建和运行你理解并信任的电脑端扩展。
@@ -360,6 +364,7 @@ flowchart LR
360
364
  - **错误包含 `profile reload requires the root Include entry`**:该错误发生在 DSH 重载 profile 时。[Issue #132](https://github.com/saya-ch/dsh-mobile/issues/132) 报告过加载两份 `dsh-app-boot` 导致此错误,但单凭提示不能确认原因。核对实际运行的 DSH 命令与当前 profile 的版本和安装路径,保留配置并按 [DSH 官方文档](https://deepseek-harness.github.io/deepseek-harness/)修复依赖;仍失败时将版本、模块路径及脱敏后的完整错误提交上游。
361
365
  - **设置错误包含 `EACCES`、`EPERM` 或锁文件操作失败**:检查报错文件的权限及启动环境注入的文件操作工具。锁清理失败也可能发生在写入之后,先核对实际保存结果。
362
366
  - **手机出现另一插件的“输入配对码”页面**:`dsh-remote-web-ui` 与 DSH Mobile 各有独立的远程通道和配对码,不能交叉使用。若电脑端连接诊断提示“第三方远程插件”,先关闭该插件的远程访问并刷新,再扫描 DSH Mobile 当前二维码。仅安装该插件而未启用它的远程接管,不会触发这条诊断。
367
+ - **Windows 初始化停在权限处理或失败**:日志中的 `sid-query` 表示查询当前账户 SID,`acl-apply` 表示应用私有文件权限,错误同时记录该阶段的完整等待耗时。不要关闭权限检查或把敏感文件改为所有人可读;提供脱敏后的阶段、耗时、错误码和 DSH 版本以继续定位。分阶段诊断不代表 [#128](https://github.com/saya-ch/dsh-mobile/issues/128) 的启动争抢问题已经解决。
363
368
  - **远程诊断显示“电脑经代理可访问”**:诊断先直连,失败后才尝试 DSH 进程环境变量中的 HTTP 代理;`NO_PROXY` 可排除目标。此结果只说明电脑经代理完成 HTTPS 探测,不代表手机或实际隧道可用。请用手机流量实际连接;若直连和代理都失败,报告仍为不可达,不会把离线误报为就绪。
364
369
  - **切换网络后局域网访问不可用**:如果日志提示 `saved LAN interface "XXX" is not connected`,表示保存的网卡当前未连接。DSH 会继续运行,移动访问暂时休眠,原网卡恢复后会自动重试;若已改用新网卡,请重新完成局域网配置或重跑 `setup`。暂时不用移动访问时,可以在 `cordis.patch.yml` 中禁用 `mobile-access`。
365
370
 
@@ -386,6 +391,9 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
386
391
  | ----------------------------------------- | -------------------------------------------------------------- |
387
392
  | `0.5.5` | `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`(npm 打包安装、隔离配对、移动页面启动及 WebSocket 工作区读取) |
388
393
  | `0.6.0` | `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`(打包安装、配对、移动页面启动与 WebSocket 工作区读取);另验证移动输入栏、模块设置及官方 Desktop 正常重启后的组件加载 |
394
+ | `0.6.2` | `0.2.0-rc.2` 的打包旧 WebView 启动、触屏滚动与缺失 API/视口负对照通过;发布 CI 通过。未将 #187 报告者的实际旧设备写成已验收 |
395
+ | `0.6.3` | `0.2.0-rc.2`、`0.2.1-alpha.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证输入栏、设置与扩展 Worker 的超时、流式传输和显式恢复 |
396
+ | `0.6.4` | `0.2.0-rc.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证 72 组真实公共插槽输入栏布局、Windows Desktop 目录选择器组合及跨平台回归。社区 Desktop 2.0.17 的原报告远程超时仍未宣称验收 |
389
397
 
390
398
  <details>
391
399
  <summary>历史版本验证记录</summary>
@@ -416,7 +424,7 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
416
424
 
417
425
  现有 App(0.3.3 及更新)无需重新配对;cpolar 用户应使用 0.3.15 或更新 App,较早版本可能在免费线路的慢速首次加载完成前超时;更早的 App 还使用不同的状态栏策略。App 0.4.0 才支持多设备列表、启动行为设置和电脑端撤销状态同步;旧版 App 仍可连接已保存的单台设备。App 0.1.3 及更早版本需卸载重装并重新配对。
418
426
 
419
- Android App 当前正式版为 0.6.1(build 77),原生功能与配对、续期协议延续 0.6.0,已有配对无需重建。插件和 App 的版本号不要求相同;连接按协议及最低版本要求检查,具体原生功能另有要求时会说明所需 App 版本。
427
+ Android App 当前正式版为 0.6.2(build 78),新增页面缩放,改善系统区域处理与加密设备记录的可靠性;包名、签名及配对/续期协议保持兼容,已有配对无需重建。插件和 App 的版本号不要求相同;连接按协议及最低版本要求检查,具体原生功能另有要求时会说明所需 App 版本。
420
428
 
421
429
  GitHub Release 的正式 APK 使用固定签名,可从同一签名的旧正式版原位升级并保留配对。自行构建的 Debug APK 若使用不同签名,不能直接覆盖安装正式版;切换前请准备重新配对。
422
430
 
package/SECURITY.md CHANGED
@@ -45,8 +45,9 @@ The maintainer will acknowledge a complete report within seven days. Publication
45
45
  - Android stores the paired-device list as an encrypted record. Removing a local row erases its local credential but does not revoke the phone at the computer; use the computer-side device controls to revoke access. A computer-side revocation invalidates the token even if the App retains the row's name for re-pairing. Network timeouts are not evidence of revocation.
46
46
  - Android grants WebView microphone access only for an audio-only request from the current paired HTTPS Origin, after Android's `RECORD_AUDIO` permission is granted. Other WebView resources and Origins remain denied. Client plugins within the authenticated page share that Origin and can invoke page APIs; install only trusted plugins before granting microphone access.
47
47
  - Treat `mobile.js` as application code with the paired page's same-origin authority. Restrict write access to trusted host-side DSH sessions and review generated API calls or browser-permission use.
48
- - Treat every extension `host.mjs` as a local program with the desktop user's Node.js privileges. It is never sandboxed and is not editable through the mobile gateway; only place code there that you trust.
49
- - Extension Actions and Routes receive filtered request data, a device identifier, and an abort signal. They cannot set proxy security headers or access the gateway's cookies, device tokens, CSRF tokens, or internal request headers.
48
+ - Treat every extension `host.mjs` as a local program with the desktop user's Node.js privileges. The extension/Native Bridge API provides no source-upload or editing endpoint, but a paired DSH operator can still use ordinary DSH tools or `/mobile` to edit files. Only run trusted code.
49
+ - Extension Actions and Routes receive filtered request data, a device identifier, and an abort signal; their provided request fields omit gateway credential/internal headers, and the gateway filters returned headers. These are API restrictions, not an OS sandbox preventing trusted Node.js code from accessing local data or networks.
50
+ - Optional local Worker execution contains synchronous JavaScript blocking without changing that trust model. It has thread, transport and V8 limits and explicit recovery, but native crashes/all native allocations and completed side effects are not isolated or rolled back. See the [Worker guide](docs/EXTENSION_WORKERS.en.md).
50
51
  ### Framed content and browser policy
51
52
 
52
53
  - Proxied GUI responses allow HTTP iframe sources for compatibility with community surfaces. HTTP content is unauthenticated and unencrypted; Android still blocks mixed HTTP content inside HTTPS pages, and browsers may block it too. Prefer HTTPS and do not treat a gateway framing allowance as a transport-security guarantee.
@@ -16,10 +16,38 @@ The optional [cloudflared](https://github.com/cloudflare/cloudflared) client is
16
16
 
17
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.
18
18
 
19
- The npm package declares direct runtime dependencies on [Schemastery](https://github.com/shigma/schemastery) `^3.18.1`, [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.
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
 
21
21
  The Android App runtime contains [Kotlin standard library](https://github.com/JetBrains/kotlin) `2.1.0`, [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) `1.6.4`, [JetBrains annotations](https://github.com/JetBrains/java-annotations) `13.0`, [AndroidX Core](https://developer.android.com/jetpack/androidx/releases/core) `1.15.0`, [AndroidX WebKit](https://developer.android.com/jetpack/androidx/releases/webkit) `1.17.1`, their AndroidX transitive components, [Guava listenablefuture](https://github.com/google/guava) `1.0`, and [ZXing Core](https://github.com/zxing/zxing) `3.5.4`. These runtime libraries are distributed under the Apache License 2.0; the exact resolved tree is attached to each release as `dsh-mobile-android-v<version>-dependencies.txt`.
22
22
 
23
+ ## Notification identity hashing
24
+
25
+ The client bundle includes the SHA-256 implementation from @noble/hashes to derive bounded notification tags from complete IDs. Its MIT license is included below:
26
+
27
+ ```text
28
+ The MIT License (MIT)
29
+
30
+ Copyright (c) 2022 Paul Miller (https://paulmillr.com)
31
+
32
+ Permission is hereby granted, free of charge, to any person obtaining a copy
33
+ of this software and associated documentation files (the “Software”), to deal
34
+ in the Software without restriction, including without limitation the rights
35
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
+ copies of the Software, and to permit persons to whom the Software is
37
+ furnished to do so, subject to the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be included in
40
+ all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48
+ THE SOFTWARE.
49
+ ```
50
+
23
51
  ## core-js browser compatibility bundle
24
52
 
25
53
  The standalone `lib/mobile-compat.js` bundles selected Iterator and `Promise.withResolvers` modules from [core-js](https://github.com/zloirock/core-js) `^3.50.0` (exact version recorded in `package-lock.json`). It is built into the npm package; browsers do not download a polyfill from a CDN. core-js is distributed under the following MIT License:
@@ -6,7 +6,19 @@ 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.1** (build 77). 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.2** (build 78). 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
+
11
+ ## 0.6.3 candidate (unreleased)
12
+
13
+ Build 79 adds per-computer recovery guidance, readable expired-CA records, duplicate-pairing protection and deduplicated status checks that leave capacity for an explicit connection. TLS still refuses expired certificates. It also improves dark-mode primary buttons and explicitly excludes encrypted pairings and WebView sessions from cloud backup and device transfer. The earlier automatic-recovery ownership corrections are included in this candidate. These native changes require a new App; the download above remains the published 0.6.2 APK. See the [0.6.4 release notes](../../CHANGELOG.md#064---2026-10-12) for the independent App candidate status.
14
+
15
+ ## 0.6.2 update
16
+
17
+ Build 78 keeps web content clear of system navigation, display cutouts and the keyboard, and adds **Settings → General → Page zoom** (80–125%, reset to 100%). Zoom is saved in this App, independently from the per-address mobile font settings, and does not reload the current conversation. Its settings entry requires plugin 0.6.3 or later; older Apps and browsers do not show an inactive control.
18
+
19
+ WebViews reporting Chromium below 100 receive a nonblocking update reminder once per detected build. You may continue, but an obsolete WebView can still lack APIs required by DSH. Use the official WebView/Chrome update route available on your device; an unknown engine version is not treated as obsolete.
20
+
21
+ This release also protects paired records and legacy migration when encrypted data is temporarily unreadable: it does not treat failed reads as an empty list or replace existing credentials. Storage errors are reported without automatically clearing pairings.
10
22
 
11
23
  ## 0.6.1 update
12
24
 
@@ -28,7 +40,7 @@ These native features require app 0.6.0 or later. See the [release notes](../../
28
40
  3. With no paired computers, choose **Local network** or **Remote access**. For LAN, create a pairing key or link under **Mobile Access → Local network**. For remote access, configure a provider and generate its pairing QR code. Scan the corresponding QR code or paste its link in the app.
29
41
  4. Name the computer after pairing. The app stores each LAN or remote pairing as a device record: LAN pins its private CA; ordinary remote paths use platform-trusted public HTTPS certificates; the self-signed FRP entry pins a remote CA. No provider app is needed on the phone.
30
42
 
31
- The **Paired computers** list shows each computer's name, connection type, address, reachability and last connection. Tap a row to connect; long-press or use its **More** button to connect, rename, check, re-pair or delete the local record. The list's settings offer **Open DSH directly** (the default, using the last-used eligible computer even when several are paired) and **Show device list**. In the app's DSH page, **Settings → General → Switch computer** returns to the list. Existing LAN and remote credentials migrate without re-pairing. A revoked computer remains listed for re-pairing or deletion; temporary unreachability is not treated as revocation.
43
+ The **Paired computers** list shows each computer's name, connection type, address, reachability and last connection. Tap a row to connect; long-press or use its **More** button to connect, rename, check or delete the local record. Revoked, expired or address-changed rows offer **Re-pair** instead of Connect. To use a new pairing link for another row, choose **Add computer** and the appropriate connection mode; re-pairing the same installation in the same mode keeps its name. The list's settings offer **Open DSH directly** (the default, using the last-used eligible computer even when several are paired) and **Show device list**. In the app's DSH page, **Settings → General → Switch computer** returns to the list. Existing LAN and remote credentials migrate without re-pairing. Temporary unreachability is not treated as revocation.
32
44
 
33
45
  Startup options are under the list's **Settings → Startup behavior**. Deleting a local device does not revoke its authorization on the computer; use the computer's Mobile Access device controls for revocation.
34
46
 
@@ -42,6 +54,8 @@ After the first pairing, the app encrypts its device records, including revocabl
42
54
 
43
55
  Before pairing, the app reads separate version metadata to distinguish an outdated app, an outdated plugin, and an unsupported protocol. A legacy plugin without that endpoint continues through the original flow. When direct launch is selected, the app attempts the saved connection within a bounded recovery budget and returns to the device list if it cannot reconnect. Automatic retries run only for transient network or provider failures. Native app screens automatically follow the Android system locale in Simplified Chinese, English, or Italian without a separate language switch. Plugin-owned UI inside the WebView follows DSH's selected locale. DSH does not currently expose Italian, but the dictionaries are ready to activate without another plugin change when it does.
44
56
 
57
+ If the initial trusted-connection screen remains open for 12 seconds, **View device list** appears without needing a server response. Retry is also available when the screen is bound to a saved computer. From the list, retry a connection, delete just its local record or use **Add computer** with a fresh pairing link; clearing all App data is unnecessary. The correction that prevents old recovery tasks from replacing manual configuration is recorded in the [0.6.4 release notes](../../CHANGELOG.md#064---2026-10-12), but is not part of the stable APK above.
58
+
45
59
  When automatic recovery renews a Session, the app keeps the existing DSH page if its interface is still mounted. A page that did not finish starting or whose renderer stopped must be reopened; unsaved in-page state cannot be recovered in that case.
46
60
 
47
61
  The app keeps the live WebView when rotating, resizing the window or changing keyboard availability, preserving the page's scroll position, references and unsent images. It requests new layout and Insets without reloading. Android still recreates the Activity for language, font-scale or system-theme changes; process termination and renderer failure can also discard unpersisted page state. This follows the [Android WebView state-management guidance](https://developer.android.com/develop/adaptive-apps/cookbook/webview-state).
@@ -65,6 +79,8 @@ On WebView 151 or later, the app gives its own HTTP cache a 64 MiB minimum quota
65
79
 
66
80
  To remove one computer, delete its row from the device list. A full reset uses Android system app information → clear app data (labels vary by system). It deletes all pairings, cookies, cache and Web storage and requires pairing again; do not use it as the first response to an ordinary reconnection failure.
67
81
 
82
+ Deleting a row removes the App's saved device token and pinned certificate, not computer-side authorization. WebView's short-lived site cookies are separate; revoke the device on the computer when access must end immediately. A full App reset clears all sites, so do not use it to remove only one computer.
83
+
68
84
  ## Security properties
69
85
 
70
86
  | Control | Android behavior |
@@ -84,16 +100,20 @@ The network security configuration does not trust user-installed CAs. For LAN, t
84
100
 
85
101
  The authenticated page can call the Android bridge through `dshMobile` extensions. It uses an `androidx.webkit` WebMessage listener, checks the exact configured top-level origin and `isMainFrame` on every message, and never uses `addJavascriptInterface`. Inbound messages are capped at 1 MiB, clipboard text at 256 KiB, binary results at 8 MiB, and replies at 12 MiB. The bridge does not expose cookies, device tokens, pairing keys, CA private keys, or arbitrary Android APIs.
86
102
 
87
- 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` 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`.
103
+ 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`.
88
104
 
89
- 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, different tasks do not replace each other and tapping opens the app. 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).
105
+ 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.
106
+
107
+ 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. The unreleased plugin correction distinguishes full session and turn IDs, including long and non-ASCII IDs; the currently published plugin 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).
90
108
 
91
109
  Only one file-selection or camera interaction runs at a time, with a five-minute deadline. Cancellation, WebView destruction, timeout and stale-session results are cleaned up or rejected. Browsers use corresponding Web APIs and return `unsupported` when unavailable.
92
110
 
93
- From 0.4.7, the app uses plain Enter for a new draft line only when an inset-backed on-screen keyboard is visible, Android reports no hardware keyboard, and an active session composer is focused. The Send button still submits a multiline draft. Floating keyboards, unknown state, older apps, and mobile browsers retain DSH's original Enter behavior; physical keyboards can still use Shift+Enter for a line break.
111
+ From App 0.4.7, its native keyboard adapter uses plain Enter for a new draft line when an inset-backed on-screen keyboard is visible, Android reports no hardware keyboard, and an active session composer is focused. The Send button still submits a multiline draft. Floating keyboards, unknown state and older Apps do not use this native rule; the plugin's touch-browser rule below can still apply. Physical keyboards can use Shift+Enter for a line break.
94
112
 
95
113
  From 0.6.0, the main composer in touch-primary browsers uses Enter to add a line to a nonempty draft and does nothing for an empty draft. DSH retains menus, composition and modified shortcuts. An external keyboard on a touch-primary browser uses that same rule; a non-touch desktop is unchanged. General settings offers a mobile font size of 12–32px, default 16px, saved for the current address only; editable inputs retain a 16px minimum.
96
114
 
115
+ Plugin 0.6.3 adds **More font settings** for body/code fonts, with **Restore defaults**. These are webpage preferences for the current address, not computer-wide settings; they do not require the new APK. Terminal fonts remain controlled by DSH. **Page zoom** is a separate native control described in the 0.6.2 update above.
116
+
97
117
  DSH records through `getUserMedia` and sends audio to the configured computer-side DSH speech provider for transcription, not browser-native SpeechRecognition or the extension bridge. The app requests microphone permission on first use and grants audio-only capture for the paired HTTPS Origin. Computer components, model and network must be available; permission does not guarantee transcription. Same-origin client plugins share the page's permissions, so grant recording only when you trust them.
98
118
 
99
119
  Computer-side extensions are separate: their `host.mjs` runs as trusted local Node.js code on the DSH host, while `mobile.js` calls its scoped actions and routes. The app bridge cannot edit or upload extension source files.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.1",
3
- "versionCode": 77,
4
- "releaseTag": "v0.6.1"
2
+ "version": "0.6.2",
3
+ "versionCode": 78,
4
+ "releaseTag": "android-v0.6.2"
5
5
  }
package/cordis.patch.yml CHANGED
@@ -8,11 +8,14 @@
8
8
  - id: directory-picker-mobile-host
9
9
  name: '@deepseek-ai/dsh-host-directory-picker-browse'
10
10
  # Windows DSH Desktop supplies its own browse pair after user patches.
11
- disabled: !!js ctx.get('desktopRuntime')?.platform === 'win32'
11
+ # Its `desktopProfiles` service can appear before `desktopRuntime`; keep
12
+ # the platform guard so a Desktop profile on macOS/Linux retains the
13
+ # portable in-page picker.
14
+ disabled: !!js process.platform === 'win32' && (ctx.get('desktopRuntime')?.platform === 'win32' || ctx.get('desktopProfiles') !== undefined)
12
15
 
13
16
  - id: directory-picker-mobile-surface
14
17
  name: '@deepseek-ai/dsh-client-ui-directory-picker-browse'
15
- disabled: !!js ctx.get('desktopRuntime')?.platform === 'win32'
18
+ disabled: !!js process.platform === 'win32' && (ctx.get('desktopRuntime')?.platform === 'win32' || ctx.get('desktopProfiles') !== undefined)
16
19
 
17
20
  - id: mobile-access
18
21
  name: dsh-mobile
@@ -32,6 +35,7 @@
32
35
 
33
36
  # Keep long question titles and answer options in one card scrollport.
34
37
  # The component switch restores the upstream layout immediately.
38
+ # DSH anchors this file entry beside the bundle patch, independent of pnpm's linker.
35
39
  - id: dsh-ui-fixes
36
- name: dsh-mobile-question-fixes
40
+ name: ./packages/question-fixes/lib/index.mjs
37
41
 
@@ -40,7 +40,7 @@ The computer-side gateway terminates TLS with a five-year CA and 397-day public-
40
40
  | `frp_attach_mode_requires_vhost_port` | Public-CA mode needs the existing frps instance's real `vhostHTTPPort`; a guessed value can make the plaintext exposure probe check the wrong port. |
41
41
  | `frp_vhost_publicly_reachable` | The public-CA entry's plaintext vhost is reachable from outside. Restrict it without exposing another listener; a separate frps instance may be safer than changing global `proxyBindAddr`. |
42
42
  | `frp_attach_cert_unknown` | The self-signed certificate is absent or unreadable. Inspect the panel's certificate status and the private `remote/ingress/` files; do not bypass fingerprint validation. |
43
- | `frp_ingress_ca_expired` | The pinned CA expired. Reconfigure the self-signed entry and pair the phone again after checking the new fingerprint. |
43
+ | `frp_ingress_ca_expired` | The pinned CA expired. Reconfigure the self-signed entry and pair the phone again after checking the new fingerprint. Android 0.6.3 candidate keeps expired records readable and removable; in published App 0.6.2 an expired CA can make the device database unreadable. Retain App data pending this correction rather than clearing all pairings for one computer. |
44
44
  | Browser reports an untrusted certificate | Expected for self-signed ingress. Use app 0.4.6 or later and explicit pairing, or public-CA mode for a browser. |
45
45
  | `frp_proxy_name_in_use` | frps keeps proxy names unique across **all** its clients, and this installation's own name (`dsh-mobile-<first 12 characters of the installation identity>`) is already registered — usually another DSH computer, or this computer's previous session before the frps heartbeat expires it. Disable self-hosted FRP there, or remove that proxy on the frps. frpc keeps running without publishing the entry port, so check proxy registration rather than relying on process liveness. |
46
46
  | `frp_remote_port_in_use` | Another proxy on the same frps already owns the chosen entry port. Ports are first-come, first-served per server, so give this computer a different `publicPort` and allow it in the firewall. |
@@ -12,7 +12,7 @@
12
12
 
13
13
  | 项 | 含义 | 你要做什么 |
14
14
  |---|---|---|
15
- | **`vhostHTTPPort`** | 你 frps 上「Caddy ↔ frps」之间的**回环明文 HTTP** 端口(上游默认 7080) | 在面板填写**你真实的那个值**。插件不会替你假定 7080:端口填错会让「明文 vhost 公网可达」的安全闸门失效 |
15
+ | **`vhostHTTPPort`** | 你 frps 上「Caddy ↔ frps」之间的**回环明文 HTTP** 端口;本项目托管部署使用 7080,接入已有服务器以其实际配置为准 | 在面板填写**你真实的那个值**。插件不会替你假定 7080:端口填错会让「明文 vhost 公网可达」的安全闸门失效 |
16
16
  | **`proxyBindAddr`** | frps 的全局代理监听地址,同时影响 HTTP vhost 和 TCP 代理 | A 档的明文 HTTP vhost 必须只监听回环;B 档的 TCP `remotePort` 要能从公网访问。若既有 frps 设置为 `127.0.0.1`,仅放行防火墙也不会使 B 档公网可达;不要为 B 档盲目改为 `0.0.0.0`,以免暴露同一 frps 上已有的明文 vhost。需先核对整个 frps 的服务与防火墙,必要时改用另一实例或 A 档。 |
17
17
  | **入口证书档 `entryTls`** | 谁终止公网 TLS | 见下两档,按需二选一 |
18
18
 
@@ -92,7 +92,7 @@ curl -k -sS -o /dev/null -w '%{http_code}\n' https://YOUR_PUBLIC_IPV4:33080/mobi
92
92
  | `frp_attach_mode_requires_vhost_port` | 选了公开 CA 证书档却没填你 frps 的真实 `vhostHTTPPort`。填上真实值即可(插件不会替你假定 7080) |
93
93
  | `frp_vhost_publicly_reachable` | 公开 CA 档的明文 vhost 端口从公网可达。限制其监听或改用独立 frps 实例;若同一实例还要提供自签档公网 TCP 入口,不要盲目把全局 `proxyBindAddr` 改为回环或公网地址。 |
94
94
  | `frp_attach_cert_unknown` | 自签入口证书缺失或不可读;检查面板证书状态与私有目录的 `remote/ingress/`,不要绕过指纹验证。 |
95
- | `frp_ingress_ca_expired` | 自签 CA 已过期,插件不会静默替换受信任 CA;重新生成 CA 后,手机须核对新指纹并重新配对。 |
95
+ | `frp_ingress_ca_expired` | 自签 CA 已过期,插件不会静默替换受信任 CA;重新生成 CA 后,手机须核对新指纹并重新配对。Android 0.6.3 候选保留过期记录可读、可删除;当前正式 App 0.6.2 的过期 CA 可能使整个设备库不可读,遇到时请保留 App 数据并等待该修正,不要为一台电脑清除全部配对。 |
96
96
  | 手机浏览器提示证书不受信任 | 自签档的正常现象;请在 App 内配对使用 |
97
97
  | 自检显示「公网入口不可达」 | 端口未放行、frpc 未启动,或 frps 未把该 `remotePort` 转发出来 |
98
98
  | `frp_proxy_name_in_use` | frps 的代理名在**整台服务器**上唯一。本机安装名(`dsh-mobile-<安装标识前 12 位>`)已被占用:多半是另一台 DSH 电脑,或本机上一次连接尚未等到 frps 心跳超时。到那台机器上关闭自建 FRP,或在 frps 上移除该代理。frpc 此时仍在运行、只是入口端口没被发布,应检查代理是否注册成功,不能仅凭进程存在判断就绪。 |
@@ -22,7 +22,7 @@ Configure the public HTTPS origin, DNS-01 credentials and local HTTPS port separ
22
22
 
23
23
  ## Installation, startup, and readiness
24
24
 
25
- Once pinned assets are published, installation requires explicit download confirmation. The plugin verifies exact length, SHA-256, Caddy core version, and DNS module version; unavailable or invalid assets are not executed. Installed is not ready: after parsing the local configuration, the proxy starts, and readiness requires verified public HTTPS and discovery identifying the current DSH instance.
25
+ Official component distribution alone does not enable installation: independently verified assets must first be pinned in a separate reviewed production-catalog PR. After that second stage, installation requires explicit download confirmation. The plugin verifies exact length, SHA-256, Caddy core version, and DNS module version; unavailable or invalid assets are not executed. Installed is not ready: after parsing the local configuration, the proxy starts, and readiness requires verified public HTTPS and discovery identifying the current DSH instance.
26
26
 
27
27
  Initial DNS-01 issuance waits for DNS propagation and certificate issuance. Keep the computer online and avoid repeated restarts that can trigger issuer limits. Managed mode creates no system service, PATH entry, startup item, or system trust-store certificate. Caddy's admin API and configuration autosave are disabled.
28
28
 
@@ -58,4 +58,18 @@ Component tags never start with `v`, avoiding the plugin release trigger. The se
58
58
 
59
59
  The public custom-download endpoint returned v2.11.7 when v2.11.6 was requested; dynamic latest downloads are not a trust source. Versioned GitHub URLs can still be replaced by repository owners: exact reviewed byte/hash pins, not URL spelling or a remotely supplied checksum alone, define the content boundary. A fork catalog is only a review candidate; it never automatically populates the [production table](<../src/caddy-component.ts>). Official production installation stays disabled until maintainers publish and review their own distribution.
60
60
 
61
+ ### Official distribution is a separate, two-stage authorization
62
+
63
+ This change prepares a channel, not a release. Stage 1 requires maintainer approval of this workflow PR on reviewed, protected `main`. Maintainers must preconfigure `caddy-component-release` with required reviewers, nonempty reviewer assignments and **prevent self-review**; administrators must not bypass environment approval. GitHub Actions supplies actual approval before the single publisher job starts. The script additionally fetches the real environment policy and refuses missing, malformed or unprotected policy before its first release mutation. An environment name, a main ancestry comparison or synthetic policy tests do not prove human review/approval.
64
+
65
+ Official publication is restricted to the **public** `saya-ch/dsh-mobile` repository and its existing stable non-`v` tag `caddy-component-2.11.6-tencentcloud-0.4.3`. Both publication inputs default to false; choosing both fails the early native validation. Wrong events, branches, repositories or channel/tag identities cannot publish. Before mutations the publisher resolves `/commits/TAG` to the exact Actions `GITHUB_SHA`; `/compare/main...SHA` must be `identical` or `behind` (main membership/ancestry only, **not code review**). The prepared assets and source metadata use that same SHA and both native builds from the same run, not older downloaded builds.
66
+
67
+ The publisher keeps only `contents: write`, using `GITHUB_TOKEN` for API calls and no token/API headers for public assets. [GitHub's Get an environment documentation](<https://docs.github.com/en/rest/deployments/environments?apiVersion=2022-11-28#get-an-environment>) normally requires Actions read, but explicitly permits public resources without that permission. This narrowly scoped public-resource exception is a prerequisite, not a verified live token capability: any authenticated 401/403/404/5xx or network failure is fatal before release creation; there is no unauthenticated retry, privilege escalation or alternate publication secret. Maintainers must confirm repository visibility, endpoint readability and protected-environment configuration. If authenticated access fails, report missing read capability rather than relaxing policy. Review publication uses `caddy-component-review` and does not apply the official policy requirement.
68
+
69
+ After those prerequisites and explicit publication authorization (not as part of this preparation task), maintainers can dispatch the existing stable tag with `publish_official_release=true` and review input false. The one existing Windows/Linux x64 matrix still builds twice, verifies native installer/TLS/API/WSS/no-system-trust behavior, and runs the full tests/build. The generic publisher creates `--draft --prerelease=false --latest=false`, refuses occupied releases without update/clobber/delete retries, uploads and downloads **all 16 assets**, compares them byte-for-byte, then publishes `--draft=false --prerelease=false --latest=false`. Review flags remain prerelease/non-latest. Official verification permits `/releases/latest` 404 when no latest exists, but rejects this component as latest and any other error or malformed success. The component never replaces the latest plugin, nor publishes npm/APK automatically. Post-publication verification failure leaves the public release in place, fails the job and emits no candidate; it never rolls back destructively.
70
+
71
+ The existing prepare/verify CLI signatures default strictly to review; only an optional trailing `--channel official` (or `--channel review`) selects the shared exact identity rules. Official `COMPONENT-RELEASE.json` has kind `managed-caddy-component-official`; successful public metadata/size/hash and actual HTTPS/validated-redirect verification of every asset emits `official-candidate-not-production`. Both channel indices and candidates retain `productionCatalogEnabled: false`; outputs are bounded and exclusive, never overwritten.
72
+
73
+ Stage 2 is **later**: independently verify the actually published official bytes, then submit a separate reviewed PR that hardcodes the exact source/size/hash pins in `CADDY_COMPONENT_RELEASES`. It remains exactly `Object.freeze({})` during this preparation. Remote candidate JSON is never runtime trust/configuration. Support remains Windows/Linux x64 with Tencent Cloud DNS only. Do not replace a private preview with an official plugin package whose catalog is empty and expect managed restart to work. Human live-network evidence is separate from final-candidate CI; neither isolated tests nor that evidence establish certificate renewal.
74
+
61
75
  Isolated tests use ephemeral loopback listeners and a private internal CA with `skip_install_trust`; no system trust, production DNS or existing proxy is changed. They **do not establish public DNS-01/ACME issuance or public-route readiness**. Those need a separately authorized dedicated test hostname, least-privilege DNS credentials and actual reachable ingress.