外观
Nexo — 2026-09-27 迭代需求文档
范围:落地审批平台首期。总 PRD 见 lamolabs-docs#54(审批平台总 PRD),本文承接其 §6.1 MVP 范围,只裁剪不扩张;产品语义(槽位语法、三种发起方式、会签/或签判定、三层状态机等)一律以总 PRD 为准,本文不复述其推导,只登记本期落地口径与降级决策。 验收标准见第 8 节,本文档定义"做什么"与"为什么";"怎么做"以同目录技术方案(
design.md)为准。
1. 背景与目标
2026-09-20 迭代交付权限平台首期时,明确挂了一条账:"审批平台仍是长期 PRD、未立项,本期写操作直落真实表,只预留审批门控开关位"(见 0920 PRD §4.1)。本期即是那条挂账所指的"审批平台上线迭代"。
同时,生态内所有审批仍停留在 IM 人工喊话(总 PRD P1-P5):无统一入口、无结构化记录、规则靠口头约定、无 SLA、每个场景都得重做一遍表单和流转。
本期新建 nexo-approval-api(审批平台后端,端口 3003、单库 nexo_approval) 与 nexo-approval-console(统一审批门户前端),一次落地引擎内核 + 人可用的门户两条线:模板配置、三种发起方式、两阶段槽位解析、条件分支、三种判定策略、审批操作与三层状态机、append-only 审计,以及动态表单渲染、审批详情页、待办与我发起的列表。
核心目标(对应总 PRD P1/P2/P3/P5):
- 有引擎:审批规则从口头约定变成模板 JSON,改人不改代码(P3);
- 有入口:发起方与审批方在一个门户里看完整条审批单,不再翻 IM(P1);
- 可追溯:每一次操作落
ApprovalAction+AuditLog,仅追加不可改(P2); - 可复用:三种发起方式走同一条装配管线,新场景接入不新增引擎代码(P5)。
P4(SLA / 超时自动裁决)本期不做 —— 超时引擎与 IM 通知一并放到下期,理由见 §4.2。
2. 承接与已知欠账
| 欠账项 | 处理 | 排期 |
|---|---|---|
0920 PRD §11 候补第一优先:nexo-account / nexo-im-api 接入 SDK 鉴权,偿还"合法 JWT 即放行" | 本期纳入为并行还债线。审批平台是第三个 perm-api 消费者,三家一次接完能在同一批用例里验证 SDK 契约,分两期反而要回归两遍 | 2026-09-27 |
| 0920 PRD §4.1:perm-api 硬删除等高危写操作预留了审批门控开关位,未接 | 本期只交付审批平台本体,perm-api 侧的实际接入(含回调签名、epoch 快照校验)不在本期,避免双平台同期互踩——与 0913→0920 的处理方式一致 | 下期 |
nexo-auth#60 服务与仓库更名 nexo-account 未完成 | 本期不动存量仓库;新服务的配置与文档一律按 nexo-account 最终命名书写,不再产生新的 nexo-auth 引用 | 挂账 |
| 生态无审计平台 | 沿用 0920 的投递适配层模式:审批平台本地落 AuditLog 表 + 结构化日志,投递目标可替换 | 沿用 |
3. 功能需求
FR 与任务映射见 §7;每条 FR 的完整产品语义见总 PRD 对应章节,此处只登记本期落地边界。
FR-1 审批模板管理(总 PRD §4.1) 系统必须支持创建、编辑、查询审批模板,模板持有 form_schema / flow_config / timeout_config / defaults 四份 JSON 配置。
FR-2 模板配置强校验 系统必须在模板写入前校验四份 JSON 的结构合法性:字段类型枚举、节点 ID 唯一、next 指向存在的节点、无环、 命名合法、countersign_rule 与 strategy 自洽。校验不过即拒绝写入,不存半成品模板。
FR-3 资源类型注册与模板绑定(总 PRD §4.2 方式一) 系统必须支持注册 resource_type 并绑定到一个审批模板,type_key 全局唯一,记录注册方 owner。
FR-4 三种发起方式同构装配(总 PRD §4.2) 系统必须支持 resource_type / template_id / template_config 三种入参创建审批单,三者仅在"取模板"这一步分叉,取到模板后走完全相同的装配管线;内联模板不持久化为可复用模板,仅绑定当前审批单。
FR-5 第一阶段槽位预填(总 PRD §4.3 步骤 1) 系统必须在创建审批单时,用 payload 中的值预填 fill_by: "system" 的表单字段,返回审批单 ID 与详情页 URL,审批单状态置 pending,此时不实例化节点。
FR-6 第二阶段槽位解析与校验(总 PRD §4.3 步骤 3) 系统必须在提交人提交时合并 payload + submitter 数据,替换模板中全部 (缺失时回落 defaults),并在替换后校验:必填槽位无缺失、审批人槽位解析结果非空且为合法用户。校验失败返回错误并停留在填写态,不产生半实例化的审批单。
FR-7 条件分支求值与节点实例化(总 PRD §4.1 / 数据模型 flow_config) 系统必须按 next.if 顺序求值结构化条件(slot / operator / value,支持 == != > >= < <= in not_in),确定最终节点序列,实例化 ApprovalNode 列表,审批单状态置 in_progress。dynamic_nodes 仅在被条件路由命中时实例化。
FR-8 角色审批人解析(总 PRD §5.6) 系统必须将 type: "role" 的审批人解析为具体用户列表,解析结果快照存入节点的 approvers,不在审批过程中二次查询;解析依赖 nexo-perm-api 新增的角色成员反查接口。
FR-9 判定引擎(总 PRD §4.3) 系统必须实现三种节点策略:single(一人决出)、any(任一通过即通过,全员拒绝才拒绝,其余人置 cancelled)、countersign(all / majority / ratio 三种 mode + veto_users 一票否决)。
FR-10 审批操作与三层状态机(总 PRD §4.3) 系统必须支持通过 / 拒绝 / 撤回 / 评论四种操作,并维护审批单、节点、审批人三层状态的一致流转;通过、拒绝、撤回各落一条 ApprovalAction,评论只落 ApprovalComment。
FR-11 业务方取消(本期新增,见 §4.6) 系统必须提供业务方身份可调的取消接口,用于业务单据作废时同步终止审批单,终态为 cancelled,与发起方主动 withdrawn 区分。
FR-12 审计日志(总 PRD §4.6 / §5.3) 系统必须对模板创建、模板编辑、资源类型注册、资源类型改绑、发起、提交、通过、拒绝、撤回、取消十个动作落 AuditLog(动作码见技术方案 §7.2),表仅追加,库层拒绝更新与删除。
FR-13 查询接口(总 PRD §4.3 步骤 6 / §4.4) 系统必须提供:按 ID 查审批单状态(业务方用)、审批单详情(含节点与时间线)、我的待审批列表、我发起的列表,后两者支持分页与状态筛选。
FR-14 平台自身接口鉴权(总 PRD §5.3) 系统必须在 nexo-perm-api 注册自身权限点并接入 /internal/check 判定,管理接口按平台管理员/业务方管理员角色管控,不得出现任何硬编码管理员逻辑。
FR-15 动态表单渲染器(总 PRD §4.1) 门户必须根据 form_schema 渲染表单,支持文本、数字、日期、下拉、多选、是/否六种字段类型,并按 fill_by(system / submitter / approver)× 当前用户角色决定每个字段的只读或可写。
FR-16 审批详情页(总 PRD §4.3 / §4.4) 门户必须提供单一详情页承载全流程:预填数据展示、提交人补充填写并提交、审批人操作、流转时间线、resource_url 跳转业务上下文。平台不单独提供"发起表单"页。
FR-17 待办与我发起的(总 PRD §4.4) 门户必须提供"我的待审批"与"我发起的"两个列表,聚合所有业务方的审批单,支持分页与状态筛选。
FR-18 桌面壳挂载 桌面壳侧边栏必须挂载审批门户入口,登录态与子应用切换沿用 nexo-perm-console / nexo-user-console 既有方案。
FR-19 存量服务接入 SDK 鉴权(承接 §2 第一条) nexo-account 与 nexo-im-api 的管理接口必须改为经 nexo-backend-sdk 鉴权客户端判定,移除"合法 JWT 即放行"。
4. 本期裁剪与降级决策
以下六条是总 PRD §7.2「待决策(开放问题)」为空、但实际卡在关键路径上的口子。本期就地收口,收口结论同步回填总 PRD #54。
4.1 附件字段移出 MVP
总 PRD §4.1 把"附件上传"列进 MVP 字段类型,但全生态没有对象存储:nexo-im-api 的消息类型只有 'text',全仓检索无任何 OSS/S3/MinIO/upload 实现。照搬会让本期顺带做一个文件服务。本期表单字段类型收敛为文本 / 数字 / 日期 / 下拉 / 多选 / 是否六种;附件与富文本、动态表格、关联资源选择器一并列入候补(§11)。业务上下文靠 resource_url 跳转承接。
4.2 通知与超时引擎不进本期
总 PRD §4.5 的 IM 通知与多级超时依赖两个不存在的东西:nexo-im-api 没有系统/机器人消息推送的 internal 接口(现有 /conversations/{id}/messages 是用户态,机器人发不出去),超时 escalate 需要汇报线而 nexo-perm-api 只有组织与角色、查不出上级。本期门户待办即通知:审批人靠"我的待审批"列表与未处理计数感知,不推送、不自动裁决。下期同时交付 im-api 系统推送接口与超时扫描器。
随之降级:审批单状态机本期不出现 auto_approved / auto_rejected 两个终态(枚举位保留,无代码路径产生)。
4.3 escalate 语义重定义
即便下期做超时,"升级通知上级"也无数据来源。口径改为:模板通过 槽位显式声明升级对象,平台不推导上下级关系。本期只在模板 schema 校验里认这个槽位,不实现动作。
4.4 删除 multi_level 策略枚举
flow_config 的节点串联本身就是"多级",节点上再挂一个 multi_level 策略是同一语义的第二套实现,会让判定引擎出现两条互相覆盖的路径。本期 strategy 枚举收敛为 single / countersign / any 三种,多级审批 = 多个串联节点。
4.5 或签判定规则补死
总 PRD §4.3 的或签状态机只写了"有人拒绝但其他人未处理 → in_progress",没写终态条件。本期定死:任一人通过 → 节点 approved,其余人置 cancelled;全员拒绝 → 节点 rejected。单人拒绝不终止或签节点。
4.6 两处数据模型缺口一次建全
- 业务方取消:总 PRD 只给了发起方"撤回",业务单据作废(如发布单关闭)时审批单会成孤儿。本期补
cancelled终态与业务方取消接口(FR-11)。 - 数据隔离字段:总 PRD §5.3 要求"审批单按业务方隔离",但
ApprovalOrder没有归属字段,方式二/三完全无归属。本期建表即加namespace(对齐nexo-perm-api命名空间口径)。隔离字段本期建全,按隔离过滤的列表行为放到下期——避免为了补字段做二次迁移。
5. 明确不做(Out of Scope)
- IM 通知推送与站内通知中心(§4.2)
- 超时引擎:计时器、多级阈值、
remind/escalate/auto_approve/auto_reject(§4.2) - 附件上传与富文本、动态表格、关联资源选择器(§4.1)
- 转交 / 加签(总 PRD §6.2)
- Webhook 回调(总 PRD §6.2,本期业务方走按 ID 轮询)
- 模板可视化编排界面(本期模板经 API 与 JSON 编辑器维护,见 §10 Q2)
- 资源类型管理界面(本期经 API 注册)
- 按业务方隔离的列表过滤行为(§4.6,字段本期建,行为下期)
nexo-perm-api高危写操作接入审批门控(§2)- 审批统计看板、业务方申请模板创建权限(总 PRD §6.2)
- i18n(总 PRD §5.5,本期仅中文)
6. 非功能需求
- 性能:审批单创建 API < 1s;审批操作 < 1s;详情页首屏 < 2s;待办列表首屏 < 2s 且分页(总 PRD §5.1)
- 安全:
ApprovalAction/AuditLogappend-only,无更新与删除路径;平台自身接口全部经 perm-api 判定,零硬编码管理员(FR-14) - 解耦:审批平台不落地用户与角色数据,角色成员解析结果仅作为节点快照存储(总 PRD §5.6)
- 幂等:同一审批人对同一节点重复提交同一操作必须幂等,不产生第二条
ApprovalAction - 可用性:平台故障不得反向阻塞业务方创建流程之外的既有功能——本期无存量接入方,回滚 = 停服务 + 壳隐藏入口
7. 任务映射
24 个任务已建 issue 并挂组织 Project,锚点
nexo-2026-09-27:Bxx/Fxx/Txx;总追踪见 lamolabs-docs#86。 分工:前端(F 线)全部 @wshiqyuan,其余(B / T 线)全部 @snailuu。
| 编号 | Issue | FR |
|---|---|---|
| B01 | nexo-approval-api#1 服务骨架与核心数据模型 | 全部地基 |
| B02 | nexo-approval-api#2 模板管理接口与配置强校验器 | FR-1 / FR-2 |
| B03 | nexo-approval-api#3 资源类型注册与模板绑定 | FR-3 |
| B04 | nexo-approval-api#4 三路发起同构装配与第一阶段预填 | FR-4 / FR-5 |
| B05 | nexo-approval-api#5 第二阶段槽位解析与提交校验 | FR-6 |
| B06 | nexo-approval-api#6 条件分支求值与节点实例化 | FR-7 |
| B07 | nexo-approval-api#7 角色审批人解析与节点快照 | FR-8 |
| B08 | nexo-approval-api#8 判定引擎三策略 | FR-9 |
| B09 | nexo-approval-api#9 审批操作与三层状态机 | FR-10 |
| B10 | nexo-approval-api#10 业务方取消与 cancelled 终态 | FR-11 |
| B11 | nexo-approval-api#11 append-only 审计日志 | FR-12 |
| B12 | nexo-approval-api#12 查询、待办与我发起的列表 | FR-13 |
| B13 | nexo-approval-api#13 平台自身接口鉴权与权限点注册 | FR-14 |
| B14 | nexo-perm-api#35 角色成员反查 internal 接口 | FR-8 |
| B15 | nexo-auth#83 账号中心接入 SDK 鉴权 | FR-19 |
| B16 | nexo-im-api#85 IM 管理侧接入 SDK 鉴权 | FR-19 |
| F01 | nexo-approval-console#1 门户骨架与登录态 | 前端地基 |
| F02 | nexo-approval-console#2 动态表单渲染器与读写矩阵 | FR-15 |
| F03 | nexo-approval-console#3 审批详情页 | FR-16 |
| F04 | nexo-approval-console#4 我的待审批与未处理计数 | FR-17 |
| F05 | nexo-approval-console#5 我发起的与进度查看 | FR-17 |
| F06 | nexo-approval-console#6 模板 JSON 编辑器与校验预览 | FR-1 / §10 Q2 |
| F07 | nexo-app#63 壳侧边栏挂载审批门户入口 | FR-18 |
| T01 | lamolabs-docs#87 验收用例编写与预跑归档 | 全部 |
8. 验收标准
- 验收用例见同目录
tc.md(由 T01 维护并预跑归档证据,门禁逐条映射见该 issue 的「门禁映射」表),覆盖:- 三种发起方式产出结构一致的审批单(同一模板分别走
resource_type/template_id/template_config,装配结果逐字段比对一致) - 总 PRD 数据模型里的
tpl_release_prod模板,is_urgent取true/false两条分支各跑通一次,节点序列符合预期 - 会签三种 mode(
all/majority/ratio)各一条,外加veto_users一票否决立即拒绝一条 - 或签两条终态:任一通过 → 其余
cancelled;全员拒绝 → 节点rejected(§4.5) - 槽位校验失败路径:必填槽位缺失、审批人解析为空,均停留在填写态且不产生节点
- 撤回与业务方取消两条终态区分正确
- 审计完整性:一单走完后
ApprovalAction与AuditLog条数与操作数一致,且无更新/删除接口可用 - 门户主流程:一个人从收到链接到审批完成全程不碰 API
- 三种发起方式产出结构一致的审批单(同一模板分别走
- 硬阈值实测取数不得估算:审批单创建、审批操作两个 API 的 p99 响应时间
9. 排期与发布(概要)
- 开发窗口 09-22 至 09-26,09-27 验收会;前后端并行策略沿用 0920 做法——接口契约在技术方案冻结后,F 线按契约 mock 先行,不等 B 线
- 发布顺序:test 环境全量联调(09-26)→ 验收通过后 prod 发布 + 首个模板种子;回滚 = 停服务 + 壳隐藏入口,对现有业务零影响(本期无存量业务方接入)
- 逐日排期见技术方案
design.md§15;验收底线为 B01–B09 + B12(门禁 #1–#5、#7),B10 / B11 / B13 / B15 / B16 允许顺延至验收会前一晚
10. 待评审收口
| 编号 | 事项 | 倾向口径 |
|---|---|---|
| Q1 | 首批接入场景。总 PRD §2.3 写的是"发布审批(发布平台)",但发布平台无仓库、总 PRD #50 仍是 p2 草稿——照此排期,"新场景接入无需开发"(P5)没有真实消费者可验证 | 改用权限授予审批作为首批场景:nexo-perm-console 现状是"有管理员角色即可直接授权、无二次确认",把 POST /api/subject-roles 与 /api/direct-grants 改为先落审批单,消费者现成且有真实风险敞口。发布平台作为第二个场景接入,反而能真正验证 P5。本期只验证引擎与门户,场景接入落在下期 |
| Q2 | 模板维护方式 | 本期 API + JSON 编辑器 + 实时 schema 校验 + 节点序列预览;可视化编排留候补。理由:flow_config 结构本期还会随实现微调,先做可视化会返工 |
| Q3 | 审批平台权限点粒度 | 沿用 0920 Q2 口径,按资源粒度建点(模板 / 资源类型 / 审批单 / 审计),不按端点逐一建 |
| Q4 | 会签 ratio 的 threshold 边界 | ≥ threshold 判通过(总 PRD 数据模型已写"通过比例 ≥ threshold"),本期不做可配置的取整策略 |
| Q5 | template_config 内联模板是否走 FR-2 全量校验 | 走。内联路径与持久化模板共用同一校验器,校验不过直接拒绝创建 |
| Q6 | 技术方案对总 PRD 数据模型的四处偏离(三路统一 template_snapshot、审批人拆独立表、节点序列物化为线性 seq、append-only 由 DB 触发器兜底) | 全部采纳。API 对外形状与总 PRD 一致,偏离全在存储层;逐条理由见 design.md §7.1 与 §18。评审通过后回填总 PRD #54 数据模型章节 |
11. 候补(登记,本期不做)
- IM 系统消息推送 internal 接口 + 审批通知适配层(下期第一优先)
- 超时扫描器与多级超时动作、
auto_approved/auto_rejected终态落地 - 首批业务场景接入(Q1 收口后落地)与按业务方隔离的列表过滤
- 附件上传(依赖对象存储或最小文件服务立项)、富文本、动态表格、关联资源选择器
- 转交 / 加签、Webhook 回调、审批统计看板
- 模板可视化编排、资源类型管理界面
nexo-perm-api高危写操作接入审批门控(偿还 0920 §4.1 预留开关位)
12. 风险与降级
| 风险 | 应对 |
|---|---|
| 首批消费者缺位:发布平台未立项,P5"接入无需开发"本期无法端到端证明 | 本期验收只证明引擎与门户;P5 的证明推到场景接入迭代。Q1 建议改用权限授予审批,把消费者从"等发布平台"变成"现成的 perm-console" |
| 双新仓并行(后端 + 前端),接口契约漂移 | 沿用 0920 做法:技术方案接口契约章节为冻结源,变更须先改文档再改代码 |
动态表单渲染器是前端单点大件(6 种类型 × 3 种 fill_by × 3 种角色视角) | F 线优先级最高,骨架与渲染器在开发窗口前两天完成;矩阵用例进 tc.md 逐格验收 |
| 三路发起方式容易长成三套代码 | 装配管线定为单一入口,三路仅"取模板"一步分叉;验收用例强制三路结果逐字段比对(§8 第一条) |
| 角色成员反查是跨仓依赖,perm-api 侧排期若滑,FR-8 阻塞 | 该接口是 perm-api 单文件读接口,排在 B 线最前;滑期降级为审批人只支持 type: "user",角色审批人顺延 |
| 本期同时还 0920 的接入债(FR-19),两件事抢窗口 | FR-19 是两个中间件替换,排在验收会前一晚亦可;不得反向挤占 B 线引擎任务 |
13. 名词解释
口径与总 PRD #54 完全一致(审批模板 / 资源类型 / 审批单 / 审批节点 / 槽位 / 会签 / 或签 / 一票否决 / 条件分支 / 内联模板等),本文不重复登记;本期特有的收口与降级见 §4。