Skip to content

Commit 54c3e62

Browse files
committed
docs: sync all docs for v3.4 — SSE, local Dev Containers, error codes, architecture
- Add SSE endpoint docs to both zh/en API reference - Update architecture docs project structure (broadcast/, cloudclaude/, local/, agentapi/, scheduler/, credgen/) - Fix Admin SPA port :3000 → :80/nginx - Update tech stack versions (Go 1.25.7 → 1.26.1, React 19 → 19.2) - Update v3-error-code-index: 51 codes, v3.4 Phase 41/44 new codes, rename DISK_MUTAGEN_DATA_BLOAT → DISK_HOTSYNC_DATA_BLOAT - Update PROJECT.md Backlog: mark SSE infrastructure as completed - Add zh/en feature docs: sse-realtime.md + cloud-claude-local.md - Update VitePress sidebar nav for new docs - Regenerate .planning/codebase/ map (4 files, 886 lines)
1 parent 6e8b720 commit 54c3e62

15 files changed

Lines changed: 1365 additions & 39 deletions

File tree

.planning/PROJECT.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ Gap closure 链(Phase 42/43/44)
4848
## Backlog(待后续里程碑收敛)
4949

5050
- **ENH-NEXT-01** 容器预热与空闲回收策略(控制面资源调度)
51-
- **ENH-NEXT-02** 性能 metrics 实时上报到 admin 后台(首连耗时、mount 模式、抖动事件分布)
51+
- **✓ SSE 实时推送基础设施** — 控制面 topic-based pub/sub + `/v1/admin/sse` + `/v1/user/sse`,前端无需轮询(v3.4 已完成)
52+
- **ENH-NEXT-02** 性能 metrics 数据上报与可视化(首连耗时、mount 模式、抖动事件分布 → 接入 SSE 通道)
5253
- **ENH-NEXT-03** admin 后台 host 详情页展示 mount 模式 / session 数 / persistent volume 列表
5354
- **ENH-NEXT-04** 自研 hot-sync spec doc 修订(v3.0 隐式设计变更)
5455
- **ENH-NEXT-05** `~/.vscode-server` 持久化 volume(容器重建后保留扩展和设置)

.planning/codebase/ARCHITECTURE.md

Lines changed: 216 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,225 @@
1-
# 架构摘要
1+
# Architecture
22

3-
## 总体结构
3+
**Analysis Date:** 2026-05-10
44

5-
当前项目推荐采用“控制面 + 宿主机代理 + 用户容器运行时”的单宿主机架构:
5+
## System Overview
66

7-
- 控制面:负责用户、会话、出口 IP 绑定、生命周期、到期和审计状态
8-
- 宿主机代理:负责 Docker、命名空间、隧道和防火墙等特权操作
9-
- 用户容器:承载 OpenSSH、Shell 工具和 `claude code`
10-
- 持久化层:使用 PostgreSQL 保存系统真实状态
7+
Cloud CLI Proxy 是一个面向单宿主机的容器化 SSH 云主机平台。用户从一个很短的 `curl` 入口开始,在终端里输入用户名和密码,等待专属 Docker 容器启动完成后,直接进入该容器内的 SSH 会话。所有网络流量都必须通过指定出口 IP 的全局隧道路由发送。
118

12-
## 关键边界
9+
```text
10+
┌─────────────────────────────────────────────────────────────────────────────┐
11+
│ cloud-claude CLI (终端用户) │
12+
│ `cmd/cloud-claude/` — Go + Cobra │
13+
├─────────────────────────────────────────────────────────────────────────────┤
14+
│ Entry Short-Link │
15+
│ `GET /entry/{username}` → bootstrap script │
16+
│ `POST /v1/entry/{username}/auth` → SSH 凭证 │
17+
├─────────────────────────────────────────────────────────────────────────────┤
18+
│ Control Plane (HTTP API) │
19+
│ `internal/controlplane/` — Go net/http, JWT, SSE │
20+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
21+
│ │ Admin API │ │ Bootstrap │ │ Entry API │ │ Scheduler │ │
22+
│ │ `/v1/admin` │ │ `/v1/boot` │ │ `/entry` │ │ expiry + reconcile │ │
23+
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────────┘ │
24+
├─────────────────────────────────────────────────────────────────────────────┤
25+
│ Host Agent (特权操作边界) │
26+
│ `internal/agent/` + `internal/agentapi/` │
27+
│ Unix socket 通信 (`/run/cloud-cli-proxy/host-agent.sock`) │
28+
├─────────────────────────────────────────────────────────────────────────────┤
29+
│ Docker + Network Layer │
30+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
31+
│ │ Runtime │ │ Network │ │ SSH Proxy │ │ Broadcast │ │
32+
│ │ `internal/ │ │ `internal/ │ │ `internal/ │ │ `internal/ │ │
33+
│ │ runtime/` │ │ network/` │ │ sshproxy/` │ │ broadcast/` │ │
34+
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────────┘ │
35+
├─────────────────────────────────────────────────────────────────────────────┤
36+
│ Data Persistence │
37+
│ `internal/store/` — PostgreSQL + pgx/v5 │
38+
└─────────────────────────────────────────────────────────────────────────────┘
39+
40+
41+
┌─────────────────────────────────────────────────────────────────────────────┐
42+
│ Admin Dashboard (Web) │
43+
│ `web/admin/` — React 19.2 + Vite + TanStack Router │
44+
└─────────────────────────────────────────────────────────────────────────────┘
45+
```
1346

14-
- Web / API 层不要直接持有过宽的宿主机特权
15-
- Docker 和网络 namespace 的操作应集中在独立边界中执行
16-
- 用户容器的默认出网必须被隧道网络接管,不能保留旁路
47+
## Component Responsibilities
1748

18-
## 核心数据流
49+
| Component | Responsibility | Key File |
50+
|-----------|----------------|----------|
51+
| Control Plane | HTTP API 服务、认证、任务编排、SSE 推送、调度器 | `internal/controlplane/app/app.go` |
52+
| Host Agent | Docker 特权操作、容器生命周期、网络配置 | `internal/agent/server.go` |
53+
| Agent API Client | 通过 Unix socket 与 Host Agent 通信 | `internal/agentapi/client.go` |
54+
| Runtime Service | 将 host action 转换为 Docker 命令队列 | `internal/runtime/runtime_service.go` |
55+
| Worker | 实际执行 docker create/start/stop/rebuild | `internal/runtime/tasks/worker.go` |
56+
| Network Provider | sing-box + nftables/iptables 全隧道出网 | `internal/network/container_proxy_provider.go` |
57+
| SSH Proxy | 用户 SSH 接入代理,转发到容器内部 SSH | `internal/sshproxy/proxy.go` |
58+
| Broadcast | SSE 实时事件广播中心 | `internal/broadcast/sse.go` |
59+
| Store / Repository | PostgreSQL 数据访问层 | `internal/store/repository/queries.go` |
60+
| cloud-claude CLI | 终端用户入口,认证、挂载、SSH 会话 | `cmd/cloud-claude/main.go` |
61+
| Admin Web | 管理后台前端 | `web/admin/src/main.tsx` |
1962

20-
1. 用户执行 `curl` 启动入口
21-
2. 控制面完成认证与权限检查
22-
3. 控制面下发启动任务
23-
4. 宿主机代理创建容器并接入受控隧道网络
24-
5. 系统验证 SSH 与网络路径都已就绪
25-
6. 用户被接入最终的 SSH 会话
63+
## Pattern Overview
2664

27-
## 当前架构原则
65+
**Overall:** 分层架构 + 端口适配器模式(Ports and Adapters)
2866

29-
- 单宿主机优先,不为 v1 提前引入多节点调度复杂度
30-
- 网络强约束优先,先保证“所有流量都必须走指定出口”
31-
- 启动体验建立在真实可验证的运行时正确性之上
67+
**Key Characteristics:**
68+
- 控制面(Control Plane)不直接持有 Docker 特权,所有特权操作通过 Host Agent 或 Embedded Worker 执行
69+
- 数据流以 Task(任务)为核心:每个 host action 创建一条 task 记录,异步执行,SSE 广播状态变更
70+
- 网络隔离通过 per-host Docker network + sing-box gateway sidecar 实现
71+
- 单宿主机优先,但架构预留了多宿主机扩展边界(host-agent socket 模型)
72+
73+
## Layers
74+
75+
### Web / API Layer
76+
- **Purpose:** HTTP API 入口、认证、路由分发
77+
- **Location:** `internal/controlplane/http/`
78+
- **Contains:** Handler 函数、JWT 中间件、路由表
79+
- **Depends on:** store/repository, runtime, broadcast, scheduler
80+
- **Used by:** Admin Dashboard, cloud-claude CLI, curl bootstrap
81+
82+
### Application / Service Layer
83+
- **Purpose:** 业务逻辑编排、任务调度、生命周期管理
84+
- **Location:** `internal/controlplane/app/`, `internal/controlplane/scheduler/`, `internal/runtime/`
85+
- **Contains:** App 组装器、ExpiryScanner、Reconciler、RuntimeService
86+
- **Depends on:** repository, agentapi, network
87+
- **Used by:** HTTP handlers
88+
89+
### Domain / Worker Layer
90+
- **Purpose:** 实际执行 Docker 和网络操作
91+
- **Location:** `internal/runtime/tasks/`, `internal/agent/`, `internal/network/`
92+
- **Contains:** Worker, Host Agent Server, ContainerProxyProvider
93+
- **Depends on:** Docker CLI, sing-box, nftables/iptables
94+
- **Used by:** RuntimeService (embedded mode) or Host Agent (独立模式)
95+
96+
### Data Layer
97+
- **Purpose:** 持久化存储
98+
- **Location:** `internal/store/repository/`, `internal/store/migrations/`
99+
- **Contains:** Repository (raw SQL), Migrator
100+
- **Depends on:** PostgreSQL + pgx/v5
101+
- **Used by:** 所有上层服务
102+
103+
## Data Flow
104+
105+
### Primary: Bootstrap Entry Flow
106+
107+
1. 用户执行 `curl https://gw.example.com/entry/alice | bash`
108+
- Handler: `internal/controlplane/http/entry.go``Script()`
109+
2. 脚本运行后调用 `POST /v1/entry/alice/auth`
110+
- Handler: `internal/controlplane/http/entry.go``Auth()`
111+
3. 控制面检查用户/主机状态,如未创建则 queue `create_host` task
112+
- `internal/runtime/runtime_service.go``QueueHostAction()`
113+
4. Task 通过 dispatcher 发往 Host Agent(或 embedded worker)
114+
- `internal/agent/server.go``internal/runtime/tasks/worker.go`
115+
5. Worker 执行 docker create/start,配置 sing-box 网络
116+
- `internal/runtime/tasks/worker.go``createHost()`
117+
- `internal/network/container_proxy_provider.go``PrepareHost()`
118+
6. 容器就绪后,auth 返回 SSH 四元组(host/port/user/pass)
119+
7. cloud-claude CLI 建立 SSH 连接并启动 claude code
120+
- `cmd/cloud-claude/main.go``ConnectAndRunClaudeV3()`
121+
122+
### Secondary: Admin Dashboard CRUD Flow
123+
124+
1. 管理员登录 → `POST /v1/auth/login` → JWT token
125+
- `internal/controlplane/http/auth.go`
126+
2. 前端 API 调用带 `Authorization: Bearer <token>`
127+
- `internal/controlplane/http/admin_*.go`
128+
3. 写操作创建 task 或更新 DB,SSE 广播变更
129+
- `internal/broadcast/sse.go``Broadcast()`
130+
4. 前端 `use-sse.ts` 接收事件,触发 React Query 刷新
131+
132+
### Tertiary: Expiry & Reconcile Flow
133+
134+
1. `ExpiryScanner` 每 60s 扫描过期用户
135+
- `internal/controlplane/scheduler/expiry.go`
136+
2. 过期用户状态改为 `expired`,自动停止其运行中主机
137+
3. `Reconciler` 每 60s 对比 DB 状态与 Docker 实际状态
138+
- `internal/controlplane/scheduler/reconciler.go`
139+
4. 发现漂移(DB=running 但容器不存在)则自动恢复或标记 stopped
140+
141+
## Key Abstractions
142+
143+
### Task-Driven Async Execution
144+
- **Purpose:** 所有耗时的 host action(create/start/stop/rebuild)都异步执行
145+
- **Pattern:** 创建 Task 记录 → dispatch 到 worker → worker 更新 task 状态 → SSE 广播
146+
- **Files:** `internal/store/repository/models.go` (Task 模型), `internal/runtime/tasks/worker.go`
147+
148+
### Host Action Contract
149+
- **Purpose:** 控制面与 host-agent 之间的操作契约
150+
- **Pattern:** `agentapi.HostActionRequest` / `HostActionResponse` JSON over HTTP (Unix socket)
151+
- **Files:** `internal/agentapi/contracts.go`
152+
153+
### Network Provider Interface
154+
- **Purpose:** 抽象网络配置,支持 Linux 实现和测试桩
155+
- **Pattern:** `network.Provider` interface: `PrepareHost` / `CleanupHost`
156+
- **Files:** `internal/network/provider.go`, `internal/network/container_proxy_provider.go`
157+
158+
### Repository Pattern
159+
- **Purpose:** 数据访问抽象,直接 SQL 无 ORM
160+
- **Pattern:** `repository.Repository` 封装 pgxpool,每个表一组 Query/Scan 方法
161+
- **Files:** `internal/store/repository/queries.go`
162+
163+
## Entry Points
164+
165+
**Control Plane:**
166+
- Location: `cmd/control-plane/main.go`
167+
- Triggers: systemd service 或 `go run`
168+
- Responsibilities: 启动 HTTP server、运行 migrations、启动 scheduler、启动 SSH proxy
169+
170+
**Host Agent:**
171+
- Location: `cmd/host-agent/main.go`
172+
- Triggers: systemd service(生产环境)或 `go run`
173+
- Responsibilities: 监听 Unix socket,执行 Docker 和网络操作
174+
175+
**cloud-claude CLI:**
176+
- Location: `cmd/cloud-claude/main.go`
177+
- Triggers: 终端用户直接执行
178+
- Responsibilities: 认证、等待容器就绪、SSH 连接、目录挂载、启动 claude code
179+
180+
**Admin Dashboard:**
181+
- Location: `web/admin/src/main.tsx`
182+
- Triggers: 浏览器访问
183+
- Responsibilities: 管理用户、主机、出口 IP、查看事件和任务
184+
185+
## Architectural Constraints
186+
187+
- **Threading:** Go 协程模型。HTTP handlers 在 goroutine 中运行;SSE 每个连接一个 goroutine;scheduler 每个 job 一个 goroutine
188+
- **Global state:** `broadcast.defaultHub` 是包级单例(SSE 连接管理);`errcodes.registry` 是包级单例(错误码注册表)
189+
- **Circular imports:** 未发现明显循环依赖。`internal/agentapi` 作为共享契约包,被 `controlplane``agent` 共同依赖
190+
- **特权分离:** Web/API 层不直接执行 Docker 命令。特权操作集中在 `internal/agent/``internal/runtime/tasks/`
191+
- **网络隔离:** 每个 host 拥有独立的 Docker network + sing-box gateway sidecar,bridge 网络断开以防止 IP 泄漏
192+
193+
## Anti-Patterns
194+
195+
### Direct Docker Exec from Control Plane
196+
197+
**What happens:** 在 embedded 模式下,control-plane 直接实例化 worker 执行 docker 命令
198+
**Why it's wrong:** 模糊了特权边界,未来多宿主机扩展时需要重构
199+
**Do this instead:** 始终通过 `agentapi.Dispatcher` 接口 dispatch,embedded 模式使用 `EmbeddedDispatcher` 适配器
200+
201+
### HTTP Status Code as Business Logic
202+
203+
**What happens:** 部分 handler 使用 HTTP 200 返回内部错误,或在 success body 中嵌入 error 字段
204+
**Why it's wrong:** 客户端难以统一处理错误
205+
**Do this instead:** 使用正确的 HTTP status code(4xx/5xx),body 统一为 `{error: string}` 或业务数据结构
206+
207+
## Error Handling
208+
209+
**Strategy:** 分层错误处理 + 统一错误码注册表
210+
211+
**Patterns:**
212+
- 基础设施层(docker exec, pgx): 包装为 `fmt.Errorf("...: %w", err)`
213+
- 业务层: 使用 `internal/cloudclaude/errcodes` 注册表定义结构化错误码
214+
- HTTP 层: 统一 `writeJSON` 输出,status code 反映错误类别
215+
216+
## Cross-Cutting Concerns
217+
218+
**Logging:** `log/slog` 结构化日志,支持 `LOG_LEVEL``LOG_FORMAT=json` 环境变量
219+
**Validation:** 输入校验分散在各 handler 中,无统一校验中间件
220+
**Authentication:** JWT (HS256) for admin/user API;entry auth 使用用户名+密码
221+
**Authorization:** Role-based (`admin` / `user`),中间件 `RequireRole`
222+
223+
---
224+
225+
*Architecture analysis: 2026-05-10*

0 commit comments

Comments
 (0)