MCPcopy
hub / github.com/garrytan/gstack / handlePublish

Function handlePublish

design/src/daemon.ts:278–356  ·  view source on GitHub ↗
(req: Request, origin: string)

Source from the content-addressed store, hash-verified

276}
277
278async function handlePublish(req: Request, origin: string): Promise<Response> {
279 let body: any;
280 try {
281 body = await req.json();
282 } catch {
283 return Response.json({ error: "Invalid JSON" }, { status: 400 });
284 }
285 if (!body || typeof body !== "object") {
286 return Response.json({ error: "Expected JSON object" }, { status: 400 });
287 }
288 const htmlPath = typeof body.html === "string" ? body.html : "";
289 if (!htmlPath) return Response.json({ error: "Missing 'html' field" }, { status: 400 });
290 if (!fs.existsSync(htmlPath)) {
291 return Response.json({ error: `HTML file not found: ${htmlPath}` }, { status: 400 });
292 }
293 let resolvedHtml: string;
294 let sourceDir: string;
295 try {
296 resolvedHtml = fs.realpathSync(path.resolve(htmlPath));
297 sourceDir = fs.realpathSync(path.dirname(resolvedHtml));
298 } catch (e: any) {
299 return Response.json({ error: `Cannot resolve path: ${e.message}` }, { status: 400 });
300 }
301 if (!fs.statSync(resolvedHtml).isFile()) {
302 return Response.json(
303 { error: `'html' must be a file, not a directory: ${htmlPath}` },
304 { status: 400 },
305 );
306 }
307
308 // sourceDir comes from realpath(html), not from the body — Codex finding:
309 // body-supplied sourceDir is a local trust boundary the daemon shouldn't cross.
310 const existing = findActiveBoardForSourceDir(sourceDir);
311 if (existing) {
312 return Response.json(
313 {
314 error: "Source directory already in use by an active board",
315 existing: {
316 id: existing.id,
317 url: `${origin}/boards/${existing.id}/`,
318 state: existing.state,
319 },
320 },
321 { status: 409 },
322 );
323 }
324 if (nonDoneCount() >= MAX_BOARDS) {
325 return Response.json(
326 {
327 error: `Cannot publish: ${MAX_BOARDS} non-done boards already exist. Submit or close some first.`,
328 },
329 { status: 503 },
330 );
331 }
332
333 const id = newBoardId();
334 const htmlContent = fs.readFileSync(resolvedHtml, "utf-8");
335 const now = Date.now();

Callers 1

fetchHandlerFunction · 0.85

Calls 7

nonDoneCountFunction · 0.85
newBoardIdFunction · 0.85
evictUntilUnderCapFunction · 0.85
markMeaningfulActivityFunction · 0.85
dlogFunction · 0.85
setMethod · 0.80

Tested by

no test coverage detected