@heimdall-ai/heimdall 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +471 -0
- package/dist/config/constants.d.ts +24 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +70 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/core/bash-manager.d.ts +56 -0
- package/dist/core/bash-manager.d.ts.map +1 -0
- package/dist/core/bash-manager.js +106 -0
- package/dist/core/bash-manager.js.map +1 -0
- package/dist/core/pyodide-manager.d.ts +125 -0
- package/dist/core/pyodide-manager.d.ts.map +1 -0
- package/dist/core/pyodide-manager.js +669 -0
- package/dist/core/pyodide-manager.js.map +1 -0
- package/dist/core/pyodide-worker.d.ts +9 -0
- package/dist/core/pyodide-worker.d.ts.map +1 -0
- package/dist/core/pyodide-worker.js +295 -0
- package/dist/core/pyodide-worker.js.map +1 -0
- package/dist/core/secure-fs.d.ts +101 -0
- package/dist/core/secure-fs.d.ts.map +1 -0
- package/dist/core/secure-fs.js +279 -0
- package/dist/core/secure-fs.js.map +1 -0
- package/dist/integration.test.d.ts +10 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/integration.test.js +439 -0
- package/dist/integration.test.js.map +1 -0
- package/dist/resources/index.d.ts +12 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +13 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/workspace.d.ts +12 -0
- package/dist/resources/workspace.d.ts.map +1 -0
- package/dist/resources/workspace.js +105 -0
- package/dist/resources/workspace.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +51 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/bash-execution.d.ts +13 -0
- package/dist/tools/bash-execution.d.ts.map +1 -0
- package/dist/tools/bash-execution.js +135 -0
- package/dist/tools/bash-execution.js.map +1 -0
- package/dist/tools/filesystem.d.ts +12 -0
- package/dist/tools/filesystem.d.ts.map +1 -0
- package/dist/tools/filesystem.js +104 -0
- package/dist/tools/filesystem.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +17 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/python-execution.d.ts +12 -0
- package/dist/tools/python-execution.d.ts.map +1 -0
- package/dist/tools/python-execution.js +77 -0
- package/dist/tools/python-execution.js.map +1 -0
- package/dist/types/index.d.ts +64 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/async-lock.d.ts +35 -0
- package/dist/utils/async-lock.d.ts.map +1 -0
- package/dist/utils/async-lock.js +57 -0
- package/dist/utils/async-lock.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecureFs - Secure filesystem wrapper with symlink protection
|
|
3
|
+
*
|
|
4
|
+
* Wraps ReadWriteFs to add symlink validation before all file operations.
|
|
5
|
+
* Prevents symlink-based path traversal attacks by resolving real paths
|
|
6
|
+
* and ensuring they stay within the workspace directory.
|
|
7
|
+
*
|
|
8
|
+
* @see SECURITY-REVIEW.md for security details
|
|
9
|
+
*/
|
|
10
|
+
import { ReadWriteFs, } from "just-bash";
|
|
11
|
+
import * as fs from "fs";
|
|
12
|
+
import * as path from "path";
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown when a symlink attack is detected
|
|
15
|
+
*/
|
|
16
|
+
export class SymlinkSecurityError extends Error {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "SymlinkSecurityError";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* SecureFs wraps ReadWriteFs with symlink protection
|
|
24
|
+
*
|
|
25
|
+
* Before every file operation, it validates that the resolved real path
|
|
26
|
+
* stays within the workspace directory. This prevents:
|
|
27
|
+
* - Direct symlinks pointing outside workspace
|
|
28
|
+
* - Nested symlink chains escaping workspace
|
|
29
|
+
* - Parent directory symlinks
|
|
30
|
+
* - Relative symlinks that escape
|
|
31
|
+
*/
|
|
32
|
+
export class SecureFs {
|
|
33
|
+
inner;
|
|
34
|
+
root;
|
|
35
|
+
resolvedRoot;
|
|
36
|
+
constructor(options) {
|
|
37
|
+
this.root = path.resolve(options.root);
|
|
38
|
+
// Resolve the root path itself (in case it's a symlink)
|
|
39
|
+
try {
|
|
40
|
+
this.resolvedRoot = fs.realpathSync(this.root);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// If root doesn't exist yet, use the absolute path
|
|
44
|
+
this.resolvedRoot = this.root;
|
|
45
|
+
}
|
|
46
|
+
this.inner = new ReadWriteFs({ root: this.root });
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Convert a virtual path to a real filesystem path
|
|
50
|
+
*/
|
|
51
|
+
toRealPath(virtualPath) {
|
|
52
|
+
// Normalize the virtual path
|
|
53
|
+
const normalized = path.posix.normalize(virtualPath);
|
|
54
|
+
// Join with root
|
|
55
|
+
return path.join(this.root, normalized);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Validate that a path doesn't escape the workspace via symlinks
|
|
59
|
+
*
|
|
60
|
+
* SECURITY: This is the core protection against symlink attacks.
|
|
61
|
+
* It resolves ALL symlinks in the path and verifies the final
|
|
62
|
+
* real path is within the workspace directory.
|
|
63
|
+
*/
|
|
64
|
+
async validatePath(virtualPath) {
|
|
65
|
+
const hostPath = this.toRealPath(virtualPath);
|
|
66
|
+
try {
|
|
67
|
+
// Resolve all symlinks to get the real path
|
|
68
|
+
const realPath = await fs.promises.realpath(hostPath);
|
|
69
|
+
// Check if the real path is within the workspace
|
|
70
|
+
if (!this.isWithinWorkspace(realPath)) {
|
|
71
|
+
throw new SymlinkSecurityError(`Security violation: Path resolves outside workspace. ` + `Symlink attack detected.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error instanceof SymlinkSecurityError) {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
// For ENOENT (file doesn't exist), validate parent directories
|
|
79
|
+
if (error.code === "ENOENT") {
|
|
80
|
+
await this.validateParentPath(hostPath);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// Re-throw other errors
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate parent directories for paths that don't exist yet
|
|
89
|
+
*
|
|
90
|
+
* SECURITY: When creating new files, we need to ensure that
|
|
91
|
+
* parent directories aren't symlinks pointing outside workspace.
|
|
92
|
+
*/
|
|
93
|
+
async validateParentPath(hostPath) {
|
|
94
|
+
let currentPath = hostPath;
|
|
95
|
+
// Walk up the directory tree until we find an existing path
|
|
96
|
+
while (currentPath !== this.root && currentPath !== path.dirname(currentPath)) {
|
|
97
|
+
currentPath = path.dirname(currentPath);
|
|
98
|
+
try {
|
|
99
|
+
const realPath = await fs.promises.realpath(currentPath);
|
|
100
|
+
if (!this.isWithinWorkspace(realPath)) {
|
|
101
|
+
throw new SymlinkSecurityError(`Security violation: Parent directory resolves outside workspace. ` +
|
|
102
|
+
`Symlink attack detected.`);
|
|
103
|
+
}
|
|
104
|
+
// Found a valid existing parent
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof SymlinkSecurityError) {
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
// Continue up the tree if this path doesn't exist
|
|
112
|
+
if (error.code !== "ENOENT") {
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check if a real path is within the workspace
|
|
120
|
+
*/
|
|
121
|
+
isWithinWorkspace(realPath) {
|
|
122
|
+
const normalizedReal = path.normalize(realPath);
|
|
123
|
+
const normalizedRoot = path.normalize(this.resolvedRoot);
|
|
124
|
+
return (normalizedReal === normalizedRoot || normalizedReal.startsWith(normalizedRoot + path.sep));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Validate symlink creation doesn't point outside workspace
|
|
128
|
+
*
|
|
129
|
+
* SECURITY: Block creation of symlinks that point to external targets
|
|
130
|
+
*/
|
|
131
|
+
async validateSymlinkTarget(target, linkPath) {
|
|
132
|
+
// Get the directory where the symlink will be created
|
|
133
|
+
const linkDir = path.dirname(this.toRealPath(linkPath));
|
|
134
|
+
// Resolve the target relative to the link's directory
|
|
135
|
+
let absoluteTarget;
|
|
136
|
+
if (path.isAbsolute(target)) {
|
|
137
|
+
absoluteTarget = target;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
absoluteTarget = path.resolve(linkDir, target);
|
|
141
|
+
}
|
|
142
|
+
// Check if target is within workspace
|
|
143
|
+
if (!this.isWithinWorkspace(absoluteTarget)) {
|
|
144
|
+
throw new SymlinkSecurityError(`Security violation: Cannot create symlink pointing outside workspace.`);
|
|
145
|
+
}
|
|
146
|
+
// Also try to resolve the target if it exists
|
|
147
|
+
try {
|
|
148
|
+
const realTarget = await fs.promises.realpath(absoluteTarget);
|
|
149
|
+
if (!this.isWithinWorkspace(realTarget)) {
|
|
150
|
+
throw new SymlinkSecurityError(`Security violation: Symlink target resolves outside workspace.`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
// Target doesn't exist yet - just check the absolute path
|
|
155
|
+
if (error.code !== "ENOENT") {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ============================================================
|
|
161
|
+
// IFileSystem Implementation - All methods validate symlinks
|
|
162
|
+
// ============================================================
|
|
163
|
+
async readFile(filePath, options) {
|
|
164
|
+
await this.validatePath(filePath);
|
|
165
|
+
return this.inner.readFile(filePath, options);
|
|
166
|
+
}
|
|
167
|
+
async readFileBuffer(filePath) {
|
|
168
|
+
await this.validatePath(filePath);
|
|
169
|
+
return this.inner.readFileBuffer(filePath);
|
|
170
|
+
}
|
|
171
|
+
async writeFile(filePath, content, options) {
|
|
172
|
+
await this.validatePath(filePath);
|
|
173
|
+
return this.inner.writeFile(filePath, content, options);
|
|
174
|
+
}
|
|
175
|
+
async appendFile(filePath, content, options) {
|
|
176
|
+
await this.validatePath(filePath);
|
|
177
|
+
return this.inner.appendFile(filePath, content, options);
|
|
178
|
+
}
|
|
179
|
+
async exists(filePath) {
|
|
180
|
+
try {
|
|
181
|
+
await this.validatePath(filePath);
|
|
182
|
+
return this.inner.exists(filePath);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error instanceof SymlinkSecurityError) {
|
|
186
|
+
// Symlinks outside workspace "don't exist" from our perspective
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async stat(filePath) {
|
|
193
|
+
await this.validatePath(filePath);
|
|
194
|
+
return this.inner.stat(filePath);
|
|
195
|
+
}
|
|
196
|
+
async lstat(filePath) {
|
|
197
|
+
// For lstat, we validate the parent but allow checking the symlink itself
|
|
198
|
+
const hostPath = this.toRealPath(filePath);
|
|
199
|
+
await this.validateParentPath(hostPath);
|
|
200
|
+
return this.inner.lstat(filePath);
|
|
201
|
+
}
|
|
202
|
+
async mkdir(filePath, options) {
|
|
203
|
+
await this.validatePath(filePath);
|
|
204
|
+
return this.inner.mkdir(filePath, options);
|
|
205
|
+
}
|
|
206
|
+
async readdir(filePath) {
|
|
207
|
+
await this.validatePath(filePath);
|
|
208
|
+
return this.inner.readdir(filePath);
|
|
209
|
+
}
|
|
210
|
+
async readdirWithFileTypes(filePath) {
|
|
211
|
+
await this.validatePath(filePath);
|
|
212
|
+
return this.inner.readdirWithFileTypes(filePath);
|
|
213
|
+
}
|
|
214
|
+
async rm(filePath, options) {
|
|
215
|
+
// For removal, check if it's a symlink first
|
|
216
|
+
const hostPath = this.toRealPath(filePath);
|
|
217
|
+
try {
|
|
218
|
+
const lstats = await fs.promises.lstat(hostPath);
|
|
219
|
+
if (lstats.isSymbolicLink()) {
|
|
220
|
+
// For symlinks, validate the parent path (where the symlink lives)
|
|
221
|
+
await this.validateParentPath(hostPath);
|
|
222
|
+
// Allow removing symlinks that point outside (cleaning up attack artifacts)
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// For regular files/directories, validate the full path
|
|
226
|
+
await this.validatePath(filePath);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if (error.code === "ENOENT") {
|
|
231
|
+
// File doesn't exist - let the underlying fs handle the error
|
|
232
|
+
if (!options?.force) {
|
|
233
|
+
return this.inner.rm(filePath, options);
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
return this.inner.rm(filePath, options);
|
|
240
|
+
}
|
|
241
|
+
async cp(src, dest, options) {
|
|
242
|
+
await this.validatePath(src);
|
|
243
|
+
await this.validatePath(dest);
|
|
244
|
+
return this.inner.cp(src, dest, options);
|
|
245
|
+
}
|
|
246
|
+
async mv(src, dest) {
|
|
247
|
+
await this.validatePath(src);
|
|
248
|
+
await this.validatePath(dest);
|
|
249
|
+
return this.inner.mv(src, dest);
|
|
250
|
+
}
|
|
251
|
+
resolvePath(base, relativePath) {
|
|
252
|
+
return this.inner.resolvePath(base, relativePath);
|
|
253
|
+
}
|
|
254
|
+
getAllPaths() {
|
|
255
|
+
return this.inner.getAllPaths();
|
|
256
|
+
}
|
|
257
|
+
async chmod(filePath, mode) {
|
|
258
|
+
await this.validatePath(filePath);
|
|
259
|
+
return this.inner.chmod(filePath, mode);
|
|
260
|
+
}
|
|
261
|
+
async symlink(target, linkPath) {
|
|
262
|
+
// SECURITY: Validate both the link location and target
|
|
263
|
+
await this.validatePath(linkPath);
|
|
264
|
+
await this.validateSymlinkTarget(target, linkPath);
|
|
265
|
+
return this.inner.symlink(target, linkPath);
|
|
266
|
+
}
|
|
267
|
+
async link(existingPath, newPath) {
|
|
268
|
+
await this.validatePath(existingPath);
|
|
269
|
+
await this.validatePath(newPath);
|
|
270
|
+
return this.inner.link(existingPath, newPath);
|
|
271
|
+
}
|
|
272
|
+
async readlink(filePath) {
|
|
273
|
+
// Validate the symlink itself exists within workspace
|
|
274
|
+
const hostPath = this.toRealPath(filePath);
|
|
275
|
+
await this.validateParentPath(hostPath);
|
|
276
|
+
return this.inner.readlink(filePath);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=secure-fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secure-fs.js","sourceRoot":"","sources":["../../src/core/secure-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,WAAW,GAQZ,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AA2B7B;;GAEG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,QAAQ;IACF,KAAK,CAAc;IACnB,IAAI,CAAS;IACb,YAAY,CAAS;IAEtC,YAAY,OAAwB;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEvC,wDAAwD;QACxD,IAAI,CAAC;YACH,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;YACnD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,WAAmB;QACpC,6BAA6B;QAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAErD,iBAAiB;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,YAAY,CAAC,WAAmB;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAE9C,IAAI,CAAC;YACH,4CAA4C;YAC5C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEtD,iDAAiD;YACjD,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,oBAAoB,CAC5B,uDAAuD,GAAG,0BAA0B,CACrF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;gBAC1C,MAAM,KAAK,CAAC;YACd,CAAC;YAED,+DAA+D;YAC/D,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBACxC,OAAO;YACT,CAAC;YAED,wBAAwB;YACxB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAC/C,IAAI,WAAW,GAAG,QAAQ,CAAC;QAE3B,4DAA4D;QAC5D,OAAO,WAAW,KAAK,IAAI,CAAC,IAAI,IAAI,WAAW,KAAK,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9E,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAExC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAEzD,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACtC,MAAM,IAAI,oBAAoB,CAC5B,mEAAmE;wBACjE,0BAA0B,CAC7B,CAAC;gBACJ,CAAC;gBAED,gCAAgC;gBAChC,OAAO;YACT,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;oBAC1C,MAAM,KAAK,CAAC;gBACd,CAAC;gBAED,kDAAkD;gBAClD,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACvD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,QAAgB;QACxC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEzD,OAAO,CACL,cAAc,KAAK,cAAc,IAAI,cAAc,CAAC,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAC1F,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,qBAAqB,CAAC,MAAc,EAAE,QAAgB;QAClE,sDAAsD;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QAExD,sDAAsD;QACtD,IAAI,cAAsB,CAAC;QAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,cAAc,GAAG,MAAM,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;QAED,sCAAsC;QACtC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,oBAAoB,CAC5B,uEAAuE,CACxE,CAAC;QACJ,CAAC;QAED,8CAA8C;QAC9C,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;YAC9D,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,oBAAoB,CAC5B,gEAAgE,CACjE,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0DAA0D;YAC1D,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,6DAA6D;IAC7D,+DAA+D;IAE/D,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,OAA0C;QACzE,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,SAAS,CACb,QAAgB,EAChB,OAAoB,EACpB,OAA2C;QAE3C,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,UAAU,CACd,QAAgB,EAChB,OAAoB,EACpB,OAA2C;QAE3C,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;gBAC1C,gEAAgE;gBAChE,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB;QACzB,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,0EAA0E;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAsB;QAClD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QACzC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,EAAE,CAAC,QAAgB,EAAE,OAAmB;QAC5C,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAEjD,IAAI,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC5B,mEAAmE;gBACnE,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBACxC,4EAA4E;YAC9E,CAAC;iBAAM,CAAC;gBACN,wDAAwD;gBACxD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,8DAA8D;gBAC9D,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;oBACpB,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC1C,CAAC;gBACD,OAAO;YACT,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,EAAE,CAAC,GAAW,EAAE,IAAY,EAAE,OAAmB;QACrD,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,EAAE,CAAC,GAAW,EAAE,IAAY;QAChC,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,WAAW,CAAC,IAAY,EAAE,YAAoB;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACpD,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,IAAY;QACxC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,QAAgB;QAC5C,uDAAuD;QACvD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,YAAoB,EAAE,OAAe;QAC9C,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,sDAAsD;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Integration Tests for Heimdall Server
|
|
3
|
+
*
|
|
4
|
+
* These tests spin up the MCP server and connect with a client
|
|
5
|
+
* to verify all functionality works end-to-end.
|
|
6
|
+
*
|
|
7
|
+
* Run with: npm test
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|