chore(08-05-contract-detail-workspace): 归档任务

这个提交包含在:
2026-08-08 02:04:33 +08:00
父节点 21851774dd
当前提交 d50bcbb0e6
共修改 6 个文件,包含 4 行新增和 4 行删除
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
@@ -0,0 +1,133 @@
# 设计说明
## 1. 总体结构
合同任务分为四个同批兼容层:
1. Prisma 增量字段与关系。
2. 合同详情/终止/历史 API 与事务审计。
3. 合同列表、详情、新建/编辑和响应式动作 UI。
4. 状态机、权限、迁移和端到端验证。
本任务不建设合同附件库。证据区只消费现有台账字段和 `ConfidentialDocumentRef` 的最小摘要。
## 2. 数据模型
在 `ContractRegistry` 增加:
```prisma
terminated_at DateTime?
terminated_reason String? @db.VarChar(1000)
terminated_by String? @db.Uuid
terminator Employee? @relation("ContractRegistryTerminator", fields: [terminated_by], references: [id], onDelete: Restrict)
```
在 `Employee` 增加反向关系 `terminated_contract_registries`。
迁移只增加三个可空列、外键和必要索引,不回填历史行,不修改 `status` 列类型。`terminated_reason` 请求 trim 后长度 10–1000。
数据库暂不增加跨列 CHECK;服务层与测试强制:
```text
status = terminated <=> terminated_at/reason/by 全部非空
status != terminated <=> terminated_at/reason/by 全部为空
```
`terminated` 是终态,本轮不允许恢复、续约或再归档,避免单一状态列丢失终止事实。
## 3. 状态值域与写入边界
- `CONTRACT_REGISTRY_PERSISTED_STATUS_VALUES` 增加 `terminated`,筛选和派生状态自动识别。
- `resolveContractRegistryEffectiveStatus` 继续只对持久状态 `active` 派生 `expired`;terminated 天然不被覆盖。
- 到期提醒继续硬过滤 `active`,无需特殊排除逻辑,但增加回归断言。
- 不把通用 create/PATCH schema 直接开放为可写 `terminated`。新增一般写状态集合 `draft/active/archived`,终止只能走专用接口,防止绕过三字段不变量。
- 通用 PATCH 对 `terminated` 和 `archived` 主记录执行状态锁:terminated 不可编辑;archived 普通字段不可覆盖。
## 4. API 合同
### 4.1 详情
`GET /api/contracts-registry/:id`
- 使用与列表相同的数据范围条件查询,未授权与不存在统一安全 404。
- 返回合同摘要、owner、project、terminator、三个终止字段、最小涉密资料索引和白名单操作历史。
- `ConfidentialDocumentRef` 不返回完整 `storage_path`、access rule raw JSON 或其他敏感原文;只返回 ID、标题、资料编号、敏感级别、存储类型、离线档案号、责任人和时间等必要摘要。
- 历史从 `AuditLog` 按 `target_type=contract_registry + target_id` 查询,只映射允许展示的 action、actor、time 和安全摘要,不直出 raw `extra`。
### 4.2 终止
`POST /api/contracts-registry/:id/terminate`
请求:`{ reason: string }`,trim 后 10–1000 字。
- 仅当前合同管理权限可调用。
- 只允许持久状态 `active`(包含页面派生 expired);draft 应删除/取消拟办,archived 与 terminated 拒绝。
- 在一个 Prisma transaction 中锁定/读取当前行、校验状态、写 `status + terminated_*`、创建 `CONTRACT_REGISTRY_TERMINATED` 审计。
- 审计创建失败时整个事务回滚;不调用现有会吞错的 best-effort helper。
- 审计 extra 只记录合同编号、from/to 状态和必要原因摘要,不写合同正文或原始 payload。
### 4.3 归档、恢复与修正
- 现有归档/恢复 UI 迁入详情。服务端至少阻止 archived 普通 PATCH 和 terminated 的任何一般状态写入。
- 归档/恢复属于状态变更,改为事务内 required audit;不得状态成功而审计失败。
- 归档后修正使用追加式 correction 记录,不覆盖主合同普通字段。可复用 `AuditLog` 新 action 与白名单修正 payload;详情把它显示为追加历史。
- 续约保持 active/expired → 新 draft + 原合同 archived,并继续事务内审计。
## 5. 前端信息架构
### 5.1 路由与页面
- 列表:`/contracts-registry`
- 详情:`/contracts-registry/:contractId`
- 新建可使用独立 `/contracts-registry/new` 或明确 Dialog;实施时优先选择复用现有表单且 dirty guard 最清晰的独立新建工作区。
- 编辑在详情工作区展开或进入明确编辑态,不再使列表页面整体变形。
### 5.2 信息顺序
1. 状态与下一步。
2. 业务摘要:编号、类型、相对方、金额、日期、负责人、敏感级别。
3. 证据区:归档位置、离线档案号、涉密资料索引;显示“涉密资料请登记线下归档位置”。
4. 变更/操作历史。
5. 动作面板:PC 右侧,窄屏/移动底部安全区,复用低风险子任务的共享动作容器。
不渲染空附件模块,不在列表增加附件完整性列。版式分区保持可扩展,但不显示六类空占位。
## 6. 动作矩阵
| 状态 | 编辑 | 续约 | 归档 | 恢复 | 终止 | 修正追加 |
| --- | --- | --- | --- | --- | --- | --- |
| draft | 允许 | 禁止 | 按现有规则 | - | 禁止 | 禁止 |
| active / expired | 允许 | 允许 | 允许 | - | 允许 | 禁止 |
| archived | 禁止覆盖 | 禁止 | - | 允许 | 禁止 | 授权角色允许 |
| terminated | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 | 只读 |
终止面板始终显示至少 10 字要求;不足时按钮禁用且邻近显示原因。确认弹窗展示合同编号、相对方、金额以及“合同将标记已终止、编号不释放、普通编辑/续约不可用”的后果。
## 7. 跨模块与权限
- 本轮详情只稳定展示已有 project 关联并跳转项目详情。
- 采购/付款没有现成合同外键或可靠查询时不显示空模块,不为页面完整性新增错误关联。
- 合同审批和付款写动作不进入详情;未来只显示授权摘要与归属模块入口。
- 所有详情数据由服务端范围查询裁剪,前端隐藏不替代权限。
## 8. 迁移、发布与回滚
- 本地:先 `prisma:validate`,生成 client,运行聚焦 route 测试和迁移状态只读检查;不得 reset 数据库。
- migration 是向后兼容的可空列。部署新 schema 后、首次产生 terminated 行前,旧应用可暂时忽略新列;不主动 drop。
- 一旦生产产生 terminated 行,旧应用不认识该状态且无法展示终止事实,应用回滚应以 roll-forward 或兼容 hotfix 为主,不能简单回到旧客户端/服务端。
- drop 三列会保留审计但使 terminated 行与字段不变量失配,因此不作为自动回滚。任何生产 schema drop、状态翻译或数据修复都需另行批准。
- 部署后显式运行 migration status,并验证 `/ready`、合同列表/详情、终止负向路径和权限;init 日志不能替代迁移状态证据。
## 9. 只读 Review
实施后 reviewer 只读检查:
- terminated 与三字段全有/全空不变量。
- 通用 create/PATCH 无法绕过专用终止接口。
- audit failure 能回滚状态写入。
- expired/expiring/renew 行为未误含 terminated。
- `terminated_by` Restrict 外键和 migration 兼容。
- 详情 403/404、document refs 和 history 不泄露敏感字段。
- archived 锁定与修正追加不覆盖主记录。
reviewer 不修改代码,发现问题由主会话修复后再复查。
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
@@ -0,0 +1,75 @@
# 实施计划
## 1. Schema 与迁移
- [x] 在 `ContractRegistry` 增加 `terminated_at/reason/by`、terminator 关系,在 `Employee` 增加反向关系。
- [x] `terminated_reason` 限制 1000,`terminated_by` 使用 `onDelete: Restrict`;按查询需要添加索引。
- [x] 生成纯增量 migration,检查只有可空列、外键/索引,无历史回填、drop 或状态改写。
- [x] 运行 `cd server && npm run prisma:format && npm run prisma:validate && npm run prisma:generate`。
## 2. 状态与服务端不变量
- [x] 持久/筛选状态加入 `terminated`,一般 create/PATCH 可写状态仍排除 terminated。
- [x] 增加 terminated 筛选、effective status、expiring 排除和 renew 拒绝测试。
- [x] 增加详情 GET,按列表相同范围查询 owner/project/terminator/document refs,并投影安全 history。
- [x] 增加专用 terminate schema 和接口,reason trim 后 10–1000。
- [x] 终止 transaction 原子写三字段、status 和 required audit;模拟 audit failure 证明全回滚。
- [x] 阻止 archived/terminated 普通字段覆盖与终止绕过;导入脚本也拒绝终止状态和覆盖既有终止合同。
- [x] 归档/恢复改为 required audit;实现归档后追加修正记录,不覆盖主合同;修正使用 `updated_at` 乐观保护。
- [x] 保持续约 active/expired 语义和事务审计,并覆盖续约审计失败回滚。
## 3. 客户端 API 与状态映射
- [x] 客户端合同类型加入 `terminated` 与三个终止字段、terminator、document refs、history DTO。
- [x] `contractStatusLabel` 增加“已终止”,未知兜底为“未知状态”而非原值。
- [x] 增加 fetch detail、terminate、correction 等必要 API 函数,不暴露 raw audit/document path。
## 4. 列表、详情和表单
- [x] 合同列表移除内联 editor,仅保留筛选、提醒、导出、状态和查看详情。
- [x] 新建合同详情路由和页面元数据,权限 guard 与现有列表一致。
- [x] 建设状态/下一步、摘要、证据区、历史和动作面板;窄屏复用共享底部动作容器,并隐藏 PC 管理动作。
- [x] 证据区展示归档位置、离线档案号、涉密资料索引和强制引导文案;不显示空附件区或附件完整性列。
- [x] 迁移编辑、续约、归档/恢复;按动作矩阵隐藏或禁用。
- [x] 终止输入持续显示至少 10 字要求;禁用时显示原因;确认包含合同编号、相对方、金额和后果。
- [x] 归档后只提供授权修正追加入口,不覆盖普通字段。
- [x] 只展示真实 project 摘要与跳转;采购/付款无稳定关联时不渲染。
## 5. 后端与迁移验证
- [x] `cd server && node --check src/routes/contractsRegistry.js`(并检查 `src/scripts/import-project-ledgers.js`)。
- [x] `cd server && npm test -- tests/unit/routes/contractsRegistry.test.js tests/unit/routes/exports.contractsRegistry.test.js tests/unit/scripts/import-project-ledgers.test.js --run`:25 passed。
- [x] `cd server && npm run prisma:validate`。
- [x] `cd server && npx prisma migrate status`(只读;不得未经批准 deploy/reset):65 migrations,`Database schema is up to date!`。
- [x] 检查生成 migration SQL 和既有数据兼容,记录应用回滚前/后首次终止写入的不同边界。
## 6. 前端与交互验证
- [x] `cd client && npm run typecheck`。
- [x] `cd client && npm run build`。
- [x] 增加合同详情聚焦 Playwright:列表进入、深链刷新、无权限/不存在、dirty guard、涉密引导、无附件区。
- [x] 覆盖终止原因不足、确认摘要、成功状态、重复终止、审计失败和窄屏动作安全区;合同详情 + Wave3 共 12 passed。
- [x] 覆盖归档锁定、修正追加、恢复、续约和未知状态兜底。
## 7. 只读 Review 与治理
- [x] 实施完成后启动只读 reviewer,按 design 第 9 节逐项审查,明确 reviewer 不改代码;首轮 finding 已记录并修复。
- [x] 主会话修复 finding 后重新运行聚焦测试并请求只读复查;最终结论 `PASS`。
- [x] 运行 task validate、process contract、docs registry、Trellis governance、敏感内容检查和 `git diff --check`。
- [x] 将终态字段、required audit、导入写路径和修正乐观保护沉淀到 `.trellis/spec/hyb-oa/backend-fastify-prisma.md`,不新建平行文档。
## 8. 提交、部署与回滚
- [x] 使用中文 commit message 并引用 `08-05-contract-detail-workspace`。
- [ ] 本地实现提交不等于批准生产 migration 或部署。
- [ ] 生产发布另行获批后,显式验证 migration status、`/ready`、合同详情和权限负向路径。
- [ ] 首次生产终止写入前保留应用回滚窗口;产生 terminated 行后优先 roll-forward,不自动 drop 列或回退到不识别 terminated 的旧应用。
## 实施证据与边界(2026-08-07)
- migration SQL 为三个可空列、一个 `Restrict` 外键和索引;未执行生产 migration、reset、db push、resolve 或手工 DDL。
- 只读迁移原始结论:`Datasource=hyb_oa_regression at localhost:5432`;`65 migrations found`;`Database schema is up to date!`。
- 合同聚焦后端 25/25 passed;合同详情与受影响 Wave3 Playwright 12/12 passed;client typecheck/build、Prisma validate、node syntax、task/process/governance/sensitive/flow/route-manifest gates 均通过。
- 仓库全量 Vitest 结果为 179 个文件(177 passed、2 failed)、1248 个测试(1245 passed、3 failed);失败仅为既有付款批次/BIFF8 模板环境问题(`paymentBatches.reimbursement.test.js` 1 条、`paymentOrderXls.test.js` 2 条),不属于本合同任务改动,未通过改页面或数据库掩盖。
- 本地 `127.0.0.1:3000/ready` 返回 200;企业微信真机、生产/公网部署仍未验证,不能据此宣称用户可测试。
- 首轮只读 reviewer 结论为 `PASS_WITH_FINDINGS`;主会话修复并补测后,最终只读复查结论为 `PASS`,reviewer 未修改代码、未写数据库。
@@ -0,0 +1,125 @@
# 合同详情页与高风险动作归位
## Goal
独立建设符合“列表查找、详情处理”的合同工作区,明确合同详情的信息顺序、权限边界、证据表达、终止状态和高风险动作位置;不把从零新增详情能力混入采购/资产的路由搬迁。
## Background
- 当前 `ContractsRegistryPage` 是“列表 + 内联新建/编辑器”,只有 `showEditor/editorId`,没有 selected ID、`?id=` 详情或独立详情态。
- 当前客户端只有合同列表查询、创建、PATCH、续约和台账导出;服务端没有单条详情 GET。
- 当前持久状态只有 `draft/active/archived`,`expired` 是按到期日推导的展示状态;Prisma `status` 为 `VarChar(32)`,新增 `terminated` 本身无需改列类型或回填历史状态。
- 当前合同审计为 best-effort:写入失败只记录服务日志而不阻断业务。终止属于高风险状态变更,原因和审计不得沿用该失败策略。
- 合同可关联项目;`ConfidentialDocumentRef` 可关联合同,但它是涉密资料索引,不是正文文件库。
- `docs/需求-合同附件归档规约.md` 已规划非涉密附件受控入库,并把它列为详情页之后的独立开发步骤。本轮不做附件能力是范围裁剪,不是永久产品边界。
## Scope
- 合同列表改为纯查找入口,详情承担状态、摘要、证据、历史和动作面板。
- 证据区本轮只承载归档位置、离线档案号和涉密资料索引;非涉密附件能力按 `docs/需求-合同附件归档规约.md` 第 13 节第 4 项另建 task。
- 增加 `terminated` 及 `terminated_at / terminated_reason / terminated_by` 三列,终止原因至少 10 个字,状态/终止字段/审计事务一致提交。
- 迁移、状态机、权限和审计变更实施后必须完成只读 reviewer;生产 migration 和部署另行获批。
## Requirements
### R1 页面与信息结构
- 合同列表只负责查找、筛选、状态摘要、到期/续签提醒、台账导出和进入详情;现有内联新建/编辑器随详情工作区落地移除。
- 合同详情信息顺序固定为:`状态与下一步 → 业务摘要 → 证据区 → 变更/操作历史 → 动作面板`。
- PC 动作面板位于详情右侧;移动端如本轮提供详情表达,只保留查看和底部安全区轻动作,不复制 PC 管理能力。
- 建立稳定合同详情路由、单条 GET 合同和客户端 detail query;服务端沿用当前合同范围权限,不扩大普通用户可见范围。
### R2 证据区本轮范围裁剪
- 本轮证据区只展示:归档位置 `archive_location`、离线档案号 `offline_archive_no`、涉密资料索引 `ConfidentialDocumentRef`。
- 必须显示业务引导:“涉密资料请登记线下归档位置”,解释 `archive_location` 非空必填的原因。
- 版式为后续附件类型分区预留扩展位置,但本轮不渲染空附件区,也不在列表显示“附件完整性”列。
- 本轮不新增合同正文或非涉密附件的上传、预览、下载与附件审计;该能力按 `docs/需求-合同附件归档规约.md` 第 13 节第 4 项另建 Trellis task。
- 不得把“不在本轮上传合同文件”写成永久产品边界。
### R3 状态模型
- 本轮状态值域为 `draft / active / terminated / archived / expired`,其中 `expired` 继续由日期推导,`terminated` 为新增持久状态,用户文案为“已终止”。
- “作废”不新增另一状态;已编号或已生效合同不再执行时统一进入“已终止”,合同编号不得释放或复用。
- `terminated` 采用专用字段 `terminated_at / terminated_reason / terminated_by`;终止原因 trim 后至少 10 个字,三项在详情状态区可直接读取。
- 状态不变量固定为:`status = terminated` 当且仅当三个终止字段均非空;其他状态三个字段均为空。服务层在事务内强制该不变量。
- `terminated_by` 关联员工并使用 `onDelete: Restrict`,终止人不得因员工记录变化丢失。
- 已签署、履行中、已完成等状态后置;真实使用证明现有字段不足时另建 task。
- 归档后普通字段锁定;授权修正只能追加变更记录,不覆盖历史事实。
### R4 动作矩阵
- 编辑:常规动作,按当前管理权限和状态开放。
- 续约:常规动作,只在既有允许状态开放,沿用新草稿 + 原合同归档语义。
- 归档/恢复:状态动作;归档后锁定普通字段,恢复及修正必须留痕。
- 终止:高风险动作;原因至少 10 个字,输入区持续显示要求,按钮禁用时明确显示“请填写终止原因,至少 10 个字”;二次确认展示合同编号、相对方、金额和后果,状态写入、三个终止字段与审计必须同一事务成功。
- 本轮不在合同详情放审批通过、驳回、退回或转审;如后续启用合同审批,只展示状态和进入统一审批中心的入口。
- 本轮不在合同详情放付款写动作;只展示授权付款摘要和“查看付款”入口。
- 台账导出继续属于列表筛选范围动作,不变成单条合同“下载”。
### R5 关联、历史与权限
- 跨模块只做“摘要 + 跳转”:项目、采购和付款只展示当前 API/关联模型能证明且当前用户有权查看的摘要;无稳定关联字段时不虚构数据。
- 详情展示合同创建、编辑、状态变化、归档/恢复、续约、终止和归档后修正历史;高风险写操作不得因审计失败而静默成功。
- 普通用户无权访问时不泄露合同是否存在;管理员和授权角色仍受服务端范围约束。
- 深链、刷新、返回、无权限、不存在和 dirty-form 离开均有可解释结果。
### R6 数据迁移、审查与发布
- 新增三个可空字段和 `terminated_by` Restrict 外键的 Prisma migration;历史合同不回填终止事实,新增列允许空值,仅终止接口可原子写入完整三项。
- migration 必须经过 `prisma:validate`、聚焦路由/服务测试、迁移状态检查及既有数据兼容验证;禁止用数据库重置代替迁移。
- 实施完成后启动只读 reviewer,重点检查状态机、权限、事务审计、迁移兼容和隐私;reviewer 不修改代码。
- 生产部署需另行明确批准;部署后必须显式验证 migration 状态、`/ready`、合同列表/详情和权限负向路径,不能只依赖 runbook 或 init 成功日志;失败时停止并按设计回滚。
- migration 为纯增量可空列;代码回滚前如已产生终止记录,先保留审计追溯并评估字段信息损失,再决定是否 drop 三列,不自动执行破坏性 schema 回滚。
## Acceptance Criteria
- [x] 合同列表不再承载记录编辑器,只保留查找、筛选、提醒、导出和进入详情。
- [x] 合同详情具有稳定深链,并按“状态与下一步、业务摘要、证据区、历史、动作面板”展示。
- [x] 证据区展示归档位置、离线档案号和涉密资料索引,并出现“涉密资料请登记线下归档位置”;不渲染空附件区或列表附件完整性列。
- [x] 本轮没有新增合同正文/非涉密附件上传、预览或下载;PRD 明确其为后续独立能力而非永久禁止。
- [x] 状态值域支持 `terminated`;终止原因至少 10 个字,操作者和时间可在详情直接读取,合同编号不释放。
- [x] 服务层与聚焦测试证明 `terminated` 与三个终止字段满足全有或全空不变量,`terminated_by` 使用 Restrict 外键。
- [x] 终止原因不足 10 字时界面邻近显示禁用原因;满足要求后,确认展示合同编号、相对方、金额和后果,状态、三字段与审计同事务成功或共同失败。
- [x] 归档后普通字段锁定;授权修正追加记录,不覆盖原历史。
- [x] 编辑、续约、归档/恢复按权限和状态显示;审批类与付款类写动作不进入合同详情。
- [x] 项目/采购/付款只做有权限且有真实数据来源的摘要与跳转,不复制对方流程。
- [x] 无权限详情请求不泄露合同事实;不存在、深链刷新、返回和 dirty-form 行为可解释。
- [x] 如包含 migration,Prisma 校验、迁移兼容、聚焦后端测试、前端 Playwright、typecheck/build 和 Trellis 门禁通过。
- [x] 只读 reviewer 完成状态机、权限、事务审计、迁移与隐私审查,且未修改代码。
## Out of Scope
- 本轮不做非涉密附件上传、预览、下载或附件审计;按合同附件归档规约第 13 节第 4 项另建 task。
- 不接入合同审批;如需要按规约第 7 节另建 task 接入统一审批中心。
- 不做电子签章、法务审查、条款库、版本协同或完整 CLM。
- 不新增已签署、履行中、已完成等尚缺事实字段支撑的状态。
- 不复制采购、资产、付款或项目完整流程。
- 不写入生产合同正文、真实附件、完整归档路径或真实业务数据。
## Accepted Risk
- “已终止”是不可逆终态,本轮不提供恢复、续约、再归档或终止后的追加说明/更正入口,已提交的终止原因也不可编辑。必填至少 10 个字的原因、合同编号/相对方/金额/后果确认和事务审计用于降低误操作与漏写风险;若后续出现真实误终止或补充说明需求,另建 task 评估受控管理员修正路径,或只追加且必审计的补充说明入口。
## Open Questions
- 无;需求范围与终止持久化方案均已确认。
## Test Plan
- `cd server && npm run prisma:format && npm run prisma:validate && npm run prisma:generate`
- `cd server && node --check src/routes/contractsRegistry.js`
- `cd server && node --check src/scripts/import-project-ledgers.js`
- `cd server && npm test -- tests/unit/routes/contractsRegistry.test.js tests/unit/routes/exports.contractsRegistry.test.js tests/unit/scripts/import-project-ledgers.test.js --run`
- `cd server && npx prisma migrate status`(只读;不得用 reset 或未经批准 deploy)。
- `cd client && npm run typecheck && npm run build`
- 聚焦 Playwright 覆盖合同列表/详情、证据引导、终止原因禁用提示、确认摘要、状态成功/重复终止、归档锁定、权限负向和窄屏动作。
- 实施后启动只读 reviewer,检查状态不变量、专用终止接口、事务审计失败回滚、`terminated` 不参与过期/续约、Restrict 外键、迁移兼容和敏感字段裁剪。
- 运行 task validate、process contract、docs registry、Trellis governance、敏感内容检查和 `git diff --check`。
## Evidence Notes
- 2026-08-07 本地只读迁移状态:`hyb_oa_regression` at `localhost:5432`,65 migrations,`Database schema is up to date!`;未执行生产 migration、reset、db push、resolve 或手工 DDL。
- 聚焦后端 25/25 passed,合同详情与 Wave3 Playwright 12/12 passed,client typecheck/build、Prisma validate、node syntax 与治理门禁通过。
- 仓库全量 Vitest 179 files(177 passed、2 failed)/ 1248 tests(1245 passed、3 failed)中有 3 条既有付款批次/BIFF8 模板环境失败;本任务不改动该路径,也不把全量结果写成全绿。
- 只读 reviewer 首轮 finding 已修复并补测,最终复查结论为 `PASS`;reviewer 未修改代码、未写数据库。企业微信真机、生产/公网仍未验证。
@@ -0,0 +1,28 @@
{
"id": "contract-detail-workspace",
"name": "contract-detail-workspace",
"title": "合同详情页与高风险动作归位",
"description": "独立规划合同详情信息结构、权限边界、证据区和高风险动作归位,不与采购/资产路由搬迁混做。",
"status": "completed",
"dev_type": null,
"scope": "server-contract-schema-api-and-client-detail",
"package": null,
"priority": "P2",
"creator": "shunli",
"assignee": "shunli",
"createdAt": "2026-08-05",
"completedAt": "2026-08-08",
"branch": null,
"base_branch": "main",
"worktree_path": null,
"commit": "2185177",
"pr_url": null,
"subtasks": [],
"children": [],
"parent": "08-05-product-interaction-consistency",
"relatedFiles": [],
"notes": "",
"meta": {
"description": "建设合同详情工作区并新增可审计的 terminated 状态、终止字段和事务审计,范围裁剪附件能力。"
}
}