feat: scaffold supabase multi-tenant backend

This commit is contained in:
Codex
2026-06-21 21:54:43 +08:00
commit c9c767c7bd
99 changed files with 36660 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
# API 目录规范
`apps/api` 是 Web、Taro 小程序、管理后台共用的业务 API。所有复杂业务写入都进入这里前端不直接写 Supabase 表。
## 当前结构
```text
apps/api/src/
server.ts HTTP 服务入口,只负责请求生命周期
core/
config.ts 环境变量和运行配置
db.ts PostgreSQL 连接池和查询封装
http.ts CORS、JSON 响应、统一错误
router.ts 汇总注册各业务域路由
features/
auth/ 短信验证码、迁移期 session、OAuth provider 预留
health/ 健康检查
tenant/ 租户解析、品牌配置、域名识别
catalog/ 公开题库、科目、手册、商城、资料资源只读接口
learning/ 答题、错题、收藏、练习 session
commerce/ 订单、支付确认、激活码、权益
referral/ 销售/代理客资追踪、首绑保护、团队关系、CRM 队列
platform-admin/ 平台方 SaaS 租户、订阅、账单、使用量
tenant-admin/ 租户品牌、域名、公开设置、登录/商户配置、成员权限、活动/兑换码运营
tenant-content/ 租户后台内容维护:题目、视频、分数线、单词、知识手册、资料资源、批量导入
```
## 新业务域落位
后续按下面方式增加目录:
```text
features/
auth/ 登录、绑定手机、OAuth 回调、会话换取
learning/ 答题记录、错题、收藏、学习进度
commerce/ 商品、订单、支付、退款、权益开通
referral/ 销售/代理增长链路、客资归属、分佣依据、CRM 入队
platform-admin/ 平台租户管理、年费、服务费、账务审计
tenant-admin/ 合作商后台配置、品牌、域名、收款账户、登录 provider、密钥掩码、成员权限、审计、活动、兑换码、优惠券
tenant-content/ 合作商内容维护、批量导入、资源绑定、内容审计
```
每个 feature 默认包含:
```text
index.ts 导出 RouteDefinition[]
routes.ts HTTP handler
service.ts 业务编排和事务
repository.ts SQL 查询和写入
types.ts 仅本领域使用的类型
```
## 规则
- `server.ts` 不直接 import 业务 handler只 import `createRouter()`
- `features/*/index.ts` 只注册路由,不写 SQL。
- `routes.ts` 做参数解析、鉴权上下文、HTTP 错误,不写复杂事务。
- `service.ts` 承接订单、支付、权益、答题判定等业务规则。
- `repository.ts` 才写 SQL所有 SQL 必须带明确租户边界。
- 可预期错误用 `HttpError`,生产环境不向前端暴露内部异常。
- 写接口必须考虑幂等、审计和租户隔离;支付 webhook 必须先设计幂等键。
- 迁移期接口可用 `x-user-id` 标识学生用户;接 Supabase Auth 后统一替换为 JWT 解析。
- 登录类接口先使用 `Authorization: Bearer tk_*` 迁移期 sessionsession 明文只返回客户端,数据库只保存 hash。
- 平台运营接口使用 `x-platform-admin-key` 作为临时保护;正式上线前要迁到平台管理员 JWT 和审计日志。
- `platform-admin` 管平台与合作商之间的 SaaS 账务,`tenant-admin` 管合作商自己的品牌、域名、公开配置、登录/商户配置、活动和兑换码,`tenant-content` 管合作商自己的题库和学习内容维护。
- `tenant-admin` 的敏感配置必须拆分:公开字段进入 `config_public`商户密钥、短信密钥、OAuth app secret 进入 `app_private.tenant_secrets` 或生产 KMS/Vault对前端只返回 `secretRef` 和掩码状态。
- `tenant-admin` 权限由 `tenant_memberships.role` 的默认权限和 `permissions` JSON 覆盖共同决定;后端接口必须校验具体权限点,不能只依赖前端菜单隐藏。
- `referral` 是增长/客资业务域,负责邀请码、扫码事件、首绑保护、销售/代理团队归属和 CRM 入队;真实 CRM webhook 发送应由 worker 处理API 只负责幂等入队。
- 资料、PDF、视频等对象存储资源必须先进入 `content_assets` 台账,再通过 API 做权限校验和签名 URL 下发;前端不能直接拼 OSS/COS/Supabase Storage 地址。
- 批量导入必须先写 `content_import_jobs/items/issues`,保留原始 payload、规范化 payload、逐行问题和审计记录同步 API 当前支持题目 JSONExcel/CSV 和其它内容类型应接入同一管线。