公司只有财务和出借收款经理两名办理人,新增限定公司、出借人和借款范围的关联方确认模式。 仅豁免指定公司代表的收款人关联;经办、自审、证据、交易归属、资金占用及 Q6 限制保留。 贯通付款、人工回单、银行对账、补证恢复、晚到补记与追回;电脑和手机显示实际确认身份。 授权版本、付款与对账停用事件及历史决定只增不改,新增迁移 20261009010000_loan_related_approval。 本地合成验证:82 迁移、HTTP 109 组、浏览器 33 组、数据库约束 9 组通过;13 个有效资金守卫变异均捕获。 已有服务端全量 4519 项通过、1 项原有跳过,后续定向 77 项通过;提示收尾另有 908 项合同测试及前端构建通过。 按用户授权提交后对干净候选运行正式 verify-candidate,不沿用旧候选回执。 限制:独立代码复核待完成(inline 模式);真实回单待验。本次仅本地提交,不推送、不部署。 生成关联决定后不能直接降回不理解该模式的旧代码;真实授权、录入、生产核实和付款仍须明确批准。
100 KiB
2026-10-08 关联方模式本地提交与正式验证(已授权)
用户明确答复“是,授权”,同意将本轮 39 项改动作为一个完整的本地提交,并对干净的新候选运行正式验证。提交范围为 33 个修改文件和 6 个新增文件,含一个新增迁移;文件摘要已与上一轮收尾清单核对一致,本次只补授权及验证安排的记录。
- 按中文提交说明引用
09-17-company-loan-principal-repayment,保留“真实回单待验、独立代码复核待完成”的限制;不推送、不部署、不查询生产、不配置真实授权或操作真实资金。 - 提交后只运行
bash scripts/qa/run-release-gate.sh verify-candidate,在独立的artifacts/release-gate/目录留存该候选回执。运行期间冻结源码、测试与任务文档,不把旧候选或限定重验结果视为本次正式通过。 - 门禁发现本任务问题时,在已批准范围内修复并做针对性验证,再形成新候选;失败证据保留。每个实际候选和最终结论以 Git 记录及其对应回执为准,不提前记录 PASS。
- 独立代码复核仍受 inline 限制而待完成;正式本地门禁不能替代独立复核、实际回单验收和生产启用审批。整体任务保持
in_progress,不归档。
下方“未提交”“待授权”等为相应阶段时点,当前授权与执行顺序以本节为准。
2026-10-08 关联方模式收尾接续(用户要求按既定思路规划并实施)
沿已批准的 RP1–RP4 和两人办理规则继续完成本地收尾,不重新实施已通过的流程,也不重新要求确认马经理公司代表权。技术员工不参与业务审批;普通回单直接按获准实际材料验收既有 OCR,无需先问银行。
- 对当前 39 项改动做最终主会话检查,重点核对授权时点、历史经办冲突、材料读取、最终资金消费者及迁移;修复下述文案遗漏,未发现未处理的本轮资金规则阻断。
- 核对既有验证回执和当前差异,补齐可供只读复核的范围及真实材料验收清单;无变化的通过结果直接复用,不把旧候选正式门禁当成关联模式门禁。
- 更新本任务记录并完成任务、治理、文档引用及差异格式检查,形成可审阅的 39 项本地提交范围;本次没有提交、推送、部署或查询生产。
- 本轮独立代码复核:当前 inline 指令禁止派 implement/check 子代理;已有两份代理报告属于前阶段,不覆盖关联方改动。主会话检查不替代此项。
- 本地提交及固定候选正式门禁:提交按明确授权执行;门禁使用干净、已提交的新候选,不能通过临时提交或忽略工作区差异绕过。
- 真实材料验收和发布准备:财务提供既有借入凭据、历史还款及余额核对、双方账户、可授权使用的回单与提交记录;生产查询、真实录入、推送和部署各自按明确授权执行。此前空存量结果不代替发布前查询。
本次不更改业务规则或扩大为 Q6、第三人审批、远端备份切换;待配合事项在本地收尾完成后集中说明。
复核交接范围
基线为 4c37fcee,本轮待提交范围仍为 33 个修改文件和 6 个新增文件。正式复核须同时检查未跟踪的新文件;仅检查 git diff 会漏掉新授权服务、迁移、界面及测试。以下作为只读复核入口,不能把此交接清单视为独立复核通过:
| 检查面 | 入口与必须保持的结果 |
|---|---|
| 授权与历史决定 | loanApprovalPolicy.js、新迁移及 Prisma:最新已确认范围不回退、付款/对账分别停用、同一员工多账号仍冲突、历史有效决定可消费、模式不可改 |
| 最终资金动作 | companyLoanPayments.js、提交/终态/SR/银行结果服务和人工回单重建:所有入口及最终消费使用相同模式;缺证仍占用、重复交易仍拒绝、关联 Q6 不可用 |
| 页面与读取 | 两个路由、授权/还款/对账组件、付款页、导航及责任人:财务经办、指定公司代表确认,技术员工无审批和材料权限;完整账号及原件仍按用途审计 |
| 数据及并发 | 新迁移不改旧迁移,旧记录独立模式;当前授权、决定人与材料上下文受约束;既有批次→回单→出借人→借款锁序,无逆序 |
| 验证及文案 | 关联 HTTP/电脑手机 fixture、单测、错误码合同:包括完整闭环、资金拒绝后的本金占用不变和授权停用两种顺序;公共借款错误提示不能把关联确认说成独立复核 |
本次主会话发现并修正 5 条公共借款错误提示:银行结果、补证需确认/已失效、回单归属、提交清单。只改提示及对应的前后端合同,未改资金判断;独立模式专用的无复核人提示和 Q6 双人要求保留。
本次增量验证证据位于 artifacts/qa-flow/loan-related-closeout-20261008/:错误码合同零发现;已有错误提示及业务错误测试 2 文件、908/908 通过;前端类型检查和构建通过;UI 规则 161 文件零发现;改动的服务端常量语法检查通过。未为文字修改重跑数据库、HTTP、浏览器或资金变异,也未重跑服务端全量。前阶段完整借款专项仍为 82 迁移、HTTP 109、浏览器 33、数据库约束 9 组通过;有效变异分三轮 8+3+2 全部捕获。最后一轮变异回执中的 5 个资金/权限关键文件摘要与当前文件一致;此比较只覆盖所列文件,不作为整仓或发布证明。主会话检查、独立复核、正式门禁及真实验收仍分别记录。
本次 task validate、Trellis 治理(含敏感扫描)、流程合同 baseline 和 git diff --check 通过。文档注册校验零错误,保留原有“22 个 docs 未登记”的一条汇总告警;不扩展清理范围。inline 缺失的 implement/check manifests 按现有规则跳过。
财务配合与真实材料验收
| 顺序 | 需要的既有材料 | 核对结果 |
|---|---|---|
| 1 本金 | 原借入凭据、协议或确认资料、系统外已还依据、代账核对结果及截止日期 | 按原借款逐笔确定未还本金;资料未核实不能申请,OA 无记录不能推定银行未付款 |
| 2 身份与范围 | 公司主体、财务和马经理真实员工关联、已确认的公司代表权说明、所覆盖借款、双方银行账户 | 在获准业务录入时登记范围并由马经理确认;不新增第三人审批,不在聊天或测试报告抄录完整账号 |
| 3 回单 | 获准用于验收的既有银行回单原件,以及有对应关系的银行提交记录 | 在受控环境按实际 OCR→归一化→匹配处理,逐项核对金额、币种、账户、状态、流水号及时间;不能仅看 OCR 返回成功 |
| 4 歧义及异常 | 现有同金额候选的归属依据;已有失败/处理中材料及相应指令终态材料(如有) | 按实际文件记录支持与不支持的字段及编号对应;材料不足保持待对账。缺少异常样本就保留该项真实验收未完成,不制造付款取样 |
原件只在获准的受控位置处理;验收记录只保留样本代号、字段是否可读、匹配或拒绝结论及脱敏证据引用。普通 OCR 验收不以询问银行或取得“查询无结果”PDF为前提;公司现有人员安排下,关联 Q6 继续关闭。
候选与发布接续
- 本地问题修复及针对性验证完成后,固定只读复核范围;独立复核未完成时明确保留该项。拟提交内容为完整的关联模式及验证、任务记录,提交说明保留“未部署、真实回单待验、独立代码复核状态”。提交只在获得明确授权后进行。
- 对获准提交后的干净候选运行
bash scripts/qa/run-release-gate.sh verify-candidate,另存候选回执;运行期间不修改源码、测试或任务文档,不并发重建前端。此命令只验证,不使用会进入生产链的all或ci-release。 - 发布前获准重新只读核实生产借款、在途/终态批次及迁移差集;本地为 82 个迁移,若生产仍保持此前的 73 个,预计差集为 9 个,但不得把这个推算填作实际
EXPECTED_PENDING_MIGRATIONS。准备覆盖数据库和附件的部署前手动快照,以及生成关联决定后禁止直接降级的兼容处置方案。 - 推送、部署和真实授权/借款录入/付款各自按明确授权执行;部署后核对版本、实际迁移、电脑手机入口和权限,再办理真实已批准的还款。备份切换仍只按原独立范围安装指定脚本,不能借此发布整个应用。
2026-10-08 关联方还款本地实施完成(未提交;独立代码复核及真实材料待验)
用户在规划完成后明确“开始实施”,授权按 RP1–RP4 自主完成本地实施及验证。本轮按财务经办、马经理代表公司确认的已定分工实施;技术员工不参与财务审批、复核或见证。当前 inline 由主会话直接实施与检查,未派 implement/check 代理;以前代理的复核不覆盖本轮差异。没有提交、推送、部署、查询生产、配置真实授权或操作真实资金。
- RP1:新增一个增量迁移
20261009010000_loan_related_approval(本地共 82 个迁移),新增授权、覆盖借款和生命周期事件,冻结还款模式与范围,补齐逐次决定上下文及数据库约束。历史记录默认独立模式,不补造授权;未改旧迁移。 - RP2:贯通付款批准/退回、导出、清单、成功/失败归属、人工回单决定及冷重建、严格失败、终态与最终取消、SR、晚到成功、误报及追回。只豁免指定确认人的收款人关联,全部历史经办冲突保留;关联 Q6 在发起、决定和最终释放处拒绝。
- RP3:现有电脑/手机页面接入授权范围和公司代表确认,按服务端能力区分动作;经理只读授权范围内的材料,查看原件与完整账号需用途及审计。两个独立登录实际操作完整正常及异常流程,技术员工无新增候选、待办或材料权限。
- RP4 可执行部分:定向 DB/HTTP/浏览器、确定性交错、资金守卫变异、受影响共用路径、主会话只读检查及既有规约维护完成。任务与流程收尾校验另见本节末。
- 本轮独立代码复核、获准真实材料验收及固定提交候选的正式发布门禁;不以本地测试或旧候选回执勾选 AC27/整体借款验收。
关键行为与收口修正
- 授权分为新付款与历史对账两方面。使用最新已确认版本,缩小范围或停用后不回退旧版本;旧版本不能再登记停用事件。新申请/批准/导出检查当前付款授权,新对账决定及最终释放检查当前对账授权;已生效审批及银行事实在证据有效时按历史上下文消费,不因事后停用或确认人离职丢失效力。
- 公司代表可以退回付款申请,必须写理由;决定不可改,不能再批准或导出,退回本身不释放占用。财务安全取消后新建更正申请,详情、台账、责任人及提醒均标为退回。
- 同一员工兼任角色或使用多账号仍不能自审;经办冲突收集包含作废、撤回及被取代材料。数据库同时校验决定的实际确认人与上下文相符、目标及授权范围一致,禁止把关联决定写进旧独立记录。
- 核销、人工证据重建、银行事实补记及恢复释放均重验历史决定,而非只信任
approved。篡改原付款或人工决定上下文的隔离反例会被拒,本金和占用不变。 - 手机实测发现退回菜单被底部导航遮挡,已改为向上展开并保留可点击高度。完整浏览器回归后仅另改一处账号查看弹窗文案,将借款的“报销单”改成“还款单”;该文字修正后受管构建/类型检查、UI 规则及差旅冻结保护再次通过。
锁序保持:既有批次 → 回单交易/附件 → 出借人及人员资格 → 排序借款;创建锁出借人 → 借款,仅新建批次。授权生命周期只锁出借人,不等待既有批次。授权停用分别与批准、导出、事实确认和最终释放做两种先后顺序,共 8 个确定性交错;材料及候选变化继续沿原门禁。串行化只覆盖动作当时已知事实,之后的新银行事实仍走晚到结果对账。
本地验证与证据
主要记录在 artifacts/qa-flow/loan-related-20261008/,均为合成资料与本轮拥有的隔离环境。
| 范围 | 实际结果与边界 |
|---|---|
| 完整借款专项 | loan-full-first.log:82 迁移、HTTP 109 组、浏览器 33 组、数据库约束 9 组全部通过,清理通过。HTTP 包含原独立模式 95 组及关联 14 组;浏览器包含原 19 组及关联电脑/手机各 7 组。OCR 只替换云端返回,识别、归一化、匹配、人工重建及最终消费走真实实现 |
| 关联正常及异常 | 范围登记/确认、原件读取、批准与退回、导出/OCR核销、人工核对、归属变化重提、逐指令终态、SR及释放、占用冲突、部分/整笔超额、部分/全额追回、误报、Q6拒绝及技术员工拒绝访问通过;审核或资金写入异常的事务回滚也有反例 |
| 服务端 | server-full.log:227 文件、4519 项通过,1 项原有跳过。此后补旧授权停用检查与数据库决定人核对,最后的 targeted-final.log 5 文件 77/77 通过,最新数据库/HTTP验证包含于上述完整专项;没有把较早全量回执说成最后小改后再次全跑 |
| 受影响共用界面 | loan-related-shared-20261008 的受管首轮为 35 通过、1 失败:报销付款、付款权限和导航通过;误选了覆盖合同已标 frozen 的历史 travel-payment-flow.spec.ts,员工入口按现行规则返回 403。未改差旅代码或权限,改按合同入口 travel-freeze-protection.spec.ts 在 loan-related-shared-freeze-20261008 重验 2/2 通过。保留首轮失败,不称首轮全通过;两轮源码/仓库完整性和自有环境清理通过,均不具有正式发布资格 |
| 静态与编译 | Prisma validate、前端类型检查/构建通过;最新 UI 规则扫描 161 文件零发现,错误码合同、敏感扫描及 21 个改动 JS/CJS 的语法检查通过。文字修正后的类型检查/构建日志在 shared-freeze-retained.log |
| 守卫变异 | mutations.json 8/8、mutations-extra.json 3/3、mutations-final.json 2/2,共 13 个有效变异全部捕获;均在临时源码副本测试,工作区被测源码摘要未变,副本已清理 |
变异覆盖当前付款授权、范围、指定身份、历史经办冲突、最终原批准消费、人工回单重建、Q6、退回决定、冻结付款上下文、最终释放当前资格、范围读取、旧授权停用和数据库首个决定的实际确认人。移除原批准/人工证据最终检查会造成错误核销,测试明确捕获;移除旧授权停用的服务检查时,数据库仍拒绝,测试捕获的是 500 取代约定 409,不是错误停用或错误资金动作。最初变异运行器用错 Vitest 配置扩展名的启动失败不计入 13 个有效结果。
中间浏览器失败记录保留于 related-browser-*.log、related-browser-ui-*.log:先修正隔离 origin 的端口、两个视口重复按钮定位、提交响应与页面刷新的等待、证据选择与查询刷新的等待,再修复实际手机菜单遮挡。最后完整专项通过;不将先前局部桌面通过描述为电脑/手机全过。相关截图位于完整专项回执列出的 artifacts/qa-layout/ 子目录。
复现入口:
- 完整专项:
RUN_ISOLATED_LOAN_DB_TEST=1 RUN_ISOLATED_LOAN_BROWSER=1 node scripts/qa/test-company-loan-db.cjs;需沿已验证的 BIFF8 Python 环境和 Playwright 浏览器缓存配置。 - 关联定向:增加
RUN_ISOLATED_LOAN_RELATED_ONLY=1;若另加RUN_ISOLATED_LOAN_RELATED_UI_ONLY=1,只做浏览器准备,关联 HTTP 明确为NOT_RUN,不得计通过。 - 共用界面:受管
bash scripts/qa/run-web-gates.sh retained-local,通过QA_RETAINED_SPECS选择报销付款、付款权限、导航及现行差旅冻结保护合同。不能用已封存的差旅整链恢复被冻结权限,也不把 retained-local 当作verify-candidate。
主会话检查及后续边界
主会话只读检查覆盖所有授权生命周期、决定入口与最终消费者、共享人工回单重建、范围读取/审计、不可变迁移、Q6及锁序,未发现未处理的本轮阻断项。对比原迁移确认两个被替换的历史触发器仅适配新增决定字段,旧状态转换保护保留。按 trellis-update-spec 更新既有后端规约,写入模式/权限时点、经办冲突、历史消费、读取与回退合同,并替换过时的“S8恢复界面未做”测试说明;运行次数保留在本任务。
- 任务仍为
in_progress。AC20–AC26 仅勾选本地合成验收;AC5、AC8、AC27及既有整体业务验收保持开放。仓库.trellis/config.yaml的dispatch_mode: inline和 workflow 禁止派 implement/check 代理,本轮没有独立代码复核结论;不需要技术员工承担财务复核。 - 新模式真实启用前仍需财务核实借款余额与账户、登记已获确认的公司授权范围,再使用获准实际回单和提交记录验收现有 OCR 及编号对应。无需事先向银行咨询普通 OCR;证据无法对应时保持待对账。Q6 在关联模式下不可用,不能以两人声明代替银行终态证据。
- 当前 HEAD 仍为
4c37fcee,本地 main 比本地 origin/main 多 12 个已存在提交,本轮差异未提交。旧候选正式门禁不证明本轮差异;后续固定提交候选再做正式门禁,推送、部署、真实授权/付款及发布前生产核实分别按授权执行。 - 新增迁移须纳入将来部署的实际迁移差集。2026-10-07 的 OA 空存量与 73 个已应用迁移只是当时时点,不能代替发布前再核实;已有银行事实后不得降回不能解释关联模式的旧代码。
- 收尾 task validate、Trellis 治理(含敏感扫描)、流程合同 baseline 及
git diff --check通过;inline 下不存在的 implement/check manifests 按规则跳过。文档注册检查零错误,保留原有一条“22 个 docs 未登记”的汇总告警,本轮未扩大清理范围。AC1–AC27 连续、原 AC1–AC19 勾选状态保留、历史正文未删;较早门禁标题仅补充“历史计划”标记。
2026-10-08 关联方还款实施规划(历史规划回执,已获本地实施授权)
用户已确认马经理有权代表公司批准,要求按财务与马经理两人办理的方向规划;技术员工不参与复核、审批、见证或财务授权。本轮完成既有PRD/design/implement收敛,不把“规划”扩为代码或真实业务操作授权。下面较早的阶段记录保留各自时点,当前实现状态与后续工作以本节为准。
当前基础与本轮产物
- 既有A/B/C、S1–S8、SR补证恢复、电脑/手机界面均已在本地实现。当前HEAD为
4c37fcee,本地main比本地origin/main多12个提交,未推送、未部署。本次待做的是关联方模式,不再把S4–S8或SR列为未实现。 - 该干净候选的正式
verify-candidate回执为PASS:浏览器372/372、无失败/跳过/重试;服务端4480通过、1项原有跳过;7个默认关闭的可选专项未执行。源码/仓库完整性及自有环境清理通过,专用浏览器目录已清理。 - 证据为
artifacts/release-gate/loan-4c37fcee-20261008/release-result.json与同目录local-followup.json;保留此前失败回执,不以新回执覆盖历史。更早的借款专项为81迁移、HTTP95、浏览器19、数据库约束9组通过。以上只证明旧独立模式及各自候选,不能证明新模式或真实还款已验收。 - S0人员事实已明确:财务一人、收款经理一人,技术员工不参与,独立模式无人可办理该笔还款。马经理公司代表权已确认,不再提问;关联模式关闭Q6,不再把额外两名独立复核人或无结果PDF作为普通还款启用条件。
- 普通回单沿已有OCR按实际文件处理,无需先问银行;真实样本尚未验收,不补造字段或编号关系。2026-10-07生产只读汇总为空只是当时时点,本轮不重查。
本轮文档清单:
- 记录已确认的公司授权、两人分工、技术员工排除和OCR验收纠正;删除未定方向的表述,保留被否定方案的历史说明。
- 收敛PRD的R3/R4/R6、原AC3独立基线及AC9–AC19的模式语义,新增未勾选的AC20–AC27;已付、异常与Q6边界一致。
- 在design给出范围/授权、权限时点、全流程分工、数据与消费者、并发、界面及启用/回退方案;覆盖人工回单重建与最终消费,不能只改审批入口。
- 拆分以下RP1–RP4及定向验收;本轮无应用实现、迁移或业务配置。
- 任务校验、Trellis治理(含敏感扫描)、流程合同baseline及git diff --check通过。主会话另核对AC1–AC27连续且既有勾选状态保留、新AC未提前验收、design/implement历史正文保留、差异仅三份规划文档;未运行应用测试或正式门禁,未进行独立代理复核。
原实施拆分(历史规划时点;当前结果见顶部)
| 切片 | 内容与主要范围 | 验收和完成条件 |
|---|---|---|
| RP1 授权、模式与数据约束 | 一个新增型迁移;借款范围授权及生命周期事件,真实身份关联,付款/对账授权区分,冻结还款模式,逐次决定上下文。沿用现有角色而不授予全局新权 | AC20/21/22/25/27;历史独立回填、关联字段/外键/不可变约束、范围和状态验证;不会单独使付款入口放行 |
| RP2 后端全链路 | 候选/创建/批准/导出;清单、两种归属、人工回单含重建、严格失败、终态、取消、SR、晚到/误报/追回;所有最终消费者、范围读取及授权接口;关联Q6三处拒绝 | AC21–AC25;每个消费者两人正例与经办冲突反例;拒绝后本金/占用/冻结正确;原独立、报销和差旅守卫不变 |
| RP3 现有页面接入 | 在借款内登记/确认范围,现有还款及对账页面显示模式、公司代表身份、材料/理由、分工按钮及不可用原因;待办、通知和审计文案一致 | AC22/26;电脑和手机实际走两人正常及异常流程,技术员工无候选/任务/材料,前后端能力一致 |
| RP4 验证、只读复核与收口 | 定向DB/HTTP/浏览器、资金守卫变异及确定性交错;针对真实OCR处理链的合成输入;补齐任务证据及复核发现,按最终变更范围跑必需检查 | AC20–AC27及受影响旧AC;只读review不改代码,inline无法派审时明确待独立复核;固定最终已提交候选后按已获授权运行正式门禁 |
- RP1完成。
- RP2完成。
- RP3完成。
- RP4完成;记录运行时验证、静态复核、真实业务验收各自结论,不合并写成“全部验收”。
所有切片作为完整可办理、可对账的模式一起启用;即使某部分能独立验证或提交,也不能部署只放开收款人审批的中间状态。公司授权登记只反映已确认的代表权,不再增加第三人批准层。新授权版本、付款批准和银行事实决定分开留痕,模式不通过前端开关或通用admin权限绕过。
针对性验收矩阵
| 主题 | 必须证明的行为 |
|---|---|
| 实际两人正例 | 仅财务、收款经理两名合成办理人,从范围登记/确认、建单、经理关联方确认、财务导出、OCR成功到核销;技术员工只作为拒绝访问的合成反例 |
| 只豁免收款人关联 | 经理仅作为收款人可以确认;分别加入制单、提交、导出、清单登记、各原件上传、人工录入或提案参与后全部拒绝。覆盖多角色及同一员工多账号,移除一条检查不能由删除收款人标识一并放行 |
| 授权和历史 | 未生效、超公司/出借人/借款范围、身份变更、客户端伪造模式、旧独立单转模式均拒绝;新版本不能改写旧付款授权。付款权限停止不破坏已付核销,新的对账决定及最终释放检查当前对账授权 |
| 正常与异常闭环 | 自动回单成功;人工录入→关联确认→证据重建→核销;同额成功/失败归属;清单及逐提交终态;严格失败与最终取消;补证重提;晚到成功→占用冲突/超额→部分/全额追回;误报关闭与多原因冻结 |
| 证据持续有效 | 缺字段、状态矛盾、同金额无归属、指令不符、缺任次提交终态、等待期未满、材料作废/替换/候选变化均不因关联模式放行;只登记事实不直接减少本金或释放占用 |
| Q6及其他业务 | 关联模式发起、复核、伪造双审后的取消均拒绝;旧独立Q6仍要求两名独立人及全证据;独立借款、报销/差旅及跨业务交易唯一性回归 |
| 决定与资金并发 | 授权停止分别与批准、导出、事实确认及释放测试两种顺序;沿现有出借人锁与人员资格锁,不新增逆序。材料/候选变化与最终资金动作仍做确定性交错;结果只保证当时已知集合,晚到证据进入对账 |
| 不可变与回滚 | 模式/授权引用不能换写,批准人与提案人不得同人,旧事实不可删;审计或资金更新失败全回滚;重复请求不重复核销/释放/追回;相关限制在服务和数据库分别验证 |
| 界面和隐私 | 两个独立登录在电脑、手机走实际弹窗;关联文案覆盖详情/待办/历史/通知,角色能力从服务端来;完整材料仍按用途审计,越范围及技术员工直接访问拒绝 |
测试沿项目已有隔离数据库、真实Fastify、Vitest及浏览器入口,不新造一套业务认证替身;OCR仅替换云端返回。每个关键资金/权限守卫做有区分度的反例及定向变异,若下游保护仍阻断则如实记录,不谎称该变异已造成错误资金动作。按切片做针对性回归,完整候选形成后再做受影响范围的完整验证,避免纯文档阶段重复全量门禁。
真实启用前的事项
- 完成上述代码、页面、迁移及验证;独立只读review按项目规则执行,受inline限制时保留待办而不虚报通过。
- 经正式业务录入核实公司、借款、未还本金、双方账户及马经理员工关联,在系统里登记此次已经确认的公司授权与范围。无需聊天提供完整账号,也不安排技术员工审批。
- 使用获准的实际回单及提交记录验收现有OCR和编号关系;正常识别不以事先银行咨询为前提。异常无终态证据继续占用,Q6保持不可用,不因样本不足降低证据标准。
- 提交、推送、部署与生产录入/付款分别按授权执行;发布前重新获准核实存量、迁移差集及手动快照。备份脚本的单独远端切换不在此范围,不能借此发布当前main。
2026-10-08 测试稳定性集中检查与新候选门禁(历史计划,最终回执见上)
用户已批准集中检查、必要测试修正、本地提交及对新干净候选运行正式门禁。本轮不推送、不部署、不查询生产、不执行远端备份操作;任务仍为进行中。
- 检查两份失败测试、此前修正的审批测试,以及邻近布局用例:严格同排对齐修正为同一次浏览器执行取值;其余宽高/横向比较、带足够间隔的上下顺序及非同类动画场景不机械改写。检查详情标题与加载提示,当前需修正的仍为下方已验证的两处。
- 保留两份测试全部原有断言和运行配置;没有新增用例、修改业务实现、增加容差、超时或重试。被测输入未变,复用下方受管定向 61/61 通过结果,不为本次文档更新重复运行。
- 将同次几何取值、精确标题定位两条已验证的规则补入既有前端规约;按任务、治理、流程合同、文档注册及 diff 检查后,本地提交两份测试、规约和本记录。
- 对新提交执行
bash scripts/qa/run-release-gate.sh verify-candidate,保留两次失败回执,新结果写入独立的artifacts/release-gate/目录。此处为提交前执行计划,不提前宣称通过;候选冻结后不再修改受版本控制的记录,最终状态以该候选的正式回执为准。 - 真实建行样本、官方查询材料和编号对应关系、合格复核人员及独立业务验收继续待外部核实;正式本地门禁不替代这些条件。
2026-10-08 第二轮正式门禁及新增测试稳定性修正
用户确认后,仅将此前的审批按钮测量修正和任务记录本地提交为 1dd84065,工作区干净;对该固定候选执行 bash scripts/qa/run-release-gate.sh verify-candidate。未推送、部署、查询生产或执行远端备份操作。
- 正式回执
artifacts/release-gate/loan-1dd84065-20261008/release-result.json为 FAIL,不具备发布资格。static 和 full-local 的前 11 个阶段通过,服务端单测 4480 通过、1 项原有跳过;网页 370/372 通过、2 失败、0 跳过、0 重试。默认关闭的 7 个可选服务端专项不计通过。上一轮失败的审批按钮用例已在本轮完整回归中通过。 - 两个新增失败来自既有测试:
r92-mobile-invoice-usability.spec.ts:335的宽泛文字定位同时命中标题与“加载票据详情…”提示,上传步骤尚未执行;system-action-confirmation.spec.ts:835顺序读取动画中两个按钮的位置,中心差约 3.69px,超过原有 2px 上限。此次候选仅改动另一份审批测试及记录,没有直接修改这两个用例或业务页面。 - 本轮仅局部修正两份测试:票据标题改用精确的 heading 定位;两个布局坐标改为同一次浏览器执行读取。保留中心差小于 2px、按钮顺序、侧栏宽度和批量上传计数等原有断言,不修改业务代码、不增大容差或跳过用例。
- 官方受管
retained-local验证这两个完整文件:61/61 通过、0 跳过、0 重试,包含原失败用例、批量上传计数及 1280/1440/1920 布局断言;运行中源码/仓库未变,环境和自有容器/运行目录清理通过。结果位于artifacts/qa-flow/loan-gate-followup-1dd84065-20261008/,不替代两轮正式失败回执。 - 定向入口:
QA_FULL_REPORT_DIR=artifacts/qa-flow/loan-gate-followup-1dd84065-20261008 QA_RETAINED_SPECS='r92-mobile-invoice-usability.spec.ts system-action-confirmation.spec.ts' bash scripts/qa/run-web-gates.sh retained-local;另显式指定本轮专用浏览器副本和受控 BIFF8 Python。任务校验、治理、流程合同及git diff --check通过。 - 正式运行全程源码/仓库未变,隔离容器及运行目录清理通过。新修正与本记录尚未提交,后续仍需固定新的已提交候选重跑正式门禁;真实建行材料、人员核实和独立业务验收继续待完成。
2026-10-08 正式本地发布门禁及测量时序修正
用户同意对固定干净候选 7a48a1e7 运行正式本地门禁;执行 bash scripts/qa/run-release-gate.sh verify-candidate,未推送、部署、查询生产或执行远端备份切换。专用浏览器经官方安装及受控复制,Chromium/WebKit 原生隔离检查通过。原始回执保留在 artifacts/release-gate/loan-7a48a1e7-20261008/release-result.json,结论 FAIL,不具备发布资格,不以针对性重验覆盖它。
- static 通过;完整服务端单测 4480 通过、1 项原有跳过,前端类型/构建、审批操作及门禁默认配置的服务端流程通过。
regression-all.sh默认关闭的 7 个可选专项没有执行,不计通过。 - 网页完整发现 59 个本地 spec、372 个用例,执行 371 通过、1 失败、0 跳过、0 重试。唯一失败是既有报销审批用例
workflow-action-confirm-ui.spec.ts:530:两个同排按钮先后读取纵坐标,相差约 1.16px,严格相等断言失败。原用例及报销页面均不在本轮借款业务改动中。 - 回执确认候选源码/仓库全程未变,隔离数据库容器及运行目录清理通过。仍不替代真实建行材料、人员可用性与外部业务验收。
- 本轮仅修正该用例的测量时序:在同一次浏览器执行中读取两个按钮的位置,保留原有纵坐标严格相等及高度差上限断言;页面仍保留 320ms 入场动画。不修改业务实现、不增加像素容差、不跳过用例。
- 用官方受管
retained-local对整个workflow-action-confirm-ui.spec.ts定向验证:21/21 通过,0 跳过、0 重试,原报销证据/退回意见断言以及电脑/手机审批场景均执行,环境和自有容器/运行目录清理通过。结果保留在artifacts/qa-flow/loan-gate-layout-20261008/,不作为正式发布回执。 - 定向入口:
QA_FULL_REPORT_DIR=artifacts/qa-flow/loan-gate-layout-20261008 QA_RETAINED_SPECS=workflow-action-confirm-ui.spec.ts bash scripts/qa/run-web-gates.sh retained-local;执行时另显式指定本次经校验复制的专用浏览器目录和受控 BIFF8 Python,不使用共享历史浏览器缓存。任务校验、治理、流程合同及git diff --check通过。 - 用户已确认将本次测试修正及任务记录这两个文件本地提交,不推送、不部署。提交后对新的固定干净候选重跑正式完整门禁,结果写入新的本地回执,保留上次失败记录;本记录提交时尚不宣称正式门禁通过。
2026-10-07 后续收口执行(用户同意执行)
按后续工作清单,先将已验证的 S4–S8 共 32 项改动本地提交,提交保留“真实回单待验、整体业务验收未通过”。随后补齐提交登记、清单复核、失败归属、晚到补记和追回的浏览器闭环,并准备发布前存量/迁移/回退检查材料。当前 inline 主会话直接实现和检查,不另派代理;此前两名代理的复核仅覆盖其当时差异。用户本轮已明确授权生产借款存量的只读汇总查询;人员与银行材料答复“不清楚”,保持待核实;推送、部署和远端备份切换不在本次默认执行内。以下“32 项未提交”属于提交前验证时点。
- 本地提交已验证 S4–S8:
431c36ea,32 项,未推送。 - 补齐其余银行对账表单的电脑/手机闭环;最终固定副本通过,在本次本地提交授权内将新增测试及 S0/发布准备记录单独提交。
- 在本任务记录具体迁移差集、发布顺序、回退限制和未满足条件。
- S0 生产存量只读核实完成;人员与银行材料仍待外部核实。
剩余界面验收补测
新增 company-loan-reconciliation-browser.cjs,由既有隔离浏览器入口调用。合成种子通过正式接口准备,实际待验动作由页面完成:电脑/手机各走提交登记→清单确认/独立复核→失败归属/独立复核→失败回单终态→取消;以及晚到成功原件上传/登记→用途审计查看输入→独立复核→补记→部分与全额追回→凭更正材料独立关闭重复误报。断言经办人无自审按钮、原占用释放、待追回变化、部分追回仍冻结、全部追回后关闭对应冻结、不创建新付款批次及手机无横向溢出。
未修改应用业务代码或新增资金规则。首轮用例把归一化后的大写指令号与小写测试预期比较而失败,已修正测试预期;后一轮通过。最新副本补明确选择新上传的更正证据,再验证最终用例。首轮失败不计通过;不新增变异测试或重复整套服务端单测,因为本轮仅补浏览器覆盖与文档。
复现:在隔离源码/构建副本内执行 RUN_ISOLATED_LOAN_DB_TEST=1 RUN_ISOLATED_LOAN_BROWSER=1 node scripts/qa/test-company-loan-db.cjs,BIFF8 使用已准备的受控 Python 环境。最终固定副本通过 81 迁移、HTTP 95、浏览器 19、数据库约束 9 组,自有副本/容器清理 PASS。脚本语法、任务、治理、流程合同、敏感扫描与 git diff --check 通过。应用代码与依赖未变,复用先前通过的构建、类型及单元测试证据。主会话遵循 inline 直接检查,没有新增代理复核,也不替代财务/银行事实验收。
S0 只读核实及发布准备(2026-10-07)
用户明确授权本轮生产借款存量只读汇总;通过既有生产连接,在 REPEATABLE READ READ ONLY 事务中查询并 ROLLBACK,设置查询/锁等待超时,未输出账户、原件或业务正文,未运行部署/迁移。核实时点 2026-10-07 22:08–22:09(北京时间)。
- OA 中出借人、借款、还款批次、占用分配和借款回单均为 0;已确认失败未取消也是 0。当前没有系统内借款存量需要回填;这不证明银行或线下没有付款。发布前必须再次核对,不能把本次空库结论永久复用。
- 已应用迁移 73 个,未完成迁移 0;与本地同名迁移的 SHA-256 全部一致,没有生产多出的迁移。本地 81 个,差集为以下 8 个(不是仅本轮新增的 3 个):
20261006010000_loan_receipt_attribution20261007010000_loan_bank_submissions20261007020000_loan_failure_attribution20261008010000_loan_bank_terminal_facts20261008020000_loan_release_recoveries20261008030000_loan_not_submitted20261008040000_loan_freeze_reasons20261008050000_loan_bank_result_events
- 人员、官方无结果 PDF、回单与指令编号关系:用户答复“不清楚”,均保留待核实;Q6 不能宣称具备实际使用条件。脱敏只读结果保存在本轮 S0 本地证据目录的 summary.json。
发布准备顺序(本轮只准备,不执行发布):
- 完成剩余浏览器闭环及业务/真实样本验收,固定最终已提交候选;不得把本轮合成回归当作正式 release-gate 回执。
- 对固定干净候选运行
bash scripts/qa/run-release-gate.sh verify-candidate,绑定当次回执;当前仍有待验证/未提交的补测,不提前运行大范围门禁或写“可部署”。不能用all/ci-release代替本地验证,因为它们会进入生产发布链。 - 经单独批准后做发布前只读核实,将实际差集作为
EXPECTED_PENDING_MIGRATIONS。若生产出现新增借款/批次、迁移差异或未完成项,重新评估,不自动套用本次 8 项或空存量结论。 - 按既定部署前手动快照方案确认快照完成与恢复证据。备份脚本切换属于另一项远端授权,仅安装指定 refresh 脚本及执行既定停用顺序,不借此部署应用。
- 推送、部署各自批准后才执行迁移/应用发布;部署后核对应用版本、81 项预期迁移、readiness、权限和借款只读页面。真实借款录入/付款仍需业务明确批准,不能制造付款验收。
- 回退保留新增表和历史事实,不删迁移或重置数据库。一旦生成补记/追回等新事实,旧代码未计算新台账,不能直接降级;停止新付款并按获批兼容修复或恢复方案处理。确认此前没有新资金事实,也仍需具体回退审批,不能默认恢复覆盖期间其他业务。
2026-10-07 后续执行接续(用户要求已确定工作直接执行)
沿既有设计与 S4–S8 清单推进本地实施、针对性验证与主会话检查,不再逐阶段等待通知。先 S4,再按依赖推进 S5、S6、S7、S8;提交、推送、生产操作仍遵守单独授权。SR-A/B 已本地提交 2e00d30f。前阶段 inline 下未派独立代理;本轮工具已可用,按 AGENTS 对资金流程的要求另派两名只读代理检查资金与界面,修复后静态复核通过(同模型,非业务独立验收)。
- S4 本地实施与合成验证:Q6 三类证据独立分类、全量材料快照、两名独立复核、人工终态及最终取消重验;覆盖混合导出(已提交部分沿 S3,未提交部分逐份举证)。
- S5–S8 本地实施、针对性回归及只读静态复核;整体业务验收仍受 S0 和真实样本限制。
- S4 技术边界:人工声明覆盖未关联提交的导出,不可覆盖任何已登记(含撤回)的提交;查询及对账单覆盖首次导出至登记日(公司时区),所有导出人的文件去向说明齐全。快照变更后重新登记、重新双审,原终态不改。附件分类不允许事后互换,不进入回单 OCR;真实材料及人员可用性仍待 S0。
本轮阶段结果(本地验证通过,尚未提交)
-
S4:新增
loan_not_submitted_proposals/reviews、三类固定证据分类、完整空清单复核、双人决定、人工终态、材料变更取代及最终取消重验。增量迁移20261008030000_loan_not_submitted。 -
S5:新增逐原因冻结、付款前统一门禁;事实登记不冻结,没有通用管理员解冻接口。迁移
20261008040000_loan_freeze_reasons。 -
S6/S7:新增银行事实、跨核销空间交易认领、逐借款补记、实际追回;本金容量同时包含补记结清。迁移
20261008050000_loan_bank_result_events。当前原件人工录入/独立核对,不声称 OCR 或银行真实性自动验证。待审的同一交易可用新证据取代,先产生新冻结再关闭旧冻结;已复核银行事实的原件不得作废,物理文件损坏仍拒绝入账。 -
S8:详情页接入提交、清单、终态、失败归属、Q6、SR 恢复、晚到补记/追回;查询完整人工输入和原件要求用途与审计,电脑/手机完成 Q6、SR 恢复及多回单终态的完整弹窗流程;其他新增表单以 HTTP 与类型检查覆盖。沿用既有视觉组件。
-
有效变异共 13/13 被测试捕获(6 个首轮、2 个金额边界、2 个最终入账守卫、3 个复核修复守卫)。包括三证类别、物理摘要、快照、冻结、交易身份、部分追回、占用冲突、超额拆分、最终候选、冻结转移、更正依据和旧取消旁路。部分变异仍被下游/数据库拒绝,测试捕获的是错误响应或错误原因,不能写成全部造成了错误释放。环境路径错误的首轮未计入;变异只在临时源码副本中进行,后续固定源码轮次摘要未变。
-
最终隔离回归:81 个迁移、HTTP 95 组、浏览器 13 组、数据库约束 9 组通过,容器清理 PASS。包含整笔超额、逐原借款差额、跨流程交易复用、原审批人离职、审计回滚、候选变更重新复核及冻结/新申请/导出的确定性交错。固定前后端源码/构建副本的最后一轮再次得到相同通过结果,副本及自有容器已清理。浏览器覆盖原有 7 组及电脑/手机 Q6 双审、SR 补证、两份处理中回单终态释放(包括作废历史回单的复核下载)6 组。人工等待期在 HTTP 验证,浏览器合成配置设为 0,不等待现实三天。
-
服务端首跑 4472 通过、8 失败、1 原有跳过(4481 总);8 个失败为报销回单旧测试替身缺少新增跨台账认领查询,补齐后相关两文件 150/150 通过,最后共享下载路径调整后再次 150/150 通过。合并覆盖 4480 项通过、1 项原有跳过,未将其描述为完整套件重新全跑通过。
-
中间失败如实保留:浏览器精确标签、分页缓存等待、Q6 合成等待期设置及重新登录加载等待先后修正;运行器后来固定 client/dist 副本,避免与构建文件更换交错。失败轮次不计通过。首轮变异因临时 Python 路径错误停在制单生成,不计有效变异。
-
Prisma 校验、前端类型检查/构建、共享回单定向测试、UI 规则、错误码合同、敏感扫描、任务治理/流程合同及 git diff --check 通过。文档注册检查退出 0,保留原有 22 个未登记 docs 告警。
-
本轮只读复核修复:取代银行事件遗留冲突冻结;误报解冻依据可作废;终态界面只能选一份处理中回单;各复核卡缺准确材料绑定;已作废处理中回单无法供复核查看。分别补齐服务/数据库保护、历史证据读取及桌面手机回归。两名代理对修复后源码静态复核通过,最终运行时结果见上方;不把同模型审查当作外部业务验收。
-
最终候选另外修正:晚到事实未处理时旧取消不能释放;归属候选在批准后变化时入账拒绝;唯一交易认领只在最终入账事务消费,允许未入账失效记录重新登记。
-
所有测试只用合成数据和本次拥有的隔离容器。未查询生产、未提交推送部署;S0、真实样本和外部业务验收仍待完成,整体借款验收未通过。
复现入口沿用上面的隔离回归命令(具体命令见下方 SR 记录);新增 3 个迁移必须列入将来经过批准的预期迁移。本轮 32 项未提交,HEAD 为 2e00d30f;未推送、未部署、未查生产。S0 仍须核实存量、两名额外合格复核人、建行官方无结果材料和回单/指令编号对应。真实银行材料、银行事实的业务真实性以及异模型/业务独立验收不由合成数据证明。保持任务进行中,不归档。
2026-10-07 SR-A / SR-B 收尾与提交授权
用户明确批准“先收尾 SR-A/B,本地提交;S4 另批”。本次将下方 15 项实现、测试及文档作为一个本地提交收口,沿用已完成的运行时验证,收尾只更新记录并重验任务治理及差异格式。未推送、未部署、未查询生产。当前 inline 模式下独立复核仍待完成;界面留在 S8,真实回单待验,不能单独部署启用。整体任务保持进行中,不归档;以下“未提交”和 HEAD 描述为实施验证时点的记录。
2026-10-07 SR-A / SR-B 本地实施(用户批准;未提交、未推送、未部署)
- 新增恢复轮次、不可变送审/复核字段、决定事件、材料修订号及数据库保护(增量迁移
20261008020000_loan_release_recoveries)。既有银行终态与依据不改,已释放/已结清分配保护不放宽。 - 新增发起、送审、独立复核、撤回、状态查询接口;终态事实登记只在最新轮次为补证中时开放。
confirmed_failed的恢复使用完整逐提交证据,不覆盖原失败核验引用。 - 最终取消消费最新批准;发起过恢复后不回退原取消路径。材料/候选变更拒绝,失效轮次可取代重提;重复取消请求只返回原结果,不重复释放。
- 数据库材料触发器覆盖导出、提交、清单、终态证据/事实、归属、回单、核验和人工录入,后台 OCR 也推进修订号;候选形成锁出借人,取消与对账接口遵守同一锁顺序。
- 新恢复接口只返回业务标识和状态;存储快照使用标识及摘要,不存解密账号。数据库 JSONB 会调整键序,摘要实现已改为递归按键排序;真实数据库往返测试已覆盖。
- 全流程 HTTP 用例新增独立 fixture,涵盖两种原终态、同一交易换回单、待定事实了结、补登提交、自审、离职、过期重提、物理文件摘要、等待期、回滚与幂等,以及最终释放对证据/提交/OCR落库/其他候选的两种确定性交错。
- 主会话完成本轮差异的只读检查;7 个变异在隔离源码副本中全部被测试抓住,未改工作区被测源码。最后迁移/约束加固后,重新执行含浏览器的隔离回归,78 迁移、HTTP 72、浏览器 7、数据库约束 9 组全部通过,容器清理 PASS。
最终验证:78 个迁移、HTTP 72 组、既有浏览器 7 组、数据库约束 9 组通过(均为隔离容器、合成数据);UI 规则、错误码合同、敏感扫描、前端类型检查及构建通过。服务端全量首跑 4470 通过、6 失败、1 跳过;6 个失败均为 BIFF8 Python 依赖缺失,按仓库锁定 requirements 在临时 venv 补齐后,涉及两个文件的 146 项全部通过,合并覆盖为 4476 项通过、1 项原有跳过,不声称重新跑过一遍完整套件。
变异证据(7/7):移除恢复轮次门禁、旧结论取消旁路拦截、快照新鲜度、恢复发起人独立性、完整释放条件、物理文件摘要、取消重试请求身份。快照/完整条件/物理摘要/轮次门禁/重试身份移除后出现本应拒绝却返回 200 的响应;旧结论旁路与自审移除后,数据库仍阻止非法操作,但返回 500 而非约定的 409/403,反例抓住了错误响应,不能表述为这两处变异已经绕过数据库并错误释放。测试结束校验被变异的工作区源码摘要未变,副本和各次隔离容器已清理。
数据库加固还覆盖:新增轮次的初始字段必须为空、序号/前轮与原银行依据一致;修订号不能回退或删除;送审快照不能在取代时顺便篡改;直接释放但未消费最新恢复批准,提交事务会失败。主会话检查范围为恢复状态机、六个接口、取消消费者、材料触发器、独立性与快照、物理证据读取、迁移和前后端错误码;不替代独立复核。
复现命令(PAYMENT_ORDER_PYTHON_BIN 指向按 server/requirements/payment-order-biff8.txt 安装的测试 venv):
RUN_ISOLATED_LOAN_DB_TEST=1 RUN_ISOLATED_LOAN_BROWSER=1 node scripts/qa/test-company-loan-db.cjs。cd server && npm run prisma:validate && npm run prisma:generate;npm test;依赖补齐后的定向命令为npm test -- tests/unit/routes/paymentBatches.reimbursement.test.js tests/unit/services/paymentOrderXls.test.js。cd client && npm run typecheck && npm run build;node scripts/qa/check-error-reason-contract.mjs、node scripts/qa/check-ui-design-rules.mjs、node scripts/qa/check-sensitive-content.mjs。
工作区:共 15 项未提交(含 1 个新迁移、1 个新服务和 1 个新 HTTP fixture),HEAD 仍为 14aee82d;本轮没有提交、推送或部署。文档注册审计退出 0,但保留原有 22 个未登记文件告警;任务/治理/流程合同与 git diff --check 通过。
边界:SR-C 界面随 S8,本轮浏览器 7 组是既有流程回归,不是新恢复界面验收。S0、真实建行样本、S4–S8 与独立复核仍未完成;未查生产。受 inline 限制,本轮主会话直接实施与检查,没有另派独立 reviewer,不报告“独立复核通过”。应用不得单独部署启用。本轮未执行生产迁移或回填,未恢复/重置任何既有数据库;QA 只创建并清理本次拥有的隔离容器。
2026-10-07 SR 补证后恢复设计接续(仅设计,未实施)
用户同意下一步先设计补证后恢复。本轮沿既有任务完成 design 顶部 SR1–SR6、PRD AC17–AC19;不执行 S4–S8,不修改资金代码或迁移,不查询生产、不提交推送部署。S3 已本地提交 14aee82d;下方 S3“未提交”等文字保留为历史时点。
本轮清单:
- 核对 S3 终态、终态事实登记及最终取消入口,确定补证被
unknown限制卡住;设计保留终态、另建恢复轮次。 - 写明适用范围、逐事实与整轮独立复核、材料失效、最终释放、并发、回滚和 S6/S8 边界。
- 同步 PRD 的恢复验收条件(未勾选通过)。
- 主会话按
trellis-check完成文档一致性自查;任务 validate、Trellis 治理(含敏感信息扫描)、流程合同 baseline、git diff --check通过。文档注册审计退出 0,报告 22 个未登记 docs 文件的告警;本轮未新增或修改 docs 文件,不扩展处理。未跑数据库、HTTP、浏览器或变异测试,未进行独立复核。 - 方案审阅及后续代码实施授权;本轮无资金代码实现或运行时通过结论。
方案批准后的执行切片(本轮不执行):
| 切片 | 内容 | 依赖与验收 |
|---|---|---|
| SR-A 数据与补证 | 增量迁移、恢复轮次/送审/决定、材料修订号;只对有效恢复轮次开放终态补证;保护原终态 | S3;AC17;迁移约束、补证往返、多轮取代、历史记录不可改 |
| SR-B 复核与释放 | 全量证据快照、逐事实与整轮权限、最终取消消费批准;覆盖相关写入口锁序 | SR-A;AC18/AC19;HTTP 正反例、失败回滚、并发、关键资金守卫变异 |
| SR-C 界面与收口 | 接入 S8 详情,PC/手机补证→独立复核→取消;旧记录与新资格并列 | SR-B 与 S8;不得因本地后端完成提前部署;整体测试与只读复核另报 |
定向测试矩阵:
- 两种原终态分别走“旧证据失效→发起恢复→上传新证据→逐事实复核→送审→独立复核→取消”,本金不减少,占用仅最后释放。
- 同一流水号重新上传/重新 OCR、清单新增再撤回、归属候选新增、批准后证据作废;旧批准拒绝,重新补证复核可恢复。撤回或驳回恢复不能走原取消旁路。
- 补登遗漏的第二次提交,少任一终态即拒绝;终态只能了结同指令处理中回单,成功事实始终阻断;Q6、未知文件、历史汇总、编号不符均不能代替证据。
- 刚导出时确认与最终取消均拒绝;等待期满才放行;无导出沿现有规则,不为补证另设等待期。
- 自审、多角色自审、旧上传/录入人换身份参与复核、当前人员离职被拒;原审批人/出借员工事后离职不拦按冻结快照登记事实。
- 最终释放分别与证据作废、OCR 核验落库、提交变化、同出借人新候选形成按两种顺序确定性交错;不得靠概率跑圈。释放先行后的新银行事实交后续对账,不宣称已处理。
- 最终事务在分配更新、批次取消、消费批准、审计处注入失败均全回滚;重复请求不重复释放;已释放/结清不可重开,恢复任何阶段不可导出/执行付款。
验证安排:设计阶段仅跑文档/治理校验与 git diff --check;代码阶段才跑隔离数据库/HTTP/浏览器及变异,按影响范围回归。inline 主会话审查不冒充独立只读复核。没有已验证的通用新工程规则,本轮方案先留在任务,不提升为模块既定规约。
2026-10-07 S3 本地实施记录(用户批准本地实施、针对性验证与只读复核,并要求纳入三条补充要求;未提交、未推送、未部署、未查询生产)
迁移 20261008010000_loan_bank_terminal_facts:
loan_bank_terminal_evidences:银行终态证据(银行书面回复、网银指令查询官方 PDF 等)单独成表,与付款回单分开。它不进入 OCR,上传不改变付款状态,不计入回单核验数量和作废回单判定。证据只能作废一次;作废后,依赖它的终态事实在同一事务内被取代。付款回单无法改成这一类型,因此不能借更换类型来解除成功或处理中回单的阻断。loan_bank_terminal_facts:每次银行提交至多一条待复核或已通过的终态事实,分两类——termination_evidence:终态为已拒绝、已撤销或已失败;failure_receipt:严格判定的失败回单,且回单流水号必须等于该提交登记的指令号。resolves_attachment_ids用于列出由这条终态事实了结的处理中回单。这些回单必须是本批次付款的单页处理中回单,且流水号等于该提交的指令号;其他提交的终态事实不能代替。终态事实只增不改,复核人须独立。
- 还款状态新增
confirmed_not_paid:终态,必须带依据,可取消释放。完整性函数和历史保护函数原样重建,只加入这个状态。
规则:
- 银行指令号登记时规范化(NFKC、去空白、大写)保存,且同一指令号不能同时登记在两个借款批次。
- 释放条件
assertNotPaidReleasable,以下全部满足才可释放:- 无历史汇总;
- 提交清单已复核且至今未变;
- 每次有效提交都有已复核、当前仍成立的终态事实;
- 每条导出记录都被某次提交关联;
- 本批次每份付款回单要么被终态事实覆盖,要么是能证明为明确失败或他笔付款的作废回单;
- 距最后一次导出已满内部等待期(默认 3 天,可配置)。
- 经独立复核人确认后,状态转为
confirmed_not_paid。 - 内部等待期适用于全部释放路径:确认未付款、单次失败确认,并在最终取消时重验(2026-10-07 复核补:单次失败路径原先漏了这一项)。
- 最终取消时在同一事务内重验:
confirmed_not_paid重跑上述全部条件,confirmed_failed重跑单次失败路径的全部条件。取消、上传回单、登记提交都要先锁批次,因此三者串行执行。 - 在失败或未付款结论之后上传的晚到回单,仍会被记录(状态不变),并因此阻断释放;释放之后才出现的新证据,留给晚到结果对账流程处理。
- 单次失败路径同时补上导出关联:有导出记录时,提交必须关联该导出(
loan.export_unlinked)。 - 新增 8 个原因码,三处都已登记;新增接口包括证据的上传与作废、终态事实的登记与复核、确认未付款(复核人操作)。
页面:仍未实施,留待 S8。不得单独部署启用。
验证与复核:
-
首轮针对性验证:HTTP 49 组、浏览器 7 组、77 迁移;11 个资金守卫变异均变红;server 4471 等通过。
-
同模型只读复核:BLOCK,三项(前两项经复核人副本探针实测),均已修复:
- B1 已登记银行提交但状态仍为
not_sent时,可单人直接取消释放:登记提交时同一事务内转为unknown;取消路径的not_sent分支另加防线,只要存在任何提交(含已撤回)、历史汇总或终态证据就拒绝。 - B2
failure_receipt终态事实绕过同金额失败归属、未做交易唯一性检查,同一笔失败交易可能分别让两个批次释放:- 失败回单分支复用单次失败路径的检查(不得被认领为付款、密钥一致);
- 存在同金额候选时,须有已复核、只覆盖该次提交的失败归属。归属新增
failure_scope(batch/submission),唯一性改为“批次+类型+覆盖提交”; - 新增只增不改的
loan_failure_evidence_uses:一笔失败交易只能作为一个批次的依据,单次失败路径和终态事实路径都在此登记,复用返回loan.failure_evidence_reused。
- B3 终态证据无法查看:新增
GET …/loan-terminal-evidences/:id/file,财务或合格的独立复核人可读,须填写理由并写审计,返回前校验 SHA-256,不缓存。
- B1 已登记银行提交但状态仍为
-
同轮非阻断修复:
- 结论已定或批次已释放后,导出、执行由 500 改为明确的 409;
- 释放后不得作废证据;
- 同一批次内指令号也须唯一。
-
第二轮同模型只读复核:BLOCK 一项(副本探针实测),B1、B3 修复成立。
- N1:单次失败路径不比对失败回单流水号与本批次指令号;只登记了提交的批次也不算同额候选,于是 A 可凭 B 指令的失败回单确认失败并释放。已修:
- 单次失败路径(确认与最终取消均调用
assertFailureFacts)及批次级失败归属,都要求失败回单流水号等于唯一已确认提交的指令号(指令号跨批次唯一); - 同额候选新增“存在任何提交登记(含撤回)”。
由于有了指令号绑定,跨批次复用失败回单在归属阶段就被拦下,
loan_failure_evidence_uses登记表退为纵深防御(测试断言 A 已登记用量)。
- 单次失败路径(确认与最终取消均调用
- 同轮修复的非阻断项:
- 归属唯一索引与查重加入
failure_scope,批次级与提交级可并存,并加 CHECK:提交级必须是失败类、只覆盖一次提交; - 单次失败路径按覆盖提交精确查找批次级归属;
- uses 表纳入回单密钥一致性检查;
- 证据查看理由改由请求头
x-access-reason(URL 编码)传递,不进入访问日志。
- 归属唯一索引与查重加入
- 新增反例:其他批次指令的失败回单走单次路径被拒,且“只登记提交”的批次算作候选;批次级与提交级失败归属并存。
- N1:单次失败路径不比对失败回单流水号与本批次指令号;只登记了提交的批次也不算同额候选,于是 A 可凭 B 指令的失败回单确认失败并释放。已修:
-
第三轮同模型只读复核(N1 修复):PASS_WITH_NOTES,无阻断;四条路径(单次失败、批次级与提交级失败归属、failure_receipt 终态事实)绑定一致。按备注补两处纵深:
- 指令号跨批次唯一改为不论状态:撤回后也不能在其他批次重新登记;
- 同一份银行书面证据(按 SHA-256)不能上传到两个批次。
记录:
- 候选范围扩大(只登记提交也算)的代价是同额历史批次让后续批次持续需要归属确认,方向安全,不放宽;
- 回单“流水号/凭证号”与网银指令号是否同一编号、两者如何对应,须用真实建行回单在 S0 核实。若不同,受影响的是需要绑定的路径——失败回单(单次失败路径、失败归属、
failure_receipt终态事实)以及处理中回单的了结,这些路径会被阻断(安全但不可用);只凭银行书面终态证据(termination_evidence)、本批次又没有需要了结的处理中回单时,不要求两个编号相等,不受影响。归属不能靠财务照抄回单号来证明;绑定只是机器校验,实际证明仍依赖银行证据、同额候选归属和独立复核。
-
部署前注意(存量):生产若已有在 S1 之前确认失败、尚未取消的借款批次,按新规则取消时会重跑 S1 条件(单次已复核提交、指令号绑定等),可能需要补登提交并复核;生产是否存在此类数据待 S0 核实。
-
记录在案(未改):
confirmed_not_paid之后若证据作废、出现晚到回单或新提交,批次保持占用(方向安全)。其中“钱确实没付、只需补证后重新复核”的情况,会被“只有unknown状态才能登记终态事实”拦住;S6 只处理晚到成功,覆盖不了这种情况。这是尚未设计的恢复缺口,需另行设计恢复路径,不由 S6 负责;- 等待期默认 3 天,可通过配置
loanReleaseWaitDays调整,尚未接入环境变量;只有手工提交、没有任何导出时,等待期不生效(按设计“距最后一次导出”计算)。
2026-10-07 S1、S2 本地实施记录(用户 2026-10-06 批准本地实施、针对性验证与只读复核;未提交、未推送、未部署;未做 S0 生产查询)
S1(迁移 20261007010000_loan_bank_submissions):
- 新表
payment_order_exports:借款批次每次导出写一条(序号、导出人、文件 SHA-256、客户方流水号、金额),只增不改。 - 新表
loan_legacy_export_summaries:迁移时回填存量借款批次已知导出次数,写明未知项(逐次明细、文件摘要、银行提交对应关系)。它不是一次真实导出或提交;存在时确认失败一律 409loan.submission_history_unverified。 - 新表
loan_bank_submissions:财务登记实际银行提交(网银导入须关联本批次导出记录),只能撤回一次,不能改。 - 新表
loan_bank_submission_attestations:财务确认“现有有效提交即全部”,独立复核人须当前有资格,且不是确认人、批次创建人、提交人、出借员工、任一导出人或提交登记人;清单变化后旧确认失效,重新确认时同事务取代。 - 确认失败:只计未作废附件(须恰为所确认的失败回单);作废附件曾被识别为成功或处理中、曾匹配、或有未驳回的人工录入,一律 409
loan.voided_receipt_unresolved;临时拦截(S3 前)——存在历史汇总、多于一条导出记录或多于一次有效提交、提交清单未经复核或已变化,均拒绝;改按付款后规则(出借员工离职不阻断,确认人按当前资格)。
S2(迁移 20261007020000_loan_failure_attribution):
- 归属确认新增
kind(settlement/failure)与covered_submission_ids;每批次每类至多一条待复核或已通过;依据类型新增“回单载明本批次银行指令号”。 - 存在同金额候选时,确认失败须有已复核、绑定失败回单证据与已确认提交清单的失败归属,否则 409
loan.receipt_attribution_required;失败归属登记前须先有已复核的提交清单。结算归属的查询全部限定 settlement 类,两类互不占位。
接口:POST /payment-batches/:id/loan-bank-submissions、…/:submissionId/withdraw、…/loan-submission-attestation、…/:attestationId/review;归属接口新增 kind、attachmentId;批次详情返回 bankSubmissions。新增 7 个原因码,三处登记。
页面:本步未做提交登记、清单复核和失败归属的界面(S8 页面整合)。S1 收紧了确认失败,界面补齐前不得单独部署启用。
验证与复核:
- 首轮针对性验证:HTTP 39 组、浏览器 7 组、76 迁移 PASS;9 个资金守卫变异均变红(其中“去掉清单复核要求”首轮未变红,因缺“已登记未复核”反例,补后变红)。
- 同模型只读复核:BLOCK,两项,均经副本实验复现。已修:
- B1 作废回单判定过宽(作废时尚未 OCR、状态不可读、状态歧义都会放行):改为“无法证明就拦截”。作废附件只有在当前版本识别为明确失败,或可读且确定不是本笔付款(金额/账户与本批次不符、无处理中或歧义标记)时才忽略;没有核验记录、未识别、状态不明、匹配过或有未驳回人工录入,一律 409。代价:无法识别的误传文件也会阻断,须以可读证据处理(留待 S3 作废复核或线下补证)。
- B2 清单批准后“登记再撤回”会让旧批准重新生效:清单确认新增
all_submission_ids,绑定全部提交行(含已撤回)及全部导出,复核后的任何登记、撤回、导出都使批准失效,须重新确认并复核。 - 同时补:确认失败人与失败归属复核人另排除全部导出人、提交登记人与清单确认人;清单复核人另排除已撤回提交的登记人;失败归属数据库层限定恰一条核验记录。
- 修复后:HTTP 40 组、浏览器 7 组、76 迁移 PASS;修复对应的 5 个变异均变红(“忽略歧义状态标记”首轮未变红,补“标记失败但带处理中”反例后变红);server 4463、prisma validate、client typecheck/build、UI strict、错误码合同、敏感扫描、diff 检查通过。
- 第二轮同模型只读复核:PASS_WITH_NOTES,无阻断,B1、B2 修复成立。按其意见加固:作废回单要判为“确定不是本笔”,须匹配结果明确不符、金额大于 0,且付款与收款账号不能都与本批次一致(同账号仅金额不同可能是本笔误读,继续阻断);作废回单逐页核对页数完整;补数据库层反例(清单确认的全部提交、导出集合不可改,已撤回提交不能恢复)。“同账号放行”变异变红。最终:HTTP 40 组、浏览器 7 组、76 迁移,server 4463 等全部通过。
- 既有问题(第二轮复核发现,自 09-06 即存在,方向为拦截;已按下条口径修复):真实 OCR 只要页面带任何问题标记就整体判为
needs_review,失败回单必带transaction_failed,而failedReceiptFact要求recognized。因此用真实 OCR 时“确认失败”永远返回 409,作废失败回单的放行分支也是死代码。测试夹具伪造了真实识别器不会产出的“已识别且带失败标记”结果,正向用例没有覆盖真实路径。修正需定义失败回单的识别口径(如仅允许唯一问题为transaction_failed),属资金规则,待用户决定;在此之前生产中任何银行失败都无法在系统内确认。 - 失败回单识别口径(用户 2026-10-07 同意并入 S1/S2,口径为 4 种失败措辞):
- 归一化新增
transactionStatusRaw(银行原始状态措辞),随核验结果存储;匹配逻辑不变,报销与成功核销不受影响(相关共享单测 237 项通过)。 - 不改顶层识别状态。失败事实另用严格判定
isClearBankFailure:单页且页数完整;状态为失败且原始措辞属于“交易失败、转账失败、付款失败、支付失败”;唯一问题标记为transaction_failed;金额、币种、双方账号、流水号齐全;再经与冻结快照匹配。它只用于确认失败,不能用于成功核销,也不绕过提交清单、失败归属与独立复核。“已撤销”“已冲正”“已退汇”不接受,分别留给 S3 指令终态与后续退款对账流程。作废回单中的失败页也按同一判定,否则继续阻断。 - 测试改走真实处理链:只替换云端
BankSlipOCR响应,从合成银行字段经 PDF 解析、recognizePaymentReceipt、normalizeBankSlip、核验存储、匹配与认领。仅两个纵深防御用例显式使用合成归一化结果(作废路径“失败但带处理中标记”、确认路径“失败但另带账号歧义标记”),二者真实归一化无法产出。新增用例:“转账失败”可确认;“已撤销/已冲正/已退汇”、缺流水号、两页回单、金额不符、带额外问题标记均拒绝;作废的“已撤销”回单继续阻断。 - 变异:接受任意失败措辞、要求顶层 recognized、作废失败页不按严格判定三者变红;“忽略多余问题标记”“跳过字段完整性”未变红——下游
matchBankSlip对任何剩余问题或缺失字段都会判不匹配,二者为纵深防御,测试无法单独区分。 - 结果:HTTP 41 组、浏览器 7 组、76 迁移,server 4463、client typecheck/build、UI strict、错误码合同、敏感扫描、diff、治理检查均通过。真实建行回单接受性仍待验。
- 只读复核(同模型):BLOCK 一项——同页两个状态字段(如“交易失败”与“已撤销”,都归一化为失败)不被判歧义,原始措辞只取首个字段,按 OCR 字段顺序可绕过白名单(复核实验证实)。已修:仅当所有状态字段原文完全相同时才记录
transactionStatusRaw,否则为空即拒绝;transactionStatus与问题标记不变,报销与成功匹配不受影响。补用例:两种字段顺序的“失败+已撤销”均拒绝、作废的“失败+已撤销”回单继续阻断、“付款失败”“支付失败”正向用例。其余检查(原文可靠性、严格判定、成功路径未放宽、测试走真实链)复核成立。
- 归一化新增
- 复核其余非阻断(留待 S3/S8):导出记录未被手工提交关联时仍可确认失败(S3 须落实每条导出都关联已终止提交或人工确认未提交);失败归属状态与提交登记、清单复核无界面;部分反例未覆盖(导出失败时导出记录回滚、回填 SQL 在有存量时的效果、报销导出不写导出记录)。
2026-10-06 对账方案实施拆分(依据 design 第 3 版;待用户批准,未实施)
通用规则:
- 每步只做新增型迁移,均涉及资金规则,完成后必须只读复核。
- 每步可单独验证、单独提交,但不代表可以单独部署启用。部署时机另行批准,提交须单独确认。
- 验证按改动范围安排:相关的数据库、HTTP、权限与并发回归,加上针对资金守卫的变异测试;改到共享付款路径时扩大回归;阶段完成后再跑完整前后端测试。
- 完整的释放条件在 S3 之前尚未实现,所以 S1、S2 不得放宽任何释放结果,只能修正误判并保留拦截(见 S1 第 3 条)。
| 步骤 | 内容 | 对应 | 依赖 |
|---|---|---|---|
| S0 前提核实(不写代码) | ① 生产有无真实还款与存量批次(只读查询须用户当轮授权);② 是否至少有 2 名与单据无关、当前有资格的经理或总经理;③ 建设银行能否出具“指令查询”官方 PDF,含查询无结果的情况(用户线下确认)。三项均不默认为已满足;不阻塞本地合成开发,但②③决定 S4 能否启用,①为上线前必须完成的存量核实 | AC16、AC12 | — |
| S1 导出与提交记录、确认失败修正 | 1. 新增制单导出记录表(序号、时间、导出人、文件摘要、客户方流水号、金额、快照摘要),每次导出写入。 2. 新增银行提交尝试登记(财务登记,关联导出记录与银行指令号),提交清单须经独立复核。 3. 确认失败:只计未作废附件,但作废的成功或处理中回单仍阻断;同时保留拦截——批次存在多于一条导出记录、提交清单未经复核、或清单中不止一次提交时,一律拒绝确认失败,留待 S3 的逐次终态规则处理。 4. 确认失败改按付款后规则:核对冻结快照,不要求出借员工在职,当前操作人按当前资格。 5. 存量:保留已知的 payment_order_export_count,新增“历史导出汇总”标明逐次明细、文件与银行提交对应关系待核实;该汇总不是一次真实导出或提交,存在它的批次在确认失败与释放时按“提交未明”拦截 |
R2、R4、AC9、AC16 | — |
| S2 失败归属 | 归属确认新增 failure 类,须写明覆盖的银行指令并绑定失败回单证据;存在同金额候选时,确认失败须有已复核的失败归属,否则保持占用;S1 第 3 条的拦截继续有效 |
R3、AC10 | S1 |
| S3 银行终态确认与释放 | 新增 terminated 类与 confirmed_not_paid 状态(含触发器);释放条件:已复核提交清单中每一次提交都有覆盖它的终态或失败证据,每条导出记录都关联已终止的提交(或有 S4 的人工确认),且无未解决的成功或处理中事实;之后取代 S1 第 3 条的临时拦截;释放后禁止再导出,页面提示原制单文件不得再导入网银 |
R1(银行确认)、AC11 | S1、S2 |
| S4 人工确认未提交(Q6) | 新增 not_submitted 类与 confirmed_not_submitted 状态;全部证据加两名不同的独立复核人;记录与页面标为人工确认;人员不足或材料缺失时继续占用 |
R1(人工例外)、AC12 | S3;能否启用取决于 S0 ②③ |
| S5 冻结原因与解冻 | 新增冻结原因表(类型、来源、状态、关闭依据);冻结拦截该出借人的新申请,以及其他在途申请的复核与导出,放行事实登记;误报原因经独立复核关闭;全部原因关闭才解冻 | AC13 | —(S6 的前置) |
| S6 晚到成功补记 | 晚到事实只增不改、标记原结论被推翻;登记即产生冻结原因;按冻结快照与历史审批核对;逐笔先处理占用冲突,再按差额结清,余额生成待追回原因;补记还款不生成付款批次、不可导出;覆盖已释放与已确认失败未释放两种情况 | R5、AC14 | S3、S5 |
| S7 追回与解冻 | 凭到账回单经独立复核登记追回,支持部分追回,全额后关闭对应原因;本期不支持冲抵 | AC15 | S6 |
| S8 收口 | 页面整合与手机端走查;恢复手册补充;完整前后端回归;把 AC9–AC16 的验证结果与剩余缺口回填到 PRD 与本文件 | 全部 | S1–S7 |
2026-10-06 C 回单批次归属保守拦截(用户批准实施;本地合成,未提交、未部署)
规则:同一出借人、同金额的其他借款批次只要曾导出制单或上传回单(含确认失败后已取消的),本批次的匹配回单就不能证明归属。
- 最终拦截在
settleLoanRepayment(assertReceiptAttributed):执行事务内claimVerifiedReceipts已为本项生成交易指纹认领,OCR 匹配与已通过的人工回单复核都经过此处;只有绑定同一交易指纹、且覆盖当前全部候选批次的已复核归属确认才能放行,否则 409loan.receipt_attribution_required,本金与占用不变。 - 确认银行失败:存在候选批次即 409,不释放占用(失败回单暂无归属确认路径,留待对账流程设计)。
- 归属确认与人工回单复核分离(新表
loan_receipt_attributions,迁移20261006010000_loan_receipt_attribution):财务登记依据类型(客户方流水号、附言含批次号、银行书面查询结果、其他候选均已对应其他交易或确认未付;不含“时间吻合”)+ 依据说明 + 排除其他候选的理由;绑定claimVerifiedReceipts(readOnly)计划认领的交易指纹和当时候选集合。独立复核人须当前有资格,且不是登记人、制单人、提交人或出借人关联员工;批准时回单证据或候选集合变化即拒绝。出现新候选后原批准失效。DB:每批次至多一条待复核/已通过(部分唯一索引)、复核人≠登记人、已复核记录与提案字段不可改、禁止删除。 - 页面:还款详情显示候选批次与归属状态,财务登记、经理/总经理独立复核;说明“时间吻合只能作辅助说明”。
- 代价:此后同一出借人同金额的正常还款(如固定金额分期)都需走归属确认。精确关联(附言写入批次号、OCR 提取客户方流水号/附言)待获准的真实建行回单样本确认字段后再做。
验证:
RUN_ISOLATED_LOAN_DB_TEST=1 RUN_ISOLATED_LOAN_BROWSER=1 node scripts/qa/test-company-loan-db.cjs:74 迁移,HTTP 27 组、浏览器 5 组、DB 约束全部 PASS。原两个复现用例改为回归断言:错误回单执行 409 且本金/占用不变;C2 经 OCR 与经人工回单复核均被拦。新增:正确回单在有候选时同样需归属确认、确认后核销成功;重复登记 409;“时间吻合”类型 400;登记人兼经理不能自审、驳回后仍拦;新候选出现使批准失效;歧义失败回单不能释放;无候选时不需也不接受归属确认;已复核记录 DB 层不可改/删。- 5 个变异(去掉核销拦截、候选排除已取消批次、去掉失败拦截、覆盖校验恒真、允许登记人复核)均变红,源码已恢复。
- server 4456 通过;prisma validate、client typecheck/build、UI strict、错误码合同通过。
- 首轮同模型只读复核:BLOCK——已批准的归属一旦因新候选或换回单失效,既不能重新登记(exists)、也不能改(触发器)、又因已导出不能取消,占用永久卡死并阻塞出借人维护(复核人副本实测成立)。已修:新增终态
superseded(及superseded_at),重新登记时同一事务内把失效的待复核/已通过记录标为已取代;触发器只放行 proposed→approved/rejected/superseded 与 approved→superseded,复核字段不可改。同轮按非阻断意见补:复核人另排除导出制单人与所认领回单的上传人;receipt-readiness在需归属确认时返回ready:false, receiptAttributionRequired:true;状态返回stale(回单或候选已变化);页面在失效时允许重新登记、财务按钮要求loan.manage,并写明同额分期每期都需确认、存在同额候选时失败回单不能释放额度须线下对账。新增回归:失效批准被重新登记取代后核销成功;换回单后旧批准不能放行、导出人兼经理不能复核、重新登记后核销成功;已通过不能改为驳回、已取代不能复活。3 个变异(不取代、复核不排除导出人、就绪不检查)均变红。 - 第二轮同模型只读复核:PASS_WITH_NOTES,死局已解除,无阻断。按其意见加固:复核人另排除同一交易所有回单的上传人及人工回单提案人;驳回不再依赖回单(无回单时待复核记录可关闭);无已核验回单时登记返回
loan.receipt_attribution_unavailable,状态返回receiptAvailable,页面不显示无效的登记按钮;批次详情中的归属展示在回单重建异常(如密钥不一致)时降级而非 500;触发器禁止未复核记录写入复核字段;取代审计记录原因(交易变化/候选变化)。新增回归:人工回单提案人不能复核归属、独立人员批准后核销;回单作废后待复核记录可驳回、重新登记返回 unavailable。 - 后续项(第二轮非阻断 5):存在同额候选且银行确实失败时系统内无释放路径,需设计线下对账结论回写(如复用归属复核确认失败),与 unknown 解除、作废附件计数、晚到结果一并处理。
- 复核其余非阻断(未处理,记录):已执行的历史同额批次永远是候选,等额分期从第二期起每期需确认,且一旦银行真实失败将无法确认失败、释放占用(与“失败归属/对账流程”一并后续设计);部分唯一索引、CHECK、触发器不在 Prisma schema 中,今后
migrate dev/diff 可能误报漂移(推测,仓库已有 r46 先例);ON DELETE RESTRICT使带归属记录的批次/员工无法物理删除(当前无此路径)。 - 第三轮补齐(用户转述的复核意见指出前述回执遗漏的三处):
- 证据绑定:归属记录新增
verification_ids、manual_proposal_ids(迁移内同表,提案后不可改),批准与核销均要求与当前计划认领的证据集合一致;同一交易重新扫描或重新人工录入即失效,取代审计原因记为receipt_evidence_changed。核销处在执行事务内以只读方式重建计划认领比对。 - 并发窗口:借款批次回单上传在批次锁后取出借人锁(批次→出借人,与既有链一致),与核销的候选检查串行。确定性测试:独立连接持出借人锁,两种排队顺序分别验证“核销在先→200、随后上传成功”“上传在先→核销 409”。去掉上传锁的变异使排队断言确定性变红。
- 浏览器:PC 端两个独立登录会话完成财务登记→经理独立复核→新增同额候选后显示“须重新登记并复核”→重新登记→再次复核→核销 200;登记人看不到复核按钮、复核人看不到登记按钮。测试环境整页刷新会丢会话,改用每步新会话。
- 验证:HTTP 32 组、浏览器 7 组、74 迁移全部 PASS;去掉证据绑定、去掉上传出借人锁两个变异均变红;server 4456、prisma validate、client typecheck/build、UI strict、错误码合同、敏感扫描、diff 检查通过。
- 证据绑定:归属记录新增
- 未覆盖:手机端未操作归属弹窗(与 PC 共用组件,仅 PC 浏览器覆盖);真实回单字段;独立复核仍为同模型。
2026-10-05 复核阻断 B1 修复与回单归属复现(用户批准 A/B/D/恢复手册 + C 复现调研;本地合成,未提交、未部署)
背景:同模型只读复核(页面与剩余资金流程)结论 BLOCK:在途还款期间做出借人身份/账户维护会使 identity_version 变化,之后登记付款、取消、确认失败全部被拒,已付款项永久无法登记;导出后原审批人或出借员工离职同样卡死。另报回单批次归属未校验。
实施:
- A(
services/companyLoans.jsassertLenderNotInFlight,routes/companyLoans.js两个维护接口):出借人锁内只要存在reserved分配即 409loan.lender_in_flight。新建还款先锁出借人再占用,故与维护互斥;导出/上传不新增占用,不需改上传锁。出借人列表新增hasInFlightRepayment,页面禁用两按钮并提示;账户弹窗误导文案已改。原因码已登记三处(server registry、client 映射、内容断言夹具)。 - B(
services/companyLoanPayments.jspostPayment):回单 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 test226 文件 4452 通过;prisma:validate、clienttypecheck/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-r215/15;loan-unit-r35文件212/212,ERP退出后的付款路由另在erp-regression-r2128/128通过。final-client-buildtypecheck/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未勾选。
- 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本地日期/错误治理候选也未部署。恢复风险处置、方案实施审阅及独立复核依然是进入条件。
- 复核当前枚举只有reimbursement/travel_order,以及readiness、回单验证、人工复核和OCR worker对reimbursement的明确限制;记录下方消费者分组,不借新增来源解冻travel_order。
- 补迁移/锁序的待审技术切片和验收出口,前端沿既有布局,不新设计视觉体系。
- 技术定稿T1:提出四类核心表及专属借款证据关系的字段/索引/FK/版本设计;按当前PaymentBatch/ReceiptClaim实际锁图审查,先以最小合成schema验证约束及并发,再实现接口。
- T2:出借人/原借入登记及财务确认,只用合成资料;不自动产生付款或新增真实收款。
- T3:新来源显式支持/拒绝矩阵、额度占用/幂等/状态与回单闭环;逐消费者负例后再接页面,不凭新增enum编译成功宣称支持。
- T4:真实认证的本地路由/数据库/浏览器全链及旧报销/差旅回归,形成独立审阅候选;新来源OCR真实样本和生产录入仍另批。
这四切片复用原8项AC,不降低审批人独立性、并发不超付、在途保持占用、全局交易去重和审计原子性。日期/错误债务后续批次、恢复事实与借款开发分别交付,不要求22个历史task全部结案,但也不默认接受未知密钥风险。