# OCDP 系统测试 Bug 报告

**测试日期:** 2026-05-11
**测试环境:** http://10.6.80.114:18080
**集群:** k3s (dbf824f1-9962-4d8e-881e-870c75fdb6f5), k8s (23880994-dfe4-48d0-abc0-b49692cc630a)
**Harbor:** harbor.bwgdi.com (83b823af-873b-457c-912c-9ccde3cb12e6)

---

## 测试团队
| Agent | 角色 | 账号 |
|-------|------|------|
| user-a-agent | 前端 UI 测试 | test-user-a / TestUserA123! |
| user-b-agent | API/部署测试 | test-user-b / TestUserB123! |
| user-c-agent | 权限隔离测试 | test-user-c / TestUserC123! |
| security-agent | 安全测试 | admin + 普通用户 |

---

## Bug 列表 (按严重度排序)

### P0 - Blocker (核心功能不可用)

| ID | 标题 | 发现者 | 页面/端点 | 描述 |
|----|------|--------|-----------|------|
| BUG-001 | **Launch 按钮点击无任何反应** | user-a | `/artifact/registries` (TagCard) | Chart Browser 中 TagCard 的 "Launch" 按钮显示为可用状态 (`is_enabled() == True`)，但点击后无任何效果：不弹出 Launch Modal，无 URL 变化，无控制台错误。**核心"一键部署"流程完全阻塞** |
| BUG-002 | **SPA 直接路由返回空白页面** | user-a | `/clusters`, `/registries`, `/monitoring`, `/launch` | 直接访问 SPA 旧路由时只渲染 `<div id="root">` 空壳，React SPA 无法挂载。代码中已定义 redirect 映射但未生效（如 `/clusters` → `/configuration/clusters`） |

### P1 - 高 (High)

| ID | 标题 | 发现者 | 页面/端点 | 描述 |
|----|------|--------|-----------|------|
| BUG-003 | DELETE 实例返回 404 但实际成功删除 | user-b, user-c | `DELETE /clusters/{id}/instances/{id}` | 删除操作正确触发 `pending-delete` 状态转换，但 HTTP 返回 **404**（空 body），非预期 202/204。客户端误判为失败 |
| BUG-004 | DELETE 实例返回空响应体 | user-b | `DELETE /clusters/{id}/instances/{id}` | 用正确的 token 和 ID 请求，返回空 body（无 JSON），前端解析会失败 |

### P2 - 中 (Medium)

| ID | 标题 | 发现者 | 页面/端点 | 描述 |
|----|------|--------|-----------|------|
| BUG-005 | Tags 专用端点缺失 | user-b | `GET /registries/{id}/repositories/{repo}/tags` | 端点未实现，返回纯文本 "404 page not found"。虽可通过 `/artifacts` 获取 tag，但 API 不完整 |
| BUG-006 | 跨用户 namespace 部署时静默覆盖 | user-c | `POST /clusters/{id}/instances` | 用户请求部署到其他用户的 namespace 时，服务端静默使用自己的 namespace，返回 200 且无任何警告或提示 |
| BUG-007 | Clusters Metrics API 缺失 | user-b | `GET /monitoring/clusters/{id}/metrics` | 监控页面可能需要的数据端点未实现（404） |
| BUG-008 | Cluster Stats API 缺失 | user-b | `GET /clusters/{id}/stats` | 统计端点未实现（404） |
| BUG-009 | Kubeconfig API 缺失 | user-b | `GET /clusters/{id}/kubeconfig` | kubeconfig 签发端点未实现（404） |
| BUG-010 | "Launch" 按钮缺乏可访问性标识 | user-a | TagCard "Launch" | Chart 上的 "Launch" 按钮无 `aria-label`，与侧边栏 "Launch Instance" 导航项标签冲突，屏幕阅读器用户无法区分 |

### P3 - 低 (Low)

| ID | 标题 | 发现者 | 页面/端点 | 描述 |
|----|------|--------|-----------|------|
| BUG-011 | API 响应格式不一致 | user-b | 列表 API | Clusters/Registries 返回裸数组，Instances 返回 `{ "instances": [...], "total": N }` 包装对象 |
| BUG-012 | `/auth/me` 返回空的 token 字段 | user-b | `GET /auth/me` | 响应中包含 `"accessToken": ""` 和 `"refreshToken": ""` 空字段，复用了 login 响应 DTO 未清理 |
| BUG-013 | 登录接口存在用户枚举漏洞 | security | `POST /auth/login` | 不存在用户返回 "user not found"，存在用户返回 "invalid password"，攻击者可枚举有效用户名 |
| BUG-014 | 登录接口无速率限制 | security | `POST /auth/login` | 10 次连续请求全部返回 401，无 429 限流或锁定 |
| BUG-015 | Nginx 版本信息泄露 | security | HTTP Headers | `Server: nginx/1.27.5` 暴露精确版本号 |
| BUG-016 | CORS 配置过于宽松 | security | All API | `Access-Control-Allow-Origin: *` 允许任意跨域请求 |
| BUG-017 | 缺少安全响应头 | security | All pages | 缺少 HSTS、X-Frame-Options、Content-Security-Policy 等 |
| BUG-018 | `/health` 端点返回 SPA HTML | security | `GET /health` | 健康检查返回完整 index.html，非 JSON 状态响应 |

---

## 分类汇总

### 前端 Bug
| ID | 描述 | 严重度 |
|----|------|--------|
| BUG-001 | Launch 按钮无反应（核心功能阻塞） | P0 🔴 |
| BUG-002 | SPA 路由空白页 | P0 🔴 |
| BUG-010 | Launch 按钮缺少 aria-label | P2 🟡 |

### 后端 API Bug
| ID | 描述 | 严重度 |
|----|------|--------|
| BUG-003 | DELETE 返回 404 | P1 🟠 |
| BUG-004 | DELETE 空 body | P1 🟠 |
| BUG-005 | Tags 端点缺失 | P2 🟡 |
| BUG-007 | Metrics API 缺失 | P2 🟡 |
| BUG-008 | Stats API 缺失 | P2 🟡 |
| BUG-009 | Kubeconfig API 缺失 | P2 🟡 |
| BUG-011 | 响应格式不一致 | P3 🔵 |
| BUG-012 | auth/me 空 token 字段 | P3 🔵 |
| BUG-018 | /health 返回 HTML | P3 🔵 |

### 安全/权限 Bug
| ID | 描述 | 严重度 |
|----|------|--------|
| BUG-006 | Namespace 静默覆盖（安全但令人困惑） | P2 🟡 |
| BUG-013 | 用户枚举（错误消息差异） | P3 🔵 |
| BUG-014 | 无速率限制 | P3 🔵 |
| BUG-015 | Nginx 版本泄露 | P3 🔵 |
| BUG-016 | CORS Origin: * | P3 🔵 |
| BUG-017 | 缺少安全响应头 | P3 🔵 |

### 严重度分布
| 级别 | 数量 |
|------|------|
| P0 (Blocker) | 2 |
| P1 (High) | 2 |
| P2 (Medium) | 6 |
| P3 (Low) | 8 |
| **合计** | **18** |

---

## 测试通过项

### 认证
- [x] 有效凭据登录 (admin + 所有 test-user)
- [x] 无效凭据返回 401
- [x] 无 token 访问被保护 API 返回 401
- [x] 无效/篡改 JWT token 全部被拒绝
- [x] /auth/me 返回正确的用户信息
- [x] JWT payload 包含角色、权限、namespace

### Cluster / Registry API
- [x] 集群列表正常返回
- [x] 集群健康检查正常
- [x] Registry 列表正常返回
- [x] 通过 artifacts 端点浏览 repository 正常
- [x] 无效 registry/repository 返回恰当错误

### 权限隔离
- [x] GET /users 返回 403 (普通用户)
- [x] POST /auth/register 返回 403 (普通用户)
- [x] 用户无法访问其他用户的 workspace 资源
- [x] 用户无法部署到其他用户的 Kubernetes namespace
- [x] 安全架构：核心认证/授权/脱敏/隔离控制均正确实现

### 实例部署生命周期
- [x] 实例创建操作成功（pending-install）
- [x] 实例状态正确追踪（pending-install → deployed）
- [x] 实例删除正确转换状态（pending-delete → 消失）
- [x] 实例列表按 clusterId 正确过滤

### 安全测试通过项
- [x] XSS/SQLi 注入安全处理
- [x] 路径遍历攻击被阻止
- [x] JWT alg=none/无效格式被拒绝
- [x] 集群凭据和 Registry 密码脱敏显示 (••••••••)
- [x] 自注册端点需认证 (401)

---

## 建议修复优先级

### 立即修复 (P0)
1. **BUG-001**: 调查 Launch 按钮 onClick handler — TagCard 组件中 `onLaunch` prop 未正确传递给 LaunchModal，或 launch 状态 / artifactType 检查阻止了 modal 打开
2. **BUG-002**: 检查 React Router `<Navigate redirect>` 组件和 SPA 的 index.html 配置，确保旧路由正确重定向

### 尽快修复 (P1)
3. **BUG-003/004**: InstanceHandler.Delete 应返回 202 Accepted + `{"status":"deleting"}` 而非 404+空 body

### 短期修复 (P2)
4. 实现 `/metrics`, `/stats` 等缺失 API
5. Launch 按钮添加 `aria-label` 属性
6. Namespace 覆盖时返回警告或 403

### 安全加固 (P3)
7. 登录错误消息统一为 "Invalid username or password"
8. 实现速率限制
9. Nginx 安全加固：`server_tokens off` + 安全响应头
10. CORS 收紧为具体域名
11. 修复 `/health` 端点
12. 统一 API 响应格式
