dsh-mobile 0.8.7 → 0.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.8.9 - 2026-11-14
6
+
7
+ - Copy a file path by tapping it on touch devices: the preview header's path bar responds to a tap by copying the path the element shows — resolved through the titled ancestor, so taps landing on the nested directory/name spans still copy — and confirms with a bottom toast that stays visible at landscape-phone and tablet widths, where the older drawer toasts stay hidden. Delivered-file cards stay a pure open action, so opening a file never replaces the clipboard. The gate is the shared touch predicate, so desktop clicks never copy and the stock context menu is untouched; inside the changes-review pane the header keeps opening the file switcher. When the async clipboard API is missing (plain-HTTP tailnet origins) or rejects, a rendered off-screen textarea with `execCommand` provides the fallback, restoring focus, selection and scroll afterwards; a failed copy reports a localized failure toast instead of staying silent, and a language rebind never stacks listeners or toasts.
8
+ - Answer a peer outside every trusted source network with its own error instead of a generic `forbidden`: the external-request trust check now returns HTTP 403 `{"error":"source_network_untrusted"}` for an untrusted source address, while a foreign Host or Origin keeps the existing `forbidden`. A pairing client can then tell "this network is not trusted here" apart from "the one-time code expired" — two failures a phone on a routed campus or VPN network cannot currently distinguish, which sends users into regenerating a QR code that was never the problem. The App half that renders the distinct message ships with the next Android release. Thanks @fgql for the reproduction in [#422](https://github.com/saya-ch/dsh-mobile/issues/422).
9
+ - Keep stock fixed-position panels out of the drawer's clip: the mobile drawer no longer leaves a resting transform on its children, so a stock `position: fixed` surface — the Cordis plugin panel and other upstream overlays — stays anchored to the viewport instead of being clipped by the drawer (issue [#413](https://github.com/saya-ch/dsh-mobile/issues/413)).
10
+ - Add the portable Windows client source: a WPF/WebView2 shell that pairs through the same Mobile gateway, validates the pinned CA and supports the iroh sidecar path, documented in [apps/windows/README.md](apps/windows/README.md). It is merged into main but **not part of any release yet and not accepted on real Windows**, so it must not be presented as a shipped platform. Thanks @bvbhu for the implementation in [#403](https://github.com/saya-ch/dsh-mobile/pull/403).
11
+
12
+ ## 0.8.8 - 2026-11-12
13
+
14
+ - Restore Web Push on DSH 0.2.2-rc.2, which removed the `roots`/`isOwnedBy` ownership walk the public push host required: when the registry no longer exposes it, ownership comes from the durable Session header instead — `origin: 'subagent'` plus its `parentSession` ancestry, bounded and stopping at a missing parent — while hosts that still expose the walk keep the previous path and the same root-targeting and child-suppression rules. The packed push lanes and the Web Push guides cover rc.2 again. Thanks @chintoleung for the report in [#407](https://github.com/saya-ch/dsh-mobile/issues/407) and the fix in [#408](https://github.com/saya-ch/dsh-mobile/pull/408).
15
+ - Carry a bounded title and body with task-completion events: the Session display title and the turn's first non-empty assistant line, each bounded by code point (80 and 200) and dropped as a pair when either half looks like a credential, so the App never receives one without the other. The page keeps its own notification unless the installed App reports `enabled`, `connected` and `canPost` at the same time, so an older App, a disconnected service or a blocked notification channel never swallows the alert; questions stay page-only. The App-side halves (announced text, one notification per Session and turn sharing a tag and id, service-owned delivery) ship with the next Android release. Thanks @owenzhao for the measurement and proposal in [#400](https://github.com/saya-ch/dsh-mobile/issues/400).
16
+ - Add an opt-in, off-by-default reading mode to the dedicated Mobile layout ([#194](https://github.com/saya-ch/dsh-mobile/issues/194)) — thanks [@rushpixy](https://github.com/rushpixy) for the report and [@lnuxe](https://github.com/lnuxe) for the implementation in [#384](https://github.com/saya-ch/dsh-mobile/pull/384): scrolling down a long conversation collapses the composer editor so the reading area is unobstructed, while the card keeps the upstream Send/Stop row. Tapping the card, focusing the composer, opening the software keyboard, or scrolling back up about 80px restores it, and it never collapses while a draft exists, a submission is in flight, or a reply is streaming. It samples the conversation scroller `[data-conversation-scroll]` rather than the document, and the Settings → General switch is shared between the settings and layout bundles through the persisted flag, so it applies without a reload.
17
+ - Stop arming a push wake timer while every concurrent send slot is busy: a completion callback re-kicks delivery as slots free, so a saturated queue no longer wakes the device for sends it cannot start. Thanks @chintoleung for [#402](https://github.com/saya-ch/dsh-mobile/pull/402).
18
+
5
19
  ## 0.8.7 - 2026-11-11
6
20
 
7
21
  - Add an opt-in, off-by-default session prefetch for the dedicated Mobile layout. After a session switch settles, the page issues one bounded, read-only `session/projections` request for the session the user just left (the most likely switch-back target), so a follow-back hits DSH session-query's prepared-session cache warm instead of re-parsing the whole log. Guarded by a per-session cooldown and a bounded timeout; failures are silent and are not retried. It stays disabled until the new "Prefetch the session you just left" switch in Settings → General is turned on; the choice is persisted and applies without a reload. Thanks @eeeggplant for the measurement and proposal in [#291](https://github.com/saya-ch/dsh-mobile/issues/291), and @lnuxe for the implementation in [#383](https://github.com/saya-ch/dsh-mobile/pull/383).
@@ -12,13 +26,21 @@ Notable changes are recorded here. GitHub Releases provide the downloadable pack
12
26
  - Declare a plugin icon so DSH shows the DSH Mobile picture in its plugin metadata instead of the default plugin glyph. The shipped `assets/brand/plugin-icon.png` is package-relative, within DSH's 256 KiB icon limit, and read without evaluating plugin code.
13
27
  - The page-side halves of the background-reminder status and in-place notification navigation ship in this plugin release; their native halves are prepared as Android 0.7.4 below and released separately. Android 0.7.3 remains the published App until then.
14
28
 
15
- ## Android 0.7.4 - Unreleased
29
+ ## Android 0.7.5 - 2026-11-14
30
+
31
+ - Show the plugin's own text in a background completion reminder: when the announced event carries the bounded title and body introduced in plugin 0.8.8, the lock-screen record uses the Session display name and the turn's first line, and falls back to the localized fixed strings when the event carries neither, so an older plugin behaves exactly as before. Each field is trimmed to a single line, stripped of control characters and bounded before use, and the text is never written to the log. Thanks @owenzhao for the measurement, the required landing points and the proposal in [#400](https://github.com/saya-ch/dsh-mobile/issues/400).
32
+ - Make the App the only delivery decision-maker for that record and stop reporting a delivery it could not perform: the service posts once per Session and turn — the same tag and the fixed notification id replace rather than add — and records the bounded stage `notify:blocked` instead of claiming success when notifications are disabled or the task channel is blocked. `notification.background.get` now also reports `canPost` (the OS-level permission and channel answer, not just stream health), which the page needs before it yields delivery to the App.
33
+ - Report a notification the page owns when the plugin yields: with plugin 0.8.8 the page stays silent only while `enabled`, `connected` and `canPost` are all true, so a revoked permission, a blocked channel, a reconnecting service or an older plugin keeps the page's own reminder instead of leaving the turn silent.
34
+ - Tell an untrusted source network apart from an expired pairing code: when the gateway answers HTTP 403 `{"error":"source_network_untrusted"}` — plugin 0.8.9 or later — the pairing dialog explains that the phone's network is outside the computer's trusted ranges and points at "Additional source networks", instead of claiming the one-time code expired. A plugin that still answers a bare `forbidden` keeps the previous message, so mixed versions behave exactly as before. Thanks @fgql for the reproduction in [#422](https://github.com/saya-ch/dsh-mobile/issues/422).
35
+ - Add a native Check for updates entry to the device-list settings: it reads the published App descriptor straight from GitHub — not through the paired gateway, so it still works while the computer is offline — compares the build number, reports that the App is current, or offers the matching Android release page after an explicit confirmation. Nothing is downloaded or installed automatically, a failed request only shows a retryable message, and an older plugin does not affect the check.
36
+
37
+ ## Android 0.7.4 - 2026-11-11
16
38
 
17
39
  - Cache the revision-addressed mobile page payload on the device, independently of the WebView's own HTTP cache. For a revalidated boot batch the App sends `If-None-Match` and serves the stored body after a 304; a revision-named plugin combo bundle is addressed by its ordered module list and revision and needs no round-trip. A body is stored only after its size and SHA-256 match the fetched bytes, a cache miss or any integrity, epoch or ownership failure falls back to the ordinary request, documents, API responses, credentials and non-revisioned assets never qualify, and clearing site data or removing the paired device clears the store. Thanks @LUgABeEEE for the implementation and the LAN measurements in [#350](https://github.com/saya-ch/dsh-mobile/pull/350).
18
40
  - Report the background reminder's real phase in its persistent notification — connecting, connected or not connected — and publish `connected`, `lastEventAt` and a bounded `lastError` stage through `notification.background.get`, so the page and a `DshMobileBg` logcat line can separate a credential-renewal, stream-open or notification-delivery failure without recording tokens or addresses.
19
41
  - Give background-service completion notifications a `dsh-task-bg-` tag so their origin is identifiable while page notifications keep `dsh-task-done-`, rebind the service to the newly active paired computer instead of retrying the previous Origin, and withdraw the opt-in when the active record cannot serve it, including an iroh pairing.
20
42
  - Open a warm notification tap in the live page instead of reloading it: the App invokes the page's in-place Session hook first and only falls back to route navigation when the page is not ready or cannot handle the route.
21
- - Prepared independently of the plugin release. The published App descriptor and download links remain on Android 0.7.3 until a separately verified signed 0.7.4 exists.
43
+ - Released independently of the plugin: plugin 0.8.7 carries the page-side halves and shipped while Android 0.7.3 was the current App, and this App release is published as `android-v0.7.4` with the established signer. The plugin release notes keep the App that was published when they shipped; the download links in this repository point at the verified 0.7.4 APKs.
22
44
 
23
45
  ## 0.8.6 - 2026-11-10
24
46
 
package/CONTRIBUTORS.md CHANGED
@@ -4,6 +4,22 @@ GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/co
4
4
 
5
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. The repository maintainer and automated dependency updates remain visible in GitHub's history.
6
6
 
7
+ ## 下一版本贡献 / Contributions for the next release
8
+
9
+ 本节随下一个版本更新 / Updated with the next release.
10
+
11
+ ## 0.8.9 贡献 / Contributions in 0.8.9
12
+
13
+ 感谢 [@bvbhu](https://github.com/bvbhu) 在 [#403](https://github.com/saya-ch/dsh-mobile/pull/403) 提供便携 Windows 客户端(已合入 main,尚未随版本发布);感谢 [@chintoleung](https://github.com/chintoleung) 在 [#420](https://github.com/saya-ch/dsh-mobile/pull/420) 实现移动页路径点按复制;感谢 [@fgql](https://github.com/fgql) 在 [#422](https://github.com/saya-ch/dsh-mobile/issues/422) 提供来源网段配对失败的完整复现。
14
+
15
+ Thanks [@bvbhu](https://github.com/bvbhu) for the portable Windows client in [#403](https://github.com/saya-ch/dsh-mobile/pull/403) (merged into main, not released yet); thanks [@chintoleung](https://github.com/chintoleung) for the tap-to-copy path implementation in [#420](https://github.com/saya-ch/dsh-mobile/pull/420); thanks [@fgql](https://github.com/fgql) for the complete reproduction of the source-network pairing failure in [#422](https://github.com/saya-ch/dsh-mobile/issues/422).
16
+
17
+ ## 0.8.8 贡献 / Contributions in 0.8.8
18
+
19
+ 感谢 [@chintoleung](https://github.com/chintoleung) 在 [#407](https://github.com/saya-ch/dsh-mobile/issues/407) 报告 DSH 0.2.2-rc.2 下 Web Push 不可用,并提供 [#408](https://github.com/saya-ch/dsh-mobile/pull/408) 的兼容修复与 [#402](https://github.com/saya-ch/dsh-mobile/pull/402) 的推送调度修复;感谢 [@owenzhao](https://github.com/owenzhao) 在 [#400](https://github.com/saya-ch/dsh-mobile/issues/400) 提供实测与落点;感谢 [@rushpixy](https://github.com/rushpixy) 在 [#194](https://github.com/saya-ch/dsh-mobile/issues/194) 提出阅读体验问题,[@lnuxe](https://github.com/lnuxe) 提供 [#384](https://github.com/saya-ch/dsh-mobile/pull/384) 的阅读模式实现。
20
+
21
+ Thanks [@chintoleung](https://github.com/chintoleung) for reporting Web Push being unavailable on DSH 0.2.2-rc.2 in [#407](https://github.com/saya-ch/dsh-mobile/issues/407), and for the compatibility fix in [#408](https://github.com/saya-ch/dsh-mobile/pull/408) and the push-scheduling fix in [#402](https://github.com/saya-ch/dsh-mobile/pull/402); thanks [@owenzhao](https://github.com/owenzhao) for the measurement and points in [#400](https://github.com/saya-ch/dsh-mobile/issues/400); thanks [@rushpixy](https://github.com/rushpixy) for the reading-experience report in [#194](https://github.com/saya-ch/dsh-mobile/issues/194), and [@lnuxe](https://github.com/lnuxe) for the reading-mode implementation in [#384](https://github.com/saya-ch/dsh-mobile/pull/384).
22
+
7
23
  ## 0.8.7 贡献 / Contributions in 0.8.7
8
24
 
9
25
  感谢 [@eeeggplant](https://github.com/eeeggplant) 在 [#291](https://github.com/saya-ch/dsh-mobile/issues/291) 提供会话切换重复加载的测量与预取提案,[@lnuxe](https://github.com/lnuxe) 通过 [#383](https://github.com/saya-ch/dsh-mobile/pull/383) 实现可选的会话预取;原作者提交保留,维护者补充独立开关、跨 bundle 的偏好同步和网关参数契约。感谢 [@owenzhao](https://github.com/owenzhao) 在 [#390](https://github.com/saya-ch/dsh-mobile/issues/390) 报告后台提醒不投递并持续提供设备侧排查信息,在 [#394](https://github.com/saya-ch/dsh-mobile/issues/394) 指出点击任务通知会整页重载;两个问题仍在确认中,本版只提供诊断与页面侧准备,不表示已修复。感谢 [@LUgABeEEE](https://github.com/LUgABeEEE) 在 [#350](https://github.com/saya-ch/dsh-mobile/pull/350) 提供网关到期连接正常关闭、认证失败分类,以及 App 端按修订号缓存页面资源的实现与测量。感谢 [@pakeh2866](https://github.com/pakeh2866) 在 [#389](https://github.com/saya-ch/dsh-mobile/issues/389) 报告文件预览后无法返回,促成第三方全屏宿主的返回键契约文档;宿主自身的修复不在本仓库。
package/README.en.md CHANGED
@@ -28,22 +28,22 @@
28
28
  <a href="#compatibility">Compatibility</a> ·
29
29
  <a href="docs/README.md">Documentation</a> ·
30
30
  <a href="#contributors">Contributors</a> ·
31
- <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.7">Release notes</a> ·
31
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.8">Release notes</a> ·
32
32
  <a href="README.md">简体中文</a>
33
33
  </p>
34
34
 
35
- > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
35
+ > DSH Mobile is a DeepSeek Harness community plugin. The native app currently ships for Android; the repository also contains an **unpublished** [portable Windows client](apps/windows/README.md) (merged into main, not part of any release yet and not accepted on real Windows, so it is not a supported platform).
36
36
  >
37
37
  > **Using an iPhone or iPad?** Use Safari or [add DSH Mobile to your Home Screen as a web app (PWA)](<#iphone-and-ipad-home-screen-web-app-pwa>)—no native iOS download needed.
38
38
  >
39
- > **Current stable release: 0.8.7**. Add an opt-in session prefetch, close an expiring Gateway WebSocket normally with clearer authentication-failure categories, and prepare the background-reminder status and in-place notification open for Android 0.7.4; also update the plugin icon and iroh troubleshooting notes. Plugin and Android App releases remain independent; Android App 0.7.3 remains the published app and 0.7.4 ships separately. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.7) · [Full changelog](CHANGELOG.md).
39
+ > **Current stable release: 0.8.9**. Tap the preview path bar on touch devices to copy the full path; the gateway answers an untrusted source network with its own error; the drawer no longer clips stock fixed-position panels (#413); the repository adds the source of the unpublished portable Windows client. Plugin and Android App releases remain independent; Android App 0.7.5 is the current app release. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.9) · [Full changelog](CHANGELOG.md).
40
40
  >
41
41
  > **Version policy**: from plugin **0.6.2** the Android app and plugin ship as independent releases (the app was still 0.6.1 then), and the app has used its own version numbers since app **0.6.2**. Their numbers do not need to match, and a plugin update does not imply an app update. [Compatibility notes](#compatibility).
42
42
 
43
43
  <p align="center">
44
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.3/dsh-mobile-android-v0.7.3.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
45
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.3/dsh-mobile-android-v0.7.3.apk"><strong>Download Android app 0.7.3 (compatibility)</strong></a><br>
46
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.3/dsh-mobile-android-v0.7.3-iroh.apk">64-bit full APK (experimental iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.3">Release notes and checksums</a></sub>
44
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.5/dsh-mobile-android-v0.7.5.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>
45
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.5/dsh-mobile-android-v0.7.5.apk"><strong>Download Android app 0.7.5 (compatibility)</strong></a><br>
46
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.5/dsh-mobile-android-v0.7.5-iroh.apk">64-bit full APK (experimental iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.5">Release notes and checksums</a></sub>
47
47
  </p>
48
48
 
49
49
  DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. The full Android App also supports experimental iroh encrypted direct connections with relay fallback. The phone reaches the computer's sessions, Workspaces, messages and tools. The computer manages LAN and remote switches and pairing authorizations separately; the Android app lists paired computers together. The plugin does not modify DeepSeek Harness source.
@@ -57,6 +57,7 @@ It also lets you customize the phone from a DSH conversation: `/mobile <what you
57
57
  - **Continue DSH work from a phone**: the same sessions, Workspaces, messages, and tools, in real time.
58
58
  - **Customize the phone UI by talking to DSH**: request layout, interaction, or feature changes in a conversation; changed customization resources are usually picked up automatically.
59
59
  - **A dedicated touch layout**: session drawer, tool details, settings, question cards, and composer reorganized for phones. The sidebar remembers its list position within the page instead of jumping to the top after a session switch. The app follows the system locale (Chinese/English/Italian), plugin UI follows DSH's locale.
60
+ - **Tap a path to copy it**: on touch devices, tapping the path bar atop a file preview copies the path that element shows to the clipboard, with a brief bottom toast of the copied value (long values shorten on screen; the clipboard keeps the full text). Tapping replaces the current clipboard; delivered-file cards remain a pure open action (no copy); the changes-review file switcher is unaffected; desktop mouse clicks never copy.
60
61
  - **Several remote options**: Tailscale, cpolar, cloudflared quick/named tunnels, self-hosted FRP, your own reverse proxy, and experimental iroh without a domain or public port; Windows/Linux x64 can also let the plugin manage Caddy HTTPS and certificates.
61
62
  - **Pairing and multi-device**: pair once via QR code, link, or key; the same Origin renews automatically, while an address, certificate or listener change requires pairing again through **Change network** (while LAN access runs) or takes effect the next time you enable it; the app lists LAN and remote paired computers together, checks their reachability periodically, and lets you switch, re-pair, or delete a local record.
62
63
  - **One-click diagnostics and approval**: check versions, gateway, network interface, firewall, and the remote path with a redacted report; approve blocked third-party plugin connections per exact path.
@@ -114,7 +115,7 @@ Restart DSH, then search for **dsh-mobile** under **Settings → Plugin Market**
114
115
 
115
116
  Download the official Android APK using the link above. Then choose LAN or remote access in the [connection guide](#connection-guide); the phone needs no separate tunnel client. For browser access, including iOS, follow the steps below.
116
117
 
117
- Registry-installed plugins check for updates when the desktop UI loads and show “Update plugin” beside the access-panel title when a newer release is available. Restart DSH after installation. The app download entry shows the latest version; local development packages are not overwritten, and Android does not check for or push app-version updates.
118
+ Registry-installed plugins check for updates when the desktop UI loads and show “Update plugin” beside the access-panel title when a newer release is available. Restart DSH after installation. The app download entry shows the latest version; local development packages are not overwritten; Android 0.7.4 does not check for or push app-version updates, and from 0.7.5 the device-list settings offer a manual “Check for updates” entry that only opens the matching release page without downloading or installing anything automatically.
118
119
 
119
120
  ### iPhone and iPad: Home Screen web app (PWA)
120
121
 
@@ -395,7 +396,7 @@ flowchart LR
395
396
  DSH -->|"same workspace, sessions and event stream"| Phone
396
397
  ```
397
398
 
398
- Three layers: the Host face for discovery, pairing, HTTPS, loopback proxying, and extension registration; the Client face for the dedicated mobile layout and extension SDK; and the Android app for a narrow native bridge. The bridge uses `androidx.webkit` WebMessage, which verifies the exact top-level origin and main frame on every bounded message, and never uses `addJavascriptInterface`. The plugin does not rewrite source or webpage files in the DeepSeek Harness installation. Its mobile gateway serves the startup compatibility layer and dedicated layout per request; installation and removal use the plugin mechanism. The upstream DSH Web port defaults to 3080 and is configurable through `dsh web --port`.
399
+ Three layers: the Host face for discovery, pairing, HTTPS, loopback proxying, and extension registration; the Client face for the dedicated mobile layout and extension SDK; and the Android app for a narrow native bridge. The bridge uses `androidx.webkit` WebMessage, which verifies the exact top-level origin and main frame on every bounded message, and never uses `addJavascriptInterface`. The plugin does not rewrite source or webpage files in the DeepSeek Harness installation. Its mobile gateway serves the startup compatibility layer and dedicated layout per request; installation and removal use the plugin mechanism. The upstream DSH Web port defaults to 3080 and is configurable through `dsh web --port`. Reading mode (opt-in, off by default) collapses the composer editor while scrolling down a long conversation: the card and its Send/Stop row stay, and tapping the card, focusing the composer, opening the software keyboard, or scrolling back up about 80px restores it. It never collapses while a draft exists, a submission is in flight, or a reply is streaming. Enable it from Settings → General.
399
400
 
400
401
  Switching sessions tears down the client Session instance and its live stream. The dedicated layout ships an opt-in, off-by-default session prefetch ([#291](https://github.com/saya-ch/dsh-mobile/issues/291)): after a switch settles, it issues one bounded, read-only `session/projections` request for the session the user just left, so a follow-back hits DSH session-query's prepared cache instead of re-parsing the whole log. Guarded by a per-session cooldown and a bounded timeout, failures are silent and never disturb normal requests or live streams; the behavior stays disabled until the "Prefetch the session you just left" switch in Settings → General is turned on (off by default; the choice is persisted).
401
402
 
@@ -449,7 +450,9 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
449
450
 
450
451
  | DSH Mobile plugin | Verified DeepSeek Harness version |
451
452
  | --- | --- |
452
- | `0.8.7` | On the `0.2.2-rc.1` packed target, add an opt-in session prefetch, close an expiring Gateway WebSocket normally with clearer authentication-failure categories, and prepare the background-reminder status and in-place notification open for Android 0.7.4; also update the plugin icon and iroh troubleshooting notes. The Android App remains 0.7.3, with 0.7.4 released separately |
453
+ | `0.8.9` | Tap the preview path bar on touch devices to copy the full path; the gateway answers an untrusted source network with `source_network_untrusted`; the drawer no longer clips stock fixed-position panels (#413); the repository adds the source of the unpublished portable Windows client. The Android App is 0.7.5 |
454
+ | `0.8.8` | On the `0.2.2-rc.2` target, restore Web Push after the AgentRegistry ownership change, carry the Session title and a bounded summary with task-completion events and yield page notifications only when the App reports it can post, add an opt-in reading mode, and stop arming push wake timers while the send queue is at capacity. The Android App is 0.7.4 |
455
+ | `0.8.7` | On the `0.2.2-rc.1` packed target, add an opt-in session prefetch, close an expiring Gateway WebSocket normally with clearer authentication-failure categories, and prepare the background-reminder status and in-place notification open for Android 0.7.4; also update the plugin icon and iroh troubleshooting notes. The Android App is 0.7.4, with the device-side page cache and real background-reminder status |
453
456
  | `0.8.6` | On the `0.2.2-rc.1` packed target, forward paired third-party plugin `x-dsh-*` headers, keep the push subscription after a Disable, expose the trusted Host push-text service, and fix Windows firewall verification, iroh directory diagnostics and the LAN diagnostic scope. The Android App is 0.7.3 with opt-in background reminders |
454
457
  | `0.8.5` | Maintenance and performance update on the `0.2.2-rc.1` packed-DSH target: catalog cache, Desktop update targeting, CGNAT LAN discovery, firewall protection and a macOS permission notice. The Android App remains 0.7.2 |
455
458
  | `0.8.4` | Plugin maintenance update. The packed DSH test target remains `0.2.2-rc.1`, alongside existing compatibility checks. The upstream rc.1 npm CLI requires Node.js 24.9 or later |
package/README.md CHANGED
@@ -28,22 +28,22 @@
28
28
  <a href="#兼容性">兼容性</a> ·
29
29
  <a href="docs/README.md">文档</a> ·
30
30
  <a href="#贡献者">贡献者</a> ·
31
- <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.7">更新记录</a> ·
31
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.8">更新记录</a> ·
32
32
  <a href="README.en.md">English</a>
33
33
  </p>
34
34
 
35
- > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
35
+ > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 目前正式支持 Android;仓库另含一个**尚未发布**的[便携 Windows 客户端](apps/windows/README.md)(源码已合入 main,但未随任何版本发布,也未完成真实 Windows 验收,因此不作为已支持平台)。
36
36
  >
37
37
  > **使用 iPhone 或 iPad?** 可以用 Safari 访问,或[添加到主屏幕作为 Web App(PWA)使用](<#iphone-与-ipad主屏幕-web-apppwa>),无需下载原生 iOS App。
38
38
  >
39
- > **当前正式版本:0.8.7**。新增默认关闭的会话预取、网关到期连接正常关闭与认证失败分类,并为 Android 0.7.4 准备后台提醒的真实状态与通知就地打开;同时更新插件图标与 iroh 排障文档。插件与 Android App 独立更新;Android App 0.7.3 仍为当前正式版,0.7.4 将独立发布。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.7) · [完整更新记录](CHANGELOG.md)。
39
+ > **当前正式版本:0.8.9**。移动页支持点按预览路径条复制完整路径;网关对不受信任的来源网段返回可区分的错误码;抽屉不再裁剪上游固定定位面板(#413);仓库加入尚未发布的便携 Windows 客户端源码。插件与 Android App 独立更新;Android App 0.7.5 为当前正式版。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.8.9) · [完整更新记录](CHANGELOG.md)。
40
40
  >
41
41
  > **版本说明**:自插件 **0.6.2** 起,Android App 与插件改为独立发布(当时 App 仍为 0.6.1);App 自 0.6.2 起使用独立编号,版本号无需一致;插件升级不代表 App 需要同步升级。[兼容说明](#兼容性)。
42
42
 
43
43
  <p align="center">
44
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.3/dsh-mobile-android-v0.7.3.apk"><img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
45
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.3/dsh-mobile-android-v0.7.3.apk"><strong>下载 Android App 0.7.3(兼容版)</strong></a><br>
46
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.3/dsh-mobile-android-v0.7.3-iroh.apk">64 位完整版(含实验性 iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.3">版本说明与校验文件</a></sub>
44
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.5/dsh-mobile-android-v0.7.5.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>
45
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.5/dsh-mobile-android-v0.7.5.apk"><strong>下载 Android App 0.7.5(兼容版)</strong></a><br>
46
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/download/android-v0.7.5/dsh-mobile-android-v0.7.5-iroh.apk">64 位完整版(含实验性 iroh)</a> · <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.5">版本说明与校验文件</a></sub>
47
47
  </p>
48
48
 
49
49
  DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP、自有反向代理远程通道连接电脑;Android 完整版还支持实验性 iroh 加密直连与中继。手机可以继续使用电脑上的会话、工作区、消息和工具。电脑端分别启停局域网与远程访问、分别管理配对授权;Android App 统一显示已配对电脑。插件不修改 DeepSeek Harness 源码。
@@ -57,6 +57,7 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
57
57
  - **在手机上继续电脑端的工作**:同一份会话、工作区、消息和工具,实时同步。
58
58
  - **用对话定制手机端**:在 DSH 对话里提出布局、交互或功能需求;文件修改完成后,自定义资源通常会自动更新。
59
59
  - **专属触屏布局**:会话抽屉、工具详情、设置、提问卡片和输入栏都按手机重新组织;侧栏列表在本页内记住位置,切换会话再打开不会总跳回顶部。App 跟随系统语言(简/英/意),插件界面跟随 DSH 语言。
60
+ - **点按路径即可复制**:触屏设备上,点按文件预览顶部的路径条,就把该元素显示的路径复制到剪贴板,并在底部短暂提示所复制的值(过长时屏幕上省略显示,剪贴板中始终是完整文本)。点按会覆盖剪贴板当前内容;交付文件卡片仍仅用于打开预览(不复制);改动审查页顶部的文件切换箭头不受影响;桌面端鼠标点击不会复制。
60
61
  - **多种远程通道**:Tailscale、cpolar、cloudflared 快速/命名隧道、自建 FRP、自有反向代理,以及无需域名和公网端口的实验性 iroh;Windows/Linux x64 还可由插件托管 Caddy HTTPS 与证书。
61
62
  - **配对与多设备**:扫码、链接或密钥配对一次;同一 Origin 下自动续期,地址、证书或监听变化后需按「更换网络」重新配对(局域网运行时)或下次开启生效;App 在一个列表中显示局域网和远程配对的电脑,定期检测可达状态,并支持切换、重新配对或删除本地记录。
62
63
  - **一键诊断与放行**:检查版本、网关、网卡、防火墙和远程通道,生成脱敏报告;被拦截的第三方插件连接按确切路径一键放行。
@@ -114,7 +115,7 @@ dsh plugin --profile web add dshmarket
114
115
 
115
116
  从上方链接下载正式 Android APK。随后按[连接教程](#连接教程)选择局域网或远程访问;手机不需要安装额外的隧道客户端。包括 iOS 在内的浏览器访问方式见下文。
116
117
 
117
- 通过 npm 安装的插件会在桌面界面加载时检查新版本,有更新时在访问面板标题右侧显示“更新插件”,安装后需重启 DSH。App 下载入口展示最新版本;本地开发包不会被自动覆盖,Android App 不会主动检查或推送版本更新。
118
+ 通过 npm 安装的插件会在桌面界面加载时检查新版本,有更新时在访问面板标题右侧显示“更新插件”,安装后需重启 DSH。App 下载入口展示最新版本;本地开发包不会被自动覆盖;Android App 0.7.4 不会主动检查或推送版本更新,0.7.5 起在设备列表设置中提供手动「检查更新」,只打开对应发布页,不自动下载或安装。
118
119
 
119
120
  ### iPhone 与 iPad:主屏幕 Web App(PWA)
120
121
 
@@ -395,7 +396,7 @@ flowchart LR
395
396
  DSH -->|"同一工作区、会话和事件流"| Phone
396
397
  ```
397
398
 
398
- 插件包含三层:Host face 负责发现、配对、HTTPS、回环代理和扩展注册表;Client face 提供独立的移动布局与扩展 SDK;Android App 提供受限的原生 Bridge。Bridge 使用 `androidx.webkit` WebMessage,每条消息都校验精确顶层 Origin 和主 Frame,并限制消息大小;不使用 `addJavascriptInterface`。插件不改写 DeepSeek Harness 安装目录中的源码或网页文件;移动网关按请求提供启动兼容层与专用布局,安装和卸载通过插件机制完成。DSH Web 上游端口默认为 3080,可通过 `dsh web --port` 修改。
399
+ 插件包含三层:Host face 负责发现、配对、HTTPS、回环代理和扩展注册表;Client face 提供独立的移动布局与扩展 SDK;Android App 提供受限的原生 Bridge。Bridge 使用 `androidx.webkit` WebMessage,每条消息都校验精确顶层 Origin 和主 Frame,并限制消息大小;不使用 `addJavascriptInterface`。插件不改写 DeepSeek Harness 安装目录中的源码或网页文件;移动网关按请求提供启动兼容层与专用布局,安装和卸载通过插件机制完成。DSH Web 上游端口默认为 3080,可通过 `dsh web --port` 修改。阅读模式(可选,默认关闭):向下滚动阅读长会话时收起输入栏的编辑区,输入框卡片与发送/停止按钮保留;点按卡片、聚焦输入框、打开软键盘或向上回滚约 80px 即恢复。有草稿、提交中或回复生成中时不会收起。可在「设置 → 通用」中开启。
399
400
 
400
401
  会话切换后会重建客户端 Session 与实时流。插件提供默认关闭的会话预取(对应 [#291](https://github.com/saya-ch/dsh-mobile/issues/291)):切换稳定后,仅对刚离开的会话发起一次有界、只读的 `session/projections` 预热,让切回命中 DSH session-query 的已准备缓存,避免重新解析整个会话日志。该行为受每会话冷却与超时约束,失败静默,且绝不打扰正常请求或实时流;在「设置 → 通用」中的「预取刚离开的会话」开关显式开启后才生效(默认关闭,选择会持久化)。
401
402
 
@@ -449,7 +450,9 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
449
450
 
450
451
  | DSH Mobile 插件 | 已验证的 DeepSeek Harness 版本与范围 |
451
452
  | --- | --- |
452
- | `0.8.7` | 在 `0.2.2-rc.1` 打包目标上加入默认关闭的会话预取、网关到期连接正常关闭与认证失败分类,并为 Android 0.7.4 准备后台提醒真实状态与通知就地打开;同时更新插件图标与 iroh 排障文档。Android App 仍为 0.7.3,0.7.4 独立发布 |
453
+ | `0.8.9` | 移动页点按预览路径条复制完整路径;网关对不受信任的来源网段返回 `source_network_untrusted`;抽屉不再裁剪上游固定定位面板(#413);仓库加入尚未发布的便携 Windows 客户端源码。Android App 为 0.7.5 |
454
+ | `0.8.8` | 在 `0.2.2-rc.2` 上恢复 Web 推送(AgentRegistry ownership 变更),任务完成事件携带会话标题与有界摘要并在 App 报告可投递时让出页面通知,新增默认关闭的阅读模式,推送调度不再在容量满时唤醒定时器。Android App 为 0.7.4 |
455
+ | `0.8.7` | 在 `0.2.2-rc.1` 打包目标上加入默认关闭的会话预取、网关到期连接正常关闭与认证失败分类,并为 Android 0.7.4 准备后台提醒真实状态与通知就地打开;同时更新插件图标与 iroh 排障文档。Android App 为 0.7.4,新增设备端页面缓存与后台提醒真实状态 |
453
456
  | `0.8.6` | 在 `0.2.2-rc.1` 打包目标上透传已配对第三方插件的 `x-dsh-*` 请求头、修正网页推送停用语义、向受信 Host 插件开放推送文案接口,并修复 Windows 防火墙校验、iroh 目录诊断与局域网诊断口径。Android App 为 0.7.3,新增可选后台提醒 |
454
457
  | `0.8.5` | 插件维护与性能更新,继续使用 `0.2.2-rc.1` 的 DSH 打包验证目标;新增目录缓存、Desktop 更新目标修复、CGNAT 局域网识别、防火墙保护与 macOS 权限提示。Android App 仍为 0.7.2 |
455
458
  | `0.8.4` | 插件维护更新,继续使用 `0.2.2-rc.1` 的 DSH 打包验证目标,并保留既有版本检查。使用 rc.1 的 npm CLI 时,按上游要求使用 Node.js 24.9 或更新版本 |
@@ -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.7.3** (build 88). The npm plugin and Android App have independent versions: a plugin update does not automatically require another APK. See the [0.7.3 changes](#073-update).
7
+ The current stable app is **0.7.5** (build 90). The npm plugin and Android App have independent versions: a plugin update does not automatically require another APK. See the [0.7.4 changes](#074-update).
8
8
 
9
9
  This APK supports Android 10 or later. iPhone and iPad use the [Safari Home Screen web app and optional Web Push](../../docs/WEB_PUSH.en.md), not this Android package; no native iOS app is distributed.
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 a signed Android APK from [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.3). 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.
14
+ 2. Install a signed Android APK from [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.5). 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,24 @@ 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.5 update
40
+
41
+ Show the plugin's own text in a background completion reminder: when the announced event carries the bounded title and body introduced in plugin 0.8.8, the lock-screen record uses the Session display name and the turn's first line, and falls back to the localized fixed strings when the event carries neither, so an older plugin behaves exactly as before. Each field is trimmed to a single line, stripped of control characters and bounded before use, and the text is never written to the log.
42
+
43
+ Make the App the only delivery decision-maker for that record and stop reporting a delivery it could not perform: the service posts once per Session and turn — the same tag and the fixed notification id replace rather than add — and records the bounded stage `notify:blocked` instead of claiming success when notifications are disabled or the task channel is blocked. `notification.background.get` now also reports `canPost` (the OS-level permission and channel answer, not just stream health), which the page needs before it yields delivery to the App.
44
+
45
+ Report a notification the page owns when the plugin yields: with plugin 0.8.8 the page stays silent only while `enabled`, `connected` and `canPost` are all true, so a revoked permission, a blocked channel, a reconnecting service or an older plugin keeps the page's own reminder instead of leaving the turn silent.
46
+
47
+ Tell an untrusted source network apart from an expired pairing code: when the gateway answers HTTP 403 `{"error":"source_network_untrusted"}` (plugin 0.8.9 or later), the pairing dialog explains that the phone's network is outside the computer's trusted ranges and points at "Additional source networks", instead of claiming the one-time code expired. A plugin that still answers a bare `forbidden` keeps the previous message, so mixed versions behave exactly as before.
48
+
49
+ Add a native Check for updates entry to the device-list settings: it reads the published App descriptor straight from GitHub — not through the paired gateway — compares the build number, reports that the App is current, or offers the matching Android release page after an explicit confirmation. Nothing is downloaded or installed automatically, and a failed request only shows a retryable message.
50
+
51
+ Both APK variants retain the established signer and existing pairings; the notification text needs plugin 0.8.8 or later and the pairing message needs plugin 0.8.9 or later.
52
+
53
+ ## 0.7.4 update
54
+
55
+ Cache the revision-addressed mobile page payload on the device, independently of the WebView's HTTP cache: a revalidated boot batch can revalidate with `If-None-Match` and serve the stored body after a 304, and a revision-named plugin combo bundle is addressed by its ordered module list and revision. A body is stored only after its size and SHA-256 match, and a cache miss or any integrity, epoch or ownership failure falls back to the ordinary request; documents, API responses, credentials and non-revisioned assets never qualify, and clearing site data or removing the paired device clears the store. The persistent background-reminder notification now reports the real phase — connecting, connected or not connected — and publishes `connected`, `lastEventAt` and a bounded `lastError` stage through `notification.background.get` and a `DshMobileBg` logcat line, background-service completion notifications carry their own `dsh-task-bg-` tag, the service rebinds to the newly active paired computer instead of retrying the previous Origin, and the opt-in is withdrawn when the active record cannot serve it, including an iroh pairing. A tapped task notification now opens the notified Session inside the live page through the page's in-place hook, falling back to route navigation when the page is not ready or cannot handle the route. Both APK variants retain the established signer and existing pairings; the page-side halves need plugin 0.8.7 or later.
56
+
39
57
  ## 0.7.3 update
40
58
 
41
59
  Open the matching conversation after a task-notification tap by carrying a bounded same-origin `dsh-session` route through the native notification, and add an explicit, opt-in `dataSync` foreground service that keeps the current paired-computer event stream alive for completion alerts after Android suspends the page. The service shows a persistent notification, refuses iroh pairings, does not replay events across disconnection, and remains subject to Android foreground-service time limits and battery policy. Both APK variants retain the established signer and existing pairings; the background stream needs plugin 0.8.6 or later.
@@ -138,6 +156,8 @@ DSH records audio through `getUserMedia` and sends it to the configured computer
138
156
 
139
157
  Task reminders use Host completion events and pending-input cards. While the page is alive it sends notifications through the native bridge; **Settings → General → Task notifications** can explicitly enable **background reminders**, a foreground service that can be turned off in Settings and keeps the active paired-computer connection alive after Android suspends the page. The service remains subject to foreground-service time limits, battery policy and connectivity, displays a persistent notification, does not yet support iroh pairings, and does not replay events across disconnection. A tap may carry a bounded same-origin `dsh-session` route, which opens the matching conversation after a cold or warm start; any other target falls back to the app root. Cloudflare Quick Tunnels do not support the event stream; see [channel limits](../../docs/CLOUDFLARE_TUNNEL.en.md#quick-tunnel-feature-limits).
140
158
 
159
+ Android's own battery management can still stop delivery, and the persistent notification does not prove the stream is alive: it stays while the service runs, whatever the connection is doing. Settings → General reports the service's real phase — connected, not connected, or the bounded failure stage it last recorded — and a `DshMobileBg` logcat line records the same transitions for `adb logcat` diagnosis. On an OEM build that freezes a background process (for example Xiaomi HyperOS's app battery saver), no App-side change keeps the stream open: allow battery use without restriction for this App, or accept that reminders arrive when the App is next foregrounded. iOS is unaffected because it uses the Web Push path instead.
160
+
141
161
  The authenticated page may use the `dshMobile` bridge for `files.pick`, `camera.capture`, `share`, clipboard read/write, task notifications/settings, background reminders (`notification.background.get`/`set`), computer switching and page scaling. The separate extension `files.pick` returns one file, follows its requested MIME types and limits bridge-returned file bytes to 8 MiB. This is not the standard DSH attachment selector's limit.
142
162
 
143
163
  Bridge file/camera operations are serialized with a five-minute deadline. Cancellation, document/session changes or WebView teardown reject stale results and clean up owned resources. Browser media selection waits for an actual result, explicit cancellation, abort or deadline; returning focus is not itself cancellation. Unsupported capabilities return `unsupported`.
@@ -182,10 +202,14 @@ Native builds also include the JVM TLS verifier matching `native/Cargo.lock`, fr
182
202
 
183
203
  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.
184
204
 
185
- The verified stable release is [Android 0.7.3](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.3), build 88. 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).
205
+ The verified stable release is [Android 0.7.5](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.5), build 90. 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).
186
206
 
187
207
  ## Acceptance and known limits
188
208
 
209
+ - Both public App 0.7.5 APKs passed checksum, manifest, established-signer and size checks; the compatibility APK contains no native libraries and the full APK carries only the two iroh transport ABIs. The final CI-built APK was not reinstalled on a phone because the device disconnected during the release; the same 0.7.5/90 code had already been accepted from a local release-signed build earlier that day (in-place upgrade, three pairings retained, native Check for updates exercised).
210
+
211
+ - Both public App 0.7.4 APKs passed checksum, manifest, established-signer and size checks; the compatibility APK contains no native libraries and the full APK carries only the two iroh transport ABIs. There is no new physical-device or public-network run for 0.7.4: the device cache, background-reminder status and in-place notification tap paths are covered by the Android unit tests and CI release builds only, and the Debug-device evidence below belongs to 0.7.3.
212
+
189
213
  - A current-source Debug build (0.7.3/build 88) paired over a cloudflared remote origin received a real completed-turn notification while the app was backgrounded and the screen locked, and tapping it opened the `dsh-session` route to the matching conversation; disabling the opt-in stopped the service and removed the notification. This was the Debug signer on one test device over a public tunnel; it does not establish the published APK, iroh, or every network and OEM behavior.
190
214
 
191
215
  - Both public App 0.7.1 APKs passed checksum, manifest, established-signer, notice and alignment checks. The full APK additionally passed ABI and retained JVM TLS/JNI entry checks; compatibility contains no native libraries. There is no new physical-device or public-relay run for 0.7.1. Earlier arm64 development traffic remains historical evidence, not proof that a current connection uses the relay.
@@ -4,14 +4,14 @@
4
4
 
5
5
  DeepSeek Harness 是这个社区维护的 Android WebView App 的显示名称。它直接打开插件提供的已认证 HTTPS 页面,不打包另一套 DSH 前端;App 与手机浏览器获得相同的 DSH 功能,以及电脑端配置的移动页面定制。
6
6
 
7
- 当前正式 App 为 **0.7.3**;构建号为 88。npm 插件与 Android App 独立编号、独立更新;插件升级不代表需要重新安装 APK。此次改进见 [0.7.3 更新](#073-更新)。
7
+ 当前正式 App 为 **0.7.5**;构建号为 90。npm 插件与 Android App 独立编号、独立更新;插件升级不代表需要重新安装 APK。此次改进见 [0.7.5 更新](#075-更新)。
8
8
 
9
9
  此 APK 支持 Android 10 及以上系统。iPhone 和 iPad 使用 [Safari 主屏幕 Web App 与可选网页推送](../../docs/WEB_PUSH.md),不安装 Android 包;本项目不分发原生 iOS App。
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.7.3) 安装已签名 APK。原有 HTTPS 通道可选兼容版 `.apk`;arm64-v8a/x86_64 设备使用实验性 iroh 时选完整版 `-iroh.apk`。两包使用相同包名和正式签名,选一个原位升级即可保留配对;不同签名的 Debug 包不能直接覆盖正式版,不要为绕过签名不匹配而卸载或清除数据。
14
+ 2. 从 [GitHub Releases](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.5) 安装已签名 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,24 @@ DeepSeek Harness 是这个社区维护的 Android WebView App 的显示名称。
36
36
 
37
37
  删除本机记录会移除保存的设备令牌和固定 CA,不等于撤销电脑授权或清除所有 WebView 短期 Cookie。需要立即终止访问时,请在电脑的 **移动访问** 中撤销设备。Android“清除应用数据”会删除全部配对和网页数据,不是普通重连的处理步骤。
38
38
 
39
+ ## 0.7.5 更新
40
+
41
+ 后台任务提醒直接显示插件提供的内容:当事件带有插件 0.8.8 引入的有界标题和正文时,锁屏记录使用会话显示名与该轮第一行文字;两者都没有时回退到本地化的固定文案,旧插件的行为与之前完全一致。每个字段都会裁成单行、移除控制字符并限长,且不会写入日志。
42
+
43
+ 由 App 单独决定该记录是否投递,并不再报告无法完成的投递:服务按会话与轮次只发一条——相同的 tag 与固定通知 id 会替换而不是追加——在通知被关闭或任务渠道被屏蔽时记录有界的 `notify:blocked` 阶段,而不是声称已投递。`notification.background.get` 现在还会报告 `canPost`(系统权限与渠道的答案,不只是流健康),页面需要在让出投递前读取它。
44
+
45
+ 插件让位时由页面自己发通知:使用插件 0.8.8 时,只有 `enabled`、`connected` 与 `canPost` 同时为真页面才保持静默;权限被撤销、渠道被屏蔽、服务重连中或插件较旧时,页面仍发自己的提醒,不会让该轮完全无提醒。
46
+
47
+ 把来源网段不受信任与配对码过期区分开:当网关返回 HTTP 403 `{"error":"source_network_untrusted"}`(需插件 0.8.9 或更高)时,配对弹窗会说明手机所在网络不在电脑的信任范围内,并指向「额外允许的来源网段」,而不是笼统地说一次性二维码已失效。仍只返回 `forbidden` 的旧插件保持原提示,混合版本行为不变。
48
+
49
+ 在设备列表设置中加入原生「检查更新」:它直接从 GitHub 读取已发布的 App 描述符(不经过已配对网关),比较构建号,提示已是最新,或经用户确认后打开对应的 Android 发布页。不会自动下载或安装,失败只显示可重试的提示。
50
+
51
+ 两种 APK 变体都保留既有签名与现有配对;通知文案需要插件 0.8.8 或更高,配对提示需要插件 0.8.9 或更高。
52
+
53
+ ## 0.7.4 更新
54
+
55
+ 把按修订号寻址的移动端页面载荷缓存在设备上,独立于 WebView 自身的 HTTP 缓存:经重新校验的启动批次可用 `If-None-Match` 校验,并在 304 后直接返回已存正文;按修订号命名的插件组合包按有序模块列表与修订号寻址。只有大小与 SHA-256 都与取回字节一致后才写入缓存;缓存未命中或任何完整性、epoch、归属校验失败都会回退到普通请求;文档、API 响应、凭据与未按修订号命名的资源不参与缓存;清除站点数据或移除已配对设备会清空该存储。后台提醒的常驻通知现在显示真实阶段(连接中、已连接、未连接),并通过 `notification.background.get` 与 `DshMobileBg` logcat 行发布 `connected`、`lastEventAt` 和有界的 `lastError` 阶段;后台服务的完成通知使用独立的 `dsh-task-bg-` 标签,服务会重新绑定到新激活的已配对电脑而不是继续重试原 Origin,活动记录无法提供服务(包括 iroh 配对)时撤回该选项。点击任务通知现在先由页面内的就地钩子在活动页面中打开对应会话,页面未就绪或无法处理该路由时回退到路由跳转。两种 APK 均沿用正式签名,可原位升级并保留已有配对;页面侧的一半需要插件 0.8.7 或更高版本。
56
+
39
57
  ## 0.7.3 更新
40
58
 
41
59
  任务通知点击可携带经校验的同源 `dsh-session` 路由,冷启动或热启动后打开对应会话;并新增可显式开启的 `dataSync` 前台服务,在 Android 挂起页面后继续接收当前已配对电脑的完成事件。该服务显示常驻通知,不支持 iroh 配对,断连期间不补发,仍受 Android 前台服务时限与电池策略限制。两种 APK 均沿用正式签名,可原位升级并保留已有配对;后台事件流需要插件 0.8.6 或更高版本。
@@ -138,6 +156,8 @@ DSH 通过 `getUserMedia` 录音并交给电脑已配置的语音提供方,不
138
156
 
139
157
  任务提醒依赖 Host 完成事件和待确认卡片。页面仍存活时由网页走原生 Bridge 发通知;在**设置 → 通用设置 → 任务通知**下可显式开启**后台提醒**,由可关闭的前台服务保持与当前已配对电脑的连接,页面被系统挂起后仍可收到完成事件。该服务会显示常驻通知,受 Android 前台服务时限、电池策略和网络影响;iroh 配对暂不支持,断连期间不补发。点击通知可携带有界的同源 `dsh-session` 路由,冷启动或热启动后打开对应会话;其他目标一律回退到 App 根入口。Cloudflare 快速隧道不支持事件流,详见[通道限制](../../docs/CLOUDFLARE_TUNNEL.md#快速隧道的功能限制)。
140
158
 
159
+ Android 自身的电池管理仍可能中断投递,而且常驻通知**不代表**事件流是活的:服务一在跑它就在,与连接状态无关。设置 → 通用设置会显示服务的真实阶段(已连接、未连接或最后一次记录到的有界失败阶段),并写入 `DshMobileBg` logcat 行,便于用 `adb logcat` 定位。在会冻结后台进程的厂商系统上(例如小米 HyperOS 的应用电池省电策略),App 侧无法维持这条流:请为该 App 关闭电池限制,或接受提醒在下一次回到前台时才出现。iOS 走网页推送通道,不受此限。
160
+
141
161
  认证页面可通过 `dshMobile` Bridge 调用 `files.pick`、`camera.capture`、分享、剪贴板读写、任务通知/设置、后台提醒(`notification.background.get`/`set`)、切换电脑及页面缩放。扩展单独调用的 `files.pick` 返回一个文件,遵循声明的 MIME 类型,通过 Bridge 返回的文件最多 8 MiB;这不是 DSH 标准附件选择器的大小限制。
142
162
 
143
163
  Bridge 文件/相机操作串行执行,最长等待五分钟。取消、文档/会话变化或 WebView 销毁会拒绝旧结果并清理资源。浏览器媒体选择等待实际结果、明确取消、中止或超时,恢复焦点不直接视为取消;不支持的能力返回 `unsupported`。
@@ -182,10 +202,14 @@ Set-Location apps/mobile/android
182
202
 
183
203
  当前源码的 Debug 构建使用包名 `io.github.sayach.dshmobile.debug` 与 `-debug` 版本后缀,可与正式 App 并存,存储和配对彼此独立。它不会升级或迁移旧版无后缀 Debug 应用;切换包名时应保留旧应用和数据,不要为此卸载或清除。Release 构建继续使用 `io.github.sayach.dshmobile` 与既定正式签名。
184
204
 
185
- 已核验的正式版本为 [Android 0.7.3](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.3),构建 88。兼容版与完整版分别附有对应的 `.sha256` 校验文件;两个公开下载均沿用正式发布签名及包名 `io.github.sayach.dshmobile`。旧版本历史集中在 [CHANGELOG](../../CHANGELOG.md)。
205
+ 已核验的正式版本为 [Android 0.7.5](https://github.com/saya-ch/dsh-mobile/releases/tag/android-v0.7.5),构建 90。兼容版与完整版分别附有对应的 `.sha256` 校验文件;两个公开下载均沿用正式发布签名及包名 `io.github.sayach.dshmobile`。旧版本历史集中在 [CHANGELOG](../../CHANGELOG.md)。
186
206
 
187
207
  ## 验收与已知限制
188
208
 
209
+ - App 0.7.5 的两份公开 APK 均通过校验值、Manifest、既定正式签名与体积检查;兼容版不含原生库,完整版只携带两个 iroh 传输 ABI。发布验收时设备断开,最终 CI 产物未在手机上重装;同一份 0.7.5/90 代码已在当天早些时候以本地正式签名构建完成原位升级、保留 3 条配对并验收了原生「检查更新」。
210
+
211
+ - App 0.7.4 的两份公开 APK 均通过校验值、Manifest、既定正式签名与体积检查;兼容版不含原生库,完整版只携带两个 iroh 传输 ABI。本版未新增真机或公网回归:设备端缓存、后台提醒状态与通知就地打开仅由 Android 单元测试与 CI 发布构建覆盖,下方的真机 Debug 证据属于 0.7.3。
212
+
189
213
  - 当前源码 Debug 构建(0.7.3/构建 88)经 cloudflared 远程入口配对后,在 App 退到后台且锁屏时收到了真实回合完成通知;点击后打开对应会话的 `dsh-session` 路由,关闭该选项后服务停止并移除通知。这是单台设备、公网隧道和 Debug 签名的验证,不代表正式 APK、iroh 或所有网络与厂商行为。
190
214
 
191
215
  - App 0.7.1 的两份公开 APK 均通过校验值、Manifest、既定正式签名、许可文本和对齐检查;完整版另检查两个 ABI 及保留的 JVM TLS/JNI 入口,兼容版确认没有原生库。本版未新增真机或公网中继回归。较早 arm64 开发构建的链路记录仍属历史证据,不能据此断言当前连接的数据已经过中继。
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.7.3",
3
- "versionCode": 88,
4
- "releaseTag": "android-v0.7.3"
2
+ "version": "0.7.5",
3
+ "versionCode": 90,
4
+ "releaseTag": "android-v0.7.5"
5
5
  }
@@ -65,7 +65,7 @@ The computer-side gateway terminates TLS with a five-year CA and 397-day public-
65
65
  # Expected output: 200. `-k` skips curl's certificate check and proves reachability only, not identity.
66
66
  ```
67
67
 
68
- HTTP 200 proves reachability only: `-k` does not verify identity. Pair through **Remote access** in app 0.4.6 or later; it fetches the CA without device credentials, checks the `dsh2` fingerprint and pins the exact Origin. CA HTTP 404 cannot fall back to platform trust. An Origin or CA change requires new pairing.
68
+ HTTP 200 proves reachability only: `-k` does not verify identity. Pair through **Remote access** in app 0.4.6 or later; it fetches the CA from `GET /mobile-access/ca.cer` without device credentials, checks the `dsh2` fingerprint and pins the exact Origin. CA HTTP 404 cannot fall back to platform trust. An Origin or CA change requires new pairing.
69
69
 
70
70
  ## Troubleshooting and cleanup
71
71
 
package/docs/IROH.en.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
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
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. This guide was verified on plugin 0.8.6 and the full Android App 0.7.3 (build 88); iroh has been available since 0.7.0. Direct connectivity, relay use and speed depend on both networks; availability on every campus, corporate or carrier network is not guaranteed.
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. This guide corresponds to plugin 0.8.8 and the full Android App 0.7.4 (build 89; the App candidate on main is 0.7.5/build 90); iroh has been available since 0.7.0. Direct connectivity, relay use and speed depend on both networks; availability on every campus, corporate or carrier network is not guaranteed.
6
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
7
 
8
8
  ## Prerequisites
@@ -26,8 +26,8 @@ To reclaim component storage, turn off iroh remote access, expand the component
26
26
 
27
27
  ## Security boundaries
28
28
 
29
- - The sidecar proxies only to a `127.0.0.1`/`::1` loopback gateway with end-to-end TLS; commands and events are versioned and bounded (16 KiB command lines, 64 KiB peer lines), and rejected closed on unknown fields.
30
- - A rotated fingerprint, replaced binary, or moved file fails verification instead of silently running a stale one: a missing or damaged component parks the channel at `unavailable`, while an identity or TLS fingerprint mismatch reports `error` (`gateway_start_failed`).
29
+ - The sidecar proxies only to a `127.0.0.1`/`::1` loopback gateway with end-to-end TLS; commands and events are versioned and bounded (16 KiB command and event lines, 64 KiB peer lines), and rejected closed on unknown fields.
30
+ - A rotated CA fingerprint, replaced binary, or moved file fails verification instead of silently running a stale one: a missing or damaged component parks the channel at `unavailable`; a mismatched CA certificate/fingerprint, or a corrupt or unreadable identity file, reports `error` and the panel shows the remote gateway failed to start (`gateway_start_failed`). Replacing the sidecar identity file does not fail; it creates a new identity and the old pairings stop matching.
31
31
  - 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.
32
32
 
33
33
  ## Troubleshooting
@@ -41,7 +41,7 @@ Before a component release, verify first use with the exact catalog-pinned execu
41
41
  | `iroh_companion_missing` | Nothing installed yet: press Install first, or point `DSH_MOBILE_IROH_COMPANION` at a companion absolute path to reuse |
42
42
  | `iroh_sidecar_invalid` | An installed file was modified; reinstalling overwrites it in place, or reinstall the companion for a damaged companion copy |
43
43
  | `iroh_platform_unsupported` | No sidecar is published for this OS/architecture |
44
- | `iroh_data_directory_insecure` | A Windows parent directory of the state path grants write or replacement rights to another account. Move `DSH_HOME` to private storage or correct those ACLs; the plugin log retains the sidecar's bounded stderr explanation. If `DSH_HOME` must stay on another volume, point `stateFile` at a private directory under the user profile, which also relocates the state files derived from that path; when editing `config` in a profile patch, supply every field, because DSH replaces the whole entry config instead of merging keys (see the same rule in [trusted networks](TRUSTED_NETWORKS.en.md)) |
44
+ | `iroh_data_directory_insecure` | A Windows parent directory of the state path grants write or replacement rights to another account. Move `DSH_HOME` to private storage or correct those ACLs; the plugin log retains the sidecar's bounded stderr explanation. Do not switch locations by hand-editing `stateFile` or the state directory: that field selects the whole DSH Mobile state directory, so changing it recreates pairings, device tokens, TLS and the iroh identity under the new path and nothing is migrated from the old one — the phone has to pair again; use the normal configuration entry and back up first. When editing `config` in a profile patch, supply every field, because DSH replaces the whole entry config instead of merging keys (see the config-override rule in [trusted networks](TRUSTED_NETWORKS.en.md)) |
45
45
  | `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 |
46
46
  | `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 |
47
47
  | 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 |
package/docs/IROH.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  iroh 用加密直连(打不通时走中继)代替公网域名和隧道账号:手机先找到电脑的加密身份,再把流量送回本机网关。你不需要准备域名、端口映射或另一套 HTTPS 隧道。
4
4
 
5
- > 插件 0.7.0 和 App 0.7.0 完整版整合电脑端通道、固定 TLS、配对界面和 Android 原生传输;功能默认关闭,仍标记为实验性。本文在插件 0.8.6 与 Android 完整版 0.7.3(build 88)上验证,iroh 自 0.7.0 起可用;能否直连、是否经过中继及连接速度取决于两端网络,不保证在所有校园网、企业网或运营商环境下可用。
5
+ > 插件 0.7.0 和 App 0.7.0 完整版整合电脑端通道、固定 TLS、配对界面和 Android 原生传输;功能默认关闭,仍标记为实验性。本文对应插件 0.8.8 与 Android 完整版 0.7.4(build 89;main 上 App 候选为 0.7.5/build 90),iroh 自 0.7.0 起可用;能否直连、是否经过中继及连接速度取决于两端网络,不保证在所有校园网、企业网或运营商环境下可用。
6
6
  > 相关设计见独立仓的[集成接缝](https://github.com/saya-ch/dsh-mobile-iroh/blob/main/docs/INTEGRATION_SEAM.md)。
7
7
 
8
8
  ## 前提
@@ -26,8 +26,8 @@ iroh 用加密直连(打不通时走中继)代替公网域名和隧道账号
26
26
 
27
27
  ## 安全边界
28
28
 
29
- - sidecar 只允许代理到 `127.0.0.1`/`::1` 的回环网关,TLS 仍端到端;命令与事件都是版本化、有界(命令行 16 KiB、peer 行 64 KiB)、未知字段直接拒绝。
30
- - 换指纹/换二进制/挪文件都会让校验失败,不会静默跑旧通道:缺少或损坏的组件停在 `unavailable`,身份或 TLS 指纹不符则进入 `error`(面板状态是 `gateway_start_failed`)。
29
+ - sidecar 只允许代理到 `127.0.0.1`/`::1` 的回环网关,TLS 仍端到端;命令与事件都是版本化、有界(命令与事件行 16 KiB、peer 行 64 KiB)、未知字段直接拒绝。
30
+ - 换 CA 指纹/换二进制/挪文件都会让校验失败,不会静默跑旧通道:缺少或损坏的组件停在 `unavailable`;CA 证书或指纹不符,或身份文件损坏、不可读时进入 `error`,面板显示远程网关启动失败(`gateway_start_failed`)。直接替换 sidecar 身份文件不会报错,但会生成新身份,旧配对随之失效。
31
31
  - 传输层撤销与设备 Token 撤销是两套授权,统一管理界面是 Phase 2 内容;电脑端撤销仍按现有设备管理生效。
32
32
 
33
33
  ## 排障
@@ -41,7 +41,7 @@ iroh 身份和证书必须存放在仅当前用户或受信系统账户可写的
41
41
  | `iroh_companion_missing` | 还没点安装(或配套不在常规布局旁);先点安装官方组件,或用 `DSH_MOBILE_IROH_COMPANION` 指向配套绝对路径复用 |
42
42
  | `iroh_sidecar_invalid` | 已装文件被改动过;重新点安装即可覆盖修复,配套副本损坏则重装配套 |
43
43
  | `iroh_platform_unsupported` | 当前系统/架构没有 sidecar 发布 |
44
- | `iroh_data_directory_insecure` | Windows 状态目录的某个上级目录允许其他账户写入或替换。请把 `DSH_HOME` 移到私有目录,或修正上级目录 ACL;插件日志会保留 sidecar 的脱敏 stderr 说明。若 `DSH_HOME` 必须留在其他卷,可把 `stateFile` 指向用户 profile 下的私有目录,插件从该路径派生的状态文件也会随之迁移;在 profile patch 里改 `config` 时要写全所有字段,因为 DSH 整体替换该条目配置,不逐键合并(参见[可信网络](TRUSTED_NETWORKS.md)的同类说明) |
44
+ | `iroh_data_directory_insecure` | Windows 状态目录的某个上级目录允许其他账户写入或替换。请把 `DSH_HOME` 移到私有目录,或修正上级目录 ACL;插件日志会保留 sidecar 的脱敏 stderr 说明。不要用手动改 `stateFile` 或状态目录来切换位置:该字段决定整个 DSH Mobile 状态目录,改动会让配对记录、设备令牌、TLS 与 iroh 身份在新目录重建,旧目录不会自动迁移,手机需要重新配对;确需换位置请走正常配置入口并在改动前备份。在 profile patch 里改 `config` 时要写全所有字段,因为 DSH 整体替换该条目配置,不逐键合并(参见[可信网络](TRUSTED_NETWORKS.md)的 config 覆盖说明) |
45
45
  | `iroh_identity_invalid` / `iroh_identity_failed` | 先检查状态目录及父目录是否私有、已有身份是否损坏,保留原文件再排查;`id` 仅检查已有身份,首次创建使用 `tls-prepare`,不是靠复制或删除身份修复 |
46
46
  | `iroh_start_timeout` | 查看 DSH 日志中的 iroh 错误及网络连接,确认固定组件可运行;不要反复重新配对来替代进程排查 |
47
47
  | 通道 `ready` 但手机连不上 | 检查 App 是否为完整版、设备是否支持打包的 ABI,以及描述符是否有效;电脑就绪不等于手机已连通,连接中继服务也不等于数据一定经过中继 |
package/docs/README.md CHANGED
@@ -15,11 +15,18 @@
15
15
  | 复用已经运行的 frps,不自动修改服务器 | [接入既有 frps](ATTACH_EXISTING_FRPS.md) | [Existing frps](ATTACH_EXISTING_FRPS.en.md) |
16
16
  | 复用 Lucky、Nginx 或 Caddy 的公开 HTTPS 入口 | [自有反向代理](SELF_HOSTED_ORIGIN.md) | [Own reverse proxy](SELF_HOSTED_ORIGIN.en.md) |
17
17
  | 由插件安装 Caddy 并管理 HTTPS 证书(0.6.9 起) | [托管 Caddy](CADDY_MANAGED.md) | [Managed Caddy](CADDY_MANAGED.en.md) |
18
- | iroh 加密直连实验通道 | [iroh 实验通道](IROH.md) | [iroh experimental channel](IROH.en.md) |
19
18
  | 页面加载慢、实时连接反复重连或长操作超时 | [慢链路与重连](SLOW_CONNECTIONS.md) | [Slow links and reconnection](SLOW_CONNECTIONS.en.md) |
20
19
  | 了解输入栏换行、附加控件与触摸目标 | [移动输入栏](MOBILE_COMPOSER_TOOLBAR.md) | [Mobile composer](MOBILE_COMPOSER_TOOLBAR.en.md) |
21
20
  | 保留电脑皮肤,排查移动页面的背景与可读性 | [皮肤与移动布局](SKIN_COMPATIBILITY.md) | [Skins and mobile layout](SKIN_COMPATIBILITY.en.md) |
22
21
 
22
+ ## 实验通道 / Experimental channel
23
+
24
+ 以下通道为实验性,不默认启用,验收证据有限:
25
+
26
+ | 你想做什么 | 中文 | English |
27
+ | --- | --- | --- |
28
+ | iroh 加密直连实验通道 | [iroh 实验通道](IROH.md) | [iroh experimental channel](IROH.en.md) |
29
+
23
30
  在 Android App 中连接公开隧道或自建入口时请选择 **远程访问**。公开受信任证书也可用手机浏览器配对;既有 frps 的自签入口需要 **0.4.6 或更高版本 App** 固定远程 CA。**iroh 则使用完整版 App 0.7.0 的独立配对流程**,不支持兼容版 APK 或手机浏览器。各通道仍要求 DSH Mobile 配对,不能直接暴露普通 DSH 或私有 HTTP 后端。
24
31
 
25
32
  ## 页面与网络设置 / Page and network settings
@@ -17,6 +17,8 @@ The current LAN subnet is always combined with the extra list. When Wi-Fi, hotsp
17
17
 
18
18
  CIDRs match the direct TCP source address, not `X-Forwarded-For`. Allowing a source subnet does not permit every network or bypass HTTPS, device pairing, exact Host / Origin, or CSRF checks. Add only the ranges actually needed, rather than allowing the entire internet to diagnose a connection.
19
19
 
20
+ When the phone and the computer are on different subnets, the source-address check rejects a pairing request before the one-time code is ever examined. From plugin 0.8.9 (not yet released) that rejection answers HTTP 403 `{"error":"source_network_untrusted"}`, separately from an expired code (HTTP 401); from Android 0.7.5 (not yet released) the App reports "phone network not trusted" and points at this page, while an older half of either side still shows the pairing link as expired. Confirm both subnets before regenerating a QR code.
21
+
20
22
  ## Windows firewall is separate
21
23
 
22
24
  DSH Mobile's default Windows HTTPS / Discovery inbound rules allow only `LocalSubnet`. Saving extra CIDRs **does not update or broaden those rules**. You or your administrator must separately allow the controlled sources to reach the actual Mobile HTTPS port in Windows firewall settings.
@@ -17,6 +17,8 @@
17
17
 
18
18
  CIDR 按直接 TCP 来源地址匹配,不依赖 `X-Forwarded-For`。允许一个来源网段不等于允许所有网络,也不跳过 HTTPS、设备配对、精确 Host / Origin 或 CSRF 检查。只追加实际需要的范围,不要为了排错直接放行整个互联网。
19
19
 
20
+ 手机与电脑不在同一网段时,配对请求会先被来源地址检查拒绝,尚未到达配对码校验。插件 0.8.9 起(尚未发布)这种拒绝单独返回 HTTP 403 `{"error":"source_network_untrusted"}`,与配对码过期(HTTP 401)区分;Android 0.7.5 起(尚未发布)App 显示「手机网络未获信任」并指向本页设置,更早的一方组合仍会把它显示为「配对链接已失效」,因此失败时先确认两台设备所在网段,再判断是否需要重新生成二维码。
21
+
20
22
  ## Windows 防火墙是另一项设置
21
23
 
22
24
  DSH Mobile 的默认 Windows HTTPS / Discovery 入站规则只允许 `LocalSubnet`。保存额外 CIDR **不会修改或扩大这些规则**;需要由你或系统管理员在 Windows 防火墙中单独允许受控来源访问实际 Mobile HTTPS 端口。
@@ -14,7 +14,7 @@ Home Screen installation does not provide offline DSH: the computer, DSH and its
14
14
 
15
15
  - A capable iPhone/iPad Home Screen web app, opened in standalone mode, with the page-level `window.pushManager` API. The plugin detects capabilities rather than trusting a browser version string. Ordinary Safari tabs and unsupported browsers do not get a service-worker fallback.
16
16
  - A **stable, trusted HTTPS origin** and an existing DSH Mobile browser pairing. HTTP and continuing through a certificate warning are not supported push configurations. The Android app's private-CA pin does not make an iPhone browser trust that CA.
17
- - Plugin **0.8.0 or later** on the computer, with DSH and the Mobile Gateway for the exact HTTPS origin running. Packed push automation covers DSH **0.2.1-rc.2 through 0.2.2-rc.1** (rc.2, rc.3, rc.5, 0.2.2-alpha.3, 0.2.2-rc.1); other versions depend on the required public services. Missing services disable push without disabling ordinary Mobile access.
17
+ - Plugin **0.8.0 or later** on the computer, with DSH and the Mobile Gateway for the exact HTTPS origin running. Browser boot automation covers DSH **0.1.7-alpha.2 through 0.2.2-rc.3** (13 versions); the packed push automation covers **0.2.1-rc.2, 0.2.1-rc.3, 0.2.1-rc.5, 0.2.2-rc.1 and 0.2.2-rc.2**, while 0.2.2-rc.3 currently runs only the boot and compressed-mux checks and is not yet part of the packed push checks; on other versions push still depends on the required public services. Missing services disable push without disabling ordinary Mobile access.
18
18
  - Outbound access to Apple's push infrastructure from the host and phone. No Apple developer membership, notification SaaS account or new public inbound port is required. This feature does not create a VPN, change certificates, open a firewall or configure a proxy.
19
19
 
20
20
  A publicly trusted private HTTPS hostname is architecturally eligible. The phone must still reach that origin to install, enable, authenticate and open a conversation. Delivery over a private/Tailscale origin is **unverified**; do not expose a private backend just to try push. Random tunnel hostnames are unsuitable for stable installation consent: an origin change never migrates authorization or subscriptions automatically. For persistent addresses, see [Cloudflare named tunnels](<CLOUDFLARE_TUNNEL.en.md>) or [your own HTTPS reverse proxy](<SELF_HOSTED_ORIGIN.en.md>); configuring an address alone does not prove push delivery.
package/docs/WEB_PUSH.md CHANGED
@@ -14,7 +14,7 @@ DSH Mobile 插件运行在**电脑**上。iPhone/iPad 用户用 **Safari** 打
14
14
 
15
15
  - 支持页面级 `window.pushManager` 的 iPhone/iPad 主屏幕 Web App,并以独立模式打开。插件检查实际能力,不根据浏览器版本字符串放行;普通 Safari 标签页和不支持的浏览器没有 Service Worker 降级方案。
16
16
  - **固定、受信任的 HTTPS Origin**,以及现有 DSH Mobile 浏览器配对。HTTP 和绕过证书警告不属于受支持的推送配置;Android App 固定私有 CA,不等于 iPhone 浏览器信任该 CA。
17
- - 电脑端已更新到插件 **0.8.0 或更高版本**,DSH 和对应 HTTPS 地址的 Mobile Gateway 正在运行。推送的打包自动化检查覆盖 DSH **0.2.1-rc.2 至 0.2.2-rc.1**(rc.2、rc.3、rc.5、0.2.2-alpha.3、0.2.2-rc.1);其他版本仍取决于所需公共服务是否可用,缺少服务只关闭推送,不关闭普通移动访问。
17
+ - 电脑端已更新到插件 **0.8.0 或更高版本**,DSH 和对应 HTTPS 地址的 Mobile Gateway 正在运行。浏览器启动自动化覆盖 DSH **0.1.7-alpha.2 至 0.2.2-rc.3**(13 个版本);推送的打包自动化检查覆盖 **0.2.1-rc.2、0.2.1-rc.3、0.2.1-rc.5、0.2.2-rc.1、0.2.2-rc.2**,0.2.2-rc.3 目前只跑启动与压缩 mux 检查、尚未纳入推送打包检查;其他版本仍取决于所需公共服务是否可用,缺少服务只关闭推送,不关闭普通移动访问。
18
18
  - 主机和手机能出站连接 Apple 推送基础设施。不需要 Apple 开发者会员、通知 SaaS 账号或新增公网入站端口。此功能不创建 VPN、不改证书/防火墙,也不配置代理。
19
19
 
20
20
  使用公开受信任证书的私有 HTTPS 主机名在架构上可以使用。安装、启用、认证和打开会话时,手机仍须能访问该 Origin。私有/Tailscale Origin 的投递**尚未实测确认**;不要为了尝试推送把私有后端直接暴露到公网。随机隧道域名不适合作为长期安装地址:Origin 改变后,不自动迁移授权或订阅。需要长期地址时,可参考 [Cloudflare 命名隧道](<CLOUDFLARE_TUNNEL.md>)或[自有 HTTPS 反向代理](<SELF_HOSTED_ORIGIN.md>);仅完成地址配置不代表推送已验证送达。