docs: 新增 SaaS 多租户架构与编码约束
This commit is contained in:
@@ -448,6 +448,43 @@ public DaoIdGenerator jcBillIdGenerator() {
|
||||
|
||||
---
|
||||
|
||||
## 9. SaaS 多租户约束(强制)
|
||||
|
||||
> 所有业务系统默认多租户 SaaS。架构见 `architecture.md §7`。本节为编码时**必须 / 禁止**清单,AI 与人工共同遵守。
|
||||
|
||||
### 9.1 数据隔离(必须)
|
||||
|
||||
1. 行级默认:每张业务表必须含 `tenant_id` 列(DDL 双份同步,§5.8);主数据表(`tenant` / `tenant_config` / `tenant_quota`)本身由平台租户管理,可豁免过滤,但实体需标注 `@PlatformTenantOnly` 注释说明。
|
||||
2. 任何数据访问(JPA Repository / `pi` 原生 SQL / `esb` 编排调用)都必须带租户条件:`tenant_id = :tenantId`(JPA)或 `tenant_id = ?`(参数化,取 `TenantContextHolder`,沿用 §5.4)。
|
||||
3. 禁止省略租户条件;跨租户操作必须 `@CrossTenant` 标注并经评审,且走独立高权限接口。
|
||||
|
||||
### 9.2 租户上下文(必须)
|
||||
|
||||
4. 请求入口由 `TenantInterceptor` 从 JWT 取 `tenantId` 写入 `TenantContextHolder`;`afterCompletion` 必须 `remove()` 防泄漏。
|
||||
5. 数据访问禁止用 `null` 租户作为"查全部"的捷径;`TenantContextHolder.getTenantId()` 为空须显式按平台租户路径处理(带 `@PlatformTenantOnly`)。
|
||||
6. 缓存 key 必须前缀 `tenant:{tenantId}:`(`TenantCacheKeyGenerator`);禁止裸 key 跨租户共享。
|
||||
|
||||
### 9.3 异步与跨进程(必须)
|
||||
|
||||
7. `@Async` 必须走带 `TenantTaskDecorator` 的线程池;Kafka Producer 打 `tenantId` 头、Consumer 头部重建上下文;XXL-JOB 参数 / 分片带 `tenantId` 且 Job 多租户感知。
|
||||
|
||||
### 9.4 前端(必须 / 禁止)
|
||||
|
||||
8. 必须:登录后保存 `useTenantStore`、调用 `applyTenantTheme`、菜单经"权限 ∩ 模块订阅"过滤。
|
||||
9. 禁止:业务代码手写 `X-Tenant-Id` 头或硬编码租户标识;theme / logo 写死(须来自 `tenantConfig`)。
|
||||
|
||||
### 9.5 扩展(建议)
|
||||
|
||||
10. 租户表复合索引 `(tenant_id, ...)`;配额敏感操作前置 `QuotaService` 校验;开通走 `TenantProvisioningService`(幂等 + 可重试)。
|
||||
|
||||
### 9.6 检查清单补充(并入 §7.3)
|
||||
|
||||
- 新增数据访问:是否带租户过滤?缓存 key 是否前缀?
|
||||
- 新增异步 / Kafka / Job:租户上下文是否传播?
|
||||
- 新增前端页面:品牌 / 主题 / 菜单是否随租户动态?
|
||||
|
||||
---
|
||||
|
||||
## 附:文档导航
|
||||
|
||||
| 文档 | 内容 |
|
||||
|
||||
Reference in New Issue
Block a user