240 lines
8.1 KiB
Markdown
240 lines
8.1 KiB
Markdown
# 前端 14 页 API 契约审计(含凭据轮询)
|
||
|
||
**日期**: 2026-06-06
|
||
**基线**: [audit-frontend-14p-2026-06-04-closure.md](audit-frontend-14p-2026-06-04-closure.md)(43 H,0 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/P1,0 × 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 | 页内 | OK(RISK 已接受) |
|
||
|
||
### 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` | OK(RISK 已接受) |
|
||
|
||
### 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` | POST(runNow) | 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 | 新增凭据轮询专章 |
|
||
|
||
跨页 RISK(WS 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。
|