@@ -1,7 +1,83 @@
# 报销状态空隙与财务处理视角:实施计划
## 2026-09-12 本人报销修复执行清单(已授权提交/推送及只读预检,部署另批)
用户在本地验收后明确批准提交、推送与只读发布预检。本轮不部署、不补写生产备份/镜像、不清理服务器、不改真实数据;执行回执保存于既有artifacts/qa-layout/finance-owner-release,提交/推送实际状态以Git及该回执为准。下文“未提交”等表述保留为本地验收时点记录,不代表后续发布准备尚未执行。
- [x] 按最新批准更新PRD/design:财务归属人由CEO一次审批,财务经办付款、CEO独立付款复核;第二财务不改变此规则,代填不算本人报销,在途不自动改写。
- [x] 已加载受影响规约,核实快照两调用点及全局自审合同,接着补失败回归。
- [x] 修复报销预检/提交共享快照路径,保留全局自审守卫及普通员工/CEO本人原路径;未新增生产配置或迁移。
- [x] 单元及真实Postgres/HTTP验证身份矩阵,缺候选没有残留pending流程;同一CEO和独立经理回归通过。
- [x] 桌面/手机验证财务本人提交、CEO一次审批、付款交接及独立复核;原BLOCKED及中间失败证据均保留。
- [x] 更新审批业务规约、spec和任务进度;语法、受影响测试、typecheck/build、Prisma及治理/diff检查通过,独立只读复核的两项发现均闭合。
- [ ] 完成后准备diff及发布影响说明;提交、推送、部署与真实在途处理分别按明确授权执行,重新核验候选/生产/备份/回退兼容,不沿用旧发布例外。
本地验收时点:代码已实现;本地验收完成;当时未提交/推送/部署,未连接生产或改真人数据;上轮已确认生产及本地基线为31ab9fbb。后续提交/推送与只读发布预检已获授权,实际部署另批。不是整个09-04任务或员工公网准入已完成。
验证与证据均在既有artifacts/qa-layout下:
- `cd server && npm test -- tests/unit/routes/reimbursements tests/unit/routes/workflow tests/unit/services/reimbursementOperationalChecks.test.js tests/unit/services/expenseStandards.check.test.js tests/unit/utils/workflow.test.js` : 249/249,finance-owner-regression-guarded;最后列表动作修订后额外运行detail/stats两文件43/43(属于249中的回归,不重复计数),finance-owner-projection-tests。
- `cd server && npm test -- tests/unit/scripts/error-reason-client.test.js` : 155/155,finance-owner-payment-error-tests。该轮命令同时带了两个不存在的付款测试路径,实际只执行这一文件,未将其声称为付款测试通过。
- `cd server && PAYMENT_ORDER_PYTHON_BIN=/tmp/hyb-oa-biff8-test-venv/bin/python npm test -- tests/unit/services/paymentOrderXls.test.js tests/unit/services/paymentBatchReadiness.test.js tests/unit/routes/paymentBatches.reimbursement.test.js` : 115/115,finance-owner-payment-tests-configured。三组共519项不同单测,不累加中间重复运行。
- `RUN_ISOLATED_DB_TEST=1 RUN_MANAGER_IS_CEO_TEST=1 RUN_OWNER_APPROVAL_TEST=1 RUN_BROWSER_TEST=1 RUN_RETAINED_DELETE_TEST=1 RUN_JOB_QUEUE=1 RUN_PAYMENT_EXPERIENCE_TEST=1 RUN_HANDOFF_PROJECTION_TEST=1 PAYMENT_ORDER_PYTHON_BIN=/tmp/hyb-oa-biff8-test-venv/bin/python node scripts/qa/test-invoice-first-http.cjs` :最终finance-owner-accepted退出0,41组场景;含预算开关两态、CEO停用/归档/作为提交人/角色缺失、第二财务、双角色自审、退回重提、转交及委托资格、两类非CEO列表动作隐藏、桌面/手机真实提交与审批,以及财务本人付款经办/独立复核/制单/合成回单。临时数据库和附件清理成功。
- 独立经理模式(上述命令移除RUN_MANAGER_IS_CEO_TEST、RUN_OWNER_APPROVAL_TEST、RUN_BROWSER_TEST):finance-owner-distinct-manager退出0,17组HTTP场景;不声称这轮含浏览器。已有同一CEO HTTP验证finance-owner-http-guarded为27组,最后完整验收以41组为准。
- `cd client && npm run build` (包含typecheck)、`cd server && npm run prisma:validate` 、受影响JS的node --check、错误原因strict合同、Trellis治理、process baseline及git diff --check通过。audit-docs --check-registry无错误,仍报告22个既有未注册文档警告,未扩大范围清理。
独立只读复核:主会话实施/测试,单独只读review先发现F1转交可绕过CEO要求,补实际actor/principal和目标角色守卫;复核再发现F2报销列表仍给非CEO动作提示,补新步骤的列表投影。最终复核0阻断、0未关闭非阻断;reviewer只审源码,未冒充独立跑测试。旧执行器能解析新快照但没有这些守卫,不允许首次新流程后仅回退旧镜像继续处理;发布影响见design。
中间失败如实保留:初始4个红色单测复现缺口;首轮HTTP因夹具使用不存在的inactive枚举失败,改用status=archived及独立archived_at两种有效数据;首轮本人浏览器误以为无警告也要二次确认,按实际precheck决策校正测试,不给用户增加确认负担;首轮付款单测未指定已有BIFF8解释器导致5项失败,配置正确解释器后115/115。没有通过增加超时、删除断言或修改付款产品代码掩盖失败。
本轮仍非完整生产应用启动:认证/HTTP/Prisma和业务路由真实,/api/me、导航和通知列表为辅助夹具;OCR为真实worker配mock提供方,未访问腾讯或银行。合成paid不等于真实付款,真实银行导入及完整恢复等其他主线缺口不由本轮代替。
## 2026-09-12 财务/CEO本人报销验证(已批准)
沿本地三人组织组合新增RUN_OWNER_APPROVAL_TEST=1,必须同时显式启用同一经理/CEO模式。仅在一次性数据库把合成manager→ceo→finance规则明确配置owner_self_fallback_role=finance;不执行生产回填脚本、不声称所有生产规则已复核。创建owner/submitter均为对应合成账号且票据同属该人的完整草稿,验证CEO无经理时走财务兜底、自审拒绝和财务审批;仅一位财务时其本人报销检查提交门是否因无非本人财务审批人而阻断。此阶段先确认事实,不自动增加角色、绕自审或修改产品规则。
发现业务阻断:CEO本人单据在显式finance兜底下生成恰好一条finance任务,CEO尝试审批403、财务200,最终approved。唯一财务本人单据提交200,CEO分别完成manager及ceo两步均200,随后finance角色任务pending;财务尝试审批409/self_approval_not_allowed,CEO尝试403,单据仍reviewing。说明此合成规则下提交前置没有阻止后续只剩申请人可匹配角色的死结;不据此断言所有生产金额档或已存在单据都受影响。
首轮admission-owner-approval预期提交409但实际200而失败;第二轮diagnostic预期自审403但实际409,按现有ensureNoSelfApproval合同纠正并增加具体原因断言。observed轮完整复现,原PASS仅代表观察断言通过、不是业务准入通过;随即改为独立businessBlockers,阻断时输出BLOCKED_OWNER_APPROVAL并退出1,避免误放行。原日志保留,最终以gate日志/退出码为准。所有运行均使用随机本地DB/合成资料,finally清理,不连生产。本轮新增本人场景是HTTP/真实Postgres验证,未新增本人浏览器场景,不复用前轮普通员工浏览器结论冒充覆盖。
建议业务方向待用户确认:财务本人报销由非本人负责人审批,不向本人再派财务审批;CEO本人继续财务兜底,付款制单人与复核人分离。不得简单允许自审、给CEO补finance角色、创建虚假审批人或直接把存量单据改成approved。涉及审批规则/快照及在途单据兼容,确认后另补本任务设计与反例,再实施只读review;当前只完成诊断测试,未修改产品或生产。
## 2026-09-12 同一经理/CEO组织组合验证(已批准)
复用既有隔离脚本,新增显式RUN_MANAGER_IS_CEO_TEST=1,仅创建合成employee、ceo+employee、finance+employee三人,员工和财务的直接经理均为CEO,不创建manager角色持有人。默认独立manager模式保留。验证现有三阶段任务实际分派及同一人是否需要两次操作,退回/重提、桌面手机、付款自审拒绝及合成回单闭环;不改产品审批规则、不修改生产账号,不推断财务本人报销自审兜底也已通过。单独保存新模式日志,失败不降低旧断言,不把查询关系当成真实审批通过。
admission-same-ceo.log及.exit:完整隔离运行退出0,29组场景PASS_REAL_DB_HTTP,数据库与合成附件清理成功。直接经理任务明确指派CEO账号,即使无人持manager角色也能提交;随后ceo角色任务仍需同一人另批一次,再到finance,重复审批409,最终无pending任务且approved。两次审批不是两个人把关,未自动去重,不因本次验证改变业务规则。财务创建批次自审403,CEO复核通过,桌面/手机制单返回、合成回单和待办1→0均通过。此结论只针对合成manager→ceo→finance规则和普通员工报销;财务本人报销与CEO自报兜底仍未验证。
实际命令沿既有RUN_ISOLATED_DB_TEST/RUN_BROWSER_TEST/RUN_JOB_QUEUE/RUN_PAYMENT_EXPERIENCE_TEST/RUN_RETAINED_DELETE_TEST/RUN_HANDOFF_PROJECTION_TEST全设1,加RUN_MANAGER_IS_CEO_TEST=1及固定BIFF8解释器运行node scripts/qa/test-invoice-first-http.cjs。运行时server/client未改变;前端沿用上轮同源构建,不重复部署。语法、Trellis治理、process-contract baseline及diff检查通过。默认模式同输入回归另记admission-distinct-manager-regression,不拿旧脚本通过抵扣此次夹具改动。
默认独立manager模式回归退出0,27组场景完整通过,清理成功。两模式回执汇总admission-organization-receipt.json,绑定三脚本摘要与各自日志;不是29+27个独立单测,也不等于完整生产启动合同。仅主会话检查,未独立review、未提交/推送、未连生产。下一步优先补财务本人报销与CEO本人报销的所有者自审/兜底场景,再汇总首批准入缺口;不为了验收去改真人角色或重放真人单据。
## 2026-09-12 首批准入认证与跨角色验证(已批准接续)
生产只读盘点(2026-09-12T09:29Z):31ab9fbb运行版本匹配。远端事务RepeatableRead/READ ONLY、10秒statement_timeout,仅取角色/经理关联、状态、通知及资料存在布尔值;不读密码哈希、银行密文值或明文,不登录、不写业务。脱敏回执admission-production-readonly-confirmed.json;初轮仅smoke-前缀不足,依据09-07历史身份清单补oa_smoke_前缀重读,初轮原件保留。E标签只属该查询顺序,身份以历史用户已确认邮箱前缀匹配,不推断姓名。
- CEO/财务/普通员工均active;后两者经理指向CEO。三人主体/开户行关联/加密账号存在,但不等于解密成功、建行校验通过或可付款。CEO与普通员工must_change_password=true,财务false;没有本轮登录验证,不把该标志直接判成不能登录或擅自清除。管理员主体/开户行关联缺失仍不自动回填,个人报销非本轮默认准入。
- 测试前缀候选4个:财务已archived;两位manager和一位employee active,没有专用ceo候选。4个主体/开户行/加密账号均缺,通知开关均true,其中一位manager缺直接经理。不得凭“已有测试账号”启动生产审批/回单链;创建或恢复角色可能影响真实审批路由,当前不授权此类变更。
- 既有check-oa-only-smoke-readiness脚本会POST登录并发起多模块读取,不是零写入元数据探针,且旧矩阵假定独立manager角色,不直接运行或注入真人密码。本轮没有搜索/加载凭据文件。
- 下一步先在本地合成环境补“员工/财务直接经理就是同一CEO、无独立manager角色”的组织组合,核审批任务去重及付款复核分离,避免为了测生产而加角色污染路由。公网合成闭环需单独方案解决专用身份、凭据受控交付、测试主体/银行卡资料、通知与支付隔离及清理;当前只报告缺口,不要求普通员工代测。真实银行导入仍由授权财务办理,不等于让财务代做软件回归。
先在已发布31ab9fbb同源代码上运行既有test-invoice-first-http.cjs:一次性本地Postgres/tmpfs、随机合成账号密码和密钥、独立临时附件目录,真实HTTP/JWT/浏览器,启用RUN_ISOLATED_DB_TEST、RUN_BROWSER_TEST、RUN_JOB_QUEUE、RUN_PAYMENT_EXPERIENCE_TEST、RUN_RETAINED_DELETE_TEST、RUN_HANDOFF_PROJECTION_TEST。当前源码无新运行时改动;前端重新构建后验证。
此阶段不读取生产凭据、不连接生产数据库、不处理真实单据;OCR强制mock提供方,支付无银行连接,通知只用现有脚本的本地合成路径。脚本finally仅清理本轮随机容器与临时目录。成功必须包含认证正反例、上传选票、退回重提、三步审批、独立付款复核/自审拒绝、制单、回单登记与待办消失;不把本地PASS当作公网真人角色验收、腾讯OCR验证或完整发布门禁通过。
执行顺序:构建 → 既有隔离脚本 → 核实际通过项及清理 → 明确剩余公网/业务主数据准入缺口。失败只归因本阶段,不解冻09-06的R1或批量修旧测试,不要求员工代测。
首次admission-flow退出1,付款浏览器超时,finally清理完成。现有异常正则漏了test-payment-experience,只显示外层420行;加入该模块名后诊断回跑仍失败,准确定位test-payment-experience.cjs:110( admission-diagnostic)。原因是旧桌面分支在actions卡片内部寻找已Portal到body的菜单项,而当前组件和既有前端规约均要求page级菜单角色。沿本阶段最小修复测试脚本:桌面/手机统一按page菜单项精确名称定位,并断言唯一、可见再点击;保留下载提示、无原因框、真实BIFF8、回到原单、进度和付款状态断言。不改运行时、不增加超时、不删除失败证据、不重建未变化前端。
admission-final继续到退回删除后退出1,定位test-reimbursement-retained-delete.cjs:163;同类遗漏:桌面DropdownMenuItem不是button,取消确认后菜单已关闭须重开。检查本轮三个关联脚本的菜单入口后,分别使用桌面menuitem/手机button、唯一性断言,桌面取消后重新打开菜单;删除后若有更多入口则展开,显式断言菜单项及按钮均不存在,避免关闭菜单导致负向假通过。旧日志名final不等于通过,最终以退出码及完整回执为准。
最终admission-complete退出0,PASS_REAL_DB_HTTP,27组场景完整完成,真实Postgres/密码登录/JWT/HTTP及桌面手机浏览器,覆盖上传去重/worker选票分类编辑、提交与退回重提、三步审批、自审拒绝、组批独立复核、首次/重复中文BIFF8下载及返回原单、合成回单登记/paid和待办消失、发票并发/故障回滚、留痕删除并发及历史只读、token撤销。容器和合成附件清理成功;前端admission-build退出0(含typecheck/build/PWA),无运行时代码变更,不要求重新部署。前三次失败回执保留;只有本次完整结果计为通过,不把27组场景写成27个Vitest测试或全项目门禁。
覆盖限制:此脚本的/api/me、导航、通知列表是辅助夹具,认证插件/登录与业务路由是真实代码;账号是合成employee/manager/ceo/finance,manager与ceo不同账号,不等于已验证公司实际“直接经理与CEO同一人”的全部路径。OCR为真实pg-boss/worker+ mock提供方,本轮无腾讯调用;无银行连接、无公网真实账号认证或生产业务写入,不将合成paid算实际付款。已有frontend规约明确Portal菜单用page级角色,本次是脚本漏遵循,不重复新增同义经验条目。
下一步:先准备生产只读准入清单,核对现有专用测试身份、角色/经理映射及资料存在性,不复用员工密码、不读取银行明文或回填;在确认专用身份和窄范围授权后再执行公网合成闭环。真实组织角色组合、专用账号的生产写入/清理范围和禁用通知/支付外联需写清,不能把本次“继续”扩成生产账号创建授权。此次仅3份QA脚本及本任务记录未提交,提交另批;不自动重启服务或再次发布31ab9fbb。
## 2026-09-12 F1 付款创建纵深防御(接续已批准后续规划)
发布后回执:用户随后明确批准五文件提交推送,并授权当前752ec413本地备份/独立镜像补齐、31ab9fbb发布及自动验收。31ab9fbb已部署,existing退出0、备份合同刷新通过,前后pending=none;公网ready/106资源扫描通过,数据库未重启、环境文件未变。运行镜像付款路由/readiness及四份制单相关文件摘要与候选一致,纯合成内存BIFF8生成读回通过;未操作真实业务。证据artifacts/qa-layout/f1-release。下列未提交/未部署和待授权描述是历史阶段;本段不属于31ab9fbb候选树。123项按输入不变复用,不追加计数;本轮未独立review、未做生产删除/创建API或真实数据库并发验证。下一主线为首批准入认证与跨角色验收,不重复开发已发布防护。
复核七处来源读取后,本轮先封住新付款创建入口:候选列表和readiness/锁后创建共用的loadEntitySnapshots显式要求deleted_at为空。不得向所有查询机械添加过滤:既有批次详情、历史收款人兜底和费用明细属于凭证读取,保留现有授权读取。删除仍只允许draft/rejected且无活动批次,不扩展approved删除,不改审批/复核/付款执行状态机。
- [x] 新回归先失败:构造approved但带删除标记的防御性fixture,候选排除,readiness与锁后创建拒绝且无成功写入/通知;未删除正例和历史批次详情保持。