Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions packages/webui/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ export const OWNED_ROUTES = new Set([
"GET /api/fs/read-file",
"GET /api/fs/raw",
"POST /api/fs/mkdir",
// Slice 14 — open / reveal in OS file manager. Same containment
// gate as the other /api/fs/* routes (lib/open-target.js); the
// execFile boundary is the only new attack surface, and it never
// touches a shell.
"POST /api/fs/open-default",
"POST /api/fs/reveal",
// Git panel (slice 03): right-panel git surface + `/review` parity
// surfaces. Containment-gated; execFile (no shell); branch
// checkout is allow-list gated. See lib/git.js header.
Expand Down Expand Up @@ -484,15 +490,27 @@ export function createHonoApp() {
// createResponseCapture buffer (which only models writeHead/end). The
// route's `rawStreamToWebResponse` returns a fetch-API Response with a
// Web ReadableStream body, so we hand it back to Hono directly and skip
// invokeHandler entirely.
// invokeHandler entirely. `?download=1` flips the response into
// "save as" mode (slice 14's third action); the same containment
// gate, size cap, and regular-file check still apply.
app.get("/api/fs/raw", (c) => {
const url = new URL(c.req.url, "http://localhost");
const path = url.searchParams.get("path") || "";
return fsRoute.rawStreamToWebResponse(path);
const download = url.searchParams.get("download") === "1";
return fsRoute.rawStreamToWebResponse(path, { download });
});
app.post("/api/fs/mkdir", (c) =>
invokeHandler(c, c.get(CAPTURE_KEY), fsRoute.handleFsMkdir),
);
// Slice 14 — open with OS default / reveal in file manager. Containment
// + per-node realpath gated inside lib/open-target.js; the route only
// JSON-decodes the body and maps structured codes to HTTP status.
app.post("/api/fs/open-default", (c) =>
invokeHandler(c, c.get(CAPTURE_KEY), fsRoute.handleFsOpenDefault),
);
app.post("/api/fs/reveal", (c) =>
invokeHandler(c, c.get(CAPTURE_KEY), fsRoute.handleFsReveal),
);

// ----- Git panel (slice 03) -----
app.get("/api/git/status", (c) =>
Expand Down
Loading
Loading