Files
OpenFlare/docs/development-guidelines.md
T
ryan 861d759f97 feat: Update development guidelines and plan for ATSFlare V2
- Revised development guidelines to include new features for V2, such as Agent management and automatic discovery.
- Expanded the data model to support agent tokens and discovery tokens.
- Updated the development plan to reflect changes in Agent management, including CRUD operations and token replacement.
- Enhanced the requirements for the second phase of development, focusing on security improvements and user experience.
2026-03-10 15:13:28 +08:00

447 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ATSFlare 开发规范
## 1. 适用范围
本规范适用于 ATSFlare 第一版与第二版阶段。
项目第一版已完成以下能力:
* 配置发布与同步
* 节点心跳检测
* Nginx 反向代理配置下发
第二版在此基础上新增以下能力:
* HTTPS/TLS 路由支持
* 证书托管(手动导入与文件导入)
* 域名管理与证书自动匹配(支持 `*.example.com`)
* Agent 管理与自动发现
* 路由自定义请求头
* 配置预览与变更摘要
当前明确仍不做:
* 多租户
* WAF、限流、Bot、防刷
* 百分比灰度发布
* 节点分组与差异化下发
* Redis、MQ、对象存储、Prometheus
* 复杂缓存策略、证书自动签发、Purge、审批流
* mid-tier、分层缓存、复杂策略编排
超出以上范围的需求,必须先更新设计文档,再开始编码。
## 2. 技术基线
### 2.1 Server
控制中心基于现有 `atsf_server` 开发:
* Web 框架:Gin
* ORM:GORM
* 数据库:SQLite
* 前端:现有 `atsf_server/web`
* 登录体系:沿用 gin-template 现有能力
约束:
* 默认不配置 `SQL_DSN`
* 默认不配置 `REDIS_CONN_STRING`
* 不为了 MVP 引入新的基础设施依赖
### 2.2 Agent
Agent 放在 `atsf_agent`,使用 Go 单体程序开发。
约束:
* 单二进制
* systemd 运行
* 优先调用独立 Nginx,不依赖系统全局 Nginx
* 支持通过 `nginx_path` 显式指定独立 Nginx 可执行文件
* 未指定 `nginx_path` 时,默认通过 Docker 启动独立 Nginx 容器
* Agent 生成资源默认统一放在 `./data`,可通过 `data_dir` 统一覆盖
* 负责本机 Nginx 路由配置写入、校验、reload、状态上报
### 2.3 Nginx 配置边界
第一版控制面只管理独立生成的 Nginx 路由配置文件,例如 `/etc/nginx/conf.d/atsflare_routes.conf`。第二版在此基础上增加证书托管能力。
第一版以下内容不纳入控制面:
* `nginx.conf`
* 缓存策略
* upstream 高级配置
第二版约束:
* 允许在控制面托管 TLS 证书并下发给节点
* 仅支持证书导入(手动粘贴与文件导入),不做自动签发/续期
* `nginx.conf`、缓存策略、upstream 高级配置仍保持节点本地静态配置
## 3. 仓库职责划分
### 3.1 `atsf_server`
负责:
* 管理端 UI
* 管理端 API
* Agent API
* 数据存储
* 配置渲染
* 版本发布
* 节点状态展示
### 3.2 `atsf_agent`
负责:
* 节点注册
* 心跳上报
* 拉取激活版本
* 写入本地 Nginx 路由配置
* 调用 `nginx -t` 和 `nginx -s reload`
* 失败回滚
* 上报应用结果
* 管理独立 Nginx 路径或 Docker Nginx 容器
### 3.3 `docs`
负责:
* 设计边界
* 开发规范
* 开发计划
* 部署与联调说明
## 4. 开发原则
所有实现都必须遵守以下原则:
* 先完成闭环,再做抽象。
* 不为了"以后可能会支持"提前引入复杂模型。
* Server 只管状态和配置,不直接 SSH 改节点。
* Agent 是唯一落地入口。
* 所有发布都是"新版本激活",不是在线覆盖编辑。
* 第一版与第二版:所有节点默认拉同一份全量配置,不做节点分组差异化下发。
* 能用 SQLite 解决的问题,不引入额外中间件。
* 新功能优先复用现有 gin-template 结构,不平行造第二套框架。
## 5. 数据模型规范
第一版核心实体(已实现):
* `proxy_routes`
* `config_versions`
* `nodes`
* `apply_logs`
第二版新增实体:
* `tls_certificates` — 证书托管
* `managed_domains` — 域名管理与证书绑定
第二版扩展实体:
* `nodes` — 增加 `agent_token`、`discovery_token`,用于节点管理与自动发现
约束(全版本):
* 不新增 `zone`、`origin_pool`、`policy`、`deployment` 这类平台化对象
* `proxy_routes` 一条域名只对应一个 `origin_url`
* `config_versions` 必须保存完整快照和渲染后的 Nginx 路由配置
* 激活版本全局只能有一个,不引入分组维度
* 回滚通过"激活旧版本"实现,不直接修改历史记录
* 域名到证书匹配必须支持精确匹配和通配符匹配(如 `*.example.com`)
* `nodes.discovery_token` 仅用于首次接入,接入成功后必须失效
* 删除节点必须立即使该节点凭证失效
如需新增表,必须先证明它服务于当前迭代版本的主链路。
## 6. Server 开发规范
### 6.1 分层约束
Server 代码按以下职责拆分:
* `controller/`: 参数解析、调用 service、返回 JSON
* `service/`: 业务逻辑、校验、渲染、版本切换
* `model/`: 数据表结构、查询和持久化
* `router/`: 路由注册
* `middleware/`: 认证、鉴权、限流等横切逻辑
* `common/`: 通用工具和配置
禁止行为:
* controller 直接拼接复杂业务逻辑
* controller 直接操作多个 model 形成事务链
* middleware 承担业务逻辑
* 为简单需求引入新的平台层抽象
### 6.2 API 约定
管理端和 Agent API 统一使用 JSON。
响应结构沿用现有模板风格:
```json
{
"success": true,
"message": "",
"data": {}
}
```
约束:
* 成功或失败都返回清晰 `message`
* 列表接口返回稳定字段,不临时拼装结构
* 新接口命名优先使用复数资源风格
* Agent API 固定放在 `/api/agent/*`
### 6.3 鉴权规范
管理端:
* 继续复用 gin-template 的登录、角色和 session 体系
Agent(第一版):
* 预共享单 Token,来自环境变量
* 请求头统一使用 `X-Agent-Token`
* Agent 与管理端认证逻辑必须分开
Agent(第二版):
* 首次接入使用 `discovery_token`
* 注册成功后下发节点专属 `agent_token`
* 后续请求改为查 `nodes.agent_token` 验证
* 不再依赖全局环境变量 Agent Token
注意:
* 不要让 Agent 接口走用户登录态
* 不要把 Nginx 命令暴露成远程管理接口
### 6.4 数据库规范
SQLite 是唯一默认数据库。
要求:
* 新增模型后必须在 `model.InitDB()` 中加入 `AutoMigrate`
* 不写 MySQL/PostgreSQL 特有 SQL
* 不依赖外部迁移工具作为 MVP 前提
* 时间字段统一使用 GORM 常规时间类型
### 6.5 发布与渲染规范
发布逻辑必须满足:
* 发布时读取全部启用的 `proxy_routes`
* 生成完整的 Nginx 路由配置
* 计算 checksum
* 保存快照到 `config_versions`
* 通过切换 `is_active` 激活版本
版本号格式固定为:
```text
YYYYMMDD-NNN
```
例如:
```text
20260309-001
```
## 7. Agent 开发规范
### 7.1 模块边界
建议目录如下:
```text
atsf_agent/
cmd/agent/
internal/config/
internal/heartbeat/
internal/sync/
internal/nginx/
internal/state/
internal/httpclient/
```
职责要求:
* `config`: 本地配置读取
* `heartbeat`: 心跳请求和状态组装
* `sync`: 检查版本、下载配置、触发应用
* `nginx`: 封装 Nginx 校验、reload 和文件写入
* `state`: 本地成功版本和运行状态缓存
* `httpclient`: Server API 调用
### 7.2 行为规范
Agent 必须满足以下行为:
* 启动后生成或读取本地 `node_id`
* 未显式配置 `node_name` 时自动获取主机名
* 未显式配置 `node_ip` 时自动获取本机 IP
* 周期性心跳
* 周期性检查激活版本
* 发现新版本后先备份旧文件
* 写入新路由配置文件
* 先执行 `nginx -t`
* 校验通过后执行 `nginx -s reload`
* 失败时回滚备份并再次校验和 reload
* 上报最终应用结果
* 优先使用 `nginx_path`
* 未配置 `nginx_path` 时自动准备并使用 Docker Nginx 容器
* 启动时先校验本地路由文件 checksum 与控制面激活版本是否一致
* Docker 模式启动时应重建容器,而不是继续复用异常停止的旧容器
* 若本地 `agent_token` 为空且配置了 `discovery_token`,则应自动发起首次注册并完成 Token 置换
### 7.3 容错规范
第一版最少保证:
* Server 不可用时,Nginx 继续使用旧配置
* 下载失败时,不修改本地配置
* 配置校验或 reload 失败时,自动尝试回滚
* 本地状态文件损坏时,允许重新初始化,但不能删除正在生效的 Nginx 配置
* Docker 容器异常停止时,启动阶段应自动重建容器并重新校验配置
### 7.4 外部命令规范
Agent 调用 Nginx 命令时必须:
* 明确记录执行命令和返回错误
* 设置合理超时
* 不依赖交互式输入
* 不通过 shell 拼接不可信参数
## 8. 前端开发规范
MVP 前端只做最小管理界面,不重做整套后台。
要求:
* 继续使用现有 React 结构和 `semantic-ui-react`
* 页面只增加 MVP 必需页面
* 不额外引入新的大型前端框架
* API 请求统一放在 `web/src/helpers/api.js` 或同类 helper 中
* 页面状态优先保持简单,不提前引入复杂全局状态管理
第一版只需要以下页面:
* 反代规则页
* 发布版本页
* 节点状态页
* 应用记录页
## 9. 代码风格规范
### 9.1 Go
* 保持 package 名称简短且小写
* 错误必须显式处理,不允许静默吞错
* 函数尽量只做一件事
* 输入校验放在 controller 或 service 边界
* 业务枚举值使用明确常量,不使用魔法字符串散落代码
* 仅在复杂逻辑前添加简短注释,不写废话注释
### 9.2 命名
* 表名和模型名使用业务语义,不沿用模板示例语义
* 统一使用 `route`, `version`, `node`, `apply log` 这些术语
* 不混用 `client`、`edge`、`agent` 指代同一模块,统一叫 `agent`
### 9.3 日志
要求记录这些关键事件:
* 发布成功/失败
* Agent 注册
* 心跳异常
* 配置下载失败
* Nginx 校验或 reload 成功/失败
* 回滚触发
日志内容要可定位问题,但不要打印敏感 Token。
## 10. 测试与验收规范
### 10.1 第一版最低测试要求(已完成)
Server 至少覆盖:
* `origin_url` 校验
* `domain` 重复校验
* Nginx 路由配置渲染结果
* 激活版本切换逻辑
* 节点在线状态判定逻辑
Agent 至少覆盖:
* 版本比较逻辑
* 配置文件备份和回滚逻辑
* `nginx -t` 或 `nginx -s reload` 失败分支
* 本地状态文件读写
### 10.2 第二版新增测试要求
Server 新增覆盖:
* HTTPS server 块渲染正确性(`enable_https=true` 时生成 443 块,`redirect_http=true` 时生成重定向块)
* HTTP-only 路由渲染结果不受 HTTPS 字段影响
* 证书导入逻辑(手动导入、文件导入)和 PEM 校验逻辑
* 域名证书匹配逻辑(精确匹配与 `*.example.com` 通配符匹配)
* `custom_headers` 注入到渲染结果的正确性
* 节点创建、编辑、删除逻辑
* `discovery_token` 首次接入成功后失效
* 删除节点后 Agent 请求立即返回 401
* Agent 自动探测主机名与 IP,且允许配置覆盖
* Agent 首次注册成功后完成本地 token 置换
* 预览接口不写库
* diff 接口变更摘要计算正确性
### 10.3 联调验收标准(第一版,已完成)
1. 管理端新增反代规则并成功发布版本
2. Agent 能检测到新版本并拉取
3. Agent 成功写入 Nginx 路由配置文件
4. Agent 成功执行 `nginx -t` 和 `nginx -s reload`
5. 节点页能看到当前版本和最后心跳
6. 当 reload 失败时,Agent 能回滚到旧配置并上报失败
### 10.4 联调验收标准(第二版)
1. 创建含 HTTPS 字段的路由并发布,Nginx 能以 HTTPS 正确转发
2. 控制面可手动导入和文件导入证书,导入后可被路由选择
3. 反代规则输入域名后可自动匹配证书,且支持 `*.example.com`
4. 通过管理界面创建节点并生成 discovery token,Agent 使用 discovery token 成功接入
5. 删除节点后 Agent 请求返回 401
6. 路由配置自定义头后,渲染结果包含对应指令
7. 发布页预览展示正确渲染结果
8. 变更摘要正确列出域名变化
## 11. 文档维护规范
出现以下情况时必须同步更新文档:
* 产品版本范围变化(V1 → V2 → V3)
* API 发生破坏性变更
* 数据模型新增或删除
* Agent 本地文件路径变更
* 部署方式变化
* 新增或撤销对中间件/基础设施的依赖
优先更新:
* `docs/design.md`
* `docs/development-guidelines.md`
* `docs/development-plan.md`