dsh-zen-remote 1.1.16 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) 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 +10051 -4777
  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 +363 -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 +3040 -0
  38. package/lib/intercept.js.map +1 -0
  39. package/lib/lan-gate-server.cjs +532 -121
  40. package/lib/merge-streams.js +1165 -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 +1792 -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/permission-sheet.d.ts +39 -0
  92. package/lib/types/client/effects/permission-sheet.d.ts.map +1 -0
  93. package/lib/types/client/effects/remote-session.d.ts +25 -0
  94. package/lib/types/client/effects/remote-session.d.ts.map +1 -0
  95. package/lib/types/client/effects/turn-fold.d.ts +9 -0
  96. package/lib/types/client/effects/turn-fold.d.ts.map +1 -1
  97. package/lib/types/client/index.d.ts.map +1 -1
  98. package/lib/types/client/locales.d.ts +187 -2
  99. package/lib/types/client/locales.d.ts.map +1 -1
  100. package/lib/types/client/remote-fetch.d.ts +51 -0
  101. package/lib/types/client/remote-fetch.d.ts.map +1 -0
  102. package/lib/types/client/remote-group-expansion.d.ts +41 -0
  103. package/lib/types/client/remote-group-expansion.d.ts.map +1 -0
  104. package/lib/types/client/remote-share-css.d.ts +19 -0
  105. package/lib/types/client/remote-share-css.d.ts.map +1 -0
  106. package/lib/types/client/remote-share-register.d.ts +113 -0
  107. package/lib/types/client/remote-share-register.d.ts.map +1 -0
  108. package/lib/types/client/remote-status-css.d.ts +15 -0
  109. package/lib/types/client/remote-status-css.d.ts.map +1 -0
  110. package/lib/types/client/remote-status-register.d.ts +46 -0
  111. package/lib/types/client/remote-status-register.d.ts.map +1 -0
  112. package/lib/types/client/settings/SettingsSection.d.ts +46 -0
  113. package/lib/types/client/settings/SettingsSection.d.ts.map +1 -0
  114. package/lib/types/client/settings/register-settings.d.ts +58 -0
  115. package/lib/types/client/settings/register-settings.d.ts.map +1 -0
  116. package/lib/types/client/settings/settings-css.d.ts +10 -0
  117. package/lib/types/client/settings/settings-css.d.ts.map +1 -0
  118. package/lib/types/client/share/share-preview.d.ts.map +1 -1
  119. package/lib/types/client/styles/composer.css.d.ts +1 -1
  120. package/lib/types/client/styles/composer.css.d.ts.map +1 -1
  121. package/lib/types/client/styles/header.css.d.ts +1 -1
  122. package/lib/types/client/styles/header.css.d.ts.map +1 -1
  123. package/lib/types/client/styles/info.css.d.ts +1 -1
  124. package/lib/types/client/styles/info.css.d.ts.map +1 -1
  125. package/lib/types/client/styles/remote-session.css.d.ts +2 -0
  126. package/lib/types/client/styles/remote-session.css.d.ts.map +1 -0
  127. package/lib/types/client-data/current-session.d.ts +41 -0
  128. package/lib/types/client-data/current-session.d.ts.map +1 -0
  129. package/lib/types/client-data/remote-group-expansion.d.ts +76 -0
  130. package/lib/types/client-data/remote-group-expansion.d.ts.map +1 -0
  131. package/lib/types/client-data/remote-status.d.ts +148 -0
  132. package/lib/types/client-data/remote-status.d.ts.map +1 -0
  133. package/lib/types/client-data/settings-form.d.ts +774 -0
  134. package/lib/types/client-data/settings-form.d.ts.map +1 -0
  135. package/lib/types/client-data/shares.d.ts +211 -0
  136. package/lib/types/client-data/shares.d.ts.map +1 -0
  137. package/lib/types/client-pairing.d.ts +114 -0
  138. package/lib/types/client-pairing.d.ts.map +1 -0
  139. package/lib/types/client-routes.d.ts +112 -0
  140. package/lib/types/client-routes.d.ts.map +1 -0
  141. package/lib/types/config.d.ts +200 -0
  142. package/lib/types/config.d.ts.map +1 -0
  143. package/lib/types/fetch-route-intercept.d.ts +156 -0
  144. package/lib/types/fetch-route-intercept.d.ts.map +1 -0
  145. package/lib/types/fingerprint.d.ts +164 -0
  146. package/lib/types/fingerprint.d.ts.map +1 -0
  147. package/lib/types/http.d.ts +41 -0
  148. package/lib/types/http.d.ts.map +1 -0
  149. package/lib/types/index.d.ts +56 -24
  150. package/lib/types/index.d.ts.map +1 -1
  151. package/lib/types/intercept-shape.d.ts +32 -0
  152. package/lib/types/intercept-shape.d.ts.map +1 -0
  153. package/lib/types/intercept.d.ts +432 -0
  154. package/lib/types/intercept.d.ts.map +1 -0
  155. package/lib/types/merge-streams.d.ts +393 -0
  156. package/lib/types/merge-streams.d.ts.map +1 -0
  157. package/lib/types/relay-access.d.ts +310 -0
  158. package/lib/types/relay-access.d.ts.map +1 -0
  159. package/lib/types/relay-client.d.ts +274 -0
  160. package/lib/types/relay-client.d.ts.map +1 -0
  161. package/lib/types/relay-filter.d.ts +103 -0
  162. package/lib/types/relay-filter.d.ts.map +1 -0
  163. package/lib/types/relay-server.d.ts +208 -0
  164. package/lib/types/relay-server.d.ts.map +1 -0
  165. package/lib/types/restart-fields.d.ts +22 -0
  166. package/lib/types/restart-fields.d.ts.map +1 -0
  167. package/lib/types/restart-watcher.d.ts +83 -0
  168. package/lib/types/restart-watcher.d.ts.map +1 -0
  169. package/lib/types/session-reference.d.ts +66 -0
  170. package/lib/types/session-reference.d.ts.map +1 -0
  171. package/lib/types/share-export.d.ts +14 -1
  172. package/lib/types/share-export.d.ts.map +1 -1
  173. package/lib/types/share-ops.d.ts +79 -0
  174. package/lib/types/share-ops.d.ts.map +1 -0
  175. package/lib/types/share-store.d.ts +87 -0
  176. package/lib/types/share-store.d.ts.map +1 -0
  177. package/lib/types/virtual-id.d.ts +38 -0
  178. package/lib/types/virtual-id.d.ts.map +1 -0
  179. package/lib/virtual-id.js +52 -0
  180. package/lib/virtual-id.js.map +1 -0
  181. package/llms.txt +17 -14
  182. package/package.json +60 -50
  183. package/scripts/build-client.mjs +5 -3
  184. package/scripts/check-host-shadow.mjs +19 -2
  185. package/scripts/check-settings-form.mjs +933 -0
  186. package/scripts/check-shares.mjs +397 -0
  187. package/scripts/check-upload-endpoint.mjs +59 -3
  188. package/scripts/sync-doc-version.mjs +8 -15
  189. package/scripts/verify-fingerprint-live.mjs +111 -0
  190. package/src/activity.ts +218 -0
  191. package/src/admin-routes.ts +627 -0
  192. package/src/client/MobileAttachButton.tsx +2 -2
  193. package/src/client/MobileAttachChips.tsx +3 -3
  194. package/src/client/MobileDrawerFooter.tsx +7 -4
  195. package/src/client/MobileHome.tsx +20 -16
  196. package/src/client/MobileHomeChips.tsx +16 -16
  197. package/src/client/MobileNavOverlay.tsx +2 -2
  198. package/src/client/MobileNavToggle.tsx +3 -3
  199. package/src/client/MobileSessionHeader.tsx +63 -42
  200. package/src/client/MobileSessionInfo.tsx +118 -17
  201. package/src/client/RemoteComposerBanner.tsx +76 -0
  202. package/src/client/RemoteHeaderIcon.tsx +103 -0
  203. package/src/client/RemoteShareMenu.tsx +57 -0
  204. package/src/client/RemoteStatusIcon.tsx +91 -0
  205. package/src/client/compat/desktop.ts +22 -0
  206. package/src/client/compat/types.ts +62 -0
  207. package/src/client/current-session-report.ts +164 -0
  208. package/src/client/effects/header-status.ts +21 -17
  209. package/src/client/effects/keyboard-guard.ts +65 -1
  210. package/src/client/effects/permission-sheet.ts +149 -0
  211. package/src/client/effects/remote-session.ts +68 -0
  212. package/src/client/effects/turn-fold.ts +52 -0
  213. package/src/client/index.tsx +151 -36
  214. package/src/client/locales.ts +396 -2
  215. package/src/client/remote-fetch.ts +125 -0
  216. package/src/client/remote-group-expansion.ts +190 -0
  217. package/src/client/remote-share-css.ts +54 -0
  218. package/src/client/remote-share-register.ts +244 -0
  219. package/src/client/remote-status-css.ts +64 -0
  220. package/src/client/remote-status-register.ts +107 -0
  221. package/src/client/settings/SettingsSection.tsx +1229 -0
  222. package/src/client/settings/register-settings.ts +116 -0
  223. package/src/client/settings/settings-css.ts +236 -0
  224. package/src/client/share/share-preview.tsx +6 -3
  225. package/src/client/share/share-sheet.tsx +3 -3
  226. package/src/client/styles/composer.css.ts +119 -26
  227. package/src/client/styles/header.css.ts +7 -7
  228. package/src/client/styles/info.css.ts +74 -0
  229. package/src/client/styles/remote-session.css.ts +251 -0
  230. package/src/client-data/current-session.ts +57 -0
  231. package/src/client-data/remote-group-expansion.ts +145 -0
  232. package/src/client-data/remote-status.ts +374 -0
  233. package/src/client-data/settings-form.ts +1371 -0
  234. package/src/client-data/shares.ts +467 -0
  235. package/src/client-pairing.ts +244 -0
  236. package/src/client-routes.ts +732 -0
  237. package/src/config.ts +447 -0
  238. package/src/fetch-route-intercept.ts +510 -0
  239. package/src/fingerprint.ts +408 -0
  240. package/src/http.ts +68 -0
  241. package/src/index.ts +719 -62
  242. package/src/intercept-shape.ts +87 -0
  243. package/src/intercept.ts +3362 -0
  244. package/src/merge-streams.ts +1272 -0
  245. package/src/relay-access.ts +669 -0
  246. package/src/relay-client.ts +1514 -0
  247. package/src/relay-filter.ts +291 -0
  248. package/src/relay-server.ts +2025 -0
  249. package/src/restart-fields.ts +36 -0
  250. package/src/restart-watcher.ts +140 -0
  251. package/src/session-reference.ts +156 -0
  252. package/src/share-export.ts +26 -1
  253. package/src/share-ops.ts +114 -0
  254. package/src/share-store.ts +373 -0
  255. package/src/virtual-id.ts +59 -0
@@ -0,0 +1,526 @@
1
+ /**
2
+ * Admin routes for the 2.0.0 settings surface (T14): pairing, device
3
+ * management and a push test, driven from the DSH plugin page's settings
4
+ * block (the T15 client half) instead of the gateway's own admin page.
5
+ *
6
+ * Why these live in the HOST process rather than the gateway: the gateway's
7
+ * admin API is loopback-only by design (isLocalDirect — loopback peer, no
8
+ * X-Forwarded-* headers), while a browser page runs on DSH's origin, never
9
+ * on the gateway's. So the browser talks to THESE same-origin routes and
10
+ * this module then calls the gateway AS the local machine — a bare
11
+ * `http://127.0.0.1:<port>` request with hand-built headers (no cookies, no
12
+ * Origin, no forwarded anything) that `isLocalDirect` admits.
13
+ *
14
+ * Two walls every route applies, in order:
15
+ *
16
+ * 1. `admit` — routes registered via webServer.register do NOT pass
17
+ * through DSH's `/api` authentication, so each request must ask the
18
+ * connection service itself; its rejection is relayed verbatim.
19
+ * 2. The gateway marker. A request wearing `x-zen-remote-via` arrived
20
+ * THROUGH the gateway from a remote device (the gateway strips
21
+ * client-forged copies before stamping its own). POSTs are refused —
22
+ * pairing and device management are server-side acts. GET status is
23
+ * answered, but with the live pairing code stripped. The marker wall
24
+ * runs BEFORE same-origin because a forwarded request presents as
25
+ * same-origin (the gateway rewrites Origin/Host), so the marker is the
26
+ * only thing identifying it.
27
+ *
28
+ * The ONE deliberate exception is the shares route (T33a): toggling session
29
+ * sharing is exactly what the spec grants the Web application端 (devices
30
+ * behind the gateway have full server permissions), so there the marker wall
31
+ * is skipped and a forwarded POST passes once it clears admit and
32
+ * same-origin. Desktop application clients can never reach any admin route —
33
+ * the gateway only forwards them into the relay prefix.
34
+ *
35
+ * Every POST additionally passes sameOriginPost, and bodies are capped at
36
+ * 16 KiB of JSON object. The handler is built by a factory so the tests can
37
+ * drive it over a real socket with a mock gateway and a mock admit.
38
+ */
39
+ import { request as httpRequest } from 'node:http';
40
+ import { responseJson, sameOriginPost } from './http.js';
41
+ import { restoreBusy } from './share-ops.js';
42
+ /** Prefix all admin routes live under (one webServer prefix registration). */
43
+ export const ADMIN_ROUTE_PREFIX = '/_dsh/zen-remote/admin';
44
+ /** GET: the gateway's status verbatim plus the effective config; remote
45
+ * callers get the live pairing code stripped. */
46
+ export const ADMIN_STATUS_ROUTE = `${ADMIN_ROUTE_PREFIX}/status`;
47
+ /** POST `{role}`: mint a pairing code. */
48
+ export const ADMIN_PAIR_ROUTE = `${ADMIN_ROUTE_PREFIX}/pair`;
49
+ /** POST `{action, id?, role?, kind?, name?}`: device management, whitelist below. */
50
+ export const ADMIN_ACTION_ROUTE = `${ADMIN_ROUTE_PREFIX}/action`;
51
+ /** POST: fire one fixed test notification through the gateway. */
52
+ export const ADMIN_PUSH_TEST_ROUTE = `${ADMIN_ROUTE_PREFIX}/push-test`;
53
+ /** GET: every shared session with its clocks, viewers and titles.
54
+ * POST `{action, sessionId?}`: share / unshare / unshare-all (T33a). */
55
+ export const ADMIN_SHARES_ROUTE = `${ADMIN_ROUTE_PREFIX}/shares`;
56
+ /** Longest wait for one gateway round-trip. */
57
+ const GATEWAY_TIMEOUT_MS = 5000;
58
+ /** Inbound admin body cap — the settings forms send a few hundred bytes. */
59
+ const MAX_BODY_BYTES = 16 * 1024;
60
+ /** Tag every test notification carries, so the phone can spot and sweep them. */
61
+ const TEST_PUSH_TAG = 'dsh-zen-remote-test';
62
+ /** The device-management verbs this surface forwards. `new-code` is
63
+ * deliberately absent: minting codes is the pair route's job, and forwarding
64
+ * it twice would only blur which surface created the live code. */
65
+ const FORWARDABLE_ACTIONS = new Set(['set-role', 'set-kind', 'rename', 'revoke', 'revoke-all']);
66
+ /** The share-toggle verbs POST shares understands (T33a). */
67
+ const SHARE_ACTIONS = new Set(['share', 'unshare', 'unshare-all']);
68
+ /** Longest wait for one session/projections call (titles, share existence).
69
+ * A hung typert gateway must not hold a route open forever. */
70
+ const PROJECTION_TIMEOUT_MS = 5000;
71
+ /** Fixed test-push copy — Chinese by default, English for `lang: 'en'`
72
+ * (`'auto'` has no requester signal here, so it falls to Chinese). */
73
+ const TEST_PUSH_COPY = {
74
+ zh: { title: 'DSH 测试推送', body: '这是一条来自 dsh-zen-remote 设置页的测试通知' },
75
+ en: { title: 'DSH Test Push', body: 'This is a test notification from the dsh-zen-remote settings page' },
76
+ };
77
+ /**
78
+ * One rejection carrying the status the client should see.
79
+ *
80
+ * Fields are assigned in the body rather than declared as constructor
81
+ * parameter properties: check scripts import these modules through Node's
82
+ * strip-only type stripping, which rejects that syntax (same reason as
83
+ * UploadError in index.ts).
84
+ */
85
+ class AdminError extends Error {
86
+ status;
87
+ code;
88
+ constructor(status, code, message) {
89
+ super(message);
90
+ this.name = 'AdminError';
91
+ this.status = status;
92
+ this.code = code;
93
+ }
94
+ }
95
+ /**
96
+ * Read the whole body under the cap and demand one JSON object. An empty
97
+ * body counts as `{}` — the gateway's own reader treats absence the same
98
+ * way, and the push-test button posts no body at all.
99
+ */
100
+ async function readJsonBody(req) {
101
+ // A declared oversized body is refused before a byte is read, so the client
102
+ // gets its 400 without the server (or the phone) spending the whole body on
103
+ // the wire. The streaming cap below remains as the chunked-body guard.
104
+ const declared = req.headers['content-length'];
105
+ const expected = declared === undefined ? undefined : Number(declared);
106
+ if (expected !== undefined && Number.isSafeInteger(expected) && expected > MAX_BODY_BYTES) {
107
+ throw new AdminError(400, 'bad-request', `request body exceeds the ${MAX_BODY_BYTES}-byte limit`);
108
+ }
109
+ const chunks = [];
110
+ let size = 0;
111
+ for await (const chunk of req) {
112
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
113
+ size += bytes.length;
114
+ if (size > MAX_BODY_BYTES) {
115
+ throw new AdminError(400, 'bad-request', `request body exceeds the ${MAX_BODY_BYTES}-byte limit`);
116
+ }
117
+ chunks.push(bytes);
118
+ }
119
+ const text = Buffer.concat(chunks).toString('utf8');
120
+ if (text.trim() === '')
121
+ return {};
122
+ let parsed;
123
+ try {
124
+ parsed = JSON.parse(text);
125
+ }
126
+ catch {
127
+ throw new AdminError(400, 'bad-request', 'request body must be valid JSON');
128
+ }
129
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
130
+ throw new AdminError(400, 'bad-request', 'request body must be a JSON object');
131
+ }
132
+ return parsed;
133
+ }
134
+ /**
135
+ * One call to the gateway AS the local machine: a fresh loopback connection
136
+ * with only the headers this call needs. No cookie, no Origin, and above all
137
+ * no X-Forwarded-* — any of those would make the gateway's isLocalDirect
138
+ * classify the call as proxied/remote and refuse the local-only surface.
139
+ * Resolves with whatever parsable JSON the gateway returned, at any status;
140
+ * deciding what that means for the route is the caller's job.
141
+ */
142
+ async function callGateway(options, method, path, payload) {
143
+ const body = payload === undefined ? undefined : JSON.stringify(payload);
144
+ return await new Promise((resolve, reject) => {
145
+ const request = httpRequest(new URL(path, options.gatewayBase), {
146
+ method,
147
+ headers: body === undefined
148
+ ? undefined
149
+ : { 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': String(Buffer.byteLength(body)) },
150
+ signal: AbortSignal.timeout(options.timeoutMs ?? GATEWAY_TIMEOUT_MS),
151
+ }, (response) => {
152
+ const chunks = [];
153
+ response.on('data', (chunk) => {
154
+ chunks.push(chunk);
155
+ });
156
+ response.on('error', () => {
157
+ reject(new AdminError(502, 'gateway-unreachable', 'The gateway response failed'));
158
+ });
159
+ response.on('end', () => {
160
+ try {
161
+ resolve({ status: response.statusCode ?? 0, body: JSON.parse(Buffer.concat(chunks).toString('utf8')) });
162
+ }
163
+ catch {
164
+ reject(new AdminError(502, 'gateway-unreachable', 'The gateway returned an unparsable response'));
165
+ }
166
+ });
167
+ });
168
+ request.on('error', () => {
169
+ reject(new AdminError(502, 'gateway-unreachable', 'The gateway did not answer'));
170
+ });
171
+ request.end(body);
172
+ });
173
+ }
174
+ /**
175
+ * One gateway round-trip for a state-changing route. A 2xx reply relays to
176
+ * the browser verbatim; anything else becomes a 502 error envelope — the
177
+ * gateway DID answer, but with a refusal the settings page must not mistake
178
+ * for success (and must not see raw, since the envelope shape is ours).
179
+ */
180
+ async function relay(options, method, path, payload, res) {
181
+ const reply = await callGateway(options, method, path, payload);
182
+ if (reply.status < 200 || reply.status >= 300) {
183
+ responseJson(res, 502, { ok: false, error: { code: 'gateway-error', status: reply.status } });
184
+ return;
185
+ }
186
+ responseJson(res, reply.status, reply.body);
187
+ }
188
+ function testPushPayload(lang) {
189
+ return { ...(lang === 'en' ? TEST_PUSH_COPY.en : TEST_PUSH_COPY.zh), tag: TEST_PUSH_TAG };
190
+ }
191
+ /** GET status: the gateway payload plus the live config. Recomputed per
192
+ * request — volatile row fields (serverName, idleHours, …) change without a
193
+ * plugin restart, so an apply-time snapshot would go stale. */
194
+ async function respondStatus(options, req, res) {
195
+ const viaGateway = req.headers['x-zen-remote-via'] !== undefined;
196
+ const config = options.getConfig();
197
+ let gateway = null;
198
+ let gatewayStatus = null;
199
+ let gatewayReachable = false;
200
+ try {
201
+ const reply = await callGateway(options, 'GET', '/lan-gate/status');
202
+ gatewayStatus = reply.status;
203
+ // A parsable JSON reply is not automatically a healthy gateway: an error
204
+ // envelope (403, 500) must not surface as "reachable".
205
+ if (reply.status >= 200 && reply.status < 300) {
206
+ gateway = reply.body;
207
+ gatewayReachable = true;
208
+ }
209
+ }
210
+ catch {
211
+ // No answer at all (refused, reset, timeout, non-JSON): gatewayStatus
212
+ // stays null and the settings page renders from config alone.
213
+ }
214
+ // A remote device may see the device list but never the live pairing code.
215
+ if (viaGateway && gateway !== null && typeof gateway === 'object') {
216
+ ;
217
+ gateway.pairing = null;
218
+ }
219
+ responseJson(res, 200, { ok: true, gateway, gatewayReachable, gatewayStatus, config, viaGateway });
220
+ }
221
+ /**
222
+ * One call to the typert gateway's `session/projections`, under the per-call
223
+ * timeout. Every failure mode the route can survive is a VALUE here — only
224
+ * a transport failure or a timeout throws, and the caller decides what those
225
+ * mean (titles: null; existence: 502). The typert lookup runs INSIDE the
226
+ * guard: a throwing lookup is a degraded composition, not a route failure.
227
+ * The timeout rides the call's cancellation signal (`AbortSignal.timeout`,
228
+ * the same shape the relay passes into gateway calls), so a timed-out
229
+ * invocation is actually STOPPED, not merely abandoned by the waiter.
230
+ */
231
+ async function projectionOf(options, sessionId) {
232
+ let gateway;
233
+ try {
234
+ gateway = options.typert?.();
235
+ }
236
+ catch {
237
+ return { kind: 'no-gateway' };
238
+ }
239
+ if (gateway === undefined)
240
+ return { kind: 'no-gateway' };
241
+ const value = await gateway.invoke({
242
+ namespace: 'session',
243
+ method: 'projections',
244
+ args: { request: { sessionId } },
245
+ signal: AbortSignal.timeout(options.projectionTimeoutMs ?? PROJECTION_TIMEOUT_MS),
246
+ });
247
+ if (value === null || value === undefined)
248
+ return { kind: 'no-session' };
249
+ const values = value.values;
250
+ return {
251
+ kind: 'values',
252
+ values: values !== null && typeof values === 'object' ? values : {},
253
+ };
254
+ }
255
+ /**
256
+ * One session title through `session/projections`. Anything other than a
257
+ * string answer — a null projection (session gone), a service-less or
258
+ * degraded composition, a transport failure, a timeout — is `null`, and one
259
+ * failed title must never fail the listing around it.
260
+ */
261
+ async function titleOf(options, sessionId) {
262
+ try {
263
+ const outcome = await projectionOf(options, sessionId);
264
+ if (outcome.kind !== 'values')
265
+ return null;
266
+ const title = outcome.values.title;
267
+ return typeof title === 'string' ? title : null;
268
+ }
269
+ catch {
270
+ return null;
271
+ }
272
+ }
273
+ /**
274
+ * Prove a session exists before `share` enters it into the table, and hand
275
+ * back its projection values for the caller's follow-up checks. The same
276
+ * `session/projections` call the titles use, where a `null` projection IS
277
+ * the "no such live session" answer. A transport failure or timeout is NOT
278
+ * a null — it refuses with 502 rather than quietly sharing a session nobody
279
+ * could see. Without a typert gateway there is nothing to ask, and the table
280
+ * alone is the truth available (empty values, no objection).
281
+ */
282
+ async function requireSession(options, sessionId) {
283
+ let outcome;
284
+ try {
285
+ outcome = await projectionOf(options, sessionId);
286
+ }
287
+ catch {
288
+ throw new AdminError(502, 'gateway-unreachable', 'The session lookup failed');
289
+ }
290
+ if (outcome.kind === 'no-gateway')
291
+ return {};
292
+ if (outcome.kind === 'no-session')
293
+ throw new AdminError(404, 'no-session', `no live session "${sessionId}"`);
294
+ return outcome.values;
295
+ }
296
+ /** Release one sessionQuery lease: the observation is a plain
297
+ * `Symbol.dispose` carrier (RT dsh-session-query SessionObservationReader —
298
+ * every lease pins a cold-cache entry until released). */
299
+ function releaseObservation(observation) {
300
+ const disposable = observation;
301
+ disposable[Symbol.dispose]?.();
302
+ }
303
+ /**
304
+ * Whether the session is a subagent child, judged off the DURABLE HEADER
305
+ * first: `sessionQuery.observeSession` reads the live-or-persisted session's
306
+ * immutable header (released immediately), and `origin === 'subagent'` is
307
+ * authoritative — per dsh-session's `validateSessionHeader` that marker is
308
+ * the one subagent signal, and a header WITHOUT it is an ordinary session
309
+ * (top-level or fork), full stop.
310
+ *
311
+ * Why the header wins over the projection's `subagent` identity: a fork of a
312
+ * subagent session REPLAYS the source's `subagent/descriptor` events, so the
313
+ * projection would wrongly condemn an ordinary fork — while a child whose
314
+ * descriptor turned corrupt projects null and would slip through.
315
+ *
316
+ * The projection identity stays as the fallback for compositions without
317
+ * sessionQuery and for reads that fail (session gone between the two
318
+ * lookups, unreadable log) — degraded knowledge beats none.
319
+ */
320
+ async function isSubagentSession(options, sessionId, projectionValues) {
321
+ let query;
322
+ try {
323
+ query = options.sessionQuery?.();
324
+ }
325
+ catch {
326
+ query = undefined;
327
+ }
328
+ if (query !== undefined) {
329
+ let observation;
330
+ try {
331
+ observation = await query.observeSession(sessionId);
332
+ }
333
+ catch {
334
+ observation = undefined;
335
+ }
336
+ if (observation !== undefined) {
337
+ try {
338
+ return observation.header?.origin === 'subagent';
339
+ }
340
+ finally {
341
+ releaseObservation(observation);
342
+ }
343
+ }
344
+ }
345
+ return projectionValues.subagent !== null && typeof projectionValues.subagent === 'object';
346
+ }
347
+ /** GET shares: the table verbatim, plus the derived fields the settings page
348
+ * renders — the idle countdown (busy reads `Infinity` from the store, `null`
349
+ * on the wire), the current viewer count, and the session titles, fetched
350
+ * concurrently so one slow or failing lookup delays nobody else. */
351
+ async function respondShares(options, res) {
352
+ const store = options.store;
353
+ const viewerCount = options.viewerCount ?? (() => 0);
354
+ const shares = store.list().map((entry) => {
355
+ const remaining = store.remainingMs(entry.sessionId);
356
+ return {
357
+ sessionId: entry.sessionId,
358
+ sharedAt: entry.sharedAt,
359
+ lastActivityAt: entry.lastActivityAt,
360
+ busy: entry.busy,
361
+ remainingMs: remaining === Infinity ? null : remaining,
362
+ viewers: viewerCount(entry.sessionId),
363
+ title: null,
364
+ };
365
+ });
366
+ await Promise.all(shares.map(async (row) => {
367
+ row.title = await titleOf(options, row.sessionId);
368
+ }));
369
+ responseJson(res, 200, { ok: true, shares });
370
+ }
371
+ /**
372
+ * Build the admin route handler for one plugin row. The returned handler
373
+ * owns the full response lifecycle of every request under
374
+ * {@link ADMIN_ROUTE_PREFIX} and never throws.
375
+ */
376
+ export function createAdminHandler(options) {
377
+ return async (req, res) => {
378
+ // Wall 1 first: DSH's own admission (webServer routes skip /api auth).
379
+ const admission = options.admit(req);
380
+ if ('rejection' in admission) {
381
+ responseJson(res, admission.rejection, {
382
+ ok: false,
383
+ error: { code: admission.rejection === 401 ? 'unauthorized' : 'forbidden' },
384
+ });
385
+ return;
386
+ }
387
+ const url = new URL(req.url ?? '/', 'http://dsh.internal');
388
+ const route = url.pathname;
389
+ const method = req.method ?? 'GET';
390
+ try {
391
+ if (route === ADMIN_STATUS_ROUTE) {
392
+ if (method !== 'GET') {
393
+ res.setHeader('Allow', 'GET');
394
+ responseJson(res, 405, { ok: false, error: { code: 'method-not-allowed', message: 'Use GET' } });
395
+ return;
396
+ }
397
+ await respondStatus(options, req, res);
398
+ return;
399
+ }
400
+ if (route === ADMIN_SHARES_ROUTE) {
401
+ // No table, no route: a composition that never built the share store
402
+ // answers like any unknown admin path.
403
+ if (options.store === undefined) {
404
+ responseJson(res, 404, { ok: false, error: { code: 'not-found', message: 'Unknown admin route' } });
405
+ return;
406
+ }
407
+ if (method === 'GET') {
408
+ await respondShares(options, res);
409
+ return;
410
+ }
411
+ if (method === 'POST') {
412
+ // The deliberate exception to the marker wall (see the module
413
+ // comment): the Web application端 behind the gateway may toggle
414
+ // sharing, so a via-gateway POST is NOT refused here. Same-origin
415
+ // still applies — a forwarded request passes it because the
416
+ // gateway rewrites Origin/Host onto the upstream origin.
417
+ if (!sameOriginPost(req)) {
418
+ responseJson(res, 403, {
419
+ ok: false,
420
+ error: { code: 'origin-rejected', message: 'The request must originate from this DSH Web application' },
421
+ });
422
+ return;
423
+ }
424
+ const body = await readJsonBody(req);
425
+ const action = body.action;
426
+ if (typeof action !== 'string' || !SHARE_ACTIONS.has(action)) {
427
+ responseJson(res, 400, {
428
+ ok: false,
429
+ error: { code: 'bad-action', message: `action must be one of ${[...SHARE_ACTIONS].join(', ')}` },
430
+ });
431
+ return;
432
+ }
433
+ const store = options.store;
434
+ if (action === 'unshare-all') {
435
+ for (const entry of store.list())
436
+ store.unshare(entry.sessionId, 'manual');
437
+ responseJson(res, 200, { ok: true });
438
+ return;
439
+ }
440
+ const sessionId = body.sessionId;
441
+ if (typeof sessionId !== 'string' || sessionId === '') {
442
+ responseJson(res, 400, { ok: false, error: { code: 'bad-request', message: 'sessionId is required' } });
443
+ return;
444
+ }
445
+ if (action === 'share') {
446
+ const values = await requireSession(options, sessionId);
447
+ // Subagent children never enter the table — they inherit
448
+ // reachability through the parent chain. Judged off the durable
449
+ // header when sessionQuery is reachable (a fork of a subagent
450
+ // replays the descriptor events, so the projection alone would
451
+ // both over- and under-reject — see isSubagentSession).
452
+ if (await isSubagentSession(options, sessionId, values)) {
453
+ responseJson(res, 400, {
454
+ ok: false,
455
+ error: { code: 'subagent-session', message: 'subagent sessions are reachable through their parent and cannot be shared alone' },
456
+ });
457
+ return;
458
+ }
459
+ store.share(sessionId);
460
+ // A session whose agent is mid-turn must not look idle: the same
461
+ // restore a restart runs, scoped to whatever runs right now.
462
+ restoreBusy(store, options.listAgents ?? (() => []));
463
+ responseJson(res, 200, { ok: true });
464
+ return;
465
+ }
466
+ store.unshare(sessionId, 'manual');
467
+ responseJson(res, 200, { ok: true });
468
+ return;
469
+ }
470
+ res.setHeader('Allow', 'GET, POST');
471
+ responseJson(res, 405, { ok: false, error: { code: 'method-not-allowed', message: 'Use GET or POST' } });
472
+ return;
473
+ }
474
+ if (route === ADMIN_PAIR_ROUTE || route === ADMIN_ACTION_ROUTE || route === ADMIN_PUSH_TEST_ROUTE) {
475
+ if (method !== 'POST') {
476
+ res.setHeader('Allow', 'POST');
477
+ responseJson(res, 405, { ok: false, error: { code: 'method-not-allowed', message: 'Use POST' } });
478
+ return;
479
+ }
480
+ // Wall 2, BEFORE same-origin: a forwarded remote request presents as
481
+ // same-origin (the gateway rewrites Origin/Host), so the marker is
482
+ // the only signal that says "this did not start on this machine".
483
+ if (req.headers['x-zen-remote-via'] !== undefined) {
484
+ responseJson(res, 403, {
485
+ ok: false,
486
+ error: { code: 'via-gateway', message: '配对与设备管理只能在服务端本机操作' },
487
+ });
488
+ return;
489
+ }
490
+ if (!sameOriginPost(req)) {
491
+ responseJson(res, 403, {
492
+ ok: false,
493
+ error: { code: 'origin-rejected', message: 'The request must originate from this DSH Web application' },
494
+ });
495
+ return;
496
+ }
497
+ if (route === ADMIN_PUSH_TEST_ROUTE) {
498
+ await readJsonBody(req); // drained and validated; the copy is fixed
499
+ // The copy language is read HERE, not at apply time: a lang edit on
500
+ // the row applies live, and getConfig() re-resolves per request.
501
+ await relay(options, 'POST', '/pwa/push/send', testPushPayload(options.getConfig().values.lang), res);
502
+ return;
503
+ }
504
+ const body = await readJsonBody(req);
505
+ if (route === ADMIN_ACTION_ROUTE && (typeof body.action !== 'string' || !FORWARDABLE_ACTIONS.has(body.action))) {
506
+ responseJson(res, 400, {
507
+ ok: false,
508
+ error: { code: 'bad-action', message: `action must be one of ${[...FORWARDABLE_ACTIONS].join(', ')}` },
509
+ });
510
+ return;
511
+ }
512
+ await relay(options, 'POST', route === ADMIN_PAIR_ROUTE ? '/lan-gate/pair' : '/lan-gate/action', body, res);
513
+ return;
514
+ }
515
+ responseJson(res, 404, { ok: false, error: { code: 'not-found', message: 'Unknown admin route' } });
516
+ }
517
+ catch (error) {
518
+ if (error instanceof AdminError) {
519
+ responseJson(res, error.status, { ok: false, error: { code: error.code, message: error.message } });
520
+ return;
521
+ }
522
+ responseJson(res, 500, { ok: false, error: { code: 'internal', message: 'The admin route failed' } });
523
+ }
524
+ };
525
+ }
526
+ //# sourceMappingURL=admin-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-routes.js","sourceRoot":"","sources":["../src/admin-routes.ts"],"names":[],"mappings":"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"}