From 449d0a5c5b4d7c7cb646fce9002df96834150454 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 31 May 2026 14:52:37 +0800 Subject: [PATCH] =?UTF-8?q?[=E4=BC=98=E5=8C=96]=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 87 +++-- docs/config.ts | 16 +- docs/design/architecture.md | 4 +- docs/design/development.md | 390 ++++++++-------------- docs/design/index.md | 4 +- docs/{reference => design}/repository.md | 0 docs/guide/development.md | 188 ----------- docs/guide/index.md | 10 +- docs/guildline/development-constraints.md | 316 ++++++++++++++++++ docs/{guide => reference}/agent.md | 2 +- docs/{guide => reference}/deployment.md | 0 docs/reference/index.md | 2 +- docs/{guide => reference}/server.md | 0 docs/{guide => reference}/upgrade.md | 0 14 files changed, 525 insertions(+), 494 deletions(-) rename docs/{reference => design}/repository.md (100%) delete mode 100644 docs/guide/development.md create mode 100644 docs/guildline/development-constraints.md rename docs/{guide => reference}/agent.md (98%) rename docs/{guide => reference}/deployment.md (100%) rename docs/{guide => reference}/server.md (100%) rename docs/{guide => reference}/upgrade.md (100%) diff --git a/AGENTS.md b/AGENTS.md index 1304199b..41b9d17d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,56 +1,87 @@ # AGENTS.md -本文件是 OpenFlare 的 AI 接手入口,不承载详细设计、规范和计划。接手项目时,先按顺序阅读以下 VitePress 文档源文件: +本文件是 OpenFlare 的 AI 接手入口,不承载详细设计、规范和计划。接手项目时,请根据以下分层文档指引进行阅读与开发: -1. [docs/design/index.md](./docs/design/index.md) - 作用:理解当前 MVP 的产品范围、系统边界、核心对象和长期约束。 +## 1. 核心必读文档(Level 3 & Level 4)- 必须阅读 ⚠️ -2. [docs/design/architecture.md](./docs/design/architecture.md) - 作用:理解 Server、Agent、OpenResty 与前端的职责边界。 +为了理解 OpenFlare 的设计理念、产品边界、核心机制以及代码编写的工程约束,**AI 在接手项目时必须首先且完整阅读以下文档**: -3. [docs/design/release-model.md](./docs/design/release-model.md) - 作用:理解配置发布、激活、回滚与 Agent 应用模型。 +### Level 3: 面向贡献者的参阅文档 (Contributor References) +* **[docs/design/index.md](./docs/design/index.md)** + *作用:理解当前 MVP 的产品范围、系统边界、核心对象和长期约束。* +* **[docs/design/architecture.md](./docs/design/architecture.md)** + *作用:理解 Server、Agent、OpenResty 与前端的职责边界与网络拓扑。* +* **[docs/design/release-model.md](./docs/design/release-model.md)** + *作用:理解配置发布、激活、回滚与 Agent 节点配置应用的模型。* +* **[docs/design/development.md](./docs/design/development.md)** + *作用:了解如何搭建本地开发环境,运行后端 Server、Agent 和前端开发服务器,以及运行测试与构建的命令。* +* **[docs/design/repository.md](./docs/design/repository.md)** + *作用:熟悉仓库的整体物理结构和各子目录的职责。* -4. [docs/design/development.md](./docs/design/development.md) - 作用:理解当前开发规范、阶段原则、分层约束、数据模型边界、API 约定、Agent 约束、前端规范与测试要求。 +### Level 4: 面向 AI 的开发指导规范 (AI Guidelines) +* **[docs/guildline/development-constraints.md](./docs/guildline/development-constraints.md)** + *作用:掌握核心后端/Agent/前端分层约束、数据模型规范、数据库迁移升级协议、API 与鉴权设计准则。* +* **[docs/guildline/Guidelines.md](./docs/guildline/Guidelines.md)** + *作用:通用的 Go 后端开发与高质量编码准则,包括架构、并发、错误处理、安全及工作流程。* +* **[docs/guildline/Project.md](./docs/guildline/Project.md)** + *作用:针对 OpenFlare 后端特定的控制器参数解析、响应处理、纯净工具类与数据库逻辑完全隔离、Go 泛型切片去重及 JSON 序列化避坑细则。* -5. [docs/guildline/](./docs/guildline/) 下的所有开发准则文件 - 作用:通用代码开发准则与特定项目开发准则(包含通用 Go 设计模式、并发安全、数据库事务约束、参数解析解析响应规范、Utils 与 GORM 彻底隔离、Slice 去重及 JSON 序列化避坑细则)。 +--- -6. [docs/guide/deployment.md](./docs/guide/deployment.md) - 作用:理解当前部署方式、Agent 接入、升级、卸载和联调步骤。 +## 2. 按需查阅文档(Level 2)- 根据需求阅读 💡 -7. [docs/reference/configuration.md](./docs/reference/configuration.md) - 作用:理解系统启动时支持的环境变量、命令行参数、运行时配置项和 Agent 配置字段。 +当开发任务涉及具体的系统部署、升级、接口联调或配置字段查阅时,**AI 应当根据需求阅读相应的参考手册**: -如任务涉及用户文档、贡献者入口或排障体验,还应阅读: +### Level 2: 面对高级用户/开发者的参阅文档 (Reference Manuals) +* **[docs/reference/configuration.md](./docs/reference/configuration.md)** + *作用:系统启动时支持的所有环境变量、命令行参数、运行时 Option 选项和 Agent 配置文件字段。* +* **[docs/reference/cli.md](./docs/reference/cli.md)** + *作用:Server 与 Agent 可用的命令行参数、安装/卸载脚本参数等参考。* +* **[docs/reference/api.md](./docs/reference/api.md)** + *作用:管理端 API 与 Agent API 的响应结构、路径和详细鉴权约定。* +* **[docs/reference/deployment.md](./docs/reference/deployment.md)** + *作用:理解 Server 和 Agent 的单机、Docker 部署配置,以及 Agent 接入、升级、卸载和联调步骤。* +* **[docs/reference/server.md](./docs/reference/server.md)** + *作用:如何配置系统配置、服务环境变量并正确启动 Server 服务。* +* **[docs/reference/agent.md](./docs/reference/agent.md)** + *作用:理解 Agent 接入的 discovery/agent 令牌鉴权机制、本地配置文件及 Docker 部署参数。* +* **[docs/reference/upgrade.md](./docs/reference/upgrade.md)** + *作用:Server 及各代理节点 Agent 的升级步骤与维护策略。* -* [docs/guide/quick-start.md](./docs/guide/quick-start.md):理解新用户从 0 到运行的最短路径。 -* [docs/guide/usage.md](./docs/guide/usage.md):理解网站配置、证书、发布、回滚和观测的基础用法。 -* [docs/guide/development.md](./docs/guide/development.md):理解本地开发、测试和构建命令。 -* [docs/guide/troubleshooting.md](./docs/guide/troubleshooting.md):理解常见失败症状与排查路径。 +--- -线上文档入口:https://open-flare.pages.dev +## 3. 新手与业务教程(Level 1)- 体验与排障参考 📘 + +如果任务涉及优化最终用户体验、丰富业务能力或排查常见故障,可参阅面向普通用户的指南: + +### Level 1: 面向新手用户的教程文档 (Novice Tutorials) +* **[docs/guide/quick-start.md](./docs/guide/quick-start.md)**:五分钟内基于 Docker Compose 快速跑起 Server 和首个 Agent 节点的完整闭环。 +* **[docs/guide/usage.md](./docs/guide/usage.md)**:反向代理网站、源站、证书托管、配置发布与回滚的常规界面操作与观测功能使用指南。 +* **[docs/guide/sso.md](./docs/guide/sso.md)**:系统如何配置 GitHub OAuth 及标准 OIDC 第三方登录,以及绑定本地账户的流程。 +* **[docs/guide/first-site.md](./docs/guide/first-site.md)**:从零开始配置、发布并验证第一个代理网站的完整步骤。 +* **[docs/guide/troubleshooting.md](./docs/guide/troubleshooting.md)**:常见数据库迁移、节点离线、OpenResty 校验失败、SSL 证书失效等故障的表现症状及标准排障路径。 + +--- ## 执行要求 * 如果实现内容超出 [产品边界](./docs/design/index.md),先修改设计文档,再继续编码。 -* 如果实现方式违反 [开发约束](./docs/design/development.md),应优先调整方案,而不是绕过规范。 +* 如果实现方式违反 [开发约束](./docs/guildline/development-constraints.md),应优先调整方案,而不是绕过规范。 * 如果实现方式涉及后端代码逻辑,必须严格遵循 [docs/guildline/](./docs/guildline/) 下的所有开发准则。 -* 如果需求与当前阶段原则冲突,优先遵守 [开发约束](./docs/design/development.md) 中的变更准入与验收标准。 -* 如果任务涉及前端改造或管理端 UI,必须同时遵守 [开发约束](./docs/design/development.md) 中的前端规范。 +* 如果需求与当前阶段原则冲突,优先遵守 [开发约束](./docs/guildline/development-constraints.md) 中的变更准入与验收标准。 +* 如果任务涉及前端改造或管理端 UI,必须同时遵守 [开发约束](./docs/guildline/development-constraints.md) 中的前端规范。 ## 文档维护要求 -当以下内容发生变化时,应同步更新对应中文文档, 不要同步英文文档: +当以下内容发生变化时,应同步更新对应中文文档,不要同步英文文档: * 产品范围或系统边界变化:更新 `docs/design/index.md` * 系统结构、模块职责变化:更新 `docs/design/architecture.md` * 发布、同步、回滚模型变化:更新 `docs/design/release-model.md` -* 业务分层、数据模型边界、接口约定、阶段原则、测试基线变化:更新 `docs/design/development.md` +* 业务分层、数据模型边界、接口约定、阶段原则、测试基线变化:更新 `docs/guildline/development-constraints.md` * 后端开发规范、代码质量要求、重构模式、去重逻辑与避坑指南变化:更新 `docs/guildline/` 下的对应开发准则文件 -* 产品启动、部署、升级、联调方式变化:更新 `docs/guide/quick-start.md`、`docs/guide/deployment.md` 和 `README.md` +* 产品启动、部署、升级、联调方式变化:更新 `docs/guide/quick-start.md`、`docs/reference/deployment.md` 和 `README.md` * 用户操作路径、常见场景变化:更新 `docs/guide/usage.md` -* 本地开发、测试、构建方式变化:更新 `docs/guide/development.md` +* 本地开发、测试、构建方式变化:更新 `docs/design/development.md` * 常见故障、排查路径变化:更新 `docs/guide/troubleshooting.md` * 环境变量、命令行参数、运行时配置、Agent 配置变化:更新 `docs/reference/configuration.md` diff --git a/docs/config.ts b/docs/config.ts index bed6a091..2bdd942e 100644 --- a/docs/config.ts +++ b/docs/config.ts @@ -69,13 +69,8 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] { { text: '概览', link: '' }, { text: '快速开始', link: 'quick-start' }, { text: '基础使用', link: 'usage' }, - { text: '部署说明', link: 'deployment' }, { text: 'SSO 登录配置', link: 'sso' }, - { text: '启动 Server', link: 'server' }, - { text: '接入 Agent', link: 'agent' }, { text: '发布第一份配置', link: 'first-site' }, - { text: '升级与维护', link: 'upgrade' }, - { text: '本地开发', link: 'development' }, { text: '故障排查', link: 'troubleshooting' } ] } @@ -88,10 +83,14 @@ function sidebarReference(): DefaultTheme.SidebarItem[] { text: '参考', items: [ { text: '概览', link: '' }, + { text: '系统架构', link: '../design/architecture' }, + { text: '启动 Server', link: 'server' }, + { text: '接入 Agent', link: 'agent' }, + { text: '部署说明', link: 'deployment' }, + { text: '升级与维护', link: 'upgrade' }, { text: '配置项', link: 'configuration' }, { text: '命令与脚本', link: 'cli' }, - { text: 'API 约定', link: 'api' }, - { text: '仓库结构', link: 'repository' } + { text: 'API 约定', link: 'api' } ] } ] @@ -105,7 +104,8 @@ function sidebarDesign(): DefaultTheme.SidebarItem[] { { text: '产品边界', link: '' }, { text: '系统架构', link: 'architecture' }, { text: '发布模型', link: 'release-model' }, - { text: '开发约束', link: 'development' } + { text: '本地开发', link: 'development' }, + { text: '仓库结构', link: 'repository' } ] } ] diff --git a/docs/design/architecture.md b/docs/design/architecture.md index 037a47c0..16c696bb 100644 --- a/docs/design/architecture.md +++ b/docs/design/architecture.md @@ -142,5 +142,5 @@ WAF 在 OpenResty `access_by_lua_file` 阶段执行。规则来自当前激活 1. [产品边界](./index.md) 2. [发布模型](./release-model.md) -3. [开发约束](./development.md) -4. [仓库结构](../reference/repository.md) +3. [开发约束](../guildline/development-constraints.md) +4. [仓库结构](./repository.md) diff --git a/docs/design/development.md b/docs/design/development.md index 64c5d9a5..8be8f1d6 100644 --- a/docs/design/development.md +++ b/docs/design/development.md @@ -1,316 +1,188 @@ -# 开发约束 +# 本地开发 -你会学到:OpenFlare 代码修改的准入标准、后端/Agent/前端分层约束、数据模型边界、API 约定、数据库迁移要求和测试交付基线。 +你会学到:如何搭建 OpenFlare 的本地开发环境、启动 Server、Agent 和管理端前端,运行测试与构建命令,并理解贡献代码前需要遵守的边界。 -本文档融合原开发规范、前端规范与开发计划,是 OpenFlare `1.0.0` 之后的工程约束入口。 +本页面向贡献者。产品边界、数据模型约束、API 约定和前端分层规范以 [开发约束](../guildline/development-constraints.md) 为准;本页只提供可执行的本地开发流程。 -## 当前结论 +## 仓库结构 -* 第一版至第六版的主线能力已经全部完成。 -* `1.0.0` 是当前正式基线。 -* 已完成阶段的过程性任务以代码、测试与 Git 历史为准。 -* 新工作优先以缺陷修复、可维护性改进、文档与测试补强为主。 - -当前开发优先级: - -1. 稳定性。 -2. 升级与回滚链路可靠性。 -3. 文档准确性。 -4. 测试覆盖补强。 -5. 在既有边界内的小步迭代。 - -## 变更准入 - -新需求进入实现前,按以下顺序判断: - -1. 是否符合 [产品边界](./)。 -2. 是否符合本文档的后端、Agent 与前端约束。 -3. 是否会破坏现有发布、同步、回滚或升级主链路。 -4. 是否需要同步更新部署、配置、README 或文档站页面。 - -如果需求超出边界或引入新基础设施,应先更新设计文档,再开始实现。 - -任何合入正式基线的改动,至少应满足: - -* 不破坏 Agent 心跳、同步、发布与回滚主链路。 -* 不破坏现有 OpenResty 主配置托管模型。 -* 不降低总览、节点详情与访问分析的既有可用性。 -* 有与风险相称的测试或联调验证。 -* 文档与代码保持一致。 - -## 技术基线 - -Server: - -* Go 1.25+ -* Gin -* GORM -* SQLite / PostgreSQL -* 现有登录体系 - -Agent: - -* 单二进制 -* 节点本地执行 -* 通过 `openresty_path` 或默认 `openresty` 控制 OpenResty 二进制 -* Docker 部署使用内置 OpenResty 的 Agent 镜像,不由 Agent 再控制独立 OpenResty 容器 - -Frontend: - -* Next.js 15 App Router -* React 19 -* TypeScript 5 -* Tailwind CSS 4 -* TanStack Query -* React Hook Form + Zod -* Zustand 仅用于轻量客户端状态 -* ESLint + Prettier -* Vitest + Testing Library + Playwright -* pnpm - -## Server 分层 - -| 目录 | 职责 | +| 路径 | 职责 | | --- | --- | -| `controller/` | 参数解析、调用 service、返回响应 | -| `service/` | 业务逻辑、校验、事务编排、渲染 | -| `model/` | 模型定义与持久化 | -| `router/` | 路由注册 | -| `middleware/` | 认证、鉴权、限流等横切逻辑 | -| `common/` | 配置、全局状态与初始化入口 | -| `utils/` | 纯工具函数与通用 helper | +| `openflare_server` | Gin + GORM + SQLite/PostgreSQL 单体控制面 | +| `openflare_server/web` | Next.js 管理端前端,静态导出后由 Go Server 托管 | +| `openflare_agent` | Go 单体 Agent,运行在节点侧 | +| `scripts` | Agent 安装与卸载脚本 | +| `docs` | VitePress 文档站 | -禁止在 `controller/` 堆积业务逻辑,禁止在 `middleware/` 实现业务流程,禁止为简单需求新增平台层抽象。 +## 环境要求 -## Agent 分层 +| 项目 | 要求 | +| --- | --- | +| Go | `1.25+` | +| Node.js | `18+` | +| pnpm | 推荐通过 `corepack enable` 使用项目声明版本 | +| Docker | Server 容器、本地联调和 Agent Docker 镜像需要 | +| OpenResty | 本地运行 Agent 时需要可执行 `openresty` | +| PostgreSQL | 可选;未配置时 Server 使用 SQLite | -Agent 保持现有模块边界: +## 初始化前端依赖 -* `config` -* `heartbeat` -* `sync` -* `openresty` / `nginx` -* `state` -* `httpclient` -* `protocol` -* `internal/updater` - -要求: - -* 每个模块职责单一。 -* 外部命令调用集中封装。 -* 状态落盘与配置落盘分离。 - -## Frontend 分层 - -推荐目录: - -```text -app/ -components/ -features/ -lib/ -hooks/ -store/ -types/ -styles/ -tests/ +```bash +cd openflare_server/web +corepack enable +pnpm install ``` -职责约束: +构建供 Go Server 托管的静态产物: -* `app/`:路由、布局、页面组装。 -* `features/`:按业务域组织模块。 -* `components/`:跨 feature 复用组件。 -* `lib/`:请求客户端、环境变量、工具函数、常量。 -* `store/`:少量跨页面 UI 状态。 -* `types/`:共享类型定义。 +```bash +pnpm build +``` -页面文件只负责获取路由参数、组织页面结构、调用 feature 组件;不应手写复杂 API 细节、复杂表单校验逻辑或维护大量彼此耦合的局部状态。 +## 启动 Server -## 数据模型规范 +SQLite 模式: -当前有效实体: +```bash +cd openflare_server +export SESSION_SECRET='dev-session-secret' +export SQLITE_PATH='./openflare-dev.db' +export LOG_LEVEL='debug' +go run . +``` -* `proxy_routes` -* `origins` -* `config_versions` -* `nodes` -* `auth_sources` -* `external_accounts` -* `node_system_profiles` -* `apply_logs` -* `tls_certificates` -* `managed_domains` -* `node_request_reports` -* `node_access_logs` -* `node_metric_snapshots` -* `traffic_analytics_rollups` -* `node_health_events` -* `options` -* `waf_rule_groups` -* `waf_rule_group_bindings` +PostgreSQL 模式: -通用约束: +```bash +cd openflare_server +export SESSION_SECRET='dev-session-secret' +export DSN='postgres://openflare:secret@127.0.0.1:5432/openflare?sslmode=disable' +export LOG_LEVEL='debug' +go run . +``` -* 不新增平台化对象,除非设计文档明确要求。 -* `origins` 仅作为可复用源站地址目录,字段保持轻量。 -* `proxy_routes` 以“网站配置”作为聚合边界,必须包含唯一 `site_name` 与非空 `domains` 列表。 -* `proxy_routes.domains` 中的每个域名都必须全局唯一,列表第一项视为主域名。 -* `proxy_routes` 继续允许保存一个或多个上游地址用于负载均衡,但不引入独立 `origin_pool`。 -* 遗留 `domain` 字段只能作为 `domains[0]` 的兼容镜像;新代码不得继续以该字段作为唯一业务输入。 -* `proxy_routes` 如关联 `origins`,必须同时保存可直接渲染的 `origin_url`。 -* 上游统一使用 named `upstream` + keepalive;单上游如带 base path 或 query,应在 `proxy_pass` 上补回 URI,多上游仅允许纯 `scheme://host[:port]`。 -* 流量限制、反向代理与缓存配置当前都归属站点级 `proxy_routes`。 -* HTTPS 证书绑定必须通过与 `domains` 平行的 `domain_cert_ids` 逐域名保存;未绑定证书的域名不得参与 HTTPS 渲染。 -* WAF 全局规则组默认应用到所有网站,自定义规则组通过 `waf_rule_group_bindings` 绑定到网站配置;发布时必须进入完整版本快照。 -* `config_versions` 必须保存完整快照与渲染结果。 -* 全局同时只能有一个激活版本。 -* 回滚通过重新激活旧版本实现。 -* `nodes` 只保留控制面状态与低频摘要。 -* 观测数据必须按节点与时间窗口关联,快照与聚合结果采用追加式模型。 -* 原始访问明细必须有受控保留策略。 -* `auth_sources` 仅保存管理端第三方登录源配置,当前支持 `github` 与 `oidc`。 -* `external_accounts` 是第三方账号与本地用户的唯一绑定来源;旧 `users.github_id` 仅用于兼容迁移,不得作为新登录流程的业务输入。 +默认访问地址: -## 数据库迁移 +```text +http://localhost:3000 +``` -任何涉及表结构、索引、列类型、分表规则或内部持久化元数据的修改,都必须同步提升数据库版本号。 +默认账号是 `root` / `123456`。 -数据库版本号定义在 `openflare_server/model`,不得只依赖 `AutoMigrate` 隐式升级存量数据库。 +## 启动前端开发服务器 -每次提升数据库版本号时,必须补充从上一版本升级到新版本的显式迁移方法。迁移方法必须包含升级后的校验逻辑;只有校验通过,才能写入新的数据库版本记录。 +前端开发服务器默认监听 `3001`,并通过 `NEXT_DEV_BACKEND_URL` 代理到后端: -v1-v7 视为历史初始基线,不再维护逐版本升级文件。从 v8 起,数据库迁移必须放在 `openflare_server/model/migrate` 目录中,并以目标版本命名文件,例如 `v16.go`。每个版本文件通过 `init()` 注册自己的迁移,当前数据库版本取已注册迁移的最大目标版本。不得为了整理文件而改变已发布 v8+ 迁移的语义。 +```bash +cd openflare_server/web +export NEXT_DEV_BACKEND_URL='http://127.0.0.1:3000' +pnpm dev +``` -执行数据库升级时必须按以下步骤完成: +访问: -1. 判断是否需要升级数据库版本:凡是新增/删除/重命名表、字段、索引、约束、列类型、分表规则,或改变持久化数据语义,都必须升级。 -2. 新增 `openflare_server/model/migrate/vN.go`,其中 `N` 为目标版本号。文件头部必须包含注释,说明本次升级了什么内容,以及为什么需要升级。 -3. 在 `vN.go` 中实现 `VN()`,并在 `init()` 中调用 `Register(VN())`。`FromVersion` 必须等于 `N-1`,`ToVersion` 必须等于 `N`。 -4. 在 `migrateVN` 中写入升级逻辑。可通过 `Context` 调用 `ApplyCurrentSchema`、历史 backfill、默认数据初始化等公共能力;复杂数据修复必须显式处理,不得只依赖 `AutoMigrate`。 -5. 在 `validateVN` 中写入升级后的校验逻辑。校验至少要覆盖新增表/字段/索引是否存在、关键默认数据是否存在、必要的数据回填是否成功。 -6. 如果新迁移需要新的公共 backfill 或校验辅助函数,将其放在 `openflare_server/model/migrations.go` 或更合适的 model 文件中,并通过 `Context` 暴露给 `model/migrate`,避免子包反向 import `model` 造成循环依赖。 -7. 补充迁移测试:至少覆盖从 `N-1` 老库升级到 `N` 后 schema version、字段/表结构、关键数据回填和校验结果。注册表连续性由 `model/migrate` 测试兜底,但具体业务迁移仍必须有测试。 -8. 同步更新设计/开发文档;如果管理端 API、配置项或用户可见行为变化,还要同步更新对应指南、配置参考和 Swagger 文档。 +```text +http://localhost:3001 +``` -新包启动后必须先检查数据库当前版本,再按顺序逐步升级到目标版本;禁止跳过中间升级步骤直接写目标版本。 +## 启动 Agent -空库初始化可以直接建立当前版本结构,但初始化完成后仍必须执行同版本校验,并落库当前数据库版本。 - -如果迁移失败或校验失败,启动流程必须中止,且不得提升数据库版本记录。涉及数据库版本变更的提交,必须补充对应的迁移测试或等效回归测试。 - -## API 与鉴权 - -管理端与 Agent API 统一使用 JSON。成功与失败都必须返回清晰 `message`: +创建本地 `agent.json`: ```json { - "success": true, - "message": "", - "data": {} + "server_url": "http://127.0.0.1:3000", + "agent_token": "replace-with-node-auth-token", + "data_dir": "./data", + "heartbeat_interval": 10000, + "request_timeout": 10000 } ``` -约定: +运行: -* Agent API 固定放在 `/api/agent/*`。 -* 总览与节点详情优先使用专用聚合接口。 -* 管理端变更类接口统一使用 `POST`;只读接口使用 `GET`。 -* 管理端继续复用现有登录、角色与 Session。 -* 第三方登录统一通过认证源 API 进入,认证源管理接口必须要求 Root Session。 -* `/api/status` 只能返回已启用认证源的公开字段,不得返回 Client Secret。 -* 第三方账号未绑定且注册关闭时,应提供绑定已有账号流程,不得自动创建用户。 -* Agent 正式请求统一使用节点专属 `agent_token`。 -* 首次接入可使用全局 `discovery_token`。 -* Agent 请求头统一使用 `X-Agent-Token`。 +```bash +cd openflare_agent +export LOG_LEVEL='debug' +go run ./cmd/agent -config ./agent.json +``` -禁止暴露远程 shell 或任意命令执行入口,禁止在日志中打印完整 Token,禁止绕过占位符约束保存不可渲染的主配置模板。 +未配置 `openresty_path` 时,Agent 默认调用 `openresty`。调试时可显式配置 `openresty_path`、`main_config_path`、`route_config_path`、`access_log_path`、`cert_dir`、`lua_dir` 和 `runtime_config_dir`。 -## 发布与运行 +## 测试 -发布逻辑必须保持: +Server: -* 发布时读取全部启用的 `proxy_routes`。 -* 同时读取 OpenResty 主配置参数、反代性能参数与缓存参数。 -* 生成完整 OpenResty 配置。 -* 计算 `checksum`。 -* 写入 `config_versions`。 -* 通过切换 `is_active` 激活版本。 +```bash +cd openflare_server +GOCACHE=/tmp/openflare-go-cache go test ./... +``` -版本约束: +Agent: -* 版本号格式固定为 `YYYYMMDD-NNN`。 -* 不在线修改历史版本。 -* 不做按节点分组的差异化版本。 -* 预览与 diff 是只读能力,不产生发布记录。 +```bash +cd openflare_agent +GOCACHE=/tmp/openflare-go-cache go test ./... +``` -Agent 必须满足: +Frontend: -* 启动后读取或生成本地 `node_id`。 -* 周期性心跳与同步。 -* 常规同步优先依据 heartbeat 返回的版本摘要判断。 -* WS 连接升级开启且连接成功时,Agent 可通过 WS 接收激活版本摘要并立即同步;WS 失败或断开必须退回 HTTP heartbeat。 -* 发现新版本时先备份旧文件。 -* 写入主配置、路由配置与必要证书文件。 -* 写入 WAF/PoW 运行时配置,并确保 WAF Lua 资源由 Agent 统一管理。 -* 写入新配置后执行 `openresty -t -c `,再 reload;reload 发现运行时未启动时允许直接启动 OpenResty。 -* 周期性运行时健康检查不得调用 `openresty -t`,避免健康探针触发 upstream 域名同步解析;应优先请求本地 `openresty_observability_port` 上的 `/openflare/stub_status`,以 HTTP `200 OK` 作为 OpenResty 主进程和 worker 正在提供服务的判断依据。 -* 新配置激活失败时必须先尝试用目标配置恢复运行,再回滚到旧配置并重新拉起 OpenResty。 -* 回滚后 OpenResty 恢复正常时上报警告;如果本地没有历史主配置可恢复,必须允许写入内置安全兜底配置并拉起对外只监听 `80` 端口、统一返回 `503` 的 OpenResty 运行态;兜底配置仍需保留本地 `stub_status` 健康检查入口。 -* 兜底运行态不得清除失败目标的阻断状态;应用记录必须能体现目标版本失败但 fallback runtime 已启动。存在历史主配置但回滚后仍无法恢复运行时上报失败。 -* 某个目标 `version + checksum` 一旦应用失败并回退,Agent 必须在本地状态中阻断该目标的重复应用。 -* Agent 维护本地 MaxMind mmdb 时,下载或刷新失败只能记录警告,不得阻断心跳、同步、配置应用或 OpenResty 健康检查。 +```bash +cd openflare_server/web +pnpm lint +pnpm typecheck +pnpm test +pnpm test:e2e +``` -## 前端请求、状态与类型 +Docs: -所有 API 请求必须统一经过 `lib/api/`: +```bash +cd docs +pnpm build +``` -* 统一处理 `success/message/data` 响应结构。 -* 统一处理鉴权失效、网络异常和通用错误消息。 -* 统一维护资源接口与请求路径。 +## 构建 -状态分层: +管理端静态产物: -* 服务端状态:TanStack Query。 -* 页面临时状态:组件内部 `useState`。 -* 跨页面 UI 状态:Zustand。 +```bash +cd openflare_server/web +pnpm build +``` -要求开启 TypeScript 严格模式,禁止滥用 `any`,API 响应、表单输入、业务实体必须有明确类型。 +Server 二进制: -## 表单、交互、样式与主题 +```bash +cd openflare_server +go build -o openflare-server . +``` -表单统一使用 React Hook Form 与 Zod。 +Agent 二进制: -高风险操作必须二次确认、展示操作对象名称,并明确成功与失败反馈。 +```bash +cd openflare_agent +go build -o openflare-agent ./cmd/agent +``` -样式原则: +## 调试入口 -* 统一使用 Tailwind CSS 与现有 token 体系。 -* 优先复用已有基础组件与布局组件。 -* 保持视觉层级、留白与语义颜色一致。 +| 场景 | 命令或位置 | +| --- | --- | +| Server 日志 | `LOG_LEVEL=debug go run .` | +| Agent 日志 | `LOG_LEVEL=debug go run ./cmd/agent -config ./agent.json` | +| Swagger | `http://localhost:3000/swagger/index.html` | +| 前端 API 代理 | `NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev` | +| OpenResty 配置校验 | `openresty -t -c ./data/etc/nginx/nginx.conf` | -主题要求: +## 代码风格与变更准入 -* 同时支持 `light`、`dark`、`system`。 -* 用户选择必须持久化。 -* 首屏尽量避免主题闪烁。 +贡献前先确认: -## 测试与交付 +1. 需求符合 [产品边界](./index.md)。 +2. 实现符合 [开发约束](../guildline/development-constraints.md)。 +3. 不破坏发布、同步、回滚或升级主链路。 +4. 涉及配置、部署、API 或产品边界时同步更新文档。 +5. 风险较高的修改补充测试或等效联调验证。 -* 关键业务逻辑必须有单元测试或等效回归测试。 -* Agent 主链路修改必须验证同步、应用与回滚。 -* 前端页面至少覆盖加载态、空态、错误态与成功反馈。 -* Go 版本调整时,同步检查 `go.mod`、Dockerfile 与 CI 工作流。 - -## 后续维护方式 - -后续规划不再按“大版本阶段文档”维护,而采用以下方式: - -* 产品边界变动:更新 [产品边界](./)。 -* 工程约束变动:更新本文档。 -* 部署与配置变动:更新 [部署说明](../guide/deployment.md)、[配置项](../reference/configuration.md) 与 README。 - -如果未来出现明确的新阶段目标,再单独新增专项计划文档;不要把已完成的历史计划继续堆回本文档。 - -当前专项“网站级规则与配置界面改造”的模型边界已纳入 [产品边界](./),执行时仍按数据模型、接口、前端页面、迁移测试与文档联动的顺序推进。 +数据库结构变更必须提升数据库版本号,并补充从上一版本到新版本的显式迁移方法和校验逻辑。 diff --git a/docs/design/index.md b/docs/design/index.md index 656d3947..2760e042 100644 --- a/docs/design/index.md +++ b/docs/design/index.md @@ -164,8 +164,8 @@ WAF 以规则组为配置边界。系统固定一个全局规则组,默认应 * 产品范围或系统边界变化时更新本文档。 * 系统结构或模块职责变化时更新 [系统架构](./architecture.md)。 * 发布、同步、回滚模型变化时更新 [发布模型](./release-model.md)。 -* 开发约束、代码规范、接口约定变化时更新 [开发约束](./development.md)。 -* 部署方式变化时更新 [部署说明](../guide/deployment.md) 与 README。 +* 开发约束、代码规范、接口约定变化时更新 [开发约束](../guildline/development-constraints.md)。 +* 部署方式变化时更新 [部署说明](../reference/deployment.md) 与 README。 * 配置项变化时更新 [配置项参考](../reference/configuration.md)。 * 已完成阶段不再以“版本计划”形式回填。 * 新阶段开始前,先补设计,再进入实现。 diff --git a/docs/reference/repository.md b/docs/design/repository.md similarity index 100% rename from docs/reference/repository.md rename to docs/design/repository.md diff --git a/docs/guide/development.md b/docs/guide/development.md deleted file mode 100644 index 03136fd8..00000000 --- a/docs/guide/development.md +++ /dev/null @@ -1,188 +0,0 @@ -# 本地开发 - -你会学到:如何搭建 OpenFlare 的本地开发环境、启动 Server、Agent 和管理端前端,运行测试与构建命令,并理解贡献代码前需要遵守的边界。 - -本页面向贡献者。产品边界、数据模型约束、API 约定和前端分层规范以 [开发约束](../design/development.md) 为准;本页只提供可执行的本地开发流程。 - -## 仓库结构 - -| 路径 | 职责 | -| --- | --- | -| `openflare_server` | Gin + GORM + SQLite/PostgreSQL 单体控制面 | -| `openflare_server/web` | Next.js 管理端前端,静态导出后由 Go Server 托管 | -| `openflare_agent` | Go 单体 Agent,运行在节点侧 | -| `scripts` | Agent 安装与卸载脚本 | -| `docs` | VitePress 文档站 | - -## 环境要求 - -| 项目 | 要求 | -| --- | --- | -| Go | `1.25+` | -| Node.js | `18+` | -| pnpm | 推荐通过 `corepack enable` 使用项目声明版本 | -| Docker | Server 容器、本地联调和 Agent Docker 镜像需要 | -| OpenResty | 本地运行 Agent 时需要可执行 `openresty` | -| PostgreSQL | 可选;未配置时 Server 使用 SQLite | - -## 初始化前端依赖 - -```bash -cd openflare_server/web -corepack enable -pnpm install -``` - -构建供 Go Server 托管的静态产物: - -```bash -pnpm build -``` - -## 启动 Server - -SQLite 模式: - -```bash -cd openflare_server -export SESSION_SECRET='dev-session-secret' -export SQLITE_PATH='./openflare-dev.db' -export LOG_LEVEL='debug' -go run . -``` - -PostgreSQL 模式: - -```bash -cd openflare_server -export SESSION_SECRET='dev-session-secret' -export DSN='postgres://openflare:secret@127.0.0.1:5432/openflare?sslmode=disable' -export LOG_LEVEL='debug' -go run . -``` - -默认访问地址: - -```text -http://localhost:3000 -``` - -默认账号是 `root` / `123456`。 - -## 启动前端开发服务器 - -前端开发服务器默认监听 `3001`,并通过 `NEXT_DEV_BACKEND_URL` 代理到后端: - -```bash -cd openflare_server/web -export NEXT_DEV_BACKEND_URL='http://127.0.0.1:3000' -pnpm dev -``` - -访问: - -```text -http://localhost:3001 -``` - -## 启动 Agent - -创建本地 `agent.json`: - -```json -{ - "server_url": "http://127.0.0.1:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "./data", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -运行: - -```bash -cd openflare_agent -export LOG_LEVEL='debug' -go run ./cmd/agent -config ./agent.json -``` - -未配置 `openresty_path` 时,Agent 默认调用 `openresty`。调试时可显式配置 `openresty_path`、`main_config_path`、`route_config_path`、`access_log_path`、`cert_dir`、`lua_dir` 和 `runtime_config_dir`。 - -## 测试 - -Server: - -```bash -cd openflare_server -GOCACHE=/tmp/openflare-go-cache go test ./... -``` - -Agent: - -```bash -cd openflare_agent -GOCACHE=/tmp/openflare-go-cache go test ./... -``` - -Frontend: - -```bash -cd openflare_server/web -pnpm lint -pnpm typecheck -pnpm test -pnpm test:e2e -``` - -Docs: - -```bash -cd docs -pnpm build -``` - -## 构建 - -管理端静态产物: - -```bash -cd openflare_server/web -pnpm build -``` - -Server 二进制: - -```bash -cd openflare_server -go build -o openflare-server . -``` - -Agent 二进制: - -```bash -cd openflare_agent -go build -o openflare-agent ./cmd/agent -``` - -## 调试入口 - -| 场景 | 命令或位置 | -| --- | --- | -| Server 日志 | `LOG_LEVEL=debug go run .` | -| Agent 日志 | `LOG_LEVEL=debug go run ./cmd/agent -config ./agent.json` | -| Swagger | `http://localhost:3000/swagger/index.html` | -| 前端 API 代理 | `NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev` | -| OpenResty 配置校验 | `openresty -t -c ./data/etc/nginx/nginx.conf` | - -## 代码风格与变更准入 - -贡献前先确认: - -1. 需求符合 [产品边界](../design/index.md)。 -2. 实现符合 [开发约束](../design/development.md)。 -3. 不破坏发布、同步、回滚或升级主链路。 -4. 涉及配置、部署、API 或产品边界时同步更新文档。 -5. 风险较高的修改补充测试或等效联调验证。 - -数据库结构变更必须提升数据库版本号,并补充从上一版本到新版本的显式迁移方法和校验逻辑。 diff --git a/docs/guide/index.md b/docs/guide/index.md index fe1d8fcf..8aa51aaa 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -10,7 +10,7 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站 1. [快速开始](./quick-start.md):用 Docker Compose 启动 Server,登录管理端,并接入第一个 Agent。 2. [基础使用](./usage.md):了解网站配置、源站、证书、发布、回滚和观测的常见操作。 -3. [部署说明](./deployment.md):把 Server 和 Agent 放到更接近生产的环境中运行。 +3. [部署说明](../reference/deployment.md):把 Server 和 Agent 放到更接近生产的环境中运行。 4. [配置项参考](../reference/configuration.md):查 Server 环境变量、运行时 Option 和 Agent 配置字段。 5. [故障排查](./troubleshooting.md):按症状排查登录、数据库、节点同步、OpenResty 应用和前端构建问题。 @@ -20,11 +20,11 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站 | --- | --- | | 5 分钟内跑起管理端 | [快速开始](./quick-start.md) | | 发布第一条反向代理配置 | [发布第一份配置](./first-site.md) | -| 接入或重装节点 Agent | [接入 Agent](./agent.md) | -| 从源码启动 Server | [启动 Server](./server.md) | +| 接入或重装节点 Agent | [接入 Agent](../reference/agent.md) | +| 从源码启动 Server | [启动 Server](../reference/server.md) | | 配置 GitHub 或 OIDC 登录 | [SSO 登录配置](./sso.md) | -| 升级 Server 或 Agent | [升级与维护](./upgrade.md) | -| 参与开发或修复问题 | [本地开发](./development.md) 与 [开发约束](../design/development.md) | +| 升级 Server 或 Agent | [升级与维护](../reference/upgrade.md) | +| 参与开发或修复问题 | [本地开发](../design/development.md) 与 [开发约束](../guildline/development-constraints.md) | | 理解架构和发布模型 | [系统架构](../design/architecture.md) 与 [发布模型](../design/release-model.md) | ## 文档分区 diff --git a/docs/guildline/development-constraints.md b/docs/guildline/development-constraints.md new file mode 100644 index 00000000..dde1a004 --- /dev/null +++ b/docs/guildline/development-constraints.md @@ -0,0 +1,316 @@ +# 开发约束 + +你会学到:OpenFlare 代码修改的准入标准、后端/Agent/前端分层约束、数据模型边界、API 约定、数据库迁移要求和测试交付基线。 + +本文档融合原开发规范、前端规范与开发计划,是 OpenFlare `1.0.0` 之后的工程约束入口。 + +## 当前结论 + +* 第一版至第六版的主线能力已经全部完成。 +* `1.0.0` 是当前正式基线。 +* 已完成阶段的过程性任务以代码、测试与 Git 历史为准。 +* 新工作优先以缺陷修复、可维护性改进、文档与测试补强为主。 + +当前开发优先级: + +1. 稳定性。 +2. 升级与回滚链路可靠性。 +3. 文档准确性。 +4. 测试覆盖补强。 +5. 在既有边界内的小步迭代。 + +## 变更准入 + +新需求进入实现前,按以下顺序判断: + +1. 是否符合 [产品边界](../design/index.md)。 +2. 是否符合本文档的后端、Agent 与前端约束。 +3. 是否会破坏现有发布、同步、回滚或升级主链路。 +4. 是否需要同步更新部署、配置、README 或文档站页面。 + +如果需求超出边界或引入新基础设施,应先更新设计文档,再开始实现。 + +任何合入正式基线的改动,至少应满足: + +* 不破坏 Agent 心跳、同步、发布与回滚主链路。 +* 不破坏现有 OpenResty 主配置托管模型。 +* 不降低总览、节点详情与访问分析的既有可用性。 +* 有与风险相称的测试或联调验证。 +* 文档与代码保持一致。 + +## 技术基线 + +Server: + +* Go 1.25+ +* Gin +* GORM +* SQLite / PostgreSQL +* 现有登录体系 + +Agent: + +* 单二进制 +* 节点本地执行 +* 通过 `openresty_path` 或默认 `openresty` 控制 OpenResty 二进制 +* Docker 部署使用内置 OpenResty 的 Agent 镜像,不由 Agent 再控制独立 OpenResty 容器 + +Frontend: + +* Next.js 15 App Router +* React 19 +* TypeScript 5 +* Tailwind CSS 4 +* TanStack Query +* React Hook Form + Zod +* Zustand 仅用于轻量客户端状态 +* ESLint + Prettier +* Vitest + Testing Library + Playwright +* pnpm + +## Server 分层 + +| 目录 | 职责 | +| --- | --- | +| `controller/` | 参数解析、调用 service、返回响应 | +| `service/` | 业务逻辑、校验、事务编排、渲染 | +| `model/` | 模型定义与持久化 | +| `router/` | 路由注册 | +| `middleware/` | 认证、鉴权、限流等横切逻辑 | +| `common/` | 配置、全局状态与初始化入口 | +| `utils/` | 纯工具函数与通用 helper | + +禁止在 `controller/` 堆积业务逻辑,禁止在 `middleware/` 实现业务流程,禁止为简单需求新增平台层抽象。 + +## Agent 分层 + +Agent 保持现有模块边界: + +* `config` +* `heartbeat` +* `sync` +* `openresty` / `nginx` +* `state` +* `httpclient` +* `protocol` +* `internal/updater` + +要求: + +* 每个模块职责单一。 +* 外部命令调用集中封装。 +* 状态落盘与配置落盘分离。 + +## Frontend 分层 + +推荐目录: + +```text +app/ +components/ +features/ +lib/ +hooks/ +store/ +types/ +styles/ +tests/ +``` + +职责约束: + +* `app/`:路由、布局、页面组装。 +* `features/`:按业务域组织模块。 +* `components/`:跨 feature 复用组件。 +* `lib/`:请求客户端、环境变量、工具函数、常量。 +* `store/`:少量跨页面 UI 状态。 +* `types/`:共享类型定义。 + +页面文件只负责获取路由参数、组织页面结构、调用 feature 组件;不应手写复杂 API 细节、复杂表单校验逻辑或维护大量彼此耦合的局部状态。 + +## 数据模型规范 + +当前有效实体: + +* `proxy_routes` +* `origins` +* `config_versions` +* `nodes` +* `auth_sources` +* `external_accounts` +* `node_system_profiles` +* `apply_logs` +* `tls_certificates` +* `managed_domains` +* `node_request_reports` +* `node_access_logs` +* `node_metric_snapshots` +* `traffic_analytics_rollups` +* `node_health_events` +* `options` +* `waf_rule_groups` +* `waf_rule_group_bindings` + +通用约束: + +* 不新增平台化对象,除非设计文档明确要求。 +* `origins` 仅作为可复用源站地址目录,字段保持轻量。 +* `proxy_routes` 以“网站配置”作为聚合边界,必须包含唯一 `site_name` 与非空 `domains` 列表。 +* `proxy_routes.domains` 中的每个域名都必须全局唯一,列表第一项视为主域名。 +* `proxy_routes` 继续允许保存一个或多个上游地址用于负载均衡,但不引入独立 `origin_pool`。 +* 遗留 `domain` 字段只能作为 `domains[0]` 的兼容镜像;新代码不得继续以该字段作为唯一业务输入。 +* `proxy_routes` 如关联 `origins`,必须同时保存可直接渲染的 `origin_url`。 +* 上游统一使用 named `upstream` + keepalive;单上游如带 base path 或 query,应在 `proxy_pass` 上补回 URI,多上游仅允许纯 `scheme://host[:port]`。 +* 流量限制、反向代理与缓存配置当前都归属站点级 `proxy_routes`。 +* HTTPS 证书绑定必须通过与 `domains` 平行的 `domain_cert_ids` 逐域名保存;未绑定证书的域名不得参与 HTTPS 渲染。 +* WAF 全局规则组默认应用到所有网站,自定义规则组通过 `waf_rule_group_bindings` 绑定到网站配置;发布时必须进入完整版本快照。 +* `config_versions` 必须保存完整快照与渲染结果。 +* 全局同时只能有一个激活版本。 +* 回滚通过重新激活旧版本实现。 +* `nodes` 只保留控制面状态与低频摘要。 +* 观测数据必须按节点与时间窗口关联,快照与聚合结果采用追加式模型。 +* 原始访问明细必须有受控保留策略。 +* `auth_sources` 仅保存管理端第三方登录源配置,当前支持 `github` 与 `oidc`。 +* `external_accounts` 是第三方账号与本地用户的唯一绑定来源;旧 `users.github_id` 仅用于兼容迁移,不得作为新登录流程的业务输入。 + +## 数据库迁移 + +任何涉及表结构、索引、列类型、分表规则或内部持久化元数据的修改,都必须同步提升数据库版本号。 + +数据库版本号定义在 `openflare_server/model`,不得只依赖 `AutoMigrate` 隐式升级存量数据库。 + +每次提升数据库版本号时,必须补充从上一版本升级到新版本的显式迁移方法。迁移方法必须包含升级后的校验逻辑;只有校验通过,才能写入新的数据库版本记录。 + +v1-v7 视为历史初始基线,不再维护逐版本升级文件。从 v8 起,数据库迁移必须放在 `openflare_server/model/migrate` 目录中,并以目标版本命名文件,例如 `v16.go`。每个版本文件通过 `init()` 注册自己的迁移,当前数据库版本取已注册迁移的最大目标版本。不得为了整理文件而改变已发布 v8+ 迁移的语义。 + +执行数据库升级时必须按以下步骤完成: + +1. 判断是否需要升级数据库版本:凡是新增/删除/重命名表、字段、索引、约束、列类型、分表规则,或改变持久化数据语义,都必须升级。 +2. 新增 `openflare_server/model/migrate/vN.go`,其中 `N` 为目标版本号。文件头部必须包含注释,说明本次升级了什么内容,以及为什么需要升级。 +3. 在 `vN.go` 中实现 `VN()`,并在 `init()` 中调用 `Register(VN())`。`FromVersion` 必须等于 `N-1`,`ToVersion` 必须等于 `N`。 +4. 在 `migrateVN` 中写入升级逻辑。可通过 `Context` 调用 `ApplyCurrentSchema`、历史 backfill、默认数据初始化等公共能力;复杂数据修复必须显式处理,不得只依赖 `AutoMigrate`。 +5. 在 `validateVN` 中写入升级后的校验逻辑。校验至少要覆盖新增表/字段/索引是否存在、关键默认数据是否存在、必要的数据回填是否成功。 +6. 如果新迁移需要新的公共 backfill 或校验辅助函数,将其放在 `openflare_server/model/migrations.go` 或更合适的 model 文件中,并通过 `Context` 暴露给 `model/migrate`,避免子包反向 import `model` 造成循环依赖。 +7. 补充迁移测试:至少覆盖从 `N-1` 老库升级到 `N` 后 schema version、字段/表结构、关键数据回填和校验结果。注册表连续性由 `model/migrate` 测试兜底,但具体业务迁移仍必须有测试。 +8. 同步更新设计/开发文档;如果管理端 API、配置项或用户可见行为变化,还要同步更新对应指南、配置参考和 Swagger 文档。 + +新包启动后必须先检查数据库当前版本,再按顺序逐步升级到目标版本;禁止跳过中间升级步骤直接写目标版本。 + +空库初始化可以直接建立当前版本结构,但初始化完成后仍必须执行同版本校验,并落库当前数据库版本。 + +如果迁移失败或校验失败,启动流程必须中止,且不得提升数据库版本记录。涉及数据库版本变更的提交,必须补充对应的迁移测试或等效回归测试。 + +## API 与鉴权 + +管理端与 Agent API 统一使用 JSON。成功与失败都必须返回清晰 `message`: + +```json +{ + "success": true, + "message": "", + "data": {} +} +``` + +约定: + +* Agent API 固定放在 `/api/agent/*`。 +* 总览与节点详情优先使用专用聚合接口。 +* 管理端变更类接口统一使用 `POST`;只读接口使用 `GET`。 +* 管理端继续复用现有登录、角色与 Session。 +* 第三方登录统一通过认证源 API 进入,认证源管理接口必须要求 Root Session。 +* `/api/status` 只能返回已启用认证源的公开字段,不得返回 Client Secret。 +* 第三方账号未绑定且注册关闭时,应提供绑定已有账号流程,不得自动创建用户。 +* Agent 正式请求统一使用节点专属 `agent_token`。 +* 首次接入可使用全局 `discovery_token`。 +* Agent 请求头统一使用 `X-Agent-Token`。 + +禁止暴露远程 shell 或任意命令执行入口,禁止在日志中打印完整 Token,禁止绕过占位符约束保存不可渲染的主配置模板。 + +## 发布与运行 + +发布逻辑必须保持: + +* 发布时读取全部启用的 `proxy_routes`。 +* 同时读取 OpenResty 主配置参数、反代性能参数与缓存参数。 +* 生成完整 OpenResty 配置。 +* 计算 `checksum`。 +* 写入 `config_versions`。 +* 通过切换 `is_active` 激活版本。 + +版本约束: + +* 版本号格式固定为 `YYYYMMDD-NNN`。 +* 不在线修改历史版本。 +* 不做按节点分组的差异化版本。 +* 预览与 diff 是只读能力,不产生发布记录。 + +Agent 必须满足: + +* 启动后读取或生成本地 `node_id`。 +* 周期性心跳与同步。 +* 常规同步优先依据 heartbeat 返回的版本摘要判断。 +* WS 连接升级开启且连接成功时,Agent 可通过 WS 接收激活版本摘要并立即同步;WS 失败或断开必须退回 HTTP heartbeat。 +* 发现新版本时先备份旧文件。 +* 写入主配置、路由配置与必要证书文件。 +* 写入 WAF/PoW 运行时配置,并确保 WAF Lua 资源由 Agent 统一管理。 +* 写入新配置后执行 `openresty -t -c `,再 reload;reload 发现运行时未启动时允许直接启动 OpenResty。 +* 周期性运行时健康检查不得调用 `openresty -t`,避免健康探针触发 upstream 域名同步解析;应优先请求本地 `openresty_observability_port` 上的 `/openflare/stub_status`,以 HTTP `200 OK` 作为 OpenResty 主进程和 worker 正在提供服务的判断依据。 +* 新配置激活失败时必须先尝试用目标配置恢复运行,再回滚到旧配置并重新拉起 OpenResty。 +* 回滚后 OpenResty 恢复正常时上报警告;如果本地没有历史主配置可恢复,必须允许写入内置安全兜底配置并拉起对外只监听 `80` 端口、统一返回 `503` 的 OpenResty 运行态;兜底配置仍需保留本地 `stub_status` 健康检查入口。 +* 兜底运行态不得清除失败目标的阻断状态;应用记录必须能体现目标版本失败但 fallback runtime 已启动。存在历史主配置但回滚后仍无法恢复运行时上报失败。 +* 某个目标 `version + checksum` 一旦应用失败并回退,Agent 必须在本地状态中阻断该目标的重复应用。 +* Agent 维护本地 MaxMind mmdb 时,下载或刷新失败只能记录警告,不得阻断心跳、同步、配置应用或 OpenResty 健康检查。 + +## 前端请求、状态与类型 + +所有 API 请求必须统一经过 `lib/api/`: + +* 统一处理 `success/message/data` 响应结构。 +* 统一处理鉴权失效、网络异常和通用错误消息。 +* 统一维护资源接口与请求路径。 + +状态分层: + +* 服务端状态:TanStack Query。 +* 页面临时状态:组件内部 `useState`。 +* 跨页面 UI 状态:Zustand。 + +要求开启 TypeScript 严格模式,禁止滥用 `any`,API 响应、表单输入、业务实体必须有明确类型。 + +## 表单、交互、样式与主题 + +表单统一使用 React Hook Form 与 Zod。 + +高风险操作必须二次确认、展示操作对象名称,并明确成功与失败反馈。 + +样式原则: + +* 统一使用 Tailwind CSS 与现有 token 体系。 +* 优先复用已有基础组件与布局组件。 +* 保持视觉层级、留白与语义颜色一致。 + +主题要求: + +* 同时支持 `light`、`dark`、`system`。 +* 用户选择必须持久化。 +* 首屏尽量避免主题闪烁。 + +## 测试与交付 + +* 关键业务逻辑必须有单元测试或等效回归测试。 +* Agent 主链路修改必须验证同步、应用与回滚。 +* 前端页面至少覆盖加载态、空态、错误态与成功反馈。 +* Go 版本调整时,同步检查 `go.mod`、Dockerfile 与 CI 工作流。 + +## 后续维护方式 + +后续规划不再按“大版本阶段文档”维护,而采用以下方式: + +* 产品边界变动:更新 [产品边界](../design/index.md)。 +* 工程约束变动:更新本文档。 +* 部署与配置变动:更新 [部署说明](../reference/deployment.md)、[配置项](../reference/configuration.md) 与 README。 + +如果未来出现明确的新阶段目标,再单独新增专项计划文档;不要把已完成的历史计划继续堆回本文档。 + +当前专项“网站级规则与配置界面改造”的模型边界已纳入 [产品边界](../design/index.md),执行时仍按数据模型、接口、前端页面、迁移测试与文档联动的顺序推进。 diff --git a/docs/guide/agent.md b/docs/reference/agent.md similarity index 98% rename from docs/guide/agent.md rename to docs/reference/agent.md index 407f547c..ac49cd38 100644 --- a/docs/guide/agent.md +++ b/docs/reference/agent.md @@ -89,7 +89,7 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/inst } ``` -如果不配置 `openresty_path`,Agent 默认调用 `openresty`。完整字段见 [配置项参考](../reference/configuration.md#agent-配置字段)。 +如果不配置 `openresty_path`,Agent 默认调用 `openresty`。完整字段见 [配置项参考](./configuration.md#agent-配置字段)。 ## Docker 运行 diff --git a/docs/guide/deployment.md b/docs/reference/deployment.md similarity index 100% rename from docs/guide/deployment.md rename to docs/reference/deployment.md diff --git a/docs/reference/index.md b/docs/reference/index.md index 2ce200fc..4879cc33 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -9,4 +9,4 @@ | [配置项](./configuration.md) | Server 环境变量、命令行参数、运行时 Option 与 Agent 配置字段 | | [命令与脚本](./cli.md) | 常用启动、构建、测试、安装和卸载命令 | | [API 约定](./api.md) | 管理端 API 与 Agent API 的响应结构、鉴权和路径约定 | -| [仓库结构](./repository.md) | `openflare_server`、`openflare_agent`、`openflare_server/web` 与 `docs` 的职责 | +| [仓库结构](../design/repository.md) | `openflare_server`、`openflare_agent`、`openflare_server/web` 与 `docs` 的职责 | diff --git a/docs/guide/server.md b/docs/reference/server.md similarity index 100% rename from docs/guide/server.md rename to docs/reference/server.md diff --git a/docs/guide/upgrade.md b/docs/reference/upgrade.md similarity index 100% rename from docs/guide/upgrade.md rename to docs/reference/upgrade.md