feat(authz): add atomic mobile knowledge writes

This commit is contained in:
冰朔 2026-08-03 22:27:09 +08:00
commit 5e2ba5b006
6 changed files with 527 additions and 19 deletions

View file

@ -437,6 +437,49 @@ function createApp(options = {}) {
}
}
if (
req.method === "PUT"
&& url.pathname === "/api/hololake/knowledge/page"
) {
const authenticated = authenticateHoloLake(req);
if (!authenticated.ok) {
return json(
res,
authenticated.status,
failure(authenticated.error),
);
}
if (!hololakeKnowledgeProvider) {
return json(res, 503, failure("knowledge_repository_unavailable"));
}
const body = await readJson(req, 1024 * 1024 + 16 * 1024);
if (!body || typeof body !== "object") {
return json(res, 400, failure("knowledge_page_request_invalid"));
}
try {
const receipt = hololakeKnowledgeProvider.writePage({
path: body.path,
content: body.content,
baseCommit: body.base_commit,
});
return json(res, 200, receipt);
} catch (error) {
const code = String(error && error.message || "");
if (code === "knowledge_commit_conflict") {
return json(res, 409, failure(code));
}
if ([
"knowledge_page_path_invalid",
"knowledge_secret_page_forbidden",
"knowledge_page_content_invalid",
"knowledge_page_too_large",
].includes(code)) {
return json(res, 400, failure(code));
}
return json(res, 503, failure("knowledge_repository_unavailable"));
}
}
if (
req.method === "GET"
&& url.pathname === "/api/hololake/knowledge/archive"
@ -1252,10 +1295,21 @@ function document(title, body) {
</style></head><body><main class="shell">${body}</main></body></html>`;
}
function readJson(req) {
function readJson(req, maxBytes = 32 * 1024) {
return new Promise((resolve, reject) => {
let raw = "";
req.on("data", chunk => { raw += chunk; if (raw.length > 32 * 1024) { const error = new Error("body too large"); error.code = "BODY_TOO_LARGE"; reject(error); req.destroy(); } });
let received = 0;
req.on("data", chunk => {
received += chunk.length;
if (received > maxBytes) {
const error = new Error("body too large");
error.code = "BODY_TOO_LARGE";
reject(error);
req.destroy();
return;
}
raw += chunk;
});
req.on("end", () => { try { resolve(JSON.parse(raw || "{}")); } catch { resolve(null); } });
req.on("error", reject);
});