mstro-app 0.1.47

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 (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/bin/commands/config.js +145 -0
  4. package/bin/commands/login.js +313 -0
  5. package/bin/commands/logout.js +75 -0
  6. package/bin/commands/status.js +197 -0
  7. package/bin/commands/whoami.js +161 -0
  8. package/bin/configure-claude.js +298 -0
  9. package/bin/mstro.js +581 -0
  10. package/bin/postinstall.js +45 -0
  11. package/bin/release.sh +110 -0
  12. package/dist/server/cli/headless/claude-invoker.d.ts +17 -0
  13. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -0
  14. package/dist/server/cli/headless/claude-invoker.js +311 -0
  15. package/dist/server/cli/headless/claude-invoker.js.map +1 -0
  16. package/dist/server/cli/headless/index.d.ts +13 -0
  17. package/dist/server/cli/headless/index.d.ts.map +1 -0
  18. package/dist/server/cli/headless/index.js +10 -0
  19. package/dist/server/cli/headless/index.js.map +1 -0
  20. package/dist/server/cli/headless/mcp-config.d.ts +11 -0
  21. package/dist/server/cli/headless/mcp-config.d.ts.map +1 -0
  22. package/dist/server/cli/headless/mcp-config.js +76 -0
  23. package/dist/server/cli/headless/mcp-config.js.map +1 -0
  24. package/dist/server/cli/headless/output-utils.d.ts +33 -0
  25. package/dist/server/cli/headless/output-utils.d.ts.map +1 -0
  26. package/dist/server/cli/headless/output-utils.js +101 -0
  27. package/dist/server/cli/headless/output-utils.js.map +1 -0
  28. package/dist/server/cli/headless/prompt-utils.d.ts +21 -0
  29. package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -0
  30. package/dist/server/cli/headless/prompt-utils.js +84 -0
  31. package/dist/server/cli/headless/prompt-utils.js.map +1 -0
  32. package/dist/server/cli/headless/runner.d.ts +24 -0
  33. package/dist/server/cli/headless/runner.d.ts.map +1 -0
  34. package/dist/server/cli/headless/runner.js +99 -0
  35. package/dist/server/cli/headless/runner.js.map +1 -0
  36. package/dist/server/cli/headless/types.d.ts +106 -0
  37. package/dist/server/cli/headless/types.d.ts.map +1 -0
  38. package/dist/server/cli/headless/types.js +4 -0
  39. package/dist/server/cli/headless/types.js.map +1 -0
  40. package/dist/server/cli/improvisation-session-manager.d.ts +155 -0
  41. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -0
  42. package/dist/server/cli/improvisation-session-manager.js +415 -0
  43. package/dist/server/cli/improvisation-session-manager.js.map +1 -0
  44. package/dist/server/index.d.ts +2 -0
  45. package/dist/server/index.d.ts.map +1 -0
  46. package/dist/server/index.js +386 -0
  47. package/dist/server/index.js.map +1 -0
  48. package/dist/server/mcp/bouncer-cli.d.ts +3 -0
  49. package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
  50. package/dist/server/mcp/bouncer-cli.js +99 -0
  51. package/dist/server/mcp/bouncer-cli.js.map +1 -0
  52. package/dist/server/mcp/bouncer-integration.d.ts +36 -0
  53. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -0
  54. package/dist/server/mcp/bouncer-integration.js +301 -0
  55. package/dist/server/mcp/bouncer-integration.js.map +1 -0
  56. package/dist/server/mcp/security-audit.d.ts +52 -0
  57. package/dist/server/mcp/security-audit.d.ts.map +1 -0
  58. package/dist/server/mcp/security-audit.js +118 -0
  59. package/dist/server/mcp/security-audit.js.map +1 -0
  60. package/dist/server/mcp/security-patterns.d.ts +73 -0
  61. package/dist/server/mcp/security-patterns.d.ts.map +1 -0
  62. package/dist/server/mcp/security-patterns.js +247 -0
  63. package/dist/server/mcp/security-patterns.js.map +1 -0
  64. package/dist/server/mcp/server.d.ts +3 -0
  65. package/dist/server/mcp/server.d.ts.map +1 -0
  66. package/dist/server/mcp/server.js +146 -0
  67. package/dist/server/mcp/server.js.map +1 -0
  68. package/dist/server/routes/files.d.ts +9 -0
  69. package/dist/server/routes/files.d.ts.map +1 -0
  70. package/dist/server/routes/files.js +24 -0
  71. package/dist/server/routes/files.js.map +1 -0
  72. package/dist/server/routes/improvise.d.ts +3 -0
  73. package/dist/server/routes/improvise.d.ts.map +1 -0
  74. package/dist/server/routes/improvise.js +72 -0
  75. package/dist/server/routes/improvise.js.map +1 -0
  76. package/dist/server/routes/index.d.ts +10 -0
  77. package/dist/server/routes/index.d.ts.map +1 -0
  78. package/dist/server/routes/index.js +12 -0
  79. package/dist/server/routes/index.js.map +1 -0
  80. package/dist/server/routes/instances.d.ts +10 -0
  81. package/dist/server/routes/instances.d.ts.map +1 -0
  82. package/dist/server/routes/instances.js +47 -0
  83. package/dist/server/routes/instances.js.map +1 -0
  84. package/dist/server/routes/notifications.d.ts +3 -0
  85. package/dist/server/routes/notifications.d.ts.map +1 -0
  86. package/dist/server/routes/notifications.js +136 -0
  87. package/dist/server/routes/notifications.js.map +1 -0
  88. package/dist/server/services/analytics.d.ts +56 -0
  89. package/dist/server/services/analytics.d.ts.map +1 -0
  90. package/dist/server/services/analytics.js +240 -0
  91. package/dist/server/services/analytics.js.map +1 -0
  92. package/dist/server/services/auth.d.ts +26 -0
  93. package/dist/server/services/auth.d.ts.map +1 -0
  94. package/dist/server/services/auth.js +71 -0
  95. package/dist/server/services/auth.js.map +1 -0
  96. package/dist/server/services/client-id.d.ts +10 -0
  97. package/dist/server/services/client-id.d.ts.map +1 -0
  98. package/dist/server/services/client-id.js +61 -0
  99. package/dist/server/services/client-id.js.map +1 -0
  100. package/dist/server/services/credentials.d.ts +39 -0
  101. package/dist/server/services/credentials.d.ts.map +1 -0
  102. package/dist/server/services/credentials.js +110 -0
  103. package/dist/server/services/credentials.js.map +1 -0
  104. package/dist/server/services/files.d.ts +119 -0
  105. package/dist/server/services/files.d.ts.map +1 -0
  106. package/dist/server/services/files.js +560 -0
  107. package/dist/server/services/files.js.map +1 -0
  108. package/dist/server/services/instances.d.ts +52 -0
  109. package/dist/server/services/instances.d.ts.map +1 -0
  110. package/dist/server/services/instances.js +241 -0
  111. package/dist/server/services/instances.js.map +1 -0
  112. package/dist/server/services/pathUtils.d.ts +47 -0
  113. package/dist/server/services/pathUtils.d.ts.map +1 -0
  114. package/dist/server/services/pathUtils.js +124 -0
  115. package/dist/server/services/pathUtils.js.map +1 -0
  116. package/dist/server/services/platform.d.ts +72 -0
  117. package/dist/server/services/platform.d.ts.map +1 -0
  118. package/dist/server/services/platform.js +368 -0
  119. package/dist/server/services/platform.js.map +1 -0
  120. package/dist/server/services/sentry.d.ts +5 -0
  121. package/dist/server/services/sentry.d.ts.map +1 -0
  122. package/dist/server/services/sentry.js +71 -0
  123. package/dist/server/services/sentry.js.map +1 -0
  124. package/dist/server/services/terminal/pty-manager.d.ts +149 -0
  125. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -0
  126. package/dist/server/services/terminal/pty-manager.js +377 -0
  127. package/dist/server/services/terminal/pty-manager.js.map +1 -0
  128. package/dist/server/services/terminal/tmux-manager.d.ts +82 -0
  129. package/dist/server/services/terminal/tmux-manager.d.ts.map +1 -0
  130. package/dist/server/services/terminal/tmux-manager.js +352 -0
  131. package/dist/server/services/terminal/tmux-manager.js.map +1 -0
  132. package/dist/server/services/websocket/autocomplete.d.ts +50 -0
  133. package/dist/server/services/websocket/autocomplete.d.ts.map +1 -0
  134. package/dist/server/services/websocket/autocomplete.js +361 -0
  135. package/dist/server/services/websocket/autocomplete.js.map +1 -0
  136. package/dist/server/services/websocket/file-utils.d.ts +44 -0
  137. package/dist/server/services/websocket/file-utils.d.ts.map +1 -0
  138. package/dist/server/services/websocket/file-utils.js +272 -0
  139. package/dist/server/services/websocket/file-utils.js.map +1 -0
  140. package/dist/server/services/websocket/handler.d.ts +246 -0
  141. package/dist/server/services/websocket/handler.d.ts.map +1 -0
  142. package/dist/server/services/websocket/handler.js +1771 -0
  143. package/dist/server/services/websocket/handler.js.map +1 -0
  144. package/dist/server/services/websocket/index.d.ts +11 -0
  145. package/dist/server/services/websocket/index.d.ts.map +1 -0
  146. package/dist/server/services/websocket/index.js +14 -0
  147. package/dist/server/services/websocket/index.js.map +1 -0
  148. package/dist/server/services/websocket/types.d.ts +214 -0
  149. package/dist/server/services/websocket/types.d.ts.map +1 -0
  150. package/dist/server/services/websocket/types.js +4 -0
  151. package/dist/server/services/websocket/types.js.map +1 -0
  152. package/dist/server/utils/agent-manager.d.ts +69 -0
  153. package/dist/server/utils/agent-manager.d.ts.map +1 -0
  154. package/dist/server/utils/agent-manager.js +269 -0
  155. package/dist/server/utils/agent-manager.js.map +1 -0
  156. package/dist/server/utils/paths.d.ts +25 -0
  157. package/dist/server/utils/paths.d.ts.map +1 -0
  158. package/dist/server/utils/paths.js +38 -0
  159. package/dist/server/utils/paths.js.map +1 -0
  160. package/dist/server/utils/port-manager.d.ts +10 -0
  161. package/dist/server/utils/port-manager.d.ts.map +1 -0
  162. package/dist/server/utils/port-manager.js +60 -0
  163. package/dist/server/utils/port-manager.js.map +1 -0
  164. package/dist/server/utils/port.d.ts +26 -0
  165. package/dist/server/utils/port.d.ts.map +1 -0
  166. package/dist/server/utils/port.js +83 -0
  167. package/dist/server/utils/port.js.map +1 -0
  168. package/hooks/bouncer.sh +138 -0
  169. package/package.json +74 -0
  170. package/server/README.md +191 -0
  171. package/server/cli/headless/claude-invoker.ts +415 -0
  172. package/server/cli/headless/index.ts +39 -0
  173. package/server/cli/headless/mcp-config.ts +87 -0
  174. package/server/cli/headless/output-utils.ts +109 -0
  175. package/server/cli/headless/prompt-utils.ts +108 -0
  176. package/server/cli/headless/runner.ts +133 -0
  177. package/server/cli/headless/types.ts +118 -0
  178. package/server/cli/improvisation-session-manager.ts +531 -0
  179. package/server/index.ts +456 -0
  180. package/server/mcp/README.md +122 -0
  181. package/server/mcp/bouncer-cli.ts +127 -0
  182. package/server/mcp/bouncer-integration.ts +430 -0
  183. package/server/mcp/security-audit.ts +180 -0
  184. package/server/mcp/security-patterns.ts +290 -0
  185. package/server/mcp/server.ts +174 -0
  186. package/server/routes/files.ts +29 -0
  187. package/server/routes/improvise.ts +82 -0
  188. package/server/routes/index.ts +13 -0
  189. package/server/routes/instances.ts +54 -0
  190. package/server/routes/notifications.ts +158 -0
  191. package/server/services/analytics.ts +277 -0
  192. package/server/services/auth.ts +80 -0
  193. package/server/services/client-id.ts +68 -0
  194. package/server/services/credentials.ts +134 -0
  195. package/server/services/files.ts +710 -0
  196. package/server/services/instances.ts +275 -0
  197. package/server/services/pathUtils.ts +158 -0
  198. package/server/services/platform.test.ts +1314 -0
  199. package/server/services/platform.ts +435 -0
  200. package/server/services/sentry.ts +81 -0
  201. package/server/services/terminal/pty-manager.ts +464 -0
  202. package/server/services/terminal/tmux-manager.ts +426 -0
  203. package/server/services/websocket/autocomplete.ts +438 -0
  204. package/server/services/websocket/file-utils.ts +305 -0
  205. package/server/services/websocket/handler.test.ts +20 -0
  206. package/server/services/websocket/handler.ts +2047 -0
  207. package/server/services/websocket/index.ts +40 -0
  208. package/server/services/websocket/types.ts +339 -0
  209. package/server/tsconfig.json +19 -0
  210. package/server/utils/agent-manager.ts +323 -0
  211. package/server/utils/paths.ts +45 -0
  212. package/server/utils/port-manager.ts +70 -0
  213. package/server/utils/port.ts +102 -0
@@ -0,0 +1,241 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * Instance Registry Service
5
+ *
6
+ * Manages multiple Mstro server instances
7
+ */
8
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
9
+ import { homedir } from 'node:os';
10
+ import { join } from 'node:path';
11
+ function clearStaleLock(lockPath) {
12
+ if (!existsSync(lockPath))
13
+ return;
14
+ try {
15
+ const lockTime = parseInt(readFileSync(lockPath, 'utf-8'), 10);
16
+ if (Date.now() - lockTime > 10000) {
17
+ try {
18
+ unlinkSync(lockPath);
19
+ }
20
+ catch { }
21
+ }
22
+ }
23
+ catch { }
24
+ }
25
+ function tryCreateLock(lockPath) {
26
+ try {
27
+ writeFileSync(lockPath, Date.now().toString(), { flag: 'wx' });
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ function busyWait() {
35
+ const endTime = Date.now() + Math.random() * 50 + 10;
36
+ while (Date.now() < endTime) { /* busy wait */ }
37
+ }
38
+ function acquireLock(lockPath, timeout = 5000) {
39
+ const start = Date.now();
40
+ while (Date.now() - start < timeout) {
41
+ clearStaleLock(lockPath);
42
+ if (tryCreateLock(lockPath))
43
+ return true;
44
+ busyWait();
45
+ }
46
+ return false;
47
+ }
48
+ function releaseLock(lockPath) {
49
+ try {
50
+ unlinkSync(lockPath);
51
+ }
52
+ catch {
53
+ // Ignore errors when releasing lock
54
+ }
55
+ }
56
+ export class InstanceRegistry {
57
+ registryPath;
58
+ currentInstance = null;
59
+ heartbeatInterval = null;
60
+ constructor() {
61
+ const mstroDir = join(homedir(), '.mstro');
62
+ if (!existsSync(mstroDir)) {
63
+ mkdirSync(mstroDir, { recursive: true, mode: 0o700 });
64
+ }
65
+ this.registryPath = join(mstroDir, 'instances.json');
66
+ }
67
+ /**
68
+ * Register current instance
69
+ */
70
+ register(port, workingDirectory) {
71
+ const instance = {
72
+ id: `mstro-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
73
+ port,
74
+ url: `http://localhost:${port}`,
75
+ workingDirectory,
76
+ startedAt: Date.now(),
77
+ lastHeartbeat: Date.now(),
78
+ pid: process.pid
79
+ };
80
+ this.currentInstance = instance;
81
+ this.saveInstance(instance);
82
+ this.startHeartbeat();
83
+ return instance;
84
+ }
85
+ /**
86
+ * Unregister current instance
87
+ */
88
+ unregister() {
89
+ if (this.currentInstance) {
90
+ this.removeInstance(this.currentInstance.id);
91
+ this.currentInstance = null;
92
+ }
93
+ this.stopHeartbeat();
94
+ }
95
+ /**
96
+ * Get current instance info
97
+ */
98
+ getCurrentInstance() {
99
+ return this.currentInstance;
100
+ }
101
+ /**
102
+ * Get all instances (with file locking to prevent race conditions)
103
+ */
104
+ static getAllInstances() {
105
+ const mstroDir = join(homedir(), '.mstro');
106
+ const registryPath = join(mstroDir, 'instances.json');
107
+ const lockPath = join(mstroDir, 'instances.lock');
108
+ if (!existsSync(registryPath)) {
109
+ return [];
110
+ }
111
+ const locked = acquireLock(lockPath, 3000);
112
+ try {
113
+ const data = readFileSync(registryPath, 'utf-8');
114
+ // Handle empty or whitespace-only content
115
+ if (!data || !data.trim()) {
116
+ return [];
117
+ }
118
+ const parsed = JSON.parse(data);
119
+ // Ensure we have an array
120
+ const instances = Array.isArray(parsed) ? parsed : [];
121
+ // Filter out stale instances (no heartbeat in last 2 minutes)
122
+ const now = Date.now();
123
+ const maxAge = 2 * 60 * 1000; // 2 minutes
124
+ return instances.filter(instance => now - instance.lastHeartbeat < maxAge);
125
+ }
126
+ catch (error) {
127
+ // If JSON is corrupted, log but don't spam - return empty and let next write fix it
128
+ if (error instanceof SyntaxError) {
129
+ console.warn('[InstanceRegistry] Registry file corrupted, will be recreated on next write');
130
+ }
131
+ else {
132
+ console.error('[InstanceRegistry] Failed to read instances registry:', error);
133
+ }
134
+ return [];
135
+ }
136
+ finally {
137
+ if (locked) {
138
+ releaseLock(lockPath);
139
+ }
140
+ }
141
+ }
142
+ /**
143
+ * Get instance by ID
144
+ */
145
+ static getInstance(id) {
146
+ const instances = InstanceRegistry.getAllInstances();
147
+ return instances.find(i => i.id === id) || null;
148
+ }
149
+ /**
150
+ * Save instance to registry (with file locking)
151
+ */
152
+ saveInstance(instance) {
153
+ const lockPath = join(homedir(), '.mstro', 'instances.lock');
154
+ const locked = acquireLock(lockPath, 5000);
155
+ try {
156
+ // Read current instances directly (without calling getAllInstances to avoid double-locking)
157
+ let instances = [];
158
+ if (existsSync(this.registryPath)) {
159
+ try {
160
+ const data = readFileSync(this.registryPath, 'utf-8');
161
+ if (data?.trim()) {
162
+ const parsed = JSON.parse(data);
163
+ instances = Array.isArray(parsed) ? parsed : [];
164
+ }
165
+ }
166
+ catch {
167
+ // If file is corrupted, start fresh
168
+ instances = [];
169
+ }
170
+ }
171
+ // Filter out stale instances while we're at it
172
+ const now = Date.now();
173
+ const maxAge = 2 * 60 * 1000;
174
+ instances = instances.filter(i => i.id !== instance.id && now - i.lastHeartbeat < maxAge);
175
+ // Add new/updated instance
176
+ instances.push(instance);
177
+ // Write atomically by writing to temp file first then renaming
178
+ const tempPath = `${this.registryPath}.tmp`;
179
+ writeFileSync(tempPath, JSON.stringify(instances, null, 2), 'utf-8');
180
+ // Rename is atomic on most filesystems
181
+ renameSync(tempPath, this.registryPath);
182
+ }
183
+ finally {
184
+ if (locked) {
185
+ releaseLock(lockPath);
186
+ }
187
+ }
188
+ }
189
+ /**
190
+ * Remove instance from registry (with file locking)
191
+ */
192
+ removeInstance(id) {
193
+ const lockPath = join(homedir(), '.mstro', 'instances.lock');
194
+ const locked = acquireLock(lockPath, 5000);
195
+ try {
196
+ let instances = [];
197
+ if (existsSync(this.registryPath)) {
198
+ try {
199
+ const data = readFileSync(this.registryPath, 'utf-8');
200
+ if (data?.trim()) {
201
+ const parsed = JSON.parse(data);
202
+ instances = Array.isArray(parsed) ? parsed : [];
203
+ }
204
+ }
205
+ catch {
206
+ instances = [];
207
+ }
208
+ }
209
+ instances = instances.filter(i => i.id !== id);
210
+ const tempPath = `${this.registryPath}.tmp`;
211
+ writeFileSync(tempPath, JSON.stringify(instances, null, 2), 'utf-8');
212
+ renameSync(tempPath, this.registryPath);
213
+ }
214
+ finally {
215
+ if (locked) {
216
+ releaseLock(lockPath);
217
+ }
218
+ }
219
+ }
220
+ /**
221
+ * Start heartbeat to keep instance alive
222
+ */
223
+ startHeartbeat() {
224
+ this.heartbeatInterval = setInterval(() => {
225
+ if (this.currentInstance) {
226
+ this.currentInstance.lastHeartbeat = Date.now();
227
+ this.saveInstance(this.currentInstance);
228
+ }
229
+ }, 30000); // Every 30 seconds
230
+ }
231
+ /**
232
+ * Stop heartbeat
233
+ */
234
+ stopHeartbeat() {
235
+ if (this.heartbeatInterval) {
236
+ clearInterval(this.heartbeatInterval);
237
+ this.heartbeatInterval = null;
238
+ }
239
+ }
240
+ }
241
+ //# sourceMappingURL=instances.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instances.js","sourceRoot":"","sources":["../../../server/services/instances.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export interface PathValidationResult {
2
+ valid: boolean;
3
+ resolvedPath: string;
4
+ error?: string;
5
+ }
6
+ /**
7
+ * Validate that a path is within the allowed working directory.
8
+ * Prevents path traversal attacks using .. or absolute paths.
9
+ *
10
+ * @param targetPath - The path to validate (relative or absolute)
11
+ * @param workingDir - The allowed working directory boundary
12
+ * @returns PathValidationResult with validation status and resolved path
13
+ */
14
+ export declare function validatePathWithinWorkingDir(targetPath: string, workingDir: string): PathValidationResult;
15
+ /**
16
+ * Validate both source and destination paths for rename/move operations.
17
+ * Both paths must be within the working directory.
18
+ *
19
+ * @param sourcePath - The source path
20
+ * @param destPath - The destination path
21
+ * @param workingDir - The allowed working directory boundary
22
+ * @returns Object with validation results for both paths
23
+ */
24
+ export declare function validateBothPathsWithinWorkingDir(sourcePath: string, destPath: string, workingDir: string): {
25
+ valid: boolean;
26
+ resolvedSourcePath: string;
27
+ resolvedDestPath: string;
28
+ error?: string;
29
+ };
30
+ /**
31
+ * Get the relative path from working directory.
32
+ * Useful for returning user-friendly paths in responses.
33
+ *
34
+ * @param absolutePath - The absolute path
35
+ * @param workingDir - The working directory
36
+ * @returns Relative path from working directory
37
+ */
38
+ export declare function getRelativePath(absolutePath: string, workingDir: string): string;
39
+ /**
40
+ * Check if a path contains dangerous patterns that should be blocked.
41
+ * This is an additional layer of defense beyond path validation.
42
+ *
43
+ * @param path - The path to check
44
+ * @returns true if path contains dangerous patterns
45
+ */
46
+ export declare function containsDangerousPatterns(path: string): boolean;
47
+ //# sourceMappingURL=pathUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,oBAAoB,CAoDtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB;IACD,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CA0BA;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS/D"}
@@ -0,0 +1,124 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * Path Utilities
5
+ *
6
+ * Secure path validation utilities to prevent path traversal attacks.
7
+ * All file explorer operations MUST validate paths through these functions.
8
+ */
9
+ import { isAbsolute, normalize, relative, resolve } from 'node:path';
10
+ /**
11
+ * Validate that a path is within the allowed working directory.
12
+ * Prevents path traversal attacks using .. or absolute paths.
13
+ *
14
+ * @param targetPath - The path to validate (relative or absolute)
15
+ * @param workingDir - The allowed working directory boundary
16
+ * @returns PathValidationResult with validation status and resolved path
17
+ */
18
+ export function validatePathWithinWorkingDir(targetPath, workingDir) {
19
+ try {
20
+ // Normalize the working directory to get canonical path
21
+ const normalizedWorkingDir = resolve(workingDir);
22
+ // Resolve the target path relative to working directory
23
+ let resolvedPath;
24
+ if (isAbsolute(targetPath)) {
25
+ resolvedPath = resolve(targetPath);
26
+ }
27
+ else {
28
+ resolvedPath = resolve(normalizedWorkingDir, targetPath);
29
+ }
30
+ // Normalize to remove any .. or . segments
31
+ resolvedPath = normalize(resolvedPath);
32
+ // Check if the resolved path starts with the working directory
33
+ // Add trailing separator to prevent partial matches (e.g., /home/user vs /home/username)
34
+ const workingDirWithSep = normalizedWorkingDir.endsWith('/')
35
+ ? normalizedWorkingDir
36
+ : `${normalizedWorkingDir}/`;
37
+ const isWithinWorkingDir = resolvedPath === normalizedWorkingDir ||
38
+ resolvedPath.startsWith(workingDirWithSep);
39
+ if (!isWithinWorkingDir) {
40
+ // Log security violation for monitoring
41
+ console.error(`[PathUtils] SECURITY: Path traversal attempt blocked. ` +
42
+ `Target: "${targetPath}", Resolved: "${resolvedPath}", WorkingDir: "${normalizedWorkingDir}"`);
43
+ return {
44
+ valid: false,
45
+ resolvedPath: '',
46
+ error: 'Access denied: path is outside working directory'
47
+ };
48
+ }
49
+ return {
50
+ valid: true,
51
+ resolvedPath
52
+ };
53
+ }
54
+ catch (error) {
55
+ console.error('[PathUtils] Error validating path:', error);
56
+ return {
57
+ valid: false,
58
+ resolvedPath: '',
59
+ error: `Invalid path: ${error.message}`
60
+ };
61
+ }
62
+ }
63
+ /**
64
+ * Validate both source and destination paths for rename/move operations.
65
+ * Both paths must be within the working directory.
66
+ *
67
+ * @param sourcePath - The source path
68
+ * @param destPath - The destination path
69
+ * @param workingDir - The allowed working directory boundary
70
+ * @returns Object with validation results for both paths
71
+ */
72
+ export function validateBothPathsWithinWorkingDir(sourcePath, destPath, workingDir) {
73
+ const sourceValidation = validatePathWithinWorkingDir(sourcePath, workingDir);
74
+ if (!sourceValidation.valid) {
75
+ return {
76
+ valid: false,
77
+ resolvedSourcePath: '',
78
+ resolvedDestPath: '',
79
+ error: `Source path error: ${sourceValidation.error}`
80
+ };
81
+ }
82
+ const destValidation = validatePathWithinWorkingDir(destPath, workingDir);
83
+ if (!destValidation.valid) {
84
+ return {
85
+ valid: false,
86
+ resolvedSourcePath: '',
87
+ resolvedDestPath: '',
88
+ error: `Destination path error: ${destValidation.error}`
89
+ };
90
+ }
91
+ return {
92
+ valid: true,
93
+ resolvedSourcePath: sourceValidation.resolvedPath,
94
+ resolvedDestPath: destValidation.resolvedPath
95
+ };
96
+ }
97
+ /**
98
+ * Get the relative path from working directory.
99
+ * Useful for returning user-friendly paths in responses.
100
+ *
101
+ * @param absolutePath - The absolute path
102
+ * @param workingDir - The working directory
103
+ * @returns Relative path from working directory
104
+ */
105
+ export function getRelativePath(absolutePath, workingDir) {
106
+ return relative(resolve(workingDir), absolutePath);
107
+ }
108
+ /**
109
+ * Check if a path contains dangerous patterns that should be blocked.
110
+ * This is an additional layer of defense beyond path validation.
111
+ *
112
+ * @param path - The path to check
113
+ * @returns true if path contains dangerous patterns
114
+ */
115
+ export function containsDangerousPatterns(path) {
116
+ const dangerousPatterns = [
117
+ /\0/, // Null bytes
118
+ /^~/, // Home directory expansion (should use absolute paths)
119
+ /\$\{/, // Variable expansion
120
+ /\$\(/, // Command substitution
121
+ ];
122
+ return dangerousPatterns.some(pattern => pattern.test(path));
123
+ }
124
+ //# sourceMappingURL=pathUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathUtils.js","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Get machine identification string
3
+ * Format: "hostname @ node-vX.X.X platform (arch)"
4
+ * Example: "Jessica @ node-v22.21.1 linux (arm64)"
5
+ */
6
+ export declare function getMachineIdentifier(): string;
7
+ interface ConnectionCallbacks {
8
+ onConnected?: (connectionId: string) => void;
9
+ onDisconnected?: () => void;
10
+ onError?: (error: string) => void;
11
+ onWebConnected?: () => void;
12
+ onWebDisconnected?: () => void;
13
+ onRelayedMessage?: (message: any) => void;
14
+ }
15
+ /**
16
+ * Platform WebSocket connection with token-based authentication
17
+ */
18
+ export declare class PlatformConnection {
19
+ private ws;
20
+ private reconnectTimeout;
21
+ private reconnectAttempts;
22
+ private maxReconnectAttempts;
23
+ private isIntentionallyClosed;
24
+ private workingDirectory;
25
+ private platformUrl;
26
+ private callbacks;
27
+ private connectionId;
28
+ private isConnected;
29
+ private tokenRefreshInterval;
30
+ private heartbeatInterval;
31
+ constructor(workingDirectory: string, callbacks?: ConnectionCallbacks, platformUrl?: string);
32
+ /**
33
+ * Refresh the device token if needed
34
+ */
35
+ private maybeRefreshToken;
36
+ /**
37
+ * Start periodic token refresh check
38
+ */
39
+ private startTokenRefreshCheck;
40
+ /**
41
+ * Start heartbeat to keep connection alive and refresh server-side TTL
42
+ */
43
+ private startHeartbeat;
44
+ /**
45
+ * Stop heartbeat
46
+ */
47
+ private stopHeartbeat;
48
+ /**
49
+ * Stop periodic token refresh check
50
+ */
51
+ private stopTokenRefreshCheck;
52
+ /**
53
+ * Connect to platform WebSocket
54
+ */
55
+ connect(): void;
56
+ private handleMessage;
57
+ private scheduleReconnect;
58
+ /**
59
+ * Send message to platform (will be relayed to web if connected)
60
+ */
61
+ send(message: any): void;
62
+ /**
63
+ * Check if connected to platform
64
+ */
65
+ isConnectedToPlatform(): boolean;
66
+ /**
67
+ * Disconnect from platform
68
+ */
69
+ disconnect(): void;
70
+ }
71
+ export {};
72
+ //# sourceMappingURL=platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../../server/services/platform.ts"],"names":[],"mappings":"AAkFA;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C;AAeD,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAA;CAC1C;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,gBAAgB,CAA6C;IACrE,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,qBAAqB,CAAQ;IACrC,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,OAAO,CAAC,iBAAiB,CAA8C;gBAGrE,gBAAgB,EAAE,MAAM,EACxB,SAAS,GAAE,mBAAwB,EACnC,WAAW,CAAC,EAAE,MAAM;IAOtB;;OAEG;YACW,iBAAiB;IA6B/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,IAAI,IAAI;IAwHf,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,iBAAiB;IAiBzB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAMxB;;OAEG;IACH,qBAAqB,IAAI,OAAO;IAIhC;;OAEG;IACH,UAAU,IAAI,IAAI;CAoBnB"}