dsh-zen-remote 1.1.16 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/AGENTS.md +54 -9
  2. package/README.md +249 -190
  3. package/README.zh-CN.md +247 -201
  4. package/assets/home.png +0 -0
  5. package/assets/info.png +0 -0
  6. package/assets/pairing.png +0 -0
  7. package/assets/session.png +0 -0
  8. package/assets/sheet.png +0 -0
  9. package/cordis.patch.yml +12 -11
  10. package/cordis.patch.yml.example +24 -9
  11. package/docs/interface.md +57 -2
  12. package/docs/remote-access.en.md +99 -58
  13. package/docs/remote-access.md +99 -42
  14. package/dsh-push.mjs +67 -54
  15. package/lan-gate.mjs +88 -20
  16. package/lib/activity.js +168 -0
  17. package/lib/activity.js.map +1 -0
  18. package/lib/admin-routes.js +526 -0
  19. package/lib/admin-routes.js.map +1 -0
  20. package/lib/client-pairing.js +224 -0
  21. package/lib/client-pairing.js.map +1 -0
  22. package/lib/client-routes.js +674 -0
  23. package/lib/client-routes.js.map +1 -0
  24. package/lib/client.js +11498 -5990
  25. package/lib/config.js +346 -0
  26. package/lib/config.js.map +1 -0
  27. package/lib/fetch-route-intercept.js +418 -0
  28. package/lib/fetch-route-intercept.js.map +1 -0
  29. package/lib/fingerprint.js +365 -0
  30. package/lib/fingerprint.js.map +1 -0
  31. package/lib/http.js +69 -0
  32. package/lib/http.js.map +1 -0
  33. package/lib/index.js +675 -54
  34. package/lib/index.js.map +1 -1
  35. package/lib/intercept-shape.js +81 -0
  36. package/lib/intercept-shape.js.map +1 -0
  37. package/lib/intercept.js +3181 -0
  38. package/lib/intercept.js.map +1 -0
  39. package/lib/lan-gate-server.cjs +532 -121
  40. package/lib/merge-streams.js +1172 -0
  41. package/lib/merge-streams.js.map +1 -0
  42. package/lib/relay-access.js +496 -0
  43. package/lib/relay-access.js.map +1 -0
  44. package/lib/relay-client.js +1303 -0
  45. package/lib/relay-client.js.map +1 -0
  46. package/lib/relay-filter.js +282 -0
  47. package/lib/relay-filter.js.map +1 -0
  48. package/lib/relay-server.js +1813 -0
  49. package/lib/relay-server.js.map +1 -0
  50. package/lib/restart-fields.js +34 -0
  51. package/lib/restart-fields.js.map +1 -0
  52. package/lib/restart-watcher.js +106 -0
  53. package/lib/restart-watcher.js.map +1 -0
  54. package/lib/session-reference.js +157 -0
  55. package/lib/session-reference.js.map +1 -0
  56. package/lib/share-export.js +16 -1
  57. package/lib/share-export.js.map +1 -1
  58. package/lib/share-ops.js +86 -0
  59. package/lib/share-ops.js.map +1 -0
  60. package/lib/share-store.js +294 -0
  61. package/lib/share-store.js.map +1 -0
  62. package/lib/types/activity.d.ts +99 -0
  63. package/lib/types/activity.d.ts.map +1 -0
  64. package/lib/types/admin-routes.d.ts +129 -0
  65. package/lib/types/admin-routes.d.ts.map +1 -0
  66. package/lib/types/client/MobileDrawerFooter.d.ts.map +1 -1
  67. package/lib/types/client/MobileHome.d.ts +1 -1
  68. package/lib/types/client/MobileHome.d.ts.map +1 -1
  69. package/lib/types/client/MobileHomeChips.d.ts +1 -1
  70. package/lib/types/client/MobileHomeChips.d.ts.map +1 -1
  71. package/lib/types/client/MobileSessionHeader.d.ts +13 -2
  72. package/lib/types/client/MobileSessionHeader.d.ts.map +1 -1
  73. package/lib/types/client/MobileSessionInfo.d.ts +20 -3
  74. package/lib/types/client/MobileSessionInfo.d.ts.map +1 -1
  75. package/lib/types/client/RemoteComposerBanner.d.ts +42 -0
  76. package/lib/types/client/RemoteComposerBanner.d.ts.map +1 -0
  77. package/lib/types/client/RemoteHeaderIcon.d.ts +37 -0
  78. package/lib/types/client/RemoteHeaderIcon.d.ts.map +1 -0
  79. package/lib/types/client/RemoteShareMenu.d.ts +28 -0
  80. package/lib/types/client/RemoteShareMenu.d.ts.map +1 -0
  81. package/lib/types/client/RemoteStatusIcon.d.ts +36 -0
  82. package/lib/types/client/RemoteStatusIcon.d.ts.map +1 -0
  83. package/lib/types/client/compat/desktop.d.ts +21 -0
  84. package/lib/types/client/compat/desktop.d.ts.map +1 -0
  85. package/lib/types/client/compat/types.d.ts +57 -0
  86. package/lib/types/client/compat/types.d.ts.map +1 -1
  87. package/lib/types/client/current-session-report.d.ts +37 -0
  88. package/lib/types/client/current-session-report.d.ts.map +1 -0
  89. package/lib/types/client/effects/header-status.d.ts.map +1 -1
  90. package/lib/types/client/effects/keyboard-guard.d.ts.map +1 -1
  91. package/lib/types/client/effects/model-group-side.d.ts +13 -0
  92. package/lib/types/client/effects/model-group-side.d.ts.map +1 -0
  93. package/lib/types/client/effects/permission-sheet.d.ts +39 -0
  94. package/lib/types/client/effects/permission-sheet.d.ts.map +1 -0
  95. package/lib/types/client/effects/remote-session.d.ts +25 -0
  96. package/lib/types/client/effects/remote-session.d.ts.map +1 -0
  97. package/lib/types/client/effects/turn-fold.d.ts +9 -0
  98. package/lib/types/client/effects/turn-fold.d.ts.map +1 -1
  99. package/lib/types/client/index.d.ts.map +1 -1
  100. package/lib/types/client/locales.d.ts +187 -2
  101. package/lib/types/client/locales.d.ts.map +1 -1
  102. package/lib/types/client/remote-fetch.d.ts +51 -0
  103. package/lib/types/client/remote-fetch.d.ts.map +1 -0
  104. package/lib/types/client/remote-group-expansion.d.ts +41 -0
  105. package/lib/types/client/remote-group-expansion.d.ts.map +1 -0
  106. package/lib/types/client/remote-share-css.d.ts +19 -0
  107. package/lib/types/client/remote-share-css.d.ts.map +1 -0
  108. package/lib/types/client/remote-share-register.d.ts +113 -0
  109. package/lib/types/client/remote-share-register.d.ts.map +1 -0
  110. package/lib/types/client/remote-status-css.d.ts +15 -0
  111. package/lib/types/client/remote-status-css.d.ts.map +1 -0
  112. package/lib/types/client/remote-status-register.d.ts +46 -0
  113. package/lib/types/client/remote-status-register.d.ts.map +1 -0
  114. package/lib/types/client/settings/SettingsSection.d.ts +46 -0
  115. package/lib/types/client/settings/SettingsSection.d.ts.map +1 -0
  116. package/lib/types/client/settings/register-settings.d.ts +58 -0
  117. package/lib/types/client/settings/register-settings.d.ts.map +1 -0
  118. package/lib/types/client/settings/settings-css.d.ts +10 -0
  119. package/lib/types/client/settings/settings-css.d.ts.map +1 -0
  120. package/lib/types/client/share/share-preview.d.ts.map +1 -1
  121. package/lib/types/client/styles/composer.css.d.ts +1 -1
  122. package/lib/types/client/styles/composer.css.d.ts.map +1 -1
  123. package/lib/types/client/styles/header.css.d.ts +1 -1
  124. package/lib/types/client/styles/header.css.d.ts.map +1 -1
  125. package/lib/types/client/styles/info.css.d.ts +1 -1
  126. package/lib/types/client/styles/info.css.d.ts.map +1 -1
  127. package/lib/types/client/styles/remote-session.css.d.ts +2 -0
  128. package/lib/types/client/styles/remote-session.css.d.ts.map +1 -0
  129. package/lib/types/client-data/current-session.d.ts +41 -0
  130. package/lib/types/client-data/current-session.d.ts.map +1 -0
  131. package/lib/types/client-data/model-group-side.d.ts +44 -0
  132. package/lib/types/client-data/model-group-side.d.ts.map +1 -0
  133. package/lib/types/client-data/remote-group-expansion.d.ts +76 -0
  134. package/lib/types/client-data/remote-group-expansion.d.ts.map +1 -0
  135. package/lib/types/client-data/remote-status.d.ts +148 -0
  136. package/lib/types/client-data/remote-status.d.ts.map +1 -0
  137. package/lib/types/client-data/settings-form.d.ts +774 -0
  138. package/lib/types/client-data/settings-form.d.ts.map +1 -0
  139. package/lib/types/client-data/shares.d.ts +211 -0
  140. package/lib/types/client-data/shares.d.ts.map +1 -0
  141. package/lib/types/client-pairing.d.ts +114 -0
  142. package/lib/types/client-pairing.d.ts.map +1 -0
  143. package/lib/types/client-routes.d.ts +112 -0
  144. package/lib/types/client-routes.d.ts.map +1 -0
  145. package/lib/types/config.d.ts +200 -0
  146. package/lib/types/config.d.ts.map +1 -0
  147. package/lib/types/fetch-route-intercept.d.ts +156 -0
  148. package/lib/types/fetch-route-intercept.d.ts.map +1 -0
  149. package/lib/types/fingerprint.d.ts +166 -0
  150. package/lib/types/fingerprint.d.ts.map +1 -0
  151. package/lib/types/http.d.ts +41 -0
  152. package/lib/types/http.d.ts.map +1 -0
  153. package/lib/types/index.d.ts +56 -24
  154. package/lib/types/index.d.ts.map +1 -1
  155. package/lib/types/intercept-shape.d.ts +32 -0
  156. package/lib/types/intercept-shape.d.ts.map +1 -0
  157. package/lib/types/intercept.d.ts +442 -0
  158. package/lib/types/intercept.d.ts.map +1 -0
  159. package/lib/types/merge-streams.d.ts +398 -0
  160. package/lib/types/merge-streams.d.ts.map +1 -0
  161. package/lib/types/relay-access.d.ts +310 -0
  162. package/lib/types/relay-access.d.ts.map +1 -0
  163. package/lib/types/relay-client.d.ts +274 -0
  164. package/lib/types/relay-client.d.ts.map +1 -0
  165. package/lib/types/relay-filter.d.ts +103 -0
  166. package/lib/types/relay-filter.d.ts.map +1 -0
  167. package/lib/types/relay-server.d.ts +208 -0
  168. package/lib/types/relay-server.d.ts.map +1 -0
  169. package/lib/types/restart-fields.d.ts +22 -0
  170. package/lib/types/restart-fields.d.ts.map +1 -0
  171. package/lib/types/restart-watcher.d.ts +83 -0
  172. package/lib/types/restart-watcher.d.ts.map +1 -0
  173. package/lib/types/session-reference.d.ts +66 -0
  174. package/lib/types/session-reference.d.ts.map +1 -0
  175. package/lib/types/share-export.d.ts +14 -1
  176. package/lib/types/share-export.d.ts.map +1 -1
  177. package/lib/types/share-ops.d.ts +79 -0
  178. package/lib/types/share-ops.d.ts.map +1 -0
  179. package/lib/types/share-store.d.ts +87 -0
  180. package/lib/types/share-store.d.ts.map +1 -0
  181. package/lib/types/virtual-id.d.ts +52 -0
  182. package/lib/types/virtual-id.d.ts.map +1 -0
  183. package/lib/virtual-id.js +66 -0
  184. package/lib/virtual-id.js.map +1 -0
  185. package/llms.txt +17 -14
  186. package/package.json +60 -50
  187. package/scripts/build-client.mjs +5 -3
  188. package/scripts/check-host-shadow.mjs +19 -2
  189. package/scripts/check-settings-form.mjs +933 -0
  190. package/scripts/check-shares.mjs +397 -0
  191. package/scripts/check-upload-endpoint.mjs +59 -3
  192. package/scripts/sync-doc-version.mjs +8 -15
  193. package/scripts/verify-fingerprint-live.mjs +111 -0
  194. package/src/activity.ts +218 -0
  195. package/src/admin-routes.ts +627 -0
  196. package/src/client/MobileAttachButton.tsx +2 -2
  197. package/src/client/MobileAttachChips.tsx +3 -3
  198. package/src/client/MobileDrawerFooter.tsx +7 -4
  199. package/src/client/MobileHome.tsx +20 -16
  200. package/src/client/MobileHomeChips.tsx +16 -16
  201. package/src/client/MobileNavOverlay.tsx +2 -2
  202. package/src/client/MobileNavToggle.tsx +3 -3
  203. package/src/client/MobileSessionHeader.tsx +63 -42
  204. package/src/client/MobileSessionInfo.tsx +118 -17
  205. package/src/client/RemoteComposerBanner.tsx +76 -0
  206. package/src/client/RemoteHeaderIcon.tsx +103 -0
  207. package/src/client/RemoteShareMenu.tsx +57 -0
  208. package/src/client/RemoteStatusIcon.tsx +91 -0
  209. package/src/client/compat/desktop.ts +22 -0
  210. package/src/client/compat/types.ts +62 -0
  211. package/src/client/current-session-report.ts +164 -0
  212. package/src/client/effects/header-status.ts +21 -17
  213. package/src/client/effects/keyboard-guard.ts +65 -1
  214. package/src/client/effects/model-group-side.ts +132 -0
  215. package/src/client/effects/permission-sheet.ts +149 -0
  216. package/src/client/effects/remote-session.ts +68 -0
  217. package/src/client/effects/turn-fold.ts +52 -0
  218. package/src/client/index.tsx +158 -36
  219. package/src/client/locales.ts +396 -2
  220. package/src/client/remote-fetch.ts +125 -0
  221. package/src/client/remote-group-expansion.ts +190 -0
  222. package/src/client/remote-share-css.ts +54 -0
  223. package/src/client/remote-share-register.ts +244 -0
  224. package/src/client/remote-status-css.ts +64 -0
  225. package/src/client/remote-status-register.ts +107 -0
  226. package/src/client/settings/SettingsSection.tsx +1229 -0
  227. package/src/client/settings/register-settings.ts +116 -0
  228. package/src/client/settings/settings-css.ts +236 -0
  229. package/src/client/share/share-preview.tsx +6 -3
  230. package/src/client/share/share-sheet.tsx +3 -3
  231. package/src/client/styles/composer.css.ts +119 -26
  232. package/src/client/styles/header.css.ts +7 -7
  233. package/src/client/styles/info.css.ts +74 -0
  234. package/src/client/styles/remote-session.css.ts +274 -0
  235. package/src/client-data/current-session.ts +57 -0
  236. package/src/client-data/model-group-side.ts +65 -0
  237. package/src/client-data/remote-group-expansion.ts +145 -0
  238. package/src/client-data/remote-status.ts +374 -0
  239. package/src/client-data/settings-form.ts +1371 -0
  240. package/src/client-data/shares.ts +467 -0
  241. package/src/client-pairing.ts +244 -0
  242. package/src/client-routes.ts +732 -0
  243. package/src/config.ts +447 -0
  244. package/src/fetch-route-intercept.ts +510 -0
  245. package/src/fingerprint.ts +410 -0
  246. package/src/http.ts +68 -0
  247. package/src/index.ts +719 -62
  248. package/src/intercept-shape.ts +87 -0
  249. package/src/intercept.ts +3510 -0
  250. package/src/merge-streams.ts +1279 -0
  251. package/src/relay-access.ts +672 -0
  252. package/src/relay-client.ts +1514 -0
  253. package/src/relay-filter.ts +291 -0
  254. package/src/relay-server.ts +2063 -0
  255. package/src/restart-fields.ts +36 -0
  256. package/src/restart-watcher.ts +140 -0
  257. package/src/session-reference.ts +156 -0
  258. package/src/share-export.ts +26 -1
  259. package/src/share-ops.ts +114 -0
  260. package/src/share-store.ts +373 -0
  261. package/src/virtual-id.ts +74 -0
package/AGENTS.md CHANGED
@@ -11,14 +11,37 @@
11
11
  | 路径 | 作用 |
12
12
  | --- | --- |
13
13
  | `package.json` | 单包声明:`dsh.bundle.patch` → `cordis.patch.yml`,`dsh.client` → `exports["./client"]` |
14
- | `cordis.patch.yml` | 组合层,三行 insert(界面 / 网关 / 推送),随包自带 |
15
- | `src/index.ts` → `lib/index.js` | host 半边入口(插件行 `dsh-zen-remote`):唯一一条路由 `POST /_dsh/mobile-nav/upload` |
16
- | `src/client/**` → `lib/client.js` | 浏览器半边(同一插件行,经 `dsh.client` 发现):app 外壳、slot、样式 |
17
- | `lan-gate.mjs` | 网关 Cordis entry(插件行 `dsh-zen-remote-gateway`):spawn 子进程 |
18
- | `lib/lan-gate-server.cjs` | 网关本体(独立 Node 子进程,Node stdlib + `web-push`) |
19
- | `dsh-push.mjs` | 推送 entry(插件行 `dsh-zen-remote-push`):回合结束推送 + `push_notify` 工具 |
14
+ | `cordis.patch.yml` | 组合层,**一行** insert(`dsh-zen-remote`),随包自带;网关与推送由主入口按角色加载,不再各占一行 |
15
+ | `src/index.ts` → `lib/index.js` | 主入口(插件行 `dsh-zen-remote`):读 `role`,host 就 `ctx.plugin()` 加载网关与推送子插件,并挂 host 路由(附件上传 / 客户端配置 / 分享导出 / 管理 / 子客户端 / 中继) |
16
+ | `src/config.ts` | 配置模型:四层回退(env > 插件行 > `lan-gate.config.json` > 默认值)、loader 的 `Config` schema(全 volatile)、`resolveRole` |
17
+ | `src/http.ts` | host 路由共用的 JSON 响应封装与同源 POST 门 |
18
+ | `src/admin-routes.ts` | 设置页管理后端 `/_dsh/zen-remote/admin/*`:代调网关本机 API(配对 / 设备 / 测试推送)+ 共享开关 |
19
+ | `src/client-routes.ts` | 子客户端路由 `/_dsh/zen-remote/client/*`:remote-status(两角色都挂,host 只应答这一条、其余 404)、配对代理、设置页诊断、plain-HTTP 转发 `client/http/*`(改动摘要 / diff) |
20
+ | `src/client-pairing.ts` | 子客户端配对纯逻辑:服务端地址归一化(http 仅限内网段)、claim/探针结果分类 |
21
+ | `src/share-store.ts` | 共享会话表(`~/.dsh/zen-remote-shares.json`,持久化,重启恢复),中继访问控制的事实来源 |
22
+ | `src/activity.ts` | 会话活动统计 + 闲置休眠扫描(`idleHours`,运行中/等待中不计时) |
23
+ | `src/share-ops.ts` | `agent/created` 的自动共享 / 分叉跟随 / busy 恢复 |
24
+ | `src/share-export.ts` | 分享图路由 `GET /_dsh/mobile-nav/share-export`(完整日志折叠人类转写) |
25
+ | `src/relay-server.ts` | 服务端中继路由 `/_dsh/zen-remote/relay/*`:ping / handshake / invoke / NDJSON stream / event-result / `v1/http`(改动摘要 / diff 的 plain-HTTP 直通,进程内交宿主 `/api` 共享 handler)/ unshare |
26
+ | `src/relay-access.ts` | 中继的按方法登记访问控制表(服务端那一张;`v1/http` 的按路由登记表也在这里) |
27
+ | `src/relay-filter.ts` | 全局流与全局列表的输出过滤(`workspace/follow` / `session/control` / `session/list` / @ 引用候选行) |
28
+ | `src/session-reference.ts` | 两端共用的 `dsh-session:` 引用编解码与「可注入文本」扫描规则(prompt content、排队消息 edit、`commands/execute` 全部字符串):服务端照它校验、子客户端照它改写,同一份规则防两端漂移 |
29
+ | `src/relay-client.ts` | 子客户端中继客户端:握手、接口指纹比对、退避重连、吊销识别 |
30
+ | `src/intercept.ts` | 子客户端本机拦截:包装 `typertGateway`,远程会话调用改走中继、虚拟 id 改写、面板判定(客户端那张字段表也在这里) |
31
+ | `src/intercept-shape.ts` | 被包装方法的形态检测,不符即拒绝安装远程拦截(本地行为不受影响) |
32
+ | `src/fetch-route-intercept.ts` | 子客户端本机拦截的第二半:包装宿主连接服务 `fetchRoutes` 表的上传与导出两项——远程会话的非图片附件经 `relay/v1/upload` 流式转服务端(超限本地拒、失败回宿主自己的 200 失败信封)、虚拟 id 的导出后台 403(形态检测、懒装重试、卸载守卫) |
33
+ | `src/virtual-id.ts` | `zr~<serverId>~<id>` 虚拟 id 算术(纯函数,无状态) |
34
+ | `src/merge-streams.ts` | 三条全局流/列表的本地 + 远程合并状态机(侧边栏远程分组) |
35
+ | `src/fingerprint.ts` | DSH 接口指纹:规范化描述符 → 分组 JSON Schema 哈希,供握手比对 |
36
+ | `src/restart-fields.ts` / `restart-watcher.ts` | 需重启字段的指纹监测,变化即重载插件行 |
37
+ | `src/client/**` → `lib/client.js` | 浏览器半边(同一插件行,经 `dsh.client` 发现):app 外壳、slot、样式、设置区块(`settings/`)、共享与远程部件(`remote-*` / `Remote*`) |
38
+ | `src/client-data/current-session.ts` + `src/client/current-session-report.ts` | 当前会话信号的浏览器上报(T62):拦截层在后台进程读不到浏览器 localStorage,由浏览器端解析宿主选择存储、值变化时 POST 到 `client/current-session` 路由;纯函数(解析 + 变化判定)与上报循环分居两文件 |
39
+ | `src/client-data/remote-group-expansion.ts` + `src/client/remote-group-expansion.ts` | 服务端分组展开状态的记忆与恢复(T64):宿主 retainAccountKeys 每次加载都清掉 zr~ 分组的展开记录,浏览器端把宿主记录镜像进自己的存储键、宿主清掉后按记录(默认展开)点击行恢复;纯函数(规划 + 解析 + 上限淘汰)与 keeper 循环分居两文件 |
40
+ | `lan-gate.mjs` | 网关子插件入口,由主入口按 host 角色加载(不再自己占插件行):spawn 子进程,共享密钥只经它进子进程 |
41
+ | `lib/lan-gate-server.cjs` | 网关本体(独立 Node 子进程,Node stdlib + `web-push`):设备角色、标记头与共享密钥、desktop-client 只放行中继前缀 |
42
+ | `dsh-push.mjs` | 推送子插件(与网关一起由主入口加载):回合结束推送 + `push_notify` 工具 |
20
43
  | `pwa/**` | manifest / service worker / 注入脚本 / 手势 / 壳级 CSS / 图标 |
21
- | `test/*.test.cjs` | 网关侧测试(真子进程 + mock 上游) |
44
+ | `test/*.test.cjs` | 网关侧测试(真子进程 + mock 上游)+ 中继端到端(`relay-e2e.test.cjs`)+ 纯逻辑导入测试 |
22
45
  | `scripts/check-*.mjs` | 界面侧自检(纯 `node:assert`,靠 Node ≥23.6 类型剥离直接 import `.ts`) |
23
46
  | `scripts/build-client.mjs` | client 打包器(内联相对模块 → `__ModuleLoader__.load({id:"dsh-zen-remote"})`) |
24
47
  | `docs/**` | 深度文档,见下 |
@@ -68,14 +91,35 @@ workflow 自带的 `GITHUB_TOKEN`,不需要额外密钥——但 job 的 `perm
68
91
 
69
92
  | 文件 | 内容 |
70
93
  | --- | --- |
71
- | [`docs/remote-access.md`](docs/remote-access.md) | 通道半边:反代配置(nginx/Caddy/Lucky)、配对流程、环境变量表、管理 API、推送、安全边界 |
72
- | [`docs/interface.md`](docs/interface.md) | 界面半边:断点策略、调试徽章、安全区体系、兼容插件清单 |
94
+ | [`docs/remote-access.md`](docs/remote-access.md) | 通道半边:反代配置(nginx/Caddy/Lucky)、设备角色与配对、环境变量表、管理 API、远程中继协议、推送、安全边界 |
95
+ | [`docs/interface.md`](docs/interface.md) | 界面半边:断点策略、设置区块与远程部件、调试徽章、安全区体系、兼容插件清单 |
73
96
 
74
97
 
75
98
  ## 合仓后仍然成立的硬约束
76
99
 
77
100
  - **网关是子进程**:`lan-gate.mjs` 只负责 spawn + 生命周期,永远不要把
78
101
  `lib/lan-gate-server.cjs` import 进 DSH 进程。
102
+ - **中继共享密钥不落地**:主入口每次 apply 现生成 `LAN_GATE_RELAY_SECRET`,
103
+ 只经环境变量交给网关子进程(无条件覆盖、缺失即删除),中继路由逐请求
104
+ `timingSafeEqual` 校验。不允许由外部环境指定,也不要把它写进日志或状态文件。
105
+ - **中继访问控制按方法登记,两张表同步**:新增远程方法必须同时登记
106
+ `src/relay-access.ts` 的 `RELAY_METHODS`(服务端,授权看登记的归属字段)
107
+ 和 `src/intercept.ts` 的 `CLIENT_METHOD_FIELDS`(客户端,改写判定),
108
+ 一致性由 `test/intercept.test.cjs` 的逐方法比对测试钉住。禁止「从参数里
109
+ 通用扫描会话 id」的写法——DSH 会悄悄丢掉不认识的参数名,扫描会被诱饵
110
+ 字段骗过;全局读(`session/list` 等)安全靠输出过滤,不靠输入判定。
111
+ - **桌面端请求没有 `Origin`/`Sec-Fetch-Site`**:DSH 桌面端主进程把窗口请求
112
+ 转发给本机后台前,自己校验过 `Origin: dsh-app://app`,然后删掉
113
+ `host` / `origin` / `cookie` / `sec-fetch-site`。所以 `src/http.ts` 的
114
+ `sameOriginPost` 对「两个头都缺」的请求是**放行**的(`admit` 顶在前面);
115
+ 别把它改成「缺 Origin 即拒绝」,那会把桌面端窗口里的所有变更请求挡掉。
116
+ 真正要拒的是可辨认的跨站(`Sec-Fetch-Site: cross-site`、Origin 与 Host 不符)。
117
+ - **volatile 字段在使用时现场读取**:`Config` 的每个字段都是 volatile——
118
+ loader 交给 `apply()` 的是 `{ get() }` 包装而不是值。任何读行配置的地方
119
+ 都要走 `unwrapVolatile`(单字段)或 `resolveConfig`(整组),禁止在
120
+ apply 时拍快照存着用;`RESTART_FIELDS` 之外的字段(`serverName`、
121
+ `idleHours`、`serverUrl`、`deviceToken`、界面旋钮)改了不重载行,
122
+ 不现场读就是永久拿到旧值。
79
123
  - **CSS 分工没变**:排版类规则在 `src/client/styles/`;`pwa/app.css` 只留壳级
80
124
  规则(iOS 输入框防缩放、安全区滚动补偿、代码块横向滚动)。两边抢同一个元素
81
125
  是历史事故的根源,加规则前先确认归属。
@@ -97,6 +141,7 @@ workflow 自带的 `GITHUB_TOKEN`,不需要额外密钥——但 job 的 `perm
97
141
  body > 块`,比组件自身结构多一层)。深度猜错的选择器**静默失效**:测试全绿、
98
142
  控制台干净,只有拿真界面量才看得出来。需要结构判断就用 JS 遍历
99
143
  (`foldsWholeRow` 那种沿父节点上溯的写法),不假设层数。
144
+ - **同机联调必须用局域网 IP 连网关**:回环地址且无转发头的请求被网关判定为「本机直连」,不校验设备令牌——同一台机器上同时跑服务端与子客户端做开发测试时,`serverUrl` 要填局域网 IP 而不是 `127.0.0.1` / `localhost`。只影响这种同机开发测试,日常两台机器(子客户端经内网/公网地址连服务端)的使用不受影响。
100
145
  - **改了界面就去真界面上量**:`turn-fold` 这类规则用自建的静态页面验证会给出
101
146
  假阳性(合成 DOM 猜不对宿主的包裹层)。打开 `127.0.0.1:3080` 读现有会话的
102
147
  `getComputedStyle` 即可,**不要为了验证去建会话或发消息**(耗真实 token,见