文件
hyb-oa/.trellis/tasks/archive/2026-09/09-05-error-explainability-payment-readiness/design.md
T
wangsli 750a184b8a
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
归档10-05错误码可解释性与付款就绪任务(09-05-error-explainability-payment-readiness)
591条历史豁免基线已清零,794条新增reasonCode已通过候选分支合并落地至
origin/main(46a70aa5),主链路零例外,无剩余阻塞验收项。
work landed via 已删除的候选分支而非专属分支,故用
--skip-branch-validation 归档。
2026-09-26 09:12:15 +08:00

26 KiB
原始文件 Blame 文件历史

Design:错误可解释性与付款就绪治理

B34 实施前解析器分类补充

实际依赖合成观测见 import-parser-fix-20260917/library-observations.json。仅普通 Error 的确切格式进入白名单:fast-csv 默认引号未闭合/引号后缺分隔符;JSZip 非 ZIP 的完整固定提示/缺少中央目录结尾;saxes 带行列前缀的未匹配闭合标签、未定义实体、无引号属性值。白名单按 CSV/XLSX 分开,未知消息、非 Error、TypeError、带其他内部故障形态均保留 500,并替换为无原异常引用/cause/自定义属性的固定 Error。白名单不声称覆盖依赖的所有损坏输入,新增格式须有真实库复现。

catch 只包两个解析 await,不包表格归一化、toBuffer、preview 或 apply。合法 CSV 的 map 原样保留文本,正常 XLSX 仍使用现库。测试抽取 app.js 原 error-handler 回调作响应/日志核验,不 import app/config 或启动 DB/jobs;合法导入继续跑原真实哈希测试,不用 mock 哈希换绿。

2026-09-17 考勤职责与 D15 优先级更正

依据用户“考勤功能在企微”的澄清,以及 docs/产品设计规则.md 的主办边界与考勤页规则,日常考勤由企微承办。client/src/pages/AttendancePage.tsx 已明确 OA 只展示摘要、解释、同步状态和审计;/attendance/monthly 是 OA 侧汇总查询,不是日常打卡入口。源码保留入口不能证明生产启用或真实使用。

下方 D15 的低年份观测继续保留,但退出当前必修/待决策清单,作为非阻塞技术记录。2000–2100 方案未获采纳,不实施新年份限制、不恢复旧 OA 打卡、不扩修待精简工资。今后只有摘要查询出现明确业务需求或实际故障证据时再评估;不能把此项处置扩大为删除企微同步、摘要或审计能力。B34 与 D16 原处置保持。

2026-09-17 三类余项的在用性与限定方案(已完成确认,产品未改)

本次批准为范围确认及先行规划,采用acceptance-boundaries-20260917/boundary-observations.json的合成观测,不把问题复现算修复通过。未新读真实配置/使用量,所称在用入口表示当前产品/源码保留入口,不证明今天的生产开关或使用频次。

B34 损坏账号导入:下一本地优先修复方案

账号管理CSV/XLSX导入仍为保留能力,不属于ERP或工资待精简分支。routes/users的dry-run/apply共用readUserImportPayload:文件尺寸/扩展名/MIME已验证,但ExcelJS的csv.read与xlsx.load异常未映射。原错误handler对非AppError返回500/SYS_001并记录原err;合成未闭合引号CSV、非ZIP XLSX、截断XLSX在两入口共6例均500,CSV两例原err.message含合成单元格标记。9个路由探针(另含两空表头文件及权限拒绝)全部数据库调用0,接口无标记泄露。此为可解释性和日志边界缺口,不声称真实内容已经泄露。

限定修改范围:users解析边界、新原因的server/client/固定夹具三方,以及users.import定向回归;不修改全局error handler、所有导入器、上传限额、员工权限或apply事务。拟新增user.import_file_invalid,400/VALID_001、details仅固定file=invalid_format,用户提示重新导出CSV/XLSX;不包含文件名、sheet/cell、原解析异常/cause或数据行。现有missing_headers/empty/row_limit_exceeded/大小错误及其优先级保持。

实施步骤:先以实际依赖可识别的CSV语法和ZIP/XML格式错误建立白名单及反例,只在内存buffer解析两个await处翻译;未知解析器/程序异常继续500,但换成无原message/cause的固定内部错误后交日志,不能把任意故障伪装成输入错。toBuffer读取故障、权限、事务/数据库/哈希异常不得被这个catch吞掉。可识别异常策略须在写产品前用现有版本补齐,不能仅按任意message包含csv/xlsx猜测,也不全局catch所有Error返回400。

验收矩阵:dry-run/apply × 未闭合引号CSV/非ZIP/截断XLSX/坏XML;合法带引号换行CSV和真实生成XLSX/日期文本/空值/500与501行保持;原7个文件原因/413来源映射保持;权限拒绝先于解析;未知异常仍500且日志/响应均无合成单元格或原exception,读取失败不改分类;格式失败不开始preview/transaction/员工部门角色/成功审计。合法apply仍跑原真实哈希用例,串行避免旧超时。验证users.import、errors-client固定映射、strict/self-test、node --check、前端typecheck/build与治理。没有新数据库结构、外联或真实导入。

D15 极低年份:分开旧代码与保留入口

parsePayMonth及统一考勤parseMonthRange对0000/0001/0099分别映射1900/1901/1999,0100/1900/2024正常;共享date-only字符串解析保留字面低年份。旧attendance服务buildMonthRange已有2000–2100限制且attendance_v1硬关闭,不存在该低年份入口,不能为验证打开它;未使用shiftMonth也不扩修。工资属于既有retirement-review候选,按用户取舍本轮不补修工资/工资导出。

统一考勤/attendance/monthly仍有页面/route入口,不能整文件以旧考勤名义排除;此为只读查询年月与边界不一致,保留低优先级决策。推荐后续仅该外部年月采用与旧业务月查询一致的2000–2100明确范围;这是新接受年份规则,须单独确认后才写代码。备选为保留四位公历年份并正确构造UTC界限,需另核0000/真实PG支持与跨世纪闰年,不宜未经决策全局替换Date.UTC。均不改历史年月/日期,不推断生产存在低年份数据。

D16 AP反向区间:范围确认后维持现合同

ApOperationsPage将ledgerDateFrom/To分别传列表与导出,共用financeLedger构造gte/lte。两端为有效日期但from>to时继续200,谓词同时成立无匹配;不交换日期、不忽略其中一端,deleted_at过滤仍保留。73项现有AP列表/导出回归通过;探针只实测共享where构造,不冒称真实PG空集。日期本身非法仍400,pendingCreatedAt反向范围的原400与ledger不是同一合同。

当前不列为必须修复项。若以后需要输入体验提示,必须同批覆盖页面、列表、CSV/XLSX导出及原因三方,把200改400作为显式需求;不可只在共享where偷偷改变规则。不新建视觉方案、不改权限/金额/写入,也不需真实数据验证本次保持结论。

G8按在用路径收口

按implement顶部B31–B33合同处理57处,17处ERP旧分支按用户最新指示跳过并保留源码/基线。其依据为产品设计规则61/89及企微路线图37;通用outbox有notification.im消费者不整文件跳过。当前权限/状态/编号/开关/认证业务规则保持,只本地合成。所有旧材料保护、独立PENDING,不读真实配置密钥/外联/提交部署或实施借款。

G7本地错误合同接续

查询考勤周报八源42处,按implement顶部B29/B30逐操作合同实施;三方固定提示、精确减基线、实际路由/服务负例和合法回归、页面安全消费及保护新候选。legacy考勤硬关闭保持,内部路由用合成门禁桩分层验证;周报项目开关失败前原update尝试保持。独立PENDING,不扩权限/状态规则,原真实数据/外联/提交部署边界不变。

G6实现边界

共享审批原步骤/角色/兜底/人员上下文守卫分别注册原因,动态主管失败沿固定安全提示,不拼角色ID或链内容。流程定义与审批规则schema由调用方显式传原因;原快照、权限、锁、状态、发布/审计和金额规则保持。不可达防御仅静态核对,不通过改规则制造测试覆盖。B28a仅把委托本人范围和有效期筛选从覆盖式object spread改为AND组合,保留每一原谓词及管理权限来源;结构核验显式单列此处,路由内存过滤负例证明普通用户不会得到他人有效委托。

Bug Analysis: 委托列表同名OR覆盖

1. Root Cause Category

  • Category: E/D - 隐含对象合并假设与测试缺口。
  • Specific Cause: 期望本人范围OR与有效期OR同时成立,但后置spread按键覆盖前者;原默认includeInactive=false触发。

2. Why Fixes Failed

无历史修复证据,不编造失败史。本轮先保留4个真实Fastify/合成内存过滤红例,唯一AND组合修复后8个范围用例及全34项委托用例通过。

3. Prevention Mechanisms

Priority Mechanism Specific Action Status
P0 结构 两个已有谓词放入AND,保留管理权及原日期边界 DONE
P0 回归 默认/false/0与true/1、本人/他人、管理员过滤、开始/结束等时边界 DONE
P1 规约 backend-fastify-prisma记录同名OR合并与消费where的测试要求 DONE

4. Systematic Expansion

本轮只对baseWhere/scopeWhere/permissionWhere传播作源码定位,未做全仓授权审计,不声称不存在其他组合问题。无通用查询框架改造;后续可见性条件变更应保留权限对象并组合筛选。模拟findMany不能无条件返回固定列表来证明数据隔离。

5. Knowledge Capture

  • 更新现有后端spec、当前design与implement;无新计划系统。
  • 本仓无src/templates/markdown/spec目录,不生成Trellis工具模板。
  • 独立只读内容复核PENDING;遵照用户不提交要求,不执行技能默认commit。

G5接续设计

合同schema由四操作显式传原因,版本/终止/归档/纠错/续订守卫保留status和事务位置。采购预算先写流水后查池、release缺池继续的原语义不改,默认409显式传给新builder;仅无剩余消费者时删除旧导出。测试区分已尝试写入、无后续额度/成功审计和mock事务恢复,不能冒称真实PG回滚。

资产分类/卡片/索引schema和人员角色原因由调用方明确给出;流转与盘点原状态和循环写入位置保持。采购上传策略仅用既有PurchaseAttachmentPolicyError.reasonCode白名单映射(未知用固定安全兜底),下载构造保留旧message/status/details.reason与必要审计。AST批量迁移需识别shorthand statusCode属性,不能因缺initializer误用默认400;本批通过下载409及原文案路由断言证明。采购金额规范化前原主表update/明细delete和预算前原重算写入不改变。

G4差旅实现设计

申请list/id、create/patch/link-project输入及既有状态/财务维度/预检/流程分支分别注册原因。link-project原parseUuid无定义,三个真实Fastify合成用例先复现非法/绑定/解绑均500,再用parseTravelRequestId修复并回归原404/403/开关守卫;不新增项目关系或状态限制。CJS语法检查不能发现运行时未定义函数,保留这组路由回归作为防复发证据。

订单/授权/交易导入共享禁用原因,各类schema和空归一化分别解释;标记付款保持精确结算交易匹配,冻结建议仍只记录建议。travelPayments缺池保留409,授权/冲正先ledger再查池,结算原仅ledger不查池/改额度。对账路由与服务旧helper默认409,迁移均显式保持;只有原schema/id错误400,原存在性校验不额外限制启停。原helper全部消费者迁移后删export/import。

七源结构检查仅排除错误构造/原因参数及已单测的ID解析器修复,原权限/状态/副作用顺序/事务保持。主会话本地证据,独立PENDING。通知、预算、流程参与者只用桩,ERP仅mock DB outbox,不声称真实发送、PG回滚或开关开放。

G3基础资料实现设计

共享schema由调用方显式给操作原因;动态参数经getErrorReason校验,所有原因在服务端、客户端固定映射与断言夹具三方登记。四主数据实体各有id/list/create/patch/空修改原因,跨模块相同公司引用拒绝复用原因;原编码规范化、层级/归档和P2002映射范围保持。日历日期替换保持500项、空数组清空、默认日历绑定与先验后删顺序。

费用标准保留合并旧范围后校验的PATCH语义,假别保留原空PATCH和嵌套policy更新,模板保留50项、禁用类型原索引详情及软删除幂等。项目14种schema、7类id、5类开关、列表和豁免备注分别明确;收口项原先初始化再验id/body顺序保持并单独合成实证。项目日期仍只有原格式校验,本轮不扩日历规则或真实功能开放。八源AST去除错误构造/原因参数后业务结构一致,只作主会话辅助证据。页面沿既有安全resolver;假别写API无现有页面调用、费用类型仅有读取客户端,不能声称完成这些管理页面。

B11–B14实现边界

预算范围和选池沿用原优先级,控制规则PATCH仍按提交body判断;账号唯一冲突详情继续兼容但客户端不拼数据库字段,密码策略与角色/会话操作不改。部门层级/归档只替换错误构造;员工各schema由调用方显式传入注册原因,分别标识合同、培训、证书和生命周期操作。

withUploadSizeReason仅包住员工上传request.file与toBuffer,精确捕获FST_REQ_FILE_TOO_LARGE→原400/VALID_001/file=file_too_large,其他异常原样。合同下载构造器使用注册原因后恢复原安全message“合同附件未通过安全校验”,409及阻断审计保留,不泄露文件字节。六源AST结构对照证实原守卫、数据访问、权限和事务未变;这些为主会话本地证据,独立仍PENDING。

B10路由原因与全量分组

预算13分支使用显式budget原因;绩效12原因中parseBody由创建/修改/评分操作显式传入,并通过getErrorReason校验,已有活动周期预检和P2002共用同一原因。移除两个无消费者的legacy builder,不改预算共享服务、schema、状态判断或守卫顺序。页面复用既有resolver;P2002测试只证明异常映射,不证明真实PG并发约束。全部546处按implement顶部互斥文件组持续收敛,详细操作合同在每批实施前补齐。

B6/D13/D14/B7–B9连续本地设计

B6保持上传原生产400合同,分别捕获取得filePart与消费toBuffer时的文件过大异常;7原因不涉及文件名/内容拼接,其他异常原样。D13证实月份00/13已有后置拒绝,只补路由/UTC月界证据;低年份Date.UTC映射另列,并未改可用年份范围。D14在公告原schema候选之后检查本地日期部分与finite Date,避免仅验ISO前缀;不拿UTC日与输入日相等作时区校验,因此跨UTC日期偏移仍合法,原无偏移/24:00滚动兼容保留。

B7–B9把公告和工资现有拒绝分支按操作注册原因;parseBody所需原因由每个调用方显式传入,删除这两个文件已无消费者的legacy builder;attendance/exports则保留可选原因,防止给其他域贴错提示。原权限、状态判断、数据库查询/锁/事务/金额规范化代码不变。公告创建/更新/归档/签收复用既有安全resolveErrorMessage及toast;工资页面本来已消费resolver,无额外UI改造。P2002冲突只是数据库桩测试,不虚报真实并发/回滚。累计新增36原因,审阅与恢复/生产交付门禁继续分开。

2026-09-17 D12/B5实现设计

D12将HR原多格式转换与日历有效性分开:canonical日期用既有isValidDateOnlyString判定,normalizer同时保留hireDateInvalid,不能将非法null解释为缺失。processProfile在原缺必填/非active守卫之后、resolveDepartment之前整条skipped/invalid_hire_date;对直接注入sourceProfiles的hireDate再校验。合法来源、新建缺省now及现有员工不改hire_date保持;运行/item审计允许,业务实体和主管同步不得消费非法项。

B5按明确操作选择7原因。合同和在岗共享legacy错误helper还被写入/冲突使用,故只迁移筛选服务具体分支;员工/合同导出外层schema另显式传域原因,经getErrorReason校验后调用business builder。其余导出不传参数,保持旧合同;不按details动态推断、不改变导出/权限/31天规则。原因注册/client/fixture及只减的baseline作为同批审阅输入。

2026-09-17 D1–D4执行边界

沿implement中已落盘的四批日期规划继续,统一复用日历谓词但仅在各已核外部schema串接refine,保留原regex、nullable/optional、权限守卫及业务写入顺序。todos两处dueDate、员工共享筛选及导出、节假日整批items、仪表板与AP导出日期分别验证;导出共用DATE_ONLY_SCHEMA保持旧定义,其他域不能被无意扩修。

非法节假日必须在解析整批时拒绝,事务/清空/新增/审计均未调用;合法批次仍按原事务写入,不以mock声称真实数据库回滚。AP pending反向区间保留400;ledger反向区间原无拒绝守卫,另待范围规则审阅,不在本批改变。员工/users与/employees共享服务,权限判断原顺序及最小目录DTO保持;日期输入修复不授权读取或修改真实员工资料。

验收为本地合成Fastify路由与已有回归、语法/合同及治理检查;不会启动真实DB、读取环境配置或触发消息。新结果/候选按新目录保存;上一轮候选与未提交修改继续保留,不把主会话自检计为独立复核。

2026-09-17 B1/B2小批设计

B1沿既有isValidDateOnlyString窄谓词:在四个高风险外部路由的原字符串regex之后refine,再保留原optional/nullable外层;区间先保证两端都是实际日历日期,再走原顺序约束。周报必须在周一归一化之前验原始输入,在岗按写入/查询各入口追踪。服务层二级消费者只有查明外部来源才补闸,不统一改转换器或批改存量。

B1每组锁定原HTTP状态、权限、workflow及事务调用次数;无效日期不能进入写入、通知或成功审计。日期函数已有测试复用,并补各真实路由负例,避免只测正则/复制schema。合同/采购等冻结业务只修输入契约,不开入口或改开关。

B2按现有检查器的实际指纹/上下文分组,不把612次历史计数当作待修bug总数。新迁移采用buildBusinessValidationError,保留status/code/details;动态OCR字段、密码规则和催办时间沿已审窄投影及服务端负载合同,不以注册静态句覆盖动态指导。异常正文、银行数据和未白名单字段不能进入提示。

回退按单一小批补丁进行,不新增迁移、不改历史数据;原因码、客户端映射、固定文案夹具、对应测试和只减不增的基线处置作为同一交付单元。新发现需要修改审批资格、状态机或付款语义时停止并另审,不藏在提示治理中。到期延期只允许逐项理由/负责人/复验条件经批准后变更,禁止集中改日期。

本轮落点与审查边界

B1a四路由加合同查询共享服务contractRegistryFilters;该服务也接合同导出,属于已证实外部输入,复用同一守卫。B1b两路由加exports的PRESENCE_HISTORY_EXPORT_QUERY_SCHEMA,限定在岗导出日期,不改所有导出共用日期schema。presenceHistory仍只处理由已校验入口或内部当前日期传入的值;其他导出/待办等日期另列后续消费者,不在本批临时扩修。

B2当前扫描229注册/316已迁移/612遗留、主链例外0。选取通知列表/渠道管理、员工待办及门户开关提示这一小批,逐固定原因码迁移原调用,不更改通知投递、权限、状态或业务开关;门户未使用的通用validation helper可删除。三方文案与真实路由负例整批校验,仅移除实际消失的AST指纹,原owner/expiresOn逐条保留。通知测试使用现有合成渠道,不调用真实企业微信。待办日期溢出属于另一个输入批次,先登记,不借提示迁移扩大行为。

1. 总体边界

本任务不把全部 VALID_001 重构成新异常体系。保留 HTTP status、顶层 code 和既有 details,在已迁移错误中增加稳定 details.reasonCode,用注册表、遗留指纹基线和 focused 测试形成只增不退的 ratchet。

服务端业务事实
  -> 原因码注册表 / domain validator
  -> AppError { code, details: { reasonCode, ...legacyDetails } }
  -> ApiError(保留 requestId)
  -> 原因码中文映射 / 页面专用投影
  -> 就近提示 + 动作禁用 + 安全兜底

2. 原因码注册表

服务端建立唯一原因码注册表模块,例如 server/src/constants/errorReasons.js。每项至少包含:

{
  code: "payment_batch.legal_entity_required",
  domain: "payment_batch",
  audience: "user",
  defaultMessage: "报销人尚未维护所属公司,请联系管理员补充后再安排付款。",
  recovery: "contact_admin",
}

客户端维护显式、可测试的 reasonCode 映射。静态提示可使用注册表默认中文;涉及数量、页面定位或权限差异的提示由窄化 renderer 处理,但必须有默认安全提示。服务端使用常量或经注册表校验的 builder,不散落裸原因码。

兼容响应继续使用 VALID_001,并同时保留 legacy details:

{
  "error": {
    "code": "VALID_001",
    "message": "参数校验失败",
    "details": {
      "reasonCode": "payment_batch.legal_entity_required",
      "legalEntity": "single_legal_entity_required"
    }
  },
  "requestId": "..."
}

新 UI 不使用该 message 作为用户文案来源。未知 reasonCode 走安全兜底,并由现有 ApiError.requestId 附加排障编号。

3. Parity 与遗留基线

新增 scripts/qa/check-error-reason-contract.mjs,使用仓库已有 parser 解析 JS/TS,而不是按 key 或行号做字符串计数:

  1. 注册表唯一、命名和元数据完整;audience=user 必须有客户端映射。
  2. reason-aware builder 的原因均已注册;客户端无孤儿映射。
  3. 泛化 buildValidationError / new AppError(...VALID_001...) 调用若没有 reasonCode,必须命中版本化遗留调用指纹。

遗留基线放在 QA 合同附近,例如 scripts/qa/error-reason-legacy-baseline.json。按业务域/文件组记录 owner、reason、expiresOn 和规范化 AST 节点形状指纹;指纹必须忽略空白、缩进、换行和纯格式化差异,源码文本与行号仅用于报告,不参与身份计算。首批主链路 operation 单列为 zero-exception,命中遗留也失败。self-test 用临时 fixture 验证新增、删除、拼写、结构性指纹变化、纯格式化不变、过期和同 key 跨域。

这避免两类假门禁:只比数量可被“一增一删”绕过;只比 details key 会把不同业务语义误判为同一覆盖。

4. 首批迁移边界

首批原因域:

  • reimbursement.*:提交、草稿编辑、票据关联/恢复。
  • payment_batch.*:候选/组合 readiness、创建、复核、回单和登记。
  • leave.*:员工提交路径。
  • attendance_correction.*:员工/授权应急提交路径。

同一业务后果跨入口复用同一码;不同业务后果即使 legacy key 相同也使用不同码。20 处旧字符串先形成 task-local 处置表:客户端 mock、主链路服务测试、内部/持久化摘要、延期域分别处理。迁移测试断言 exact reasonCode、HTTP status、兼容字段和准确中文,不使用模糊 message 正则。

5. 付款 readiness 服务

抽取无 HTTP 展示依赖的 resolvePaymentBatchCreationReadiness。输入包括 entity type、entity IDs、付款渠道、maker ID 和当前配置;输出只含安全原因:

type PaymentReadiness = {
  ready: boolean;
  blockers: Array<{
    reasonCode: PaymentBatchReasonCode;
    entityId?: string; // 只用于关联,不直接渲染
    entityCode?: string;
  }>;
};

解析器复用快照、部门 gate、活动占用、付款账户和 reviewer 事实。敏感账户只做存在性、银行机构和可解密判断,响应不带密文、完整账号或原始 employee。

GET candidates
  -> 单条 resolver
  -> readiness/blockers 决定可选性和提示

POST readiness(只读)
  -> 当前多选集合的组合 resolver
  -> 跨公司/占用/复核人等组合提示

POST create
  -> 事务 + 锁后复用同一 resolver
  -> ready=false 抛相同 reasonCode
  -> ready=true 才创建 batch/items/audit/notification

候选查询必须批量载入必要关系、占用、付款账户和复核人事实,避免在候选循环中产生 N+1。readiness 不落库、不进入长期缓存;资料补齐后刷新查询即可得到新事实。

6. UI 投影

依据 ui-ux-pro-max 的表单反馈规则:错误就近、提供恢复路径、toast 不作唯一反馈。

  • 正常候选保持紧凑,不显示“资料已齐全”。
  • 异常候选仍出现在列表中,避免再次形成不可见状态空隙;复选框 disabled,行内展示必要缺项。
  • 缺员工资料时说明需管理员维护;仅有维护权限者看到对应入口。
  • 非建行时说明当前银行付款渠道限制,不引导伪填。
  • 组合 readiness 紧贴主动作,使用 role=alert/aria-live,按钮以 aria-describedby 关联原因。
  • create 并发失败复用相同映射留在动作附近;toast 只补充“未创建付款安排”。
  • 未知错误显示可行动兜底及可用 request ID,不回显原始 details。

7. 兼容、隐私与回滚

  • API 是加法变更;旧 code/details 保留,旧客户端继续工作。
  • 不记录银行卡、密文、完整账号或真实 payload。原因码是否进入脱敏服务端日志延期评估。
  • 不改变付款状态机、maker-checker、角色、通知对象、回单门禁或 B1/B2。
  • 无 migration/schema/seed/flag/routing。生产资料补录不属于部署步骤。
  • 建议按“原因码/parity、首批迁移、付款 readiness/UI”形成逻辑提交;付款提交可独立回滚且无数据库补偿。
  • 部署另行批准;公网只用合成 fixture 验证。不得自动创建、复核或付款 0014。

8. 到期清单的后续分流合同(2026-09-09)

按已有 scanner 输出的 file/operation/fingerprint/count 与源文件摘要建立逐条台账,文件表仅作索引。未知使用状况记为待复核,不推导无需维护或默认低频;未证明删除/迁移成功的记录不得核销。保留原 expiresOn 与 owner,不把新 reviewDue 当作门禁新期限;拟延期日期和批准记录必须独立且逐模块说明。

共用 validation builder 的一个指纹可能影响多个业务分支,迁移必须在调用语义层选择原因;不能批量将所有旧错误映射成一个“通用参数错误”或只更新计数。每个获批迁移分支先定位入口与旧 HTTP status/code/details,再增加精确 reasonCode/中文及失败副作用断言。当前只完成清单,不新增迁移范围或任何线上行为。