# 迁移自有表被运行时 bootstrap 越权创建

日期：2026-07-14
文档路径：document/development/2026-07-14/dev-logs/bugs/migration-owned-table-bootstrap-drift.md

## 修复记录
- 09:21：记录 bug 修复：迁移自有表被运行时 bootstrap 越权创建。（bug-log:1347366b）
  - Git 提交检查：fetch 成功；upstream `origin/main`；upstream 新提交：未发现；本地 ahead 提交：1347366b (HEAD -> main) feat(expenses): secure timeline and draft events；22669a90 feat(expenses): show unified expense event timeline；a616b30c fix(expenses): unify AI application submission transaction；653eda05 feat(auth): add opaque bearer sessions；661990b2 feat(expenses): add transactional expense case events。
  - 修改：新增 `schema_ownership.py` 统一四张 migration-owned 表的所有权边界，把 Agent Foundation、员工、预算、设置、系统看板、数字员工看板和演示数据初始化中的全量 `create_all` 改为只创建 legacy 表；新增 `migration_preflight.py`，在启动迁移前只读核对 Alembic revision 与自有表集合，遇到无版本表、缺表、多表、未知版本或多版本时直接拒绝，不自动 stamp 或修复。
  - 操作：调整 `server_start.sh` 的启动顺序和 `alembic.ini` 的脚本绝对定位方式；在无端口、无持久卷、tmpfs 数据目录的一次性 PostgreSQL 17 容器中执行空库升级、重复升级、降级到 base、漂移拦截和再次升级，结束后自动删除临时容器；没有执行持久化开发数据库迁移。
  - 验证：迁移与预检定向测试 `19 passed, 1 skipped`；一次性 PostgreSQL 真实迁移测试 `4 passed`，最终 revision 为 `20260713_0002`，关键唯一约束、复合索引和外键级联均通过，legacy 哨兵跨降级/再升级保留；受影响服务回归 `46 passed, 1 failed`，唯一失败为既有员工目录历史部门归一化用例，单独运行同样失败，与本次建表 helper 无关；新增文件 Ruff 全规则、旧服务 F/I/B/UP、Shell 语法、Alembic heads 和 `git diff --check` 均通过。
  - 影响：运行时 bootstrap 不再可能越权重建 Alembic 管理的表，启动会在可能破坏数据前暴露版本/表漂移；完整 legacy schema baseline 仍未建立，后续迁移旧表时必须继续小步验证。
