基线:鉴权会话+工作组+工作台三区修复+编排工作区+产品设计文档

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-27 20:43:35 +08:00
co-authored by Claude Fable 5
parent 61fe181678
commit ac85ecf2ea
119 changed files with 16634 additions and 1246 deletions
+28
View File
@@ -23,6 +23,7 @@ import {
listToolsRoute,
listTriggersRoute,
publishProcessRoute,
saveProcessRoute,
reassignTaskRoute,
resumeTaskRoute,
staffIdSchema,
@@ -255,6 +256,33 @@ export function registerGovernanceOpsRoutes(app: Hono<AppEnv>, container: Contai
return c.json({ packages: await container.process.listPackages() });
});
/**
* 保存编排 —— 保存 ≠ 发布:草稿可反复存;**已发布版本不可回改**。
* 想改已发布的,另起新版本(恒新增、版本并存,在途按启动时版本跑完)。
*/
app.put(saveProcessRoute.path, async (c) => {
const denied = await governProcess(c.get('account'));
if (denied) return c.json(denied, denyStatus(denied));
const parsed = saveProcessRoute.body.safeParse(await c.req.json());
if (!parsed.success) {
const body: ApiError = { code: 'validation-failed', message: '流程包不合 schema', detail: parsed.error.issues };
return c.json(body, 400);
}
const incoming = parsed.data.pkg;
const existing = await container.process.getPackage(incoming.id, incoming.version);
if (existing !== undefined && existing.state === 'published') {
const body: ApiError = {
code: 'precondition-failed',
message: `v${incoming.version} 已发布,不可回改 —— 另存为 v${incoming.version + 1} 再编排`,
};
return c.json(body, 412);
}
// 保存的永远是草稿:发布是另一道门(闭合校验),不在保存里顺带
const pkg = await container.process.savePackage({ ...incoming, state: 'draft' });
const report = await container.process.validate(pkg);
return c.json({ pkg, report });
});
/** 画图即校验 —— 与前端画布同源 */
app.post(validateProcessRoute.path, async (c) => {
const denied = await governProcess(c.get('account'));