


修改 Rust 反向代理,不破坏事件循环和安全
让 AI 修改、测试或发布多进程 Rust 代理时使用。给出构建与功能开关、错误与日志、事件循环与协议行为、测试与模糊测试、涉及安全的代码、拉取请求和发布步骤的规则。
要使用这个AI规则
## 保持代理各个库的分层和依赖方向
将仓库视为一个依赖方向明确的分层系统:
- 控制平面库负责配置解析、命令模式、共享状态、日志辅助工具和进程间通道。
- 协议/运行时库负责单线程事件循环、路由、套接字、缓冲区、指标、TLS、HTTP和PROXY protocol处理。
- 二进制crate负责监督进程、工作进程、CLI、配置加载、热重配置、升级和命令服务器。
- 集成测试和确定性模拟crate可以依赖运行时库,但不得将其`async`依赖或仅供测试的依赖泄漏到生产代码中。
- 当工具链要求不同时,模糊测试目标可以位于主工作区之外。
保持从运行时代码指向控制平面代码的依赖方向。每个工作进程都应保持单线程,避免在事件循环中使用共享互斥锁;除非有意重新设计架构,否则生产库不得引入`async`运行时。
## 用固定的工具链构建,并测试功能组合
修改代码之前,先确定固定的Rust工具链和所需的代码生成器。如果模式生成是硬性前提,则应在解释编译失败之前安装或确认该生成器。
常规构建和测试应使用锁定的依赖项。使用仓库配置要求的工具链运行格式化程序,以不允许警告的方式运行lint,并在发布相关工作之前测试整个工作区。迭代期间使用聚焦的测试套件,之后再回到受影响的工作区级门控。
将功能标志视为明确的兼容性单元:
- 记录默认分配器和密码学方案的选择。
- 分别测试每个受支持的密码学提供方,包括面向合规的模式。
- 绝不得在生产构建中启用测试注入钩子。
- 当debug或trace日志、解析器宽容模式、SIMD、零拷贝I/O和遥测功能会改变行为、占用或可观测性时,应将其保持为显式选择的功能。
不得因为一次默认构建通过就宣称变更无误。确认变更直接影响的功能组合。
## 处理错误和日志时不触发 panic,也不手改生成代码
在库中使用结构化错误,只在可执行文件边界添加广泛的上下文。由网络控制的输入必须转换为协议错误、连接动作、指标和带上下文的日志;在发布路径上,它绝不得触发`unwrap`、`expect`、`panic`或不可达分支。
遵循附近代码的所有权惯例。将借用的字符串或字节转换为拥有所有权的值时,优先使用能表达意图的转换;如果类型已经是可克隆的所有权值,则使用常规克隆。
协议模块必须使用既有的上下文日志宏和稳定的搜索标签。保留规范的会话/请求/后端包络,以便运维人员关联故障。预期的空闲关闭和频繁状态使用debug或trace;warning和error仅用于真实的协议错误或不变量破坏。
将面向外部的指标放在中央指标层中;新增或重命名指标时,更新面向用户的配置参考。将仪表值下溢视为正确性缺陷。
绝不得手工编辑生成的协议绑定。应编辑源模式,并通过构建流程重新生成绑定。热路径中的任何新增`unsafe`代码都需要在附近说明不变量,并配备聚焦测试。
## 别让套接字写入和缓冲区卡住事件循环
对于边沿触发I/O,仅从读取路径将字节排入队列还不够:必须显式发出待写就绪信号。缺少该信号会导致会话只在特定帧边界或缓冲区边界停滞。
标量和向量化套接字写入实现必须在结构上保持对称,包括重试和部分写入行为。对于加密前端,应避免可能发出重置并截断已排队字节的全双工关闭;只关闭写入侧,让对端关闭通过正常读取路径处理。
维持足以容纳最大协议帧及其头部的缓冲区。应在启动时验证该配置,而不是允许过小的缓冲区使成帧代码死锁。
将线路级连接状态与拥有缓冲区的流状态分离,并通过受生命周期规则检查的稳定标识符相互引用。前端协议协商与后端能力提示是不同概念;不得误将其中一个用作另一个的门控。
洪泛控制必须涵盖重置风暴、连续的延续帧、重复控制帧和优先级滥用。多进程热重配置必须先在监督进程中验证命令,再将命令分发给单线程工作进程。
## 用模糊测试和可重放的模拟分层测试
使用五个互补的测试层:模块旁的单元测试、进程级集成测试、模糊测试目标、针对sans-I/O状态机的确定性模拟,以及保护日志布局等结构契约的回归守卫。
对于解析器和非平凡状态机函数,在debug构建中编码前置条件、后置条件以及正向与反向成对的断言。公共状态机入口点应以完整的不变量扫描结束。断言描述内部不可能状态;对于对抗性网络输入,仍必须返回安全的协议结果。
使用带种子的随机源、虚拟时间、对抗性负载和故障注入来驱动确定性模拟。记录种子,使每次失败都能重放。仅将模拟专用的运行时标志和依赖项限定在模拟crate中。
集成测试必须动态分配端口,读取完整的TCP响应而不是单个分段,并使用明确的截止时间或重试至条件满足,而不是任意sleep。被忽略的测试需要具体的环境依赖或可追踪理由;绝不得使用`ignore`隐藏回归。
对于升级、解析器、压缩或成帧变更,除常规测试外,还要运行专用集成测试套件和对应的模糊测试目标。
## 谨慎修改 TLS、解析器和分帧,并加回归测试
对于TLS设置、协议协商、名称绑定、证书加载、解析器和头部规范化、流量控制、命令成帧、描述符传递、指标及日志,只进行保守且有测试依据的变更。
拒绝有歧义的消息成帧,不要转发与实际应用的成帧方式不同的表示。保持伪头部顺序、Content-Length协调、请求走私防护,以及正确的重置或优雅关闭语义。
对于命令通道,验证长度前缀、部分消息、文件描述符传递、状态重放和缓冲区边界。对于PROXY protocol处理,应覆盖部分头部、超大头部和健康检查流量。
不得通过日志或指标暴露秘密或敏感值。在每条错误路径和关闭路径上,都要保持计数器和仪表值正确。
修改事件循环或安全代码时,先为确切的不变量添加聚焦的回归覆盖,再运行相邻协议测试。不得在同一变更中混入无关的重构。
## 在拉取请求中写明对协议和安全的影响
修改复杂协议子系统之前,先阅读规范的生命周期说明或架构说明。将旧文档视为线索,并对照当前代码检查其中的文件引用。
使用范围明确的分支和能标识受影响子系统的约定式提交消息。遵循仓库的签名和sign-off策略。当任务已授权发布时,push已提交的分支并报告对应的CI运行;否则应停在本地已获授权的边界。
除非明确指定了活跃的集成分支,否则以当前默认分支为基础。拉取请求应说明协议或安全影响、已运行的命令、新增测试和文档更新。遵守代码所有权和贡献者许可门控。
当用户或运维人员可见的行为发生变化时,更新变更日志和配置参考,包括配置键、指标、命令行标志和升级要求。
交接之前,审查差异中是否存在生成文件、意外的功能泄漏、测试缺失、陈旧引用或无关编辑。
## 获准后才发布,并先测试热升级
将部署视为独立的授权步骤。先使用锁定或冻结的依赖项构建发布产物,再在与预发布环境等效的环境中验证配置,并运行受影响的就绪门控。
容器和操作系统软件包必须安装与本地相同的构建前提,包括模式生成器和平台库。固定工具链,并将仅供测试的依赖项排除在生产产物之外。
对于事件循环或工作进程生命周期回归,使用一个工作进程、禁用自动重启并启用回溯来复现。这样可避免监督进程的恢复掩盖第一次失败。
热升级必须保持监听器和会话交接的不变量。在发布前显式测试升级路径。不得将普通重启成功视为描述符传递或状态重放正常工作的证据。
没有明确授权和回滚路径时,不得部署到生产环境、修改凭据或执行破坏性恢复。报告构建了什么、哪些门控已通过、哪些内容仍未验证,以及工作停止的确切边界。
