feat(lanes): expose GET/DELETE /api/lanes/:id/proof + proof-link over proof.js (C)

This commit is contained in:
2026-08-04 16:04:47 +07:00
parent e6942db7fe
commit 5de66d0b13
2 changed files with 199 additions and 0 deletions
+45
View File
@@ -15,6 +15,7 @@ const { db } = require("../db");
const lanesLib = require("../lib/lanes");
const { listPipelines, getPipeline, nodeStates, progressPct } = require("../lib/pipelines");
const laneFeatures = require("../lib/lane-features");
const proofLib = require("../lib/proof");
const { broadcast } = require("../websocket");
const runs = require("../lib/run-spawner");
const { sameOriginGuard } = require("./run");
@@ -282,6 +283,50 @@ router.post("/:id/features/activate", sameOriginGuard, (req, res) => {
}
});
router.get("/:id/proof", (req, res) => {
const lane = lanesLib.getLane(req.params.id);
if (!lane) return res.status(404).json({ error: { code: "ENOLANE", message: "lane not found" } });
res.json({ features: proofLib.listProof(lane.id) });
});
router.get("/:id/proof/:slug/:group/:file", (req, res) => {
const lane = lanesLib.getLane(req.params.id);
if (!lane) return res.status(404).send("not found");
const p = proofLib.proofFile(lane.id, req.params.slug, req.params.group, req.params.file);
if (!p) return res.status(404).send("not found");
const ext = path.extname(p).toLowerCase();
const contentType =
ext === ".html" ? "text/html; charset=utf-8" : ext === ".png" ? "image/png" : "image/jpeg";
res.type(contentType).sendFile(p);
});
router.delete("/:id/proof/:slug", sameOriginGuard, (req, res) => {
const lane = lanesLib.getLane(req.params.id);
if (!lane) return res.status(404).json({ error: { code: "ENOLANE", message: "lane not found" } });
try {
const result = proofLib.deleteProof(lane.id, {
slug: req.params.slug,
group: req.body?.group,
images: req.body?.images,
});
res.json(result);
} catch (err) {
if (err.code === "ENOFEATURE") {
return res.status(404).json({ error: { code: err.code, message: err.message } });
}
if (err.code === "EBADPATH") {
return res.status(400).json({ error: { code: err.code, message: err.message } });
}
res.status(500).json({ error: { code: err.code, message: err.message } });
}
});
router.post("/:id/proof-link", sameOriginGuard, (req, res) => {
const lane = lanesLib.getLane(req.params.id);
if (!lane) return res.status(404).json({ error: { code: "ENOLANE", message: "lane not found" } });
res.json(proofLib.ensureProofLink(lane));
});
/**
* A lane's working-copy facts: branch, short HEAD, that commit's subject, and
* the uncommitted counts. Read-only, so no same-origin guard — that guard