Files
tiku-backend.net/docs/migration/phase-2-engineering-foundation.md

88 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 第二阶段:.NET 工程底座
完成日期2026-07-27。
本阶段按 greenfield 项目建设,不承担旧 Supabase / NestJS 数据兼容。数据库结构以 EF Core 实体、Fluent Configuration 和 Migration 为唯一权威来源API 运行时不自动修改数据库。
## 数据库开发与发布边界
- 开发采用 code first修改实体或 Fluent Configuration 后生成 EF Core Migration。
- Migration 统一保存在 `Tiku.Infrastructure/Persistence/Migrations/`
- `Tiku.DbMigrator` 是执行 Migration 的独立入口。
- `Tiku.Api``Tiku.Worker` 不调用 `Database.Migrate()`,避免多实例启动时争抢 DDL也避免应用进程持有结构变更权限。
- 发布前生成并审查 SQL生产环境由部署流程显式执行 DbMigrator 或审核后的 SQL。
- Development 未配置连接串时默认连接本机 `tiku` 数据库,并使用当前系统用户名,不内置密码。
- 非 Development 环境必须显式配置 `ConnectionStrings:Database``DATABASE_URL`,缺失时启动失败。
常用命令:
```bash
dotnet ef migrations add <MigrationName> \
--project Tiku.Infrastructure \
--startup-project Tiku.DbMigrator
dotnet ef migrations script \
--project Tiku.Infrastructure \
--startup-project Tiku.DbMigrator
dotnet run --project Tiku.DbMigrator
```
## 真实 PostgreSQL 测试基线
`Tiku.IntegrationTests` 已移除 EF Core InMemory provider全部集成测试连接真实 PostgreSQL
- 管理连接可通过 `TIKU_TEST_POSTGRES_ADMIN` 覆盖。
- 默认管理连接为 `Host=localhost;Database=postgres;Username=<当前系统用户>`
- 测试进程创建一次已执行完整 Migration 的模板数据库。
- 每个 `ApiTestFactory` 从模板克隆独立 `tiku_it_*` 数据库,测试之间不共享业务数据。
- Factory 释放时终止连接并删除克隆库;进程退出时删除模板库。
- 测试只允许管理 `tiku_it_*` 命名空间,不访问或清理已有 `tiku` 业务数据库。
真实关系型测试暴露并修正了以下 InMemory 无法可靠验证的问题:
- 测试夹具缺失的 Region、School、Subject、Category、Question 等外键实体。
- `Question``QuestionVersion` 当前版本引用形成的插入循环,改为事务内分阶段保存。
- `ReferralLead.FirstTrackId``ReferralTrack.LeadId` 形成的插入循环,改为事务内分阶段保存。
- PostgreSQL JSON 映射不能将未定义的 `default(JsonElement)` 生成为 SQL literal缺省数组改为有效的 `[]`
- 徽章发放不再伪造超长 legacy ID通知使用新记录 ID 生成独立、稳定的去重键。
## 配置与密钥安全
- 根配置不再提交可用于生产的 JWT signing key。
- Development 只使用明确标识的开发 JWT keyProduction 拒绝该 key。
- 租户第三方凭据使用 AES-256-GCM envelope 保存。
- 每条密文使用 12-byte nonce、16-byte authentication tag。
- AAD 绑定 `tenantId``secretRef``keyId`,密文不能跨租户或跨引用替换。
- 主密钥必须是 Base64 编码的 32 字节值Production 拒绝仓库内的开发测试 key。
- 运行时配置键为 `Security:TenantSecrets:KeyId``Security:TenantSecrets:MasterKey`;环境变量可使用 `TIKU_TENANT_SECRET_KEY_ID``TIKU_TENANT_SECRET_MASTER_KEY`
- 新 schema 只保留 `encryption_key_id``encrypted_payload``encryption_nonce``encryption_tag`,不保留明文字段或明文回退读取路径。
本阶段的 `EncryptTenantSecretPayloads` Migration 会直接删除旧 `secret_payload` 字段。这是 greenfield 决策,不提供旧数据转换或兼容窗口。
## 验证结果
2026-07-27 在本机 PostgreSQL 18.4、.NET SDK 10.0.301 上完成:
```text
dotnet build通过0 warning / 0 error
dotnet test通过265/265
UnitTests16/16
IntegrationTests真实 PostgreSQL249/249
dotnet format --verify-no-changes通过
git diff --check通过
EF Core migration script通过生成 4184 行 SQL
测试数据库清理:通过,无 tiku_it_* 残留
```
## 第二阶段退出条件
- [x] EF Core Migration 成为 code-first schema 的唯一版本历史。
- [x] API 与 Worker 不在启动时自动执行 Migration。
- [x] 生产数据库、JWT 和租户密钥配置缺失时 fail fast。
- [x] 租户第三方凭据只保存 AES-GCM 密文 envelope。
- [x] 集成测试完全切换到隔离的真实 PostgreSQL 数据库。
- [x] 修复真实数据库暴露的外键、循环依赖、JSON 和字段长度问题。
- [x] 全量构建、测试、格式与 Migration SQL 验证通过。