## 2026-10-05 复核阻断 B1 修复与回单归属复现(用户批准 A/B/D/恢复手册 + C 复现调研;本地合成,未提交、未部署) 背景:同模型只读复核(页面与剩余资金流程)结论 BLOCK:在途还款期间做出借人身份/账户维护会使 identity_version 变化,之后登记付款、取消、确认失败全部被拒,已付款项永久无法登记;导出后原审批人或出借员工离职同样卡死。另报回单批次归属未校验。 实施: - A(`services/companyLoans.js` `assertLenderNotInFlight`,`routes/companyLoans.js` 两个维护接口):出借人锁内只要存在 `reserved` 分配即 409 `loan.lender_in_flight`。新建还款先锁出借人再占用,故与维护互斥;导出/上传不新增占用,不需改上传锁。出借人列表新增 `hasInFlightRepayment`,页面禁用两按钮并提示;账户弹窗误导文案已改。原因码已登记三处(server registry、client 映射、内容断言夹具)。 - B(`services/companyLoanPayments.js` `postPayment`):回单 OCR 认领、人工回单参与人、核销三处按审批时资格认定——不再复核原审批人当前在职/角色、出借员工当前在职及主数据启用;仍校验身份已核实、身份/账户版本与提交时一致、付款快照收款资料一致、`reviewed_by/reviewed_at` 存在且审批人不是制单人/提交人/出借人关联员工(这三者之间可重合)。审批时资格依据:复核路由当时已用 `activeReviewer` 校验当前角色后写入 `reviewed_by/reviewed_at`。新建、复核、导出制单、确认银行失败保持当前资格校验;当前操作人仍须有当前权限与独立性。 - D:`scripts/qa/company-loan-http-fixture.cjs` 原“在途改身份/改账户”两段按新规则重写(改用新出借人,原出借人因负例循环留有 unknown 占用、按设计不可维护),新增:在途(导出前后)维护被拒、取消/结清后可维护;维护与新建并发 3 轮不留陈旧版本占用;导出后原审批人与出借员工离职,经 OCR 与经人工复核两条路径均从上传回单走到核销成功;付款前导出仍要求审批人当前有资格。浏览器脚本新增 PC/手机在途时两按钮禁用。 - 恢复手册:`docs/trialrun/OPS7运维交接Runbook.md` §5 增加资金类数据恢复后先暂停付款、对照银行流水补齐、核对余额与在途占用再开放。 验证(Docker 隔离 PostgreSQL,`--network none`,合成数据;需 `PAYMENT_ORDER_PYTHON_BIN` 指向 BIFF8 venv): - `RUN_ISOLATED_LOAN_DB_TEST=1 RUN_ISOLATED_LOAN_BROWSER=1 node scripts/qa/test-company-loan-db.cjs`:73 迁移、9 组 DB 约束、HTTP 21 组、浏览器 5 组全部 PASS,清理 PASS。 - 4 个源码变异(OCR/核销/人工复核改回当前资格、去掉在途拦截)均使测试变红,源码已恢复并逐字比对。 - server `npm test` 226 文件 4452 通过;`prisma:validate`、client `typecheck`/`build`、UI strict、错误码合同、文档审计(0 error)、敏感扫描、`git diff --check` 通过。 - 未覆盖:独立复核仍为同模型;真实银行/OCR 样本;生产存量(待核实)。 C 复现结果(合成全流程,测试只记录结果不设守卫): - 同一出借人两笔 7.00 在途,P 的成功回单传到 Q:`matched`,Q 执行 200 核销成功——**错误核销成立**。 - 旧 6.00 批次确认失败并取消后新建同额批次,旧批次晚到的成功回单传到新批次:`matched`,执行 200 核销成功——**错误核销成立**。 - 调研:BIFF8 制单每行已有唯一客户流水号 `批次号-R00n`;借款附言固定为“归还借款本金”(报销附言含单号);OCR 只提取金额、币种、双方账号、状态和银行流水号,不提取客户流水号/附言;建行回单是否保留二者无仓库证据,需获准的真实回单样本确认。修法待用户确认,未实施。 同模型只读复核(同日,独立上下文):本轮 A、B 修复范围 PASS_WITH_NOTES,无阻断;**借款功能整体尚未通过完整验收**(C 错误核销已复现,仍阻断真实还款)。A 互斥成立(reserved 只经 `prepareLoanRepayment` 在出借人锁后创建;幂等重放不新建;迁移触发器禁止 settled/released 回退);B 未放宽过头(`reviewed_by` 全仓唯一写入点在复核路由且已过 `activeReviewer`;出借人无归档写入;停用主数据不降低伪造回单门槛)。按其第 4、5 条补强: - 并发测试改为确定性交错:独立连接持出借人行锁,两请求按指定顺序排队后释放;新建在先 → 维护 409 `loan.lender_in_flight`,维护在先 → 两者 200 且新建采用新版本;两种顺序均无陈旧占用。“检查挪到加锁前”变异确定性变红。 - 付款后独立性反例:把已匹配回单批次的 `reviewed_by` 改为制单人或出借员工后执行均 403,恢复后正常核销;“去掉 `assertApprovedIndependently`”变异变红。 复核另记残余(未处理,计入下列阻塞):人工回单复核人在复核后、执行前离职会使执行被拒(与报销共用,推测可作废重传绕过,未验证);确认银行失败路径在出借员工离职后仍卡死,叠加 A 会长期冻结该出借人维护;付款后关闭提交人部门的付款批次灰度开关会拦执行(重新打开即可恢复)。 仍阻止真实还款验收:C 修复;unknown 状态人工解除、作废附件计数、晚到结果对账流程;B 未覆盖确认银行失败路径在出借员工离职后的卡死;AC5 真实样本;独立复核。 ## 2026-09-18 共享付款回归与交接补充 09-06本地受管重验已覆盖报销主管/财务审批、财务同页进度、批次独立复核、回单人工更正/独立复核、付款核销及AP/票据归档两条主链;完整r6为3通过/1入口矩阵失败,矩阵另在r7通过。此证据支持共享付款旧来源回归,不代替本task真实银行样本、独立资金链审阅或公网验收。当前官方current在09-06,本task仍in_progress;上批review-candidate-r1保护保持。独立问题及真实批次/银行/K1/K2清单见retained-gates-closeout-20260917的independent-and-external-readiness.json,均未进行真实查询或操作。 ## 2026-09-17 最终本地回执(当前入口) T1–T4本地实现与合成闭环完成,官方current保持本task,状态in_progress。证据根为`artifacts/qa-layout/payment-feedback-loan-slim-20260917`;最终`final-loan-browser`退出0:空库72迁移、9组真实PostgreSQL约束/两连接并发、16组正式登录Fastify/Prisma/PG HTTP场景、3组桌面/手机/员工拒绝浏览器检查全部通过;仅本轮容器/浏览器/服务/临时目录清理PASS。最终桌面、手机截图已查看,沿原有样式且银行字段脱敏;手机详情仍在移动入口。 报销原地进度`progress-green-r2`15/15;`loan-unit-r3`5文件212/212,ERP退出后的付款路由另在`erp-regression-r2`128/128通过。`final-client-build`typecheck/Vite/PWA、`final-prisma`、`final-module-load`通过。ERP共享回归按r1/r2已通过文件及r3修正后的63/63分别引用,不将分轮结果相加当全量。strict原因码850注册/886使用/legacy0/findings=[]。旧Browserslist/punycode提示和22个历史未登记文档不扩治。 ### 验收支持与开放项 | 验收 | 当前证据与结论 | | --- | --- | | AC1 | 正式财务登录、历史两笔借入、凭据唯一、四类材料、余额确认及系统外已还证据通过。 | | AC2 | 两借款一付款、部分还本、精确金额、跨来源限制、超额拒绝、两连接占用和同requestKey并发幂等通过。 | | AC3 | 显式财务权限、经理/CEO独立审批、排制单/提交/收款人、无人可批与身份/账户版本变动拒绝通过。 | | AC4 | 审批/BIFF8导出不减本金,在途不释放;安全取消、独立确认失败、成功原子claim/核销及真实数据库审计失败回滚通过。 | | AC5 | 合成自动worker/双人手工回单、双方账户/币种/金额/pending负例、跨借款/报销交易去重通过;真实银行/OCR样本接受性仍待验,完整AC保留开放。 | | AC6 | 原借款分配、余额截止状态、独立会计交接与材料权限通过;不把无OA记录当无银行还款。 | | AC7 | 付款/制单/回单及ERP触达业务回归通过,PC/手机正式登录同链与普通员工403通过,默认银行信息脱敏。 | | AC8 | 迁移/锁图/回退影响已落盘;独立只读复核PENDING,08-23实际保管/恢复事实与银行样本/迁移发布条件开放。 | 主会话只读自审核对了显式角色、账户/身份版本、创建lender→loan锁序、既有batch→receipt→lender→loan核销锁序、loan错误整体抛出回滚、unknown不释放及ERP共享边界;没有把此自审称作独立复核。待办姓名区分可处理人与站内提醒对象,仅`wecom_app_sent`成功记录可描述个人发送,多接收人anchor不推断全部送达;真实批次姓名/企微发送事实未查。 最终`closeout-governance/process/docs`与两个task validate通过;文档仅原22项登记warning。保护核验`protection-final.json`:HEAD/index未动,22个目录6447个旧材料SHA与精确文件集合全部原样;177个旧差异151个逐字不变,26个在本批授权路径叠加修改。ERP退出留下的两处尾空格已修,最终diff和敏感回执另存。本批独立审阅入口为`review-candidate-r1`,仅按baseline快照计算本轮增量,当前源码快照、删除清单与定向证据分开;manifest外部完整性回执不自引用。独立状态PENDING。未读取真实配置/密钥/备份,未连接生产/ARM,未重跑旧恢复,未提交/推送/部署/真实通知或付款。下方阶段过程保持历史原文,不再代表当前未实现状态。 ## 2026-09-17 T3/T4接续回执 T3及前端台账/付款分配/材料/会计交接已落地。`loan-payment-http-r3`:72迁移、9组约束、12组真实认证HTTP通过;`loan-unit-r3`:付款/制单/回单/通知5文件212项通过。`loan-browser-r2`桌面和手机走到还款详情并留截图,末项员工拒绝页断言错用地址导致整轮FAIL;已改为实际`/403`,不计该轮完整通过。新增跨借款/报销交易去重、金额/币种/双方账户/在途负例与同键并发,重跑中。 审批姓名区分当前可处理人和站内通知对象;企微发送只认`wecom_app_sent`成功,多接收人anchor记录不推出全部送达。不读真实delivery payload或配置。旧日期/恢复状态为历史规划记录,以本顶部实际回执为准。独立只读review PENDING;真实银行接受性、录入/付款/发布未执行。 ## 2026-09-17 当前实施回执(取代下方旧 planning/未实施描述) 官方current已start并回读本task。T1增量schema、迁移、延迟聚合约束已落地;独占PostgreSQL无网络/无宿主端口/只用合成库。初始化socket路径已修正,失败轮次原样保留。`loan-db-prototype-r5` 全部72迁移和9组约束通过,包括实际双连接锁等待与超额拒绝;容器清理通过。 T2台账/加密出借人/身份确认/原凭据唯一/材料上传下载/期初余额确认已实现。`loan-ledger-http` 真实密码登录、正式auth插件及Fastify/Prisma/PG验证5组接口场景通过,同时重跑9组DB检查。普通员工、经理、system_admin及仅admin不能管理借款;期初余额少于原本金须补系统外已还证据;审计失败由数据库触发,业务写整体回滚。Prisma validate/generate通过,generate使用本树既有链接依赖目录;不安装新依赖。 T3正在接入现有付款消费者:专属还款申请、多借款一付款、占用/独立复核、回单worker/人工例外、原子claim和本金核销;尚未完成本切片验证。T4前端和完整验收待执行。AC不提前勾选,独立只读复核PENDING,真实银行样本、发布、实际录入/付款仍未授权。 # 实施顺序(仅规划,尚未开始) ## 2026-09-17 执行优先级更新 用户要求尽快完成既有借款方案。先完成09-04两处真人反馈修复,随后官方start本task,本地T1约束/并发原型→T2台账与证据→T3本金分配及既有付款来源全链适配→T4合成闭环和旧报销回归连续推进。范围按原8项AC,不把文档齐全当产品完成。原“仅规划/不实施”的优先级由本节替代;真实操作与独立/发布门禁仍有效。 只使用运行独占的本地PostgreSQL和合成加密材料,禁外部通知/OCR/银行调用,不连接生产/ARM或读取真实配置密钥备份。无现成真实身份/付款事实时保持未确认,不用admin兜底。inline下独立只读复核PENDING,主会话不得冒称独立通过;未独立审查的新资金链不发布。 ## 2026-09-17 T1本地技术准备回执(最新入口) 已按09-08后期规划细化design第8–10节:四核心表+专属LoanEvidence、既有PaymentBatch增量、金额/唯一/FK/删除保护、余额公式、权限/接口/并发矩阵。当前execute的来源锁早于receipt advisory,不能直接复用为借款锁序;已明确新来源分派和所有写路径的顺序。文档提出取消后新申请保留历史、unknown银行结果不释放/重付,原8项AC未勾选。 - [x] T1a字段/约束/锁图/消费者与测试合同草案,源码引用已核。 - [ ] T1b获得进入条件后,以最小合成schema证明CHECK/部分唯一/延迟触发器/FK和两连接并发;尚未创建schema、迁移或数据库。 - [ ] T1c独立只读审阅具体方案与原型,不把主会话对照源码计独立通过。 - [ ] T2/T3/T4仍未开始;原恢复风险和产品实施准入保持,当前planning不变。 ## 准入 本task为09-08协调表的C阶段,不是其子任务。当前仍planning;本轮官方current在09-05执行本地治理,未切入本task。创建与规划补充不授权借款业务实现。先审阅本PRD/design,核08-23关键恢复状态和09-05到期治理结果;受保护操作等待不要求22项历史task全绿,但实际密钥不可用/敏感恢复失败没有处置时不直接扩大付款数据范围。 ## 顺序与验证 - [ ] 取得本task方案实施批准,用官方task.py start切换并回读;检查执行树、AGENTS、相关backend/approval/receipt/security/frontend spec及未提交差异,记录只允许本批改动的路径。 - [ ] 清点所有PaymentBatchEntityType消费者,设计最小Prisma模型/增量迁移、唯一约束、FK和权限矩阵;确认制单/复核/登记锁序与旧报销兼容,不引入通用工作流引擎。 - [ ] 实现出借人/借款登记、证据与余额确认,先做无权限、身份不明、重复/历史登记和可用额度负例,再做正向。 - [ ] 实现一申请一笔付款及多借款分配,复用批次独立复核;补同笔借款并发、取消/失败/未知在途和幂等断言,不能只用顺序mock证明防超付。 - [ ] 显式接入用途/备注、快照/来源重验、回单队列范围/匹配/人工复核/全局交易去重;未支持分支拒绝,错金额/账号/失败交易没有人工旁路。 - [ ] 接入既有风格的台账/还款列表与详情及会计交接记录,保持财务/审批人/普通员工可见范围和PC/手机同功能。 - [ ] 在合成独立库运行真实路由、登录浏览器和DB同链;新业务反例与原报销/差旅、动态错误合同回归分别记录,不使用真实公司借款样本或真实付款。 - [ ] 执行`cd server && npm run prisma:validate`、相关`node --check`及新增Vitest;执行`cd client && npm run typecheck && npm run build`及定向Playwright;新增测试文件及精确命令在实施时登记,当前不声称存在或已跑。 - [ ] 执行原因码、Trellis/process/docs/敏感扫描及`git diff --check`;冻结候选并取得真实外部只读内容复核,主会话检查不冒充独立验收。 - [ ] 新迁移/真实样本OCR、提交/推送、发布、真实资料导入及真实付款分别按具体范围取得批准;部署后只读验收通过才能告知公网可用。 ## 停止与交接 收款人自审、超额占用、在途可重复付款、旧来源回归失败、秘密/真实资料进入日志或不可回退的迁移方案均阻断候选。找不到合格审批人时明确业务阻断,不通过改角色或admin兜底完成样例。业务少/无自然付款不制造交易测试;需要真实样本时先单独列授权范围。 08-23和09-05若新增重大风险,先回09-08协调;本task不顺手改生产密钥/恢复工具或替其他task清理。原始PRD验收保持未勾选,正式实施结果、测试、独立审查和发布分节记录。K0已完成本地验证,K1/K2仍无实际保管/真实解密证据;新会话先核09-08协调入口,不因文件齐全或K0通过就先开发借款模块。 ## 2026-09-17 规划补充与开发前审阅包 用户要求对未完成工作先补规划;本轮只更新本task计划,不新增枚举/表/接口/UI,不读取真实借款资料。K0的30项合成结果不能替代保管事实;09-05本地日期/错误治理候选也未部署。恢复风险处置、方案实施审阅及独立复核依然是进入条件。 - [x] 复核当前枚举只有reimbursement/travel_order,以及readiness、回单验证、人工复核和OCR worker对reimbursement的明确限制;记录下方消费者分组,不借新增来源解冻travel_order。 - [x] 补迁移/锁序的待审技术切片和验收出口,前端沿既有布局,不新设计视觉体系。 - [ ] 技术定稿T1:提出四类核心表及专属借款证据关系的字段/索引/FK/版本设计;按当前PaymentBatch/ReceiptClaim实际锁图审查,先以最小合成schema验证约束及并发,再实现接口。 - [ ] T2:出借人/原借入登记及财务确认,只用合成资料;不自动产生付款或新增真实收款。 - [ ] T3:新来源显式支持/拒绝矩阵、额度占用/幂等/状态与回单闭环;逐消费者负例后再接页面,不凭新增enum编译成功宣称支持。 - [ ] T4:真实认证的本地路由/数据库/浏览器全链及旧报销/差旅回归,形成独立审阅候选;新来源OCR真实样本和生产录入仍另批。 这四切片复用原8项AC,不降低审批人独立性、并发不超付、在途保持占用、全局交易去重和审计原子性。日期/错误债务后续批次、恢复事实与借款开发分别交付,不要求22个历史task全部结案,但也不默认接受未知密钥风险。