# 自查：两份驳回信的共性

同期两位同学的驳回理由看似不同，实质是两件事：

| 案例 | 驳回要点 | 实质问题 |
| --- | --- | --- |
| JoinWitness | “通用性受到明显限制。建议参考 pandas、Polars” | 做成了一个专用工具，而不是可复用的基础件 |
| TideWeave | “基础能力声明仍不充分……建议补充完整机制，明确边界语义，参考 Flink 生态” | 声称做了某类系统，但没有把该类系统的核心机制讲全、做全 |

这份文档用同样两把尺子量 MoonGate，列出已经补的和明确不做的。

## 一、通用性

**已具备**

- 对 MCP 客户端与 MCP 服务端都透明：stdio 上的 JSON-RPC 2.0，握手、通知、错误码按协议转发。
- 覆盖 `tools/call`、`resources/read`、`prompts/get`，不只 tools。
- 策略语言与具体工具无关：工具名 glob、参数 glob/前缀/取反/路径规范化，不内置任何业务词表。
- 同一份 MoonBit 核心有两种部署形态：网关进程，或嵌进服务端的 guard；也作为 Mooncakes 库供其他 MoonBit 项目调用。
- 不依赖模型、不依赖云服务、不依赖外部调用记录。
- 一个网关可带多个 MCP 服务端：合并工具清单、按归属路由、跨进程血缘。

**明确不做，也不是本项目的前提**

- 多服务端模式目前只合并 `tools`；`resources`/`prompts` 路由到第一个服务端。
- 只实现 stdio：HTTP/SSE 传输未覆盖。MCP 的远程服务端常走 Streamable HTTP，这是已知缺口。
- 不是通用策略语言（不对标 OPA/Cedar）：作用域限定在“一次工具调用的边界”，不表达跨资源的关系查询、不引用外部数据源。

**与 Mooncakes 现有模块的关系**

`yadidyc/moonpod` 是传输无关的策略核心，`eisem/moon_policy` 是 RBAC 引擎；MoonGate 不是它们的扩展，也不复用代码。区别在于 MoonGate 拦在 MCP 协议上，做工具清单裁剪、跨进程血缘、密钥替身与双端执行。完整对照见 [OVERLAP.md](OVERLAP.md)。

**为什么这不等于“专用工具”**

它不解决某一个业务问题（例如“审计某公司的关联交易”），而是任何 MCP 部署都会遇到的边界问题：工具该不该执行、值该不该出站、谁批准了这次调用。参考对象不是某个应用，而是“进程沙箱 / API 网关”这类基础件。

## 二、基础能力完整性

对照一个执行边界系统应有的构件，逐项说明状态与语义位置：

| 构件 | 状态 | 语义与证据 |
| --- | --- | --- |
| 协议解析与关联 | 完整 | 请求/响应按 id 关联；通知透传；服务端反向请求默认拒绝（`sampling`/`elicitation`） |
| 策略求值 | 完整 | 有序首匹配、默认拒绝、参数条件、路径词法规范化；求值顺序见 `POLICY.md` |
| 能力裁剪 | 完整 | 被无条件拒绝的工具从 `tools/list` 移除 |
| 频率控制 | 完整 | 会话级滑动窗口，所有调用尝试计数 |
| 会话配额 | 完整 | 调用数、参数字节、密钥替换次数；审批批准时复检 |
| 数据血缘 | 完整 | 敏感结果提取、SHA-256 指纹、来源调用、外发匹配、证据 |
| 密钥替身 | 完整 | 结果脱敏为占位符；按 `reveal` 规则替换；未授权目的地拒绝 |
| 人工审批 | 完整 | 参数摘要绑定、TTL、单次消费、拒绝/超时错误码 |
| 账本 | 完整 | 逐事件哈希链、规范化 JSON、离线 `verify`、HTML 报告 |
| 策略互操作 | 部分 | 导入 MoonPod JSON 策略子集；command_rules/resource_rules/tool_quotas 明确不支持 |
| 多服务端 | 部分 | 合并 tools、按归属路由、跨进程血缘；resources/prompts 未做跨服务端路由 |
| 第二执行点 | 完整 | 无状态 guard；审批交给网关；策略加载失败关闭；未解析占位符拒绝；与网关的硬判定一致性由穷举测试覆盖 |
| 状态生命周期 | 完整 | 会话、in-flight、pending approval、vault 均随会话释放；审批超时由 tick 清理 |
| 失败模式 | 完整 | 非法 JSON、未知方法、缺参数、超长行、上游崩溃、引擎异常，逐项定义行为（`SEMANTICS.md`） |

**明确的缺口**

- 没有多服务端命名空间与路由。
- 没有 HTTP/SSE 传输。
- 没有沙箱：不限制服务端进程的文件/网络权限。
- 没有多用户身份与审批鉴权。
- 血缘与替身都是精确值匹配，不处理编码、分片、改写。

这些缺口写在 README 的“边界”和 `SEMANTICS.md` 的“不保证”里，不用“全面防护”这类表述掩盖。

## 三、边界语义是否讲清

`SEMANTICS.md` 给出：

- 信任模型：信任什么、不信任什么、假设是什么；
- 两个执行点各自保证什么（表格）；
- 七条保证与八条不保证；
- 威胁—覆盖矩阵（含“覆盖不了”的行）；
- 失败模式表（每一种异常的具体行为）；
- 账本能证明什么、不能证明什么。

## 四、创新点是否成立

不是“又实现了一遍策略网关”，而是两个可以独立验证的性质：

1. **同一策略、两个执行点**：演示第 10 步绕过网关直连服务端，仍被拒绝；两点共用 `guard_decision` / `decide` 的规则匹配语义。
2. **密钥替身发生在工具调用边界**：模型上下文里没有明文，占位符可以跨调用流转，替换目标逐条授权；账本与错误信息都不含明文。

这两点都不是靠文档声明，而是有进程级断言：接收端按路径计数、文件系统状态、账本不含明文、服务端直连仍拒绝。

## 五、这一轮实际做了什么

- 新增 `mask_secrets` / `reveal` 与内存 vault，模型不再看到明文密钥；
- 服务端 guard 拒绝未解析占位符；
- 路径词法规范化，关闭 `reports/../../etc/passwd` 绕过；
- guard 策略加载失败改为失败关闭；
- 会话配额（调用数 / 参数字节 / 替换次数）；
- 两点判定一致性穷举测试；
- 47 个单元测试、21 个 Node 测试，CI 三平台；
- 发布 Mooncakes 库，供其他 MoonBit 项目直接调用 guard。
