Archived
治理台按 §9.1 拆成九个 gov-* feature,共用件落 shared/gov:
· 外壳(左轨/顶栏/面包屑/页签/整页下钻)自原型 Governance.tsx 平移,
DOM 与 g-* 类名原样;路由状态即应用状态,区/页签/下钻栈全编码进 hash 可深链
· 编排画布 diagram-js 画布件 1:1 平移(flow-layout/flow-node-paint/FlowDiagram),
新增 pkg-to-graph 把 ProcessPackage 转成画布图模型;统一报价 v1 全图 12 节点 15 边渲染通过
· 后端补四路由:审批单 / 工作流下钻 / 通道实例 / 度量仪表
SSE 订阅层(§9.2):app 层单一连接,按信封目标失效缓存;
组件不再自行轮询(去掉 refetchInterval)。广播只说「哪个目标动了」,不带业务载荷,
且在投递已落库已送达之后才发 —— 不是第二条投递链路。
两处实质修正:
· 治理路由一律要 govern → 读路由改要 read。客体三类 × 动作三种的分法就是为此:
BD 有 task:read 能看在途、动不了控制事件;一律 govern 等于把三种动作压成一种
· 控制事件/恢复/改派原记为 engine-transition(归机器产出)→ 新增 control 条目种类,
归人裁决侧。归侧是按动作类型的纯推导,所以「谁干的」必须体现在 kind 上;
否则人的叫停会被算进自主率的机器分子
判据 ⑩ 治理台一半跑通:在途监控 / 叫停 / 恢复,治理动作留痕可查。
无权查看不再画成空清单,按岗位说明缺哪一项。
gates: tsc / eslint / depcruise(286 模块)/ api-report / 360 测试 全绿
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
/**
|
|
* 投递回执广播 —— 前端单一 SSE 连接的服务端一侧(编码规范 §9.2)。
|
|
*
|
|
* 它**不是第二条投递链路**:投递五诺仍由 `sys.event_delivery` 承担。
|
|
* 这里只在投递已落库、已送达**之后**,把「哪个目标动了」这一事实告诉在线的浏览器,
|
|
* 让前端失效对应缓存、回服务端重取投影 —— 前端零过程状态,推送里不带业务载荷。
|
|
*/
|
|
|
|
/** 动了的目标:与信封 `correlation.target` 同构;`kind: 'system'` 表示治理面的全局变更 */
|
|
export type Touch = {
|
|
readonly kind: 'task' | 'workflow' | 'staff' | 'system';
|
|
readonly id: string;
|
|
/** 变更缘由,仅用于前端选择失效哪一组键 */
|
|
readonly reason: string;
|
|
};
|
|
|
|
export type Broadcaster = {
|
|
publish(touch: Touch): void;
|
|
subscribe(listener: (touch: Touch) => void): () => void;
|
|
readonly size: number;
|
|
};
|
|
|
|
export function createBroadcaster(): Broadcaster {
|
|
const listeners = new Set<(touch: Touch) => void>();
|
|
return {
|
|
publish(touch) {
|
|
// 广播失败不得反噬业务:任何一个订阅者抛错都只影响它自己
|
|
for (const listener of listeners) {
|
|
try {
|
|
listener(touch);
|
|
} catch {
|
|
listeners.delete(listener);
|
|
}
|
|
}
|
|
},
|
|
subscribe(listener) {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
},
|
|
get size() {
|
|
return listeners.size;
|
|
},
|
|
};
|
|
}
|