# MVP v3.0 迭代总结（Ray + SFTPGo + API + WebUI）

本文总结 v3.0 迭代最终落地的功能、架构、运行方式、验收点与已知限制，便于后续评审、交接与继续迭代。

相关更详细文档：
- `specs/mvp/v3.0/v3.0_design.md`
- `specs/mvp/v3.0/v3.0_api.md`
- `specs/mvp/v3.0/v3.0_dev_plan.md`
- `specs/mvp/v3.0/v3.0_acceptance.md`
- `specs/mvp/v3.0/v3.0_progress.md`

---

## 1. 目标与范围

v3.0 作为“第一版可发布”的最小闭环，主要新增：
- **WebUI**：最小可用的人机界面（登录、任务提交与查看、数据入口、管理员入口）。
- **用户管理**：基于内部 token 的用户体系（admin 与普通用户），支持创建用户与签发 token。
- **数据管理入口（SFTPGo）**：用户通过 SFTP/WebClient 上传下载自己的数据；同时暴露只读的共享数据/缓存目录（common）用于复用。
- **保持训练闭环**：仍通过 Ray Job 提交到集群执行（PPO/GRPO/SFT 三类 workload 都验证）。

明确不做（本迭代保持最小）：
- 不支持用户自定义训练代码（TaskSpec 的 `code_path` 固定走 common 下的 verl snapshot 策略）。
- 不做复杂资源排队优化/多集群/多租隔离策略（目前隔离粒度主要在用户 jobs 目录层）。

---

## 2. 系统架构（最终形态）

核心组件：
- **Ray 集群（容器）**
  - `argus-ray-head`：head 节点（无 GPU/不跑训练），提供 Ray Dashboard 与 Job Server。
  - `argus-ray-worker-0/1`：worker 节点（有 GPU），承载训练任务。
  - worker 以 “stateless + watchdog 自动连接 head” 的方式加入集群。
- **API Server（运行在 head 容器内）**
  - 读取 YAML 配置（dev/prod），维护任务队列（sqlite），并周期性调度将任务提交到 Ray。
  - 同时承载 WebUI（`/ui`）。
- **SFTPGo（容器）**
  - 提供 SFTP（端口 `2022`）与 Web Client/Admin（端口 `8081` 映射到容器 8080）。
  - 用户 home 为 `/private/users/<user>`，默认可读写。
  - 额外提供 `/common/*` 共享只读入口（见第 4 节）。
- **共享存储（NFS/GPFS 等挂载到容器内 `/private`）**
  - `/private/common`：共享缓存（hf、datasets、models、db、logs 等）。
  - `/private/users/<user>`：用户隔离目录（jobs/datasets/models/code/trash 等）。

---

## 3. 任务与调度（Task / Ray Job）

### 3.1 Task（平台概念）
- 用户向 API 提交 TaskSpec（YAML），平台分配 `task_id`（可读、包含用户名）。
- `task_id` 对应内部状态机与重试逻辑；底层每次提交 Ray Job 会产生 attempt 与 `ray_submission_id`。

### 3.2 Ray Job（Ray 概念）
- 真正执行训练的 driver 通过 Ray Job 运行在集群 worker 上（避免 head 承载训练）。
- head 节点通过 `--num-cpus=0` / 自定义资源等策略避免调度到 head。

### 3.3 VERL 资源预检查的处理
- VERL 在创建资源池时会做 fail-fast 资源预检查（如“可用 GPU 不足”直接报错退出）。
- v3.0 延续 v2.x 的策略：服务端识别失败原因并按策略重试/回退（具体见 scheduler 实现与 v2.5/3.0 文档）。

---

## 4. 数据管理（SFTPGo）与 common 只读目录

### 4.1 用户目录（读写）
- 用户通过 SFTP/WebClient 访问自己的 home：`/private/users/<user>`
- 目录结构（至少）：`datasets/ models/ code/ jobs/ trash/ common/`

### 4.2 common 只读（方案 A：Virtual Folder）
本迭代采用 SFTPGo 的 Virtual Folder + 路径权限覆盖，实现用户可读共享目录但不可写。

最终对外暴露为：
- `/common/datasets`（只读）
  - **mapped_path 指向真实目录 `/private/datasets`**（避免 `/private/common/datasets` 中大量 symlink 导致的 WebClient “权限不足/越界”问题）
- `/common/hf`（只读）
  - mapped_path 指向 `/private/hf`

备注：
- `/private/common/datasets` 内部存在 symlink（如 `gsm8k -> /private/datasets/gsm8k`），如果虚拟目录映射到 symlink 根目录，SFTPGo 会把 symlink 跳转视为“逃逸 root”，导致点击进入时报权限不足；因此选择直接映射到真实目录根。

---

## 5. WebUI（最小可用）

入口：
- `/ui/login`：粘贴 token（存 browser `localStorage`）
- `/ui/tasks`：任务列表（Running/Pending/Completed），Completed 支持分页
- `/ui/tasks/new`：提交任务（PPO/GRPO/SFT 三套样例可一键填充）
- `/ui/data`：展示当前用户名、支持重置 SFTPGo 密码并复制；提供跳转到 SFTPGo WebClient；提示 FileZilla 等客户端用法
- `/ui/admin`：管理员入口（创建用户、签发 token、用户列表）
- 导航栏提供 Ray Dashboard 快捷跳转（当前 IP 的 `:8265`）

关于 admin 页面权限：
- admin 页面本身可访问，但其数据请求必须携带 admin token；否则会在页面内显示 401/403/错误信息（满足“需要先提供 admin token 才能看到内容”）。

---

## 6. API（v3.0 新增/强化点）

核心接口（节选）：
- 认证：
  - Bearer token：`MVP_INTERNAL_TOKEN`（admin）或用户 token（由 admin 签发）
- 用户管理（admin）：
  - `POST /api/v2/users` 创建用户（并初始化用户目录）
  - `GET /api/v2/users` 获取用户列表（包含最新 token、创建/更新时间等）
  - `POST /api/v2/users/{user_id}/tokens` 签发用户 token
- 任务：
  - `POST /api/v2/tasks` 提交 TaskSpec（YAML）
  - `GET /api/v2/tasks` 任务列表（支持 states/limit/offset，用于 Completed 分页）
  - `GET /api/v2/tasks/{task_id}`、`POST /api/v2/tasks/{task_id}:cancel`、`GET /api/v2/tasks/{task_id}/logs`
  - `GET /api/v2/queue`（运行中/待调度概览）
- 数据/SFTP：
  - `GET /api/v2/me` 返回用户路径信息、SFTP 连接信息，并 best-effort 对齐 SFTPGo 用户配置
  - `POST /api/v2/me/sftp:reset_password` 用户自助重置 SFTPGo 密码（一次性返回明文）

安全取舍说明（当前为内网/开发优先）：
- 为了 Admin WebUI “可查看并复制 token”，数据库持久化存储了 `token_plain`（明文 token）。
  - 这在生产场景通常不建议；未来可改为只展示“重置/重新签发”而不回显明文，或只回显一次。

---

## 7. 持久化与清理

- 任务队列：sqlite（WAL 模式）
- SFTPGo：自带 sqlite db（容器挂载持久化目录）
- Jobs 目录清理策略（服务端 janitor）：
  - job 结束后 3 天移动到回收目录（trash）
  - 回收目录再保留 7 天后删除

---

## 8. 运行方式与脚本

开发/验收脚本：
- `src/mvp/scripts/run_all_v30_api.sh`：端到端拉起（Ray + SFTPGo + API），并通过 API 提交 PPO/GRPO/SFT，等待完成并验收
- 其他脚本用于启动/停止 API、准备数据与模型、探测服务就绪等（详见 scripts 目录与 README）

典型端到端（示例参数）：
- `MVP_INTERNAL_TOKEN=my-dev-token`
- `SFTPGO_ADMIN_PASSWORD=my-dev-sftpgo-admin`
- 支持 `RESET_DB/RESET_SFTPGO` 用于测试环境重置

---

## 9. 验证结果（已跑通）

在 `argus@h1` 环境中已完成端到端验证：
- Ray 集群可用（head + 2 worker）
- API server + WebUI 可用
- SFTPGo（admin + 普通用户）可用
- 通过 API 连续提交 PPO/GRPO/SFT 三种任务均能完成（SUCCEEDED）
- 用户可以登录 SFTPGo WebClient/SFTP，访问自己的目录，并访问 `/common/datasets`、`/common/hf` 的只读内容

同时本地单测通过：
- pytest 全绿
- 覆盖率阈值 >= 90%

---

## 10. 已知限制 & 后续可改进

- WebUI 当前为最小版，交互与权限提示仍偏“工程化”而非产品化（后续可增强错误提示、搜索筛选、任务详情聚合等）。
- token 明文持久化仅适合内网/开发场景；生产建议改为一次性展示或支持撤销/轮换策略。
- SFTPGo 虚拟目录目前保留了历史遗留映射（例如 `/common/models` 可能残留），后续可在升级脚本中做一次性清理与迁移。

