dsh-mobile 0.6.18 → 0.7.0

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,27 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.7.0 - 2026-10-28
6
+
7
+ - Distribute the iroh sidecar from this plugin. **Install official component** downloads the pinned `dsh-mobile-iroh 0.1.0-alpha.1` release per platform, verifies byte length and SHA-256, and promotes it into the plugin private directory with backup and rollback; a verified companion copy is reused without downloading during the transition, and switching the channel on alone never downloads. The panel names the download size, reports verification progress, and identifies the exact missing/invalid/offline failure instead of a generic not-ready message.
8
+ - Add the experimental iroh remote provider with its own endpoint-pinned gateway TLS identity (stable CA, 90-day DNS leaf with 30-day renewal headroom, no silent regeneration) and a five-minute one-time pairing window that binds the sidecar code to a one-time gateway token, redeemable through the ordinary pair endpoint over the iroh transport. Drain buffered sidecar startup events before minting, so a stale code is never offered.
9
+ - Vendor the iroh transport host Rust source (`native/iroh-host`, shared core `native/iroh-core`, MIT with preserved dsh-tether attribution) with per-platform build lanes for the host and both Android ABIs.
10
+ - Integrate Android's experimental iroh connection through a JNI-backed HTTPS CONNECT transport, pairing parsing, connection/status controllers and optional pairing-record fields. App 0.7.0's full APK includes arm64-v8a and x86_64; the compatibility APK retains existing HTTPS channels without native libraries. Thanks @qzyqmzn for [#284](https://github.com/saya-ch/dsh-mobile/pull/284), based on the independent dsh-mobile-iroh experiment.
11
+
12
+ - Retain iroh probe and sidecar ownership until cleanup succeeds; concurrent shutdown waits for admitted startup, and failed termination remains visible and retryable.
13
+ - Keep the shell chrome opaque under translucent skins. The navigation drawer, the right detail panel and the panel return bar composite their theme token over the CSS `Canvas` system colour, so a skin that makes those tokens translucent — or leaves them unresolvable — no longer lets conversation text show through the sidebar labels. Thanks @LUgABeEEE for [#286](https://github.com/saya-ch/dsh-mobile/pull/286).
14
+ - Isolate the dedicated mobile shell's stacking context so positioned, positive-z-index menus attached to `document.body` can appear above its drawer. Preserve the existing stock-adapter layer values; see the [overlay guidance](docs/MOBILE_PLUGIN_ADAPTATION.en.md#overlay-layering-and-portals) for limits and modal behavior. Thanks @LUgABeEEE for [#295](https://github.com/saya-ch/dsh-mobile/pull/295) and @eeeggplant for [#288](https://github.com/saya-ch/dsh-mobile/issues/288).
15
+ - Document using an existing cloudflared tunnel instead of a plugin-managed component. The own-reverse-proxy provider already accepts a public HTTPS origin in front of the plugin's authenticated backend, so a user who already runs a named tunnel can point it at that backend and keep owning DNS, the certificate and the tunnel Token; the plugin neither installs a second copy nor stores the Token. The [self-hosted origin guide](docs/SELF_HOSTED_ORIGIN.en.md#when-you-already-run-cloudflared-yourself) now covers the ingress snippet, the reload step and the two caveats (port 3444 overlap with the managed component, and never targeting 3080/3443). Thanks @yuyang0 for [#300](https://github.com/saya-ch/dsh-mobile/issues/300).
16
+ - Show a localized, dismissible notice when mobile customization cannot authenticate or load. A Gateway authentication rejection can request the existing native renewal owner even if transport appears connected; transient failure retains explicit **Retry loading**, and confirmed renewal refreshes read-only custom assets without reloading the page. Stop further renewal after an explicit credential rejection. Browser-only pages retain actionable guidance instead of silently hiding the failure. Thanks @eeeggplant for [#298](https://github.com/saya-ch/dsh-mobile/issues/298).
17
+ - Restore the conversation when leaving DSH's native detail-panel fullscreen view. Preserve the active panel and normal toggle behavior instead of leaving the mobile conversation hidden. Thanks @LUgABeEEE for [#299](https://github.com/saya-ch/dsh-mobile/pull/299).
18
+ - Update the Android build toolchain and development-only YAML tooling. Thanks @LUgABeEEE for [#296](https://github.com/saya-ch/dsh-mobile/pull/296), [#293](https://github.com/saya-ch/dsh-mobile/pull/293) and [#294](https://github.com/saya-ch/dsh-mobile/pull/294).
19
+
20
+ ## Android 0.7.0 - 2026-10-28
21
+
22
+ - Add optional experimental iroh pairing and transport in the full 64-bit APK. Existing HTTPS pairings, device management and WebView behavior remain available in both builds; standalone dsh-mobile-iroh App records do not migrate automatically.
23
+ - Publish a full `-iroh.apk` and a smaller compatibility `.apk`, with the same application ID, versionCode 85 and established signer. The legacy update/download filename continues to serve the compatibility build, including for 32-bit devices; install the full build explicitly to use iroh. Installing an official build over another retains local data, but the compatibility build cannot connect iroh records.
24
+ - Bundle native third-party notices and verify native ABI packaging, 16 KB alignment, compatibility-library exclusion and both signatures in the release workflow.
25
+
5
26
  ## 0.6.18 - 2026-10-26
6
27
 
7
28
  - Preserve DSH's adaptive directory-picker composition. The dedicated Mobile page reuses an available upstream browse picker, including its **New folder** action; a host using the system chooser keeps that chooser on Desktop and gets a separate web directory flow on the remote page. Thanks @OranImp for [#271](https://github.com/saya-ch/dsh-mobile/issues/271).
@@ -199,7 +220,7 @@ Notable changes are recorded here. GitHub Releases provide the downloadable pack
199
220
 
200
221
  ## 0.6.2 - 2026-10-08
201
222
 
202
- - 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).
223
+ - 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 @luoyangshovel for [#187](https://github.com/saya-ch/dsh-mobile/issues/187).
203
224
  - Keep the mobile shell within the viewport when the browser does not support `dvh`, so DSH's existing conversation area retains a scroll range. Portrait/landscape touch checks cover this missing-feature case; the Android 13 devices in #187 still need confirmation from their actual WebViews.
204
225
  - Release the npm plugin and Android App independently. Plugin updates retain the existing signed APK when native code is unchanged; App downloads use the published App descriptor, and plugin update notes follow the npm version. Android remains 0.6.1 (build 77) for this plugin update.
205
226
  - Keep release history in this changelog, simplify both project READMEs and clarify which component needs updating.
package/CONTRIBUTORS.md CHANGED
@@ -163,7 +163,7 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
163
163
  | [@jonaskilli](https://github.com/jonaskilli) | [#198](https://github.com/saya-ch/dsh-mobile/issues/198) |
164
164
  | [@jueruibo](https://github.com/jueruibo) | [#101](https://github.com/saya-ch/dsh-mobile/issues/101) |
165
165
  | [@KMGTPEZY](https://github.com/KMGTPEZY) | [#95](https://github.com/saya-ch/dsh-mobile/issues/95) |
166
- | [@luoyangchan](https://github.com/luoyangchan) | [#187](https://github.com/saya-ch/dsh-mobile/issues/187) |
166
+ | [@luoyangshovel](https://github.com/luoyangshovel) | [#187](https://github.com/saya-ch/dsh-mobile/issues/187) |
167
167
  | [@LWping](https://github.com/LWping) | [#94](https://github.com/saya-ch/dsh-mobile/issues/94) |
168
168
  | [@miqian-nomad](https://github.com/miqian-nomad) | [#97](https://github.com/saya-ch/dsh-mobile/issues/97) |
169
169
  | [@MLYR](https://github.com/MLYR) | [#193](https://github.com/saya-ch/dsh-mobile/issues/193) |
package/README.en.md CHANGED
@@ -32,14 +32,14 @@
32
32
 
33
33
  > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
34
34
  >
35
- > **Current stable release: 0.6.18**. Create folders from the remote directory picker, with compact navigation and controls that leave more room for folders. Recover from stale module choices that prevented the page from opening, and optionally administer a NAS from an authenticated, controlled network. The Android App is released independently; App **0.6.7** supports these plugin features. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18) · [Full changelog](CHANGELOG.md).
35
+ > **Current stable release: 0.7.0**. Add experimental iroh connections, improve sidebars under translucent skins, third-party menu layering and fullscreen-panel exit, and offer recovery feedback when mobile customization fails to load. Existing HTTPS channels and older Apps remain usable; iroh requires the full App with native transport. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.0) · [Full changelog](CHANGELOG.md).
36
36
  >
37
37
  > **Version policy**: since plugin **0.6.2**, the Android app and plugin use independent version numbers and releases. Their numbers do not need to match, and a plugin update does not imply an app update. [Compatibility notes](#compatibility).
38
38
 
39
39
  <p align="center">
40
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.7/dsh-mobile-android-v0.6.7.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>
41
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.7/dsh-mobile-android-v0.6.7.apk"><strong>Download Android app 0.6.7</strong></a><br>
42
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.7">Release notes and checksums</a></sub>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0.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>
41
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0.apk"><strong>Download Android app 0.7.0 (compatibility)</strong></a><br>
42
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0-iroh.apk">64-bit full APK (experimental iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0">Release notes and checksums</a></sub>
43
43
  </p>
44
44
 
45
45
  DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. Both routes reach the same sessions, Workspaces, messages, and tools. The computer manages their switches and pairing authorizations separately; the Android app lists paired computers together. The plugin does not modify DeepSeek Harness source.
@@ -207,7 +207,7 @@ See [Compatibility](#compatibility) for the supported components and platforms.
207
207
 
208
208
  ### Experimental iroh connection
209
209
 
210
- [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh) is being developed independently to explore iroh connections while retaining DSH Mobile's pairing, device list and WebView experience. The local development candidate connects the Rust transport and Android app, with local QUIC/HTTPS/WSS checks and Android builds passing. It has not been integrated into this plugin or formally released; the desktop management UI, automatic certificate setup and physical cross-network acceptance remain unfinished. It is not yet a connection option in the current stable app.
210
+ Plugin 0.7.0 integrates the experimental connection from [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh): encrypted direct or relayed access without a public domain, port forwarding or a tunnel account. Select **Mobile access → Remote → iroh (Experimental)** on the computer, install and verify the official component, enable it, then scan its dedicated QR code with the full App. LAN and existing HTTPS channels remain available; mobile browsers cannot connect through iroh directly. See the [iroh guide](docs/IROH.en.md) for platforms, pairing and troubleshooting.
211
211
 
212
212
  ## Extend and customize
213
213
 
@@ -410,6 +410,7 @@ The plugin retains DSH host peer declarations without rejecting installation or
410
410
  | Self-hosted FRP | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) |
411
411
  | Own reverse proxy | Yes (config only) | Yes (config only) | Yes (config only) | Yes (config only) |
412
412
  | Managed Caddy | Yes (on-demand) | Yes (on-demand) | No | No |
413
+ | iroh (Experimental) | Yes (on-demand) | Yes (on-demand) | No | No |
413
414
 
414
415
  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.
415
416
 
@@ -421,8 +422,9 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
421
422
  | `0.6.14` | Release CI packed-browser jobs green on all eight DSH versions from `0.1.7-alpha.2` to `0.2.1-rc.2`; no additional per-version manual acceptance was recorded for this release |
422
423
  | `0.6.15` | `0.2.1-rc.2`: real admin-panel pairing in Firefox 158 privacy mode, the HTTPS mobile page and Workspace-read baseline, and silent Blob playback; release CI green on all eight versions |
423
424
  | `0.6.16` | `0.2.1-rc.2`: Gallery selection, plain-text draft transfer through public DSH input APIs, real mux recovery and cross-client pending questions; CI additionally covered `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.2` and `0.2.1-alpha.3` |
424
- | `0.6.18` | `0.2.1-rc.2`: 18 real packed Chromium directory-picker checks, including compact layout, folder creation and cancellation; the candidate was installed in local official Desktop `0.2.1-rc.3` with LAN and Cloudflare gateways running |
425
425
  | `0.6.17` | `0.2.0-rc.2` and `0.2.1-rc.2`: 15 real packed Chromium directory-picker checks, the old-WebView missing-API simulation and Workspace mux reads; the published package was then installed into official Desktop `0.2.1-rc.2` and its files matched byte for byte |
426
+ | `0.6.18` | `0.2.1-rc.2`: 18 real packed Chromium directory-picker checks, including compact layout, folder creation and cancellation; the candidate was installed in local official Desktop `0.2.1-rc.3` with LAN and Cloudflare gateways running |
427
+ | `0.7.0` | Packed-browser CI across eight DSH versions (`0.1.7-alpha.2`–`0.2.1-rc.2`), Windows/Linux Gateway and iroh Host checks, both Android ABIs and compatibility APK checks. See the [iroh guide](docs/IROH.en.md) for device and network limits |
426
428
 
427
429
  <details>
428
430
  <summary>Historical version checks</summary>
package/README.md CHANGED
@@ -32,14 +32,14 @@
32
32
 
33
33
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
34
34
  >
35
- > **当前正式版本:0.6.18**。远程目录选择支持新建文件夹,导航和按钮更紧凑,为文件夹列表留出更多空间;修复过期模块配置导致无法进入页面的问题,并增加受控 NAS 管理入口。Android App 独立发布,现有 **0.6.7** 可使用本次插件功能。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18) · [完整更新记录](CHANGELOG.md)。
35
+ > **当前正式版本:0.7.0**。新增实验性 iroh 连接,改善透明皮肤下的侧栏、第三方菜单层级和全屏面板退出,并在移动定制加载失败时提供恢复提示。现有 HTTPS 通道和旧版 App 仍可使用;iroh 需要含原生传输的完整版 App。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.7.0) · [完整更新记录](CHANGELOG.md)。
36
36
  >
37
37
  > **版本说明**:自插件 **0.6.2** 起,Android App 与插件独立编号、独立发布,版本号无需一致;插件升级不代表 App 需要同步升级。[兼容说明](#兼容性)。
38
38
 
39
39
  <p align="center">
40
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.7/dsh-mobile-android-v0.6.7.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>
41
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.6.7/dsh-mobile-android-v0.6.7.apk"><strong>下载 Android App 0.6.7</strong></a><br>
42
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.7">版本说明与校验文件</a></sub>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0.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>
41
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0.apk"><strong>下载 Android App 0.7.0(兼容版)</strong></a><br>
42
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.0/dsh-mobile-android-v0.7.0-iroh.apk">64 位完整版(含实验性 iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0">版本说明与校验文件</a></sub>
43
43
  </p>
44
44
 
45
45
  DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP 或自有反向代理远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
@@ -207,7 +207,7 @@ Funnel 的运行组件把公开监听生命周期绑定到父进程和受限控
207
207
 
208
208
  ### 实验中的 iroh 连接
209
209
 
210
- [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh) 正在独立开发,探索通过 iroh 连接电脑,并沿用 DSH Mobile 的配对、设备列表和 WebView 体验。目前本地开发候选已接通 Rust 传输与 Android,并通过本地 QUIC/HTTPS/WSS 验证和 Android 构建;尚未并入本插件或正式发布,电脑端操作界面、自动证书配置与真机跨网验收仍待完成。它还不是当前正式 App 可选的连接方式。
210
+ 插件 0.7.0 整合了 [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh) 的实验性连接:通过加密直连或中继访问电脑,不要求公网域名、端口映射或隧道账号。电脑端选择 **移动访问 → 远程 → iroh(实验性)**,安装并校验官方组件后启用,再用完整版 App 扫描专属二维码。局域网和既有 HTTPS 通道不受影响;手机浏览器不能直接使用 iroh。平台要求、配对与排障见 [iroh 使用说明](docs/IROH.md)。
211
211
 
212
212
  ## 扩展与自定义
213
213
 
@@ -410,6 +410,7 @@ flowchart LR
410
410
  | 自建 FRP | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) |
411
411
  | 自有反向代理 | 支持(纯配置) | 支持(纯配置) | 支持(纯配置) | 支持(纯配置) |
412
412
  | 托管 Caddy | 支持(按需下载) | 支持(按需下载) | 不支持 | 不支持 |
413
+ | iroh(实验性) | 支持(按需下载) | 支持(按需下载) | 不支持 | 不支持 |
413
414
 
414
415
  macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funnel 与 cpolar 暂未提供 macOS 组件。诊断页的防火墙检查目前仅覆盖 Windows,其他系统显示“不适用”。
415
416
 
@@ -421,8 +422,9 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
421
422
  | `0.6.14` | 8 个 DSH 版本(`0.1.7-alpha.2`–`0.2.1-rc.2`)的发布 CI 打包浏览器作业全绿;本版未记录额外的逐版本人工验收范围 |
422
423
  | `0.6.15` | `0.2.1-rc.2` 的 Firefox 158 隐私模式真实管理面板配对、HTTPS 移动页面与工作区读取基线,以及静音 Blob 播放;发布 CI 8 版本全绿 |
423
424
  | `0.6.16` | `0.2.1-rc.2` 的相册选择、纯文本草稿经公开 DSH 输入接口传输、真实 mux 恢复与跨客户端待答问题;CI 另覆盖 `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.2`、`0.2.1-alpha.3` |
424
- | `0.6.18` | `0.2.1-rc.2` 上的 18 项真实打包 Chromium 目录选择检查,含紧凑布局、目录创建和取消;本机官方 Desktop `0.2.1-rc.3` 已装入候选并启用局域网与 Cloudflare 网关 |
425
425
  | `0.6.17` | `0.2.0-rc.2`、`0.2.1-rc.2` 的 15 项真实打包 Chromium 目录选择检查、旧 WebView 缺失 API 模拟与工作区 mux 读取;发布后装入官方 Desktop `0.2.1-rc.2` 并核对包内文件一致 |
426
+ | `0.6.18` | `0.2.1-rc.2` 上的 18 项真实打包 Chromium 目录选择检查,含紧凑布局、目录创建和取消;本机官方 Desktop `0.2.1-rc.3` 已装入候选并启用局域网与 Cloudflare 网关 |
427
+ | `0.7.0` | 8 个 DSH 版本(`0.1.7-alpha.2`–`0.2.1-rc.2`)的打包浏览器 CI;Windows/Linux Gateway 与 iroh Host、Android 双 ABI 和兼容版包检查。设备与网络范围见 [iroh 说明](docs/IROH.md) |
426
428
 
427
429
  <details>
428
430
  <summary>历史版本验证记录</summary>
@@ -16,10 +16,43 @@ The optional [cloudflared](https://github.com/cloudflare/cloudflared) client is
16
16
 
17
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
+ The experimental Rust transport is adapted from [dsh-mobile-iroh](https://github.com/saya-ch/dsh-mobile-iroh), copyright 2026 Guangqi Zhang, under the MIT License, and the host baseline preserves zexadev's MIT-licensed dsh-tether attribution. The source notices and complete licenses are retained under `native/iroh-host/` and included with the npm package. The optional sidecar is not bundled: explicit installation reuses a verified companion copy or downloads the size- and SHA-256-pinned companion release payload. Enabling the channel alone does not download it.
20
+
19
21
  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`, [eventsource-parser](https://github.com/rexxars/eventsource-parser) `3.1.0`, [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
22
 
21
23
  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
24
 
25
+ The full Android APK packages `libdsh_mobile_iroh_android_transport.so` for arm64-v8a and x86_64, from `native/iroh-android-transport` and `native/iroh-core`. It includes the matching `org.rustls:rustls-platform-verifier` JVM component from an immutable official Maven archive, selecting its version from the Android shim entry in `native/Cargo.lock`. These transport sources retain their MIT license; the surrounding Android shell remains Apache-2.0. The compatibility APK uses `-PirohNative=false` and contains neither native libraries nor the JVM verifier dependency; it retains installation support for 32-bit devices. Both builds include the third-party notices asset.
26
+
27
+ ### Rust workspace dependency metadata
28
+
29
+ The inventory made with `cargo metadata --locked --manifest-path native/Cargo.toml` describes the whole Rust workspace, including target-specific and development dependencies. It is not an inventory of code linked into either Android ABI, nor a complete set of license/notice texts for distribution. The exact versions remain in `native/Cargo.lock`.
30
+
31
+ Before publishing a native-enabled APK, identify the dependencies actually shipped for each target, retain the applicable license and notice texts with the distribution, and verify any source-availability obligations. The source MIT notices retained here do not by themselves complete that release check.
32
+
33
+ #### Where the complete license texts live
34
+
35
+ The upstream `dsh-mobile-iroh` companion package ships a generated
36
+ `native/THIRD_PARTY_NOTICES.txt` (~2.9 MB). It lists each dependency's declared
37
+ license, crates.io source and the full reproduced license text, and its header states
38
+ it covers build-time dependencies for the Windows x64, Linux x64, Android arm64 and
39
+ Android x64 targets. The two entries that need more than a one-line note are present in
40
+ full:
41
+
42
+ - **`attohttpc` 0.30.1** and **`option-ext` 0.2.0** — complete Mozilla Public License
43
+ 2.0 text. MPL-2.0 is file-level copyleft: static linking and distribution inside a
44
+ larger work is permitted, the MPL-covered source stays available under MPL-2.0 from
45
+ the sources named there, and no DSH Mobile source file is derived from them.
46
+ - **`r-efi`** offers `MIT OR Apache-2.0 OR LGPL-2.1-or-later`; the permissive option is
47
+ taken, so LGPL-2.1 does not apply.
48
+
49
+ Both APK variants bundle this notice at `assets/THIRD_PARTY_NOTICES.txt`, based on
50
+ the published companion package with both transport source licenses and the MIT
51
+ text for Windows build dependency `winapi-util` added from their sources. `node scripts/check-iroh-notices.mjs`
52
+ checks coverage of each Android ABI's normal/build graph. When `native/Cargo.lock`
53
+ changes, regenerate the notice and replace this asset so the shipped texts stay current. See the [iroh
54
+ guide](docs/IROH.en.md) for the full and compatibility APK requirements.
55
+
23
56
  ## Notification identity hashing
24
57
 
25
58
  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:
@@ -4,14 +4,14 @@
4
4
 
5
5
  DeepSeek Harness is the display name of this community-maintained Android WebView app. It opens the plugin's authenticated HTTPS page rather than bundling another DSH frontend. The app and mobile browsers receive the same DSH features and computer-side mobile customizations.
6
6
 
7
- The current stable app is **0.6.7** (build 83). The npm plugin and Android App have independent versions: a plugin update does not automatically require another APK. See the [0.6.7 changes](#067-update).
7
+ The current stable app is **0.7.0** (build 85). The npm plugin and Android App have independent versions: a plugin update does not automatically require another APK. See the [0.7.0 changes](#070-update).
8
8
 
9
9
  Android 10 or later is supported. The local iOS experiment is not a published or supported client.
10
10
 
11
11
  ## Install and pair
12
12
 
13
13
  1. Install and enable the plugin using the [project quick start](../../README.en.md#quick-start). Complete LAN setup from the command line or the computer's **Mobile Access** panel.
14
- 2. Install the signed Android APK from [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.7). Upgrade an official installation in place using the same release signer to retain its pairings. A differently signed Debug APK cannot replace it; do not uninstall or clear data just to bypass that mismatch.
14
+ 2. Install a signed Android APK from [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0). Choose the compatibility `.apk` for existing HTTPS channels, or the full `-iroh.apk` for experimental iroh on arm64-v8a/x86_64. Both have the same package ID and official signer; install only one and upgrade in place to retain pairings. A differently signed Debug APK cannot replace it; do not uninstall or clear data just to bypass that mismatch.
15
15
  3. On the computer, generate a pairing key/link under **Mobile Access → Local network**, or configure a remote provider and generate its remote pairing QR code. In the app, choose the matching connection mode and scan or paste the link.
16
16
  4. Name the computer. The app stores each LAN or remote pairing as its own record. The phone does not need a cpolar, Cloudflare or Tailscale app.
17
17
 
@@ -36,6 +36,16 @@ Page zoom changes the whole page and is separate from per-address text preferenc
36
36
 
37
37
  Deleting a local record removes its saved token and pinned CA, not the computer's authorization or every short-lived WebView cookie. Use **Mobile Access** on the computer to revoke access immediately. A full Android clear-app-data reset removes all pairings and web data and is not a normal reconnection step.
38
38
 
39
+ ## 0.7.0 update
40
+
41
+ App 0.7.0/build 85 adds optional experimental iroh pairing and native transport in the full APK, working with plugin 0.7.0 or later. The compatibility APK retains existing HTTPS channels without native libraries, including on 32-bit devices. Legacy updates download compatibility by default; choose the full APK explicitly when using iroh. Both retain the device list, HTTPS pairings and established signer. Records from the separate experimental App do not migrate automatically.
42
+
43
+ iroh is off by default. The computer installs a verified component, then generates a dedicated pairing QR code under **Mobile access → Remote → iroh (Experimental)**. Direct/relayed connectivity depends on both networks; mobile browsers cannot use this transport directly. See the [iroh guide](../../docs/IROH.en.md).
44
+
45
+ ## 0.6.8 update
46
+
47
+ App 0.6.8/build 84 keeps the first page download under the existing overall connection deadline instead of interrupting it with a shorter page timer and automatically starting over. A genuine first-load failure keeps explicit retry; recovery for an already running page, TLS verification and cancellation remain available. Upgrade the App to receive this native fix; a plugin-only update cannot provide it.
48
+
39
49
  ## 0.6.7 update
40
50
 
41
51
  App 0.6.7/build 83 adds optional same-computer LAN/remote switching when used with plugin 0.6.16 or later. Manual remains the default. Pair both entries independently, then choose a switching mode in device-list Settings. Eligible same-Session plain-text drafts can follow an automatic switch; this is not full-page state migration. See the [switching rules](#automatic-same-computer-connection).
@@ -147,12 +157,27 @@ Set-Location apps/mobile/android
147
157
 
148
158
  The Debug APK is `app/build/outputs/apk/debug/app-debug.apk`. Official releases use the established signing key stored only in repository Secrets. A local unsigned Release build or a Debug install is not official-signer evidence.
149
159
 
160
+ Every build ships the experimental iroh transport by default. It requires Rust 1.99.1 with the `aarch64-linux-android` and `x86_64-linux-android` targets plus an explicitly selected NDK:
161
+
162
+ ```powershell
163
+ Set-Location apps/mobile/android
164
+ ./gradlew.bat :app:assembleDebug -PirohNdk=C:/Android/Sdk/ndk/25.2.9519653 -x :app:lintAnalyzeDebugUnitTest -x :app:lintAnalyzeDebugAndroidTest
165
+ ```
166
+
167
+ Pass `-PirohNative=false` for a fast toolchain-free lane that builds the original HTTPS shell: the iroh pairing entry is absent and `IrohNative` reports itself unavailable. The transport libraries are generated under `app/build/generated/iroh/jniLibs/` and never committed. A native-enabled build does not change the package identity or the established signer; the independent alpha signer from the iroh experiment is not used here.
168
+
169
+ Native builds also include the JVM TLS verifier matching `native/Cargo.lock`, from the revision-pinned official Maven archive. Preserve its JNI/Proguard rules: compiling and packaging the `.so` alone is insufficient. The APK verifier checks the retained JVM classes and native entry names in both Debug and minified Release builds.
170
+
150
171
  Current-source Debug builds use package `io.github.sayach.dshmobile.debug` with a `-debug` version suffix. They install beside the official App with separate storage and pairings. They do not upgrade or migrate an older unsuffixed Debug installation; preserve that app and its data rather than uninstalling or clearing it to switch packages. Release builds keep `io.github.sayach.dshmobile` and the established signer.
151
172
 
152
- The verified stable release is [Android 0.6.7](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.7), build 83, SHA-256 `919153244e6b84eb55c4701146f50454995330e080da9c91389e8816b2bd9b79`. The downloaded APK retains the established release signer and package `io.github.sayach.dshmobile`. Earlier release history belongs in [CHANGELOG](../../CHANGELOG.md).
173
+ The verified stable release is [Android 0.7.0](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0), build 85. The compatibility and full APKs each have a matching `.sha256` asset. Both public downloads retain the established release signer and package `io.github.sayach.dshmobile`. Earlier release history belongs in [CHANGELOG](../../CHANGELOG.md).
153
174
 
154
175
  ## Acceptance and known limits
155
176
 
177
+ - Both public App 0.7.0 APKs passed checksum, manifest, signer, notice and alignment checks. The full APK additionally passed ABI and retained JVM TLS/JNI entry checks; compatibility contains no native libraries. Earlier arm64 development evidence covers native iroh Gateway/custom-resource traffic without ADB forwarding. The final JVM TLS dependency correction has not had a new physical-device/public-relay run; a relay socket alone does not prove relayed payload traffic.
178
+
179
+ - App 0.6.8's public APK passed identity, checksum and established-signer verification. A matching-signer Debug upgrade opened DSH and retained the saved device; controlled slow-link fault injection was interrupted before pairing and is not counted as passed.
180
+
156
181
  - App 0.6.7 Debug builds were checked on PJW110, Android 16 and WebView 153 with isolated DSH 0.2.1-rc.2 over USB-reversed pinned HTTPS. Actual automatic staged adoption retained a same-Session Unicode draft and kept target native zoom/renewal working without another page load. Confirmation cancellation, held-target Back cancellation and late responses, native renewal cancellation, keyboard Back and picker cancellation also passed; QA pairings and mappings were removed afterward. This was not a real Wi-Fi/cellular transition or an installation of the formally signed APK.
157
182
  - Connection-control development builds used Debug metadata 0.6.4/build 80 on PJW110, Android 16 and Google WebView 153.0.8010.36. Against an isolated DSH 0.2.0-rc.2/plugin 0.6.10 instance over USB and pinned HTTPS, checks covered pairing/startup/saved-connection cancellation, Back, failed manual connections and return from a failed page after stopping native recovery. Held module responses also verified early webpage display, touch-through outside compact cancellation, cancellation and later completion. Pairings were retained and owned QA records removed.
158
183
  - Debug builds of App 0.6.4 retained one WebView across document replacement/reload, rejected an old selection, and received controlled PNG bytes with a decoded DSH draft preview. A held navigation and HTTP 204 also checked selector availability. Earlier checks covered model-menu Back, rotation with draft/reference/image retention, known revocation, re-pairing, icon choices and list ordering. None required a model prompt.
@@ -4,14 +4,14 @@
4
4
 
5
5
  DeepSeek Harness 是这个社区维护的 Android WebView App 的显示名称。它直接打开插件提供的已认证 HTTPS 页面,不打包另一套 DSH 前端;App 与手机浏览器获得相同的 DSH 功能,以及电脑端配置的移动页面定制。
6
6
 
7
- 当前正式 App 为 **0.6.7**;构建号为 83。npm 插件与 Android App 独立编号、独立更新;插件升级不代表需要重新安装 APK。此次改进见 [0.6.7 更新](#067-更新)。
7
+ 当前正式 App 为 **0.7.0**;构建号为 85。npm 插件与 Android App 独立编号、独立更新;插件升级不代表需要重新安装 APK。此次改进见 [0.7.0 更新](#070-更新)。
8
8
 
9
9
  支持 Android 10 及以上系统。iOS 本地实验不属于已发布或受支持的客户端。
10
10
 
11
11
  ## 安装与配对
12
12
 
13
13
  1. 按[项目快速开始](../../README.md#快速开始)安装并启用插件。局域网配置可通过命令行或电脑端的 **移动访问** 面板完成。
14
- 2. 从 [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.7) 安装已签名 APK。正式版沿用相同发布签名,可原位升级并保留配对;不同签名的 Debug 包不能直接覆盖正式版,不要为绕过签名不匹配而卸载或清除数据。
14
+ 2. 从 [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0) 安装已签名 APK。原有 HTTPS 通道可选兼容版 `.apk`;arm64-v8a/x86_64 设备使用实验性 iroh 时选完整版 `-iroh.apk`。两包使用相同包名和正式签名,选一个原位升级即可保留配对;不同签名的 Debug 包不能直接覆盖正式版,不要为绕过签名不匹配而卸载或清除数据。
15
15
  3. 在电脑 **移动访问 → 局域网访问** 中生成密钥/配对链接,或配置远程通道并生成远程配对二维码。在 App 选择对应方式,扫码或粘贴链接。
16
16
  4. 为电脑命名。每条局域网或远程配对单独保存;手机无需安装 cpolar、Cloudflare 或 Tailscale App。
17
17
 
@@ -36,6 +36,16 @@ DeepSeek Harness 是这个社区维护的 Android WebView App 的显示名称。
36
36
 
37
37
  删除本机记录会移除保存的设备令牌和固定 CA,不等于撤销电脑授权或清除所有 WebView 短期 Cookie。需要立即终止访问时,请在电脑的 **移动访问** 中撤销设备。Android“清除应用数据”会删除全部配对和网页数据,不是普通重连的处理步骤。
38
38
 
39
+ ## 0.7.0 更新
40
+
41
+ App 0.7.0/构建 85 在完整版中增加可选的实验性 iroh 配对和原生传输,配合插件 0.7.0 及以上版本使用。兼容版不含原生库,保留现有 HTTPS 通道并继续支持 32 位设备。旧版更新入口默认下载兼容版;使用 iroh 时请主动选择完整版。两包均保留设备列表、HTTPS 配对和原有正式签名。独立实验 App 的记录不会自动迁移。
42
+
43
+ iroh 默认关闭。电脑端安装经过校验的组件后,在 **移动访问 → 远程 → iroh(实验性)** 中生成专属配对二维码。直连和中继可用性取决于两端网络,手机浏览器不能直接使用这条传输,详见 [iroh 使用说明](../../docs/IROH.md)。
44
+
45
+ ## 0.6.8 更新
46
+
47
+ App 0.6.8/构建 84 让首次页面下载沿用既有连接总期限,不再被较短页面计时器打断后自动重新下载。首次加载确实失败时保留明确重试;已经正常打开的页面仍可恢复连接,TLS 验证和取消能力不变。这项原生修复需要升级 App,不能仅靠更新插件获得。
48
+
39
49
  ## 0.6.7 更新
40
50
 
41
51
  App 0.6.7/构建 83 配合插件 0.6.16 及以上版本,新增可选的同电脑局域网/远程切换,默认仍为手动。分别配对两个入口后,在设备列表设置中选择切换方式;符合条件的同会话纯文本草稿可随自动切换迁移,但这不是完整页面状态迁移,详见[切换规则](#同电脑自动连接)。
@@ -147,12 +157,27 @@ Set-Location apps/mobile/android
147
157
 
148
158
  Debug APK 位于 `app/build/outputs/apk/debug/app-debug.apk`。正式发布沿用只保存在仓库 Secrets 中的签名密钥,本地未签名 Release 构建或 Debug 安装不能替代正式签名核验。
149
159
 
160
+ 每次构建默认自带实验性 iroh 传输。需要 Rust 1.99.1(含 `aarch64-linux-android` 与 `x86_64-linux-android` 目标)与明确指定的 NDK:
161
+
162
+ ```powershell
163
+ Set-Location apps/mobile/android
164
+ ./gradlew.bat :app:assembleDebug -PirohNdk=C:/Android/Sdk/ndk/25.2.9519653 -x :app:lintAnalyzeDebugUnitTest -x :app:lintAnalyzeDebugAndroidTest
165
+ ```
166
+
167
+ 传 `-PirohNative=false` 可走免工具链的快速通道,构建的是原 HTTPS 外壳:没有 iroh 配对入口,`IrohNative` 会报告自身不可用。传输库生成在 `app/build/generated/iroh/jniLibs/` 下,永不提交。启用原生库的构建不改变包名与既定正式签名;实验阶段的独立 alpha 签名在这里不使用。
168
+
169
+ 原生构建还会从固定提交的官方 Maven 归档引入与 `native/Cargo.lock` 匹配的 JVM TLS 校验组件。必须保留其 JNI/Proguard 规则,仅打包 `.so` 不足以完成接入。APK 验证会检查 Debug 和压缩后的 Release 是否保留所需 JVM 类和原生入口名称。
170
+
150
171
  当前源码的 Debug 构建使用包名 `io.github.sayach.dshmobile.debug` 与 `-debug` 版本后缀,可与正式 App 并存,存储和配对彼此独立。它不会升级或迁移旧版无后缀 Debug 应用;切换包名时应保留旧应用和数据,不要为此卸载或清除。Release 构建继续使用 `io.github.sayach.dshmobile` 与既定正式签名。
151
172
 
152
- 已核验的正式版本为 [Android 0.6.7](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.6.7),构建 83,SHA-256:`919153244e6b84eb55c4701146f50454995330e080da9c91389e8816b2bd9b79`。下载的 APK 沿用正式发布签名及包名 `io.github.sayach.dshmobile`。旧版本历史集中在 [CHANGELOG](../../CHANGELOG.md)。
173
+ 已核验的正式版本为 [Android 0.7.0](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.0),构建 85。兼容版与完整版分别附有对应的 `.sha256` 校验文件;两个公开下载均沿用正式发布签名及包名 `io.github.sayach.dshmobile`。旧版本历史集中在 [CHANGELOG](../../CHANGELOG.md)。
153
174
 
154
175
  ## 验收与已知限制
155
176
 
177
+ - App 0.7.0 的两份公开 APK 均通过校验值、Manifest、正式签名、许可文本和对齐检查;完整版另检查两个 ABI 及保留的 JVM TLS/JNI 入口,兼容版确认没有原生库。此前的 arm64 开发构建有不依赖 ADB 转发的原生 iroh 网关/定制资源真机链路证据;最后补齐 JVM TLS 依赖后尚未新增真机公网中继回归,不能仅凭中继连接存在宣称数据已走中继。
178
+
179
+ - App 0.6.8 的公开 APK 已核验身份、校验值和既定正式签名。Debug 包同签名原位升级后可打开 DSH,并保留原设备记录;受控慢链路故障注入在配对前中断,不计为通过。
180
+
156
181
  - App 0.6.7 Debug 构建在 PJW110、Android 16、WebView 153 上,通过 USB 映射和固定 CA 的 HTTPS 连接隔离的 DSH 0.2.1-rc.2。真实自动接管保留同会话 Unicode 草稿,目标原生缩放/续期可用且不额外刷新;还通过确认取消、目标加载中按返回取消与迟到响应、原生续期取消、键盘返回和选择器取消。临时配对与映射已清理;这不是实际 Wi-Fi/蜂窝切网,也不是正式签名 APK 的装机验收。
157
182
  - 连接控制的开发包使用 Debug 元数据 0.6.4/构建 80,在 PJW110、Android 16、Google WebView 153.0.8010.36 上,通过 USB 和固定 CA 的 HTTPS 连接隔离的 DSH 0.2.0-rc.2/插件 0.6.10。检查了配对/启动/已保存连接取消、系统返回、手动失败收尾,以及停止原生恢复后从失效页面返回;暂停模块响应时也验证了提前露出网页、非按钮区域触摸透传、取消和放行后完成。原配对保留,临时 QA 记录已清理。
158
183
  - App 0.6.4 的 Debug 构建在同一 WebView 中覆盖文档替换/刷新、拒绝旧选择、接收受控 PNG 字节并形成已解码草稿预览;还检查了暂停导航及 HTTP 204 后选择器的可用性。更早的检查覆盖模型菜单返回、旋转保留草稿/引用/图片、已知撤销、重新配对、图标选择与列表顺序,均未发送模型请求。
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.6.7",
3
- "versionCode": 83,
4
- "releaseTag": "android-v0.6.7"
2
+ "version": "0.7.0",
3
+ "versionCode": 85,
4
+ "releaseTag": "android-v0.7.0"
5
5
  }
@@ -8,6 +8,8 @@ Choose which client components the dedicated mobile page loads. This does not un
8
8
 
9
9
  Selection applies to whole module IDs, not individual buttons, cards or sidebars inside a module. A plugin may register several modules or share/depend on a module with other features. A feature not delivered as an optional client module may not be independently removable here.
10
10
 
11
+ The selection covers client modules only. A plugin may also inject page-level styles from the host into every page — wallpapers and whole-page palettes are the usual case. That content is not a client module, so deselecting one does not remove it: disable the whole plugin, or let the plugin adapt itself to the mobile layout. See [skins and mobile layout](SKIN_COMPATIBILITY.en.md) for skin diagnosis.
12
+
11
13
  ## Computer defaults and this device
12
14
 
13
15
  - On the **computer: Settings → General → Mobile page modules → Manage**, set defaults for this computer's mobile access. Enable a LAN or remote access entry first so the current DSH module catalog can be read.
@@ -8,6 +8,8 @@
8
8
 
9
9
  选择作用于完整模块 ID,不能分别隐藏同一模块中的按钮、卡片或侧栏。一个插件可能注册多个模块,也可能与其他功能共用或依赖某个模块;未拆为可选客户端模块的功能不一定能在这里单独关闭。
10
10
 
11
+ 模块选择只作用于客户端模块。插件还可以在服务端把样式直接注入每个页面——典型就是皮肤壁纸和整页配色;这类内容不是客户端模块,取消勾选不会让它消失。要彻底关掉请禁用整个插件,或由插件自己按移动布局适配。皮肤类插件的排查见[皮肤与移动布局](SKIN_COMPATIBILITY.md)。
12
+
11
13
  ## 电脑默认与本设备选择
12
14
 
13
15
  - **电脑端:设置 → 通用设置 → 移动页面模块 → 管理**,修改此电脑的移动访问默认加载项。先开启一个局域网或远程访问入口,才能读取当前 DSH 的模块目录。
@@ -2,6 +2,8 @@
2
2
 
3
3
  [中文指南](CLOUDFLARE_TUNNEL.md)
4
4
 
5
+ > Already running cloudflared or a system service? Use the [own-reverse-proxy mode](SELF_HOSTED_ORIGIN.en.md#when-you-already-run-cloudflared-yourself) and route that tunnel to the protected HTTP backend shown in the panel, without another component installation or a tunnel Token stored by the plugin. The instructions below describe the separate plugin-managed option.
6
+
5
7
  The built-in cloudflared provider runs in one of two modes, chosen in the panel under **Mobile access → Remote → cloudflared → Tunnel type**:
6
8
 
7
9
  | | Quick tunnel (default) | Named tunnel |
@@ -2,6 +2,8 @@
2
2
 
3
3
  [English guide](CLOUDFLARE_TUNNEL.en.md)
4
4
 
5
+ > 已经自己运行 cloudflared 或使用系统服务?可改用[自备反向代理模式](SELF_HOSTED_ORIGIN.md#已经自己运行-cloudflared-时),将现有隧道指向面板展示的受保护 HTTP 后端,无需再安装组件或在插件保存隧道 Token。以下步骤介绍由插件管理 cloudflared 的另一种方式。
6
+
5
7
  内置的 cloudflared 通道有两种模式,在面板 **移动访问 → 远程 → cloudflared → 隧道类型** 中切换:
6
8
 
7
9
  | | 快速隧道(默认) | 命名隧道 |
@@ -0,0 +1,44 @@
1
+ # Experimental iroh connection
2
+
3
+ iroh replaces public domains and tunnel accounts with an encrypted direct connection (relay fallback when direct fails): the phone finds the computer's cryptographic identity first, then traffic returns to the loopback gateway. You need no domain, port mapping, or separate HTTPS tunnel.
4
+
5
+ > Plugin 0.7.0 and the full App 0.7.0 integrate the computer provider, pinned TLS, pairing UI and Android native transport. The feature is off by default and remains experimental. Direct connectivity, relay use and speed depend on both networks; availability on every campus, corporate or carrier network is not guaranteed.
6
+ > The design lives in the companion's [integration seam](https://github.com/saya-ch/dsh-mobile-iroh/blob/main/docs/INTEGRATION_SEAM.md).
7
+
8
+ ## Prerequisites
9
+
10
+ - Windows x64 or Linux x64 (the only published sidecar targets).
11
+ - Android 10+ with the full `-iroh.apk`, supporting arm64-v8a and x86_64. The ordinary `.apk` is the compatibility build without native libraries: it retains existing HTTPS connections and serves older automatic-update links, but cannot use iroh. Mobile browsers cannot connect directly through iroh either. Both APKs have the same application ID and official signer; install only one.
12
+ - Press **Install official component** once to fetch the sidecar: the plugin downloads the pinned `dsh-mobile-iroh 0.1.0-alpha.1` release per platform (about 15 MB on Windows x64, 24 MB on Linux x64), verifies its SHA-256, and stores it in the plugin private directory. An installed companion plugin with a verified copy is reused instead, with no download. The Rust source lives with the main repository under `native/iroh-host` (shared core under `native/iroh-core`) and is built per platform in CI.
13
+ - DSH Mobile stays enabled; the iroh channel is off by default and never disturbs LAN or other remote channels.
14
+
15
+ ## Usage
16
+
17
+ 1. Under **Mobile access → Remote**, pick `iroh (Experimental)`.
18
+ 2. Press **Prepare iroh → Install official component** (labelled with the download size): the first run downloads and verifies the sidecar; later runs reuse the verified copy. A hash mismatch or an unsupported platform stops here with a reason instead of a half-started channel. Merely switching the channel on never triggers a download.
19
+ 3. Turn remote access on: the plugin resolves the endpoint identity, issues the endpoint gateway certificate (own CA, 90-day leaf, 30-day renewal headroom), starts a dedicated gateway, launches the sidecar, and waits for `ready`. `ready` means the sidecar is connected and the gateway serves its loopback socket.
20
+ 4. Press **Generate iroh pairing QR code** and scan it with the full App. The descriptor binds the sidecar's six-digit code, the Gateway's one-time token and pinned CA. Generating another descriptor replaces the previous pairing window; pairing a phone redeems the Gateway token through the normal pair endpoint over iroh.
21
+ 5. Switching off or switching providers stops the owned process and Gateway without deleting stored pairings. The independent App has a different package identity; its Keystore credentials are not automatically migrated into this App.
22
+
23
+ ## Security boundaries
24
+
25
+ - The sidecar proxies only to a `127.0.0.1`/`::1` loopback gateway with end-to-end TLS; commands and events are versioned, bounded, and rejected closed on unknown fields.
26
+ - A rotated fingerprint, replaced binary, or moved file fails verification and parks the channel at `unavailable` instead of silently running a stale one.
27
+ - Transport revocation and device-token revocation are separate authorizations; their unified management is Phase 2 work. Computer-side revocation keeps working through the existing device management.
28
+
29
+ ## Troubleshooting
30
+
31
+ Store the iroh identity and certificates in a directory tree writable only by the current user or trusted system accounts. DSH's default state under the Windows user profile is intended for this; custom locations also need private ancestors. Some AppData or shared locations grant other accounts write access and are rejected. Do not loosen ACLs, delete real identities or move state into untrusted storage to bypass the check. Back up and preserve existing identity files.
32
+
33
+ Before a component release, verify first use with the exact catalog-pinned executable, not only a locally compiled host or a directory initialized by hand. The controller invokes `tls-prepare` because `id` only reads existing identity state. On Windows, `DSH_IROH_PINNED_FIRST_USE=<verified executable> npx vitest run tests/iroh-pinned-first-use.test.ts` checks initialization, reuse and corruption refusal in owned private storage. A failure blocks component acceptance; do not loosen directory ACL checks or replace real identities to make it pass.
34
+
35
+ | Symptom | Meaning |
36
+ | --- | --- |
37
+ | `iroh_companion_missing` | Nothing installed yet: press Install first, or point `DSH_MOBILE_IROH_COMPANION` at a companion absolute path to reuse |
38
+ | `iroh_sidecar_invalid` | An installed file was modified; reinstalling overwrites it in place, or reinstall the companion for a damaged companion copy |
39
+ | `iroh_platform_unsupported` | No sidecar is published for this OS/architecture |
40
+ | `iroh_identity_invalid` / `iroh_identity_failed` | Check private permissions on the state directory and its ancestors and check for damaged identity files, preserving originals. `id` reads an existing identity; first use invokes `tls-prepare`, not copying or deleting an identity |
41
+ | `iroh_start_timeout` | Inspect iroh errors in the DSH log and network connectivity, and verify that the pinned component runs; repeated pairing is not a substitute for process diagnosis |
42
+ | Channel `ready` but no phone connects | Check that the App is the full build, the device supports a packaged ABI and the descriptor is fresh. Computer readiness does not establish phone connectivity; a relay-service connection alone does not establish that data uses the relay |
43
+
44
+ Chinese version: [IROH.md](IROH.md).
package/docs/IROH.md ADDED
@@ -0,0 +1,44 @@
1
+ # iroh 实验性连接
2
+
3
+ iroh 用加密直连(打不通时走中继)代替公网域名和隧道账号:手机先找到电脑的加密身份,再把流量送回本机网关。你不需要准备域名、端口映射或另一套 HTTPS 隧道。
4
+
5
+ > 插件 0.7.0 和 App 0.7.0 完整版整合电脑端通道、固定 TLS、配对界面和 Android 原生传输。功能默认关闭,仍标记为实验性;能否直连、是否经过中继及连接速度取决于两端网络,不保证在所有校园网、企业网或运营商环境下可用。
6
+ > 相关设计见独立仓的[集成接缝](https://github.com/saya-ch/dsh-mobile-iroh/blob/main/docs/INTEGRATION_SEAM.md)。
7
+
8
+ ## 前提
9
+
10
+ - Windows x64 或 Linux x64(sidecar 只发布这两个目标)。
11
+ - Android 10+,安装含 iroh 的完整版 `-iroh.apk`,支持 arm64-v8a 和 x86_64。普通 `.apk` 是无原生库的兼容版,保留原有 HTTPS 连接并供旧版自动更新使用;不支持 iroh,也不支持手机浏览器直接接入。两个 APK 使用相同包名和正式签名,只需安装一个。
12
+ - 点 **安装官方组件** 一次下好 sidecar:插件从固定的 `dsh-mobile-iroh 0.1.0-alpha.1` 发行版按平台下载(Windows x64 约 15 MB,Linux x64 约 24 MB),校验 SHA-256 后放进插件私有目录;已装配套插件且副本校验通过时会直接复用,不再下载。Rust 源码随主仓在 `native/iroh-host`(公共 core 在 `native/iroh-core`)维护,CI 按平台构建校验。
13
+ - DSH Mobile 保持启用;iroh 通道默认关闭,不影响局域网和其他远程通道。
14
+
15
+ ## 使用
16
+
17
+ 1. 在 **移动访问 → 远程** 选择 `iroh(实验性)`。
18
+ 2. 点 **准备 iroh → 安装官方组件**(带下载大小):首次下载并校验 sidecar,通过才算就绪;再次点击会复用已校验的副本。哈希不对、平台不支持都会直接给出原因,不会启动半截通道。注意只是点开通道开关不会触发下载。
19
+ 3. 打开远程开关:插件依次解析端点身份、签发端点专属网关证书(自有 CA,90 天叶子、30 天提前续)、起专用网关、拉起 sidecar 进程并等待 `ready`。`ready` 表示 sidecar 已连接且网关在回环监听。
20
+ 4. 点 **生成 iroh 配对二维码**,用完整版 App 扫描。描述符绑定 sidecar 的 6 位码、网关的一次性 token 和固定 CA;再次生成会替换旧配对窗口,手机通过 iroh 上的普通 pair 接口核销网关 token。
21
+ 5. 关闭或切换通道会停止自有进程与网关,不删除已保存的配对。独立实验 App 的包名不同,其 Keystore 凭据不会自动迁移到本 App。
22
+
23
+ ## 安全边界
24
+
25
+ - sidecar 只允许代理到 `127.0.0.1`/`::1` 的回环网关,TLS 仍端到端;命令与事件都是版本化、定长、未知字段直接拒绝。
26
+ - 换指纹/换二进制/挪文件都会让校验失败并停在 `unavailable`,不会静默跑旧通道。
27
+ - 传输层撤销与设备 Token 撤销是两套授权,统一管理界面是 Phase 2 内容;电脑端撤销仍按现有设备管理生效。
28
+
29
+ ## 排障
30
+
31
+ iroh 身份和证书必须存放在仅当前用户或受信系统账户可写的目录树。Windows 默认的用户 profile 下 DSH 状态目录符合此用途;自定义状态位置时也要检查父目录权限。某些 AppData 或共享目录允许其他账户写入,会被拒绝;不要通过放宽 ACL、删除真实身份或移入不可信目录来绕过检查。已有身份应先备份并保留。
32
+
33
+ 组件发布前必须使用目录中固定的二进制验证首次启用,不能只测本地编译的 host 或手工初始化过的目录。控制器调用 `tls-prepare`,因为 `id` 只读取既有身份。Windows 可设置 `DSH_IROH_PINNED_FIRST_USE=<已校验的程序>` 后运行 `npx vitest run tests/iroh-pinned-first-use.test.ts`,检查私有测试目录中的初始化、复用与损坏拒绝。失败应阻止组件验收,不得通过放松目录 ACL 检查或替换真实身份来让测试通过。
34
+
35
+ | 现象 | 含义 |
36
+ | --- | --- |
37
+ | `iroh_companion_missing` | 还没点安装(或配套不在常规布局旁);先点安装官方组件,或用 `DSH_MOBILE_IROH_COMPANION` 指向配套绝对路径复用 |
38
+ | `iroh_sidecar_invalid` | 已装文件被改动过;重新点安装即可覆盖修复,配套副本损坏则重装配套 |
39
+ | `iroh_platform_unsupported` | 当前系统/架构没有 sidecar 发布 |
40
+ | `iroh_identity_invalid` / `iroh_identity_failed` | 先检查状态目录及父目录是否私有、已有身份是否损坏,保留原文件再排查;`id` 仅检查已有身份,首次创建使用 `tls-prepare`,不是靠复制或删除身份修复 |
41
+ | `iroh_start_timeout` | 查看 DSH 日志中的 iroh 错误及网络连接,确认固定组件可运行;不要反复重新配对来替代进程排查 |
42
+ | 通道 `ready` 但手机连不上 | 检查 App 是否为完整版、设备是否支持打包的 ABI,以及描述符是否有效;电脑就绪不等于手机已连通,连接中继服务也不等于数据一定经过中继 |
43
+
44
+ 英文版见 [IROH.en.md](IROH.en.md)。
@@ -116,6 +116,14 @@ Constrain overlays to their actual container and visible area, rather than using
116
116
 
117
117
  Add `env(safe-area-inset-*)` only where content really reaches a screen edge and the host has not already handled it, avoiding duplicate space. Save, Cancel and errors must remain visible or reachable by scrolling with the keyboard open. An independent scroll area should not move the page underneath.
118
118
 
119
+ ### Overlay layering and portals
120
+
121
+ The dedicated mobile shell uses `isolation:isolate` so its drawer and panels share a local stacking context. A positioned menu portalled directly to `document.body` with a positive `z-index` can paint above that shell; its value does not have to exceed the drawer's internal value. The stock-layout adapter retains its existing layer values.
122
+
123
+ This is not a guarantee that every body child outranks every dialog. Negative values, zero/auto paint order, ancestor stacking contexts, and the browser's top layer affect the result. Menus inside the shell remain constrained by their ancestors. Prefer the host's overlay facilities where available, and dismiss a menu when its owning panel closes or a modal takes focus. Do not globally raise third-party widgets or change DSH's dialog layers.
124
+
125
+ Verify actual visibility, focus and `document.elementFromPoint()` while the drawer, detail panel and settings are open, in narrow and wide layouts. The owned `smoke:plugin-portal-layers` fixture checks positive-z-index body menus and a top-layer dialog; it is not acceptance of every community plugin.
126
+
119
127
  ## Verification: what code checks, browsers and devices establish
120
128
 
121
129
  ### Structural checks
@@ -116,6 +116,14 @@ h('button', { className: 'icon-button', 'aria-label': label }, h(Icon, { 'aria-h
116
116
 
117
117
  只有确实延伸到屏幕边缘且未被宿主处理的区域才追加 `env(safe-area-inset-*)`,避免重复留白。键盘打开后,保存、取消和错误提示仍应可见或可滚动到达;独立滚动区域不应拖动背后的页面。
118
118
 
119
+ ### 浮层层级与 portal
120
+
121
+ 专用移动布局通过 `isolation:isolate` 将抽屉和面板限制在外壳自身的层叠上下文。直接挂载到 `document.body`、具有定位和正 `z-index` 的菜单可以显示在外壳上方,无需超过抽屉内部的层级值。原生布局适配器保留既有层级值。
122
+
123
+ 这不代表任意 body 子元素都能覆盖所有对话框。负值、零值/auto 的绘制顺序、祖先的层叠上下文以及浏览器顶层都会影响结果;外壳内部的菜单仍受祖先约束。优先使用宿主已有的浮层能力,所属面板关闭或模态层获得焦点时收起菜单,不要统一抬高第三方组件或修改 DSH 对话框层级。
124
+
125
+ 在窄屏与宽屏下,分别打开抽屉、详情和设置,检查实际可见性、焦点及 `document.elementFromPoint()` 命中。`smoke:plugin-portal-layers` 的受控场景检查正层级 body 菜单和浏览器顶层对话框,不代表所有社区插件均已验收。
126
+
119
127
  ## 验证:代码检查、浏览器与真机分别证明什么
120
128
 
121
129
  ### 结构检查
package/docs/README.md CHANGED
@@ -13,6 +13,7 @@
13
13
  | 复用已经运行的 frps,不自动修改服务器 | [接入既有 frps](ATTACH_EXISTING_FRPS.md) | [Existing frps](ATTACH_EXISTING_FRPS.en.md) |
14
14
  | 复用 Lucky、Nginx 或 Caddy 的公开 HTTPS 入口 | [自有反向代理](SELF_HOSTED_ORIGIN.md) | [Own reverse proxy](SELF_HOSTED_ORIGIN.en.md) |
15
15
  | 由插件安装 Caddy 并管理 HTTPS 证书(0.6.9 起) | [托管 Caddy](CADDY_MANAGED.md) | [Managed Caddy](CADDY_MANAGED.en.md) |
16
+ | iroh 加密直连实验通道 | [iroh 实验通道](IROH.md) | [iroh experimental channel](IROH.en.md) |
16
17
  | 页面加载慢、实时连接反复重连或长操作超时 | [慢链路与重连](SLOW_CONNECTIONS.md) | [Slow links and reconnection](SLOW_CONNECTIONS.en.md) |
17
18
  | 了解输入栏换行、附加控件与触摸目标 | [移动输入栏](MOBILE_COMPOSER_TOOLBAR.md) | [Mobile composer](MOBILE_COMPOSER_TOOLBAR.en.md) |
18
19
  | 保留电脑皮肤,排查移动页面的背景与可读性 | [皮肤与移动布局](SKIN_COMPATIBILITY.md) | [Skins and mobile layout](SKIN_COMPATIBILITY.en.md) |
@@ -53,6 +53,31 @@ Select **Save and start backend**. An active backend reloads its settings. The p
53
53
 
54
54
  For a separate proxy host, configure routing and a firewall rule limited to its actual private source yourself. This provider does not change the firewall.
55
55
 
56
+ ### When you already run cloudflared yourself
57
+
58
+ If you already configured a named tunnel the official way (`cloudflared tunnel`, possibly as a systemd unit, a launchd job or a Windows service), **you do not need the plugin to install a second copy, and you do not need to store a tunnel Token in it**. Use the own-reverse-proxy provider above and point your existing tunnel at the plugin's HTTP backend:
59
+
60
+ 1. In **Mobile access → Remote → Self-hosted → Own reverse proxy**, fill in: the public HTTPS address as your tunnel's public hostname (for example `https://dsh.example.com`), the private listen IP as `127.0.0.1`, an unused backend port (default `3444`), and the allowed source as `127.0.0.0/8`.
61
+ 2. Select **Save and start backend** and copy the HTTP backend address the panel shows.
62
+ 3. For a locally managed tunnel, update the matching `ingress` entry's `service` while keeping your existing tunnel identity, credentials and other routes. This is an excerpt, not a replacement configuration:
63
+
64
+ ```yaml
65
+ tunnel: <your tunnel ID>
66
+ ingress:
67
+ - hostname: dsh.example.com
68
+ service: http://127.0.0.1:3444
69
+ - service: http_status:404
70
+ ```
71
+
72
+ 4. Apply the change using your existing deployment procedure, restarting the service if required. For a dashboard-managed tunnel, edit the public hostname's service in Cloudflare instead of creating a local configuration file. **The plugin never starts, stops, reloads or removes that service, and never reads its configuration or Token.**
73
+
74
+ The split is deliberate: **you own the tunnel, DNS and public certificate; the plugin owns device pairing and DSH authentication.** The backend still enforces device pairing, exact Host/Origin checks and CSRF, so pointing a tunnel at it does not expose a bare DSH to the internet.
75
+
76
+ Two things to watch:
77
+
78
+ - **Avoid the port clash.** The plugin's own cloudflared component also defaults to `3444`. Only one remote provider should run at a time; stop the plugin-managed one before switching, or pick a different port here.
79
+ - **Use the HTTP backend address shown by the panel.** The original DSH Web port (which may differ from `3080`) is not this protected backend. The LAN HTTPS entry (commonly `3443`) has separate trust and pairing and is not the HTTP backend for this mode; do not assume that the panel rejects every incorrect external tunnel target.
80
+
56
81
  ### Nginx and IPv6
57
82
 
58
83
  The phone's public IPv6 connection to Nginx and Nginx's HTTP connection to DSH Mobile are separate connections. **An IPv6 public entry does not require an IPv6 backend.** On the same computer, Nginx can accept public IPv6 and forward to `http://127.0.0.1:3444`; the source CIDR remains IPv4 loopback. For an explicit `::1` backend, use `http://[::1]:3444` and `::1/128` instead.