M3(完成): interaction 与 activity-registry
interaction(L3): - 控制权按态转交:活动在跑归活动,流转/审批/终态归系统;输入侧永远归系统(单入口) - 视图区净化门:含 <script> / on* / 外部资源的模版一律拒推 —— 容器无脚本执行权 - 对话流单入口:自由输入同写任务记忆并抛人事件;SSE 单连接 + 按目标失效广播 - 前端零过程状态:对话流与视图都是服务端投影 activity-registry(L4): - 安装两审:静态审(签名/SDK/工具契约齐备/模型名已绑定/schema/悬空监听/模版无脚本/ 零环境能力/动态执行/验收等级不得谎报)+ 回放审(旧成不坏是硬门,旧败能成只入报告) - 资产与包分离版本化:包只携资产初始版,不覆盖已有更高资产版;装载 = 包版本 + 生效资产版 - 进化管线状态机:候选 → 回放 → 人放行 → 生效;回退是显式治理动作 245 个测试通过,门禁五道全绿 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
co-authored by
Claude Opus 5
parent
d96c6e6dff
commit
2850e6d4ef
@@ -0,0 +1,66 @@
|
||||
/** 控制权按态转交与视图净化门 —— domain 测试零 mock(OS 4.1,AM 07) */
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
checkTemplate,
|
||||
handoverHappens,
|
||||
inputControl,
|
||||
INTERACTION_PHASES,
|
||||
outputControl,
|
||||
templateIsSafe,
|
||||
} from '../internal/domain/control-handover.ts';
|
||||
|
||||
describe('输出侧控制权', () => {
|
||||
it('活动在跑时归活动', () => {
|
||||
expect(outputControl('active')).toBe('activity');
|
||||
expect(outputControl('awaiting-human')).toBe('activity');
|
||||
expect(outputControl('awaiting-event')).toBe('activity');
|
||||
});
|
||||
|
||||
it('流转 / 审批 / 终态归系统', () => {
|
||||
expect(outputControl('activating')).toBe('system');
|
||||
expect(outputControl('approving')).toBe('system');
|
||||
expect(outputControl('transitioning')).toBe('system');
|
||||
expect(outputControl('terminal')).toBe('system');
|
||||
});
|
||||
|
||||
it('每一个态都有确定归属', () => {
|
||||
for (const phase of INTERACTION_PHASES) expect(['activity', 'system']).toContain(outputControl(phase));
|
||||
});
|
||||
});
|
||||
|
||||
describe('输入侧永远归系统 —— 单入口,不参与转交', () => {
|
||||
it('恒为 system', () => {
|
||||
expect(inputControl()).toBe('system');
|
||||
});
|
||||
});
|
||||
|
||||
describe('转交判定', () => {
|
||||
it('跨归属才算转交', () => {
|
||||
expect(handoverHappens('active', 'transitioning')).toBe(true);
|
||||
expect(handoverHappens('active', 'awaiting-human')).toBe(false);
|
||||
expect(handoverHappens('approving', 'terminal')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('视图模版净化门 —— 容器无脚本执行权', () => {
|
||||
it('纯内容模版放行', () => {
|
||||
expect(templateIsSafe('<div class="jc-card"><h3>报价草案</h3><p>12 条</p></div>')).toBe(true);
|
||||
});
|
||||
|
||||
it('含 <script> 即拒', () => {
|
||||
expect(checkTemplate('<div><script>alert(1)</script></div>').map((v) => v.code)).toContain('script');
|
||||
});
|
||||
|
||||
it('含 on* 事件处理器即拒', () => {
|
||||
expect(checkTemplate('<button onclick="go()">x</button>').map((v) => v.code)).toContain('event-handler');
|
||||
});
|
||||
|
||||
it('引用外部资源即拒', () => {
|
||||
expect(checkTemplate('<img src="https://evil.com/x.png">').map((v) => v.code)).toContain('external-resource');
|
||||
expect(checkTemplate('<link href="//cdn/x.css">').map((v) => v.code)).toContain('external-resource');
|
||||
});
|
||||
|
||||
it('相对路径资源不算外部', () => {
|
||||
expect(templateIsSafe('<img src="/samples/quote.png">')).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user