soc2-cockpit/server/index.js

76 lines
2.7 KiB
JavaScript

import http from "node:http";
import { URL } from "node:url";
import { host, port } from "./config.js";
import { readJsonBody, sendJson, sendText } from "./lib/http.js";
import { listEvidenceArtifacts, loadRegistry, resetRegistry, writeEvidenceArtifact, writeRegistry } from "./lib/store.js";
import { validateRegistry } from "../src/lib/validation.js";
const server = http.createServer(async (req, res) => {
if (!req.url) return sendJson(res, 400, { error: "Missing URL." });
const url = new URL(req.url, `http://${req.headers.host || `${host}:${port}`}`);
if (req.method === "OPTIONS") {
res.writeHead(204, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
});
return res.end();
}
try {
if (req.method === "GET" && url.pathname === "/health") {
return sendText(res, 200, "ok");
}
if (req.method === "GET" && url.pathname === "/api/health") {
const registry = await loadRegistry();
const validation = validateRegistry(registry);
return sendJson(res, 200, {
ok: true,
service: "soc2-cockpit-api",
registryValid: validation.isValid,
warningCount: validation.warnings.length,
errorCount: validation.errors.length,
});
}
if (req.method === "GET" && url.pathname === "/api/registry") {
const registry = await loadRegistry();
return sendJson(res, 200, { registry, validation: validateRegistry(registry) });
}
if (req.method === "PUT" && url.pathname === "/api/registry") {
const payload = await readJsonBody(req);
const result = await writeRegistry(payload);
return sendJson(res, 200, result);
}
if (req.method === "POST" && url.pathname === "/api/registry/reset") {
const result = await resetRegistry();
return sendJson(res, 200, result);
}
if (req.method === "GET" && url.pathname === "/api/evidence") {
const artifacts = await listEvidenceArtifacts();
return sendJson(res, 200, { artifacts });
}
if (req.method === "POST" && url.pathname === "/api/evidence") {
const payload = await readJsonBody(req);
const artifact = await writeEvidenceArtifact(payload);
return sendJson(res, 201, { artifact });
}
return sendJson(res, 404, { error: "Not found." });
} catch (error) {
if (error?.validation) {
return sendJson(res, 400, { error: error.message, validation: error.validation });
}
return sendJson(res, 500, { error: error?.message || "Internal server error." });
}
});
server.listen(port, host, () => {
console.log(`SOC 2 cockpit API listening on http://${host}:${port}`);
});