Co-authored-by: Serhii Dziupin <serkraser@gmail.com> Co-authored-by: Alan Chen <2144783+alanzchen@users.noreply.github.com>
3.2 KiB
3.2 KiB
FS Module Documentation
Purpose
Own filesystem API behavior for the web server runtime, including workspace-bound file operations, directory listing, reveal, and background command execution jobs.
Entrypoints and structure
packages/web/server/lib/fs/routes.js: route registration and runtime-owned state for/api/fs/*endpoints.packages/web/server/lib/fs/search.js: fuzzy filesystem search runtime used by non-FS routes (for example project icon discovery).
Public exports
registerFsRoutes(app, dependencies)fromroutes.js- Registers all filesystem routes:
GET /api/fs/homePOST /api/fs/mkdirGET /api/fs/readGET /api/fs/rawGET /api/fs/serve/:path(*)POST /api/fs/writePOST /api/fs/uploadPOST /api/fs/deletePOST /api/fs/renamePOST /api/fs/revealPOST /api/fs/execGET /api/fs/exec/:jobIdGET /api/fs/list
- Owns exec job queue state (
execJobs) and lifecycle/TTL pruning. - Enforces workspace boundary checks with active project + worktree fallback support.
- Registers all filesystem routes:
createFsSearchRuntime({ fsPromises, path, spawn, resolveGitBinaryForSpawn })fromsearch.js- Returns
{ searchFilesystemFiles(rootPath, options) }. - Supports fuzzy matching, hidden-file handling, and optional
git check-ignorefiltering.
- Returns
Composition contract with index.js
index.jsprovides composition-time dependencies only (platform primitives + callbacks such asresolveProjectDirectory,normalizeDirectoryPath, andbuildAugmentedPath).index.jsno longer owns FS route handlers or FS exec job state.
Notes for contributors
- Keep filesystem policy (workspace root checks, error mapping, exec timeout behavior) inside this module, not in the composition root.
- Filesystem
EPERM/EACCESfailures use the stablereason: "os-permission"response marker. Policy denials such as workspace-boundary or missing-grant failures must not use that marker because a native folder picker cannot remediate them. - Read-only routes authorize the requested path against the workspace before resolving symlinks. A symlink reached through the workspace may therefore target a file outside it, while a directly requested outside path still requires an exact-path grant. Write routes keep canonical-target boundary checks.
- If adding new
/api/fs/*endpoints, add them inroutes.jsand extend this document. GET /api/fs/listmay resolve symlinks withrealpathto read directory contents, but the responsepathand each entrypathmust stay in the caller's requested path space (path.join(requestedPath, name)). Returning real paths breaks file-tree expansion for directories reached through workspace symlinks.POST /api/fs/uploadaccepts oneapplication/octet-streambody withpathand optionaloverwrite=truequery parameters. The body streams into a same-directory temp file with a 100 MiB default cap configurable throughOPENCHAMBER_FS_UPLOAD_MAX_BYTES; failed and oversized uploads clean up that temp file. New files commit through an atomic no-replace link, existing files return409unless overwrite is explicit, directory targets are rejected, and the destination parent resolves before writing so uploads cannot escape through workspace symlinks.