dsh-plugin-tether 0.1.7 → 0.1.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,32 @@
2
2
 
3
3
  本文件记录面向用户的变化。每个版本的这一节会原样作为该版本 Release 的说明。
4
4
 
5
+ ## 0.1.9
6
+
7
+ ### 新增
8
+
9
+ - **适配 dsh 0.1.2-alpha 的浏览器认证**([#4](https://github.com/zexadev/dsh-tether/issues/4))。dsh 0.1.2-alpha 起,网页界面与 Host API 要求持有经启动 token 兑换的签名 cookie,无凭据一律 401——手机端表现为连上后一片 401 提示。
10
+
11
+ 适配完全在电脑侧完成:插件启动时自动完成 token→cookie 兑换,sidecar 在代理出口把认证注入每个转发请求。**手机 App 无需更新**;dsh 的跨站请求防护经隧道原样保留(伪造来源仍被 403 拒绝)。
12
+
13
+ cookie 是 `SameSite=Strict` 且绑定地址端口,手机 WebView 的内嵌页面属跨站上下文、cookie 根本不会随请求发出,所以「把登录链接发给手机打开」这条路在浏览器规则下走不通,注入只能发生在电脑侧。
14
+
15
+ - 继续兼容 dsh 0.1.0-rc.7 / rc.8:旧版没有浏览器认证,代理保持原样透传,行为不变。
16
+
17
+ ## 0.1.8
18
+
19
+ ### 修复
20
+
21
+ - **iOS:连接成功但界面空白**。iOS 的 App Transport Security 默认禁止 WebView 加载明文 HTTP,而手机端的界面正是从本机代理出口 `http://127.0.0.1:<端口>` 加载的。安卓侧一直有对应配置放行回环流量,iOS 侧没有。iroh 连接是原生代码不受 ATS 约束,所以「显示已连接」与「界面空白」会同时出现。
22
+
23
+ 现只放行回环、`.local` 与链路本地地址(`NSAllowsLocalNetworking`),其余域仍受 ATS 约束——与安卓侧只放行 `127.0.0.1` / `localhost` 的做法一致。
24
+
25
+ 由用户反馈发现。**本修复未在 iOS 真机验证**,若仍有问题请在 issue 里补充电脑侧终端的完整输出。
26
+
27
+ ### 新增
28
+
29
+ - 手机第一次开始加载界面时,电脑侧会打印「手机已开始加载界面」。此前电脑侧对代理流完全静默,「连上却空白」无从判断是手机压根没发请求,还是发了但转发不通。
30
+
5
31
  ## 0.1.7
6
32
 
7
33
  ### 元数据
package/README.md CHANGED
@@ -17,9 +17,11 @@
17
17
  <a href="../../releases"><img src="https://img.shields.io/github/downloads/zexadev/dsh-tether/total?style=flat&label=downloads&color=4D6BFE" alt="Downloads"></a>
18
18
  <a href="../../stargazers"><img src="https://img.shields.io/github/stars/zexadev/dsh-tether?style=flat&label=%E2%98%85&color=08C" alt="Stars"></a>
19
19
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT"></a>
20
- <img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8">
20
+ <img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8%20%7C%200.1.2--alpha-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8 | 0.1.2-alpha">
21
21
  <img src="https://img.shields.io/badge/Android-4493F8?style=flat" alt="Android">
22
22
  <img src="https://img.shields.io/badge/iOS-beta-8E8E93?style=flat" alt="iOS beta">
23
+ <a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/dsh-tether.svg" alt="dsh.so security scan"></a>
24
+ <a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/install/dsh-tether.svg" alt="dsh.so install check"></a>
23
25
  </p>
24
26
 
25
27
  <p align="center">
@@ -106,7 +108,7 @@ From then on the app connects by itself when you open it.
106
108
  - The iOS build is beta: built only in CI, never run on a real device, and you sign it yourself. Android is the one verified on real hardware.
107
109
  - The app connects when you open it and holds no background connection — Android's doze would not let it anyway.
108
110
  - The interface on the phone is DSH's own; the narrow-screen fit comes from minimal injected styles, so a dsh layout change may need a follow-up here.
109
- - Verified against dsh **`0.1.0-rc.7`** and **`0.1.0-rc.8`**. dsh is in developer preview — check this line before assuming a newer dsh works.
111
+ - Verified against dsh **`0.1.0-rc.7`**, **`0.1.0-rc.8`** and **`0.1.2-alpha`**. dsh is in developer preview — check this line before assuming a newer dsh works. The browser authentication dsh introduced in 0.1.2-alpha is handled entirely on the machine side; the phone app needs no update for it.
110
112
 
111
113
  ## What has been verified
112
114
 
package/README.zh.md CHANGED
@@ -17,9 +17,11 @@
17
17
  <a href="../../releases"><img src="https://img.shields.io/github/downloads/zexadev/dsh-tether/total?style=flat&label=downloads&color=4D6BFE" alt="下载量"></a>
18
18
  <a href="../../stargazers"><img src="https://img.shields.io/github/stars/zexadev/dsh-tether?style=flat&label=%E2%98%85&color=08C" alt="Stars"></a>
19
19
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT"></a>
20
- <img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8">
20
+ <img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8%20%7C%200.1.2--alpha-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8 | 0.1.2-alpha">
21
21
  <img src="https://img.shields.io/badge/Android-4493F8?style=flat" alt="Android">
22
22
  <img src="https://img.shields.io/badge/iOS-%E6%B5%8B%E8%AF%95%E7%89%88-8E8E93?style=flat" alt="iOS 测试版">
23
+ <a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/dsh-tether.svg" alt="dsh.so 安全扫描"></a>
24
+ <a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/install/dsh-tether.svg" alt="dsh.so 安装实测"></a>
23
25
  </p>
24
26
 
25
27
  <p align="center">
@@ -106,7 +108,7 @@ dsh plugin --profile web add .
106
108
  - iOS 版是测试版:只在 CI 上构建,从未在真机运行过,且需要自行签名。安卓版是经过真机验证的那一个。
107
109
  - App 打开时才连接,不在后台常驻——Android 的 doze 也留不住它。
108
110
  - 手机上的界面是 DSH 自己的,窄屏适配靠注入的最小样式完成;dsh 改版式时可能需要跟进。
109
- - 已针对 dsh **`0.1.0-rc.7`** 与 **`0.1.0-rc.8`** 验证。dsh 处于 developer preview,换更新的 dsh 之前先看这一行。
111
+ - 已针对 dsh **`0.1.0-rc.7`**、**`0.1.0-rc.8`** 与 **`0.1.2-alpha`** 验证。dsh 处于 developer preview,换更新的 dsh 之前先看这一行。dsh 0.1.2-alpha 引入的浏览器认证完全在电脑侧处理,手机 App 无需更新。
110
112
 
111
113
  ## 验证过什么
112
114
 
package/index.js CHANGED
@@ -159,6 +159,9 @@ function apply(ctx, config = {}) {
159
159
  case 'peer-disconnected':
160
160
  console.log('[tether] 手机已断开')
161
161
  break
162
+ case 'proxy-opened':
163
+ console.log('[tether] 手机已开始加载界面')
164
+ break
162
165
  case 'devices': {
163
166
  const waiters = pendingDevices
164
167
  pendingDevices = []
@@ -172,6 +175,44 @@ function apply(ctx, config = {}) {
172
175
 
173
176
  ctx.effect(() => ctx.webServer.tapIndex(injectNarrowScreenCss))
174
177
 
178
+ // dsh 0.1.2-alpha 起浏览器界面要求认证:进程启动 token 经 GET /?token= 换成
179
+ // HMAC 签名 cookie,index 与 /api 无 cookie 一律 401。cookie 是 SameSite=Strict
180
+ // 且绑定 Host authority——手机 WebView 的 iframe 属跨站上下文,cookie 根本不会
181
+ // 随请求发出,把 token 交给手机没有用;唯一可行位置在电脑侧:这里自己完成兑换,
182
+ // 把 cookie 交给 sidecar 在代理流上逐请求注入。
183
+ ctx.inject(['connection'], (connCtx) => {
184
+ // rc.7/rc.8 也有 connection 服务,只是没有浏览器认证;判据必须是能力
185
+ // 本身而不是服务存在性(实测 rc.8 走到这里,靠服务存在性判会误报错)
186
+ if (typeof connCtx.connection.authenticatedUrl !== 'function') return
187
+ const authority = new URL(`http://${proxyTarget}`).host
188
+ const exchange = async () => {
189
+ const url = connCtx.connection.authenticatedUrl(`http://${proxyTarget}/`)
190
+ const res = await fetch(url, { redirect: 'manual' })
191
+ const setCookie = res.headers.getSetCookie()
192
+ if (res.status !== 303 || setCookie.length !== 1) {
193
+ throw new Error(`token 兑换应答异常: HTTP ${res.status}, set-cookie ×${setCookie.length}`)
194
+ }
195
+ send({ type: 'proxy-auth', cookie: setCookie[0].split(';', 1)[0], authority })
196
+ }
197
+ const exchangeWithRetry = async () => {
198
+ for (let attempt = 1; ; attempt++) {
199
+ try {
200
+ return await exchange()
201
+ } catch (error) {
202
+ if (attempt >= 3) {
203
+ console.error('[tether] 浏览器认证 cookie 获取失败,手机端将收到 401:', error)
204
+ return
205
+ }
206
+ await new Promise((resolve) => setTimeout(resolve, 1000 * attempt))
207
+ }
208
+ }
209
+ }
210
+ void exchangeWithRetry()
211
+ // cookie 绝对有效期默认 30 天,dsh 进程可能活得更久;定期重兑换续上
212
+ const timer = setInterval(() => { void exchangeWithRetry() }, 12 * 60 * 60 * 1000)
213
+ connCtx.effect(() => () => clearInterval(timer))
214
+ })
215
+
175
216
  // 「打开配置文件」在宿主机桌面开编辑器,手机上按了毫无反应。这条路由把同一份
176
217
  // 文件的内容原样交给手机自己渲染。路径由 Host 侧的 settings.documentPath 决定,
177
218
  // 不接受客户端传路径——否则就成了任意文件读取。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-tether",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Mobile client for the DeepSeek Harness — use the dsh on your dev machine from your Android or iOS phone, remotely across networks, peer-to-peer with no server in between (iroh)",
5
5
  "keywords": [
6
6
  "dsh",
@@ -42,18 +42,18 @@
42
42
  }
43
43
  },
44
44
  "peerDependencies": {
45
- "@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7",
46
- "@deepseek-ai/dsh-user-approval": ">=0.1.0-rc.7"
45
+ "@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.1.1-0 || >=0.1.2-alpha.0 <0.1.3-0",
46
+ "@deepseek-ai/dsh-user-approval": ">=0.1.0-rc.7 <0.1.1-0 || >=0.1.2-alpha.0 <0.1.3-0"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "@deepseek-ai/dsh-host-webserver": { "optional": true },
50
50
  "@deepseek-ai/dsh-user-approval": { "optional": true }
51
51
  },
52
52
  "optionalDependencies": {
53
- "dsh-tether-host-darwin-arm64": "0.1.7",
54
- "dsh-tether-host-darwin-x64": "0.1.7",
55
- "dsh-tether-host-linux-arm64": "0.1.7",
56
- "dsh-tether-host-linux-x64": "0.1.7",
57
- "dsh-tether-host-win32-x64": "0.1.7"
53
+ "dsh-tether-host-darwin-arm64": "0.1.9",
54
+ "dsh-tether-host-darwin-x64": "0.1.9",
55
+ "dsh-tether-host-linux-arm64": "0.1.9",
56
+ "dsh-tether-host-linux-x64": "0.1.9",
57
+ "dsh-tether-host-win32-x64": "0.1.9"
58
58
  }
59
59
  }