# 多项目 CDK 接入说明

## 项目隔离规则

每个项目都有固定且永不复用的 `project_key`。普通 CDK、客户端密钥、用户绑定、任务、卡库筛选和项目入口都以该标识隔离：

- 普通 CDK 只能验证和调用所属项目，不能跨项目使用或融卡；
- 仅 `registration_scope=global` 的 `admin_cdk`，以及平台总管理员 CDK，可跨全部已启用 `integration_mode=registration` 项目完成注册绑定、授权刷新和工作区心跳；它们不获得任何平台管理接口权限；
- 项目暂停后，所属普通 CDK 立即停止新调用；历史卡、账本和审计仍保留；
- `super_admin` 管理员身份是平台级身份，管理全部项目，但不会把管理员权限下发给项目 CDK；
- CDK 明文、管理员密钥、访问令牌、会话、Cookie、代理认证和验证码不得写入项目源码、日志或接口响应。

## 平台预置注册机项目

以下注册机项目已经在平台创建完成。开卡时必须选择对应项目，不能把普通 CDK 或客户端密钥跨项目复用：

| 项目名称 | `project_key` | 专用对接文档 |
| --- | --- | --- |
| GPTFREE 注册机 | `registration_core` | `GET /api/v1/registration-core-guide` |
| 生图注册机 | `image_generation_registration` | `GET /api/v1/image-generation-registration-guide` |

两者均使用 `integration_mode=registration` 和相同的 API 契约，但每个项目有独立客户端密钥、CDK、绑定、充值和换卡记录。只有显式配置为 `registration_scope=global` 的管理员 CDK 和平台总管理员 CDK 可以跨项目建立独立绑定；这不会让普通项目 CDK 互通。

## 新项目创建

管理员调用：

```bash
curl -sS -X POST "$BASE_URL/api/v1/admin/projects" \
  -H "Authorization: Bearer $SUPER_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "project_key": "example_register",
    "name": "示例注册机",
    "description": "独立本地注册项目",
    "entry_path": "https://example.invalid/",
    "integration_mode": "registration"
  }'
```

`project_key` 创建后不可修改；项目可改名、暂停或下线。接入类型如下：

| `integration_mode` | 用途 | 项目端接口 |
| --- | --- | --- |
| `task_api` | 云端提炼、协议支付和任务轮询 | 动态渠道、预检、任务、查询、取消 |
| `cdk_access` | 项目只需要验证 CDK 状态和有效期 | 项目契约、CDK 状态 |
| `registration` | 本地注册机用户绑定、续期和短期授权 | 激活、授权刷新、工作区心跳 |

创建后，从“开卡”选择该项目开普通 CDK。不同项目的 CDK 无法互相调用或融卡。

## 项目契约 API

项目端使用自己的 CDK 读取契约，不需要抓取管理台，也不需要复制云端脚本：

```bash
curl -sS "$BASE_URL/api/v1/projects/example_register/integration" \
  -H "Authorization: Bearer $PROJECT_CDK"
```

响应包含项目名称、接入类型、稳定接口清单、CDK 隔离边界和卡库管理路径。它不返回 CDK 明文、管理员密钥、用户密码、令牌、会话、支付链接或代理资料。

项目端首次接入还必须读取机器能力接口：

```bash
curl -sS "$BASE_URL/api/v1/projects/example_register/capabilities" \
  -H "Authorization: Bearer $PROJECT_CDK"
```

以 `capabilities.revision`、`project_access_allowed`、`feature_flags` 和 `required_endpoint_ids` 为准选择调用链；不要自行解析 OpenAPI 路径、猜测 CDK 所属项目或根据 CDK 前缀判断权限。

所有项目都可以用下面接口校验当前 CDK：

```bash
curl -sS "$BASE_URL/api/v1/cdk/status?project_key=example_register" \
  -H "Authorization: Bearer $PROJECT_CDK"
```

项目只应依据 `cdk.status`、`expires_at`、`activation_status`、`remaining_quota` 和 `available_slots` 决定是否继续，不得仅凭本地缓存放行。

## 注册机授权项目

`integration_mode=registration` 的项目使用独立客户端签名，不把本地密码、工作区内容或会话上传到平台。

管理员项目级接口：

```text
GET/POST /api/v1/admin/projects/{project_key}/registration/client-keys
POST     /api/v1/admin/projects/{project_key}/registration/client-keys/{id}/rotate
GET      /api/v1/admin/projects/{project_key}/registration/overview
GET      /api/v1/admin/projects/{project_key}/registration/users
POST     /api/v1/admin/projects/{project_key}/registration/cdks/{id}/renew
```

项目端接口：

```text
POST /api/v1/projects/{project_key}/registration/activate
POST /api/v1/projects/{project_key}/registration/authorize
POST /api/v1/projects/{project_key}/registration/workspace
```

这三条项目端接口使用以下签名头：

```text
X-Registration-Client-Key: <项目级客户端密钥>
X-Registration-Timestamp: <Unix seconds>
X-Registration-Signature: <HMAC-SHA256 hex>
```

签名原文：

```text
timestamp.METHOD.path.sha256(canonical_json_body)
```

相同客户端密钥只能调用自己的 `project_key`。跨项目调用返回 `registration_client_key_scope_denied`。普通 CDK 跨项目绑定返回 `registration_project_access_denied`；未显式配置全局范围的管理员 CDK 返回 `registration_scope_denied`。

### 全局注册机管理员 CDK

管理员若需要一张 CDK 管理多个注册机项目，必须显式创建：

```json
{
  "role": "admin_cdk",
  "name": "全局注册机维护卡",
  "registration_scope": "global"
}
```

该卡仍使用每个项目各自的客户端密钥与 HMAC，不会把项目客户端密钥变成全局密钥。项目契约中 `authentication.cross_project_access=true` 表示当前 CDK 可跨注册机项目；`project_isolated=true` 始终表示绑定、授权和工作区数据按项目隔离。

## 管理台与卡库

项目卡片提供三项管理入口：

- **查看 CDK**：自动带入项目筛选，卡库只显示该项目的卡；
- **项目概览**：显示该项目的卡状态、活动任务；注册机项目额外显示用户绑定统计；
- **对接信息**：显示项目契约地址和管理员卡库、概览接口。

管理员也可以直接查询：

```text
GET /api/v1/admin/cdks?project_key={project_key}
GET /api/v1/admin/projects/{project_key}/summary
GET /api/v1/admin/projects/{project_key}/integration
```

## 给项目开发者的提示词

将下面内容连同项目源码交给项目开发者或代码助手。将尖括号替换为实际值；不要把任何密钥、CDK、令牌、Cookie、代理或验证码放进 Git。

```text
请把当前项目接入 CDK 管理库，保持现有业务逻辑不变。

项目资料：
- project_key: <项目标识>
- CDK 平台基础地址: <BASE_URL>
- 接入类型: <task_api | cdk_access | registration>
- 项目当前入口: <项目入口>

实现要求：
1. 启动时调用 GET /api/v1/projects/<project_key>/capabilities，使用 Authorization: Bearer <项目 CDK>；只以 `capabilities` 返回的能力决定可调用接口。随后可读取 `/integration` 获取完整契约。
2. 每次实际运行前调用 GET /api/v1/cdk/status?project_key=<project_key>。状态无效、过期、额度不足或并发为 0 时停止，不伪造成功。
3. 如果接入类型是 task_api：读取动态渠道目录、先 preflight，再用 Idempotency-Key 提交任务并轮询；不上传原始支付链接、验证码、Cookie 或会话资料。
4. 如果接入类型是 registration：使用项目级客户端密钥的 HMAC 签名调用 activate、authorize、workspace；仅当项目契约明确返回 `cdk.registration_scope=global` 且 `authentication.cross_project_access=true` 时，才允许同一管理员 CDK 在其他注册机项目激活；本地密码、工作区内容、浏览器会话不得上传。
5. 如果接入类型是 cdk_access：仅实现项目 CDK 输入/本地安全保存、状态校验、失效提示和退出，不自行扣费或创建平台任务。
6. 不得把 CDK、管理员密钥、客户端密钥、访问令牌、Cookie、代理认证、验证码或完整支付链接写入日志、页面、测试夹具或 Git。
7. 增加单元测试：正常授权、项目不匹配、CDK 过期或禁用、网络失败重试、停止后的本地状态恢复。
8. 完成后提供修改文件清单、接口调用说明和测试结果。
```

完整字段定义见 `/api/v1/openapi.yaml`，统一 v1.3.0 对接说明见 `/api/v1/integration-guide/latest` 或 `/api/v1/registration-integration-guide`，动态任务说明见 `/api/v1/integration-guide`，GPTFREE 注册机说明见 `/api/v1/registration-core-guide`，生图注册机说明见 `/api/v1/image-generation-registration-guide`。

注册机项目使用持久账号模型：账号唯一键是 `project_key + username + client_user_ref`，CDK 只是可替换授权。CDK 到期后本地仍可登录并调用 `registration/account/status`，管理员签发新卡后调用 `registration/rebind`；账号、工作区和客户端加密配置不会因换卡丢失。配置更新必须使用 `expected_version`，服务端保留版本历史并拒绝旧版本覆盖。
