zenfun aa69ce3659 feat(api): add admin endpoint to issue keys for masters
Add `POST /admin/masters/{id}/keys` allowing admins to issue child keys
on behalf of a master. Introduce an `issued_by` field in the Key model
to audit whether a key was issued by the master or an admin.

Refactor master service to use typed errors for consistent HTTP status
mapping and ensure validation logic (active status, group check) is
shared.
2025-12-15 15:59:33 +08:00
2025-12-14 23:54:12 +08:00
2025-12-14 23:54:12 +08:00

EZ-API (控制平面)

EZ-API 网关系统的管理中心和控制平面。

目标

EZ-API 是"大脑"。它管理着事实的来源 (Source of Truth)。 它负责:

  1. 管理 API: 提供商 (Providers)、API 密钥 (Keys) 和模型 (Models) 的 CRUD 操作。
  2. 状态同步: 将配置快照推送到 Redis供 Balancer 使用。
  3. 日志摄取: 异步将访问日志写入 PostgreSQL。

架构设计

控制平面采用了传统的三层架构,但有一个关键的转折:它主动将状态推送到边缘 (Redis)。

  • 数据库: PostgreSQL (持久化存储)。
  • 缓存/总线: Redis (向 Balancer 分发配置)。
  • 框架: Gin + GORM。

API 端点

管理接口

  • POST /providers: 注册新的上游 AI 提供商。
  • POST /keys: 创建新的客户端 API 密钥。
  • POST /models: 注册支持的模型。
  • GET /models: 列出所有模型。
  • POST /admin/masters/{id}/keys: 代某个 master 签发子 key子 key 仍归属该 master仅审计 issued_by=admin)。

Feature Flags给未来前端用

控制平面会把轻量“开关配置”存到 Redis 的 hashmeta:features,并提供管理接口:

  • GET /admin/features
  • PUT /admin/featuresbody 为 JSON map

常用 flags

  • dp_state_store_backend: memory(默认)/ redis
  • dp_claude_cross_upstream: true / false

系统接口

  • POST /sync/snapshot: 强制将 DB 状态全量重新同步到 Redis。
  • POST /logs: 供 Balancer 推送日志的内部端点 (异步)。

配置说明

变量名 默认值 说明
EZ_API_PORT 8080 监听端口。
EZ_PG_DSN host=localhost... PostgreSQL 连接字符串。
EZ_REDIS_ADDR localhost:6379 Redis 地址。
EZ_LOG_QUEUE 10000 日志缓冲通道的容量。
EZ_LOG_BATCH_SIZE 10 单次 DB 事务写入的日志数量。
EZ_LOG_LEVEL info 日志级别,支持 debuginfowarnerror

配置读取优先级:环境变量 > 配置文件 > 默认值。通过 Viper 支持 ./config.yaml(或 ./config/config.yaml),也可用 EZ_CONFIG_FILE 指定路径。示例:

server:
  port: 8080
postgres:
  dsn: host=localhost user=postgres password=postgres dbname=ezapi port=5432 sslmode=disable
redis:
  addr: localhost:6379
  db: 0
log:
  batch_size: 10
  flush_ms: 1000
  queue_capacity: 10000
auth:
  jwt_secret: change_me_in_production

运行方式

本地运行

go run cmd/server/main.go

Docker 运行

docker build -t ez-api .
docker run -p 8080:8080 --env-file .env ez-api

本地联合开发(配合 balancer

  • 目录结构建议:/workspace/ 下并列放置 ez-apibalancerfoundation
  • 初始化本地 Go 工作区Go 1.20+,不要求提交到任一仓库):在 /workspace 执行
    go work init
    go work use ./ez-api ./balancer ./foundation
    
    如果你只使用已发布的 github.com/ez-api/foundation v0.1.0(或更高 tag则不需要 go.work

集成测试

依赖 Docker 与 docker compose且默认在工作区里与 balancer 仓库并列(用于构建镜像)。在仓库内运行:

cd ez-api
./test/integration.sh

脚本会拉起 docker-compose.integration.yml 中的服务,运行带 integration tag 的 Go 测试,并在完成后清理容器和卷。

测试

  • 单元测试:go test ./...(测试文件与源码同目录,更多约定见 TESTING.md

日志

  • 业务代码统一使用标准库 log/sloglogger.Info("msg", "k", v) 风格)。
  • 输出后端仍为 zerolog(通过 github.com/ez-api/foundation/logging 的 slog handler bridge默认 ConsoleWriter。
  • 通过 EZ_LOG_LEVEL 控制控制平面的日志等级,配合异步 DB 写入LogWriter一起使用。

JSON

  • 项目内 JSON 编解码统一走 github.com/ez-api/foundation/jsoncodec(内部使用 Sonic

依赖约定

  • Control Planeez-api与 Data Planebalancer共享一部分“协议约定/基础设施”代码JSON、日志、provider type 规则),统一沉淀在 github.com/ez-api/foundation
  • 本仓库的 go.mod 需要依赖一个可用的 foundation 版本:发布后建议锁定到 v0.1.0(或更高 tag本地联调可使用 go.work(见下文)。

设计决策

  • 异步日志: 日志不会立即写入 DB。它们被缓冲在内存中并分批刷新以减少 DB IOPS。
  • 快照同步: Balancer 不查询 DB而是由 EZ-API 将 JSON 快照推送到 Redis。这将高流量的数据平面与关系型数据库解耦。
Description
No description provided
Readme 27 MiB
Languages
Go 99.2%
Shell 0.5%
Makefile 0.2%