


开发多租户自动化平台,不混淆租户与版本
在为拥有社区版、企业版和托管版的多租户自动化平台编写代码时使用。它让每个查询都限定在正确的项目内,通过安全客户端发送对外HTTP请求以防范SSRF,在使用依赖项的工作区中声明依赖项,并在所有版本上测试后才结束。
要使用这个AI规则
## 隔离各租户的数据,不把高级版代码导入社区版
将租户范围、产品版本、功能访问权限和品牌呈现视为安全与行为契约。
### 强制实施隔离
- 在平台、项目和用户层级明确建立所有权模型。
- 使用正确的项目标识符或平台标识符限定每个数据库查询的范围;绝不能依赖调用方事后过滤结果。
- 要求每个端点都声明访问控制。
- 在受保护行为执行前应用后端授权和功能中间件;对不可用的付费功能返回标准`402`响应,并在前端守卫和查询启用条件中采用同样的限制。
### 保持版本之间的单向依赖
- 让高级版或托管版通过已注册的钩子或接口扩展社区版核心。
- 绝不能把高级版专用的应用代码导入社区版代码。
- 社区版默认不带特定品牌;在托管环境中应用已配置的品牌呈现;自托管企业版的品牌呈现则依据相应的套餐能力进行限制。
- 通过5条路径验证面向客户的行为:社区版自托管、企业版自托管、免费托管版、付费托管版和企业托管版。
- 所有面向客户的名称、颜色、徽标、登录界面和消息都应由已配置的外观决定,而不是硬编码产品品牌。
## 在使用依赖项的工作区中声明它,并用锁保护多服务器共享的数据
明确依赖项归属和并发数据行为,使本地运行成功的结果能够与生产部署保持一致。
### 维护软件包边界
- 按照从轻量、独立于框架的基础层到较重的应用层软件包的顺序组织共享库。
- 可复用的集成和执行引擎只能依赖轻量软件包;需要的应用行为应通过范围狭窄的框架层公开。
- 每个运行时依赖项都应在导入它的工作区中声明;每个测试或工具依赖项都应在该工作区的开发依赖项中声明。
- 根清单只用于仓库级工具或真正的引导要求。
- 统一锁定版本,并在更改依赖项后使用规范安装程序更新锁文件。
### 保护持久化与并发处理
- 当对象映射器不会自动发现新实体时,应明确注册这些实体。
- 将副作用分离到专用模块中,并在变更成功后显式调用。
- 对于多服务器任务,使用分布式锁、队列去重,或具有`skip-locked`语义的行锁。
- 避免使用托管服务不支持的数据库扩展。
- 外部传入的对象必须先清理,再存入数据库。
## 不用any和强制类型转换,并使用项目共享的辅助工具
使用可预测的接口、数据流、文件组织方式和共享实用工具。
### 保持类型完整性
- 不要使用`any`;应使用准确的类型,或将`unknown`与类型守卫结合使用。
- 不要通过类型断言强行传递值。应修正源类型、添加验证或收窄值的类型。
- 使用API前先查阅库文档,并替换所有被标记为已弃用的内容。
- 凡是参数超过1个的函数,都使用经过解构的单一对象参数。
- 函数之间优先采用不可变数据流;构建并返回新的集合,而不是修改调用方拥有的对象。
### 明确约定
- 使用项目共享的结果辅助工具处理同步和异步错误。
- 将面向用户的验证消息设为本地化键;常见表单错误使用共享键,必要时再添加新键。
- 检查当前分支后,对兼容性修复或新增内容提升共享软件包的补丁版本;对新的导出或行为提升次版本。
- 将不导出的辅助工具定义为独立函数,把可执行逻辑放在前面,并在末尾集中放置导出的常量和类型,不要将它们穿插在逻辑中。
- 注释应说明某项决定为何存在,而不是解释一目了然的代码在做什么。
- 通过1个命名对象导出多个普通实用工具,同时让React组件继续使用命名导出。
## 通过安全客户端发送对外HTTP请求以防范SSRF,并遵守API规则
在每个不受信任的边界上应用明确的请求语义和安全的网络客户端。
### 规范端点
- 所有创建和更新变更都使用`POST`,删除操作使用`DELETE`;如果API契约不包含`PUT`或`PATCH`,就绝不能使用它们。
- 为每个端点明确配置安全访问权限。
- 使用规范标识符、错误类型、模式基类、集合辅助工具和数据库清理工具,不要重新实现这些内容。
### 防止服务器端请求伪造
- 服务器组件发出的HTTP请求必须通过批准的安全客户端。
- 对源自用户输入、管理员配置、OAuth端点或第三方集成的URL,绝不能使用原始`fetch`或不受限制的客户端工厂。
- 保留对私有地址、环回地址和云元数据地址的过滤。
- 在边界处进行类型转换、URL验证和外部对象清理。
### 将迁移视为受控变更
- 创建或修改迁移前,先阅读仓库的迁移操作指南。
- 遵循已记录的生成与结构流程,不要自行编造迁移布局。
- 保持迁移与支持的托管数据库环境兼容。
## 只在页面主要数据加载失败时显示全局错误对话框
只有在失败的数据对当前页面不可或缺时,才显示全局查询失败提示。
### 按影响对查询分类
- 对表格行或主要列表等页面核心数据,设置可触发全局错误对话框的查询元数据标志。
- 对功能标志、元数据、单项查找、筛选选项或用户详情等辅助数据,不要启用该标志。
- 采用以下判断规则:如果失败会造成无法解释的空白页面或空的主要视图,就显示对话框。
- 当周围界面仍然可用时,允许次要查询静默失败。
- 在相应套餐能力可用之前,始终禁用受功能限制的查询。
## 用单体仓库的任务运行器测试租户隔离和每个版本
通过单体仓库的规范任务运行器执行针对性测试,并验证因版本不同而存在差异的路径。
### 检验代码与数据
- 对共享代码和执行代码运行单元测试,对API行为运行集成测试。
- 使用标准测试环境辅助工具和请求上下文辅助工具,使身份验证与路由行为和生产环境一致。
- 确保测试数据相互隔离,并在测试之间清理。
- 当代码使用锁、去重或基于`skip-locked`的数据库选择时,添加并发测试。
- 通过证明无法返回其他项目或平台的数据,测试租户隔离。
### 使用受支持的命令
- 在认为任务完成之前,运行仓库要求的代码检查与修复命令。
- 使用已配置的单体仓库任务运行器和筛选软件包的命令;不要调用无关的构建系统。
- 当托管前端指向远程后端时,应避免会重定向到托管域名的OAuth流程;改用不发生重定向的凭据或完全本地的后端。
- 在每条受支持的路径中验证版本限制、品牌呈现、额度和功能可用性。
## 给变更加上标签,必需的检查通过后再结束
使用功能文档、标签和最终检查,使变更易于理解并达到可发布状态。
### 准备实施
- 修改功能前,先阅读专门介绍其实体、服务、数据流和集成限制的文档。
- 让关键的跨领域安全规则保持简洁,并与分步骤的功能工作流分开。
- 检查依赖项清单、实体注册、租户过滤器、版本之间的导入、访问声明和副作用执行顺序。
### 准备贡献内容
- 恰好添加1个主要变更标签,用于区分功能、新的错误修复或无需写入变更日志的内部变更。
- 当变更影响第三方集成或核心集成时,再添加一个单独的集成领域标签。
- 确认锁文件、软件包版本、本地化键、测试和生成的产物与实现一致。
- 运行所需的代码检查、测试和安全检查,并报告任何未能运行的检查。
- 在最终差异和验证结果提供支持之前,不要宣布完成。
