feat: scaffold ai gateway identity and design
This commit is contained in:
@@ -19,7 +19,14 @@ Content-Type: application/json
|
||||
"sub": "user-id",
|
||||
"username": "demo",
|
||||
"role": ["user"],
|
||||
"tenantId": null,
|
||||
"tenantId": "tenant-id",
|
||||
"gatewayTenantId": "optional-gateway-tenant-id",
|
||||
"tenantKey": "team-a",
|
||||
"source": "server-main",
|
||||
"gatewayUserId": "optional-gateway-user-id",
|
||||
"userGroupId": "optional-primary-group-id",
|
||||
"userGroupKey": "pro",
|
||||
"userGroupKeys": ["pro", "image-plus"],
|
||||
"apiKeyId": "key-id",
|
||||
"apiKeySecret": "sk-...",
|
||||
"apiKeyName": "production-key"
|
||||
@@ -38,7 +45,180 @@ file=@result.png
|
||||
|
||||
AI Gateway 不维护独立 OSS 配置,也不向 `server-main` 申请预签名。需要上传本地中间产物、provider 临时 URL 转存、base64 解码结果时,统一组装 multipart 请求调用主服务开放上传接口,并记录主服务返回的 file id / URL / object key。
|
||||
|
||||
### 1.3 结算事件
|
||||
### 1.3 租户同步
|
||||
|
||||
AI Gateway 在独立模式下自己维护租户;接入 `server-main` 时保存主服务租户/组织同步副本,用于任务隔离、平台可见性、租户级限流和审计。
|
||||
|
||||
建议新增同步接口:
|
||||
|
||||
```http
|
||||
POST /internal/platform/tenants/sync
|
||||
Authorization: Bearer ${SERVER_MAIN_INTERNAL_TOKEN}
|
||||
Content-Type: application/json
|
||||
Idempotency-Key: tenant:${source}:${externalTenantId}:${version}
|
||||
```
|
||||
|
||||
请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "server-main",
|
||||
"externalTenantId": "tenant-id",
|
||||
"tenantKey": "team-a",
|
||||
"name": "Team A",
|
||||
"status": "active",
|
||||
"planKey": "pro",
|
||||
"rateLimitPolicy": {
|
||||
"rules": [
|
||||
{ "metric": "rpm", "limit": 500, "windowSeconds": 60 },
|
||||
{ "metric": "concurrent", "limit": 20, "leaseTtlSeconds": 900 }
|
||||
]
|
||||
},
|
||||
"sourceUpdatedAt": "2026-05-09T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- Gateway 使用 `source + externalTenantId` 幂等 upsert 到 `gateway_tenants`。
|
||||
- 租户禁用后,新任务拒绝入队;已运行任务按任务策略快照继续或由管理员取消。
|
||||
- 用户同步必须带可映射的 `tenantId` / `tenantKey`,使任务、用户、用户组、限流和平台可见性都能落到同一租户上下文。
|
||||
|
||||
### 1.4 用户同步
|
||||
|
||||
AI Gateway 需要在独立模式下自己维护用户,在接入 `server-main` 时保存主服务用户的同步副本。同步副本只用于模型调用策略、审计、任务归属和用户组解析,不承接主服务余额、订单、充值流水。
|
||||
|
||||
建议新增同步接口:
|
||||
|
||||
```http
|
||||
POST /internal/platform/users/sync
|
||||
Authorization: Bearer ${SERVER_MAIN_INTERNAL_TOKEN}
|
||||
Content-Type: application/json
|
||||
Idempotency-Key: user:${source}:${externalUserId}:${version}
|
||||
```
|
||||
|
||||
请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "server-main",
|
||||
"externalUserId": "user-id",
|
||||
"username": "demo",
|
||||
"displayName": "Demo User",
|
||||
"email": "demo@example.com",
|
||||
"tenantId": "tenant-id",
|
||||
"tenantKey": "team-a",
|
||||
"roles": ["user"],
|
||||
"status": "active",
|
||||
"sourceUpdatedAt": "2026-05-09T12:00:00Z",
|
||||
"userGroupKeys": ["pro", "image-plus"]
|
||||
}
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- Gateway 使用 `source + externalUserId` 幂等 upsert 到 `gateway_users`。
|
||||
- `status=disabled/locked/deleted` 后,Gateway 应拒绝创建新任务;已运行任务按任务策略快照继续或由管理员取消。
|
||||
- 用户角色以主服务返回为准,但 Gateway 可以叠加本地管理角色,二者需要在 `auth_profile` 或 `metadata` 里可审计。
|
||||
- 用户组关系可以随用户同步一起带,也可以通过用户组同步接口单独维护,最终都落到 `gateway_user_group_memberships`。
|
||||
|
||||
### 1.5 用户组与折扣策略同步
|
||||
|
||||
用户组是跨服务策略:Gateway 需要按用户组执行模型调用折扣、TPM/RPM/并发、队列优先级;`server-main` 需要按用户组执行充值折扣、资源包赠送、余额流水。两边必须保持同一个 `groupKey`。
|
||||
|
||||
建议新增同步接口:
|
||||
|
||||
```http
|
||||
POST /internal/platform/user-groups/sync
|
||||
Authorization: Bearer ${SERVER_MAIN_INTERNAL_TOKEN}
|
||||
Content-Type: application/json
|
||||
Idempotency-Key: ${groupKey}:${version}
|
||||
```
|
||||
|
||||
请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"groupKey": "enterprise",
|
||||
"name": "企业组",
|
||||
"rechargeDiscountPolicy": {
|
||||
"type": "tiered_bonus",
|
||||
"tiers": [{ "minAmount": 1000, "bonusRatio": 0.12 }]
|
||||
},
|
||||
"billingDiscountPolicy": {
|
||||
"defaultDiscountFactor": 0.9
|
||||
},
|
||||
"rateLimitPolicy": {
|
||||
"rules": [
|
||||
{ "metric": "rpm", "limit": 1200, "windowSeconds": 60 },
|
||||
{ "metric": "concurrent", "limit": 50, "leaseTtlSeconds": 900 }
|
||||
]
|
||||
},
|
||||
"memberships": [
|
||||
{ "principalType": "user", "principalId": "user-id" },
|
||||
{ "principalType": "tenant", "principalId": "tenant-id" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- `server-main` 是充值、余额和订单事实源,负责执行 `rechargeDiscountPolicy`。
|
||||
- Gateway 是模型执行事实源,负责执行 `billingDiscountPolicy`、`rateLimitPolicy`、队列和并发策略。
|
||||
- 用户登录 / API Key 校验返回 claim 时,建议带上命中的 `userGroupKey` / `userGroupId`;Gateway 也可以根据同步缓存二次解析。
|
||||
|
||||
### 1.6 任务进度回调到 server-main
|
||||
|
||||
AI Gateway 不直接替换原业务前端 WebSocket 通道。Gateway 配置任务进度回调地址,所有任务中间状态先写入 Gateway 本地事件表和 callback outbox,再回调给 `server-main`,由 `server-main` 内部推送流程复用原 WebSocket 网关推送给业务前端。
|
||||
|
||||
```http
|
||||
POST /internal/platform/task-progress-callbacks
|
||||
Authorization: Bearer ${SERVER_MAIN_INTERNAL_TOKEN}
|
||||
Content-Type: application/json
|
||||
Idempotency-Key: ${taskId}:${seq}
|
||||
X-EasyAI-Event-Type: task.progress
|
||||
```
|
||||
|
||||
请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"eventId": "uuid",
|
||||
"taskId": "gateway-task-id",
|
||||
"externalTaskId": "server-main-task-id",
|
||||
"userId": "user-id",
|
||||
"tenantId": "tenant-id",
|
||||
"apiKeyId": "optional",
|
||||
"kind": "images.generations",
|
||||
"model": "gpt-image-1",
|
||||
"seq": 12,
|
||||
"event": "progress",
|
||||
"status": "running",
|
||||
"phase": "polling",
|
||||
"progress": 0.42,
|
||||
"message": "Generating video frames",
|
||||
"payload": {},
|
||||
"createdAt": "2026-05-09T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
`server-main` 处理要求:
|
||||
|
||||
- 使用 `Idempotency-Key` 或 `taskId + seq` 幂等去重。
|
||||
- 根据 `externalTaskId` / `taskId` / `userId` / `tenantId` 定位原业务频道。
|
||||
- 复用现有 WebSocket 网关事件格式推给前端,尽量不改业务前端订阅协议。
|
||||
- 只负责推送与必要状态同步,不重新执行任务、不重新计算计费。
|
||||
|
||||
Gateway 侧配置:
|
||||
|
||||
```env
|
||||
TASK_PROGRESS_CALLBACK_ENABLED=true
|
||||
TASK_PROGRESS_CALLBACK_URL=http://easyai-server-main:3000/internal/platform/task-progress-callbacks
|
||||
TASK_PROGRESS_CALLBACK_TIMEOUT_MS=5000
|
||||
TASK_PROGRESS_CALLBACK_MAX_ATTEMPTS=10
|
||||
```
|
||||
|
||||
### 1.7 结算事件
|
||||
|
||||
```http
|
||||
POST /internal/platform/settlements
|
||||
@@ -66,6 +246,7 @@ Idempotency-Key: ${eventId}
|
||||
AI_GATEWAY_ENABLED=true
|
||||
AI_GATEWAY_BASE_URL=http://easyai-ai-gateway:8088
|
||||
AI_GATEWAY_INTERNAL_TOKEN=change-me
|
||||
AI_GATEWAY_TASK_PROGRESS_CALLBACK_ENABLED=true
|
||||
```
|
||||
|
||||
## 3. 迁移期双写与比对
|
||||
@@ -81,7 +262,7 @@ AI_GATEWAY_INTERNAL_TOKEN=change-me
|
||||
|
||||
- `refresh_token` 签发和刷新。
|
||||
- 用户余额查询。
|
||||
- 用户 API Key 的创建、撤销、列表。
|
||||
- 账单锁、扣费流水。
|
||||
- `server-main` 用户 API Key 的创建、撤销、列表。Gateway 独立模式会维护自己的本地 API Key。
|
||||
- `server-main` 账单锁、扣费流水。Gateway 独立模式会维护自己的钱包账户、充值订单和钱包流水。
|
||||
- OSS/COS/S3 上传配置和实际文件落库。
|
||||
- 对话与绘图历史最终落库。
|
||||
|
||||
Reference in New Issue
Block a user