docs: streamline project guidance

Keep the public README terse and operational, and align the repository skills with the current lifecycle, transport, validation, and release boundaries.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
zyycn
2026-07-15 12:20:00 +08:00
co-authored by Codex
parent 40a2b70bf2
commit b043fced0c
6 changed files with 218 additions and 448 deletions
+56 -130
View File
@@ -1,41 +1,33 @@
<div align="center">
<img src="frontend/public/favicon.svg" alt="Codex Proxy RS" width="88" height="88" />
<img src="frontend/public/favicon.svg" alt="Codex Proxy RS" width="80" height="80" />
# Codex Proxy RS
**基于 Rust 的高性能 Codex 多账号网关代理**
OpenAI Responses 多账号网关。
[![CI](https://github.com/zyycn/codex-proxy-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/zyycn/codex-proxy-rs/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/zyycn/codex-proxy-rs?display_name=tag&sort=semver)](https://github.com/zyycn/codex-proxy-rs/releases)
[![Rust 1.97](https://img.shields.io/badge/Rust-1.97-000?logo=rust&logoColor=white)](https://www.rust-lang.org/)
[![Vue 3.5](https://img.shields.io/badge/Vue-3.5-42b883?logo=vuedotjs&logoColor=white)](https://vuejs.org/)
[![Vite 8](https://img.shields.io/badge/Vite-8-646cff?logo=vite&logoColor=white)](https://vite.dev/)
[![GHCR](https://img.shields.io/badge/GHCR-codex--proxy--rs-2496ED?logo=docker&logoColor=white)](https://github.com/zyycn/codex-proxy-rs/pkgs/container/codex-proxy-rs)
[![MIT](https://img.shields.io/badge/License-MIT-blue.svg)](#开源许可)
[![MIT](https://img.shields.io/badge/License-MIT-blue.svg)](#许可)
[快速开始](#快速开始) · [首次使用](#首次使用) · [客户端接入](#客户端接入) · [常见问题](#常见问题) · [部署文档](deploy/README.md)
[部署](deploy/README.md) · [架构](docs/architecture.md) · [发布](https://github.com/zyycn/codex-proxy-rs/releases)
</div>
> [!NOTE]
> 当前兼容 OpenAI Responses API,不提供 `/v1/chat/completions`。
## 边界
## 功能
- OpenAI Responses:HTTP、SSE、官方 WebSocket。
- 多账号调度、故障切换、额度与身份隔离。
- 会话级 WebSocket 池与共享 HTTP/2 后备。
- PostgreSQL 持久化,Redis 运行态协调。
- Vue 管理端:账号、客户端 Key、用量、费用、延迟与错误。
- 支持 Responses HTTP、SSE 和官方 WebSocket 请求。
- 提供智能调度、额度重置优先、轮询和粘滞四种账号策略。
- 某个账号遇到额度、认证、模型或传输错误时,继续尝试其他账号。
- 在网页中管理账号、客户端 Key、模型别名和运行参数。
- 按请求、模型、账号或客户端 Key 查看 Token、费用、缓存、TTFT、延迟和错误。
- 支持账号 OAuth、Token 导入以及 CPR、Sub2API、CLIProxyAPI JSON 导入。
- 可直接生成 Codex CLI 配置,或通过 deeplink 导入 CCSwitch。
不提供 `/v1/chat/completions`。
## 快速开始
## 部署
Docker Compose 是最简单的启动方式。开始前请安装 Docker Engine 和 Docker Compose Plugin。
### 1. 准备配置
要求 Docker Engine 与 Docker Compose Plugin。
```bash
git clone https://github.com/zyycn/codex-proxy-rs.git
@@ -48,74 +40,62 @@ sudo chown "$(id -u):10001" deploy/config.yaml
chmod 0640 deploy/config.yaml
```
分别执行三次以下命令生成密码:
分别生成 PostgreSQL、Redis 和管理员密码:
```bash
openssl rand -hex 24
```
把结果填入 `deploy/config.yaml` 的 `database.password`、`redis.password` 和
`admin.default_password`。PostgreSQL 与 Redis 密码必须是 48 位十六进制字符;管理员密码
至少 12 位且不能包含 `$`。
写入 `deploy/config.yaml`:
> [!IMPORTANT]
> 应用容器以非 root 用户 `10001:10001` 运行。Linux Bind Mount 会保留宿主机权限,因此需要允许容器用户组读取配置并写入数据和日志目录:
>
> ```bash
> sudo chown -R "$(id -u):10001" .runtime/data .runtime/logs
> chmod 0770 .runtime/data .runtime/logs
> ```
>
> 配置文件通过 Compose `configs` 只读挂载;普通 Compose 会保留宿主机权限,因此由
> 当前用户持有、仅向容器组开放读取权限。
> macOS 和 Windows 的 Docker Desktop 通常也不需要调整数据目录权限。
- `x-cpr.database.password`
- `x-cpr.redis.password`
- `x-cpr.admin.default_password`
### 2. 启动服务
前两个值必须是 48 位十六进制字符。管理员密码至少 12 位,且不能包含 `$`。
Linux 需要开放容器组写权限:
```bash
sudo chown -R "$(id -u):10001" .runtime/data .runtime/logs
chmod 0770 .runtime/data .runtime/logs
```
启动:
```bash
docker compose -f deploy/compose.yaml config --quiet
docker compose -f deploy/compose.yaml pull
docker compose -f deploy/compose.yaml up -d --no-build
```
启动后检查:
```bash
docker compose -f deploy/compose.yaml ps
curl -i http://127.0.0.1:8080/healthz
```
`/healthz` 返回 `204 No Content` 即表示服务正常。管理端地址为 <http://127.0.0.1:8080>。
`204 No Content` 表示应用、PostgreSQL 与 Redis 均可用。管理端位于
`http://127.0.0.1:8080`。
## 首次使用
完整部署与密码轮换规则见 [deploy/README.md](deploy/README.md)。
1. 使用 `admin@cpr.local` 和 `x-cpr.admin.default_password` 中设置的密码登录。
2. 打开“账号”,用 OAuth、Access/Refresh Token 或 JSON 文件添加账号。
3. 点一次连接测试,能看到模型和额度即可。
4. 打开“API 密钥”,创建一个 `sk_...` 客户端 Key。
5. 点击“使用密钥”复制 Codex CLI 配置,或一键导入 CCSwitch。
## 初始化
> [!TIP]
> `admin.default_password` 只用于首次创建管理员。已有管理员后修改该字段不会重置登录密码。
1. 使用 `admin@cpr.local` 与配置中的初始密码登录。
2. 添加 Codex 账号并执行连接测试。
3. 创建 `sk_...` 客户端 Key。
4. 复制 Codex CLI 配置,或导入 CCSwitch。
## 客户端接入
`admin.default_password` 只在首次创建管理员时生效。
## 客户端
| 配置 | 值 |
| -------- | ---------------------------------------- |
| Base URL | `http://127.0.0.1:8080/v1` |
| API Key | 管理端创建的 `sk_...` 客户端 Key |
| API Key | 管理端创建的 `sk_...` |
| 鉴权 | `Authorization: Bearer <client-api-key>` |
先查询当前可用模型:
```bash
curl http://127.0.0.1:8080/v1/models \
-H 'Authorization: Bearer <client-api-key>'
```
发送一个非流式 Responses 请求:
```bash
curl http://127.0.0.1:8080/v1/responses \
-H 'Authorization: Bearer <client-api-key>' \
-H 'Content-Type: application/json' \
@@ -126,90 +106,36 @@ curl http://127.0.0.1:8080/v1/responses \
}'
```
<details>
<summary>查看全部客户端 API 路由</summary>
| 路由 | 说明 |
| -------------------------------- | ------------------------------- |
| `POST /v1/responses` | Responses 非流式或 SSE 流式请求 |
| `GET /v1/responses` | 官方 Responses WebSocket |
| `POST /v1/responses/review` | Review 请求 |
| `GET /v1/models` | OpenAI 格式的模型列表 |
| `GET /v1/models/catalog` | 完整模型目录 |
| `GET /v1/models/{model_id}` | 模型详情 |
| `GET /v1/models/{model_id}/info` | 模型运行信息 |
| 路由 | 用途 |
| --------------------------- | ------------------- |
| `POST /v1/responses` | JSON 或 SSE |
| `GET /v1/responses` | Responses WebSocket |
| `POST /v1/responses/review` | Review |
| `GET /v1/models` | 模型列表 |
| `GET /v1/models/catalog` | 模型目录 |
所有 `/v1/*` 路由都需要客户端 API Key。
</details>
## 管理端
| 页面 | 内容 |
| -------- | ---------------------------------------------------------------------- |
| 概览 | 查看服务状态、请求趋势、Token、账号池容量、请求健康和最近调用 |
| 账号 | 添加、导入、导出、测试、启停账号,以及刷新 Token 和额度 |
| API 密钥 | 创建、复制、启停或删除 Key,生成 Codex CLI 配置并导入 CCSwitch |
| 使用统计 | 按时间、模型、账号和客户端 Key 查看用量、费用、缓存、延迟和错误 |
| 系统设置 | 配置模型别名、调度策略、单账号并发、请求间隔、刷新参数和管理员 API Key |
| 系统更新 | 查看版本和发布说明;Release 版本可以在线更新并重启 |
## 常用操作
### 升级
## 运维
```bash
# 升级
docker compose -f deploy/compose.yaml pull codex-proxy-rs
docker compose -f deploy/compose.yaml up -d --no-build
```
### 查看日志
```bash
# 日志
docker compose -f deploy/compose.yaml logs -f codex-proxy-rs
```
### 从当前源码构建
```bash
# 从源码构建
docker compose -f deploy/compose.yaml build codex-proxy-rs
docker compose -f deploy/compose.yaml up -d
```
> [!WARNING]
> PostgreSQL、Redis、应用数据和文件日志都保存在仓库根目录 `.runtime/`。普通
> `docker compose down` 不会删除这些绑定目录;删除 `.runtime/` 才会清除数据。升级前请备份
> 整个目录,数据库备份中包含客户端凭据,应按敏感数据保管。
运行状态保存在 `.runtime/`。删除该目录会清除数据库、Redis、身份密钥和日志。
## 常见问题
Compose 默认只绑定 `127.0.0.1`。公网接入应使用 HTTPS 反向代理,并转发 WebSocket
upgrade 与真实客户端 IP;不要暴露 PostgreSQL 或 Redis。
### `/healthz` 返回 `503`
## 许可
检查 PostgreSQL 和 Redis 容器是否健康:
```bash
docker compose -f deploy/compose.yaml ps
docker compose -f deploy/compose.yaml logs postgres redis
```
### 容器反复重启
检查 `deploy/config.yaml` 的三个密码是否填写完整,以及 `.runtime/data`、`.runtime/logs`
的权限是否正确。
### 需要从其他设备访问
Compose 默认仅绑定 `127.0.0.1`。请在服务前配置 HTTPS 反向代理,并正确转发 WebSocket 升级和真实客户端 IP 请求头。不要直接暴露 PostgreSQL 或 Redis。
## 相关链接
- [发布版本](https://github.com/zyycn/codex-proxy-rs/releases)
- [容器镜像](https://github.com/zyycn/codex-proxy-rs/pkgs/container/codex-proxy-rs)
- [详细部署说明](deploy/README.md)
- [架构说明](docs/architecture.md)
Docker 镜像支持 Linux amd64/arm64。Release 压缩包另有 macOS arm64 和 Windows amd64 版本。
## 开源许可
Codex Proxy RS 基于 [MIT License](https://opensource.org/license/mit) 开源。
[MIT](LICENSE)
+36 -29
View File
@@ -1,51 +1,58 @@
---
name: codex-proxy-rs
description: Codex Proxy RS 仓库开发指南。Use when working on its Rust/Axum backend, Vue frontend, PostgreSQL/Redis storage, account-pool scheduling, Responses proxy and recovery, telemetry, Docker deployment, CI/release, configuration, debugging, or documentation.
description: Codex Proxy RS 仓库开发指南。Use when changing or auditing its Rust backend, Vue frontend, PostgreSQL/Redis state, account scheduling, Responses transport and recovery, telemetry, Docker deployment, CI, release, configuration, or project documentation.
---
# Codex Proxy RS
使用此 skill 处理 Codex Proxy RS 的开发、审计、验证和发布工作。
## 事实来源
## 开始前
1. 以当前源码、配置和测试为准。
2. 非简单改动读取 `references/repo-guide.md`。
3. 涉及目录、生命周期、存储或后台任务时读取 `docs/architecture.md`。
4. skill 或文档与实现冲突时,在同一改动中修正。
1. 确认当前仓库根目录是 `codex-proxy-rs`。
2. 存在 `.codegraph/` 时,优先用 CodeGraph 定位调用链,再回到源码和测试验证。
3. 非简单改动先阅读 `references/repo-guide.md`。
4. 涉及目录边界、请求链路、存储归属或后台任务时,同时阅读 `docs/architecture.md`。
5. 始终以当前源码、配置和测试为准;发现 skill 与代码不一致时,在同一改动中修正 skill。
6. 保持改动紧贴用户请求,不擅自改变目录、部署或发布契约。
存在 `.codegraph/` 时可先定位调用链;结论必须回到源码和测试验证。
## 任务分流
## 边界
- 后端:遵循 `backend/src` 当前领域边界;测试统一放在 `backend/tests`,禁止写入 `backend/src`。
- 存储:PostgreSQL 是权威持久化,Redis 保存运行态数据,本地数据目录保存身份密钥和更新状态。
- 前端:使用 Vue 3 `<script setup>`、TypeScript、Tailwind v4、已有组件和主题 token。
- Docker / 发布:保留非 root runtime、YAML 凭据桥接、`.runtime` 绑定目录、GitHub Release、GHCR 和在线更新契约。
- 文档:README 面向部署者和使用者;`docs/architecture.md` 面向开发者。不要新增过程型审计或迁移文档。
- `v1/*` 使用 Request → Attempt → Stream 生命周期。功能规则只能留在唯一 owner 内。
- `api` 解析和编码;`dispatch` 编排;`fleet` 管账号;`upstream` 管协议与传输;`telemetry` 保存确定事实。
- transport 不选择账号,不解释账号状态,不在 payload 发送后重放。
- PostgreSQL 是持久化权威;Redis 保存会话、租约、模型快照和短期状态。
- 测试只放 `backend/tests/`。禁止在 `backend/src/` 写 test-only 代码。
- Vue 使用 `<script setup lang="ts">`、现有基础组件和主题 token。
- README 面向使用者,保持简短;长期架构只写入 `docs/architecture.md`。
- 不添加兼容 shim、重复状态机、第二套配置或补丁式旁路。
## 工作流
1. 检查工作树,区分用户改动与当前任务。
2. 追踪入口、owner、状态变化和输出,再决定修改点。
3. 在最小所有权边界内实现;行为变化用外置集成测试固定。
4. 同步受影响的架构、配置或 skill。
5. 按风险运行验证,最后检查 staged 与 unstaged 范围。
## 验证
按改动范围选择足以证明行为的命令。跨领域改动执行完整门禁:
从仓库根目录执行:
```bash
cd backend
cargo fmt --check
cargo clippy --all-targets --all-features --locked
cargo test --test main --locked
cargo +1.97.0 fmt --manifest-path backend/Cargo.toml -- --check
cargo +1.97.0 clippy --manifest-path backend/Cargo.toml --all-targets --all-features --locked -- -D warnings
cargo +1.97.0 test --manifest-path backend/Cargo.toml --locked
pnpm --dir frontend format:check
pnpm --dir frontend build
docker compose -f deploy/compose.yaml config --quiet
```
后端集成测试需要可用的 PostgreSQL 和 Redis;通过 `CPR_TEST_DATABASE_URL`、`CPR_TEST_REDIS_URL` 指定测试连接。使用部署 Compose 时,连接密码必须与 `deploy/config.yaml` 一致。
后端完整测试需要 PostgreSQL、Redis,以及与 `deploy/config.yaml` 一致的
`CPR_TEST_DATABASE_URL`、`CPR_TEST_REDIS_URL`。
涉及在线更新时,至少运行 `api::admin::system_routes` 相关测试。涉及发布或镜像时,按 `references/repo-guide.md` 核对版本元数据、Release asset 和镜像 tag。
## Git 与发布
## Git
沿用仓库历史:使用简短的 Conventional Commit subject,并带署名:
```text
Co-authored-by: Codex <noreply@openai.com>
```
- 使用简短 Conventional Commit subject。
- 提交前检查 `git status --short`、cached/unstaged diff 和 `git diff --check`。
- 提交带 `Co-authored-by: Codex <noreply@openai.com>`。
- 发布以 `release/version.yaml` 和带注释的 `vX.Y.Z` tag 为准。
- 发布完成后核对远端 `main`、tag、Actions、Release asset 与 GHCR。
+2 -2
View File
@@ -1,4 +1,4 @@
interface:
display_name: "Codex Proxy RS"
short_description: "按当前架构开发和维护 Rust/Vue/PostgreSQL/Redis 代理服务"
default_prompt: "使用 $codex-proxy-rs 按当前源码和架构开发、验证或维护 Codex Proxy RS。"
short_description: "按当前架构维护 Rust/Vue 多账号 Responses 网关"
default_prompt: "使用 $codex-proxy-rs 按当前源码与架构完成开发、验证或发布。"
+86 -200
View File
@@ -1,232 +1,118 @@
# Codex Proxy RS 项目指南
## 目录
## 权威来源
- [Codex Proxy RS 项目指南](#codex-proxy-rs-项目指南)
- [目录](#目录)
- [事实来源](#事实来源)
- [仓库结构](#仓库结构)
- [后端边界](#后端边界)
- [存储边界](#存储边界)
- [前端规范](#前端规范)
- [Docker 和运行时](#docker-和运行时)
- [发布和在线更新](#发布和在线更新)
- [文档边界](#文档边界)
- [验证矩阵](#验证矩阵)
- [项目约束](#项目约束)
- 行为:当前源码、配置和测试。
- 架构:`docs/architecture.md`。
- 部署:`deploy/config.example.yaml`、`deploy/compose.yaml`、`deploy/README.md`。
- 发布:`release/version.yaml`、`release/platforms.yaml`、`.github/workflows/release.yml`。
## 事实来源
本文件只记录高频开发入口,不复制完整架构。
1. 当前源码、配置和测试是行为事实。
2. `docs/architecture.md` 是目录、依赖方向、请求链路和存储归属的权威说明。
3. 本文件记录开发流程和高频约束,不复制完整架构。
4. 文档与代码冲突时先核对实现,再在同一提交中修正文档。
## 结构
## 仓库结构
| 路径 | 责任 |
| ----------------------------- | --------------------------------------------- |
| `backend/src/api` | HTTP/WebSocket 契约、鉴权、响应编码、静态资源 |
| `backend/src/dispatch` | `v1/*` Request → Attempt → Stream 编排 |
| `backend/src/fleet` | 账号、调度、quota、token、Cookie、管理操作 |
| `backend/src/upstream/openai` | Codex 协议、HTTP/2、WebSocket、指纹 |
| `backend/src/telemetry` | usage、错误事实、聚合和查询 |
| `backend/src/infra` | PostgreSQL、Redis、日志、路径、身份 |
| `backend/src/bootstrap` | 配置、装配、后台任务、关闭 |
| `backend/tests` | 集成、契约、fixture;生产源码内禁止测试 |
| `frontend` | Vue 管理端 |
| `deploy` | 唯一 Compose 与配置模板 |
| `docs/architecture.md` | 唯一长期架构文档 |
| `release` | 版本与平台元数据 |
- `backend/src/`:Rust 1.97 / Axum 后端生产代码。
- `backend/tests/`:后端集成测试和 fixtures。测试代码禁止放进 `backend/src/`。
- `backend/build.rs`:把版本、Git SHA、构建时间和构建类型写入编译期环境变量。
- `frontend/`:Vue 3、Vite 8、Tailwind v4、Pinia、Vue Router、Axios、Lucide 和 ECharts 管理端。
- `deploy/`:Dockerfile、唯一的 `compose.yaml` 和 `config.example.yaml`。
- `docs/architecture.md`:唯一长期架构文档。
- `release/`:版本、目标平台和发布脚本。
- `skills/`:项目本地 Codex skills。
仓库根目录没有 Cargo manifest。后端命令使用
`--manifest-path backend/Cargo.toml`,或先进入 `backend/`。
仓库根目录没有 Cargo workspace manifest。Rust 命令必须显式使用 `backend/Cargo.toml`。
## 后端所有权
## 后端边界
- `api` 只做入站/出站适配,不写业务规则。
- `dispatch/lifecycle` 只编排顺序、retry、commit 和 finalize。
- `dispatch/controllers` 中每个功能只能有一个 owner,controller 不互调。
- `fleet/account_failure.rs` 统一解释跨入口账号失败和状态 effect。
- `upstream/openai/failure.rs` 只生成 typed failure facts。
- `upstream/openai/transport` 只建立连接、收发协议和产出 transport metrics。
- `telemetry` 保存已经确定的事实,不参与调度。
- `bootstrap` 是 composition root,不解释业务错误。
项目没有 `application` 层。`bootstrap` 是装配根,业务规则留在各领域模块。
提交边界后不得自动换 transport、账号或重放 payload。账号身份按 attempt 重建;客户端
session/thread/turn 等拓扑字段原样透传。
| 目录 | 职责 |
| --- | --- |
| `backend/src/api` | 入站 HTTP、鉴权提取、响应映射和静态资源 |
| `backend/src/bootstrap` | 配置加载、服务装配、启动关闭和后台任务 |
| `backend/src/dispatch` | Responses 编排、账号失败处理、流生命周期和会话恢复 |
| `backend/src/fleet` | 账号、账号池、调度、quota、刷新、Cookie 和管理操作 |
| `backend/src/upstream/openai` | OpenAI/Codex 协议、HTTP/WebSocket 传输、token 和指纹 |
| `backend/src/telemetry` | 成功/失败事实、聚合桶、账号用量和 Dashboard 查询 |
| `backend/src/keys` | 客户端 API Key |
| `backend/src/auth` | 管理员用户和登录会话 |
| `backend/src/settings` | PostgreSQL 运行时设置和 watch 广播 |
| `backend/src/models` | 模型目录和 Redis 快照 |
| `backend/src/update` | Release 查询、下载、替换、回滚和更新状态 |
| `backend/src/infra` | PostgreSQL、Redis、日志、身份和通用工具 |
## Responses 传输
关键入口:
- 热 WS 立即复用。
- 冷 WS 前台预算为 800ms;超时后当前请求使用同账号 HTTP/2。
- 未完成的 WS 只在后台继续握手,不发送原 payload;成功后进入 Idle。
- `Connecting` 按 key 单飞并沿用原绝对 deadline。
- 账号驱逐和 shutdown 取消 opening;迟到连接不能重新入池。
- warmup 与 connection-local continuation 必须使用精确 WS。
- breaker 按 origin/TLS profile 统计退化 opening,同一次 opening 只计一次。
- 总路由:`backend/src/api/router.rs`
- 客户端路由:`backend/src/api/client/router.rs`
- 管理端路由:`backend/src/api/admin/router.rs`
- 服务装配:`backend/src/bootstrap/services.rs`
- 非流式调度:`backend/src/dispatch/service.rs`
- 流式调度:`backend/src/dispatch/stream/lifecycle.rs`
- 账号调度:`backend/src/fleet/scheduler/mod.rs`
完整 typestate、pool、breaker 和指标契约见 `docs/architecture.md`。
对应测试:
## 存储
- 系统更新:`backend/tests/api/admin/system_routes/mod.rs`
- 代理调度:`backend/tests/dispatch/service.rs` 及其子目录
- 静态资源和健康检查:`backend/tests/api/assets.rs`
| 位置 | 数据 |
| --------------- | ------------------------------------------------------ |
| PostgreSQL | 管理员、Key、账号、quota、设置、Cookie、指纹、遥测事实 |
| Redis | 管理会话、刷新租约、模型快照、响应归属、短期会话状态 |
| `.runtime/data` | 身份 HMAC secret、更新状态和锁 |
| `.runtime/logs` | 结构化轮转日志 |
启动服务:
规则:
```bash
cd backend
cargo run -- serve
```
- migration 只能新增;禁止修改已应用 SQL。
- Redis 业务键使用 `cpr:` 前缀和明确 TTL。
- `identity_hmac_secret` 必须随部署保留。
- 遥测或 affinity 写入失败不能改变已取得的代理响应。
- 账号明确失效先更新内存并驱逐 WS,再异步持久化。
`main.rs` 还提供内部维护命令 `rebuild-buckets`,用于从保留期内的请求事实重建聚合桶。
## 前端
## 存储边界
- Vue 3 Composition API、`<script setup lang="ts">`。
- API:`frontend/src/api/modules`。
- 基础组件:`frontend/src/components/base`。
- 页面状态和副作用:对应 `views/*/composables`。
- 使用现有主题 token、Tailwind utilities 和 Lucide。
- 独立功能使用独立 loading;旧请求不得覆盖较新响应。
- 保持紧凑、低噪声的运维界面。
| 存储 | 数据 |
| --- | --- |
| PostgreSQL | 管理员、客户端 Key、运行时设置、账号、quota、累计用量、请求事实、错误事实、聚合桶、Cookie 和指纹 |
| Redis | 管理会话、token 刷新租约、模型计划快照、会话亲和与 replay |
| 本地数据目录 | `identity_hmac_secret`、更新状态、锁和临时文件 |
| 文件日志目录 | 轮转后的结构化日志 |
## 运行与部署
约束:
- 配置入口只有 `deploy/config.yaml`;项目不使用 `.env`。
- Compose 运行 PostgreSQL、Redis 和非 root 应用容器 `10001:10001`。
- 持久状态全部位于 `.runtime/`。
- 应用默认绑定 `127.0.0.1:8080`;公网使用 HTTPS 反向代理。
- Docker runtime 只包含后端二进制、前端产物和运行依赖。
- PostgreSQL migration 必须新增版本,禁止修改已应用 SQL;启动会校验版本顺序、名称和 checksum。
- Redis 业务键统一使用 `cpr:` 前缀;会话、租约和 affinity 依赖 TTL。
- `identity_hmac_secret` 决定账号作用域身份和 installation ID,换镜像时必须保留。
- 模型别名、调度策略、并发、请求间隔和刷新参数保存到 PostgreSQL,不放回 YAML。
- 遥测和 affinity 写入失败不能改变已经取得的代理响应语义。
不要输出 `docker compose config`、`docker inspect` 或真实连接 URL 中的密码。
## 前端规范
- 使用 Vue 3 Composition API 和 `<script setup lang="ts">`。
- API 客户端位于 `frontend/src/api/modules`。
- 基础 UI 位于 `frontend/src/components/base`。
- 页面私有组件和 composables 放在对应 `frontend/src/views/*` 下。
- 优先使用 Tailwind v4 utilities;需要 CSS 时复用 `frontend/src/styles/tokens.css`。
- 保持亮色和暗色主题一致,有 token 时不硬编码一次性颜色。
- 按钮和紧凑操作优先使用 Lucide 图标。
- 弹窗工作流沿用现有 modal/component 模式,不为一次性操作增加路由。
## Docker 和运行时
- Runtime 基于 `debian:bookworm-slim`,只安装 `ca-certificates` 和健康检查所需的 `curl`。
- 镜像包含单个后端二进制和 `web/dist`,以非 root 用户 `10001:10001` 运行。
- Builder 使用 Node 24 和 Rust 1.97,构建工具不得进入 runtime。
- 默认应用镜像是 `ghcr.io/zyycn/codex-proxy-rs:latest`。
`deploy/config.example.yaml` 是完整启动配置模板。真实配置复制为被 Git 忽略的
`deploy/config.yaml`,其中同时保存应用行为、管理员初始化密码、PostgreSQL 密码和 Redis 密码。
服务密码通过 YAML anchor 与 Compose `extends` 传给内置服务,不使用 `.env` 配置文件。
首次部署:
```bash
mkdir -p .runtime/data .runtime/logs
install -d -m 0750 .runtime/postgres .runtime/redis
cp deploy/config.example.yaml deploy/config.yaml
sudo chown "$(id -u):10001" deploy/config.yaml
chmod 0640 deploy/config.yaml
# 设置 deploy/config.yaml 中的三个密码后执行
docker compose -f deploy/compose.yaml config --quiet
docker compose -f deploy/compose.yaml up -d
```
挂载和卷:
- `deploy/config.yaml` -> `/app/deploy/config.yaml`,Compose config、只读(宿主 mode `0640`)
- `.runtime/data` -> `/app/.runtime/data`
- `.runtime/logs` -> `/app/.runtime/logs`
- `.runtime/postgres` -> PostgreSQL 权威数据
- `.runtime/redis` -> Redis AOF
普通 `docker compose down` 不删除绑定目录;删除 `.runtime` 才会清除本地状态。
## 发布和在线更新
发布契约:
- 发布入口:`release/publish <version>`
- 产品版本:`release/version.yaml`
- 目标平台:`release/platforms.yaml`
- Release workflow:`.github/workflows/release.yml`
- `v*` tag 触发 Release
- Docker 平台:`linux/amd64`、`linux/arm64`
Release asset:
```text
codex-proxy-rs_<version>_linux_amd64.tar.gz
codex-proxy-rs_<version>_linux_arm64.tar.gz
codex-proxy-rs_<version>_darwin_arm64.tar.gz
codex-proxy-rs_<version>_windows_amd64.zip
checksums.txt
```
GHCR 发布 `<version>` 和 `sha-<git-sha>` tag;只有稳定版本更新 `latest`,预发布版本不得覆盖 `latest`。
在线更新接口位于 `/api/admin/system/*`,前端入口是
`frontend/src/layout/components/SystemUpdateModal.vue`。Docker 环境使用:
- `CPR_DEPLOYMENT_MODE=docker`
- `CPR_UPDATE_REPOSITORY=zyycn/codex-proxy-rs`
- `CPR_UPDATE_CHANNEL=stable`
- `CPR_UPDATE_TEMP_DIR=/app/.runtime/data/update-tmp`
- `CPR_UPDATE_STATE_FILE=/app/.runtime/data/update-state.json`
- `CPR_UPDATE_LOCK_FILE=/app/.runtime/data/update.lock`
- `CPR_WEB_DIST_DIR=/app/web/dist`
- `CPR_ENABLE_SELF_RESTART=true`
更新会校验 checksum,替换二进制和 `web/dist`,再触发进程重启。文件替换必须保留跨文件系统的 copy-and-remove fallback。
## 文档边界
- 根 `README.md` 面向部署者和 API 使用者,只写当前产品能力、部署、配置、持久化、升级和排障。
- README 不写内部发布脚本、CI 门禁、审计过程或内测迁移流程。
- `docs/` 只保留 `architecture.md`,用于说明当前目录、依赖、请求链路、调度恢复、存储和后台任务。
- 维护者专用流程写入本 skill,不新增过程型 Markdown 文档。
## 验证矩阵
Rust:
```bash
cd backend
cargo fmt --check
cargo clippy --all-targets --all-features --locked
cargo test --test main --locked
```
完整测试需要 PostgreSQL 和 Redis。通过以下变量提供连接:
```text
CPR_TEST_DATABASE_URL
CPR_TEST_REDIS_URL
```
使用部署 Compose 时,测试 URL 的密码必须与 `deploy/config.yaml` 一致并正确进行 URL 编码。不要在日志或提交中输出真实密码。
前端:
## 验证
```bash
cargo +1.97.0 fmt --manifest-path backend/Cargo.toml -- --check
cargo +1.97.0 clippy --manifest-path backend/Cargo.toml --all-targets --all-features --locked -- -D warnings
cargo +1.97.0 test --manifest-path backend/Cargo.toml --locked
pnpm --dir frontend format:check
pnpm --dir frontend build
```
Compose:
```bash
docker compose -f deploy/compose.yaml config --quiet
```
聚焦测试应使用现有集成测试模块过滤;只有跨模块契约、存储或用户流程变化时才扩大到完整门禁。发布与镜像改动还需核对 `.github/workflows/_quality.yml`、`.github/workflows/_container.yml` 和 `.github/workflows/release.yml`。
聚焦改动先运行对应模块。跨领域、存储、生命周期或发布改动执行完整门禁。
## 项目约束
## 发布
- 新代码和重构不保留兼容别名、临时 shim、重复旧 API 或补丁式旁路。
- 不把测试写入 `backend/src`。
- 不为 Cargo `target` 添加仓库级重定向;运行时数据和日志放在 `.runtime`。
- 已确认且属于当前范围的问题应先修复,再继续后续测试。
- README、架构、skill、workflow、Dockerfile 和真实命令必须一致。
- UI 保持安静、紧凑的运维控制台风格,避免营销式布局、卡片套卡片和重复说明。
- 不创建冗余 Docker 配置、第二套版本源或重复存储路径。
- CodeGraph 用于定位;只有后续判断依赖已修改的索引且工具需要手动刷新时才同步索引。
1. 更新 `release/version.yaml`。
2. 提交版本变更。
3. 创建同版本带注释 `vX.Y.Z` tag。
4. 原子推送 `main` 与 tag。
5. 等待 Release workflow 完成。
6. 核对远端 `main`、tag target、GitHub Release、assets 和 GHCR tags。
Release 包含 Linux amd64/arm64、macOS arm64、Windows amd64;稳定版本更新 GHCR
`latest`。在线更新必须验证 checksum,并保留跨文件系统 copy-and-remove fallback。
+36 -85
View File
@@ -1,108 +1,59 @@
---
name: engineering-standards
description: 面向长期维护的工程规范工作流。当用户要求代码审计、问题修复、重构、实现方案、生产问题追溯,或强调代码质量、干净架构、拒绝垃圾代码、禁止兼容写法、先审计再改代码、参考项目对比时使用。
description: 证据优先的长期维护工作流。用于代码审计、问题修复、重构、生产故障、参考项目对比,以及用户强调干净架构、禁止兼容写法、先审计再实现或拒绝代码异味的任务。
---
# 工程规范
先证明当前系统的真实行为,再决定是否改代码。证据来自当前源码、配置、测试和运行结果。
## 证据顺序
## 证据门禁
1. 当前运行结果与可复现输入。
2. 当前源码、配置、数据库和日志。
3. 当前测试与公开契约。
4. 架构文档。
5. 记忆和参考项目。
对非简单行为变更,动代码前在内部确认:
后两项只能辅助定位,不能覆盖当前事实。
1. 现有机制:入口、调用链、数据变化、持久化、读取和展示路径。
2. 缺口证据:已经证明的断点及对应源码位置。
3. 改动边界:在现有所有权模型中负责修复该问题的最小边界。
## 工作流
不强制向用户输出固定模板。根据任务复杂度,用简短进度或审计结论说明关键证据。简单文案、格式或明确的机械修改只需检查受影响文件并直接完成。
1. 追踪入口、调用链、状态变化、持久化、读取和输出。
2. 区分展示、接口、领域规则、存储、异步任务和外部依赖。
3. 找到现有 owner,证明断点位于该边界。
4. 在 owner 内直接修复;必要重构必须减少分支或重复职责。
5. 通过公开接口或外置集成测试固定行为。
6. 运行项目既定格式、lint 和相关测试,再检查最终 diff。
在现有链路被追完并证明不足之前,不引入新的机制、分支或旁路绕开问题。
简单文案和机械修改直接完成,不套审计模板。结论先行,只报告影响判断的证据。
## 审计流程
## 实现约束
以当前仓库的实时源码为唯一事实来源。当前链路清楚后,才使用记忆或参考项目补充判断。
1. 确认用户讨论的数据或行为。
2. 追踪它在哪里产生、转换、持久化、加载和展示。
3. 同时检查主动链路和被动链路。运行时行为分别确认触发条件、执行路径、持久化、读取和展示。
4. 分类问题所在边界:
- 展示层
- 接口契约
- 持久化层
- 运行时行为
- 外部依赖
- 异步或周期任务
5. 说明支持分类的证据,以及仍未证明的部分。
6. 排查中发现旁支问题时先记录证据。确认属于当前范围的,修复后再继续测试;与任务无关的只在结尾报告,不擅自扩大改动。只有无法从用户目标判断范围时才询问。
存在 CodeGraph 时可先用它定位,再回到源码和测试验证。不要把索引摘要、记忆或参考项目当成强于当前源码的证据。
- 不添加兼容 shim、重复 API、双状态机或临时旁路。
- 不用大范围重构掩盖尚未理解的问题。
- 不为局部问题修改无关模块。
- 不在没有复用或所有权收益时增加抽象。
- 用户只要求审计、文档或方案时,不扩大到实现。
- 已确认且属于当前范围的问题,先修复再继续测试。
- 测试遵守仓库目录边界,不混入生产源码。
- 行为语义变化应在修改前明确说明。
## 参考项目
参考项目只用于理解可能的模式。除非同时满足以下条件,否则不把参考实现搬进当前项目:
只有同时满足以下条件才采用参考实现:
1. 当前项目确实缺少所需行为。
2. 当前架构存在匹配的所有权边界。
3. 新设计不会绕开或复制现有链路。
4. 当前任务范围允许实现。
1. 当前项目已证明缺少该行为。
2. 当前架构存在匹配 owner。
3. 不会复制现有链路。
4. 用户授权的范围包含实现。
参考项目与当前源码冲突时,以当前源码为准。
## 干净实现
优先在现有所有权边界内完成直接修复。
- 除非用户明确要求,不添加兼容代码。
- 不用补丁式分支、重复机制或外层绕路掩盖边界问题。
- 不用大范围重构掩盖不确定性。
- 不为局部问题修改无关模块。
- 只有确实降低复杂度或符合现有模式时才添加抽象。
- 必要重构必须收敛职责、减少分支并让主链路更清楚。
- 未证明现有设计不足时,不引入第二条执行路径。
方案改变行为语义时,动代码前明确说明影响。
## 范围纪律
- 简单问题先给结论。
- 审计给出具体源码证据。
- 不做推测性断言,不虚构事实、数据来源或系统行为。
- 新项目和新链路不保留无意义兼容路径。
- 仓库约定测试目录时,不把测试写入源码模块。
- 用户限定为审计、文档、评审或方案时,只交付对应产物。
- 用户要求直接修复且范围清楚时,不用重复确认阻断执行。
## 动代码前
非简单行为变更应满足:
1. 当前链路已经端到端追完。
2. 问题已按证据分类。
3. 已证明现有机制不能满足需求,而不是尚未找到。
4. 改动落在最小的干净所有权边界。
5. 测试通过公开接口或集成测试面覆盖行为。
缺少任一项时继续调查。简单机械修改不需要套用完整审计流程,但仍要检查目标文件、相邻约束和最终差异。
参考代码用于验证机制,不用于替代当前项目证据。
## 收尾
结束前确认:
交付只包含:
1. 运行格式化和相关测试。
2. 运行项目既定 lint。
3. 没有把测试加入错误目录。
4. 没有用参考项目取代当前项目证据。
5. 没有未经批准引入额外分支、旁路或兼容实现。
6. 只有后续判断依赖已改动索引且工具要求手动刷新时,才同步 CodeGraph。
7. 汇报改动、验证结果和明确未做的事项。
- 已改变的行为与边界。
- 能证明结果的验证。
- 明确未做或仍受外部状态阻塞的事项。
## 禁止的做法
1. 只看局部触发点就断言完整系统行为。
2. 没追完已有链路就新增另一套机制。
3. 没证明现有机制失败就设计旁路。
4. 直接照搬参考项目,跳过当前源码证据。
5. 用兼容 shim、重复 API 或生命周期补丁掩盖所有权问题。
正确顺序是:追清现有链路,证明断点,选择所有权边界,完成干净修复,再用真实测试验证。
禁止把排查时间线、空洞原则或未证实猜测包装成深度。
@@ -1,4 +1,4 @@
interface:
display_name: "工程规范"
short_description: "长期维护的工程规范:证据优先、范围纪律、干净实现与审计工作流。"
default_prompt: "使用 $engineering-standards 按工程规范先审计当前代码链路,再提出或实现干净修复。"
short_description: "证据优先、边界清晰、拒绝兼容旁路的长期工程维护工作流"
default_prompt: "使用 $engineering-standards 追清当前链路,并在唯一所有权边界内完成干净修复。"