Files
Agent-System/.doc/remediation/2026-09-17-document-author-only-plan.md

33 KiB
Raw Permalink Blame History

title, type, date, status, artifact_contract, product_contract_source, execution
title type date status artifact_contract product_contract_source execution
文档编制人兼任审核批准 - Plan feat 2026-09-17 planned ce-unified-plan/v1 ce-plan-bootstrap code

文档编制人兼任审核批准 - Plan

Goal Capsule

在系统管理员授权后,项目创建者可以为项目工作流中的每份文档单独启用「编制人兼任审核、批准」,只选择一位编制人即可完成该文档的全部人工职责。

本次交付为设计方案,尚未授权业务实现。已确认的需求是两级授权和逐文档配置。R9(激活前配置/激活后冻结)与 R10(关总开关后存量按冻结继续、不提供紧急熔断)已于 2026-09-17 审核批准,并补强 Heal 三入口投影稳定性为硬性验收项。实现与发布须分别提供源码、数据库、真实产品 PI 和浏览器证据。

基线为本地 dev@adb48c8,2026-09-17 源码核查;不代表正在运行的镜像已具备本能力。远端已 fetch,本地 dev 领先 origin/dev 44 个提交、落后 0。本方案不修改正式工作流定义,不将兼任等同于免审批。


Product Contract

Summary

新增管理员总开关,默认关闭;新增逐文档职责模式,默认沿用当前规则。创建者开启某份文档的兼任模式后,只填写编制人,审核人与批准人由服务端派生为同一人。仍执行送审、审核和批准,保留每一步身份、意见和时间。

Problem Frame

当前系统仅允许可选文档三职全空或三职完整指定,且完整指定时要求三人不同。用户需要小团队或个人也能执行完整的文档治理流程,并由管理员控制这一例外是否可用。

当前权限、文档人员投影和前端角色识别使用不同数据路径。因此仅放宽三职分离校验不足以支持本需求,还必须保证配置、生成、查看、修改、审批和阶段推进使用同一份职责来源。

Requirements

权限与配置

  • R1. 仅系统管理员可开启或关闭系统级「允许编制人兼任审核、批准」权限,默认关闭。
  • R2. 仅权威项目创建者可为自己创建的项目逐文档选择兼任模式;普通成员、项目角色管理员和其他项目创建者不能设置。系统管理员如果不是该项目创建者,也不因此获得逐文档配置权。
  • R3. 每份文档独立选择,管理员开启总权限不自动修改任何项目或文档;新文档、新实例和复制产生的文档默认不继承兼任授权。
  • R4. 兼任文档必须指定一名有效、在任的项目成员为编制人;可以不是创建者。审核与批准由该人承担,不能再指定其他审核人或批准人。

审批与可见性

  • R5. 兼任模式属于纳入人工审批:保留送审→审核→批准三个动作、现有内容锁和驳回要求;不得生成完成后自动批准或通过阶段门禁。
  • R6. 未开启兼任的文档继续遵守当前三职分离与可选免审批规则;必需文档不得借兼任模式省去编制人或审批。
  • R7. 设置页、冻结快照、文档详情、操作按钮、签署展示与日志一致显示兼任关系;同一个人能在正确状态执行对应职责动作。
  • R8. 兼任不授予系统管理员、创建者或其他成员代审权,也不扩大跨项目读取、非当前阶段写入和已结束实例写入权限。

生命周期与持久化(已审核批准,2026-09-17)

  • R9. 首期仅在工作流激活前配置;激活时冻结该文档模式和职责,运行中的实例不直接改规划。已激活的存量项目不自动转换。若用户要求运行中转换,必须先扩展本方案的受控职责变更单元,不可悄悄放开现有 PUT。
  • R10. 管理员关闭总开关后,禁止新启用、保存仍含兼任的规划和激活兼任规划;允许清除兼任后保存。已激活的兼任实例按冻结授权继续执行,历史日志不变。界面必须解释该开关是「授权新配置」,不是紧急停用所有存量审批;本期不提供针对已激活实例的紧急撤销/熔断能力。
  • R11. 模式、编制人、授权依据、配置版本及各步骤日志需持久化,刷新、重登和服务重启不得丢失。
  • R12. 编制人离任或账号停用后,不得继续执行三项职责;阻断尚未完成动作并展示原因,不自动找替代人,不重写历史签署。

Permission Matrix

操作 系统管理员但非项目创建者 当前项目创建者 普通项目成员 其他项目用户
修改系统总开关 允许 仅同时为系统管理员时 禁止 禁止
查看本项目可用模式 沿用当前项目读取权限 允许 沿用项目读取权限 禁止
规划期逐文档启停兼任 禁止 总开关开启才可启用;可关闭 禁止 禁止
指定编制人 禁止 规划期按 R4 禁止 禁止
送审、审核、批准 仅自己是该文档指定职责人时 同左 同左 禁止
已激活实例直接改职责 禁止 禁止(R9) 禁止 禁止

Mode Matrix

「文档启用」「纳入人工审批」「编制人兼任」是不同含义,不能复用一个开关。

文档状态/配置 输入 有效职责 审批与门禁
文档禁用 不设置职责 无 沿用 skipped_disabled
可选文档免审批 三职全空,兼任关闭 none 沿用既有免审批规则
标准人工审批 三职齐全且三人不同 full 保留正常人工审批
兼任人工审批 兼任开启,仅编制人 A author_only;有效三职为 A/A/A 与标准审批同样要求最终批准
未开兼任却只填 A 缺审核和批准 partial 拒绝
标准模式填 A/A/A 三职同人 非法 继续拒绝职责分离违规
兼任开启但无 A 缺编制人 非法 拒绝
兼任开启又填不同审核人 B 矛盾输入 非法 拒绝,不能静默吞掉 B

User Flows

  1. 管理员进入「系统管理台→系统设置→工作流治理」,开启总授权;页面显示保存结果、修改人和修改时间。
  2. 创建者进入项目设置,展开某个阶段,在文档行开启「由编制人兼任审核、批准」。只保留编制人选择器,其余两项显示「同编制人(自动承担)」。其他文档保持原配置。
  3. 保存并预览:摘要列出标准审批、兼任审批、免审批的份数,列出每份兼任文档及编制人。确认后冻结。
  4. 编制人完成内容后送审,在审核中以审核人身份确认,在批准中以批准人身份确认;日志展示同一人对应三个职责,而非三个虚构人员。
  5. 页面刷新、重新进入项目后仍显示同样配置;最终批准后才按现有阻塞条件满足阶段门禁。

Scope Boundaries

本期覆盖所有通过项目工作流实例管理的文档,不针对某个任务名写白名单;freeform 文档与未绑定工作流的旧文档不提供此开关。不新增批量全选、不改项目成员全局 document_duty 为多角色,不自动改已发布工作流模板或历史签署。

生命周期口径(已审核批准,2026-09-17): R9 首期仅激活前配置、激活后冻结职责;R10 关闭总开关后禁止新启用/保存仍含兼任的规划/激活兼任规划,已激活实例按冻结授权继续执行。总开关是「授权新配置」,不提供已激活实例的紧急撤销/熔断能力;若业务需要合规级紧急止损,应作为独立后续方案,不在本期 Definition of Done 范围内。


Planning Contract

Current Implementation Evidence

以下为源码确认事实,不是运行验收结果。

位置 / 符号 当前行为 对本需求的影响
internal/projectinstance/types.go:DocTaskPlan / DocDuty 仅 enabled、approval_configurable 和三职 ID,无逐文档兼任标记 增加显式职责模式
internal/projectinstance/duty_mode.go none/partial/full;partial 拒绝;三职重复报 SEPARATION_OF_DUTY_VIOLATION 不能只填作者或仅关闭分离校验
internal/projectinstance/validator.go:validateActivationPlan / previewSummary 激活至少 countFullDutyDocs>0;预览统计 full/none 必须把合法兼任计为受治理文档
internal/projectinstance/service.go 创建者可保存/预览/激活;active 后 ErrPlanFrozen;已有 revision、plan hash、token 复用规划流程,补全授权版本和事务检查
internal/projectworkflow/service.go:IsProjectCreator 权威项目创建者检查 不使用 UI 当前角色或项目 manager 代替
internal/projectinstance/store.go:sync 子实例逻辑 从规划写 project_doc_task_instances 和三职 assignment 兼任需派生三项实际职责,不能只存作者而漏审批归属
internal/projectinstance/duty_action.go / stage_access.go / gate.go 按动作校验单一职责;阶段可见性有 full 判定;门禁依赖 approved 校验与阶段可见性都需认识新模式
internal/sysadmin/settings.go / store.go 白名单设置、DB 持久化;无该 key;只记录最后修改人时间 可复用管理入口,新增策略消费与历史审计
internal/server/admin_system_handlers.go 所有系统设置写入 requireSystemAdmin 复用该入口,不开放管理列表给普通成员
internal/docduty/store.go:HealProjectDocuments 按项目成员默认职责扫描并回填所有 task_key 非空文档 可能覆盖逐文档三职,必须区分实例绑定与旧默认
internal/bizdev/service.go / internal/docgov/project_docs.go 生成后、列表读取时调用 HealProjectDocuments 重开页面即可触发回填,必须验证刷新后仍一致
internal/docduty/revoke.go 成员职责变化撤销审核/批准槽位,随后参与 heal 不能把项目默认职责变化误当成逐文档兼任变更
internal/server/handlers.go:三个 DocGov 决议 handler 使用登录身份及动作固定 author/reviewer/approver;先执行工作流鉴权 服务端已有按动作身份模型,应保留
internal/docgov/state_machine.go drafting/reviewing/approving/approved;检查对应职责 ID;无额外三人不同判断 复用状态机,测试身份一致和锁定边界
web/src/lib/currentDocRole.ts author 命中后立即返回,不支持同时三职 A/A/A 会一直被当成 author
web/src/lib/docGovActionVisibility.ts / DocGovActionBar.tsx 按单一 currentRole 显示送审/审核/批准 必须改为动作能力或多职责判断
web/src/lib/projectSettingsDuties.ts / ProjectSettingsModal.tsx 重复服务端 full/none 校验,人工审批默认要求至少三人 单成员兼任会被前端提前挡住
deploy/postgres/goose/00017_2026-09-12-project-workflow-instances.sql assignment 唯一键是任务实例+职责,无跨职责用户唯一限制 同一用户可有三条职责记录,不必拆用户身份
deploy/postgres/goose/00049_2026-09-17-system-settings.sql system_settings 已存在 采用增量迁移,不重建设置机制

相关历史边界参见 .doc/test-reports/2026-09-14-governance-action-level-authz-test-report.md 与 .doc/test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md。它们说明已有验收意图,本次未重跑其测试。

IDE 所列 rdev 设计、short-term 和 backlog 当前位于 feature/rdev-template-depth 的独立工作区,不在本方案 dev 基线;已读取作兼容输入。rdev 的关闭文档/N/A、阶段前置、任务键命名空间化保持原语义。本方案按实例+阶段+任务身份绑定;待 rdev 合入后增加对应回归,不宣称其已在 dev 发布。

Key Technical Decisions

  • KTD1. 新增 duty_policy,值为 separated / author_only,属于 DocTaskPlan 的逐文档配置。缺省按 separated 解读;none/partial/full 仍是职责完整度,不能把「免审批」和「兼任」混为一谈。统一提供按任务解析模式、有效职责、是否受治理的领域能力;原 ClassifyDocDuty 保留给旧调用,治理调用迁到新解析器。(R3–R6)
  • KTD2. 配置快照保存用户意图:author_only 的 duties 规范形式只含 author_user_id。服务端通过唯一解析器派生有效 A/A/A,写三条 document_duty_assignments,并投影到 document_records 的三个 ID/名称。读接口区分配置职责与有效职责,客户端不得把有效 A/A/A 原样误写成标准配置。(R4、R11)
  • KTD3. 新设置 key 建议 workflow.allow_author_only_approval,类型严格 bool,默认 false,无环境变量绕过,保存无需重启。projectinstance 通过窄的策略读取接口消费,由 app 装配注入;不从领域服务调用 HTTP,不让 projectinstance 成为 sysadmin 设置表的第二写入 owner。(R1)
  • KTD4. 配置写入、预览和激活都复核总授权;真正激活必须在事务内对授权版本复核,并与关闭总开关串行化。token 绑定 plan hash、项目/规划版本、授权 revision。总开关 false→true 后旧 token 仍作废,不能以「当前又是 true」放行。(R10、R11)
  • KTD5. 实例绑定文档的职责权威是冻结 DocTaskPlan,经解析生成 assignments 和文档投影。项目成员 document_duty 只供旧无实例文档的默认分配。heal/revoke/生成/通知不得再次用项目默认人员覆盖实例文档。(R3、R7、R12)
  • KTD6. 运行时按具体动作检查有效职责和当前在任状态;状态机仍按 author/reviewer/approver 记录实际动作角色。前端采用服务端动作能力集驱动按钮,可同时拥有多个职责,保留 viewer fail-closed,不新增一个可以绕过所有检查的万能角色。(R5、R7、R8)
  • KTD7. 遵守 R9 的冻结边界;未知 mode、缺失授权来源或绑定不唯一时拒绝写动作。历史缺字段只代表旧 separated,不自动解释为兼任;不能全库 A/A/A 回填。(R6、R9、R11)

Data Model

以下是设计契约,字段落位按 owner 边界实现,不是现有字段清单。

数据 建议新增/扩展 用途与兼容
system_settings 目标 key;monotonic revision(默认 0) 总权限 CAS、token 失效;目标行在迁移时初始化 false,避免无行锁问题
系统设置审计 仅本策略必需的 before/after、revision、actor、时间、request ID 与设置更新同一事务提交;不把整站审计改造扩大到本期
DocTaskPlan JSON duty_policy,可选且旧值缺省 separated 逐文档意图,纳入 plan hash;兼容 old hash 的序列化须有固定样本
workflow instance 授权快照 policy key、revision、允许状态、activated_by/at 记录激活时获准的依据;由服务端生成,拒绝客户端伪造
activation token policy revision(新字段或令牌存储的版本化元数据) 防预览后管理员撤销授权;旧 token 含兼任无 revision 必须重新预览
document_records doc_task_instance_id 可空外键 对新实例创建文档强制绑定;旧文档仅唯一匹配才回填,不修改历史职责
document_duty_assignments 复用三角色,兼任三行 user_id 相同 无需放宽角色唯一约束;author 必须有效且正数
文档视图 duty_policy、effective_duties、allowed_actions、blocked_reason 以服务端计算值展示;读参数不能切换权限
文档审计 details duty_policy、instance/task ID、授权 revision 送审/审核/批准均记录真人身份及该次 action role

不预占 Goose 序号:实施时根据 dev 与并行 rdev 分支最新迁移取下一个空闲序号。迁移需覆盖 PG store 与 memStore 的字段 round-trip。兼容旧数据时禁止把 NULL 改成 0 外键。

High-Level Technical Design

职责解析链:

flowchart TB
  A[管理员总授权] --> B[创建者逐文档配置]
  B --> C[保存与预览校验]
  C --> D[事务内复核授权并激活]
  D --> E[冻结实例配置与授权依据]
  E --> F[统一解析有效三职]
  F --> G[职责表与文档人员投影]
  F --> H[动作鉴权和阶段可见性]
  H --> I[前端能力与操作按钮]
  G --> J[文档状态机与审计]

兼任保留原审批状态机:

stateDiagram-v2
  drafting --> reviewing: A以编制身份送审
  reviewing --> approving: A以审核身份通过
  reviewing --> drafting: A审核驳回并填写原因
  approving --> approved: A以批准身份通过
  approving --> drafting: A批准驳回
  approving --> reviewing: 现有配置允许时退回审核

新授权和冻结授权的判断路径:

flowchart TB
  A[请求] --> B{规划配置或激活?}
  B -->|是| C{权威创建者且planning?}
  C -->|否| X[拒绝]
  C -->|是| D{含author_only?}
  D -->|否| E[原职责规则]
  D -->|是| F{总授权有效且版本一致?}
  F -->|否| X
  F -->|是| G[检查作者与输入一致性]
  B -->|运行时动作| H[查冻结策略及实例任务绑定]
  H --> I[检查成员有效性 当前阶段 状态和租约]
  I --> J[按动作职责执行]

激活事务与设置撤销都以策略行锁形成先后顺序,再按统一顺序获取项目职责锁和实例相关行锁。策略 owner 提供事务兼容读取/锁定适配;不能照搬在事务外重查布尔值的方式。原则:关闭先提交则激活失败;激活先提交则成为 R10 中可继续的存量实例。并行成员移除与激活也必须在同一项目职责锁语义下判定,不能在事务开始前检查后直接信任。

API Contract

接口 变更 服务端强制条件
GET/PUT /api/v1/admin/system/settings[/{key}] 注册总开关;目标 key 增加 expected_revision,返回新 revision requireSystemAdmin;严格拒绝 null、字符串布尔;审计与值同事务
GET /api/v1/projects/{id}/settings 返回精简 governance_policy capability、revision 与 blocked_reason 保留项目访问校验;不泄露其他系统设置
PUT /api/v1/projects/{id}/workflow-plan 每个文档可传 duty_policy;兼任只传 author ID;沿用规划版本 创建者、planning、总授权、有效成员、输入无矛盾
激活 preview / activate 现有接口 预览分列兼任文档;token 绑定策略 revision 保存成功不等于已获激活授权;提交时重新事务校验
文档详情和项目文档列表 返回模式、有效三职与允许动作 统一来源;任务身份、实例身份须匹配
docgov 送审/审核/批准接口 URL不变,增加模式审计上下文 登录用户+对应 action,不信任请求的 user_id/user_name

建议新增错误码:AUTHOR_ONLY_POLICY_DISABLED(403)、AUTHOR_ONLY_POLICY_CHANGED(409)、AUTHOR_ONLY_AUTHOR_REQUIRED / AUTHOR_ONLY_DUTY_CONFLICT / UNKNOWN_DUTY_POLICY(400 validation issue)、DUTY_BINDING_AMBIGUOUS(409)、DUTY_ASSIGNEE_INACTIVE(403)。总权限存储不可用返回 503;缺失目标配置采用默认关闭,但数据库故障不能伪装成正常缺项。保留已有 PLAN_FROZEN、PLAN_REVISION_CONFLICT 与 SEPARATION_OF_DUTY_VIOLATION。

author_only 写入审核/批准 ID:省略或 0 为规范输入;若为与作者相同的正数,可规范化为省略以兼容回显,但若不同则拒绝。关闭兼任时清除派生审核/批准,要求重新选择符合分离规则的人员;旧选择可仅作为未保存草稿提示,不自动恢复为真实授权。

UX Details

系统设置开关说明写明 R10,并展示预计受影响的待激活兼任文档数量及存量继续执行说明。保存失败保留用户输入和错误,不在本地假装开启成功。多管理员同时修改返回版本冲突,不自动覆盖。

项目设置按文档行提供兼任选项;总权限关闭时禁用并解释来源;非创建者只读。兼任只能在文档已启用且纳入人工审批时选择。兼任文档仅需一位成员;混合方案只要仍存在标准人工审批文档,才继续提示至少三位有效人员。

总开关在页面打开期间被关闭时,保存失败展示定位到文档的原因,提供关闭兼任选项;不丢弃整份未保存规划,不自动重试激活。预览和冻结视图同时展示「角色指派数」和「实际人数」,避免 A/A/A 被误认为三个人。

文档正文签署区显示真实姓名及兼任标记,但未发生审核/批准时不得显示签署时间或声称已通过。按钮随状态变化,审阅阶段即使当前人也是作者也不能编辑锁定正文;驳回后恢复编辑。查看/认领按当前状态或明确动作记录相应角色,不能打开一次页面就伪造三次履责。

Risks and Compatibility

  1. 回填覆盖(硬性门禁,非偶然安全): HealProjectDocuments / ApplySlotRevocations 与 ConfigSnapshot 是独立职责写路径,当前不区分实例绑定文档。实现必须在 heal/revoke 增加「实例绑定文档跳过项目默认覆盖」显式分支,禁止依赖「只填缺失槽位、碰巧不覆盖」的偶然安全。U3 必须对三入口(文档生成、列表 GET、成员变更)及 author 被误判非在任时的 healSlot 分别证明投影不变;未通过不得开放 UI。
  2. 历史身份混淆: 不以 project_id+task_key 跨实例盲绑;旧文档匹配多实例则保持原记录并报可定位问题。新生成文档必须携带 task instance ID,无法绑定应停止受控写入。
  3. 成员退出: runtime 复核在任资格覆盖 author_only;保留冻结快照用于历史展示。普通成员默认职责改变不得影响冻结文档;真实退出/停用应阻断动作。暂不新增运行中换人 UI。
  4. 并发审批: 同一人可打开多个标签,服务端仍需保证状态比较/版本检查;重复请求不能重复创建批准事件、版本封存或推进通知。延迟到达的审核请求不能作用于后续修订版本。
  5. 通知与事件: 审核待办发给同一人是有效业务,不可因发送者=接收者一概过滤。按事件+接收者去重,不把审核与批准两项待办合并成一个动作。
  6. 回滚: 关闭开关只停止新配置,不能安全地把已存在兼任实例交给完全不识别新模式的旧二进制。上线后若需回退代码,保留模式识别与冻结策略读取兼容补丁;不得通过清空审核/批准人员回滚。
  7. 总开关非紧急熔断(R10): 关闭总授权不会阻断已激活兼任实例的剩余送审/审核/批准。界面与运维说明必须写明这一点,避免被误解为「关总开关=紧急止损」。存量紧急撤销不在本期范围。

Implementation Units

U1. 策略存储与总授权

目标:提供管理员可写、项目治理可可靠消费的总授权。覆盖 R1、R10、R11,采用 KTD3、KTD4。

文件:internal/sysadmin/settings.go、store.go、internal/server/admin_system_handlers.go、internal/app/ 装配、增量 Goose 迁移;必要时新增 sysadmin 内的策略审计存储文件。

实现重点:默认关闭;严格 bool;目标设置 revision 与 CAS;事务内审计;窄接口可参与激活事务。仅本 key 要求的新协议不破坏其他设置键调用。

测试场景:管理员开关成功;普通用户伪造 PUT 被拒;null/字符串拒绝;DB断开不放行;并发修改只一个版本成功;审计写失败时设置回滚;重启读回。

U2. 逐文档模式、规划校验与激活

依赖 U1。覆盖 R2–R6、R9–R11,采用 KTD1、KTD2、KTD4、KTD7。

文件:internal/projectinstance/{types,duty_mode,validator,service,store,hash,tx,errors}.go、internal/server/project_settings_handlers.go。

实现重点:新增模式解析;所有 full-only 分支改为正确的受治理判断;保存、预览、激活一致;任务禁用/免审批清除模式;有效成员检查;规划 hash/授权 revision 和确认 token 一致。保存快照与提升 plan revision 应原子化,失败不能留下可读取的新规划配旧版本。

测试场景:一位成员、至少一份合法兼任文档可激活;只填作者但未开模式仍拒绝;混合 full/none/author_only;其他项目创建者、非创建者管理员拒绝;修改总授权后旧 token 拒绝;激活与撤销并发的两种提交顺序;旧 separated snapshot/hash 兼容。

U3. 文档绑定与职责投影一致性

依赖 U2;这是开放 UI 前的必要门禁。覆盖 R3、R4、R7、R11、R12,采用 KTD2、KTD5。

文件:internal/docduty/{store,resolve,revoke}.go、internal/docgov/{types,engine,project_docs,repository}.go、internal/bizdev/service.go、internal/projectinstance/store.go、任务执行请求与 app 适配、增量迁移。

实现重点:新文档绑定具体任务实例;受治理实例职责优先;统一有效职责映射用于创建、读取、heal、memStore;legacy fallback 仅在明确无实例时可用。HealBinding/healSlot/ApplySlotRevocations 对已绑定 doc_task_instance_id 的文档必须显式跳过项目默认覆盖,不得因 author 被误判非在任而重新分配默认人。旧已批准文档不因新功能读取被改写签署人员。

测试场景:同项目两份兼任文档由不同作者承担;第三份标准审批三人;第四份 none;反复 GET/成员默认角色调整/重启后四份职责均不串;未知或歧义绑定阻断;旧无实例文档仍按既有规则;NULL外键正常。硬性投影稳定性(开放 UI 前门禁): 已激活 author_only 文档在以下三入口触发 HealProjectDocuments 后,document_records 与 assignments 投影必须保持 A/A/A——(1) 仅刷新文档列表(ListWorkflowDocumentsByProject);(2) 文档生成完成(bizdev);(3) 成员变更后 heal。另测:author 被误判为非在任成员时,healSlot 不得把审核/批准槽位改写为项目默认人;真实离任仍按 R12 阻断写动作且不自动替人。

U4. 动作鉴权、文档状态机与事件

依赖 U3。覆盖 R5、R7、R8、R12,采用 KTD6。

文件:internal/projectinstance/{duty_action,document_access,stage_access,gate}.go、internal/server/{stage_access_helpers,handlers,document_revision_access}.go、internal/app/docflow/、internal/docgov/、相关通知订阅与审计视图。

实现重点:有效三职与在任状态统一判定;三个动作使用不同 action role;归档/修订账本与事件沿用既有事务机制;审核、批准不能跳状态,租约和内容 hash 不因同人而失效。Audit details 增加模式及来源。

测试场景:A顺序三动作成功且三份日志身份真实;其他成员/创建者/管理员越权失败;作者退出后全部写动作拒绝;审核中改正文失败;驳回原因必填;跨标签重复批准只产生一次有效终态事件;审批针对旧版本内容被拒;阶段直到最终批准才可推进。

U5. 系统设置与逐文档 UI

依赖 U1、U2,可与 U3/U4 开发隔离进行,联调必须等待后端完整。覆盖 R1–R4、R7、R9–R11。

文件:web/src/components/admin/console/sections/SettingsSection.tsx、web/src/components/project/ProjectSettingsModal.tsx、web/src/lib/projectSettingsDuties.ts、web/src/types/projectSettings.ts、web/src/api/projectSettings.ts。

实现重点:按 UX Details 配置、错误定位、人数要求、预览和冻结展示;策略 capability 来自项目 settings,而非向普通用户开放 admin settings。文档模式在不同阶段展开折叠后不串行。

测试场景:单成员可配置兼任;混合标准模式仍提示三人要求;非创建者只读;系统开关关闭时禁用及保存失败保留草稿;切换文档、刷新、重新登录后模式不变;已激活项目仍冻结。

U6. 多职责动作展示和真实闭环验收

依赖 U3–U5。覆盖 R5–R8、R11、R12,采用 KTD6。

文件:web/src/lib/{currentDocRole,docGovActionVisibility,controlledDocHydrate,deliverableSync}.ts、web/src/components/doc/DocGovActionBar.tsx、web/src/App.tsx、文档 API/types、相关 UI/PG/真实 PI 测试与报告。

实现重点:消费服务端动作能力,多职责不再被 author-first 短路;认领、提案、修订、按钮与日志一致;受控文档不按名字提权。证明刷新及重启保持一致后再开启真实项目配置。

测试场景:真实产品 PI 生成→A打开文档→送审→审核→批准→版本/日志→阶段门禁;标准和免审批文档并存;不同用户负例;两标签并发、刷新重开、重启;rdev 合入后复验 rd_ 文档及旧键兼容,不改 N/A 行为。


Verification Contract

本方案阶段未运行业务测试,以下为实现阶段必须提交的证据。

层级 覆盖 通过标准
Go 单元 策略值、模式解析、权限矩阵、状态、门禁、hash 所有模式边界及错误路径可重复验证
PostgreSQL 集成 设置审计原子性、并发撤销/激活、成员退出、三职责落库、投影绑定;HealProjectDocuments 三入口对实例绑定 author_only 文档投影不变 实际事务交错结果符合 KTD4;失败不留下半成品;列表 GET/生成/成员变更均不得覆盖冻结 A/A/A
前端单元/构建 单成员配置、双层开关、多职责按钮、错误恢复 测试与构建通过,无同人只见作者按钮
HTTP 负例 修改请求身份、跨项目、非创建者、未知模式、关闭总授权 服务端拒绝,不能依赖隐藏按钮
浏览器 E2E 管理员开关→创建者逐文档设置→A全部动作→其他人被拒 真页面操作、日志可见;无 API 直写替代关键步骤
产品 PI E2E 正式生成及既有修订/租约流程 使用仓库要求的真实产品 PI + MiniMax;stub 仅作前期定位
持久化 刷新、重开、重登、服务重启 模式、职责、审核状态、版本和审计一致
回归 既有 full/none、标准三人分离、freeform、legacy、终止实例 原有权限和生命周期边界不退化

实现时执行 PROJECT 规定的 go vet ./...、go test -short ./...、前端 npm test 与 npm run build,以及使用隔离测试库的 PG 集成和明确启用的真实 PI 测试。不得把 skip 当 pass。共享容器重建验证必须在主仓占 CURRENT 集成槽位后执行;worktree 不启停共享容器。

重点验收样例:

  • AE1(R1–R4):管理员开启后,创建者在文档甲选择 A,在文档乙选择 B;甲/乙有效三职分别为 A/A/A、B/B/B,互不影响。
  • AE2(R5–R8):A只能按状态依次送审、审核、批准;未批准前门禁阻塞;另一个管理员无该文档职责仍被拒。
  • AE3(R6):总开关开启但文档未勾选,A/A/A仍拒绝;三职空仅对原来允许免审批的文档合法。
  • AE4(R10、R11):预览后总开关关闭再打开,旧 token 409;已先完成激活的实例刷新后仍可按冻结策略办理。关闭总开关不得阻断已激活实例的剩余审批动作(非紧急熔断)。
  • AE5(R7、R11):项目成员默认审核人改为 C 后,读取兼任文档仍显示 A/A/A,不改历史签署;列表、正文及按钮一致。
  • AE5a(R7、KTD5):已激活 author_only 文档在仅刷新文档列表(触发 ListWorkflowDocumentsByProject → HealProjectDocuments)后,投影仍为 A/A/A,不被项目默认职责覆盖。
  • AE5b(R7、KTD5):文档生成完成与成员变更后 heal 两入口分别复测 AE5a;author 被误判为非在任时,healSlot 不得把审核/批准槽位改写为项目默认人。
  • AE6(R12):A离任后保持历史名字,但所有新动作拒绝,不能被 heal 自动替换或按名字回退提权。

Definition of Done

  • R9、R10 的生命周期口径经过用户审核(2026-09-17):批准「激活前配置 + 激活后冻结」与「关总开关仅停新配置、存量按冻结继续」;明确总开关不提供存量紧急熔断,该能力如需另立方案。Heal 三入口投影稳定性已升为 U3/Verification 硬性验收项。
  • U1–U6 全部完成且证据覆盖对应需求;管理员和创建者两个权限层级均在服务端生效。(short-term U1–U6 均为 done;U6 报告回链)
  • 配置、快照、assignments、document_records、前端、审计在同一任务身份下对齐。(U2–U4 + U6 闭环证据;规范存储仅 Author + 有效 A/A/A 投影)
  • 单成员兼任完整链与三人标准链均通过;不得只提交设置页截图。(U4 矩阵 + U6 HTTP/浏览器证据;标准分离回归见 U4/U2 单测)
  • PostgreSQL、真实产品 PI、浏览器、重启与跨用户负例分别标明结果及限制;AE5a/AE5b 必须有证据。(U3:TestHealProjectDocuments_SkipsDutyLocked_PG 等 duty_locked 过滤;U6:既有 PI 生成文档 + Playwright 徽标 + lizhuguan 403。限制:U6 未单独跑「刷新/重登/重启」专轮,依赖 schema 持久化与 rebuild 后复测)
  • .doc/test-reports/ 有验收报告并回链任务和 FEATURE-MATRIX;无新增已确认发布 blocker 才保持 gap-matrix 原结论。(U6 报告;变更提案 HTTP 另记 audit,不升为发布 blocker)
  • 发布先迁移与部署识别新模式的服务,再开放总授权;默认 off,试点后扩面。推送、dev集成与环境晋升状态分别报告。(dev 已合入并 rebuild:merge: feature/document-author-only-plan @ 09a9921,health schema_version=52,总开关默认 off。未做:push origin/dev、test/main 晋升、开放总授权试点——需另授)