forked from xiongyuxing/tiku-backend.net
5.7 KiB
5.7 KiB
TIKU Backend
题库 SaaS 的正式后端。项目已收敛到 ASP.NET Core + EF Core + PostgreSQL,本仓库是后续开发的唯一目标后端。架构决策见 ADR 0001。
架构边界
- 旧 NestJS / Supabase 仓库只作为业务行为和接口清单参考,不作为运行时依赖。
- 不兼容旧 Supabase 数据库、RLS、Storage bucket、Refresh Token 或旧题单 JSON。
- PostgreSQL 按标准 PostgreSQL 使用,不绑定 Supabase 托管能力。
- 普通 schema 由 EF Core entity、Fluent Configuration 和 Migration 管理;
Tiku.DbMigrator是迁移入口。 - 多租户隔离不使用 PostgreSQL RLS;由 Host 租户解析、EF Query Filter、写入拦截器、PostgreSQL 约束和真实 PostgreSQL 测试共同保证。
- 身份、短信、对象存储、支付、通知和 AI 都通过 Application 层接口表达业务意图;第三方 SDK、密钥读取和 provider 细节只允许出现在 Infrastructure。
- 租户自定义域名由可信 Host 解析,不接受 query/header 伪造切换租户。
- 公共题库由唯一平台主体拥有;订阅有效租户可访问公共题,租户私题只属于本租户。
技术栈与目录
- ASP.NET Core Controller API
- Entity Framework Core + Npgsql
- PostgreSQL
- Serilog
- ZLinq
- AlibabaCloud OSS / SMS SDK
- Senparc.Weixin.*
- AlipaySDKNet.Standard
- Microsoft Semantic Kernel(仅 Infrastructure AI 边界)
- xUnit
Tiku.Api # HTTP API、认证授权、OpenAPI/Scalar、静态原型入口
Tiku.Application # 应用服务、用例编排、接口抽象
Tiku.Domain # 领域实体、枚举、基础类型
Tiku.Infrastructure # EF Core、PostgreSQL、外部服务实现
Tiku.DbMigrator # 数据库迁移启动项目
Tiku.Worker # 后台任务入口
Tiku.UnitTests # 单元测试
Tiku.IntegrationTests # API / EF / PostgreSQL 集成测试
docs # ADR、架构说明和迁移路线
平台端静态原型
平台端 demo 已作为静态文件挂到 API 项目:
GET /platform-admin/
它是功能原型壳,不是正式视觉规范。默认 mock 模式;联调时通过 runtime-config.js 注入同源 /api、平台 access token provider 和 API 模式。
当前不把后端改成 MVC/Razor,也不为这个静态 demo 单独维护 Node 服务。后续平台端产品化时,建议迁为独立 React/Vite/Next 工程,.NET 继续提供 API。
数据库与 ORM 分工
EF Core code-first migration 负责:
- 表、列、索引、普通外键;
- 普通 unique/check constraint;
- 模型快照和迁移历史;
- 通过
Tiku.DbMigrator显式执行迁移。
PostgreSQL guard 负责 EF 无法表达的跨表租户不变量:
TenantQuestionReference只能引用平台公共题或当前租户私题;TaxonomyNode父节点只能属于平台主体或当前租户;- 需要读取
tenants.mode或比较 owner 关系的条件约束。
维护规则:
- SQL 只放在
Tiku.Infrastructure/Persistence/PostgreSqlTenantConstraintSql.cs。 - Migration 只调用
migrationBuilder.EnsureTenantIsolationGuards()/DropTenantIsolationGuards()。 - 重建
InitialSchema后,Up()末尾必须调用EnsureTenantIsolationGuards(),Down()开头必须调用DropTenantIsolationGuards()。 - 新增 guard 前先判断能否用 EF FK / unique / check 表达;表达不了才加 PostgreSQL guard。
- 每个 guard 必须有 migration script 断言和真实 PostgreSQL 越权测试。
开发约束
- 新增租户实体必须实现租户 marker,并通过模型测试确认 Query Filter、租户唯一索引和组合外键。
- 普通 Controller / Service 不接受可写
tenantId、任意 owner tenant GUID、任意 bucket 或 provider 密钥。 - 题目写接口使用
QuestionLocator;答题接口使用sessionQuestionId;不得恢复裸QuestionId练习写入。 - 自定义域名请求不得通过
tenantCode、hostquery 或客户端转发头切换租户。 - 业务层不得直接引用第三方 SDK namespace、拼 OSS bucket、读取微信/支付/短信/AI 密钥。
- 不新增 Supabase provider、Supabase URL 拼接、Supabase Storage 或 Supabase Auth 兼容层。
- AI 面向租户教师后台和题目反馈审核;租户 API Key 存
TenantSecret,SK 类型不得进入 Domain/Application/API。
文档入口
常用命令
dotnet restore TIKU-BACKEND.slnx
dotnet build TIKU-BACKEND.slnx --no-restore
dotnet test TIKU-BACKEND.slnx --no-build
dotnet format TIKU-BACKEND.slnx --verify-no-changes --no-restore
git diff --check
生成迁移 SQL:
dotnet ef migrations script \
--project Tiku.Infrastructure \
--startup-project Tiku.DbMigrator
检查模型是否有未生成 migration 的变更:
dotnet ef migrations has-pending-model-changes \
--project Tiku.Infrastructure \
--startup-project Tiku.DbMigrator
首次部署可在迁移完成后创建平台超级管理员:
export TIKU_BOOTSTRAP_PLATFORM_ADMIN_EMAIL='admin@example.com'
export TIKU_BOOTSTRAP_PLATFORM_ADMIN_PASSWORD='replace-with-a-strong-temporary-password'
export TIKU_BOOTSTRAP_PLATFORM_ADMIN_NAME='Platform Administrator'
dotnet run --project Tiku.DbMigrator -- --bootstrap-platform-admin
该命令只允许在不存在任何平台角色用户绑定时执行。不要把临时密码写入仓库配置或命令行参数。