# Ops-Assistant 前端对接文档（给 Gemini）

> 目的：让前端可独立完成 ops-assistant 新后台页面，不依赖旧 xiaji 记账页面心智。  
> 基址：同源（已登录后直接请求 `/api/v1/*`）  
> 鉴权：Cookie Session（`ops_user` + `ops_token`）

---

## 0. 统一响应约定（必须）

### 成功
```json
{
  "code": "OK",
  "message": "ok",
  "data": { ... }
}
```

### 失败
```json
{
  "code": "ERR_XXX",
  "message": "可读错误信息"
}
```

### 前端统一处理建议
- `if (!res.ok)`: 显示 `message`
- `if (res.ok)`: 使用 `data`
- 不再使用 `error/status` 老字段

> 例外：`GET /api/v1/export` 成功是文件流下载，不是 JSON。

---

## 1. 权限与用户信息

### 1.1 获取当前用户
**GET** `/api/v1/me`

### data 字段
- `username`
- `role`
- `user_id`
- `permissions[]`
- `flags{}`
- `effective_capabilities{}`

### capability 常用键
- `can_view_ops`
- `can_cancel_ops`
- `can_retry_ops`
- `can_view_flags`
- `can_edit_flags`
- `can_view_channels`
- `can_edit_channels`
- `can_test_channels`
- `can_view_audit`

前端应以 capability 驱动按钮显隐。

---

## 2. Dashboard（新后台首页主数据）

### 2.1 获取总览
**GET** `/api/v1/dashboard/overview`

### 返回 data
```json
{
  "jobs": {
    "recent": [OpsJob...],
    "status_count": {
      "pending": 0,
      "running": 0,
      "success": 0,
      "failed": 0,
      "cancelled": 0
    }
  },
  "modules": [
    {"module":"cpa","enabled":true},
    {"module":"cf","enabled":false},
    {"module":"mail","enabled":false}
  ],
  "channels": [
    {"platform":"telegram","enabled":true,"status":"ok"}
  ]
}
```

### 2.2 获取轻量摘要（推荐首页首屏）
**GET** `/api/v1/dashboard/summary`

### 返回 data
```json
{
  "jobs": {
    "total": 120,
    "running": 2,
    "failed": 5,
    "success": 98
  },
  "modules": {
    "cpa": true,
    "cf": false,
    "mail": false
  }
}
```

---

## 3. 模块管理（Module Center）

### 3.1 模块列表
**GET** `/api/v1/modules`

### 返回 data
```json
{
  "modules": [
    {
      "module":"cpa",
      "display_name":"CPA 管理",
      "flag_key":"enable_module_cpa",
      "enabled":true
    }
  ]
}
```

### 3.2 切换模块开关
**POST** `/api/v1/modules/:module/toggle`

- `:module` 仅支持：`cpa|cf|mail`

### body
```json
{
  "enabled": true,
  "reason": "前端联调启用"
}
```

### 成功 data
```json
{
  "module": "cf",
  "flag_key": "enable_module_cf",
  "old": false,
  "new": true
}
```

### 交互建议
- 操作前确认弹窗
- 必填 reason
- 成功后刷新 `/api/v1/modules` 与 `/api/v1/dashboard/overview`

---

## 4. Ops 任务中心

### 4.1 任务列表
**GET** `/api/v1/ops/jobs?limit=50`

支持筛选 query：
- `status`（pending|running|success|failed|cancelled）
- `target`（如 hwsg）
- `runbook`（如 cpa_usage_backup）
- `request_id`
- `operator`（操作者 user_id，int64）
- `risk_level`（low|medium|high 等）
- `q`（模糊检索，命中 command/runbook/target/request_id）
- `from`（RFC3339，按 created_at 下界过滤）
- `to`（RFC3339，按 created_at 上界过滤）

### data
```json
{
  "jobs": [OpsJob...],
  "filters": {
    "limit": 50,
    "status": "failed",
    "target": "hwsg",
    "runbook": "cpa_usage_restore",
    "request_id": "ops-u1-1741563000",
    "operator": "1",
    "risk_level": "high",
    "q": "restore",
    "from": "2026-03-10T07:00:00+08:00",
    "to": "2026-03-10T08:00:00+08:00"
  }
}
```

### 4.2 按 request_id 反查任务
**GET** `/api/v1/ops/jobs/request/:requestID?limit=50`

### data
```json
{
  "request_id":"req-20260310-abc",
  "total": 3,
  "jobs":[OpsJob...]
}
```

### 4.3 任务详情（含步骤 + 聚合统计）
**GET** `/api/v1/ops/jobs/:id`

### data
```json
{
  "job": { ... },
  "steps": [
    {
      "step_id":"...",
      "action":"ssh.exec",
      "status":"success|failed|running",
      "stdout_tail":"...",
      "stderr_tail":"..."
    }
  ],
  "step_stats": {
    "running": 0,
    "success": 3,
    "failed": 1,
    "skipped": 0
  },
  "step_total": 4,
  "duration": {
    "job_ms": 5321,
    "steps_ms_sum": 4870
  }
}
```

### 4.4 取消任务
**POST** `/api/v1/ops/jobs/:id/cancel`

body:
```json
{"reason":"人工终止，参数配置错误"}
```

### data
```json
{"id":123,"reason":"人工终止，参数配置错误"}
```

### 4.5 重试任务
**POST** `/api/v1/ops/jobs/:id/retry`

body:
```json
{"reason":"修复配置后重试"}
```

### data
```json
{"old_job_id":123,"new_job_id":456,"reason":"修复配置后重试"}
```

### 前端权限
- cancel 按钮：`can_cancel_ops`
- retry 按钮：`can_retry_ops`

### 交互约束
- cancel/retry 必须填写 reason（后端强校验）
- retry 仅允许 failed 状态任务
- cancel 仅允许 pending/running 状态任务
- `from/to` 参数必须是 RFC3339（如 `2026-03-10T07:00:00+08:00`）

---

## 5. 通道管理（Channels）

### 5.1 通道列表
**GET** `/api/v1/admin/channels`

### data
```json
{
  "channels": [
    {
      "platform":"telegram",
      "name":"Telegram Bot",
      "enabled": true,
      "status":"ok",
      "config_json":"{}",
      "draft_config_json":"{}",
      "secrets":"{\"token\":\"***\"}",
      "draft_secrets":"{}",
      "has_draft": false
    }
  ]
}
```

### 5.2 更新草稿
**PATCH** `/api/v1/admin/channels/:platform`

body 可包含：
- `name`
- `enabled`
- `config`
- `secrets`

### 5.3 发布草稿
**POST** `/api/v1/admin/channels/:platform/publish`

### 5.4 热加载
**POST** `/api/v1/admin/channels/reload`

### 5.5 一键全禁用
**POST** `/api/v1/admin/channels/disable-all`

### 5.6 启用/禁用单通道
- **POST** `/api/v1/admin/channels/:platform/enable`
- **POST** `/api/v1/admin/channels/:platform/disable`

### 5.7 连通性测试
**POST** `/api/v1/admin/channels/:platform/test`

### 5.8 原子应用（patch + publish + reload）
**POST** `/api/v1/admin/channels/:platform/apply`

> apply 失败 message 中可能包含 stage 信息（patch/publish/reload）。

---

## 6. 审计日志

### 6.1 查询审计
**GET** `/api/v1/admin/audit`

支持 query：
- `action`
- `target_type`
- `result`
- `actor_id`
- `from` (RFC3339)
- `to` (RFC3339)
- `limit` (默认100，最大500)
- `offset`

### data
```json
{ "logs": [AuditLog...] }
```

---

## 7. 风险开关（Flags）

### 7.1 列表
**GET** `/api/v1/admin/settings/flags`

### data
```json
{ "flags": [FeatureFlag...] }
```

### 7.2 修改
**PATCH** `/api/v1/admin/settings/flags/:key`

body:
```json
{ "enabled": true, "reason": "..." }
```

> 部分 flag `RequireReason=true`，reason 为空会失败。

---

## 8. 兼容层（前端新代码不要用）

以下仅兼容旧页面：
- `GET /api/records`
- `POST /delete/:id`
- `GET /export`

新前端一律使用 `/api/v1/*`。

### 8.1 Legacy 使用统计（用于迁移观察）
**GET** `/api/v1/admin/legacy/usage`

### data
```json
{
  "summary": [
    {"route":"/api/records","count":12},
    {"route":"/delete/:id","count":3},
    {"route":"/export","count":1}
  ],
  "recent": [AuditLog...]
}
```

### 8.2 Legacy 调用趋势（按天）
**GET** `/api/v1/admin/legacy/trend?days=7`

- `days` 范围：`1~90`，默认 `7`

### data
```json
{
  "days": 7,
  "from": "2026-03-04T00:00:00+08:00",
  "trends": [
    {
      "route": "/api/records",
      "points": [
        {"day":"2026-03-04","count":2},
        {"day":"2026-03-05","count":1}
      ]
    }
  ]
}
```

### 8.3 Legacy 响应头（便于前端观察迁移）
访问旧路由时，响应头会包含：
- `X-API-Deprecated: true`
- `X-API-Replacement: <对应新路由>`
- `Warning: 299 - "legacy API deprecated, use ..."`

### 8.4 Legacy 下线就绪评估
**GET** `/api/v1/admin/legacy/readiness?days=7&zero_days=3`

- `days`：观察窗口（1~90，默认 7）
- `zero_days`：要求连续 0 调用天数（1~30，默认 3）

### data
```json
{
  "days": 7,
  "zero_days": 3,
  "window_total": 0,
  "route_totals": {
    "/api/records": 0,
    "/delete/:id": 0,
    "/export": 0
  },
  "consecutive_zero_days": {
    "/api/records": 7,
    "/delete/:id": 7,
    "/export": 7
  },
  "ready": true,
  "recommendation": "可考虑下线 legacy 路由（已满足连续0调用阈值）"
}
```

---

## 9. 前端落地建议（给 Gemini）

1. 建立统一 `apiClient`：
   - `request(url, options)`
   - 自动解析 `{code,message,data}`
   - 非 2xx 抛 message

2. 页面优先级：
   - P1：Dashboard（overview + summary）
   - P1：Ops Jobs
   - P1：Modules
   - P2：Channels
   - P2：Audit

3. 权限驱动 UI：
   - 所有按钮显隐由 `effective_capabilities` 控制

4. 状态刷新策略：
   - dashboard 每 10~20s 轮询
   - ops jobs running 状态 5~10s 轮询

5. 错误展示：
   - toast + message 文本
   - 不展示后端堆栈

---

## 10. 已知限制

- export 成功仍为文件流（设计如此）。
- gojieba 编译 warning 可忽略（非功能错误）。
