mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-15 08:06:21 +00:00
refactor: align backend names
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -125,7 +125,7 @@ async fn ensure_default_admin_exists(
|
||||
### 1. 管理员登录
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8080/admin/login \
|
||||
curl -X POST http://127.0.0.1:8080/api/admin/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"password":"admin"}'
|
||||
```
|
||||
@@ -151,7 +151,7 @@ cpr_admin_session=sess_a27875537483420ab7ba6ce4d1f91b5e; Path=/; HttpOnly; SameS
|
||||
### 2. 导入测试账号
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8080/admin/accounts/import \
|
||||
curl -X POST http://127.0.0.1:8080/api/admin/accounts/import \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Cookie: cpr_admin_session=sess_a27875537483420ab7ba6ce4d1f91b5e" \
|
||||
-d @accounts-export.json
|
||||
@@ -177,7 +177,7 @@ curl -X POST http://127.0.0.1:8080/admin/accounts/import \
|
||||
#### 3.1 创建 API 密钥
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8080/admin/api-keys \
|
||||
curl -X POST http://127.0.0.1:8080/api/admin/api-keys \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Cookie: cpr_admin_session=sess_..." \
|
||||
-d '{"name":"test-key","label":"测试密钥"}'
|
||||
@@ -197,7 +197,7 @@ curl -X POST http://127.0.0.1:8080/admin/api-keys \
|
||||
#### 3.2 刷新模型列表
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8080/admin/refresh-models \
|
||||
curl -X POST http://127.0.0.1:8080/api/admin/refresh-models \
|
||||
-H "Cookie: cpr_admin_session=sess_..."
|
||||
```
|
||||
|
||||
@@ -262,7 +262,7 @@ curl -X POST http://127.0.0.1:8080/v1/chat/completions \
|
||||
由于 `AdminConfig` 添加了新字段,需要修复所有测试文件中的初始化代码。
|
||||
|
||||
**影响的测试文件:**
|
||||
- `tests/admin/*.rs` (6 个文件)
|
||||
- `tests/api/admin/*.rs` (6 个文件)
|
||||
- `tests/codex_serving/*.rs` (2 个文件)
|
||||
- `tests/runtime/startup.rs`
|
||||
- `tests/support/*.rs` (2 个文件)
|
||||
@@ -325,7 +325,7 @@ test result: ok. 49 passed; 0 failed
|
||||
- `tests/**/*.rs` - 修复测试中的 AdminConfig 初始化
|
||||
|
||||
### 不变的模块
|
||||
- `src/admin/auth/service.rs` - 认证逻辑无需变更
|
||||
- `src/api/admin/auth/service.rs` - 认证逻辑无需变更
|
||||
- `src/platform/identity/admin_session.rs` - 密码哈希逻辑无需变更
|
||||
- `src/platform/storage/schema.sql` - 数据库表结构无需变更
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ pub fn capture_set_cookie(&mut self, account_id: &str, raw: &str) {
|
||||
- 添加所有浏览器特征头
|
||||
- 修正 `x-openai-internal-codex-residency` 为 `"us"`
|
||||
|
||||
4. **src/codex/gateway/transport/client.rs**
|
||||
4. **src/codex/gateway/transport/http_client.rs**
|
||||
- 更新导入:`build_codex_headers` → `build_ordered_codex_headers`
|
||||
- 重构 `request_headers()` 使用排序后的头
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
### 2. 核心传输层更新
|
||||
|
||||
#### `src/codex/gateway/transport/client.rs`
|
||||
#### `src/codex/gateway/transport/http_client.rs`
|
||||
- `CodexRequestContext` 添加两个新字段:
|
||||
- `installation_id: Option<&'a str>`
|
||||
- `session_id: Option<&'a str>`
|
||||
@@ -209,10 +209,10 @@ Dispatch Service (src/codex/serving/dispatch/mod.rs)
|
||||
|
||||
### 修改文件 (9)
|
||||
- `src/codex/gateway/mod.rs` (+2 行)
|
||||
- `src/codex/gateway/transport/client.rs` (+4 行)
|
||||
- `src/codex/gateway/transport/http_client.rs` (+4 行)
|
||||
- `src/codex/serving/dispatch/mod.rs` (+15 行)
|
||||
- `src/codex/accounts/service/health.rs` (+2 行)
|
||||
- `src/codex/accounts/models/service.rs` (+2 行)
|
||||
- `src/codex/models/service.rs` (+2 行)
|
||||
- `src/codex/serving/diagnostics.rs` (+2 行)
|
||||
- `Cargo.toml` (+1 行)
|
||||
- `tests/codex_gateway/client.rs` (+2 行)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
Rust 状态:
|
||||
- 到位:`src/codex/gateway/transport/headers.rs` 构造账号、residency、request id、UA、sec-ch、默认 header 和顺序。
|
||||
- 到位:`src/codex/gateway/transport/client.rs` 将 installation/window/turn/parent/subagent 同步到 header 和 `client_metadata`。
|
||||
- 到位:`src/codex/gateway/transport/http_client.rs` 将 installation/window/turn/parent/subagent 同步到 header 和 `client_metadata`。
|
||||
- 到位:`src/codex/gateway/installation.rs` 兼容读取 `~/.codex/installation_id`,否则落库生成。
|
||||
- 到位:`src/runtime/bootstrap.rs` 从数据库加载自动更新指纹,避免实际请求继续使用硬编码默认值。
|
||||
- 边界:Rust 使用 `reqwest + rustls` 传输,未声称复制原版 native transport 的完整 Chrome TLS 指纹。IP 代理/VPN 相关能力不属于移植范围。
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
- 使用 SHA256 哈希生成确定性标识符
|
||||
- 格式:`cp_{hash[..32]}` (conversation) 或 `cw_{hash[..32]}` (window)
|
||||
|
||||
- 更新 `src/codex/gateway/transport/client.rs`
|
||||
- 更新 `src/codex/gateway/transport/http_client.rs`
|
||||
- 在 `CodexRequestContext` 添加 `installation_id` 和 `session_id` 字段
|
||||
- 在 `request_headers()` 方法中添加这两个 header
|
||||
|
||||
@@ -132,10 +132,10 @@ test codex::gateway::installation::tests::test_generate_and_persist ... ok
|
||||
|
||||
### 修改文件
|
||||
1. `src/codex/gateway/mod.rs` - 导出新模块
|
||||
2. `src/codex/gateway/transport/client.rs` - 添加新 header 字段
|
||||
2. `src/codex/gateway/transport/http_client.rs` - 添加新 header 字段
|
||||
3. `src/codex/serving/dispatch/mod.rs` - 集成身份派生逻辑
|
||||
4. `src/codex/accounts/service/health.rs` - 更新 context 构造
|
||||
5. `src/codex/accounts/models/service.rs` - 更新 context 构造
|
||||
5. `src/codex/models/service.rs` - 更新 context 构造
|
||||
6. `src/codex/serving/diagnostics.rs` - 更新 context 构造
|
||||
7. `Cargo.toml` - 添加 `dirs = "5.0.1"` 依赖
|
||||
|
||||
|
||||
+27
-25
@@ -1,10 +1,12 @@
|
||||
# API Contract
|
||||
|
||||
`codex-proxy-rs` exposes two API families.
|
||||
`codex-proxy-rs` exposes two API families. The `/admin/*` path is reserved for
|
||||
the future human Web console; machine-readable management endpoints live under
|
||||
`/api/admin/*`.
|
||||
|
||||
## `/v1/*`
|
||||
|
||||
These endpoints are OpenAI-compatible and are authenticated only by enabled local client API keys created through `/admin/api-keys` and sent as `Authorization: Bearer cpr_...`.
|
||||
These endpoints are OpenAI-compatible and are authenticated only by enabled local client API keys created through `/api/admin/api-keys` and sent as `Authorization: Bearer cpr_...`.
|
||||
Responses include an `X-Request-Id` header for tracing, but the body stays OpenAI-compatible and does not include a custom `requestId` field.
|
||||
|
||||
Error body:
|
||||
@@ -159,14 +161,14 @@ Refresh failures are recorded as non-secret `account.refresh` event logs with th
|
||||
|
||||
`previous_response_id` and explicit WebSocket-only requests are rejected until the WebSocket transport is implemented and verified.
|
||||
|
||||
## `/admin/*`
|
||||
## `/api/admin/*`
|
||||
|
||||
Admin endpoints are authenticated only by HttpOnly admin session cookies.
|
||||
Admin JSON uses lower camelCase field names. Every admin response includes an `X-Request-Id` header, and every JSON body includes `requestId`.
|
||||
|
||||
Use real HTTP status codes and body-level frontend codes together. Do not return HTTP `200` for failed requests. The body `code` exists for frontend branching; the HTTP status remains the transport truth.
|
||||
|
||||
### `GET /admin/diagnostics`
|
||||
### `GET /api/admin/diagnostics`
|
||||
|
||||
Returns the same non-secret runtime diagnostics summary as `/debug/diagnostics`, wrapped in the admin envelope and gated by the admin session cookie.
|
||||
|
||||
@@ -193,7 +195,7 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /admin/login`
|
||||
### `POST /api/admin/login`
|
||||
|
||||
Authenticates only with the configured admin password stored in `admin_users`. Client API keys (`Bearer cpr_...`) are ignored by the admin login flow and cannot create admin sessions.
|
||||
|
||||
@@ -226,7 +228,7 @@ Set-Cookie: cpr_admin_session=...; Path=/; HttpOnly; SameSite=Lax; Max-Age=3600
|
||||
|
||||
Invalid password response uses HTTP `401` and body code `40102`.
|
||||
|
||||
### `GET /admin/settings`
|
||||
### `GET /api/admin/settings`
|
||||
|
||||
Returns the in-scope runtime settings visible to the admin UI. This endpoint uses admin sessions, not client API keys.
|
||||
|
||||
@@ -263,7 +265,7 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `PATCH /admin/settings`
|
||||
### `PATCH /api/admin/settings`
|
||||
|
||||
Updates retained settings and writes them to root `local.yaml` as a config overlay. The route requires the admin session cookie. Client API keys and removed TypeScript-era fields are not accepted.
|
||||
|
||||
@@ -297,7 +299,7 @@ Request:
|
||||
}
|
||||
```
|
||||
|
||||
Success response uses the same `data` shape as `GET /admin/settings`.
|
||||
Success response uses the same `data` shape as `GET /api/admin/settings`.
|
||||
|
||||
Validation:
|
||||
|
||||
@@ -306,7 +308,7 @@ Validation:
|
||||
- Quota warning thresholds must be between `0` and `100`.
|
||||
- Removed settings such as `proxyUrl`, `openaiApiKey`, `ollama`, provider settings, proxy API key settings, and Electron/self-update settings return HTTP `400` with body code `40001`.
|
||||
|
||||
### `GET /admin/logs`
|
||||
### `GET /api/admin/logs`
|
||||
|
||||
Returns cursor-paginated event logs for admin troubleshooting. The list uses the standard admin page envelope and lower camelCase fields.
|
||||
|
||||
@@ -348,7 +350,7 @@ Example item:
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/logs/state`
|
||||
### `GET /api/admin/logs/state`
|
||||
|
||||
Returns the current retained logging configuration plus the number of stored SQLite event logs.
|
||||
|
||||
@@ -368,9 +370,9 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `PATCH /admin/logs/state`
|
||||
### `PATCH /api/admin/logs/state`
|
||||
|
||||
Updates the in-process logging state used by admin log controls. This is runtime-only; persistent configuration changes still go through `PATCH /admin/settings`.
|
||||
Updates the in-process logging state used by admin log controls. This is runtime-only; persistent configuration changes still go through `PATCH /api/admin/settings`.
|
||||
|
||||
Request:
|
||||
|
||||
@@ -382,13 +384,13 @@ Request:
|
||||
}
|
||||
```
|
||||
|
||||
Success response uses the same data shape as `GET /admin/logs/state`.
|
||||
Success response uses the same data shape as `GET /api/admin/logs/state`.
|
||||
|
||||
### `GET /admin/logs/{id}`
|
||||
### `GET /api/admin/logs/{id}`
|
||||
|
||||
Returns a single stored event log by id using the same event shape as list items. Missing ids return HTTP `404` with body code `40401`.
|
||||
|
||||
### `DELETE /admin/logs`
|
||||
### `DELETE /api/admin/logs`
|
||||
|
||||
Clears stored SQLite event logs.
|
||||
|
||||
@@ -405,7 +407,7 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/usage-stats`
|
||||
### `GET /api/admin/usage-stats`
|
||||
|
||||
Returns cursor-paginated account usage counters recorded after `/v1/*` calls. The endpoint never returns account access tokens, refresh tokens, Cookie values, or client API keys.
|
||||
|
||||
@@ -425,7 +427,7 @@ Example item:
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/usage-stats/summary`
|
||||
### `GET /api/admin/usage-stats/summary`
|
||||
|
||||
Returns global usage totals across accounts.
|
||||
|
||||
@@ -446,11 +448,11 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/api-keys`
|
||||
### `GET /api/admin/api-keys`
|
||||
|
||||
Returns local client API keys with cursor pagination. The plaintext key and hash are never returned by list endpoints.
|
||||
|
||||
### `POST /admin/api-keys`
|
||||
### `POST /api/admin/api-keys`
|
||||
|
||||
Creates a local client API key for `/v1/*`. The plaintext value is returned only in this response; store it client-side and use it as `Authorization: Bearer <plaintext>`.
|
||||
|
||||
@@ -481,14 +483,14 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/api-keys/export`
|
||||
### `GET /api/admin/api-keys/export`
|
||||
|
||||
Exports Rust-local client API key metadata for backup or migration. The export never includes plaintext keys, key hashes, or the raw auth pepper. Because `cpr_` keys are stored only as peppered HMAC hashes, imports rotate keys instead of preserving the original plaintext.
|
||||
|
||||
Optional query:
|
||||
|
||||
```http
|
||||
GET /admin/api-keys/export?ids=key_01,key_02
|
||||
GET /api/admin/api-keys/export?ids=key_01,key_02
|
||||
```
|
||||
|
||||
Success response:
|
||||
@@ -516,7 +518,7 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /admin/api-keys/import`
|
||||
### `POST /api/admin/api-keys/import`
|
||||
|
||||
Imports Rust-local client API key metadata exported by this service. Import creates new local `cpr_` keys using the target instance's pepper and returns the new plaintext values only in this response. Clients must replace the old keys with these rotated plaintext values.
|
||||
|
||||
@@ -567,11 +569,11 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/accounts`
|
||||
### `GET /api/admin/accounts`
|
||||
|
||||
Returns stored Codex accounts with cursor pagination. Access tokens and refresh tokens are never decrypted or returned.
|
||||
|
||||
### `GET /admin/accounts/quota-warnings`
|
||||
### `GET /api/admin/accounts/quota-warnings`
|
||||
|
||||
Returns active quota warnings computed from cached account quota snapshots in SQLite. The route requires an admin session cookie and does not call the upstream Codex backend.
|
||||
|
||||
@@ -598,7 +600,7 @@ Success response:
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /admin/accounts/import`
|
||||
### `POST /api/admin/accounts/import`
|
||||
|
||||
Imports accounts into encrypted SQLite storage. The request body uses the Rust import format, which accepts the exported account object fields needed by this service and ignores unrelated fields.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
src/
|
||||
├── codex/ # OpenAI/Codex 对接层(核心业务逻辑)
|
||||
├── service/ # 业务服务层(Chat, Responses, Diagnostics)
|
||||
├── http/ # HTTP 路由层(/v1/* 和 /admin/*)
|
||||
├── http/ # HTTP 路由层(/v1/* 和 /api/admin/*)
|
||||
├── auth/ # 认证模块(API keys, sessions)
|
||||
├── scheduler/ # 后台调度器(refresh, quota, model)
|
||||
├── storage/ # 数据持久化(SQLite)
|
||||
@@ -30,7 +30,7 @@ src/
|
||||
|
||||
**三层认证边界设计:**
|
||||
```
|
||||
Admin Auth (密码 + Session) → /admin/*
|
||||
Admin Auth (密码 + Session) → /api/admin/*
|
||||
Client API Keys (cpr_ 前缀) → /v1/*
|
||||
Upstream Tokens (内部加密) → ChatGPT Backend
|
||||
```
|
||||
@@ -151,7 +151,7 @@ src/codex/accounts/service/
|
||||
├── cookies.rs # Cookie 操作
|
||||
├── health.rs # 健康检查
|
||||
├── import.rs # 导入逻辑
|
||||
├── mutation.rs # CRUD 操作
|
||||
├── lifecycle.rs # CRUD 操作
|
||||
├── quota.rs # 配额管理
|
||||
├── refresh.rs # 令牌刷新
|
||||
└── runtime_pool.rs # 运行时池同步
|
||||
@@ -224,7 +224,7 @@ pub enum AccountServiceError {
|
||||
### 5. 🟢 配置热重载未完全实现
|
||||
|
||||
**当前状态:**
|
||||
- `/admin/settings PATCH` 写入 `local.yaml`
|
||||
- `/api/admin/settings PATCH` 写入 `local.yaml`
|
||||
- 更新 `AppState` 中的 config
|
||||
- ⚠️ 但已构造的服务(如调度器)仍使用旧配置
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ src/
|
||||
│ │ │ ├── cookies.rs
|
||||
│ │ │ ├── health.rs
|
||||
│ │ │ ├── import.rs # 手动/CLI/OAuth 导入
|
||||
│ │ │ ├── mutation.rs
|
||||
│ │ │ ├── lifecycle.rs
|
||||
│ │ │ ├── quota.rs
|
||||
│ │ │ ├── refresh.rs
|
||||
│ │ │ └── runtime_pool.rs
|
||||
@@ -136,18 +136,18 @@ src/
|
||||
│
|
||||
├── admin/ # 🔵 后台管理域(控制面)
|
||||
│ ├── mod.rs
|
||||
│ ├── http/ # /admin/* ← http/admin/
|
||||
│ │ ├── mod.rs # ← http/admin/mod.rs
|
||||
│ │ ├── router.rs # ← http/admin/router.rs
|
||||
│ │ ├── response.rs # ← http/admin/response.rs(AdminError envelope)
|
||||
│ │ ├── auth.rs # ← http/admin/auth.rs(login/status/logout)
|
||||
│ │ ├── api_keys.rs # ← http/admin/api_keys.rs
|
||||
│ │ ├── logs.rs # ← http/admin/logs.rs
|
||||
│ │ ├── models.rs # ← http/admin/models.rs(refresh-models)
|
||||
│ │ ├── settings.rs # ← http/admin/settings.rs
|
||||
│ │ ├── usage.rs # ← http/admin/usage.rs
|
||||
│ │ ├── diagnostics.rs # ← http/admin/diagnostics.rs
|
||||
│ │ └── accounts/ # ⭐ 拆分 http/admin/accounts.rs(1697 行)
|
||||
│ ├── http/ # /api/admin/* ← http/api/admin/
|
||||
│ │ ├── mod.rs # ← http/api/admin/mod.rs
|
||||
│ │ ├── router.rs # ← http/api/admin/router.rs
|
||||
│ │ ├── response.rs # ← http/api/admin/response.rs(AdminError envelope)
|
||||
│ │ ├── auth.rs # ← http/api/admin/auth.rs(login/status/logout)
|
||||
│ │ ├── api_keys.rs # ← http/api/admin/api_keys.rs
|
||||
│ │ ├── logs.rs # ← http/api/admin/logs.rs
|
||||
│ │ ├── models.rs # ← http/api/admin/models.rs(refresh-models)
|
||||
│ │ ├── settings.rs # ← http/api/admin/settings.rs
|
||||
│ │ ├── usage.rs # ← http/api/admin/usage.rs
|
||||
│ │ ├── diagnostics.rs # ← http/api/admin/diagnostics.rs
|
||||
│ │ └── accounts/ # ⭐ 拆分 http/api/admin/accounts.rs(1697 行)
|
||||
│ │ ├── mod.rs # 路由注册 + 共享 DTO
|
||||
│ │ ├── list.rs # accounts / export_accounts
|
||||
│ │ ├── create.rs # create_account / import_accounts / import_cli_auth
|
||||
@@ -156,7 +156,7 @@ src/
|
||||
│ │ ├── health.rs # health_check_accounts
|
||||
│ │ ├── quota.rs # quota_warnings / account_quota
|
||||
│ │ ├── cookies.rs # get / set / delete cookies
|
||||
│ │ └── oauth.rs # ← http/admin/auth.rs 中 OAuth 流程
|
||||
│ │ └── oauth.rs # ← http/api/admin/auth.rs 中 OAuth 流程
|
||||
│ │ # device-login / poll / login-start / code-relay / callback
|
||||
│ ├── auth/ # 管理员认证 + key 管理策略
|
||||
│ │ ├── mod.rs
|
||||
@@ -200,7 +200,7 @@ src/
|
||||
|
||||
大部分是目录搬迁,但有 3 个文件需要真正动刀:
|
||||
|
||||
1. **`http/admin/accounts.rs`(1697 行)→ `admin/http/accounts/` 9 文件**。按上面 16 个 handler 归类(list/create/mutate/delete/health/quota/cookies/oauth + mod 路由)。
|
||||
1. **`http/api/admin/accounts.rs`(1697 行)→ `admin/http/accounts/` 9 文件**。按上面 16 个 handler 归类(list/create/mutate/delete/health/quota/cookies/oauth + mod 路由)。
|
||||
|
||||
2. **`service/admin_auth.rs` 拆责**。密码登录/会话校验留 `admin/auth/service.rs`;OAuth token 交换 + 账号导入的编排移到 `admin/http/accounts/oauth.rs`,由它调用 `codex::gateway::oauth`(换 token)+ `codex::accounts::service::import`(落库)。
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ The cleanup started from these pressure points:
|
||||
| `tests/admin_accounts_route_test.rs` | 2588 | Admin account scenarios are too large to scan or move safely. |
|
||||
| `tests/v1_upstream_route_test.rs` | 2115 | Responses HTTP SSE, WebSocket, fallback, error mapping, usage, and logging side effects are mixed. |
|
||||
| `tests/chat_completions_route_test.rs` | 710 | Manageable, but should eventually align with the v1 split. |
|
||||
| `tests/admin_api_keys_route_test.rs` | 659 | Manageable, but can share common admin test setup. |
|
||||
| `tests/admin_client_keys_route_test.rs` | 659 | Manageable, but can share common admin test setup. |
|
||||
|
||||
The main coupling pattern is:
|
||||
|
||||
@@ -51,8 +51,8 @@ touch fallback, account state, usage logs, and protocol conversion at the same t
|
||||
|
||||
As of this cleanup pass:
|
||||
|
||||
- `src/http/admin/mod.rs` is the admin module entry, backed by resource-specific files
|
||||
under `src/http/admin/` and a dedicated admin router.
|
||||
- `src/http/api/admin/mod.rs` is the admin module entry, backed by resource-specific files
|
||||
under `src/http/api/admin/` and a dedicated admin router.
|
||||
- `src/http/v1/mod.rs` is the v1 module entry, backed by thin route handlers for auth,
|
||||
chat, responses, models, errors, and router mounting under `src/http/v1/`.
|
||||
- `src/service/` now contains backend-facing HTTP use-case services:
|
||||
@@ -78,7 +78,7 @@ As of this cleanup pass:
|
||||
- admin model catalog refresh orchestration lives in `codex::models::service::ModelService`.
|
||||
- `tests/common/` now contains shared integration-test helpers, including generic
|
||||
response/session helpers plus admin account and v1 upstream route fixtures.
|
||||
- `tests/admin_accounts_route_test.rs` has been split into list, mutation,
|
||||
- `tests/admin_accounts_route_test.rs` has been split into list, lifecycle,
|
||||
import/export, OAuth/auth, and cookies/quota/refresh/health scenario files.
|
||||
- `tests/v1_upstream_route_test.rs` has been split into Responses HTTP/SSE,
|
||||
Responses WebSocket, upstream fallback/refresh, and upstream error scenario files.
|
||||
@@ -100,8 +100,8 @@ As of this cleanup pass:
|
||||
- `codex/upstream/dispatch.rs`, `fallback.rs`, `refresh.rs`, `stream.rs`, and
|
||||
`usage.rs` now own the obvious helper groups for dispatch response helpers, retry
|
||||
classification, token refresh retry, SSE response collection, and usage recording.
|
||||
- `codex/accounts/service/import.rs`, `mutation.rs`, `cookies.rs`, `quota.rs`, `health.rs`,
|
||||
`refresh.rs`, and `runtime_pool.rs` now own account import, mutation, cookie, quota,
|
||||
- `codex/accounts/service/import.rs`, `lifecycle.rs`, `cookies.rs`, `quota.rs`, `health.rs`,
|
||||
`refresh.rs`, and `runtime_pool.rs` now own account import, lifecycle, cookie, quota,
|
||||
health-check, single-account refresh, and runtime-pool workflows instead of leaving
|
||||
them in `service/account/mod.rs`.
|
||||
- `ChatService` and `ResponsesService` own a cloned `CodexUpstreamService` instance injected from
|
||||
@@ -128,7 +128,7 @@ As of this cleanup pass:
|
||||
moved out of route tests into `tests/fixtures/*.sse`.
|
||||
- v1 Responses WebSocket mocked response payloads have been moved into
|
||||
`tests/fixtures/*.json`.
|
||||
- `http/admin/response.rs` now provides `AdminError`, and the admin route modules use
|
||||
- `http/api/admin/response.rs` now provides `AdminError`, and the admin route modules use
|
||||
`Result<impl IntoResponse, AdminError>` for standard admin-envelope failures.
|
||||
- admin auth handlers now propagate session, login, OAuth, and PKCE failures through
|
||||
`AdminError`; success paths that must set cookies or redirect still build explicit
|
||||
@@ -210,7 +210,7 @@ and the Rust best-practice rules below.
|
||||
### Async, Sharing, And Trait Objects
|
||||
|
||||
- Shared runtime state should use `Arc` and explicit synchronization primitives such as
|
||||
`tokio::sync::Mutex` only where mutation is required.
|
||||
`tokio::sync::Mutex` only where lifecycle is required.
|
||||
- Keep lock scopes short. Do not hold account-pool or session locks while performing
|
||||
network requests, database calls, or expensive serialization.
|
||||
- Prefer generics/static dispatch for local helper abstractions. Use `Arc<dyn Trait>`
|
||||
@@ -336,7 +336,7 @@ src/
|
||||
service/
|
||||
mod.rs
|
||||
import.rs
|
||||
mutation.rs
|
||||
lifecycle.rs
|
||||
cookies.rs
|
||||
quota.rs
|
||||
health.rs
|
||||
@@ -505,7 +505,7 @@ This phase should be mostly mechanical:
|
||||
Create:
|
||||
|
||||
```text
|
||||
src/http/admin/
|
||||
src/http/api/admin/
|
||||
mod.rs
|
||||
router.rs
|
||||
response.rs
|
||||
@@ -526,10 +526,10 @@ Suggested ownership:
|
||||
| `auth.rs` | `login`, `auth_status`, `auth_logout`, OAuth PKCE/device routes, admin session cookie helpers. |
|
||||
| `accounts.rs` | account list/create/import/export/delete/status/label, health check, refresh, reset usage, quota, cookies, account import parsing helpers. |
|
||||
| `api_keys.rs` | local client key list/create/import/export/delete/status/label/batch helpers. |
|
||||
| `logs.rs` | `/admin/logs` handler and log DTOs. |
|
||||
| `models.rs` | `/admin/refresh-models` handler and model refresh DTOs. |
|
||||
| `settings.rs` | `/admin/settings` handler and settings DTOs. |
|
||||
| `usage.rs` | `/admin/usage-stats` and `/admin/usage-stats/summary`. |
|
||||
| `logs.rs` | `/api/admin/logs` handler and log DTOs. |
|
||||
| `models.rs` | `/api/admin/refresh-models` handler and model refresh DTOs. |
|
||||
| `settings.rs` | `/api/admin/settings` handler and settings DTOs. |
|
||||
| `usage.rs` | `/api/admin/usage-stats` and `/api/admin/usage-stats/summary`. |
|
||||
| `router.rs` | admin route mounting only. |
|
||||
|
||||
Keep cross-resource helpers private when possible. If a helper is needed by multiple
|
||||
@@ -540,10 +540,10 @@ The admin router should own admin paths:
|
||||
```rust
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/admin/login", post(auth::login))
|
||||
.route("/admin/auth/status", get(auth::auth_status))
|
||||
.route("/admin/accounts", get(accounts::accounts).post(accounts::create_account))
|
||||
.route("/admin/api-keys", get(api_keys::api_keys).post(api_keys::create_api_key))
|
||||
.route("/api/admin/login", post(auth::login))
|
||||
.route("/api/admin/auth/status", get(auth::auth_status))
|
||||
.route("/api/admin/accounts", get(accounts::accounts).post(accounts::create_account))
|
||||
.route("/api/admin/api-keys", get(api_keys::api_keys).post(api_keys::create_api_key))
|
||||
}
|
||||
```
|
||||
|
||||
@@ -600,7 +600,7 @@ cargo test --test admin_accounts_mutation_test
|
||||
cargo test --test admin_accounts_import_export_test
|
||||
cargo test --test admin_accounts_oauth_test
|
||||
cargo test --test admin_accounts_cookies_quota_test
|
||||
cargo test --test admin_api_keys_route_test
|
||||
cargo test --test admin_client_keys_route_test
|
||||
cargo test --test v1_responses_http_sse_test
|
||||
cargo test --test v1_responses_websocket_test
|
||||
cargo test --test v1_upstream_fallback_test
|
||||
@@ -758,7 +758,7 @@ Targets:
|
||||
```text
|
||||
src/codex/protocol/error.rs
|
||||
src/http/response.rs
|
||||
src/http/admin/response.rs
|
||||
src/http/api/admin/response.rs
|
||||
src/http/v1/errors.rs
|
||||
```
|
||||
|
||||
@@ -990,7 +990,7 @@ cargo test --test v1_upstream_errors_test
|
||||
|
||||
### Step 4: Split Former `src/http/admin.rs`
|
||||
|
||||
Move admin code into `src/http/admin/*.rs`, with `src/http/admin/mod.rs` as the module
|
||||
Move admin code into `src/http/api/admin/*.rs`, with `src/http/api/admin/mod.rs` as the module
|
||||
entry. Preserve behavior.
|
||||
|
||||
Verification:
|
||||
@@ -1002,7 +1002,7 @@ cargo test --test admin_accounts_mutation_test
|
||||
cargo test --test admin_accounts_import_export_test
|
||||
cargo test --test admin_accounts_oauth_test
|
||||
cargo test --test admin_accounts_cookies_quota_test
|
||||
cargo test --test admin_api_keys_route_test
|
||||
cargo test --test admin_client_keys_route_test
|
||||
cargo test --test admin_logs_route_test
|
||||
cargo test --test admin_models_route_test
|
||||
cargo test --test admin_settings_route_test
|
||||
@@ -1090,7 +1090,7 @@ cargo test --test admin_accounts_mutation_test
|
||||
cargo test --test admin_accounts_import_export_test
|
||||
cargo test --test admin_accounts_oauth_test
|
||||
cargo test --test admin_accounts_cookies_quota_test
|
||||
cargo test --test admin_api_keys_route_test
|
||||
cargo test --test admin_client_keys_route_test
|
||||
cargo test --test v1_responses_http_sse_test
|
||||
cargo test --test v1_responses_websocket_test
|
||||
cargo test --test v1_upstream_fallback_test
|
||||
|
||||
@@ -0,0 +1,468 @@
|
||||
# Backend Naming Audit
|
||||
|
||||
## Verdict
|
||||
|
||||
当前后端命名可以作为第一版完整架构定稿。主边界已经清楚:`runtime` 负责装配,`web` 负责未来 Web 控制台承载,`admin` 负责管理域,`codex` 负责 Codex 业务内核,`platform` 负责跨领域基础设施。
|
||||
|
||||
命名的艺术不在于词汇华丽,而在于每个名字都能回答三个问题:
|
||||
|
||||
- 这个目录属于哪个领域。
|
||||
- 这个文件对外暴露什么责任。
|
||||
- 这个名字是否会让后来的人误以为它还承担了别的职责。
|
||||
|
||||
本轮审计结论:源码目录已经达到“可长期演进”的层级。剩余问题主要是少数兼容性术语和偏大的聚合文件,不影响当前架构定稿。
|
||||
|
||||
## Naming Principles
|
||||
|
||||
- 路由表面用 `api`、`http`、`web` 表达协议和承载面。
|
||||
- 业务能力用领域名表达,例如 `accounts`、`models`、`events`、`gateway`。
|
||||
- 基础设施只放在 `platform`,避免业务目录承担系统能力。
|
||||
- 测试目录跟随生产目录命名,测试文件表达场景而不是实现细节。
|
||||
- 对外兼容词可以保留在 route 和 DTO 中,内部模块优先使用更准确的领域词。
|
||||
|
||||
## Complete Architecture Tree
|
||||
|
||||
以下目录排除了生成物和本地状态:`.git`、`target`、`data`、`logs`、`designs`。
|
||||
|
||||
```text
|
||||
.
|
||||
├── docs
|
||||
│ ├── superpowers
|
||||
│ │ ├── plans
|
||||
│ │ │ ├── 2026-06-11-codex-proxy-rs.md
|
||||
│ │ │ ├── 2026-06-12-openai-gpt-codex-parity.md
|
||||
│ │ │ ├── 2026-06-13-utils-module-migration.md
|
||||
│ │ │ ├── 2026-06-14-backend-naming-architecture.md
|
||||
│ │ │ └── 2026-06-14-logging-refactor.md
|
||||
│ │ └── specs
|
||||
│ │ ├── 2026-06-12-openai-gpt-codex-parity-design.md
|
||||
│ │ ├── 2026-06-13-architecture-refactor-design.md
|
||||
│ │ ├── 2026-06-14-backend-naming-architecture-design.md
|
||||
│ │ └── 2026-06-14-logging-refactor-design.md
|
||||
│ ├── ADMIN_INITIALIZATION_FIX.md
|
||||
│ ├── FINGERPRINT_AUTO_UPDATE.md
|
||||
│ ├── FINGERPRINT_FIX.md
|
||||
│ ├── FINGERPRINT_PROPAGATION_FIX.md
|
||||
│ ├── FINGERPRINT_UPDATE_TEST_REPORT.md
|
||||
│ ├── IMPLEMENTATION_COMPARISON.md
|
||||
│ ├── IMPLEMENTATION_COMPLETE.md
|
||||
│ ├── OPENAI_CODEX_PARITY_AUDIT.md
|
||||
│ ├── OPENAI_REQUEST_ALIGNMENT.md
|
||||
│ ├── RELIABILITY_ENHANCEMENTS.md
|
||||
│ ├── RESPONSE_CHAIN_ALIGNMENT.md
|
||||
│ ├── api.md
|
||||
│ ├── architecture-audit.md
|
||||
│ ├── architecture-capability-plan.md
|
||||
│ ├── architecture-reorganization.md
|
||||
│ ├── backend-naming-audit.md
|
||||
│ ├── code-quality-audit.md
|
||||
│ ├── database-storage-audit.md
|
||||
│ ├── dependency-policy.md
|
||||
│ ├── implementation-status.md
|
||||
│ ├── optimization-roadmap.md
|
||||
│ ├── rust-community-review.md
|
||||
│ ├── scheduler-completion-report.md
|
||||
│ ├── scheduler-implementation.md
|
||||
│ ├── scheduler-usage.md
|
||||
│ └── status-codes.md
|
||||
├── src
|
||||
│ ├── admin
|
||||
│ │ ├── api
|
||||
│ │ │ ├── accounts
|
||||
│ │ │ │ ├── cookies.rs
|
||||
│ │ │ │ ├── create.rs
|
||||
│ │ │ │ ├── delete.rs
|
||||
│ │ │ │ ├── export.rs
|
||||
│ │ │ │ ├── health.rs
|
||||
│ │ │ │ ├── import.rs
|
||||
│ │ │ │ ├── lifecycle.rs
|
||||
│ │ │ │ ├── list.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── oauth.rs
|
||||
│ │ │ │ └── quota.rs
|
||||
│ │ │ ├── client_keys
|
||||
│ │ │ │ ├── create.rs
|
||||
│ │ │ │ ├── export.rs
|
||||
│ │ │ │ ├── import.rs
|
||||
│ │ │ │ ├── lifecycle.rs
|
||||
│ │ │ │ ├── list.rs
|
||||
│ │ │ │ └── mod.rs
|
||||
│ │ │ ├── logs
|
||||
│ │ │ │ ├── detail.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── query.rs
|
||||
│ │ │ │ └── state.rs
|
||||
│ │ │ ├── diagnostics.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── models.rs
|
||||
│ │ │ ├── response.rs
|
||||
│ │ │ ├── router.rs
|
||||
│ │ │ ├── session.rs
|
||||
│ │ │ ├── settings.rs
|
||||
│ │ │ └── usage.rs
|
||||
│ │ ├── client_keys
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── service.rs
|
||||
│ │ ├── session
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── repository.rs
|
||||
│ │ │ └── service.rs
|
||||
│ │ ├── tasks
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── session_cleanup.rs
|
||||
│ │ ├── mod.rs
|
||||
│ │ └── settings.rs
|
||||
│ ├── codex
|
||||
│ │ ├── accounts
|
||||
│ │ │ ├── cookies
|
||||
│ │ │ │ ├── jar.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ └── repository.rs
|
||||
│ │ │ ├── repository
|
||||
│ │ │ │ ├── accounts.rs
|
||||
│ │ │ │ ├── leases.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── quotas.rs
|
||||
│ │ │ │ ├── tokens.rs
|
||||
│ │ │ │ └── usage.rs
|
||||
│ │ │ ├── service
|
||||
│ │ │ │ ├── cookies.rs
|
||||
│ │ │ │ ├── health.rs
|
||||
│ │ │ │ ├── import.rs
|
||||
│ │ │ │ ├── lifecycle.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── pool_sync.rs
|
||||
│ │ │ │ ├── quota.rs
|
||||
│ │ │ │ └── refresh.rs
|
||||
│ │ │ ├── cloudflare_challenge.rs
|
||||
│ │ │ ├── jwt.rs
|
||||
│ │ │ ├── lifecycle.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── model.rs
|
||||
│ │ │ ├── pool.rs
|
||||
│ │ │ └── usage_snapshots.rs
|
||||
│ │ ├── events
|
||||
│ │ │ ├── event.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── repository.rs
|
||||
│ │ │ └── service.rs
|
||||
│ │ ├── gateway
|
||||
│ │ │ ├── fingerprint
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── model.rs
|
||||
│ │ │ │ ├── repository.rs
|
||||
│ │ │ │ ├── update_checker.rs
|
||||
│ │ │ │ └── updater.rs
|
||||
│ │ │ ├── oauth
|
||||
│ │ │ │ ├── client.rs
|
||||
│ │ │ │ ├── codex_cli.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── refresh.rs
|
||||
│ │ │ │ └── token.rs
|
||||
│ │ │ ├── protocol
|
||||
│ │ │ │ ├── codex_to_openai.rs
|
||||
│ │ │ │ ├── error.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── openai_to_codex.rs
|
||||
│ │ │ │ └── schema.rs
|
||||
│ │ │ ├── transport
|
||||
│ │ │ │ ├── websocket
|
||||
│ │ │ │ │ ├── codec.rs
|
||||
│ │ │ │ │ ├── mod.rs
|
||||
│ │ │ │ │ └── pool.rs
|
||||
│ │ │ │ ├── headers.rs
|
||||
│ │ │ │ ├── http_client.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── rate_limits.rs
|
||||
│ │ │ │ ├── sse.rs
|
||||
│ │ │ │ ├── types.rs
|
||||
│ │ │ │ └── usage_events.rs
|
||||
│ │ │ ├── conversation_identity.rs
|
||||
│ │ │ ├── installation_id.rs
|
||||
│ │ │ └── mod.rs
|
||||
│ │ ├── models
|
||||
│ │ │ ├── catalog.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── repository.rs
|
||||
│ │ │ └── service.rs
|
||||
│ │ ├── serving
|
||||
│ │ │ ├── dispatch
|
||||
│ │ │ │ ├── account_refresh.rs
|
||||
│ │ │ │ ├── affinity.rs
|
||||
│ │ │ │ ├── fallback.rs
|
||||
│ │ │ │ ├── limits.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── routing.rs
|
||||
│ │ │ │ ├── stream.rs
|
||||
│ │ │ │ ├── stream_audit.rs
|
||||
│ │ │ │ └── usage.rs
|
||||
│ │ │ ├── http
|
||||
│ │ │ │ ├── auth.rs
|
||||
│ │ │ │ ├── chat.rs
|
||||
│ │ │ │ ├── diagnostics.rs
|
||||
│ │ │ │ ├── errors.rs
|
||||
│ │ │ │ ├── mod.rs
|
||||
│ │ │ │ ├── models.rs
|
||||
│ │ │ │ ├── responses.rs
|
||||
│ │ │ │ └── router.rs
|
||||
│ │ │ ├── chat.rs
|
||||
│ │ │ ├── diagnostics.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── responses.rs
|
||||
│ │ ├── tasks
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── model_refresh.rs
|
||||
│ │ │ ├── quota_refresh.rs
|
||||
│ │ │ └── token_refresh.rs
|
||||
│ │ ├── usage
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── service.rs
|
||||
│ │ └── mod.rs
|
||||
│ ├── config
|
||||
│ │ ├── loader.rs
|
||||
│ │ ├── mod.rs
|
||||
│ │ └── types.rs
|
||||
│ ├── platform
|
||||
│ │ ├── crypto
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── secret_box.rs
|
||||
│ │ ├── http
|
||||
│ │ │ ├── auth.rs
|
||||
│ │ │ ├── health.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── request_id.rs
|
||||
│ │ ├── identity
|
||||
│ │ │ ├── admin_session.rs
|
||||
│ │ │ ├── client_key.rs
|
||||
│ │ │ ├── client_key_repository.rs
|
||||
│ │ │ ├── error.rs
|
||||
│ │ │ └── mod.rs
|
||||
│ │ ├── logging
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── rotation.rs
|
||||
│ │ ├── storage
|
||||
│ │ │ ├── db.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ ├── paths.rs
|
||||
│ │ │ └── schema.sql
|
||||
│ │ └── mod.rs
|
||||
│ ├── runtime
|
||||
│ │ ├── tasks
|
||||
│ │ │ ├── coordinator.rs
|
||||
│ │ │ ├── mod.rs
|
||||
│ │ │ └── types.rs
|
||||
│ │ ├── bootstrap.rs
|
||||
│ │ ├── mod.rs
|
||||
│ │ ├── router.rs
|
||||
│ │ └── state.rs
|
||||
│ ├── utils
|
||||
│ │ ├── json.rs
|
||||
│ │ ├── mod.rs
|
||||
│ │ └── pagination.rs
|
||||
│ ├── web
|
||||
│ │ ├── assets.rs
|
||||
│ │ ├── mod.rs
|
||||
│ │ ├── router.rs
|
||||
│ │ ├── security.rs
|
||||
│ │ └── shell.rs
|
||||
│ ├── lib.rs
|
||||
│ └── main.rs
|
||||
├── tests
|
||||
│ ├── admin
|
||||
│ │ ├── accounts
|
||||
│ │ │ ├── cookies_quota.rs
|
||||
│ │ │ ├── import_export.rs
|
||||
│ │ │ ├── lifecycle.rs
|
||||
│ │ │ ├── list.rs
|
||||
│ │ │ └── oauth.rs
|
||||
│ │ ├── api_contract.rs
|
||||
│ │ ├── client_keys_route.rs
|
||||
│ │ ├── logs_route.rs
|
||||
│ │ ├── models_route.rs
|
||||
│ │ ├── session.rs
|
||||
│ │ ├── session_login_route.rs
|
||||
│ │ ├── session_repository.rs
|
||||
│ │ ├── settings_route.rs
|
||||
│ │ └── usage_stats_route.rs
|
||||
│ ├── architecture
|
||||
│ │ ├── accounts_boundary.rs
|
||||
│ │ ├── admin_accounts_split.rs
|
||||
│ │ ├── admin_boundary.rs
|
||||
│ │ ├── codex_activity_boundary.rs
|
||||
│ │ ├── gateway_boundary.rs
|
||||
│ │ ├── platform_boundary.rs
|
||||
│ │ ├── runtime_tasks_boundary.rs
|
||||
│ │ └── serving_boundary.rs
|
||||
│ ├── codex_accounts
|
||||
│ │ ├── cookie_store.rs
|
||||
│ │ ├── pool_scheduling.rs
|
||||
│ │ ├── refresh.rs
|
||||
│ │ ├── refresh_scheduler.rs
|
||||
│ │ ├── repository.rs
|
||||
│ │ └── service_refresh.rs
|
||||
│ ├── codex_events
|
||||
│ │ └── logs_pagination.rs
|
||||
│ ├── codex_gateway
|
||||
│ │ ├── websocket
|
||||
│ │ │ └── pool.rs
|
||||
│ │ ├── cli_auth_import.rs
|
||||
│ │ ├── fingerprint_update.rs
|
||||
│ │ ├── headers.rs
|
||||
│ │ ├── http_client.rs
|
||||
│ │ ├── oauth_refresh.rs
|
||||
│ │ ├── usage_events.rs
|
||||
│ │ └── websocket.rs
|
||||
│ ├── codex_models
|
||||
│ │ └── catalog.rs
|
||||
│ ├── codex_serving
|
||||
│ │ ├── chat_completions.rs
|
||||
│ │ ├── diagnostics_route.rs
|
||||
│ │ ├── responses_http_sse.rs
|
||||
│ │ ├── responses_websocket.rs
|
||||
│ │ ├── routes_chat.rs
|
||||
│ │ ├── routes_responses.rs
|
||||
│ │ ├── upstream_errors.rs
|
||||
│ │ └── upstream_fallback.rs
|
||||
│ ├── fixtures
|
||||
│ │ ├── chat
|
||||
│ │ │ ├── non_stream_text.sse
|
||||
│ │ │ ├── parallel_tools_success.sse
|
||||
│ │ │ ├── retry_after_success.sse
|
||||
│ │ │ ├── stream_text.sse
|
||||
│ │ │ ├── tool_reasoning_complete.sse
|
||||
│ │ │ └── tool_stream.sse
|
||||
│ │ └── responses
|
||||
│ │ ├── http_sse
|
||||
│ │ │ ├── after_402.sse
|
||||
│ │ │ ├── after_403.sse
|
||||
│ │ │ ├── after_429.sse
|
||||
│ │ │ ├── after_cloudflare_403.sse
|
||||
│ │ │ ├── after_refresh.sse
|
||||
│ │ │ ├── completed_fields.sse
|
||||
│ │ │ ├── completed_reasoning_include.sse
|
||||
│ │ │ ├── completed_usage.sse
|
||||
│ │ │ ├── default_stream.sse
|
||||
│ │ │ ├── done_item_completed.sse
|
||||
│ │ │ ├── error_event.sse
|
||||
│ │ │ ├── failed_event.sse
|
||||
│ │ │ ├── stream_after_429.sse
|
||||
│ │ │ ├── stream_after_refresh.sse
|
||||
│ │ │ ├── stream_error_event.sse
|
||||
│ │ │ ├── stream_failed_event.sse
|
||||
│ │ │ ├── stream_usage.sse
|
||||
│ │ │ └── text_deltas_completed.sse
|
||||
│ │ └── websocket
|
||||
│ │ ├── completed.json
|
||||
│ │ ├── first_account_limited.json
|
||||
│ │ ├── history_rate_limited.json
|
||||
│ │ ├── rate_limited.json
|
||||
│ │ ├── second_account_limited.json
|
||||
│ │ └── token_revoked.json
|
||||
│ ├── platform
|
||||
│ │ ├── client_key_auth.rs
|
||||
│ │ ├── crypto.rs
|
||||
│ │ ├── http_auth.rs
|
||||
│ │ ├── log_rotation.rs
|
||||
│ │ └── storage_schema.rs
|
||||
│ ├── runtime
|
||||
│ │ ├── http_trace.rs
|
||||
│ │ └── startup.rs
|
||||
│ ├── support
|
||||
│ │ ├── admin_accounts.rs
|
||||
│ │ ├── mod.rs
|
||||
│ │ └── upstream.rs
|
||||
│ ├── admin.rs
|
||||
│ ├── architecture.rs
|
||||
│ ├── codex_accounts.rs
|
||||
│ ├── codex_events.rs
|
||||
│ ├── codex_gateway.rs
|
||||
│ ├── codex_models.rs
|
||||
│ ├── codex_serving.rs
|
||||
│ ├── config.rs
|
||||
│ ├── platform.rs
|
||||
│ └── runtime.rs
|
||||
├── .gitignore
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
├── Dockerfile
|
||||
├── README.md
|
||||
├── config.yaml
|
||||
├── docker-compose.yml
|
||||
└── rust-toolchain.toml
|
||||
```
|
||||
|
||||
## Domain Audit
|
||||
|
||||
| Area | Verdict | Notes |
|
||||
| --- | --- | --- |
|
||||
| `src/runtime` | Good | `bootstrap`、`router`、`state`、`tasks` 表达装配层职责,适合单 crate 起步阶段。 |
|
||||
| `src/web` | Good | 只作为未来 Admin Web 控制台的后端挂载面,没有前端历史包袱。 |
|
||||
| `src/admin/api` | Good | 管理 JSON API 从 `http` 收束为 `api`,比协议名更能表达契约层。 |
|
||||
| `src/admin/session` | Good | 管理员登录态与 `client_keys` 拆开,避免 `auth` 泛化。 |
|
||||
| `src/admin/client_keys` | Good | 内部语义是本地客户端凭据,不是上游 provider key。 |
|
||||
| `src/codex/accounts` | Good | 账号、cookies、仓储、服务、调度池都在账号域内。 |
|
||||
| `src/codex/models` | Good | model catalog 从账号域剥离,边界正确。 |
|
||||
| `src/codex/events` | Good | 业务事件从进程日志中独立出来,命名比 `logs` 更准确。 |
|
||||
| `src/codex/gateway` | Good | `protocol`、`transport`、`oauth`、`fingerprint` 是上游链路的自然分层。 |
|
||||
| `src/codex/serving` | Good | 对外 OpenAI-compatible 服务面与上游 gateway 分离。 |
|
||||
| `src/platform` | Good | `crypto`、`http`、`identity`、`logging`、`storage` 都是跨领域能力。 |
|
||||
| `src/config` | Good | 配置加载与类型独立,暂不需要进一步艺术化命名。 |
|
||||
| `src/utils` | Acceptable | 当前只有 `json` 和 `pagination`,还没变成杂物间;后续如果扩张,应优先迁回领域目录。 |
|
||||
|
||||
## File Naming Audit
|
||||
|
||||
### Names To Keep
|
||||
|
||||
- `admin/api/accounts/lifecycle.rs`:覆盖状态、标签、删除、批量变更,比 `mutate.rs` 更准确。
|
||||
- `admin/api/client_keys/*`:内部使用 `client_keys` 是正确选择,路由保留 `/api-keys` 是对外兼容。
|
||||
- `codex/accounts/cloudflare_challenge.rs`:比 `cf_path_block.rs` 明确,表达真实安全链路问题。
|
||||
- `codex/accounts/service/pool_sync.rs`:表达账号仓储与运行时池同步,比 `runtime_pool.rs` 更有边界。
|
||||
- `codex/gateway/conversation_identity.rs`:比泛化 `identity.rs` 更准确。
|
||||
- `codex/gateway/installation_id.rs`:表达 ChatGPT/Codex 安装标识,不混入一般 installation 概念。
|
||||
- `codex/gateway/transport/http_client.rs`:比 `client.rs` 清楚,因为 transport 下还有 WebSocket。
|
||||
- `codex/gateway/transport/usage_events.rs`:表达从上游事件流中提取 usage,而不是通用 usage 领域。
|
||||
- `codex/tasks/{model_refresh,quota_refresh,token_refresh}.rs`:任务以动作命名,职责清晰。
|
||||
- `platform/http/request_id.rs`:比 `middleware.rs` 精确。
|
||||
- `platform/crypto/secret_box.rs`:表达加密封装能力,适合稳定复用。
|
||||
|
||||
### Names That Are Acceptable But Can Be Refined Later
|
||||
|
||||
- `src/codex/accounts/model.rs`:目前承载 `Account` 和 `AccountStatus`,与 `codex/models` 有轻微视觉冲突。若继续追求极致,可改成 `account.rs`,让 `accounts/account.rs` 与 `models/catalog.rs` 完全错开。
|
||||
- `src/admin/api/client_keys/*` 内部 handler 名仍使用 `api_key`,例如 `create_api_key`。这是对外路由 `/api/admin/api-keys` 的兼容词,不是架构错误。若后续精修,可把 handler 改为 `create_client_key`,DTO 保留 `ClientApiKey*`。
|
||||
- `tests/codex_events/logs_pagination.rs`:目录已经叫 `codex_events`,文件还叫 `logs_pagination`。如果按领域纯度,可改为 `event_log_pagination.rs`。
|
||||
- `tests/admin/*_route.rs`:测试文件显式带 `route`,表达 HTTP 路由测试,可以保留。若未来测试分层更细,可迁到 `tests/admin/api/*`。
|
||||
- `src/codex/gateway/transport/types.rs`:`types` 是弱名,但当前范围在 `transport` 下仍可接受;如果继续增长,应按 request/response/error 拆出更具体文件。
|
||||
|
||||
### Names To Avoid Reintroducing
|
||||
|
||||
- `admin/http`:会把管理 API 误导为协议工具层。
|
||||
- `admin/auth`:同时包含 session 和 client key 时语义过宽。
|
||||
- `codex/accounts/models`:会让 model catalog 看起来像账号私有数据。
|
||||
- `codex/logs`:会混淆业务事件和进程日志。
|
||||
- `platform/http/middleware.rs`:middleware 是技术位置,不是责任名。
|
||||
- `gateway/identity.rs`:identity 太泛,会掩盖 conversation identity 的具体含义。
|
||||
- `transport/client.rs`:在有 HTTP、SSE、WebSocket 多传输时过于笼统。
|
||||
|
||||
## Size And Organization Audit
|
||||
|
||||
命名已经过关,但少数文件仍偏大,后续可在不改变逻辑的前提下继续整理:
|
||||
|
||||
- `src/codex/serving/dispatch/mod.rs`:约 1000 行,是下一轮最值得拆的聚合点。建议按 request context、response assembly、fallback decision、event recording 继续切分。
|
||||
- `src/codex/gateway/transport/http_client.rs`:约 780 行。可拆为 request building、response parsing、model fetching、probe 四块。
|
||||
- `src/codex/accounts/repository/accounts.rs`:约 700 行。可按 load/list/write/status 或 token metadata 继续切分。
|
||||
- `src/codex/accounts/pool.rs`、`src/codex/serving/dispatch/affinity.rs`、`src/codex/gateway/transport/websocket/*` 当前偏大但仍有领域凝聚力,暂不强拆。
|
||||
|
||||
这些不是命名阻断项。继续优化时应遵守“只拆大文件,不改逻辑”,每次拆分后跑 `cargo fmt --check`、`cargo test --locked`、`cargo clippy --all-targets --all-features --locked -- -D warnings`。
|
||||
|
||||
## Final Recommendation
|
||||
|
||||
当前架构可以定为:
|
||||
|
||||
```text
|
||||
runtime -> web/admin/codex/platform/config/utils
|
||||
admin -> api/session/client_keys/tasks/settings
|
||||
codex -> accounts/models/gateway/serving/events/usage/tasks
|
||||
platform-> crypto/http/identity/logging/storage
|
||||
```
|
||||
|
||||
这是一个适合项目起步阶段的完整体:没有过度抽象,没有强行 workspace 化,也没有把 Web 前端塞进后端。后续前端可以独立演进,后端只保留 `src/web` 作为运行时挂载点。
|
||||
@@ -64,7 +64,7 @@ Claude 审计中“窗口字段未持久化”的结论成立,但“配额控
|
||||
|
||||
- v1 response 和 401 后账户刷新失败事件通过 `LogService::record` 写入。
|
||||
- 在一个入口执行 `enabled`、`capacity`、`capture_body` 和 metadata 规范。
|
||||
- 管理端 `/admin/logs/state` 和请求链路共享同一个 `LogService` 实例,运行时开关立即生效。
|
||||
- 管理端 `/api/admin/logs/state` 和请求链路共享同一个 `LogService` 实例,运行时开关立即生效。
|
||||
|
||||
### P2:收敛 schema 约束(已落地)
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -37,7 +37,7 @@
|
||||
|
||||
**问题:**
|
||||
```
|
||||
1697 行 - src/http/admin/accounts.rs ⚠️ 太大!
|
||||
1697 行 - src/http/api/admin/accounts.rs ⚠️ 太大!
|
||||
895 行 - src/codex/upstream/mod.rs
|
||||
784 行 - src/codex/accounts/repository.rs
|
||||
```
|
||||
@@ -46,9 +46,9 @@
|
||||
|
||||
**改进方案:**
|
||||
```rust
|
||||
// 当前:src/http/admin/accounts.rs (1697 行)
|
||||
// 当前:src/http/api/admin/accounts.rs (1697 行)
|
||||
// 建议拆分为:
|
||||
src/http/admin/accounts/
|
||||
src/http/api/admin/accounts/
|
||||
├── mod.rs // 路由注册
|
||||
├── list.rs // GET /accounts
|
||||
├── create.rs // POST /accounts
|
||||
@@ -138,7 +138,7 @@ src/codex/accounts/service/
|
||||
├── cookies.rs // Cookie 操作
|
||||
├── health.rs // 健康检查
|
||||
├── import.rs // 导入逻辑
|
||||
├── mutation.rs // CRUD
|
||||
├── lifecycle.rs // CRUD
|
||||
├── quota.rs // 配额
|
||||
├── refresh.rs // 刷新
|
||||
└── runtime_pool.rs // 池同步
|
||||
@@ -397,7 +397,7 @@ pub account_pool: Arc<RwLock<AccountPool>>,
|
||||
- 风险:低
|
||||
|
||||
2. **🟡 拆分大文件**
|
||||
- 先拆 `http/admin/accounts.rs` (1697 行)
|
||||
- 先拆 `http/api/admin/accounts.rs` (1697 行)
|
||||
- 按功能模块拆分(list/create/update/delete/oauth)
|
||||
- 成本:中等
|
||||
- 收益:提升可维护性
|
||||
|
||||
@@ -12,9 +12,9 @@ HTTP status codes are not replaced by body codes. Admin/frontend APIs return bot
|
||||
|
||||
| HTTP status | Body code range | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `200` | `200` | Successful read, login, or mutation with response body. |
|
||||
| `200` | `200` | Successful read, login, or lifecycle with response body. |
|
||||
| `201` | `201` | Resource created. |
|
||||
| `204` | `204` | Successful mutation with no response body. No JSON envelope is sent. |
|
||||
| `204` | `204` | Successful lifecycle with no response body. No JSON envelope is sent. |
|
||||
| `400` | `40000`-`40099` | Malformed JSON, invalid parameters, or invalid cursor. |
|
||||
| `401` | `40100`-`40199` | Missing/expired admin session or bad admin password. |
|
||||
| `403` | `40300`-`40399` | Authenticated admin lacks permission for a local-only/bootstrap action. |
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
# Backend Naming Architecture Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Rename backend modules so every directory and file has one clear domain meaning while reserving `/admin` for the future Web console.
|
||||
|
||||
**Architecture:** Move the current management JSON handlers from `admin/http` to `admin/api`, keep `/v1/*` under `codex/serving`, add a `web` backend shell for future static assets, and split ambiguous support modules into domain-specific names. The work is mechanical and must not change upstream Codex behavior.
|
||||
|
||||
**Tech Stack:** Rust 2021, Axum, SQLx, Tokio, tracing, existing integration tests.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
Create:
|
||||
- `src/web/mod.rs`
|
||||
- `src/web/router.rs`
|
||||
- `src/web/assets.rs`
|
||||
- `src/web/shell.rs`
|
||||
- `src/web/security.rs`
|
||||
- `src/platform/crypto/mod.rs`
|
||||
- `src/platform/crypto/secret_box.rs`
|
||||
- `src/platform/logging/mod.rs`
|
||||
- `src/admin/api/client_keys/mod.rs`
|
||||
- `src/admin/api/logs/mod.rs`
|
||||
- `src/admin/session/mod.rs`
|
||||
- `src/admin/client_keys/mod.rs`
|
||||
- `src/codex/events/mod.rs`
|
||||
- `src/codex/models/mod.rs`
|
||||
|
||||
Move or rename:
|
||||
- `src/admin/http` to `src/admin/api`
|
||||
- `src/admin/auth/repository.rs` to `src/admin/session/repository.rs`
|
||||
- `src/admin/auth/service.rs` to `src/admin/session/service.rs`
|
||||
- `src/admin/auth/api_key.rs` to `src/admin/client_keys/service.rs`
|
||||
- `src/admin/http/api_keys.rs` to `src/admin/api/client_keys/mod.rs`
|
||||
- `src/admin/http/auth.rs` to `src/admin/api/session.rs`
|
||||
- `src/admin/http/logs.rs` to `src/admin/api/logs/mod.rs`
|
||||
- `src/admin/http/accounts/mutate.rs` to `src/admin/api/accounts/lifecycle.rs`
|
||||
- `src/codex/accounts/cf_path_block.rs` to `src/codex/accounts/cloudflare_challenge.rs`
|
||||
- `src/codex/accounts/models` to `src/codex/models`
|
||||
- `src/codex/accounts/repository/lease.rs` to `src/codex/accounts/repository/leases.rs`
|
||||
- `src/codex/accounts/repository/quota.rs` to `src/codex/accounts/repository/quotas.rs`
|
||||
- `src/codex/accounts/repository/token.rs` to `src/codex/accounts/repository/tokens.rs`
|
||||
- `src/codex/accounts/service/mutation.rs` to `src/codex/accounts/service/lifecycle.rs`
|
||||
- `src/codex/accounts/service/runtime_pool.rs` to `src/codex/accounts/service/pool_sync.rs`
|
||||
- `src/codex/gateway/identity.rs` to `src/codex/gateway/conversation_identity.rs`
|
||||
- `src/codex/gateway/installation.rs` to `src/codex/gateway/installation_id.rs`
|
||||
- `src/codex/gateway/oauth/cli_import.rs` to `src/codex/gateway/oauth/codex_cli.rs`
|
||||
- `src/codex/gateway/transport/client.rs` to `src/codex/gateway/transport/http_client.rs`
|
||||
- `src/codex/gateway/transport/usage.rs` to `src/codex/gateway/transport/usage_events.rs`
|
||||
- `src/codex/logs` to `src/codex/events`
|
||||
- `src/codex/logs/rotation.rs` to `src/platform/logging/rotation.rs`
|
||||
- `src/codex/tasks/model.rs` to `src/codex/tasks/model_refresh.rs`
|
||||
- `src/codex/tasks/quota.rs` to `src/codex/tasks/quota_refresh.rs`
|
||||
- `src/codex/tasks/refresh.rs` to `src/codex/tasks/token_refresh.rs`
|
||||
- `src/codex/serving/dispatch/audit.rs` to `src/codex/serving/dispatch/stream_audit.rs`
|
||||
- `src/codex/serving/dispatch/refresh.rs` to `src/codex/serving/dispatch/account_refresh.rs`
|
||||
- `src/platform/crypto.rs` to `src/platform/crypto/secret_box.rs`
|
||||
- `src/platform/http/middleware.rs` to `src/platform/http/request_id.rs`
|
||||
- `src/platform/identity/api_key.rs` to `src/platform/identity/client_key.rs`
|
||||
- `src/platform/identity/api_key_repository.rs` to `src/platform/identity/client_key_repository.rs`
|
||||
|
||||
## Task 1: Freeze the naming contract
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/superpowers/specs/2026-06-14-backend-naming-architecture-design.md`
|
||||
- Create: `docs/superpowers/plans/2026-06-14-backend-naming-architecture.md`
|
||||
|
||||
- [x] **Step 1: Write the design spec**
|
||||
|
||||
Record route boundaries, target source tree, naming decisions, and migration policy.
|
||||
|
||||
- [x] **Step 2: Write this implementation plan**
|
||||
|
||||
List every file move and the verification gates.
|
||||
|
||||
## Task 2: Move management API and backend Web shell
|
||||
|
||||
**Files:**
|
||||
- Move: `src/admin/http/**` to `src/admin/api/**`
|
||||
- Create: `src/web/{mod.rs,router.rs,assets.rs,shell.rs,security.rs}`
|
||||
- Modify: `src/admin/mod.rs`
|
||||
- Modify: `src/runtime/router.rs`
|
||||
- Test: `tests/architecture/admin_boundary.rs`
|
||||
|
||||
- [x] **Step 1: Move the management API directory**
|
||||
|
||||
Run file moves so handlers live under `admin::api`.
|
||||
|
||||
- [x] **Step 2: Update admin module exports**
|
||||
|
||||
Expose `pub mod api;`, `pub mod session;`, and `pub mod client_keys;`.
|
||||
|
||||
- [x] **Step 3: Add empty Web shell modules**
|
||||
|
||||
Add `src/web` modules with module-level documentation only. Do not serve frontend assets yet.
|
||||
|
||||
- [x] **Step 4: Update route mounting**
|
||||
|
||||
Import `crate::admin::api as admin_api` in `runtime/router.rs` and merge `admin_api::router()`.
|
||||
|
||||
## Task 3: Rename session and client key domains
|
||||
|
||||
**Files:**
|
||||
- Move: `src/admin/auth/service.rs` to `src/admin/session/service.rs`
|
||||
- Move: `src/admin/auth/repository.rs` to `src/admin/session/repository.rs`
|
||||
- Move: `src/admin/auth/api_key.rs` to `src/admin/client_keys/service.rs`
|
||||
- Move: `src/admin/api/api_keys.rs` to `src/admin/api/client_keys/mod.rs`
|
||||
- Move: `src/admin/api/auth.rs` to `src/admin/api/session.rs`
|
||||
- Modify: `src/runtime/state.rs`
|
||||
- Modify: `src/runtime/bootstrap.rs`
|
||||
- Test: `tests/architecture/admin_boundary.rs`
|
||||
|
||||
- [x] **Step 1: Move files into the new domains**
|
||||
|
||||
Keep type names stable unless a rename is required by compiler errors.
|
||||
|
||||
- [x] **Step 2: Replace imports**
|
||||
|
||||
Replace `admin::auth::service` with `admin::session::service`, `admin::auth::repository` with `admin::session::repository`, and `admin::auth::api_key` with `admin::client_keys::service`.
|
||||
|
||||
- [x] **Step 3: Update API router imports**
|
||||
|
||||
Import the API key handlers from `admin::api::client_keys` and session handlers from `admin::api::session`.
|
||||
|
||||
## Task 4: Rename Codex catalog, events, gateway, transport, and task modules
|
||||
|
||||
**Files:**
|
||||
- Move the Codex files listed in the File Structure section.
|
||||
- Modify: `src/codex/mod.rs`
|
||||
- Modify: `src/codex/accounts/mod.rs`
|
||||
- Modify: `src/codex/accounts/repository.rs`
|
||||
- Modify: `src/codex/accounts/service/mod.rs`
|
||||
- Modify: `src/codex/gateway/mod.rs`
|
||||
- Modify: `src/codex/gateway/oauth/mod.rs`
|
||||
- Modify: `src/codex/gateway/transport/mod.rs`
|
||||
- Modify: `src/codex/tasks/mod.rs`
|
||||
- Modify: `src/codex/serving/dispatch/mod.rs`
|
||||
- Test: `tests/architecture/{accounts_boundary.rs,gateway_boundary.rs,serving_boundary.rs}`
|
||||
|
||||
- [x] **Step 1: Move model catalog to `codex/models`**
|
||||
|
||||
Update references from `codex::accounts::models` to `codex::models`.
|
||||
|
||||
- [x] **Step 2: Move business logs to `codex/events`**
|
||||
|
||||
Update references from `codex::logs` to `codex::events`.
|
||||
|
||||
- [x] **Step 3: Move gateway and transport files**
|
||||
|
||||
Update `identity`, `installation`, `cli_import`, `client`, and `usage` references to the new names.
|
||||
|
||||
- [x] **Step 4: Move task and dispatch helper names**
|
||||
|
||||
Update `model`, `quota`, `refresh`, `audit`, and dispatch refresh references to the new names.
|
||||
|
||||
## Task 5: Rename platform foundations
|
||||
|
||||
**Files:**
|
||||
- Move: `src/platform/crypto.rs` to `src/platform/crypto/secret_box.rs`
|
||||
- Move: `src/platform/http/middleware.rs` to `src/platform/http/request_id.rs`
|
||||
- Move: `src/platform/identity/api_key.rs` to `src/platform/identity/client_key.rs`
|
||||
- Move: `src/platform/identity/api_key_repository.rs` to `src/platform/identity/client_key_repository.rs`
|
||||
- Modify: `src/platform/mod.rs`
|
||||
- Modify: `src/platform/http/mod.rs`
|
||||
- Modify: `src/platform/identity/mod.rs`
|
||||
- Test: `tests/architecture/platform_boundary.rs`
|
||||
|
||||
- [x] **Step 1: Move files**
|
||||
|
||||
Create `platform::crypto::secret_box`, re-export `SecretBox`, `CryptoError`, and `CryptoResult` from `platform::crypto`.
|
||||
|
||||
- [x] **Step 2: Replace imports**
|
||||
|
||||
Update all imports of `platform::http::middleware`, `platform::identity::api_key`, and `platform::identity::api_key_repository`.
|
||||
|
||||
## Task 6: Update tests, docs references, and verify
|
||||
|
||||
**Files:**
|
||||
- Modify tests under `tests/**`
|
||||
- Modify current docs under `docs/api.md`, `docs/architecture-capability-plan.md`, `docs/architecture-reorganization.md`, `docs/implementation-status.md`, and this spec/plan if paths drift.
|
||||
|
||||
- [x] **Step 1: Update architecture tests**
|
||||
|
||||
Make architecture tests assert the new public module paths.
|
||||
|
||||
- [x] **Step 2: Update integration test imports**
|
||||
|
||||
Replace old paths with new paths while leaving test behavior unchanged.
|
||||
|
||||
- [x] **Step 3: Run formatting**
|
||||
|
||||
Run: `cargo fmt --check`
|
||||
|
||||
Expected: no formatting diff. If it fails, run `cargo fmt` and re-run `cargo fmt --check`.
|
||||
|
||||
- [x] **Step 4: Run tests**
|
||||
|
||||
Run: `cargo test --locked`
|
||||
|
||||
Expected: all tests pass.
|
||||
|
||||
- [x] **Step 5: Run Clippy**
|
||||
|
||||
Run: `cargo clippy --all-targets --all-features --locked -- -D warnings`
|
||||
|
||||
Expected: no warnings.
|
||||
|
||||
- [x] **Step 6: Check whitespace**
|
||||
|
||||
Run: `git diff --check`
|
||||
|
||||
Expected: no whitespace errors.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Backend Naming Architecture Design
|
||||
|
||||
## Goal
|
||||
|
||||
将后端目录整理成一名一义的结构,为 `/admin` Web 控制台预留承载面,并把现有管理 JSON API 收束到 `/api/admin` 的后端契约层。
|
||||
|
||||
## Scope
|
||||
|
||||
本次设计只覆盖 Rust 后端目录、模块命名、路由边界和测试命名。前端工程由独立目录和独立约定承载,后端只提供 `src/web` 作为构建产物的挂载位置。
|
||||
|
||||
## Route Boundaries
|
||||
|
||||
```text
|
||||
/admin/* Web 控制台入口,由 src/web 承载
|
||||
/api/admin/* 管理 API,由 src/admin/api 承载
|
||||
/v1/* OpenAI-compatible API,由 src/codex/serving 承载
|
||||
/auth/openai/callback OpenAI OAuth 回调
|
||||
/debug/* 本地诊断
|
||||
/health 存活检查
|
||||
```
|
||||
|
||||
`admin` 是管理域,`web` 是浏览器承载面,`codex` 是 Codex 上游内核,`platform` 是跨领域系统能力。任何目录名都应表达唯一责任,避免 `http`、`auth`、`api_key` 这类多义名泄漏到领域边界。
|
||||
|
||||
## Target Source Tree
|
||||
|
||||
```text
|
||||
src/
|
||||
main.rs
|
||||
lib.rs
|
||||
|
||||
runtime/{mod.rs, bootstrap.rs, router.rs, state.rs}
|
||||
runtime/tasks/{mod.rs, coordinator.rs, types.rs}
|
||||
|
||||
web/{mod.rs, router.rs, assets.rs, shell.rs, security.rs}
|
||||
|
||||
admin/{mod.rs, settings.rs}
|
||||
admin/api/{mod.rs, router.rs, response.rs, session.rs, diagnostics.rs, settings.rs, models.rs, usage.rs}
|
||||
admin/api/accounts/{mod.rs, list.rs, create.rs, import.rs, export.rs, lifecycle.rs, quota.rs, cookies.rs, oauth.rs, health.rs}
|
||||
admin/api/client_keys/{mod.rs, list.rs, create.rs, import.rs, export.rs, lifecycle.rs}
|
||||
admin/api/logs/{mod.rs, query.rs, detail.rs, state.rs}
|
||||
admin/session/{mod.rs, service.rs, repository.rs}
|
||||
admin/client_keys/{mod.rs, service.rs}
|
||||
admin/tasks/{mod.rs, session_cleanup.rs}
|
||||
|
||||
codex/{mod.rs}
|
||||
codex/accounts/{mod.rs, model.rs, jwt.rs, pool.rs, lifecycle.rs, cloudflare_challenge.rs, usage_snapshots.rs}
|
||||
codex/accounts/cookies/{mod.rs, jar.rs, repository.rs}
|
||||
codex/accounts/repository/{mod.rs, accounts.rs, tokens.rs, leases.rs, quotas.rs, usage.rs}
|
||||
codex/accounts/service/{mod.rs, cookies.rs, health.rs, import.rs, lifecycle.rs, quota.rs, refresh.rs, pool_sync.rs}
|
||||
|
||||
codex/models/{mod.rs, catalog.rs, repository.rs, service.rs}
|
||||
|
||||
codex/gateway/{mod.rs, conversation_identity.rs, installation_id.rs}
|
||||
codex/gateway/fingerprint/{mod.rs, model.rs, repository.rs, update_checker.rs, updater.rs}
|
||||
codex/gateway/oauth/{mod.rs, client.rs, codex_cli.rs, refresh.rs, token.rs}
|
||||
codex/gateway/protocol/{mod.rs, schema.rs, error.rs, openai_to_codex.rs, codex_to_openai.rs}
|
||||
codex/gateway/transport/{mod.rs, http_client.rs, headers.rs, rate_limits.rs, sse.rs, usage_events.rs}
|
||||
codex/gateway/transport/websocket/{mod.rs, codec.rs, pool.rs}
|
||||
|
||||
codex/events/{mod.rs, event.rs, repository.rs, service.rs}
|
||||
codex/usage/{mod.rs, service.rs}
|
||||
codex/tasks/{mod.rs, model_refresh.rs, quota_refresh.rs, token_refresh.rs}
|
||||
|
||||
codex/serving/{mod.rs, chat.rs, responses.rs, diagnostics.rs}
|
||||
codex/serving/http/{mod.rs, router.rs, auth.rs, chat.rs, responses.rs, models.rs, diagnostics.rs, errors.rs}
|
||||
codex/serving/dispatch/{mod.rs, affinity.rs, routing.rs, fallback.rs, limits.rs, account_refresh.rs, stream.rs, stream_audit.rs, usage.rs}
|
||||
|
||||
platform/{mod.rs}
|
||||
platform/crypto/{mod.rs, secret_box.rs}
|
||||
platform/http/{mod.rs, auth.rs, health.rs, request_id.rs}
|
||||
platform/identity/{mod.rs, admin_session.rs, client_key.rs, client_key_repository.rs, error.rs}
|
||||
platform/storage/{mod.rs, db.rs, paths.rs, schema.sql}
|
||||
platform/logging/{mod.rs, rotation.rs}
|
||||
|
||||
config/{mod.rs, loader.rs, types.rs}
|
||||
utils/{mod.rs, json.rs, pagination.rs}
|
||||
```
|
||||
|
||||
## Naming Decisions
|
||||
|
||||
`admin/http` becomes `admin/api` because the module exposes the management API contract, not generic HTTP utilities.
|
||||
|
||||
`admin/auth` splits into `admin/session` and `admin/client_keys`. Admin login is session management; local `cpr_` keys are client credentials for `/v1/*`, not upstream provider keys.
|
||||
|
||||
`api_keys` becomes `client_keys` where the code manages local client credentials. The route can remain `/api/admin/api-keys` for product compatibility, but Rust modules should state the stronger domain meaning.
|
||||
|
||||
`codex/accounts/models` moves to `codex/models`. Model catalog and plan snapshots are Codex catalog concerns, not account-owned state.
|
||||
|
||||
`codex/logs` becomes `codex/events`. The SQLite event stream is a business event store used by the admin console; process file logging belongs under `platform/logging`.
|
||||
|
||||
`platform/http/middleware.rs` becomes `platform/http/request_id.rs` because it has one stable responsibility.
|
||||
|
||||
## Migration Policy
|
||||
|
||||
Implementation should be mechanical first: move files, update module declarations, update imports, then run formatting and tests. Business logic changes are out of scope unless required to preserve existing behavior under the new route boundary.
|
||||
|
||||
The migration must keep `/v1/*` OpenAI-compatible behavior unchanged and keep admin session auth separate from local client API keys.
|
||||
Reference in New Issue
Block a user