@linxin666/dsh-remote-web-ui 0.3.13 → 0.3.15

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 (51) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +3 -3
  3. package/README.zh.md +3 -3
  4. package/lib/client.js +55 -21
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +174 -39
  7. package/lib/types/client/RemoteEntry.d.ts.map +1 -1
  8. package/lib/types/client/RemoteEntry.js +11 -1
  9. package/lib/types/client/RemotePanel.d.ts +5 -1
  10. package/lib/types/client/RemotePanel.d.ts.map +1 -1
  11. package/lib/types/client/RemotePanel.js +2 -2
  12. package/lib/types/client/locales.d.ts +8 -0
  13. package/lib/types/client/locales.d.ts.map +1 -1
  14. package/lib/types/client/locales.js +8 -0
  15. package/lib/types/client/mobile-adapt.d.ts.map +1 -1
  16. package/lib/types/client/mobile-adapt.js +7 -12
  17. package/lib/types/client/remote-channel.d.ts +0 -2
  18. package/lib/types/client/remote-channel.d.ts.map +1 -1
  19. package/lib/types/client/remote-channel.js +0 -4
  20. package/lib/types/index.d.ts +9 -1
  21. package/lib/types/index.d.ts.map +1 -1
  22. package/lib/types/index.js +54 -27
  23. package/lib/types/loopback-proxy.d.ts.map +1 -1
  24. package/lib/types/loopback-proxy.js +16 -0
  25. package/lib/types/remote-api.d.ts +1 -1
  26. package/lib/types/remote-api.d.ts.map +1 -1
  27. package/lib/types/remote-api.js +1 -1
  28. package/lib/types/remote-channel-boot.d.ts.map +1 -1
  29. package/lib/types/remote-channel-boot.js +0 -1
  30. package/lib/types/remote-channel-rules.d.ts +0 -1
  31. package/lib/types/remote-channel-rules.d.ts.map +1 -1
  32. package/lib/types/remote-channel-rules.js +0 -1
  33. package/lib/types/remote-methods.d.ts +1 -4
  34. package/lib/types/remote-methods.d.ts.map +1 -1
  35. package/lib/types/remote-methods.js +1 -5
  36. package/lib/types/routes.d.ts +26 -2
  37. package/lib/types/routes.d.ts.map +1 -1
  38. package/lib/types/routes.js +150 -5
  39. package/package.json +18 -18
  40. package/src/client/RemoteEntry.tsx +12 -0
  41. package/src/client/RemotePanel.tsx +37 -2
  42. package/src/client/locales.ts +8 -0
  43. package/src/client/mobile-adapt.ts +5 -10
  44. package/src/client/remote-channel.ts +0 -3
  45. package/src/index.ts +59 -26
  46. package/src/loopback-proxy.ts +15 -0
  47. package/src/remote-api.ts +0 -1
  48. package/src/remote-channel-boot.ts +0 -1
  49. package/src/remote-channel-rules.ts +0 -2
  50. package/src/remote-methods.ts +1 -6
  51. package/src/routes.ts +141 -7
@@ -214,7 +214,6 @@ const ADAPT_CSS = [
214
214
  `body.${ACTIVE_CLASS} [data-dsh-plugin=\"task-board\"],`,
215
215
  `body.${ACTIVE_CLASS} [data-dsh-plugin=\"git-graph\"],`,
216
216
  `body.${ACTIVE_CLASS} [data-dsh-plugin=\"pet\"],`,
217
- `body.${ACTIVE_CLASS} [data-dsh-plugin=\"perf\"],`,
218
217
  `body.${ACTIVE_CLASS} [data-dsh-plugin=\"usage\"]{display:none !important}`,
219
218
  // The official workbench (Files / source control) mounts into a
220
219
  // full-viewport portal layer with no data-dsh-plugin root, so the plugin
@@ -965,17 +964,13 @@ export function startMobileAdapt() {
965
964
  }
966
965
  lanOrigFocus.call(this, options);
967
966
  };
968
- let lastComposerTapRegistered = false;
969
- if (!lastComposerTapRegistered) {
970
- lastComposerTapRegistered = true;
971
- document.addEventListener('pointerdown', (e) => {
972
- if (!active)
973
- return;
974
- const t = e.target;
975
- if (t instanceof Element && (t.tagName === 'TEXTAREA' || t.tagName === 'INPUT') && t.closest('[class$="_composerSeat"]') !== null)
976
- lastComposerTap = Date.now();
977
- }, true);
978
- }
967
+ document.addEventListener('pointerdown', (e) => {
968
+ if (!active)
969
+ return;
970
+ const t = e.target;
971
+ if (t instanceof Element && (t.tagName === 'TEXTAREA' || t.tagName === 'INPUT') && t.closest('[class$="_composerSeat"]') !== null)
972
+ lastComposerTap = Date.now();
973
+ }, true);
979
974
  // The plugin apply() wires toggleSidebar/closeDetails to ctx.layout once
980
975
  // it is live, and flips the master switch when the settings snapshot
981
976
  // settles.
@@ -11,8 +11,6 @@
11
11
  * - the pairing routes (`/api/pair/*`) stay where they are — accept must
12
12
  * work BEFORE a device is paired;
13
13
  * - the update endpoints (`/api/update/*`) stay loopback-only;
14
- * - desktop-launcher create/shutdown (`/api/dsh-desktop-launcher/*`) stay
15
- * loopback-only (host-local files and process exit);
16
14
  * - the family settings bridge (`/api/dsh-web-ui-settings/*`) stays
17
15
  * loopback-only (same plane as SDK settings.*);
18
16
  * - `/api/*` (SDK methods and `/api/<plugin>/...` plugin namespaces),
@@ -1 +1 @@
1
- {"version":3,"file":"remote-channel.d.ts","sourceRoot":"","sources":["../../../src/client/remote-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,iBAAiB,EAEjB,aAAa,EACd,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAA;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AAIvE,qEAAqE;AACrE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAA;IACpD,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC9D;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,6BAA6B,EACvC,iBAAiB,EAAE,OAAO,GAAG,SAAS,GACrC,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAcnF;AAED,wEAAwE;AACxE,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAA;IAC3B,WAAW,CAAC,EAAE,OAAO,WAAW,CAAA;IAChC,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,cAAc,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACzD;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAoBD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E;AA0BD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,IAAI,CAmG1G;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,iBAAiB,CAIxF"}
1
+ {"version":3,"file":"remote-channel.d.ts","sourceRoot":"","sources":["../../../src/client/remote-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EACL,iBAAiB,EAEjB,aAAa,EACd,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAA;AAC3C,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AAIvE,qEAAqE;AACrE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAA;IACpD,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC9D;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,6BAA6B,EACvC,iBAAiB,EAAE,OAAO,GAAG,SAAS,GACrC,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI5D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAShE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAcnF;AAED,wEAAwE;AACxE,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAA;IAC3B,WAAW,CAAC,EAAE,OAAO,WAAW,CAAA;IAChC,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,iBAAiB,CAAC,EAAE,cAAc,CAAA;IAClC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,cAAc,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CACzD;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAoBD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E;AA0BD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,IAAI,CAmG1G;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,iBAAiB,CAIxF"}
@@ -11,8 +11,6 @@
11
11
  * - the pairing routes (`/api/pair/*`) stay where they are — accept must
12
12
  * work BEFORE a device is paired;
13
13
  * - the update endpoints (`/api/update/*`) stay loopback-only;
14
- * - desktop-launcher create/shutdown (`/api/dsh-desktop-launcher/*`) stay
15
- * loopback-only (host-local files and process exit);
16
14
  * - the family settings bridge (`/api/dsh-web-ui-settings/*`) stays
17
15
  * loopback-only (same plane as SDK settings.*);
18
16
  * - `/api/*` (SDK methods and `/api/<plugin>/...` plugin namespaces),
@@ -60,8 +58,6 @@ export function shouldRewriteFetchPath(pathname) {
60
58
  return false;
61
59
  if (pathname.startsWith(RULES.updatePrefix))
62
60
  return false;
63
- if (pathname === RULES.desktopLauncherPrefix || pathname.startsWith(`${RULES.desktopLauncherPrefix}/`))
64
- return false;
65
61
  if (pathname === RULES.settingsBridgePrefix || pathname.startsWith(`${RULES.settingsBridgePrefix}/`))
66
62
  return false;
67
63
  if (pathname.startsWith(RULES.apiPrefix))
@@ -76,6 +76,13 @@ export interface Config {
76
76
  * warning (LAN-only behavior preserved). Ignored while `autoTunnel` is on.
77
77
  */
78
78
  publicBaseUrl?: string;
79
+ /**
80
+ * Extra trusted host authorities (exact host:port or port-less host) allowed
81
+ * to access pairing endpoints and remote web services. Useful in Docker, reverse proxy,
82
+ * or NAT environments where incoming request Host headers differ from the container's
83
+ * internal network addresses. Can also be set via the DSH_REMOTE_TRUSTED_HOSTS env var.
84
+ */
85
+ trustedHosts?: string[];
79
86
  /**
80
87
  * Absolute path to a JSON file where paired device sessions are persisted.
81
88
  * Defaults to `$DSH_HOME/remote-web-ui-devices.json` so a paired device
@@ -146,8 +153,9 @@ export declare const Config: z<Config>;
146
153
  * which legitimately resolves to `undefined` when unset (the schema keeps it
147
154
  * optional, so `Required` alone would over-narrow it to `string`).
148
155
  */
149
- type ResolvedConfig = Required<Omit<Config, 'publicBaseUrl' | 'devicesFile' | 'lanBind' | 'profile' | 'tunnelToken'>> & {
156
+ type ResolvedConfig = Required<Omit<Config, 'publicBaseUrl' | 'trustedHosts' | 'devicesFile' | 'lanBind' | 'profile' | 'tunnelToken'>> & {
150
157
  publicBaseUrl: string | undefined;
158
+ trustedHosts: string[] | undefined;
151
159
  devicesFile: string;
152
160
  /** undefined until the user flips the toggle once; undefined never writes the patch. */
153
161
  lanBind: boolean | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,7 @@ export const Config = z.object({
50
50
  cookieName: z.string().min(1).default('dsh_pair'),
51
51
  requirePairingForLan: z.boolean().default(true),
52
52
  publicBaseUrl: z.string(),
53
+ trustedHosts: z.array(z.string()),
53
54
  devicesFile: z.string(),
54
55
  autoTunnel: z.boolean().default(false),
55
56
  tunnelToken: z.string().role('secret'),
@@ -89,6 +90,7 @@ const DEFAULTS = {
89
90
  cookieName: 'dsh_pair',
90
91
  requirePairingForLan: true,
91
92
  publicBaseUrl: undefined,
93
+ trustedHosts: undefined,
92
94
  devicesFile: defaultDevicesFile(),
93
95
  autoTunnel: false,
94
96
  tunnelToken: undefined,
@@ -104,6 +106,7 @@ const DEFAULTS = {
104
106
  */
105
107
  export const apply = mountOnce('@linxin666/dsh-remote-web-ui', applyImpl);
106
108
  function applyImpl(ctx, config) {
109
+ const envPublicBase = process.env.DSH_REMOTE_PUBLIC_BASE_URL?.trim() || undefined;
107
110
  const resolved = {
108
111
  tokenTtlMs: config?.tokenTtlMs ?? DEFAULTS.tokenTtlMs,
109
112
  offlineAfterMs: config?.offlineAfterMs ?? DEFAULTS.offlineAfterMs,
@@ -111,7 +114,8 @@ function applyImpl(ctx, config) {
111
114
  idleExpireMs: config?.idleExpireMs ?? DEFAULTS.idleExpireMs,
112
115
  cookieName: config?.cookieName ?? DEFAULTS.cookieName,
113
116
  requirePairingForLan: config?.requirePairingForLan ?? DEFAULTS.requirePairingForLan,
114
- publicBaseUrl: config?.publicBaseUrl,
117
+ publicBaseUrl: config?.publicBaseUrl ?? envPublicBase,
118
+ trustedHosts: config?.trustedHosts,
115
119
  devicesFile: config?.devicesFile ?? DEFAULTS.devicesFile,
116
120
  autoTunnel: config?.autoTunnel ?? DEFAULTS.autoTunnel,
117
121
  tunnelToken: config?.tunnelToken,
@@ -133,7 +137,8 @@ function applyImpl(ctx, config) {
133
137
  idleExpireMs: value.idleExpireMs ?? DEFAULTS.idleExpireMs,
134
138
  cookieName: value.cookieName ?? DEFAULTS.cookieName,
135
139
  requirePairingForLan: value.requirePairingForLan ?? DEFAULTS.requirePairingForLan,
136
- publicBaseUrl: value.publicBaseUrl,
140
+ publicBaseUrl: value.publicBaseUrl ?? envPublicBase,
141
+ trustedHosts: value.trustedHosts,
137
142
  devicesFile: value.devicesFile ?? DEFAULTS.devicesFile,
138
143
  autoTunnel: value.autoTunnel ?? DEFAULTS.autoTunnel,
139
144
  tunnelToken: value.tunnelToken,
@@ -282,14 +287,16 @@ function applyImpl(ctx, config) {
282
287
  // directory on update, so a boot-time captured path would fail to read
283
288
  // after a successful update; versions are re-read from disk per check.
284
289
  const requireFromHost = createRequire(import.meta.url);
285
- const resolveAnchorPath = () => resolveAnchorManifest(specifier => {
290
+ /** Host-process resolve that degrades to "not installed" (undefined) instead of throwing. */
291
+ const hostResolve = (specifier) => {
286
292
  try {
287
293
  return requireFromHost.resolve(specifier);
288
294
  }
289
295
  catch {
290
296
  return undefined;
291
297
  }
292
- });
298
+ };
299
+ const resolveAnchorPath = () => resolveAnchorManifest(hostResolve);
293
300
  const releaseNotesCache = new Map();
294
301
  const fetchReleaseNotesCached = async (version) => {
295
302
  const cached = releaseNotesCache.get(version);
@@ -305,14 +312,7 @@ function applyImpl(ctx, config) {
305
312
  fence: request => isTrustedApiRequest(request, []),
306
313
  check: () => checkUpdates({
307
314
  anchorManifestPath: resolveAnchorPath(),
308
- resolve: specifier => {
309
- try {
310
- return requireFromHost.resolve(specifier);
311
- }
312
- catch {
313
- return undefined;
314
- }
315
- },
315
+ resolve: hostResolve,
316
316
  fetchLatest: name => fetchLatestVersion(name, fetch),
317
317
  fetchReleaseNotes: fetchReleaseNotesCached,
318
318
  }),
@@ -336,14 +336,7 @@ function applyImpl(ctx, config) {
336
336
  run: { profileDir: target.profileDir, packages: target.packages },
337
337
  check: {
338
338
  anchorManifestPath: resolveAnchorPath(),
339
- resolve: specifier => {
340
- try {
341
- return requireFromHost.resolve(specifier);
342
- }
343
- catch {
344
- return undefined;
345
- }
346
- },
339
+ resolve: hostResolve,
347
340
  fetchLatest: name => fetchLatestVersion(name, fetch),
348
341
  fetchReleaseNotes: fetchReleaseNotesCached,
349
342
  },
@@ -437,10 +430,31 @@ function applyImpl(ctx, config) {
437
430
  const routes = [
438
431
  ...makeRoutes({
439
432
  service,
440
- lanAddresses: service.lanAddresses,
441
433
  requirePairingForLan: () => resolve().requirePairingForLan,
442
434
  lanBindStatus,
443
435
  indexDocument: fetchAppShell,
436
+ trustedHosts: () => {
437
+ const list = [];
438
+ const envHosts = process.env.DSH_REMOTE_TRUSTED_HOSTS;
439
+ if (typeof envHosts === 'string' && envHosts.trim() !== '') {
440
+ for (const item of envHosts.split(',')) {
441
+ const trimmed = item.trim();
442
+ if (trimmed !== '')
443
+ list.push(trimmed);
444
+ }
445
+ }
446
+ const cfgHosts = resolve().trustedHosts;
447
+ if (Array.isArray(cfgHosts)) {
448
+ for (const item of cfgHosts) {
449
+ if (typeof item === 'string') {
450
+ const trimmed = item.trim();
451
+ if (trimmed !== '')
452
+ list.push(trimmed);
453
+ }
454
+ }
455
+ }
456
+ return list;
457
+ },
444
458
  }),
445
459
  // The remote desktop channel: policy-gated `/remote` prefix that
446
460
  // re-issues fenced paths to loopback (see remote-api.ts). The live
@@ -709,13 +723,26 @@ function applyImpl(ctx, config) {
709
723
  table.push({ kind: 'script', placement: 'head', text: REMOTE_CHANNEL_BOOT_SCRIPT });
710
724
  }), 'remote-web-ui: remote channel boot patch');
711
725
  ctx.inject(['settings'], (settingsCtx) => {
712
- settingsCtx.settings.installSection(ctx, REMOTE_WEB_UI_SETTINGS_NAMESPACE, Config, config ?? {}, {
713
- setSource: (source) => {
714
- current = source;
726
+ try {
727
+ if (typeof settingsCtx.settings?.installSection === 'function') {
728
+ settingsCtx.settings.installSection(ctx, REMOTE_WEB_UI_SETTINGS_NAMESPACE, Config, config ?? {}, {
729
+ setSource: (source) => {
730
+ current = source;
731
+ sync();
732
+ },
733
+ onChange: sync,
734
+ });
735
+ }
736
+ else if (typeof settingsCtx.settings?.register === 'function') {
737
+ const scope = settingsCtx.settings.register(REMOTE_WEB_UI_SETTINGS_NAMESPACE, Config, { base: config ?? {} });
738
+ current = () => scope?.get?.() ?? (config ?? {});
739
+ scope?.watch?.(() => { sync(); });
715
740
  sync();
716
- },
717
- onChange: sync,
718
- });
741
+ }
742
+ }
743
+ catch {
744
+ // Defensive fallback against settings registration differences
745
+ }
719
746
  });
720
747
  sync();
721
748
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loopback-proxy.d.ts","sourceRoot":"","sources":["../../src/loopback-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAuB,cAAc,EAAE,MAAM,WAAW,CAAA;AAGrF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAoBhD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,SAAS,GACf,IAAI,CAIN;AAmDD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAoCN"}
1
+ {"version":3,"file":"loopback-proxy.d.ts","sourceRoot":"","sources":["../../src/loopback-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAuB,cAAc,EAAE,MAAM,WAAW,CAAA;AAGrF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAoBhD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,SAAS,GACf,IAAI,CAIN;AAkED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAoCN"}
@@ -77,6 +77,18 @@ function pipeLoopbackHttp(req, res, port, upstreamPath, auth, cookie) {
77
77
  }
78
78
  res.writeHead(upstreamRes.statusCode ?? 502, out);
79
79
  upstreamRes.pipe(res);
80
+ // Inner leg died mid-response (reset, truncation): tear the outer leg
81
+ // down instead of letting the truncated response raise an unhandled
82
+ // 'error' with no listener.
83
+ upstreamRes.on('error', () => { res.destroy(); });
84
+ // Outer leg died before the response finished (phone left mid-request):
85
+ // reset the inner request so the loopback server stops working on a call
86
+ // nobody will read. Guarded so a normal completion never destroys a
87
+ // keep-alive socket the agent would reuse.
88
+ res.on('close', () => {
89
+ if (!upstreamRes.readableEnded)
90
+ upstream.destroy();
91
+ });
80
92
  });
81
93
  upstream.on('error', () => {
82
94
  if (!res.headersSent) {
@@ -85,6 +97,10 @@ function pipeLoopbackHttp(req, res, port, upstreamPath, auth, cookie) {
85
97
  }
86
98
  res.destroy();
87
99
  });
100
+ // The outer request aborted mid-body: reset the inner request instead of
101
+ // feeding it a truncated body that still gets processed (mirror of the
102
+ // upgrade path's two-leg teardown).
103
+ req.on('error', () => { upstream.destroy(); });
88
104
  req.pipe(upstream);
89
105
  }
90
106
  /**
@@ -25,7 +25,7 @@ import type { IncomingMessage } from 'node:http';
25
25
  import type { WebRoute, WebUpgradeRoute } from '@deepseek-ai/dsh-host-webserver';
26
26
  import type { PairingService } from './pairing.ts';
27
27
  import type { InnerAuth } from './inner-auth.ts';
28
- export { DESKTOP_LAUNCHER_PATH, LOCAL_ONLY_PREFIXES, PLUGIN_MANAGER_PATH, REMOTE_API_PATHS, REMOTE_DEVICE_HEADER, REMOTE_DEVICE_QUERY, REMOTE_PREFIX, REMOTE_UPGRADE_PATHS, WEB_UI_SETTINGS_BRIDGE_PATH, localOnlyDenial, } from './remote-methods.ts';
28
+ export { LOCAL_ONLY_PREFIXES, PLUGIN_MANAGER_PATH, REMOTE_API_PATHS, REMOTE_DEVICE_HEADER, REMOTE_DEVICE_QUERY, REMOTE_PREFIX, REMOTE_UPGRADE_PATHS, WEB_UI_SETTINGS_BRIDGE_PATH, localOnlyDenial, } from './remote-methods.ts';
29
29
  export { REMOTE_API_PREFIX } from './remote-methods.ts';
30
30
  /** Route-family dependencies. */
31
31
  export interface RemoteApiDeps {
@@ -1 +1 @@
1
- {"version":3,"file":"remote-api.d.ts","sourceRoot":"","sources":["../../src/remote-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAUhD,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAgBvD,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,OAAO,EAAE,cAAc,CAAA;IACvB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAA;IAChD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAWD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUhE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAQlG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,QAAQ,EAAE,CA0CnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAWzF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,aAAa,GAAG,eAAe,EAAE,CA2CjF"}
1
+ {"version":3,"file":"remote-api.d.ts","sourceRoot":"","sources":["../../src/remote-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAA;AAEhE,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAUhD,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAgBvD,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,OAAO,EAAE,cAAc,CAAA;IACvB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAA;IAChD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAWD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUhE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAQlG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,QAAQ,EAAE,CA0CnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAWzF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,aAAa,GAAG,eAAe,EAAE,CA2CjF"}
@@ -25,7 +25,7 @@ import { readCookie } from "./gate.js";
25
25
  import { writeJson } from "./http.js";
26
26
  import { proxyLoopbackHttp, proxyLoopbackUpgrade } from "./loopback-proxy.js";
27
27
  import { REMOTE_DEVICE_HEADER, REMOTE_DEVICE_QUERY, REMOTE_PREFIX, REMOTE_UPGRADE_PATHS, localOnlyDenial, } from "./remote-methods.js";
28
- export { DESKTOP_LAUNCHER_PATH, LOCAL_ONLY_PREFIXES, PLUGIN_MANAGER_PATH, REMOTE_API_PATHS, REMOTE_DEVICE_HEADER, REMOTE_DEVICE_QUERY, REMOTE_PREFIX, REMOTE_UPGRADE_PATHS, WEB_UI_SETTINGS_BRIDGE_PATH, localOnlyDenial, } from "./remote-methods.js";
28
+ export { LOCAL_ONLY_PREFIXES, PLUGIN_MANAGER_PATH, REMOTE_API_PATHS, REMOTE_DEVICE_HEADER, REMOTE_DEVICE_QUERY, REMOTE_PREFIX, REMOTE_UPGRADE_PATHS, WEB_UI_SETTINGS_BRIDGE_PATH, localOnlyDenial, } from "./remote-methods.js";
29
29
  export { REMOTE_API_PREFIX } from "./remote-methods.js";
30
30
  const ALLOWED_METHODS = new Set(['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE']);
31
31
  /** Reject traversal and empty segments; allow plugin file-path characters. */
@@ -1 +1 @@
1
- {"version":3,"file":"remote-channel-boot.d.ts","sourceRoot":"","sources":["../../src/remote-channel-boot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAoD,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAErH;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,GAAE,kBAAyC,GAAG,MAAM,CA+HrG;AAED,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,2BAA2B,CAAA;AAQzD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,SAAwB,EAAE,MAAM,SAAwB,GAAG,MAAM,CAgB9G;AAED,0EAA0E;AAC1E,eAAO,MAAM,0BAA0B,EAAE,MAAuC,CAAA"}
1
+ {"version":3,"file":"remote-channel-boot.d.ts","sourceRoot":"","sources":["../../src/remote-channel-boot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAoD,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAErH;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,GAAE,kBAAyC,GAAG,MAAM,CA8HrG;AAED,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,2BAA2B,CAAA;AAQzD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,SAAwB,EAAE,MAAM,SAAwB,GAAG,MAAM,CAgB9G;AAED,0EAA0E;AAC1E,eAAO,MAAM,0BAA0B,EAAE,MAAuC,CAAA"}
@@ -57,7 +57,6 @@ export function buildRemoteChannelBootScript(rules = REMOTE_CHANNEL_RULES) {
57
57
  'function sf(p){' +
58
58
  'if(p.indexOf(R.pairPrefix)===0)return false;' +
59
59
  'if(p.indexOf(R.updatePrefix)===0)return false;' +
60
- 'if(p===R.desktopLauncherPrefix||p.indexOf(R.desktopLauncherPrefix+"/")===0)return false;' +
61
60
  'if(p===R.settingsBridgePrefix||p.indexOf(R.settingsBridgePrefix+"/")===0)return false;' +
62
61
  'if(p.indexOf(R.apiPrefix)===0)return true;' +
63
62
  'if(p.indexOf(R.sidebarPrefix)===0||p==="/sidebar")return true;' +
@@ -17,7 +17,6 @@ export interface RemoteChannelRules {
17
17
  readonly apiPrefix: string;
18
18
  readonly pairPrefix: string;
19
19
  readonly updatePrefix: string;
20
- readonly desktopLauncherPrefix: string;
21
20
  readonly settingsBridgePrefix: string;
22
21
  readonly sidebarPrefix: string;
23
22
  readonly gitPrefix: string;
@@ -1 +1 @@
1
- {"version":3,"file":"remote-channel-rules.d.ts","sourceRoot":"","sources":["../../src/remote-channel-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kEAAkE;AAClE,eAAO,MAAM,aAAa,YAAY,CAAA;AAEtC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAE/E,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,CAAA;AAEpD,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,gBAAyB,CAAA;AAEvD,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAA;IACtC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,yBAAyB;AACzB,eAAO,MAAM,oBAAoB,EAAE,kBAsBlC,CAAA;AAED,iEAAiE;AACjE,eAAO,MAAM,0BAA0B,gCAAgC,CAAA;AAEvE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAC/B,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAC7B,eAAe,EAAE,OAAO,CAAA;IACxB,OAAO,IAAI,IAAI,CAAA;CAChB"}
1
+ {"version":3,"file":"remote-channel-rules.d.ts","sourceRoot":"","sources":["../../src/remote-channel-rules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,kEAAkE;AAClE,eAAO,MAAM,aAAa,YAAY,CAAA;AAEtC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAE/E,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,CAAA;AAEpD,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,gBAAyB,CAAA;AAEvD,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,yBAAyB;AACzB,eAAO,MAAM,oBAAoB,EAAE,kBAqBlC,CAAA;AAED,iEAAiE;AACjE,eAAO,MAAM,0BAA0B,gCAAgC,CAAA;AAEvE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAC/B,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAC7B,eAAe,EAAE,OAAO,CAAA;IACxB,OAAO,IAAI,IAAI,CAAA;CAChB"}
@@ -17,7 +17,6 @@ export const REMOTE_CHANNEL_RULES = {
17
17
  apiPrefix: '/api/',
18
18
  pairPrefix: '/api/pair/',
19
19
  updatePrefix: '/api/update/',
20
- desktopLauncherPrefix: '/api/dsh-desktop-launcher',
21
20
  settingsBridgePrefix: '/api/dsh-web-ui-settings',
22
21
  sidebarPrefix: '/sidebar/',
23
22
  gitPrefix: '/git/',
@@ -34,8 +34,6 @@ export declare const REMOTE_API_PATHS: {
34
34
  export declare const REMOTE_UPGRADE_PATHS: readonly ["/remote/api/remote.mux", "/remote/sidebar/ws/terminal", "/remote/sidebar/ws/agent-terminals", "/remote/api/dsh-ssh/terminal"];
35
35
  /** Plugin-manager HTTP prefix: install/remove stay physically local. */
36
36
  export declare const PLUGIN_MANAGER_PATH = "/api/plugin-manager";
37
- /** Desktop-launcher HTTP prefix: shortcut create and host shutdown stay physically local. */
38
- export declare const DESKTOP_LAUNCHER_PATH = "/api/dsh-desktop-launcher";
39
37
  /** Family settings-bridge HTTP prefix — re-exposed to paired devices (plain settings parity). */
40
38
  export declare const WEB_UI_SETTINGS_BRIDGE_PATH = "/api/dsh-web-ui-settings";
41
39
  /**
@@ -54,8 +52,7 @@ export declare const REMOTE_DEVICE_QUERY = "device";
54
52
  * paired remote desktop may use the full host API (chat, sessions,
55
53
  * settings, credentials, presets — it is a full-control credential), but it
56
54
  * must not reach the machine-control planes: pairing control itself, the
57
- * dsh-web self-update installer, plugin install/remove, and desktop
58
- * launcher actions (host shutdown, shortcuts).
55
+ * dsh-web self-update installer, and plugin install/remove.
59
56
  */
60
57
  export declare const LOCAL_ONLY_PREFIXES: readonly string[];
61
58
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"remote-methods.d.ts","sourceRoot":"","sources":["../../src/remote-methods.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gFAAgF;AAChF,eAAO,MAAM,aAAa,YAAY,CAAA;AAEtC,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,gBAAyB,CAAA;AAEvD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB;;CAEnB,CAAA;AAEV;;;GAGG;AACH,eAAO,MAAM,oBAAoB,0IAKvB,CAAA;AAEV,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,wBAAwB,CAAA;AAExD,6FAA6F;AAC7F,eAAO,MAAM,qBAAqB,8BAA8B,CAAA;AAEhE,iGAAiG;AACjG,eAAO,MAAM,2BAA2B,6BAA6B,CAAA;AAErE;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,wBAAwB,CAAA;AACzD,eAAO,MAAM,mBAAmB,WAAW,CAAA;AAE3C;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAKvC,CAAA;AAEV;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOrE"}
1
+ {"version":3,"file":"remote-methods.d.ts","sourceRoot":"","sources":["../../src/remote-methods.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gFAAgF;AAChF,eAAO,MAAM,aAAa,YAAY,CAAA;AAEtC,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,gBAAyB,CAAA;AAEvD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB;;CAEnB,CAAA;AAEV;;;GAGG;AACH,eAAO,MAAM,oBAAoB,0IAKvB,CAAA;AAEV,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,wBAAwB,CAAA;AAExD,iGAAiG;AACjG,eAAO,MAAM,2BAA2B,6BAA6B,CAAA;AAErE;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,wBAAwB,CAAA;AACzD,eAAO,MAAM,mBAAmB,WAAW,CAAA;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAIvC,CAAA;AAEV;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOrE"}
@@ -39,8 +39,6 @@ export const REMOTE_UPGRADE_PATHS = [
39
39
  ];
40
40
  /** Plugin-manager HTTP prefix: install/remove stay physically local. */
41
41
  export const PLUGIN_MANAGER_PATH = '/api/plugin-manager';
42
- /** Desktop-launcher HTTP prefix: shortcut create and host shutdown stay physically local. */
43
- export const DESKTOP_LAUNCHER_PATH = '/api/dsh-desktop-launcher';
44
42
  /** Family settings-bridge HTTP prefix — re-exposed to paired devices (plain settings parity). */
45
43
  export const WEB_UI_SETTINGS_BRIDGE_PATH = '/api/dsh-web-ui-settings';
46
44
  /**
@@ -59,14 +57,12 @@ export const REMOTE_DEVICE_QUERY = 'device';
59
57
  * paired remote desktop may use the full host API (chat, sessions,
60
58
  * settings, credentials, presets — it is a full-control credential), but it
61
59
  * must not reach the machine-control planes: pairing control itself, the
62
- * dsh-web self-update installer, plugin install/remove, and desktop
63
- * launcher actions (host shutdown, shortcuts).
60
+ * dsh-web self-update installer, and plugin install/remove.
64
61
  */
65
62
  export const LOCAL_ONLY_PREFIXES = [
66
63
  '/api/pair',
67
64
  '/api/update',
68
65
  PLUGIN_MANAGER_PATH,
69
- DESKTOP_LAUNCHER_PATH,
70
66
  ];
71
67
  /**
72
68
  * Whether a paired inner path must stay physically local.
@@ -31,6 +31,17 @@ import { type PairingService, type PairingSnapshot } from './pairing.ts';
31
31
  * browser markers are same-origin.
32
32
  */
33
33
  export declare function isTrustedApiRequest(request: IncomingMessage, trustedHosts: readonly string[]): boolean;
34
+ /**
35
+ * Test whether a hostname represents a private local-area network (RFC 1918 / ULA / mDNS / loopback).
36
+ * Supports pairing in container-bridged (Docker) or NAT-proxied topologies where the host
37
+ * machine's LAN IP or proxy domain differs from the container's internal sampled network interface.
38
+ */
39
+ export declare function isPrivateOrLocalHostname(hostname: string): boolean;
40
+ /**
41
+ * Validates that an incoming request is non-cross-site (rejects cross-site fetch metadata
42
+ * and ensures Origin matches Host when present).
43
+ */
44
+ export declare function isNonCrossSite(request: IncomingMessage): boolean;
34
45
  /**
35
46
  * The rate-limit bucket key for one accept attempt (pure; unit-tested).
36
47
  * The first client-visible XFF hop separates buckets behind the auto-tunnel
@@ -41,6 +52,19 @@ export declare function isTrustedApiRequest(request: IncomingMessage, trustedHos
41
52
  * @param bucket - page (GET /pair-accept) vs api (POST /api/pair/accept).
42
53
  */
43
54
  export declare function acceptLimitKey(socketIp: string, forwarded: string | undefined, bucket: 'page' | 'api'): string;
55
+ /**
56
+ * Cap on the dynamically trusted hosts (see {@link addBounded}): room for
57
+ * every legitimate router/proxy aliasing shape, small enough that a flood of
58
+ * distinct private Host headers cannot grow the table unboundedly.
59
+ */
60
+ export declare const MAX_DYNAMIC_TRUSTED_HOSTS = 64;
61
+ /**
62
+ * FIFO-bounded Set insert: past `max` entries the oldest one is evicted
63
+ * (a Set iterates in insertion order). The dynamic trusted-host table is fed
64
+ * by caller-controlled Host headers, so it must stay bounded; an evicted
65
+ * legitimate host re-adds itself on that device's next gated request.
66
+ */
67
+ export declare function addBounded(set: Set<string>, value: string, max: number): void;
44
68
  /**
45
69
  * The host authority of a configured public base URL, e.g. `foo.trycloudflare.com`
46
70
  * from `https://foo.trycloudflare.com`. Undefined when the URL does not parse —
@@ -138,8 +162,6 @@ export declare class PairingEventsStream {
138
162
  export interface PairRoutesDeps {
139
163
  /** The pairing service. */
140
164
  service: PairingService;
141
- /** The LAN IP literals the fence accepts (derived from the bind host). */
142
- lanAddresses: readonly string[];
143
165
  /** Current desktop gate policy, re-read for every status response. */
144
166
  requirePairingForLan?: boolean | (() => boolean);
145
167
  /**
@@ -158,6 +180,8 @@ export interface PairRoutesDeps {
158
180
  * cookieless header/query credential). Undefined drops the route (tests).
159
181
  */
160
182
  indexDocument?: (deviceId: string) => Promise<string | undefined>;
183
+ /** Extra trusted non-loopback hosts (from config or environment). */
184
+ trustedHosts?: readonly string[] | (() => readonly string[]);
161
185
  }
162
186
  /**
163
187
  * Build the /api/pair route family.
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,EAAE,CAAC,EAAgB,MAAM,KAAK,CAAA;AACrC,OAAO,EAA0B,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAKhG;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CA6BtG;AAKD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAK9G;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAOxE;AAKD;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,sBAAsB,CAAA;AAEzD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAoD/C;AA4BD,8CAA8C;AAC9C,eAAO,MAAM,UAAU;;;;;;;;;IASrB,iEAAiE;;IAEjE,iFAAiF;;IAEjF;;;OAGG;;CAEK,CAAA;AAEV;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;iBAE7B,CAAA;AACF,eAAO,MAAM,mBAAmB;;iBAE9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;iBAE9B,CAAA;AACF,eAAO,MAAM,uBAAuB,gCAA6B,CAAA;AAoBjE,gDAAgD;AAChD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAElD;;OAEG;gBACS,OAAO,EAAE,cAAc;IAInC,4DAA4D;IAC5D,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI;IAiBrD,kEAAkE;IAClE,IAAI,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAYrC,wCAAwC;IACxC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,OAAO,EAAE,cAAc,CAAA;IACvB,0EAA0E;IAC1E,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAA;IAChD;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAClE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,QAAQ,EAAE,CAmY3D"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"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"}