@rcrsr/rill 0.8.0 → 0.8.1
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.md +28 -0
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/error-registry.js +164 -0
- package/dist/error-registry.js.map +1 -1
- package/dist/ext/crypto/index.d.ts +32 -0
- package/dist/ext/crypto/index.d.ts.map +1 -0
- package/dist/ext/crypto/index.js +143 -0
- package/dist/ext/crypto/index.js.map +1 -0
- package/dist/ext/exec/index.d.ts +45 -0
- package/dist/ext/exec/index.d.ts.map +1 -0
- package/dist/ext/exec/index.js +168 -0
- package/dist/ext/exec/index.js.map +1 -0
- package/dist/ext/exec/runner.d.ts +62 -0
- package/dist/ext/exec/runner.d.ts.map +1 -0
- package/dist/ext/exec/runner.js +168 -0
- package/dist/ext/exec/runner.js.map +1 -0
- package/dist/ext/fetch/index.d.ts +68 -0
- package/dist/ext/fetch/index.d.ts.map +1 -0
- package/dist/ext/fetch/index.js +259 -0
- package/dist/ext/fetch/index.js.map +1 -0
- package/dist/ext/fetch/request.d.ts +90 -0
- package/dist/ext/fetch/request.d.ts.map +1 -0
- package/dist/ext/fetch/request.js +413 -0
- package/dist/ext/fetch/request.js.map +1 -0
- package/dist/ext/fs/index.d.ts +39 -0
- package/dist/ext/fs/index.d.ts.map +1 -0
- package/dist/ext/fs/index.js +560 -0
- package/dist/ext/fs/index.js.map +1 -0
- package/dist/ext/fs/sandbox.d.ts +78 -0
- package/dist/ext/fs/sandbox.d.ts.map +1 -0
- package/dist/ext/fs/sandbox.js +208 -0
- package/dist/ext/fs/sandbox.js.map +1 -0
- package/dist/ext/kv/index.d.ts +46 -0
- package/dist/ext/kv/index.d.ts.map +1 -0
- package/dist/ext/kv/index.js +215 -0
- package/dist/ext/kv/index.js.map +1 -0
- package/dist/ext/kv/store.d.ts +46 -0
- package/dist/ext/kv/store.d.ts.map +1 -0
- package/dist/ext/kv/store.js +256 -0
- package/dist/ext/kv/store.js.map +1 -0
- package/dist/generated/version-data.d.ts +1 -1
- package/dist/generated/version-data.js +2 -2
- package/package.json +37 -11
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fs Extension Factory
|
|
3
|
+
*
|
|
4
|
+
* Provides sandboxed filesystem operations via mount-based access control.
|
|
5
|
+
* All 12 functions implement path validation, permission checks, and glob filtering.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { RuntimeError } from '../../error-classes.js';
|
|
10
|
+
import { resolvePath, matchesGlob, initializeMount, } from './sandbox.js';
|
|
11
|
+
// ============================================================
|
|
12
|
+
// FACTORY
|
|
13
|
+
// ============================================================
|
|
14
|
+
/**
|
|
15
|
+
* Create filesystem extension with sandboxed operations.
|
|
16
|
+
*
|
|
17
|
+
* Initializes all mounts by resolving paths at creation time.
|
|
18
|
+
* Returns 12 functions: read, write, append, list, find, exists, remove, stat, mkdir, copy, move, mounts.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Mount configuration and defaults
|
|
21
|
+
* @returns ExtensionResult with 12 filesystem functions
|
|
22
|
+
* @throws RuntimeError if mount initialization fails
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const fsExt = createFsExtension({
|
|
27
|
+
* mounts: {
|
|
28
|
+
* workspace: { path: '/home/user/project', mode: 'read-write' }
|
|
29
|
+
* }
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function createFsExtension(config) {
|
|
34
|
+
// Apply defaults
|
|
35
|
+
const maxFileSize = config.maxFileSize ?? 10485760; // 10MB
|
|
36
|
+
const encoding = config.encoding ?? 'utf-8';
|
|
37
|
+
// Initialize all mounts (resolve paths at creation time)
|
|
38
|
+
const mounts = { ...config.mounts };
|
|
39
|
+
const initPromises = Object.values(mounts).map((mount) => initializeMount(mount));
|
|
40
|
+
// Block on initialization to catch config errors early
|
|
41
|
+
// This is a sync factory, so we use a promise wrapper pattern
|
|
42
|
+
let initError;
|
|
43
|
+
Promise.all(initPromises).catch((err) => {
|
|
44
|
+
initError = err;
|
|
45
|
+
});
|
|
46
|
+
// Helper: check for initialization errors before operations
|
|
47
|
+
const ensureInitialized = async () => {
|
|
48
|
+
if (initError)
|
|
49
|
+
throw initError;
|
|
50
|
+
await Promise.all(initPromises); // Wait for completion
|
|
51
|
+
};
|
|
52
|
+
// Helper: get effective max file size (mount-specific or global)
|
|
53
|
+
const getMaxFileSize = (mountName) => {
|
|
54
|
+
const mount = mounts[mountName];
|
|
55
|
+
return mount?.maxFileSize ?? maxFileSize;
|
|
56
|
+
};
|
|
57
|
+
// Helper: check file size against limit
|
|
58
|
+
const checkFileSize = (size, max, filePath) => {
|
|
59
|
+
if (size > max) {
|
|
60
|
+
throw new RuntimeError('RILL-R004', `file exceeds size limit (${size} > ${max})`, undefined, { path: filePath, size, max });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
// ============================================================
|
|
64
|
+
// FUNCTIONS
|
|
65
|
+
// ============================================================
|
|
66
|
+
/**
|
|
67
|
+
* Read file contents.
|
|
68
|
+
* IR-1, EC-5 (file not found), EC-6 (size limit)
|
|
69
|
+
*/
|
|
70
|
+
const read = async (args
|
|
71
|
+
// ctx and location not used but required by CallableFn signature
|
|
72
|
+
) => {
|
|
73
|
+
await ensureInitialized();
|
|
74
|
+
const mountName = args[0];
|
|
75
|
+
const filePath = args[1];
|
|
76
|
+
// EC-5: Catch file not found from resolvePath
|
|
77
|
+
let resolvedPath;
|
|
78
|
+
try {
|
|
79
|
+
resolvedPath = await resolvePath(mountName, filePath, mounts, 'read');
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof RuntimeError) {
|
|
83
|
+
// Convert RILL-R021 (sandbox error) to RILL-R004 (extension error)
|
|
84
|
+
throw new RuntimeError('RILL-R004', `file not found: ${filePath}`, undefined, { path: filePath });
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
// Check file size before reading
|
|
89
|
+
const stats = await fs.stat(resolvedPath);
|
|
90
|
+
const max = getMaxFileSize(mountName);
|
|
91
|
+
checkFileSize(stats.size, max, resolvedPath);
|
|
92
|
+
return await fs.readFile(resolvedPath, encoding);
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Write file contents, replacing if exists.
|
|
96
|
+
* IR-2
|
|
97
|
+
*/
|
|
98
|
+
const write = async (args) => {
|
|
99
|
+
await ensureInitialized();
|
|
100
|
+
const mountName = args[0];
|
|
101
|
+
const filePath = args[1];
|
|
102
|
+
const content = args[2];
|
|
103
|
+
const resolvedPath = await resolvePath(mountName, filePath, mounts, 'write', true // createMode: resolve parent directory
|
|
104
|
+
);
|
|
105
|
+
// Check content size before writing
|
|
106
|
+
const contentSize = Buffer.byteLength(content, encoding);
|
|
107
|
+
const max = getMaxFileSize(mountName);
|
|
108
|
+
checkFileSize(contentSize, max, resolvedPath);
|
|
109
|
+
await fs.writeFile(resolvedPath, content, encoding);
|
|
110
|
+
// Return bytes written as string
|
|
111
|
+
return String(contentSize);
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Append content to file.
|
|
115
|
+
* IR-3
|
|
116
|
+
*/
|
|
117
|
+
const append = async (args) => {
|
|
118
|
+
await ensureInitialized();
|
|
119
|
+
const mountName = args[0];
|
|
120
|
+
const filePath = args[1];
|
|
121
|
+
const content = args[2];
|
|
122
|
+
const resolvedPath = await resolvePath(mountName, filePath, mounts, 'write', true // createMode: allow new files
|
|
123
|
+
);
|
|
124
|
+
// Check content size before appending
|
|
125
|
+
const contentSize = Buffer.byteLength(content, encoding);
|
|
126
|
+
const max = getMaxFileSize(mountName);
|
|
127
|
+
// Check total size after append (current + new content)
|
|
128
|
+
try {
|
|
129
|
+
const stats = await fs.stat(resolvedPath);
|
|
130
|
+
checkFileSize(stats.size + contentSize, max, resolvedPath);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
// File doesn't exist yet - just check new content size
|
|
134
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
|
135
|
+
if (error.code === 'ENOENT') {
|
|
136
|
+
checkFileSize(contentSize, max, resolvedPath);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
await fs.appendFile(resolvedPath, content, encoding);
|
|
147
|
+
// Return bytes written as string
|
|
148
|
+
return String(contentSize);
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* List directory contents.
|
|
152
|
+
* IR-4, returns list of dicts with name, type, size.
|
|
153
|
+
*/
|
|
154
|
+
const list = async (args) => {
|
|
155
|
+
await ensureInitialized();
|
|
156
|
+
const mountName = args[0];
|
|
157
|
+
const dirPath = args[1] ?? '';
|
|
158
|
+
const resolvedPath = await resolvePath(mountName, dirPath, mounts, 'read');
|
|
159
|
+
const entries = await fs.readdir(resolvedPath, { withFileTypes: true });
|
|
160
|
+
const result = [];
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
const fullPath = path.join(resolvedPath, entry.name);
|
|
163
|
+
const stats = await fs.stat(fullPath);
|
|
164
|
+
result.push({
|
|
165
|
+
name: entry.name,
|
|
166
|
+
type: entry.isDirectory() ? 'directory' : 'file',
|
|
167
|
+
size: stats.size,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return result;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Recursive file search with optional glob pattern.
|
|
174
|
+
* IR-5
|
|
175
|
+
*/
|
|
176
|
+
const find = async (args) => {
|
|
177
|
+
await ensureInitialized();
|
|
178
|
+
const mountName = args[0];
|
|
179
|
+
const pattern = args[1] ?? '*';
|
|
180
|
+
const mount = mounts[mountName];
|
|
181
|
+
if (!mount || !mount.resolvedPath) {
|
|
182
|
+
throw new RuntimeError('RILL-R004', `mount "${mountName}" not configured`, undefined, { mountName });
|
|
183
|
+
}
|
|
184
|
+
const basePath = mount.resolvedPath;
|
|
185
|
+
const results = [];
|
|
186
|
+
// Recursive directory traversal
|
|
187
|
+
const traverse = async (currentPath) => {
|
|
188
|
+
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
const fullPath = path.join(currentPath, entry.name);
|
|
191
|
+
if (entry.isDirectory()) {
|
|
192
|
+
await traverse(fullPath);
|
|
193
|
+
}
|
|
194
|
+
else if (matchesGlob(entry.name, pattern)) {
|
|
195
|
+
// Return path relative to mount base
|
|
196
|
+
const relativePath = path.relative(basePath, fullPath);
|
|
197
|
+
results.push(relativePath);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
await traverse(basePath);
|
|
202
|
+
return results;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Check file existence.
|
|
206
|
+
* IR-6
|
|
207
|
+
*/
|
|
208
|
+
const exists = async (args) => {
|
|
209
|
+
await ensureInitialized();
|
|
210
|
+
const mountName = args[0];
|
|
211
|
+
const filePath = args[1];
|
|
212
|
+
try {
|
|
213
|
+
await resolvePath(mountName, filePath, mounts, 'read');
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
if (error instanceof RuntimeError) {
|
|
218
|
+
// File not found or path escape - return false
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Delete file.
|
|
226
|
+
* IR-7
|
|
227
|
+
*/
|
|
228
|
+
const remove = async (args) => {
|
|
229
|
+
await ensureInitialized();
|
|
230
|
+
const mountName = args[0];
|
|
231
|
+
const filePath = args[1];
|
|
232
|
+
// Catch file not found from resolvePath
|
|
233
|
+
let resolvedPath;
|
|
234
|
+
try {
|
|
235
|
+
resolvedPath = await resolvePath(mountName, filePath, mounts, 'write');
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
if (error instanceof RuntimeError) {
|
|
239
|
+
// File not found - return false
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
await fs.rm(resolvedPath);
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
|
250
|
+
if (error.code === 'ENOENT') {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Get file metadata.
|
|
259
|
+
* IR-8, returns dict with name, type, size, created, modified (ISO 8601).
|
|
260
|
+
*/
|
|
261
|
+
const stat = async (args) => {
|
|
262
|
+
await ensureInitialized();
|
|
263
|
+
const mountName = args[0];
|
|
264
|
+
const filePath = args[1];
|
|
265
|
+
// Catch file not found from resolvePath
|
|
266
|
+
let resolvedPath;
|
|
267
|
+
try {
|
|
268
|
+
resolvedPath = await resolvePath(mountName, filePath, mounts, 'read');
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error instanceof RuntimeError) {
|
|
272
|
+
// Convert RILL-R021 to RILL-R004
|
|
273
|
+
throw new RuntimeError('RILL-R004', `file not found: ${filePath}`, undefined, { path: filePath });
|
|
274
|
+
}
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
const stats = await fs.stat(resolvedPath);
|
|
278
|
+
const filename = path.basename(resolvedPath);
|
|
279
|
+
return {
|
|
280
|
+
name: filename,
|
|
281
|
+
type: stats.isDirectory() ? 'directory' : 'file',
|
|
282
|
+
size: stats.size,
|
|
283
|
+
created: stats.birthtime.toISOString(),
|
|
284
|
+
modified: stats.mtime.toISOString(),
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* Create directory.
|
|
289
|
+
* IR-9
|
|
290
|
+
*/
|
|
291
|
+
const mkdir = async (args) => {
|
|
292
|
+
await ensureInitialized();
|
|
293
|
+
const mountName = args[0];
|
|
294
|
+
const dirPath = args[1];
|
|
295
|
+
const mount = mounts[mountName];
|
|
296
|
+
if (!mount || !mount.resolvedPath) {
|
|
297
|
+
throw new RuntimeError('RILL-R004', `mount "${mountName}" not configured`, undefined, { mountName });
|
|
298
|
+
}
|
|
299
|
+
// For mkdir, build path manually to avoid parent directory checks
|
|
300
|
+
const mountBase = mount.resolvedPath;
|
|
301
|
+
const joined = path.join(mountBase, dirPath);
|
|
302
|
+
const normalized = path.resolve(joined);
|
|
303
|
+
// Verify path is within mount boundary
|
|
304
|
+
if (!normalized.startsWith(mountBase + path.sep) &&
|
|
305
|
+
normalized !== mountBase) {
|
|
306
|
+
throw new RuntimeError('RILL-R004', 'path escapes mount boundary', undefined, { mountName, path: dirPath, normalized, mountBase });
|
|
307
|
+
}
|
|
308
|
+
// Check if already exists
|
|
309
|
+
try {
|
|
310
|
+
const stats = await fs.stat(normalized);
|
|
311
|
+
if (stats.isDirectory()) {
|
|
312
|
+
return false; // Already exists
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
// ENOENT is expected - directory doesn't exist yet
|
|
317
|
+
if (error &&
|
|
318
|
+
typeof error === 'object' &&
|
|
319
|
+
'code' in error &&
|
|
320
|
+
error.code !== 'ENOENT') {
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
try {
|
|
325
|
+
await fs.mkdir(normalized, { recursive: true });
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
|
330
|
+
if (error.code === 'EEXIST') {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
/**
|
|
338
|
+
* Copy file within mount.
|
|
339
|
+
* IR-10
|
|
340
|
+
*/
|
|
341
|
+
const copy = async (args) => {
|
|
342
|
+
await ensureInitialized();
|
|
343
|
+
const mountName = args[0];
|
|
344
|
+
const srcPath = args[1];
|
|
345
|
+
const destPath = args[2];
|
|
346
|
+
const resolvedSrc = await resolvePath(mountName, srcPath, mounts, 'read');
|
|
347
|
+
const resolvedDest = await resolvePath(mountName, destPath, mounts, 'write', true // createMode
|
|
348
|
+
);
|
|
349
|
+
// Check file size before copying
|
|
350
|
+
const stats = await fs.stat(resolvedSrc);
|
|
351
|
+
const max = getMaxFileSize(mountName);
|
|
352
|
+
checkFileSize(stats.size, max, resolvedDest);
|
|
353
|
+
try {
|
|
354
|
+
await fs.copyFile(resolvedSrc, resolvedDest);
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
|
359
|
+
if (error.code === 'ENOENT') {
|
|
360
|
+
throw new RuntimeError('RILL-R004', `file not found: ${srcPath}`, undefined, { path: resolvedSrc });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* Move file within mount.
|
|
368
|
+
* IR-11
|
|
369
|
+
*/
|
|
370
|
+
const move = async (args) => {
|
|
371
|
+
await ensureInitialized();
|
|
372
|
+
const mountName = args[0];
|
|
373
|
+
const srcPath = args[1];
|
|
374
|
+
const destPath = args[2];
|
|
375
|
+
const resolvedSrc = await resolvePath(mountName, srcPath, mounts, 'read');
|
|
376
|
+
const resolvedDest = await resolvePath(mountName, destPath, mounts, 'write', true // createMode
|
|
377
|
+
);
|
|
378
|
+
try {
|
|
379
|
+
await fs.rename(resolvedSrc, resolvedDest);
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
|
384
|
+
if (error.code === 'ENOENT') {
|
|
385
|
+
throw new RuntimeError('RILL-R004', `file not found: ${srcPath}`, undefined, { path: resolvedSrc });
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
/**
|
|
392
|
+
* List configured mounts.
|
|
393
|
+
* IR-12, returns list of dicts with name, mode, glob.
|
|
394
|
+
*/
|
|
395
|
+
const mountsList = async () => {
|
|
396
|
+
await ensureInitialized();
|
|
397
|
+
const result = [];
|
|
398
|
+
for (const [name, mount] of Object.entries(mounts)) {
|
|
399
|
+
result.push({
|
|
400
|
+
name,
|
|
401
|
+
mode: mount.mode,
|
|
402
|
+
glob: mount.glob ?? '',
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return result;
|
|
406
|
+
};
|
|
407
|
+
// ============================================================
|
|
408
|
+
// EXTENSION RESULT
|
|
409
|
+
// ============================================================
|
|
410
|
+
return {
|
|
411
|
+
read: {
|
|
412
|
+
params: [
|
|
413
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
414
|
+
{
|
|
415
|
+
name: 'path',
|
|
416
|
+
type: 'string',
|
|
417
|
+
description: 'File path relative to mount',
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
fn: read,
|
|
421
|
+
description: 'Read file contents',
|
|
422
|
+
returnType: 'string',
|
|
423
|
+
},
|
|
424
|
+
write: {
|
|
425
|
+
params: [
|
|
426
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
427
|
+
{
|
|
428
|
+
name: 'path',
|
|
429
|
+
type: 'string',
|
|
430
|
+
description: 'File path relative to mount',
|
|
431
|
+
},
|
|
432
|
+
{ name: 'content', type: 'string', description: 'Content to write' },
|
|
433
|
+
],
|
|
434
|
+
fn: write,
|
|
435
|
+
description: 'Write file, replacing if exists',
|
|
436
|
+
returnType: 'string',
|
|
437
|
+
},
|
|
438
|
+
append: {
|
|
439
|
+
params: [
|
|
440
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
441
|
+
{
|
|
442
|
+
name: 'path',
|
|
443
|
+
type: 'string',
|
|
444
|
+
description: 'File path relative to mount',
|
|
445
|
+
},
|
|
446
|
+
{ name: 'content', type: 'string', description: 'Content to append' },
|
|
447
|
+
],
|
|
448
|
+
fn: append,
|
|
449
|
+
description: 'Append content to file',
|
|
450
|
+
returnType: 'string',
|
|
451
|
+
},
|
|
452
|
+
list: {
|
|
453
|
+
params: [
|
|
454
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
455
|
+
{
|
|
456
|
+
name: 'path',
|
|
457
|
+
type: 'string',
|
|
458
|
+
description: 'Directory path relative to mount',
|
|
459
|
+
defaultValue: '',
|
|
460
|
+
},
|
|
461
|
+
],
|
|
462
|
+
fn: list,
|
|
463
|
+
description: 'List directory contents',
|
|
464
|
+
returnType: 'list',
|
|
465
|
+
},
|
|
466
|
+
find: {
|
|
467
|
+
params: [
|
|
468
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
469
|
+
{
|
|
470
|
+
name: 'pattern',
|
|
471
|
+
type: 'string',
|
|
472
|
+
description: 'Glob pattern for filtering',
|
|
473
|
+
defaultValue: '*',
|
|
474
|
+
},
|
|
475
|
+
],
|
|
476
|
+
fn: find,
|
|
477
|
+
description: 'Recursive file search',
|
|
478
|
+
returnType: 'list',
|
|
479
|
+
},
|
|
480
|
+
exists: {
|
|
481
|
+
params: [
|
|
482
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
483
|
+
{
|
|
484
|
+
name: 'path',
|
|
485
|
+
type: 'string',
|
|
486
|
+
description: 'File path relative to mount',
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
fn: exists,
|
|
490
|
+
description: 'Check file existence',
|
|
491
|
+
returnType: 'bool',
|
|
492
|
+
},
|
|
493
|
+
remove: {
|
|
494
|
+
params: [
|
|
495
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
496
|
+
{
|
|
497
|
+
name: 'path',
|
|
498
|
+
type: 'string',
|
|
499
|
+
description: 'File path relative to mount',
|
|
500
|
+
},
|
|
501
|
+
],
|
|
502
|
+
fn: remove,
|
|
503
|
+
description: 'Delete file',
|
|
504
|
+
returnType: 'bool',
|
|
505
|
+
},
|
|
506
|
+
stat: {
|
|
507
|
+
params: [
|
|
508
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
509
|
+
{
|
|
510
|
+
name: 'path',
|
|
511
|
+
type: 'string',
|
|
512
|
+
description: 'File path relative to mount',
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
fn: stat,
|
|
516
|
+
description: 'Get file metadata',
|
|
517
|
+
returnType: 'dict',
|
|
518
|
+
},
|
|
519
|
+
mkdir: {
|
|
520
|
+
params: [
|
|
521
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
522
|
+
{
|
|
523
|
+
name: 'path',
|
|
524
|
+
type: 'string',
|
|
525
|
+
description: 'Directory path relative to mount',
|
|
526
|
+
},
|
|
527
|
+
],
|
|
528
|
+
fn: mkdir,
|
|
529
|
+
description: 'Create directory',
|
|
530
|
+
returnType: 'bool',
|
|
531
|
+
},
|
|
532
|
+
copy: {
|
|
533
|
+
params: [
|
|
534
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
535
|
+
{ name: 'src', type: 'string', description: 'Source file path' },
|
|
536
|
+
{ name: 'dest', type: 'string', description: 'Destination file path' },
|
|
537
|
+
],
|
|
538
|
+
fn: copy,
|
|
539
|
+
description: 'Copy file within mount',
|
|
540
|
+
returnType: 'bool',
|
|
541
|
+
},
|
|
542
|
+
move: {
|
|
543
|
+
params: [
|
|
544
|
+
{ name: 'mount', type: 'string', description: 'Mount name' },
|
|
545
|
+
{ name: 'src', type: 'string', description: 'Source file path' },
|
|
546
|
+
{ name: 'dest', type: 'string', description: 'Destination file path' },
|
|
547
|
+
],
|
|
548
|
+
fn: move,
|
|
549
|
+
description: 'Move file within mount',
|
|
550
|
+
returnType: 'bool',
|
|
551
|
+
},
|
|
552
|
+
mounts: {
|
|
553
|
+
params: [],
|
|
554
|
+
fn: mountsList,
|
|
555
|
+
description: 'List configured mounts',
|
|
556
|
+
returnType: 'list',
|
|
557
|
+
},
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ext/fs/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fs Extension Sandbox Module
|
|
3
|
+
*
|
|
4
|
+
* Path resolution and validation implementing 9-step security sequence.
|
|
5
|
+
* Prevents path traversal and symlink attacks via realpath() defense.
|
|
6
|
+
*/
|
|
7
|
+
/** Mount configuration defining sandbox boundaries */
|
|
8
|
+
export interface MountConfig {
|
|
9
|
+
/** Absolute or relative path on host filesystem */
|
|
10
|
+
path: string;
|
|
11
|
+
/** Access mode for this mount */
|
|
12
|
+
mode: 'read' | 'write' | 'read-write';
|
|
13
|
+
/** Optional file pattern filter (simple glob) */
|
|
14
|
+
glob?: string | undefined;
|
|
15
|
+
/** Override file size limit per-mount (bytes) */
|
|
16
|
+
maxFileSize?: number | undefined;
|
|
17
|
+
/** Resolved canonical path (set during mount initialization) */
|
|
18
|
+
resolvedPath?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Operation type for mode validation */
|
|
21
|
+
export type Operation = 'read' | 'write';
|
|
22
|
+
/**
|
|
23
|
+
* Resolves and validates path within mount boundaries.
|
|
24
|
+
*
|
|
25
|
+
* 9-step path resolution sequence (spec lines 331-342):
|
|
26
|
+
* 1. Resolve mount name to MountConfig
|
|
27
|
+
* 2. Use mount's resolved physical path (from creation time)
|
|
28
|
+
* 3. Join resolved mount base with script's relative path argument
|
|
29
|
+
* 4. Normalize with path.resolve() to collapse .. segments
|
|
30
|
+
* 5. Resolve final path with fs.realpath() (symlink defense)
|
|
31
|
+
* 6. Verify resolved path starts with mount's resolved base (startsWith())
|
|
32
|
+
* 7. If glob set, verify filename matches pattern
|
|
33
|
+
* 8. Check mode permits operation
|
|
34
|
+
* 9. Return validated path for node:fs operation
|
|
35
|
+
*
|
|
36
|
+
* @param mountName - Mount identifier from script
|
|
37
|
+
* @param relativePath - Script-provided path relative to mount
|
|
38
|
+
* @param mounts - Mount configuration map
|
|
39
|
+
* @param operation - Operation type for mode validation
|
|
40
|
+
* @param createMode - For write operations creating new files (checks parent dir)
|
|
41
|
+
* @returns Validated absolute path
|
|
42
|
+
* @throws RuntimeError - EC-1 (unknown mount), EC-2 (path escape), EC-3 (glob), EC-4 (mode), EC-7 (permission)
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolvePath(mountName: string, relativePath: string, mounts: Record<string, MountConfig>, operation: Operation, createMode?: boolean): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Simple glob pattern matching (spec lines 346-354).
|
|
47
|
+
*
|
|
48
|
+
* Supported patterns:
|
|
49
|
+
* - *.csv - Files ending in .csv
|
|
50
|
+
* - *.{json,yaml} - Files ending in .json or .yaml
|
|
51
|
+
* - * - All files (default when omitted)
|
|
52
|
+
* - **\/*.csv - CSV files at any depth (for find() only)
|
|
53
|
+
*
|
|
54
|
+
* No third-party glob library. Uses path.extname() checks.
|
|
55
|
+
*
|
|
56
|
+
* @param filename - Filename to match (basename only)
|
|
57
|
+
* @param pattern - Glob pattern
|
|
58
|
+
* @returns true if filename matches pattern
|
|
59
|
+
*/
|
|
60
|
+
export declare function matchesGlob(filename: string, pattern: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Checks if mount mode permits operation.
|
|
63
|
+
*
|
|
64
|
+
* @param mode - Mount access mode
|
|
65
|
+
* @param operation - Operation type
|
|
66
|
+
* @returns true if operation permitted
|
|
67
|
+
*/
|
|
68
|
+
export declare function checkMode(mode: 'read' | 'write' | 'read-write', operation: Operation): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Resolves mount path at creation time (Step 2 of sequence).
|
|
71
|
+
*
|
|
72
|
+
* Mutates MountConfig to set resolvedPath field.
|
|
73
|
+
*
|
|
74
|
+
* @param mount - Mount configuration
|
|
75
|
+
* @throws RuntimeError - If mount path invalid or inaccessible
|
|
76
|
+
*/
|
|
77
|
+
export declare function initializeMount(mount: MountConfig): Promise<void>;
|
|
78
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/ext/fs/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC;IACtC,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,yCAAyC;AACzC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAMzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,SAAS,EAAE,SAAS,EACpB,UAAU,UAAQ,GACjB,OAAO,CAAC,MAAM,CAAC,CAyIjB;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CA2BtE;AAMD;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,EACrC,SAAS,EAAE,SAAS,GACnB,OAAO,CAKT;AAMD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BvE"}
|