# EZ-API 控制平面 (Control Plane) 业务文档

> 本文档作为 Swagger 接口定义的补充，旨在详细说明 EZ-API 的业务逻辑、核心模型关系及配置含义，帮助前端开发与运维人员快速上手。
> **Swagger 入口**：`GET /swagger/index.html`

---

## 1. 快速入门

### 1.1 服务地址 (Base URL)
默认地址：`http://{host}:8080`

### 1.2 鉴权体系
系统采用三级鉴权机制，分别对应不同的操作权限：

| 角色 | 鉴权方式 | 配置来源 | 说明 |
| :--- | :--- | :--- | :--- |
| **Admin** | `Authorization: Bearer <admin_token>` | 环境变量 `EZ_ADMIN_TOKEN` | 全局管理权限，可管理所有租户、供应商和模型。 |
| **Master** | `Authorization: Bearer <master_key>` | 创建 Master 时返回 | 租户级权限，仅能管理所属的子 Key、查看自身统计和日志。 |
| **Key** | `Authorization: Bearer <child_key>` | Master 或 Admin 签发 | 用于调用 AI API，可通过 `/auth/whoami` 查询身份信息。 |
| **Internal** | `X-Internal-Token: <token>` | 环境变量 `EZ_INTERNAL_STATS_TOKEN` | 内部组件（如 Data Plane）同步指标使用。 |

### 1.4 身份识别接口
使用 `GET /auth/whoami` 可根据 Authorization header 中的 Token 识别当前身份类型：

| Token 类型 | 返回 `type` | 说明 |
| :--- | :--- | :--- |
| Admin Token | `"admin"` | 进入管理员面板 |
| Master Key | `"master"` | 进入租户自服务面板 |
| Child Key | `"key"` | 显示 Key 信息页，包含 `issued_by` 字段标识签发者 |

**示例响应**：
```json
// Admin Token
{"type": "admin", "role": "admin"}

// Master Key
{"type": "master", "id": 1, "name": "研发团队", "group": "default", ...}

// Child Key
{"type": "key", "id": 5, "master_id": 1, "issued_by": "master", ...}
```

### 1.3 通用约定
- **分页处理**：
  - 管理端列表 (`GET /admin/*`)：使用 `page` (从 1 开始) 和 `limit` (默认 50，最大 200)。
  - 日志列表：使用 `limit` 和 `offset`。
- **时间格式**：
  - 查询参数 (`since`/`until`)：使用 **Unix 秒**（整数）。
  - 日志清理 (`before`)：使用 **RFC3339 字符串** (例如 `2025-01-01T00:00:00Z`)。
- **模糊搜索**：`search` 参数通常匹配名称、描述或关键标识符。

---

## 2. 核心业务模型

EZ-API 的核心逻辑围绕“租户-令牌-路由-供应商”展开。

### 2.1 资源关系图
```mermaid
graph TD
    Admin[Admin 管理员] -- 创建 --> Master[Master 租户]
    Master -- 签发 --> Key[Key 子令牌]
    Master -- 关联 --> Namespace[Namespace 命名空间]
    Namespace -- 定义 --> Binding[Binding 路由规则]
    Binding -- 映射 --> ProviderGroup[ProviderGroup 上游组]
    ProviderGroup -- 包含 --> APIKey[APIKey 上游凭证]
    Binding -. 关联 .-> Model[Model 能力表]
```

### 2.2 身份与权限模型
- **Master (租户)**：系统的顶级账户单位。
  - `group`：路由分组，决定该租户默认使用哪一组供应商。
  - `epoch`：版本号。当 Master 被删除或重置时，Epoch 增加，所有旧的子 Key 将立即失效。
  - `global_qps`：租户级总限流，`0` 表示不限流。
- **Key (子令牌)**：由 Master 签发给最终用户使用的 API Key。
  - `scopes`：权限描述，仅用于业务标识。
  - `quota_limit`：总额度限制（Token 数），`-1` 表示无限额。
  - `quota_reset_type`：额度重置周期（如 `daily`, `monthly`）。
  - `allow_ips`/`deny_ips`：支持 CIDR 格式的 IP 白名单/黑名单。

### 2.3 路由与供应商模型
- **ProviderGroup (上游组)**：一组同类型上游定义（如 OpenAI / Anthropic / Compatible）。
  - `base_url`、`models` 在 Group 层统一声明。
  - `name` 即路由的 `route_group`（内部使用）。
- **APIKey (上游凭证)**：具体可用的 key 池。
  - `weight`：同组内负载均衡权重。
  - `auto_ban` / `ban_until`：支持自动熔断与手动禁用。
- **Model (模型能力表)**：全局能力注册表（上下文长度、功能支持等）。
- **Namespace (命名空间)**：逻辑隔离单位，用于组织 Binding 规则。
- **Binding (路由规则)**：核心路由逻辑。
  - 将 `bindingKey = namespace.public_model` 映射到 `group_id`（ProviderGroup）。
  - 同一 `bindingKey` 可存在多条 Binding（候选），通过 `weight` 进行加权选择。
  - `selector_type` + `selector_value` 用于从 Group 的 `models` 中解析上游 true_model。
  - 能力校验以 `bindingKey` 为 key（CP 会将 true_model 能力汇总到 `bindingKey`）。
  - 客户端请求若未携带 namespace，DP 会使用 key 的 `default_namespace` 生成 `bindingKey`。

### 2.4 状态机约定
| 状态值 | 适用对象 | 含义 |
| :--- | :--- | :--- |
| `active` | 所有 | 正常可用。 |
| `suspended` | Master, Key, Namespace | 已停用，请求将被拦截。 |
| `auto_disabled` | APIKey | 因故障被系统自动熔断。 |
| `manual_disabled` | APIKey | 被管理员手动禁用。 |

---

## 3. 功能开关 (Feature Flags)

系统支持通过 API 动态调整运行时行为。

### 3.1 存储逻辑
- **常规开关**：存储在 Redis Hash `meta:features` 中。
- **日志策略**：由于涉及清理逻辑，存储在独立 Key 中。

### 3.2 常用配置项
| 配置项 | 类型 | 说明 | 默认值 |
| :--- | :--- | :--- | :--- |
| `dp_state_store_backend` | string | 状态存储后端：`memory` (单机) / `redis` (集群)。 | `memory` |
| `dp_claude_cross_upstream` | bool | 是否允许将 Claude 协议请求路由到 OpenAI 兼容与 Google-family 上游。 | `true` |
| `log_request_body_enabled` | bool | 是否在日志中记录请求体（注意隐私风险）。 | `true` |
| `log_retention_days` | int | 日志保留天数。写入 Redis `meta:log:retention_days`。 | `30` |
| `log_max_records` | int | 最大日志保留条数。写入 Redis `meta:log:max_records`。 | `1000000` |

> **注意**：更新 Feature 后，Data Plane (DP) 会在下一个同步周期（通常为秒级）自动加载新配置。

---

## 4. API 模块概览

### 4.0 公开接口 - 无需鉴权
| 端点 | 说明 | 响应示例 |
|------|------|----------|
| `GET /health` | 健康检查（含依赖状态） | `{"status": "ok", "database": "up", "redis": "up", "uptime": "1h30m"}` |
| `GET /status` | 公开状态摘要 | `{"status": "ok", "uptime": "1h30m", "version": "v0.1.0"}` |
| `GET /about` | 系统信息 | `{"name": "EZ-API Gateway", "version": "v0.1.0", ...}` |
| `GET /auth/whoami` | 身份识别 | 根据 Token 返回身份类型和详细信息 |
| `GET /swagger/*` | API 文档 | Swagger UI |

### 4.1 管理端 (Admin API) - 需 Admin Token
- **租户管理**：创建 Master、签发子 Key、实时 QPS 监控、冻结/解冻。
- **上游管理**：ProviderGroup + APIKey 的 CRUD 与批量操作。
- **模型注册表**：管理全局模型能力，支持从远程 `models.dev` 刷新和回滚。
- **日志审计**：全站请求日志查询、按条件批量删除日志、配置 Webhook 告警。

### 4.2 租户端 (Master API) - 需 Master Key
- **自服务**：查看租户信息、管理自己的子 Key。
- **数据分析**：查看所属租户的请求日志、用量统计、实时 QPS。

### 4.3 内部接口 (Internal API) - 需 Internal Token
- **指标回传**：Data Plane 定期调用 `/internal/stats/flush` 同步 Token 消耗和请求数。

---

## 5. 典型操作示例

### 5.1 租户与令牌管理
1. **创建 Master 租户**：
   ```bash
   curl -X POST http://localhost:8080/admin/masters \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "name": "研发团队",
       "group": "default",
       "max_child_keys": 10,
       "global_qps": 50
     }'
   ```
2. **为 Master 签发子 Key**（注意：`key_secret` 仅在此处返回一次）：
   ```bash
   curl -X POST http://localhost:8080/admin/masters/{master_id}/keys \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "scopes": "chat,embedding",
       "quota_limit": 5000000,
       "quota_reset_type": "monthly",
       "model_limits_enabled": true,
       "model_limits": "gpt-4,claude-3-opus"
     }'
   ```

### 5.2 供应商与路由配置
1. **创建 ProviderGroup**：
   ```bash
   curl -X POST http://localhost:8080/admin/provider-groups \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "name": "openai-default",
       "type": "openai",
       "base_url": "https://api.openai.com/v1",
       "models": ["gpt-4o", "gpt-4o-mini"]
     }'
   ```
2. **创建 APIKey**：
   ```bash
   curl -X POST http://localhost:8080/admin/api-keys \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "group_id": 1,
       "api_key": "sk-...",
       "weight": 10
     }'
   ```
3. **创建模型路由 (Binding)**：
   ```bash
   curl -X POST http://localhost:8080/admin/bindings \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "namespace": "default",
       "public_model": "gpt-4o",
       "group_id": 1,
       "selector_type": "exact",
       "selector_value": "gpt-4o",
       "weight": 1
     }'
   ```

### 5.3 系统运维与监控
1. **调整全局日志保留策略**：
   ```bash
   curl -X PUT http://localhost:8080/admin/features \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "log_retention_days": 15,
       "log_max_records": 2000000
     }'
   ```
2. **查询特定 Key 的请求日志**：
   ```bash
   curl "http://localhost:8080/admin/logs?key_id=123&limit=20&status_code=200" \
     -H "Authorization: Bearer <admin_token>"
   ```
3. **查看租户实时统计**：
   ```bash
   curl http://localhost:8080/admin/masters/{id}/realtime \
     -H "Authorization: Bearer <admin_token>"
   ```

### 5.4 租户自服务 (Master API)
1. **租户签发子 Key**：
   ```bash
   curl -X POST http://localhost:8080/v1/tokens \
     -H "Authorization: Bearer <master_key>" \
     -H "Content-Type: application/json" \
     -d '{
       "scopes": "app-1",
       "quota_limit": 100000
     }'
   ```
2. **租户查看自身用量统计**：
   ```bash
   curl "http://localhost:8080/v1/stats?period=today" \
     -H "Authorization: Bearer <master_key>"
   ```

### 5.5 内部与高级操作
1. **手动刷新模型注册表**：
   ```bash
   curl -X POST http://localhost:8080/admin/model-registry/refresh \
     -H "Authorization: Bearer <admin_token>" \
     -H "Content-Type: application/json" \
     -d '{"ref": "main"}'
   ```
2. **内部指标回传 (Internal)**：
   ```bash
   curl -X POST http://localhost:8080/internal/stats/flush \
     -H "X-Internal-Token: <internal_token>" \
     -H "Content-Type: application/json" \
     -d '{
       "keys": [
         {
           "token_hash": "...",
           "requests": 100,
           "tokens": 5000,
           "last_accessed_at": 1734849600
         }
       ]
     }'
   ```

---

## 6. 备注
- **数据一致性**：控制平面 (CP) 修改配置后，数据平面 (DP) 通过 Redis Pub/Sub 或定期轮询实现最终一致性。
- **安全性**：请务必妥善保管 `EZ_ADMIN_TOKEN`。Master Key 和子 Key Secret 在数据库中均以哈希形式存储，丢失无法找回，只能重置。
