From db2fa7a710f4bfb3f4e429631c938fe79802eb34 Mon Sep 17 00:00:00 2001 From: zhi Date: Fri, 20 Mar 2026 08:05:23 +0000 Subject: [PATCH] chore: update monitor implementation docs and submodule refs - Track API key-only monitor flow - Update backend/frontend/plugin submodules to latest monitor fixes - Include frontend API key UI branch pointer --- DEVELOPMENT_PLAN.md | 650 +++++++++++++++++++++++++++++++++++++ HarborForge.Backend | 2 +- HarborForge.Frontend | 2 +- HarborForge.OpenclawPlugin | 2 +- HarborForge.Test | 2 +- 5 files changed, 654 insertions(+), 4 deletions(-) create mode 100644 DEVELOPMENT_PLAN.md diff --git a/DEVELOPMENT_PLAN.md b/DEVELOPMENT_PLAN.md new file mode 100644 index 0000000..baa9b13 --- /dev/null +++ b/DEVELOPMENT_PLAN.md @@ -0,0 +1,650 @@ +# HarborForge 开发计划 + +**版本**: 0.3.0 +**日期**: 2026-03-19 +**状态**: 开发中 + +--- + +## 1. 项目概述 + +HarborForge 是一个 **AI Agent 与人类协同的任务管理平台**,用于管理项目、里程碑、任务和提案(Propose)。 + +### 核心特性 +- 项目驱动的任务管理 +- 里程碑(Milestone)状态机管理 +- 任务(Task)状态机管理 +- 提案(Propose)工作流 +- 角色权限系统(RBAC) +- 服务器监控集成 +- Webhook 扩展能力 +- OpenClaw 插件生态 + +--- + +## 2. 系统架构 + +### 2.1 整体架构 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 客户端层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ +│ │ Web Frontend │ │ OpenClaw CLI │ │ OpenClaw Plugin │ │ +│ │ (React/Vite) │ │ │ │ (Server Monitor) │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │ +└─────────┼─────────────────┼─────────────────────┼──────────────┘ + │ │ │ + └─────────────────┼─────────────────────┘ + │ HTTP/WebSocket +┌───────────────────────────▼─────────────────────────────────────┐ +│ HarborForge.Backend │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ FastAPI + SQLAlchemy + MySQL │ │ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ +│ │ │ Projects│ │Milestones│ │ Tasks │ │Proposes │ │ │ +│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ +│ │ │ Auth │ │ RBAC │ │ Monitor │ │ Webhooks│ │ │ +│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ +│ └─────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + └──────────────────────────────────────────────────────┐ + │ +┌────────────────────────────────────────────────────────────────▼┐ +│ 外部集成 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ +│ │ LLM Providers│ │ Keycloak │ │ AbstractWizard │ │ +│ │ (Claude/etc) │ │ (Auth) │ │ (Config Management) │ │ +│ └──────────────┘ └──────────────┘ └──────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 2.2 模块划分 + +| 模块 | 技术栈 | 职责 | +|------|--------|------| +| **Backend** | FastAPI + SQLAlchemy + MySQL | REST API + WebSocket,业务逻辑 | +| **Frontend** | React + Vite + TypeScript | 用户界面,管理后台 | +| **OpenclawPlugin** | Node.js + TypeScript | OpenClaw 集成,服务器监控 | +| **Backend.Test** | pytest | 独立测试套件 | +| **Frontend.Test** | Playwright | E2E 测试 | + +--- + +## 3. 数据模型 + +### 3.1 核心实体关系 + +``` +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Project │◄────┤ Milestone │◄────┤ Task │ +│ │ │ │ │ │ +│ - id │ │ - id │ │ - id │ +│ - name │ │ - title │ │ - title │ +│ - owner_id │ │ - status │ │ - status │ +│ - project_code│ │ - project_id│ │ - type │ +└──────┬──────┘ └─────────────┘ └──────┬──────┘ + │ │ + │ ┌─────────────┐ │ + └────────►│ Propose │◄─────────────┘ + │ │ + │ - id │ + │ - title │ + │ - status │ + │ - feat_task_id (accept时创建) + └─────────────┘ +``` + +### 3.2 状态机定义 + +#### Milestone 状态 +``` +open ──freeze──► freeze ──start──► undergoing ──close──► closed + │ │ + │ └──auto-complete──► completed + │ + └──────────────────────────────────────────────────► closed +``` + +#### Task 状态 +``` +open ──assign+start──► undergoing ──finish+comment──► completed ──close──► closed + │ │ + │ └──reopen──► open + │ + └──pending──► undergoing ──(同上) +``` + +#### Propose 状态 +``` +open ──accept──► accepted (创建 feature story task) + │ + └──reject──► rejected ──reopen──► open +``` + +--- + +## 4. API 接口设计 + +### 4.1 认证接口 + +```yaml +POST /auth/token + # JWT 登录 + Body: { username: string, password: string } + Response: { access_token: string, token_type: "bearer" } + +GET /users/me + # 获取当前用户信息 + Headers: Authorization: Bearer {token} +``` + +### 4.2 项目接口 + +```yaml +GET /projects + # 列表(支持分页) + Query: { page: int, page_size: int } + +POST /projects + # 创建 + Body: { name: string, description?: string, project_code?: string } + +GET /projects/{id} + # 详情 + +PATCH /projects/{id} + # 更新 + +DELETE /projects/{id} + # 删除(需确认) +``` + +### 4.3 里程碑接口 + +```yaml +GET /projects/{project_id}/milestones + # 列表 + Query: { status: "open|freeze|undergoing|completed|closed" } + +POST /projects/{project_id}/milestones + # 创建 + Body: { title: string, description?: string, due_date?: datetime } + +GET /projects/{project_id}/milestones/{id} + # 详情 + +PATCH /projects/{project_id}/milestones/{id} + # 更新(仅在 open 状态允许修改大部分字段) + +DELETE /projects/{project_id}/milestones/{id} + # 删除 + +# 状态机动作 +POST /projects/{project_id}/milestones/{id}/freeze +POST /projects/{project_id}/milestones/{id}/start +POST /projects/{project_id}/milestones/{id}/close + +# 预检接口 +GET /projects/{project_id}/milestones/{id}/preflight + # 返回 { can_freeze: bool, can_start: bool, reasons: [...] } +``` + +### 4.4 任务接口 + +```yaml +GET /projects/{project_id}/tasks + # 列表 + Query: { + status: "open|pending|undergoing|completed|closed", + assignee_id: int, + milestone_id: int, + task_type: "issue|story|test|..." + } + +POST /projects/{project_id}/tasks + # 创建 + Body: { + title: string, + milestone_id: int, + task_type: "issue|story|test|maintenance|research|review|resolution", + priority: "low|medium|high|critical", + assignee_id?: int + } + +GET /projects/{project_id}/tasks/{id} + # 详情(包含 comments) + +PATCH /projects/{project_id}/tasks/{id} + # 更新 + # 注意:undergoing/completed/closed 状态限制 body 编辑 + +DELETE /projects/{project_id}/tasks/{id} + # 删除 + +# 状态机动作 +POST /projects/{project_id}/tasks/{id}/transition + Body: { + action: "open|start|finish|close|reopen", + comment?: string, # finish 时必填 + close_reason?: string # close 时可选 + } +``` + +### 4.5 Propose 接口 + +```yaml +GET /projects/{project_id}/proposes + # 列表 + +POST /projects/{project_id}/proposes + # 创建 + Body: { title: string, description?: string } + +GET /projects/{project_id}/proposes/{id} + # 详情 + +PATCH /projects/{project_id}/proposes/{id} + # 更新(仅在 open 状态允许) + +# 状态机动作 +POST /projects/{project_id}/proposes/{id}/accept + Body: { milestone_id: int } # 指定 milestone 创建 feature story task + +POST /projects/{project_id}/proposes/{id}/reject + +POST /projects/{project_id}/proposes/{id}/reopen + # rejected -> open +``` + +### 4.6 监控接口 + +```yaml +GET /monitor/public/overview + # 公开概览数据 + +# 管理接口 +GET /monitor/admin/servers +POST /monitor/admin/servers +DELETE /monitor/admin/servers/{id} +POST /monitor/admin/servers/{id}/api-key +DELETE /monitor/admin/servers/{id}/api-key + +# 服务器上报(插件调用) +POST /monitor/server/heartbeat-v2 + Headers: + X-API-Key: string + Body: + identifier: string + openclaw_version: string # 远程主机上的 OpenClaw 版本 + plugin_version: string # harborforge-monitor 插件版本 + cpu_pct: float + mem_pct: float + disk_pct: float + swap_pct: float + load_avg: [float, float, float] + uptime_seconds: int + agents: [...] +``` + +### 4.7 其他接口 + +```yaml +# 评论 +GET /projects/{project_id}/tasks/{task_id}/comments +POST /projects/{project_id}/tasks/{task_id}/comments + +# 角色权限 +GET /roles +GET /roles/{id} +POST /roles +PATCH /roles/{id} +DELETE /roles/{id} + +# Webhook +GET /webhooks +POST /webhooks +DELETE /webhooks/{id} + +# Dashboard +GET /dashboard/stats?project_id={id} + +# 健康检查 +GET /health +GET /version +``` + +--- + +## 5. 安全设计 + +### 5.1 认证 +- **JWT Token**: 基于 `python-jose`,有效期 configurable +- **API Key**: 支持服务间调用 +- **Admin 权限**: `users.is_admin` 字段控制 + +### 5.2 项目权限 (RBAC) + +| 角色 | 权限范围 | +|------|----------| +| admin | 全局所有操作 | +| owner | 项目内所有操作 | +| mgr | 里程碑/任务管理,接受/拒绝 propose | +| dev | 任务操作,创建 propose | +| guest | 只读访问 | + +### 5.3 监控插件安全 + +``` +1. 服务器注册 +2. 管理员生成 API Key +3. 插件将 API Key 写入 OpenClaw plugin config +4. sidecar 通过 X-API-Key 调用 /monitor/server/heartbeat-v2 +5. 服务端按 API Key 识别并接收遥测 +``` + +--- + +## 6. 开发里程碑 + +### P0 - 基础框架 ✅ +- [x] 项目初始化 (FastAPI + SQLAlchemy) +- [x] 用户认证 (JWT) +- [x] Docker Compose 部署 + +### P1 - 核心 CRUD ✅ +- [x] Projects CRUD +- [x] Milestones CRUD +- [x] Tasks CRUD +- [x] Comments + +### P2 - 权限系统 ✅ +- [x] Role/Permission 模型 +- [x] RBAC 中间件 +- [x] 项目成员管理 + +### P3 - 里程碑状态机 ✅ +- [x] freeze/start/close 动作 +- [x] 自动完成钩子 +- [x] 编辑限制 + +### P4 - 任务依赖 ✅ +- [x] depend_on 字段 +- [x] 依赖检查工具 +- [x] 批量操作 + +### P5 - 任务状态机 ✅ +- [x] open/start/finish/close/reopen +- [x] 负责人检查 +- [x] 完成时必须评论 +- [x] 编辑限制 + +### P6 - Propose 系统 ✅ +- [x] Propose CRUD +- [x] accept/reject/reopen +- [x] accept 时创建 feature story task + +### P7 - 任务类型重构 ✅ +- [x] 移除 task 类型 +- [x] issue 作为默认 +- [x] 前端同步更新 + +### P8 - 里程碑预检 ✅ +- [x] preflight 接口 +- [x] 前端按钮状态 + +### P9 - 任务操作 UI ✅ +- [x] 操作按钮 +- [x] 完成评论弹窗 +- [x] 关闭原因弹窗 + +### P10 - Propose UI ✅ +- [x] Propose 列表页 +- [x] Propose 详情页 +- [x] 编辑弹窗(仅 open 状态) + +### P11 - 监控后端 ✅ +- [x] Provider 账户管理 +- [x] 服务器注册/挑战 +- [x] 心跳接收 +- [x] WebSocket 支持 + +### P12 - CLI 工具 ✅ +- [x] 命令行交互 +- [x] Webhook 管理 +- [x] 配置查看 + +### P13 - 测试 ✅ +- [x] Backend 单元测试 (pytest) +- [x] 里程碑状态机测试 +- [x] 任务状态机测试 +- [x] Propose 测试 +- [x] Frontend E2E 测试 + +### P14 - OpenClaw 集成 🔄 +- [x] Plugin 架构设计 +- [x] 遥测服务器 +- [x] 安装脚本 +- [ ] 完整测试 + +### P15 - 文档与发布 📋 +- [ ] API 文档 (OpenAPI) +- [ ] 部署文档 +- [ ] 用户手册 +- [ ] v1.0 发布 + +--- + +## 7. 远程服务器通信协议 + +### 7.1 注册流程 + +```mermaid +sequenceDiagram + participant Admin + participant Monitor + participant Server + participant Plugin + + Admin->>Monitor: POST /admin/servers + Monitor->>Admin: { challenge_uuid, expires_at } + + Admin->>Server: 配置 challenge_uuid + + Plugin->>Monitor: GET /public/server-public-key + Monitor->>Plugin: { public_key_pem, key_id } + + Plugin->>Plugin: 加密 payload + Note right of Plugin: RSA-OAEP + SHA256 + + Plugin->>Monitor: POST /server/heartbeat + Note right of Plugin: 或 WS /server/ws + + Monitor->>Monitor: 验证 challenge_uuid + Monitor->>Monitor: 验证 timestamp (防重放) + Monitor->>Monitor: 存储 server_state +``` + +### 7.2 心跳协议 + +**HTTP Heartbeat:** +```http +POST /monitor/server/heartbeat +Content-Type: application/json +X-Server-Identifier: vps.t1 +X-Challenge-UUID: abc-123-def + +{ + "identifier": "vps.t1", + "challenge_uuid": "abc-123-def", + "timestamp": "2026-03-19T14:00:00Z", + "cpu_pct": 12.5, + "mem_pct": 41.2, + "disk_pct": 62.0, + "swap_pct": 0.0, + "uptime_sec": 86400, + "load_avg_1m": 0.5, + "platform": "linux", + "hostname": "vps.t1", + "openclaw_version": "1.2.3", + "openclaw_agent_count": 3, + "openclaw_agents": [ + { "id": "dev", "name": "Developer", "status": "running" } + ] +} +``` + +**WebSocket 连接:** +```javascript +// 1. 建立连接 +const ws = new WebSocket('wss://monitor.example.com/monitor/server/ws'); + +// 2. 发送加密握手 +ws.send(JSON.stringify({ + encrypted_payload: "base64_encoded_rsa_encrypted_json" +})); + +// 3. 接收确认 +// Server: { "status": "authenticated" } + +// 4. 定期发送遥测 +setInterval(() => { + ws.send(JSON.stringify({ + type: "telemetry", + data: { /* 同上 */ } + })); +}, 30000); +``` + +### 7.3 加密格式 + +```python +# Payload 结构 (加密前) +{ + "identifier": "vps.t1", + "challenge_uuid": "uuid-from-admin", + "nonce": "random-128bit-hex", # 防重放 + "ts": "2026-03-19T14:00:00Z" # UTC ISO8601,10分钟有效期 +} + +# 加密 +encrypted = RSA_OAEP_SHA256_encrypt( + plaintext=json.dumps(payload), + public_key=monitor_public_key +) + +# 传输 (base64) +encrypted_payload_b64 = base64.b64encode(encrypted).decode() +``` + +--- + +## 8. 技术规范 + +### 8.1 代码规范 +- **Backend**: PEP8, Black formatter, mypy type hints +- **Frontend**: ESLint, Prettier, strict TypeScript +- **Commits**: Conventional Commits (`feat:`, `fix:`, `test:`, `docs:`) + +### 8.2 数据库规范 +- 所有表必须有 `id` (PK, auto_increment) +- 时间字段使用 `DateTime(timezone=True)` +- 枚举使用 SQLAlchemy `Enum` + `values_callable` +- 外键必须建索引 + +### 8.3 API 规范 +- RESTful 设计 +- 统一响应格式: `{ data: ..., error?: ..., message?: ... }` +- HTTP 状态码规范使用 +- 分页: `{ items: [...], total: N, page: 1, page_size: 20 }` + +### 8.4 测试规范 +- 测试覆盖率 > 80% +- 单元测试: SQLite in-memory +- E2E 测试: 独立 Docker 环境 +- CI: GitHub Actions / Gitea Actions + +--- + +## 9. 部署架构 + +### 9.1 生产环境 + +```yaml +# docker-compose.prod.yml +services: + mysql: + image: mysql:8.0 + volumes: + - mysql_data:/var/lib/mysql + + backend: + build: ./HarborForge.Backend + environment: + - DATABASE_URL=mysql+pymysql://... + - SECRET_KEY=${SECRET_KEY} + + frontend: + build: ./HarborForge.Frontend + + nginx: + image: nginx:alpine + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + - ./ssl:/etc/nginx/ssl +``` + +### 9.2 监控插件部署 + +```bash +# 1. 在 Monitor 注册服务器,获取 challenge_uuid +# 2. 在服务器安装插件 +node scripts/install.mjs + +# 3. 配置 ~/.openclaw/openclaw.json +{ + "plugins": { + "harborforge-monitor": { + "enabled": true, + "challengeUuid": "YOUR_CHALLENGE_UUID" + } + } +} + +# 4. 重启 Gateway +openclaw gateway restart +``` + +--- + +## 10. 参考资源 + +### 代码仓库 +- `HarborForge.Backend` - FastAPI 后端 +- `HarborForge.Frontend` - React 前端 +- `HarborForge.Test` - 测试套件 +- `HarborForge.OpenclawPlugin` - OpenClaw 插件 + +### 关键文件 +- `app/models/` - SQLAlchemy 模型 +- `app/api/routers/` - API 路由 +- `app/schemas/schemas.py` - Pydantic 模型 +- `app/services/` - 业务逻辑 +- `tests/` - 测试文件 + +### 外部依赖 +- FastAPI 0.109 +- SQLAlchemy 2.0 +- React 18 + Vite 5 +- OpenClaw Gateway + +--- + +**文档版本**: 0.3.0 +**最后更新**: 2026-03-19 +**维护者**: HarborForge Team diff --git a/HarborForge.Backend b/HarborForge.Backend index 67c648d..9b5e2dc 160000 --- a/HarborForge.Backend +++ b/HarborForge.Backend @@ -1 +1 @@ -Subproject commit 67c648d6d83f0b20c4f20447dac41d9037fab7b0 +Subproject commit 9b5e2dc15cfaa41a6869d62fcbaf8da07df63bbf diff --git a/HarborForge.Frontend b/HarborForge.Frontend index bdeb064..bad1c8f 160000 --- a/HarborForge.Frontend +++ b/HarborForge.Frontend @@ -1 +1 @@ -Subproject commit bdeb06407e4802ed0e98f6bc7fda70e76e53c5d1 +Subproject commit bad1c8fca9ea33818c8482d34f5d8b46a4c389f4 diff --git a/HarborForge.OpenclawPlugin b/HarborForge.OpenclawPlugin index 0debe83..ab42936 160000 --- a/HarborForge.OpenclawPlugin +++ b/HarborForge.OpenclawPlugin @@ -1 +1 @@ -Subproject commit 0debe835b4020d033e5b03d4bd2efee1c9088268 +Subproject commit ab42936408d8839f7bcf0b3dcc4f88f15b4e9824 diff --git a/HarborForge.Test b/HarborForge.Test index 5a45a72..11d0865 160000 --- a/HarborForge.Test +++ b/HarborForge.Test @@ -1 +1 @@ -Subproject commit 5a45a72dcf27eec96ad82789c9e8b4cea5481733 +Subproject commit 11d0865fd3cc1cff52b760c08449edb3d21afa54