二阶段提案合并的安全边界
解释计划批准、暂存提案、二次确认和服务端精确合并如何共同形成可审阅的 Agent 写入边界。
#type / synthesis
#status / growing
#tech / ai
#discipline / knowledge-base
#resource / mcp
#resource / chatgpt
[!abstract] 速记结论 第一次批准的是“把方案固化成待审提案”,第二次批准的才是“把指定提案合并到正式知识库”。两次批准之间必须存在可检查的 proposal ID、目标、预览或 diff。
[!info] related notes
- 所属 MOC: ChatGPT MOC
- 前置概念: Agent 中的 Approval Checkpoints, Agent 中的人类监督
- 架构案例: ChatGPT 网页端维护本地 Obsidian 的架构
- 操作指南: 验收并日常使用 ChatGPT 本地知识库维护链路
二阶段提案合并的安全边界
范围
本文解释为什么一次“可以”不足以同时授权提案生成和最终写入,以及三层控制如何协作。它不规定具体知识库的 frontmatter 或标签内容。
为什么需要放在一起理解
Agent 在规划时只掌握抽象意图,例如“补一篇详细的 ChatGPT 实践笔记”。当它把意图变成完整 Markdown 后,真实影响才变得可见:
- 最终文件名是什么;
- 是新建还是覆盖;
- frontmatter 和标签是否正确;
- 删除或替换了哪些段落;
- 是否修改了错误的同名笔记;
- 是否引入断链。
如果第一次批准直接触发最终写入,用户批准的是意图,不是具体变更。
状态模型
stateDiagram-v2
[*] --> Investigating
Investigating --> Planned: 给出方案
Planned --> Staged: 第一次批准
Staged --> Rejected: 用户拒绝或要求修改
Staged --> Applying: 第二次批准 + 操作确认
Applying --> Applied: 校验与写入成功
Applying --> Staged: 校验失败
Applied --> Archived: 归档并记录审计
两次批准批准的对象不同
| 检查点 | 用户看到什么 | 允许的副作用 | 不允许 |
|---|---|---|---|
| 第一次批准 | 文件角色、目标、标签、结构和链接方案 | 写入 `inbox/` 提案 | 修改正式 `z/` |
| 第二次批准 | proposal ID、目标、完整预览或 diff | 合并该精确提案 | 合并其他提案或任意路径 |
| ChatGPT 操作确认 | App、工具名和即将执行的动作 | 发起一次 `apply_proposal` | 保存为无条件永久批准 |
三层安全控制
Agent 与 Skill:行为层
负责让模型按正确顺序工作、展示证据并停下来。优势是能理解语义;弱点是可能被误解、遗漏或受到 prompt injection。
ChatGPT 审批:交互层
负责在外部写操作前显示确认卡。优势是用户可见;弱点是它只知道工具调用,不理解 Vault 的全部内部不变量。
MCP Server:权限层
负责不可绕过的机械约束:
- 只接受服务端签发的 proposal ID;
- proposal 内容哈希必须一致;
- patch 的目标基线哈希必须一致;
- 只允许目标位于 `z/*.md`;
- 拒绝路径穿越和 symlink 逃逸;
- 单次调用只消费一个提案;
- 成功后归档并追加审计。
真正安全保证应落在这一层。
并发修改为什么必须拒绝
生成 patch 后,用户可能在 Obsidian 中手工修改目标。如果此时仍按旧基线覆盖,Agent 会静默丢失人工改动。
因此提案需要记录目标生成时的 hash。合并时:
- 重新读取当前目标;
- 计算当前 hash;
- 与提案的 base hash 比较;
- 不一致则拒绝;
- 重新搜索、读取并生成新提案。
拒绝比自动三方合并更保守,但适合知识库:内容语义冲突需要人或 Agent 重新理解,不应机械拼接。
为什么需要归档和审计
审批卡只证明用户当时点过确认,不能回答后续问题:
- 哪个 proposal 被消费;
- 写入了哪个目标;
- 当时完整内容是什么;
- 索引是否成功更新;
- 是否重复执行。
归档保存提案证据,JSONL 保存可查询事件,Git 保存正式文件版本。三者分别承担“意图快照、操作记录、结果历史”。
适用边界
适合:
- 知识库、文档、配置和内容管理;
- 写入可延迟几秒或一轮对话;
- 用户需要检查 diff;
- 冲突时宁可拒绝也不覆盖。
不适合直接照搬:
- 高频实时协作编辑;
- 必须自动解决并发合并的系统;
- 每次写入都可完全无损撤销且风险极低的临时数据;
- 紧急自动响应且无法等待人的控制系统。
最小验收
- 第一次批准后 `z/` hash 不变;
- 提案能列出精确 ID、目标和预览;
- 第二次批准前无法调用最终写入;
- 修改提案文件后合并被拒绝;
- 修改 patch 目标后合并被拒绝;
- 路径穿越目标被拒绝;
- 成功后提案只能消费一次;
- 归档、审计和索引结果可验证。