feat: add local approval submission drafts

This commit is contained in:
2026-08-19 15:53:47 +00:00
parent 0a7ad6a3b6
commit 5d889d4445
21 changed files with 176 additions and 25 deletions
+14 -4
View File
@@ -3,9 +3,11 @@
## 数据路径
```text
用户 ─ Messenger ─ Agent ─ 远程 Streamable HTTP MCP/OAuth ─ 统一审批网关
├─ 钉钉 OA
└─ 薪福通
用户 ─ Messenger ─ Agent
├─ 可选本机私有提单草稿
└─ 远程 Streamable HTTP MCP/OAuth ─ 统一审批网关
├─ 钉钉 OA
└─ 薪福通
```
支持远程 MCP 和标准 OAuth,且用户能完成宿主所注册回调的场景直接连接网关,不安装客户端运行时。若宿主使用 `127.0.0.1`/`localhost` 回调,授权页必须在 Agent 所在设备打开。宿主缺少远程传输/OAuth 能力,或用户通过 SSH、无头终端、Messenger 等方式跨设备交互而无法完成本机回调时,使用本地 Bridge 把 stdio 转换为远程 Streamable HTTP,并通过可跨设备的 device-code 登录。Bridge 只保存用户自己的短期 access/refresh token,不包含企业密钥、不读取审批上游,也不监听端口。
@@ -24,6 +26,14 @@ Agent 面向统一审批语义,不直接理解钉钉 `processInstanceId/taskId
所有工具以普通 `content.text` 中的精简 JSON 作为跨宿主可见结果,同时保留相同的精简 `structuredContent` 供支持结构化结果的宿主使用;两处都不携带诊断字段或上游原始响应。`raw` 仍是受过滤、分页和硬限额保护的按需诊断视图,不是默认数据通道。
## 本机提单草稿
草稿不是网关工具或上游单据状态,而是 Agent 的本地文件工作流。只有用户明确要求起草或保存时,Agent 才在当前 OS 用户的私有应用数据目录写入草稿;Windows 使用 `%LOCALAPPDATA%\DingTalkApproval\drafts`,macOS 使用 `~/Library/Application Support/DingTalkApproval/drafts`,Linux 使用 `${XDG_DATA_HOME:-~/.local/share}/dingtalk-approval/drafts`。POSIX 目录/文件权限分别为 `0700`/`0600`,保存采用同目录临时文件原子替换。宿主没有本地文件能力时明确不支持持久草稿,禁止退化为网关存储。
草稿仅保存用户填写值、来源和模板显示名、可选项决定,以及附件本地路径、大小、修改时间和 SHA-256。它不保存 Token、当前用户身份、短期 `templateId`/`confirmationId`/`revokeId`、审批动作引用或完整上游 Schema,也不复制或预上传附件。恢复时按来源和模板名重新实时列模板并获取 Schema;模板不唯一、字段变化、附件丢失或哈希变化都必须回到用户确认。当前 MCP 没有附件上传工具,本机路径或文件内容不能作为上游附件编号提交;实时 Schema 要求附件编号时只能保留草稿并转到原生客户端。普通草稿超过 90 天未更新会在下次草稿操作时清理。
正式提交仍完整经过网关的身份、模板、字段、发票查重、预览和一次性确认校验。本机文件被修改不能扩大权限。提交成功或即时完成后删除草稿;确定失败时保留并回到编辑;`outcome_uncertain` 时冻结草稿、丢弃短期引用并禁止自动重试,直到本人发起历史或原生客户端证明结果。
单张或部分操作使用 v4 紧凑无状态 `approvalId`。载荷只包含来源、上游标识、用途和 30 分钟有效期,不包含标题、申请人、金额、详情或用户 ID;网关以当前 OAuth 用户派生专属 AES-GCM 密钥,因此同一服务器密钥下其他用户也无法解开。常见薪福通引用约 60 字符,钉钉 OA 引用约 100 字符;长度头可以把宿主截断与普通篡改区分开。待办引用允许进入实时写前校验;`approval_list_history` 签发的 `handled/submitted` 引用只能读取详情,动作查询和批处理会在首次上游写入前拒绝。网关继续接受尚未过期的 v2/v3 待办引用,升级或进程重启不会让同一密钥签发的引用失效。
历史列表不与待办混合,也不签发 `selectionId`。未指定时间时默认查询最近 30 天;`startDate/endDate` 接受按 `Asia/Shanghai` 解释的 `YYYY-MM-DD` 或带时区的 ISO 8601 时间,结束日期包含全天,单次跨度最多 120 天。钉钉 `handled` 从本人已完成工作记录取得,`submitted` 在该时间窗口内按当前用户可见模板查询本人发起实例;薪福通 `handled` 从本人的已处理任务取得,`submitted` 使用服务器派生的本人员工号查询单据,再由网关统一按时间窗口过滤。读取历史详情时再次验证当前用户确实处理过该任务或确实是发起人;审批正文、费用明细和附件仍只实时读取、不落库。
@@ -82,7 +92,7 @@ Agent 面向统一审批语义,不直接理解钉钉 `processInstanceId/taskId
撤回接口若返回 `XFTSYS*` 服务异常或网络级异常,网关会立即只读复核本人单据状态:已撤回则返回 `revoked`,仍为待审批则返回带 `postWriteVerified` 的 `failed`,无法明确归类才返回 `outcome_uncertain`。任何分支都不会自动重试写操作。
截至 `1.1.0-rc.14`,薪福通撤回仍是实验能力:当前企业真实调用 `approve/recall` 会返回 `XFTSYS9999`,写后复核确认单据仍为待审批,尚无成功样本。该限制不影响薪福通查询、审批处理或发起审批;正式版不得把“接口已接通”表述为“撤回已验证成功”。
截至 `1.1.0-rc.15`,薪福通撤回仍是实验能力:当前企业真实调用 `approve/recall` 会返回 `XFTSYS9999`,写后复核确认单据仍为待审批,尚无成功样本。该限制不影响薪福通查询、审批处理或发起审批;正式版不得把“接口已接通”表述为“撤回已验证成功”。
薪福通创建或撤回需要复核时,`approval_get_submission_status` 先用服务器派生的本人员工号和单据详情双重确认目标属于当前用户的已发起单据,再返回状态名称和精简流程历史。只有实时状态仍为 `1(待审批)` 才签发新的短期、用户绑定 `revokeId`;已通过、草稿、拒绝或已撤回单据都不会获得撤回引用。该工具不返回审批正文,也不触发写操作。
+3 -3
View File
@@ -37,7 +37,7 @@ https://approval.justconn.top/oauth/dingtalk/callback
创建接口必须保持权限校验开启。网关统一提交 `APPRV_PEND`,并在写后实时读取本人单据状态:进入待审批时提供撤回引用;按企业流程规则即时通过时返回 `completed`,不提供撤回引用且禁止重复提交。
`1.1.0-rc.14` 中薪福通撤回仍标记为实验能力:权限和调用契约已接通,但当前企业真实请求返回 `XFTSYS9999`,尚未取得成功样本。网关会写后复核并禁止自动重试。面向试用用户时必须保留这一说明;若业务要求撤回必须稳定可用,应等待薪福通定位后再升级为正式能力。
`1.1.0-rc.15` 中薪福通撤回仍标记为实验能力:权限和调用契约已接通,但当前企业真实请求返回 `XFTSYS9999`,尚未取得成功样本。网关会写后复核并禁止自动重试。面向试用用户时必须保留这一说明;若业务要求撤回必须稳定可用,应等待薪福通定位后再升级为正式能力。
## 首次凭证配置
@@ -119,7 +119,7 @@ https://approval.justconn.top/downloads/dingmcp/install.md
公开 `install.md` 是按回调拓扑选择路径的短安装说明。同机浏览器能够完成宿主回调时,Agent 应按宿主官方方式注册名为 `dingtalk-approval` 的远程 Streamable HTTP MCP,URL 为 `https://approval.justconn.top/mcp`,并由宿主使用标准 OAuth 元数据、动态客户端注册和 PKCE 登录。该路径不下载 Node/npm、Bridge 或 Skill;网关 MCP `instructions` 已提供完整业务规则。登录后只读调用 `approval_list_todos(source=all, limit=1)`,钉钉 OA 与薪福通都为 `ok` 才算验收通过。
宿主缺少远程 MCP/标准 OAuth,或 loopback 回调与用户打开授权页的设备不一致时,`install.md` 引导到 `compat-install.md`,无需先尝试一次必然失败的远程登录。兼容页保留签名客户端、平台引导、Skill、stdio MCP、可跨设备的 device-code 登录、更新、卸载和故障恢复步骤。Windows PowerShell 产物必须带 UTF-8 BOM,Node 探测使用外层双引号/内层单引号,避免 PowerShell 5.1 吞掉传给原生程序的双引号。
宿主缺少远程 MCP/标准 OAuth,或 loopback 回调与用户打开授权页的设备不一致时,`install.md` 引导到 `compat-install.md`,无需先尝试一次必然失败的远程登录。兼容页保留签名客户端、平台引导、Skill、stdio MCP、可跨设备的 device-code 登录、更新、卸载和故障恢复步骤。完整 Skill 必须同时包含 `references/create-approval.md` 和 `references/local-drafts.md`。Windows PowerShell 产物必须带 UTF-8 BOM,Node 探测使用外层双引号/内层单引号,避免 PowerShell 5.1 吞掉传给原生程序的双引号。
兼容 Windows 下载优先使用 `curl.exe`,从系统代理变量继承代理,并设置 10 秒连接超时、20 秒低速判定和 90 秒单源总时限;没有 curl 才以 `Invoke-WebRequest -TimeoutSec 90` 兜底。Node 固定版本制品仍按阿里云、npmmirror、官方源顺序尝试并强制校验官方 SHA-256。项目 artifact 由 Ed25519 清单和 SHA-256 保护;来源失败可换源,签名或哈希不符必须立即停止。
@@ -135,7 +135,7 @@ curl --fail https://approval.justconn.top/downloads/dingmcp/manifest.json
curl --fail https://approval.justconn.top/downloads/dingmcp/manifest.sig
```
备份时必须把 `.runtime/auth.sqlite`、同路径派生的 `.runtime/auth.sqlite.invoice-dedup.sqlite` 与 `.secrets/oauth-session.key` 一并迁移。发票查重库只含不可逆 HMAC 和最小状态元数据;审批正文不落库,不需要备份。
备份时必须把 `.runtime/auth.sqlite`、同路径派生的 `.runtime/auth.sqlite.invoice-dedup.sqlite` 与 `.secrets/oauth-session.key` 一并迁移。发票查重库只含不可逆 HMAC 和最小状态元数据;审批正文不落库,不需要备份。本机提单草稿不在服务器上,也不属于服务器备份;用户如需迁移,必须把 Agent 所在机器的当前用户私有草稿目录作为敏感业务数据单独处理。
每个候选版和正式版发布前执行 [发布检查清单](release-checklist.md)。
+1
View File
@@ -17,6 +17,7 @@
- 兼容安装结果的 `loginCommand` 能在 MCP 未加载时刷新登录链接;MCP 已加载时 `approval_login` 完成同一操作。不得因链接过期而重装,首次成功响应只展示一次 onboarding 示例。
- 只读验证待办、本人已处理历史、本人发起历史、历史默认最近 30 天及显式时间窗口、搜索、详情、费用结构化字段、动作、模板 Schema、部门/城市选项和越权拒绝;历史引用必须被动作查询和批处理拒绝。
- 发票查重验证钉钉/XFT 跨来源精确匹配、弱匹配、用户隔离、状态更新、来源不可用、历史截断、详情失败、并发确认、35 天过期清理和网关重启恢复;数据库不得出现用户 ID、发票原号、审批正文或附件。重复风险和不完整覆盖未获用户确认时不得签发可提交 `confirmationId`。
- 本机草稿验证 Windows/macOS/Linux 私有目录选择、POSIX `0700`/`0600`、原子保存、90 天普通草稿清理、模板和 Schema 实时恢复、附件 SHA-256 变化、提交成功删除、确定失败保留及 `outcome_uncertain` 冻结。确认网关数据库、日志、发行包和项目仓库都不出现草稿正文,草稿中不保存 Token、身份 ID、短期模板/确认/撤回引用或完整 Schema。
- 真实写操作只执行用户明确授权的样本;任何 `outcome_uncertain` 都停止,不自动重试。
- Mock 契约确认网关和 bridge 的批量 Schema 均固定为 20;第 6 个截断引用及任一无效退回目标都会返回 `preflight_failed`、`writesStarted=false`,上游写调用数为 0。
- 代表性 v4 引用长度满足钉钉 OA 不超过 128 字符、薪福通不超过 80 字符,并通过篡改、过期、跨用户、跨密钥、同密钥重启及 v2/v3 兼容测试。