Files
X-Financial/document/development/2026-07-16/dev-logs/bugs/zero-entry-receipt-tenant-and-rollback.md

3.4 KiB
Raw Permalink Blame History

零录入票据归集跨租户隔离与失败回滚

日期2026-07-16 文档路径document/development/2026-07-16/dev-logs/bugs/zero-entry-receipt-tenant-and-rollback.md

修复记录

  • 09:35记录 bug 修复零录入票据归集跨租户隔离与失败回滚。bug-log:54754b55
    • Git 提交检查2026-07-16 09:35 CST 执行 git fetch --all --prune 成功;origin/main 没有远端新提交;本地 ahead 11 条,依次是 54754b55 个人费用申请记忆、211f85d9 统一核验申请工作流、5b246307 申请预览决策、a662cfe6 申请反馈账本、5ed34c2b 历史费用单回填、11275e4b 迁移所有权安全、1347366b 费用时间线与草稿事件安全、22669a90 统一费用事件时间线、a616b30c AI 申请提交事务、653eda05 Bearer 会话、661990b2 事务化费用事件;这些提交均为本轮开始前已有的本地检查点,本次未合并或改写历史。
    • 修改:receipt_folder.py 把票据命名空间从仅用户名收口为租户与用户联合边界,并用稳定摘要消除有损清洗碰撞;attachment_association_jobs.py 同时校验任务租户和 owner平台管理员也不能跨租户读取。expense_receipt_matcher.py 改用纯只读本人 Claim 查询并要求每份票据独立满足证据门槛。expense_receipt_association.py 将 Claim、Case、Link、业务事件、票据元数据和新旧附件目录纳入统一失败补偿避免事件或文件中途异常留下半关联状态。
    • 操作:新增持久化 attachment_association_jobs 模型、仓储和 20260716_0006 迁移任务按租户、owner、票据集合和 generation 去重,运行态使用租约、attempt_count + running 栅栏、进程锁和 PostgreSQL advisory lock。同票据与同 Claim 分别串行化Claim 锁内清理旧事务并重新匹配;待确认或失败任务保留原代审计历史,以新 generation 重新评估,自动关联成功代继续幂等复用。低置信、相近候选、混入无关票据、无草稿和仅有申请统一返回需要确认的零写入结果;同步扩展前端任务协议、会话恢复、候选卡片、幂等重放和成功风险复核提示,并更新功能 CONCEPT/TODO。
    • 验证:所有后端验证均在项目主容器内执行并设置 60 秒超时。后端归集专项 20 项、归集与相邻服务及迁移所有权组合回归 71 项通过,覆盖纯只读确认、逐票据证据、事件失败、文件元数据失败、既有申请 Case 保留、同票据并发、不同票据并发同 Claim、租约过期恢复、旧 worker/迟到回调栅栏、待确认重评估、失败代际历史保留、普通用户及管理员跨租户隔离;前端关联链路组合回归 29 项通过;相关 Python 文件 ruff --select F,I,UP 通过Vite 生产构建通过。一次性 tmpfs PostgreSQL 17 中完整迁移循环 4 项通过,临时数据库已清理,持久开发库未修改。
    • 影响:同用户名在不同租户的票据、任务和候选 Claim 不再互相可见;自动归集中途失败不会留下已改 Claim、孤立 Case/Link/Event、错误票据状态或被覆盖的旧附件目录低证据和混合票据批次只提示确认不扩大自动化权限任务重启或多 worker 后仍可查询和恢复。非默认租户原先落在旧用户名目录中的历史票据改为 fail-closed不做未经确认的跨目录迁移。