@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.
- package/README.i18n.yaml +2 -2
- package/README.md +3 -3
- package/README.zh.md +3 -3
- package/lib/client.js +55 -21
- package/lib/client.js.map +1 -1
- package/lib/index.js +174 -39
- package/lib/types/client/RemoteEntry.d.ts.map +1 -1
- package/lib/types/client/RemoteEntry.js +11 -1
- package/lib/types/client/RemotePanel.d.ts +5 -1
- package/lib/types/client/RemotePanel.d.ts.map +1 -1
- package/lib/types/client/RemotePanel.js +2 -2
- package/lib/types/client/locales.d.ts +8 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +8 -0
- package/lib/types/client/mobile-adapt.d.ts.map +1 -1
- package/lib/types/client/mobile-adapt.js +7 -12
- package/lib/types/client/remote-channel.d.ts +0 -2
- package/lib/types/client/remote-channel.d.ts.map +1 -1
- package/lib/types/client/remote-channel.js +0 -4
- package/lib/types/index.d.ts +9 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +54 -27
- package/lib/types/loopback-proxy.d.ts.map +1 -1
- package/lib/types/loopback-proxy.js +16 -0
- package/lib/types/remote-api.d.ts +1 -1
- package/lib/types/remote-api.d.ts.map +1 -1
- package/lib/types/remote-api.js +1 -1
- package/lib/types/remote-channel-boot.d.ts.map +1 -1
- package/lib/types/remote-channel-boot.js +0 -1
- package/lib/types/remote-channel-rules.d.ts +0 -1
- package/lib/types/remote-channel-rules.d.ts.map +1 -1
- package/lib/types/remote-channel-rules.js +0 -1
- package/lib/types/remote-methods.d.ts +1 -4
- package/lib/types/remote-methods.d.ts.map +1 -1
- package/lib/types/remote-methods.js +1 -5
- package/lib/types/routes.d.ts +26 -2
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +150 -5
- package/package.json +18 -18
- package/src/client/RemoteEntry.tsx +12 -0
- package/src/client/RemotePanel.tsx +37 -2
- package/src/client/locales.ts +8 -0
- package/src/client/mobile-adapt.ts +5 -10
- package/src/client/remote-channel.ts +0 -3
- package/src/index.ts +59 -26
- package/src/loopback-proxy.ts +15 -0
- package/src/remote-api.ts +0 -1
- package/src/remote-channel-boot.ts +0 -1
- package/src/remote-channel-rules.ts +0 -2
- package/src/remote-methods.ts +1 -6
- 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
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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
|
|
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))
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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;
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,CAAC,MAAM,aAAa,CAAA;AAO3B,OAAO,EAA0C,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAgCzF,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd;;;;;;;;;;;WAWG;QACH,UAAU,CACR,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GACrC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAC9B;CACF;AAED,iCAAiC;AACjC,eAAO,MAAM,IAAI,kBAAkB,CAAA;AAEnC,+DAA+D;AAC/D,eAAO,MAAM,MAAM,UAA+C,CAAA;AAElE;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,EAAsB,iBAAiB,CAAA;AAEpF,qEAAqE;AACrE,MAAM,WAAW,MAAM;IACrB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;;OAWG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/types/index.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
-
|
|
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;
|
|
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 {
|
|
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,
|
|
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"}
|
package/lib/types/remote-api.js
CHANGED
|
@@ -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 {
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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.
|
package/lib/types/routes.d.ts
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"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"}
|