多租户与权限
租户隔离怎么强制、功能开关与配额怎么发、权限模型怎么配。
隔离是强制的,不是自觉的
租户隔离有三层保障,任意一层单独失守都不至于漏数据:
| 层 | 机制 | 失守时的表现 |
|---|---|---|
| 运行时 | Prisma 层租户守卫,模型未登记则启动即失败 | 服务起不来,而不是悄悄查全表 |
| 静态 | tenant-scope lint 规则扫缺失的 tenant_id 过滤 | 提交前告警 |
| 契约 | 模块 schema 必须带 tenant_id 且建 [tenant_id] 索引 | 契约校验报错 |
平台控制台是唯一按设计跨租户的地方:平台请求不带 tenant_id,守卫据此放行,
相应的 lint 告警在平台模块目录下显式关闭。
功能开关与配额
租户能用什么由两组数据决定:
- 功能开关(
tenant_features)—— 模块与功能项的开通状态。关掉后后端不挂路由、 前端不进侧栏,是真关而不是隐藏入口。 - 配额(
tenant_limits)—— 例如max_users席位上限。超限时写操作被拦下, 返回明确的升级提示而不是 500。
套餐(免费版 / 基础版 / 专业版 …)就是这两组数据的预设组合, 在平台控制台按租户调整,也可以脱离套餐单独覆盖某一项。
权限模型
权限是 PBAC(基于权限的访问控制):
- 模块声明权限 key,例如
notes.read/notes.write - 角色是权限的集合,租户内可自定义
- 用户挂角色,请求时聚合出权限集
未启用 rbac 模块时退化为「登录即可访问」,方便小项目先跑起来再收紧。
审计
所有写操作都记审计日志:谁、什么时候、对哪个资源做了什么。
业务模块通过事件总线上报(events.emit),不直接依赖审计模块的实现,
因此审计模块可以整体替换或摘掉。