借款出借人改为从现有员工选择并复用资料(09-17-company-loan-principal-repayment)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

- 新增员工来源预览、关联与显式刷新接口,受 loan.manage 与员工银行卡权限保护;服务端读取并加密保存,客户端不能另传姓名账号
- 同公司同员工唯一复用,请求键绑定来源;锁序出借人→员工,员工使用 FOR NO KEY UPDATE
- 员工关联出借人禁止手工改账号;在途还款期间禁止刷新,刷新推进版本并使旧公司代表授权失效
- 电脑/手机共用对话框,写请求在卸载或身份切换时取消
- 无新增迁移;本地 126 组 HTTP、45 组浏览器、9 个变异通过,两名只读复核及 Claude 独立复核无阻断

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
2026-10-09 21:03:07 +08:00
共同撰写人 Claude Opus 5.5
父节点 c1034bbe38
当前提交 45737ccb9a
共修改 20 个文件,包含 1157 行新增和 28 行删除
@@ -1,3 +1,45 @@
## 2026-10-09 N5 员工出借人选择调整(本地实现与验证完成,未提交)
用户提出从现有员工选择出借人并复用资料,避免重复手录。已只读核对员工主档、敏感银行卡维护接口、借款登记/身份/账户接口及电脑手机共用页面;实现基线为本地 `c1034bbe`,线上仍为 `beb9f02c`。用户已明确确认方案,本轮接续本地实现及针对性验证;不连接生产、不代录真实数据,提交、推送和部署不在本轮授权内。
实施顺序:
1. 增加受现有财务和银行卡权限保护的员工资料预览及关联动作;服务端读取姓名、银行和加密账号,版本、重复及并发检查与审计同事务处理。
2. 把员工出借人入口改为选择与确认,移除该路径重复手录;已有登记复用,缺资料指向原员工维护入口;需要使用更新后的员工资料时显式核对并沿既有在途/版本规则刷新。使用既有组件,不引入新视觉体系。
3. 以合成数据完成 AC28–AC31 的正常与拒绝场景、并发和桌面/手机办理流程;资金守卫做必要的针对性变异,并检查旧付款快照及两人关联审批规则保持。
4. 做任务与相关前后端检查、只读复核,按实际能力报告独立复核状态。完成后汇报本地差异及验证,再按授权提交;推送、生产查询、部署和真实台账写入仍各自批准。新候选发布时重新取得完整门禁,不沿用 `beb9f02c` 回执。
范围限于现有员工资料复用与相关借款入口;不改当前报销待办、回单核验口径或生产批次状态。原非员工入口保留,技术员工不参与审批。优先复用现有表;若需要新迁移或存量合并,先补具体影响与批准,不顺手执行。
### 已实现内容
- 新增员工来源预览、关联和显式刷新服务及三个接口;受财务角色、`loan.manage` 和银行卡权限保护。只返回遮罩摘要;客户端不能另传姓名或账号。服务端读源、核对公司与版本,关联真实员工并加密保存借款侧资料及审计,不创建员工、不生成借款或付款。
- 同公司同员工的唯一匹配登记复用;历史重复、归档、旧入口绕过及预览后来源变化均拒绝。复用和创建都保存当前经办人的请求键绑定,防止同一键跨员工或公司使用。已有出借人先锁出借人,再排序锁员工;员工使用 `FOR NO KEY UPDATE`,兼容审计外键的 `KEY SHARE`。
- 员工资料不一致时要求显式“使用当前员工资料”,有在途占用不能刷新。刷新重验身份/账户/来源版本,同时推进身份与账户版本、留存核对审计并使旧公司代表授权失效;原本金及历史付款快照不改。员工关联记录不能再走手工收款账号 PATCH。
- 电脑、手机共用原组件样式:默认员工选择、公司明确核对、遮罩资料、缺项提示及有权限时的维护入口;非员工登记单列保留。资料查询按身份/员工/公司隔离并可取消;两个新写请求在卸载或切换身份时取消,避免迟到 401 以新账号重发。此保护不宣称已覆盖所有旧页面写请求。
- 本轮无新增迁移,仍为 82 项。旧测试为同一员工反复建立同公司出借人,现改为每个独立场景使用独立的合成公司;原业务断言保留。测试错误包装改为正式服务的 `requestId/error` 结构,保留原拒绝断言并验证实际页面错误提示。
### 独立只读复核与修复
本次复用了财务与界面两名只读复核代理,均不改文件、不重跑测试、不连接生产;本轮结论不借用 N3 的历史复核。两者接收修复与专项回执后均为 **REVIEWED_NO_BLOCKER**。
| 发现 | 修复及见证 |
| --- | --- |
| 财务 P2:复用未绑定请求键,旧键可能用于另一个员工 | 创建/复用的审计均保存来源及请求键,按经办人串行;顺序、并发与移除绑定的反例通过。 |
| 财务 P2:员工 `FOR UPDATE` 与审计员工外键形成锁循环 | 改为 `FOR NO KEY UPDATE`;实际 HTTP 关联和刷新经数据库 gate 确定性交错,两请求均完成;恢复旧锁时观测 PostgreSQL 死锁计数增长。 |
| 界面 P1:仅隔离回调不能阻止旧 POST 在切换身份后因 401 被重发 | 两个写动作透传并在卸载/身份变化时终止 `AbortSignal`;同一浏览器文档中真实退出/登录另一财务,延迟旧 401,验证取消、无重发、无错误写入/审计,同时验证同身份自动刷新仍成功。 |
### 验证回执
证据根目录:`artifacts/qa-flow/loan-employee-source-20261009/`,均为本地合成数据。
- `mutations-r6.log`:82 迁移、10 组员工 HTTP、9 个针对性变异、资源清理全部 PASS。变异覆盖银行卡权限、来源版本、旧身份重复入口、员工串行锁、外键锁兼容、在途占用、出借人版本、复用请求键及必要审计;普通超时或环境失败不能算捕获。
- `browser-r3.log`:10 组员工 HTTP 和 8 组电脑/手机浏览器场景 PASS,包括历史借入、余额核对、财务登记授权及指定经理确认;关联/刷新同身份 401 恢复、跨身份迟到请求取消均实际执行。截图在 `browser-LWICsl/`;横向溢出检查和主会话截图走查通过。
- `unit-r1.log`:本轮针对授权策略和错误消息合同的 2 文件、948 项通过;其输入未改变,后续复用。`frontend-build-r5.log` 的类型检查及构建、Prisma 校验、错误码合同、UI 规则和差异检查通过。未运行本次服务端全量或完整发布门禁。
- 完整借款 HTTP/浏览器回归:`regression-r2.log`、`regression-r2-process.json` 和去重汇总 `regression-r2-summary.json` 为 PASS,退出 0;82 迁移、原有 116 组 HTTP 加新增 10 组(共 126 组)、45 组浏览器、9 组基础数据库检查及资源清理通过。45 组已包含关联模式的 18 组和新入口的 8 组,不重复累加。首轮收到 SIGTERM(退出 143),没有最终回执,不能算通过;信号来源未证实,原日志和 `regression-r1-interruption.json` 保留,已按 owner 标签核对并只清理该轮隔离容器/临时目录。第二轮使用同一命令和断言在独立进程执行,不缩小范围、不增加用例重试。
- 较早失败记录保留:首轮账号解密返回空值的分类问题已修;前两轮浏览器分别暴露选择框可访问名称和测试错误包装问题,已修并完整重跑专项;`mutations-r3`–`r5` 的合成交错类型/顺序及捕获分类未通过,不计入通过次数,最终以 r6 为准。
AC28–AC31 的本地实现及验收已完成,最终文档治理结果见本目录 `final-checks.json`。文档索引保留既有 22 份未登记文件的警告,无新增错误,不在本轮整理无关文档。N5 真实台账/公司授权登记和 N6 首笔真实还款仍待办理,整体任务保持 `in_progress`;没有提交、推送、部署、访问生产、调用真实 OCR 或代录真实资料。线上仍为 `beb9f02c`;新候选以后发布须重新跑完整门禁。
## 2026-10-09 N4 发布结果与 N5/N6 接续
本节记录已完成的发布,候选为 `beb9f02c19970aa452c3fac02debfb10db0d4a3d`。Claude 会话执行发布及核对、由用户转交结果;主会话另核对本地候选、只读汇总、部署与补验日志、独立复核记录及生产 PDF 冒烟回执。本轮只更新现有任务文档,没有重新连接生产、执行付款或改动程序;整体任务仍为 `in_progress`。