Files
tiku-backend.net/docs/migration/phase-3-tenant-isolation-and-shared-question-bank.md

53 lines
2.3 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.

# 第三阶段:租户隔离、共享题库与前端运行时
状态:已完成主线设计和实现。
## 目标
- 普通业务代码默认只能读取和写入当前租户数据。
- 公共题库由平台主体拥有,有效租户可访问。
- 租户私题只属于本租户。
- 公共题和私题可混合组卷、答题、收藏、错题和统计。
- 租户自定义域名安全解析到统一前端运行时配置。
## 结果
- `ITenantContext` 只读化,请求租户由中间件解析。
- EF Core Query Filter 自动按租户过滤。
- SaveChanges 拦截器自动写入当前租户并拒绝跨租户写入。
- DbContext 使用 scoped `AddDbContext`,避免池化串租户状态。
- `TenantResolutionMiddleware` 在认证前按可信 Host 解析租户。
- JWT tenant claim 与 Host 解析不一致时返回 403。
- 未知、Pending、禁用域名在业务前返回 404。
- 唯一 `PlatformOwned` 租户拥有公共题库、公共题、公共题版本和公共分类主干。
- `TenantQuestionReference` 作为公共题/私题消费引用。
- `PracticeSessionQuestion` 锁定题目版本,历史答题按原版本回放。
- `TenantFrontendConfig` 支持 Draft / Preview / Publish。
- `GET /api/runtime/bootstrap` 仅根据当前 Host 返回公开配置。
## 数据库边界
EF Core 负责实体、索引、外键和普通约束。以下跨表租户不变量由集中 PostgreSQL guard 管理:
- `TenantQuestionReference` 只能引用平台公共题或当前租户私题。
- `TaxonomyNode` 父节点只能属于平台主体或当前租户。
维护规则见根目录 README 的“数据库与 ORM 分工”。
## 验收
- A 租户不能读取、修改、删除或 Attach B 租户数据。
- A 可访问公共题和 A 私题,不能构造 B 私题引用。
- 公共题 V1 创建会话后发布 V2旧会话仍使用 V1新会话使用 V2。
- Host A 携带 Tenant B JWT 返回 403。
- Pending/未知域名和 Suspended 租户无法获取 runtime bootstrap。
- 新增租户实体漏写 filter、组合外键或租户索引时模型测试失败。
```bash
dotnet build TIKU-BACKEND.slnx --no-restore
dotnet test Tiku.UnitTests/Tiku.UnitTests.csproj --no-build
dotnet test Tiku.IntegrationTests/Tiku.IntegrationTests.csproj --no-build
dotnet ef migrations script --project Tiku.Infrastructure --startup-project Tiku.DbMigrator
git diff --check
```