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

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
+13
View File
@@ -192,6 +192,19 @@ export const listProcessPackagesRoute = {
} as const satisfies RouteContract;
/** 画图即校验 —— 与前端画布同源的闭合校验 */
/**
* 保存流程包(编排工作区的落笔)。
* **保存 ≠ 发布**:落的是这一版的定义(草稿可反复存);已发布版本不可回改 ——
* 后端按 (id, version, state) 判:published 版拒存,提示另起新版本。
* 返回连同闭合报告:画图即校验,每次落笔都知道离「可发布」还差几条。
*/
export const saveProcessRoute = {
method: 'PUT',
path: '/api/gov/process',
body: z.object({ pkg: processPackageSchema }),
output: z.object({ pkg: processPackageSchema, report: closureReportSchema }),
} as const satisfies RouteContract;
export const validateProcessRoute = {
method: 'POST',
path: '/api/gov/process/validate',
+1 -1
View File
@@ -6,7 +6,7 @@
*/
import type { z } from 'zod';
export const HTTP_METHODS = ['GET', 'POST', 'PATCH', 'DELETE'] as const;
export const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] as const;
export type HttpMethod = (typeof HTTP_METHODS)[number];
/**
+100 -1
View File
@@ -5,16 +5,35 @@
import { z } from 'zod';
import type { RouteContract } from './http.ts';
import { sessionSchema } from '../org.ts';
import { chatMessageSchema, deliverableSchema, formFieldSchema, stageSchema, viewBlockSchema, workOrderSchema } from '../card.ts';
import { chatMessageSchema, deliverableSchema, fileDocSchema, formFieldSchema, stageSchema, viewBlockSchema, workOrderSchema } from '../card.ts';
import { attributionSideSchema, taskRuntimeStateSchema, terminalStateSchema, workflowStateSchema } from '../terminal.ts';
import { staffIdSchema, taskIdSchema } from '../id.ts';
/** 我是谁 —— 无会话即 401,前端据此落登录页(ADR-010) */
export const sessionRoute = {
method: 'GET',
path: '/api/session',
output: sessionSchema,
} as const satisfies RouteContract;
/**
* 登录 —— 单组织 cookie session(编码规范 §4 / ADR-010)。
* 成功即种 `jcai_session`(HttpOnly);失败只回一句话,不区分账号不存在还是口令错。
*/
export const loginRoute = {
method: 'POST',
path: '/api/login',
body: z.object({ account: z.string().min(1), password: z.string().min(1) }),
output: sessionSchema,
} as const satisfies RouteContract;
/** 登出 —— 服务端会话立刻作废,不等 cookie 到期 */
export const logoutRoute = {
method: 'POST',
path: '/api/logout',
output: z.object({ ok: z.boolean() }),
} as const satisfies RouteContract;
export const healthRoute = {
method: 'GET',
path: '/api/health',
@@ -49,10 +68,29 @@ export const listTasksRoute = {
output: z.object({ tasks: z.array(taskCardSchema) }),
} as const satisfies RouteContract;
/**
* 流程链上的一环 —— 「一条 = 一个活动的一次运行」之外,人还要看见自己在整条流程的哪儿。
* 别人负责的节点也在链上(只读),但不进任务清单。
*/
export const chainNodeSchema = z.object({
nodeId: z.string(),
label: z.string(),
kind: z.enum(['activity', 'approval']),
/** 谁做:姓名 · 岗位;岗位未落到具体人时只给岗位名 */
ownerName: z.string(),
ownerRole: z.string(),
state: z.enum(['done', 'current', 'todo']),
});
export type ChainNode = z.infer<typeof chainNodeSchema>;
/** 任务详情 —— 工作区与对话区的服务端投影(前端零过程状态,刷新即重建) */
export const taskDetailSchema = z.object({
card: taskCardSchema,
goal: z.string(),
/** 本单负责人 —— 标题区落款与报告署名 */
owner: z.object({ name: z.string(), role: z.string() }),
/** 整条流程的节点链(含他人节点,只读) */
chain: z.array(chainNodeSchema),
budget: z.object({
steps: z.string(),
tokens: z.string(),
@@ -61,6 +99,18 @@ export const taskDetailSchema = z.object({
}),
stages: z.array(stageSchema),
deliverables: z.array(deliverableSchema),
/**
* 工作成果 = 一组**文件**,大部分是 HTML 汇报报告。
* 一行一份、点进去看;文件本体随投影一并下发,前端不另取。
*/
results: z.array(
z.object({
label: z.string(),
desc: z.string(),
at: z.string().optional(),
file: fileDocSchema,
}),
),
workOrders: z.array(workOrderSchema),
chat: z.array(chatMessageSchema),
view: z.array(viewBlockSchema),
@@ -94,6 +144,17 @@ export const replyWorkOrderRoute = {
output: z.object({ ok: z.boolean(), producesCompletion: z.boolean() }),
} as const satisfies RouteContract;
/**
* 对话卡回传(决策 / 补全 / 评价)—— 与后端回传校验**同 schema**。
* 对话流是一切回环输入的唯一入口(OS 4.1):卡就长在对话流上,答也就地答。
*/
export const replyChatCardRoute = {
method: 'POST',
path: '/api/desk/chat-cards/reply',
body: z.object({ reply: z.record(z.string(), z.unknown()) }),
output: z.object({ ok: z.boolean() }),
} as const satisfies RouteContract;
/** 负责人的自由输入 —— 人事件的第二形态 */
export const sayRoute = {
method: 'POST',
@@ -319,3 +380,41 @@ export const decideApprovalRoute = {
} as const satisfies RouteContract;
export type ListApprovalsForMeOutput = z.infer<typeof listApprovalsForMeRoute.output>;
/* ── 登记触发:人工起单的统一形态(OS 3.1) ─────────────────────────── */
/**
* 「登记触发 —— 人工起单的统一形态:登记人选择流程包、按调用接口 schema 填写输入
* (表单由 schema 自动渲染)、提交即起单。」**登记人即来源**。
*/
export const listRegistrationTriggersRoute = {
method: 'GET',
path: '/api/triggers/registration',
output: z.object({
triggers: z.array(
z.object({
id: z.string(),
name: z.string(),
processPackageId: z.string(),
enabled: z.boolean(),
/** 调用接口的入参 schema —— 登记表单据此渲染 */
inputSchema: z.record(z.string(), z.unknown()),
}),
),
}),
} as const satisfies RouteContract;
export const fireRegistrationRoute = {
method: 'POST',
path: '/api/triggers/:triggerId/register',
params: z.object({ triggerId: z.string() }),
body: z.object({ data: z.record(z.string(), z.unknown()) }),
output: z.object({
ok: z.boolean(),
workflowId: z.string().optional(),
skipped: z.string().optional(),
missing: z.array(z.string()).optional(),
}),
} as const satisfies RouteContract;
export type ListRegistrationTriggersOutput = z.infer<typeof listRegistrationTriggersRoute.output>;