Files
Nexus/docs/reports/2026-06-06-frontend-14p-contract-audit.md
2026-07-08 22:31:31 +08:00

240 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端 14 页 API 契约审计(含凭据轮询)
**日期**: 2026-06-06
**基线**: [audit-frontend-14p-2026-06-04-closure.md](audit-frontend-14p-2026-06-04-closure.md)43 H0 P0/P1
**增量范围**: 凭据轮询 `add-by-ip` / `pending_servers`;预设 `username` 字段
**方法**: 静态对照 `frontend/src/pages/*` + composables ↔ `server/api/*.py` 路由与响应形
## 结论
| 维度 | 结果 |
|------|------|
| 14 页 API 路径 | **PASS** — 全部端点在后端存在且 HTTP 方法一致 |
| 新增契约(Servers / Credentials | **PASS** — 请求/响应字段前后端对齐 |
| 类型集中化 | **PASS**`PendingServerItem` / `AddByIpResponse` / `PollErrorItem` 已入 `types/api.ts` |
| 单元测试 | **PASS**`tests/test_credential_poller.py` 7 passed |
| 本地门控 | **WARN**`local_verify.sh` 因本地 MySQL 断连未跑通(环境问题,非契约缺口) |
| 生产 SPA 部署 | **PASS**`ServersPage`/`CredentialsPage` 分块已含新契约;见 [production-verification](2026-06-06-credential-polling-production-verification.md) |
**新 FINDING**: 0 × P0/P10 × P2(契约层)
---
## 1. 凭据轮询契约(增量)
### 1.1 后端
| 方法 | 路径 | 实现 |
|------|------|------|
| POST | `/api/servers/add-by-ip` | `servers.py``poll_credentials` → 成功 `create_server` / 失败 `pending_servers` |
| GET | `/api/servers/pending` | `PendingServerRepositoryImpl.list_all` |
| POST | `/api/servers/pending/{id}/retry` | 再轮询;域名已存在 → 409 |
| DELETE | `/api/servers/pending/{id}` | 204 |
预设 `username`: `settings.py` `GET/POST/PUT` `/presets/``/ssh-key-presets/`
### 1.2 前端
| 组件 | 调用 |
|------|------|
| `ServersPage.vue` | 上述四端点;`onMounted` 加载 pending |
| `CredentialsPage.vue` | 预设 CRUD 含 `username`(默认 `root` |
### 1.3 响应形对照
| 字段 | 后端 | 前端消费 |
|------|------|----------|
| `success` | ✓ | 分支成功/失败 |
| `server` | `Server` 序列化 | 刷新列表 |
| `matched_preset` / `matched_username` | ✓ | 成功 toast |
| `pending_id` | ✓ | 失败后可查列表 |
| `errors[]` | `PollError` 列表 | 失败对话框表格 |
| `message` | 聚合摘要 | 对话框标题区 |
---
## 2. 十四页 API 矩阵
前缀均为 `/api``http` 客户端已含前缀,下表写相对路径。
### 2.1 DashboardPage `/`
| 端点 | 方法 | 后端 | 状态 |
|------|------|------|------|
| `/servers/stats` | GET | `servers.py` | OK |
| `/alert-history/` | GET | `alert_history.py` | OK |
| `/audit/` | GET | `audit.py` | OK |
| `/servers/` | GET | `servers.py` | OK |
| `/settings/bing-wallpapers/sync` | POST | `settings.py` | OK |
### 2.2 ServersPage `/servers`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/servers/` | GET/POST/PUT/DELETE | OK |
| `/servers/stats` | GET | OK |
| `/servers/check` | POST | OK |
| `/servers/batch/install-agent` 等 | POST | OK |
| `/servers/{id}/logs` | GET | OK |
| `/servers/add-by-ip` | POST | **新增 OK** |
| `/servers/pending` | GET | **新增 OK** |
| `/servers/pending/{id}/retry` | POST | **新增 OK** |
| `/servers/pending/{id}` | DELETE | **新增 OK** |
| `/presets/``/ssh-key-presets/``/assets/nodes` | GET | OK(表单 composable |
### 2.3 TerminalPage `/terminal`
| 端点 | 方法 | 位置 | 状态 |
|------|------|------|------|
| `/auth/webssh-token` | POST | `useTerminalSessions` | OK |
| `/servers/` | GET | `useTerminalSessions` | OK |
| `/terminal/quick-commands` | GET/POST/PUT/DELETE | `useTerminalQuickCommands` | OK |
| `/terminal/quick-commands/reorder` | PUT | `useTerminalQuickCommands` | OK |
| WebSocket `/ws/terminal` | WS | 页内 | OKRISK 已接受) |
### 2.4 FilesPage `/files`
| 端点 | 方法 | Composable | 状态 |
|------|------|------------|------|
| `/files/browse` | GET | `useFilesBrowse`(首选) | OK |
| `/sync/browse` | POST | `useFilesBrowse` 回退 | OK |
| `/servers/{id}/files-capability` | GET | `useFilesPermissions` | OK |
| `/servers/{id}/setup-files-sudo` | POST | `useFilesPermissions` | OK |
| `/sync/read-file``write-file``file-ops``chmod``compress``decompress``file-clipboard``upload` | POST | `useFilesActions` 等 | OK |
### 2.5 PushPage `/push`
| 端点 | 方法 | Composable | 状态 |
|------|------|------------|------|
| `/servers/` | GET | `usePushServers` | OK |
| `/sync/preview` | POST | `usePushPreview` | OK |
| `/sync/files` | POST | `usePushProgress` | OK |
| `/sync/cancel` | POST | `usePushProgress` | OK |
| `/servers/logs` | GET | `usePushLogs` | OK |
| `/sync/reconcile-stale-logs` | POST | `usePushLogs` | OK |
| `/sync/diagnose` | POST | `usePushLogs` | OK |
| WebSocket `/ws/sync` | WS | `usePushProgress` | OKRISK 已接受) |
### 2.6 ScriptsPage `/scripts`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/scripts/` | GET/POST/PUT/DELETE | OK |
| `/scripts/exec` | POST | OK |
| `/scripts/executions` | GET | OK |
| `/scripts/executions/{id}` | GET | OK |
| `/scripts/executions/{id}/stop` | POST | OK |
### 2.7 CredentialsPage `/credentials`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/presets/` | GET/POST/PUT/DELETE | OK**username 新增** |
| `/ssh-key-presets/` | GET/POST/PUT/DELETE | OK**username 新增** |
| `/scripts/credentials` | GET/POST/PUT/DELETE | OK |
### 2.8 SchedulesPage `/schedules`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/schedules/` | GET/POST/PUT/DELETE | OK |
| `/sync/files` | POSTrunNow | OK |
### 2.9 RetriesPage `/retries`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/retries/` | GET | OK |
| `/retries/{id}/retry` | POST | OK |
| `/retries/{id}` | DELETE | OK |
### 2.10 CommandsPage `/commands`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/assets/command-logs` | GET | OK |
| `/assets/ssh-sessions` | GET | OK |
### 2.11 AlertsPage `/alerts`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/alert-history/stats` | GET | OK |
| `/alert-history/` | GET | OK |
### 2.12 AuditPage `/audit`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/audit/` | GET | OK |
### 2.13 SettingsPage `/settings`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/settings/` | GET | OK |
| `/settings/{key}` | PUT | OK |
| `/settings/telegram/test` | POST | OK |
| `/settings/telegram/reveal-token` | POST | OK |
| `/settings/api-key/reveal` | POST | OK |
| `/settings/ip-allowlist` | GET/POST | OK |
| `/settings/ip-allowlist/toggle` | POST | OK |
| `/auth/password` | PUT | OK |
| `/auth/totp/setup` | POST | OK |
| `/auth/totp/enable` | POST | OK |
| `/auth/totp/disable` | POST | OK |
### 2.14 LoginPage `/login`
| 端点 | 方法 | 状态 |
|------|------|------|
| `/settings/bing-wallpapers` | GET | OK(公开只读) |
| `/auth/login` | POST | `stores/auth`(非页内直接调) | OK |
### 2.15 全局(App / auth store
| 端点 | 方法 | 状态 |
|------|------|------|
| `/search/` | GET | `App.vue` | OK |
| `/auth/me` | GET | `stores/auth` | OK |
| `/auth/logout` | POST | `stores/auth` | OK |
---
## 3. 与 2026-06-04 closure 的差异
| 变更 | 说明 |
|------|------|
| ServersPage +4 端点 | 凭据轮询快速添加与失败队列 |
| CredentialsPage 预设 | `username` 字段贯通 DB / API / UI |
| `types/api.ts` | 新增 pending 相关类型 |
| 功能指南 §12.2、§12.7 | 已更新 |
| 附录 J | 新增凭据轮询专章 |
跨页 RISKWS JWT、危险命令、bing 公开 GET)**无变化**,仍见 `risk-acceptance-single-operator.md`
---
## 4. 验证记录
```bash
.venv/bin/pytest tests/test_credential_poller.py -q # 7 passed
cd frontend && npx vite build # OK
```
```bash
# 待环境恢复后
bash scripts/local_verify.sh
cd frontend && NEXUS_E2E_BASE=http://127.0.0.1:8600 npm run test:e2e
```
---
## 5. 后续建议
1. 生产部署前端构建物(`ServersPage` / `CredentialsPage` 新 UI)。
2. 可选 E2E:快速添加 IP → 失败列表 → 重试/删除。
3. `acceptance_catalog.py` 可增加 `add-by-ip` 条目(若纳入 L4 回归)。
**维护**: 改 API 时同步更新本报告对应行、附录 J、功能指南 §12。