## 修复记录

- 13:40：修复 0026 Agent 资产租户安全迁移在真实历史建表路径下无法完整回退的问题。
  - Git 提交检查：已执行 `git fetch --all --prune`、`git status -sb`、`git rev-parse --abbrev-ref --symbolic-full-name @{u}`、`git log HEAD..@{u}` 和 `git log @{u}..HEAD`；`origin/main` 无新提交，本地 `main` ahead 17，工作区包含多智能体并行变更，未合并、覆盖或提交。
  - 本地 ahead 摘要：17 个提交覆盖审批任务与幂等回放（`242d68c3`、`28b834ed`、`4940ebc4`）、租户安全费用学习/预审/票据关联/申请记忆与反馈（`ee88a36b`、`6bdf65bc`、`ae3f02c3`、`54754b55`、`211f85d9`、`5b246307`、`a662cfe6`）、历史回填与迁移安全（`5ed34c2b`、`11275e4b`）、费用时间线与事务（`1347366b`、`22669a90`、`a616b30c`、`661990b2`）及不透明认证会话（`653eda05`）。
  - 根因：空库先经过 0026 时 Agent 资产旧表尚不存在，迁移会按设计跳过这些表；之后旧表由当前模型补建，PostgreSQL 为列级租户外键生成 `*_tenant_id_fkey`，而 0026 回退硬编码删除 `fk_*_tenant`，首个 `agent_asset_rule_feedback` 约束不存在即中断。
  - 修改：`20260717_0026_agent_asset_tenant_security.py` 新增带 PostgreSQL 标识符引用的约束安全删除器，0026 回退对它负责的复合外键、租户外键、范围检查和唯一约束统一使用 `DROP CONSTRAINT IF EXISTS`；升级路径与最终升级约束保持不变，模型自动命名的列级外键仍随租户列删除安全清理。
  - 操作：在 `financial-internal` 网络启动独立 `postgres:16-alpine` 一次性数据库，使用应用容器和项目 venv 执行真实 Alembic 循环；验证结束后停止探针，并确认 `--rm` 已删除容器。
  - 验证：相关 Ruff 检查通过；PostgreSQL-only 迁移防误用测试 42 项通过；一次性 PostgreSQL 上的完整迁移循环 1 项通过（7.00 秒），覆盖空库升级至 0028、回退至 0008、再次升级、完整回退至 base、最终再次升级至 0028，同时验证约束存在与缺失两种删除路径。
  - 影响：真实历史路径与当前模型补建路径都能安全回退 0026；缺少迁移命名约束时不再失败，已有约束仍被正常移除，且不会改变 head 升级结构。
