Skip to content

Commit c11b0ad

Browse files
earayuBryceclaude
authored
docs(zh-CN): tasks #10 + #12 + #15 — Phase 4 domains consolidated + admin-guide + integration + web-access (#1643)
* docs(zh-CN): admin-guide/api-keys.md (task #15) First doc in Bryce lane parallel claim (tasks #10/#11/#12/#15 per PM msg=eebfbd82). Covers API Key admin operations: create/rotate/revoke/query + cross-domain rationale (governance vs identity). Technical details cross-ref to architecture/identity-governance-model-platform-marketplace.md. Baseline: origin/main @ 10cabcf (post PR #1637 blueprint merge). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(zh-CN): task #15 + task #12 admin-guide + integration trio - admin-guide/audit-log.md: AuditLog ORM + query interfaces + G15 literal compare admin check + UserView Protocol cross-ref - admin-guide/quota-system.md: UserQuota + per-user limit/usage + recalculate + system default + quota_service permanent DI seam note - integration/openai-compat.md: POST /chat/completions endpoint + bot_id/chat_id/language query params + stream vs non-stream + SDK examples + known incompat Per PM msg=dc3fa008 priority order audit-log -> quota-system -> openai-compat. * docs(zh-CN): architecture/web-access.md (task #12) - web_access domain scope: no ORM, 2 sub-packages (search + reader) - routes mounted at /api/v2 prefix (web/search + web/read) - provider abstraction: DuckDuckGo/Jina (search), Trafilatura/Jina (read) - soft-fail semantics on search; consumer list (KB document_service, MCP) - local AuthenticatedUser Protocol (only id) — G16 honors - Phase 2a hard-cut schema relocation + OpenAPI byte-stable note * docs(zh-CN): architecture/identity-governance-model-platform-marketplace.md (task #10) Consolidated 4-domain (Phase 4) architecture doc: - identity: User/OAuthAccount/Role ORM + ports (AuthenticatedUser + 3 *InitOps) + UserManager.on_after_register + identity_user_ops (User write facade, lesson 9a-sexdec terminal) - governance: ApiKey/AuditLog ORM + UserView Protocol + G15 literal-compare admin - model_platform: LLMProvider/LLMProviderModel + 2-router split (llm_routes v1 + providers_v2) - marketplace: CollectionMarketplace/UserCollectionSubscription + Q2 public rename check_marketplace_access Cross-cutting: 14 per-domain AuthenticatedUser Protocol rationale, G15/G16/G17 gate catalog, Invitation class-body Role exception, G17=7 entries (3 identity adapters + 4 KB), legacy shim map (Phase 7+ candidates), cross-ref to SSoT docs/modularization/architecture.md. Baseline: origin/main @ 28a9f53. * docs(zh-CN): task #15 last doc + Weston IA small fixes - user-guide/collection-marketplace.md (task #15): owner publish/unpublish + subscriber subscribe/unsubscribe + read-only access paths + permission matrix - admin-guide/_category.yaml: title 管理指南 / position 4 (8-category IA per rewrite-plan Section 3) - architecture/identity-governance-model-platform-marketplace.md: degrade Markdown link to ./indexing-retrieval-kg.md → plain code path + 起稿中 (Weston msg=450030a1 item 2, A-pattern per PR #1640) - architecture/web-access.md: same link degrade All Weston PR #1643 scoped IA fixes (msg=450030a1) applied. task #10 / #12 / #15 ready for merge per PM msg=73fc0969. --------- Co-authored-by: Bryce <bryce@apecloud.local> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent c75a739 commit c11b0ad

8 files changed

Lines changed: 1811 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
title: 管理指南
2+
position: 4

docs/zh-CN/admin-guide/api-keys.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# API Key 管理
2+
3+
> **读者定位**:ApeRAG 系统管理员 / 高级用户。
4+
>
5+
> **范围**:API Key 的创建、轮换、查询、吊销 admin 操作。技术面(ORM / 服务层 / DI)见 [`architecture/identity-governance-model-platform-marketplace.md`](../architecture/identity-governance-model-platform-marketplace.md) 的 governance 章节。
6+
7+
## 概述
8+
9+
API Key 是 ApeRAG 提供的程序化访问凭证,与 fastapi-users 的 Cookie 会话认证并存:
10+
11+
- **人工访问**:Web UI / Cookie 认证(登录态)
12+
- **程序化访问**:API Key(`Authorization: Bearer sk-...`
13+
14+
所有通过 API Key 发起的 HTTP 请求会被映射到 key 所属用户身份,权限与该用户一致。API Key 不可跨用户共享。
15+
16+
## 实体模型(管理员视角)
17+
18+
API Key 由 governance 域拥有,字段要点:
19+
20+
| 字段 | 含义 | 说明 |
21+
| --- | --- | --- |
22+
| `id` | Key 记录主键 | 形如 `keyXXXX...`,由系统生成 |
23+
| `key` | Bearer Token 明文 | 形如 `sk-<32 位十六进制>`,仅创建时返回给用户,后续仅保存在数据库 |
24+
| `user` | 所属用户 ID | 对应 identity 域的 `User.id` |
25+
| `description` | 备注 | 可选 |
26+
| `status` | 状态 | `ACTIVE` / `DELETED`(软删除) |
27+
| `is_system` | 是否系统生成 | 区分用户自建与系统内部使用的 key |
28+
| `last_used_at` | 最近一次使用时间 | 便于发现闲置 key |
29+
| `gmt_created` / `gmt_updated` / `gmt_deleted` | 审计时间戳 | 软删除不物理移除记录 |
30+
31+
## 常见管理操作
32+
33+
### 查询某个用户的所有 API Key
34+
35+
```http
36+
GET /api/v1/apikeys
37+
Authorization: Bearer sk-<admin-key>
38+
```
39+
40+
返回的列表中,管理员默认只能看到自己的 key。若需跨用户查询,走审计日志(见 [audit-log.md](./audit-log.md))。
41+
42+
### 创建 API Key
43+
44+
```http
45+
POST /api/v1/apikeys
46+
Content-Type: application/json
47+
Authorization: Bearer sk-<owner-key>
48+
49+
{
50+
"description": "CI runner for apecloud/aperag"
51+
}
52+
```
53+
54+
响应会包含一次性的 `key` 明文(形如 `sk-xxxxxxxxxxxx...`)。
55+
56+
> ⚠️ **只会返回这一次**。保存到 CI / 密钥管理器后再也取不回。如果丢失,必须走「吊销 + 重建」流程,不要考虑明文恢复。
57+
58+
### 更新备注
59+
60+
```http
61+
PUT /api/v1/apikeys/{apikey_id}
62+
Content-Type: application/json
63+
64+
{
65+
"description": "rotated 2026-04 per security policy"
66+
}
67+
```
68+
69+
只能改 `description`。如果要换 token,请参考下面的「轮换(rotate)」节。
70+
71+
### 吊销(软删除)
72+
73+
```http
74+
DELETE /api/v1/apikeys/{apikey_id}
75+
```
76+
77+
此操作会:
78+
79+
1.`status` 置为 `DELETED`,填写 `gmt_deleted`
80+
2. 之后使用该 token 的所有请求都会被拒绝(401)
81+
3. **不会**清除 `key` 字段,便于事后审计追溯哪个 token 曾发起过什么操作
82+
4. 审计日志中的历史记录保留
83+
84+
## 轮换(rotate)
85+
86+
ApeRAG 目前没有原子化的「保留 id、换 token」接口。推荐的轮换步骤:
87+
88+
1. `POST /apikeys`:创建新 key(得到新 `sk-...`
89+
2. 将新 key 分发到调用方(CI、外部系统)
90+
3. 观察几天,确认旧 key 不再产生流量(通过 `last_used_at` 或审计日志)
91+
4. `DELETE /apikeys/{old_id}`:吊销旧 key
92+
93+
建议将轮换写进组织的安全 playbook,不依赖内存。
94+
95+
## 系统生成的 API Key
96+
97+
`is_system = true` 的 API Key 是 ApeRAG 内部为其他能力自动签发的凭证(例如某些一次性工具流)。这些 key:
98+
99+
- **不应被人工吊销**,否则会影响系统功能
100+
- 通常没有 `description`,但会绑定明确的 `user`
101+
- 在管理员查询接口中会显式标出 `is_system`
102+
103+
## 跨 domain 边界(为什么 API Key 属于 governance 不属于 identity)
104+
105+
从概念上,API Key 是「某个用户的访问凭证」;但在 ApeRAG 12 域模型里,它归 **governance** 域而非 **identity** 域,原因是:
106+
107+
- `identity` 域管理「谁是谁」(User / Role / OAuthAccount)
108+
- `governance` 域管理「谁在什么时间做了什么」(API Key / Audit Log / Audit Resource)
109+
110+
API Key 更接近 **访问凭证 + 操作归属**,语义上和审计日志同源,因此在 Phase 4 模块化重构中归 governance 域(`aperag/domains/governance/db/models.py`)。
111+
112+
跨域读侧通过 `governance.ports.UserView` 读取 `User.username` 等展示字段,不持有 `User` ORM 实例(遵守 G16 边界规则,详见 architecture 章节)。
113+
114+
## 相关文档
115+
116+
- [`architecture/identity-governance-model-platform-marketplace.md`](../architecture/identity-governance-model-platform-marketplace.md) — governance 域架构实现 + `UserView` Protocol
117+
- [`admin-guide/audit-log.md`](./audit-log.md) — 审计日志查询
118+
- [`reference/prompt-api.md`](../reference/prompt-api.md) — 示例 API 调用
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# 审计日志(Audit Log)
2+
3+
> **读者定位**:ApeRAG 系统管理员(`role == "admin"`)、SRE、合规审计人员。
4+
>
5+
> **范围**:审计日志的数据模型、查询接口、权限边界、敏感字段过滤。架构层实现细节见 [`architecture/identity-governance-model-platform-marketplace.md`](../architecture/identity-governance-model-platform-marketplace.md) 的 governance 章节。
6+
7+
## 概述
8+
9+
`AuditLog` 记录系统里所有**变更类 HTTP 操作**(POST / PUT / DELETE)的执行痕迹,用于:
10+
11+
- 事后追溯("这条数据是谁、什么时候、通过什么请求改掉的")
12+
- 异常排查(HTTP 4xx / 5xx 的请求体、响应体、错误信息)
13+
- 安全合规(接入点、IP、User-Agent、Request ID 关联)
14+
15+
审计日志由 `@audit(resource_type=..., api_name=...)` 装饰器自动写入,业务 handler 无需手动调用。装饰器实现位于 `aperag/utils/audit_decorator.py`,服务层位于 `aperag/domains/governance/service/audit_service.py`
16+
17+
## 数据模型
18+
19+
`AuditLog` 实体(`aperag/domains/governance/db/models.py`)字段:
20+
21+
| 字段 | 类型 | 说明 |
22+
| --- | --- | --- |
23+
| `id` | UUID 字符串 | 主键 |
24+
| `user_id` | 字符串,可空 | 操作者用户 ID(匿名接口可能为空) |
25+
| `username` | 字符串,可空 | 操作者用户名(冗余存储,避免 join) |
26+
| `resource_type` | `AuditResource` 枚举 | 见下节枚举列表 |
27+
| `resource_id` | 字符串 |`path` 中解析出来的资源 ID(查询时解析,不在写入时落库) |
28+
| `api_name` | 字符串 |`@audit` 装饰器传入,形如 `CreateCollection` |
29+
| `http_method` | 字符串 | `POST` / `PUT` / `DELETE`|
30+
| `path` | 字符串 | 请求路径(如 `/api/v1/collections/col-abc123`|
31+
| `status_code` | 整数 | HTTP 响应码 |
32+
| `request_data` | JSON 字符串 | 请求体,敏感字段已过滤 |
33+
| `response_data` | JSON 字符串 | 响应体,敏感字段已过滤 |
34+
| `error_message` | 字符串 | 失败时保留异常信息 |
35+
| `ip_address` | 字符串 | 客户端 IP |
36+
| `user_agent` | 字符串 | 浏览器 / CLI 标识 |
37+
| `request_id` | 字符串 | 用于跨服务 trace 关联 |
38+
| `start_time` / `end_time` | 毫秒时间戳 | `end_time - start_time` 即耗时 |
39+
| `gmt_created` | 时间戳 | 落库时间 |
40+
41+
### AuditResource 枚举
42+
43+
写入的资源类型由 `@audit(resource_type="...")` 传入,取值必须在 `AuditResource` 枚举内:
44+
45+
`collection` / `document` / `bot` / `chat` / `message` / `api_key` / `llm_provider` / `llm_provider_model` / `model_service_provider` / `user` / `config` / `invitation` / `auth` / `chat_completion` / `search` / `llm` / `flow` / `system` / `index`
46+
47+
## 敏感字段过滤
48+
49+
写入前,`audit_service` 会递归扫描 `request_data` / `response_data`,将以下字段名(忽略大小写)的值替换为 `***FILTERED***`
50+
51+
`password` / `token` / `api_key` / `secret` / `authorization` / `access_token` / `refresh_token` / `private_key` / `credential`
52+
53+
> 注意:过滤基于**字段名子串匹配**,不会扫描字段值本身。若自定义字段需要脱敏,用上面任一关键词命名即可(例如 `oauth_token`)。
54+
55+
## 查询接口
56+
57+
### 列表查询
58+
59+
```http
60+
GET /api/v1/audit-logs
61+
Authorization: Bearer sk-<admin-key>
62+
```
63+
64+
支持的 query 参数:
65+
66+
| 参数 | 说明 |
67+
| --- | --- |
68+
| `user_id` | 按用户 ID 过滤。**非 admin 时该参数被忽略,强制回填为当前用户** |
69+
| `username` | 按用户名过滤 |
70+
| `resource_type` | 任一 `AuditResource` 枚举值 |
71+
| `resource_id` | 资源 ID 精确匹配 |
72+
| `api_name` | API 操作名精确匹配 |
73+
| `http_method` | `POST` / `PUT` / `DELETE` |
74+
| `status_code` | HTTP 响应码精确匹配 |
75+
| `start_date` / `end_date` | ISO-8601 时间区间 |
76+
| `page` / `page_size` | 分页,默认 `page=1` / `page_size=20``page_size` 上限 100 |
77+
| `sort_by` / `sort_order` | 排序字段 + `asc` / `desc`,默认按时间倒序 |
78+
| `search` | 模糊搜索(在 api_name / path 上做 LIKE) |
79+
80+
### 单条查询
81+
82+
```http
83+
GET /api/v1/audit-logs/{audit_id}
84+
```
85+
86+
返回完整的 `AuditLog` + 运行时计算的 `resource_id`(从 `path` 正则提取)和 `duration_ms`
87+
88+
### 权限规则
89+
90+
```
91+
if user.role == "admin":
92+
# 可见所有人的日志
93+
pass
94+
else:
95+
# 强制只看自己的日志,忽略 user_id / username 参数
96+
filter_user_id = user.id
97+
```
98+
99+
该 literal 比较**不依赖** identity 域的 `Role` 枚举(G15 边界规则 — governance 域不能 import `Role`)。admin 角色名以字符串 `"admin"` 写死在 governance handler 里。
100+
101+
## 常见管理场景
102+
103+
### 追溯某个知识库被谁删除
104+
105+
```http
106+
GET /api/v1/audit-logs?resource_type=collection&api_name=DeleteCollection&page_size=100
107+
```
108+
109+
按时间倒序扫,结合 `resource_id`(会从 `/collections/{id}` 中解析出来)定位目标记录,记录中的 `user_id` + `username` + `ip_address` 即操作者身份。
110+
111+
### 排查 5xx 错误
112+
113+
```http
114+
GET /api/v1/audit-logs?status_code=500&start_date=2026-04-20T00:00:00Z
115+
```
116+
117+
返回结果中的 `error_message` 字段会保留异常 repr;`request_id` 可以在日志系统中 grep 到完整调用栈。
118+
119+
### 统计 API 调用量
120+
121+
```http
122+
GET /api/v1/audit-logs?api_name=CreateChatCompletion&start_date=2026-04-01T00:00:00Z
123+
```
124+
125+
后端目前只提供 listing,不直接提供 aggregation 接口。如果要做 per-day / per-user 的统计报表,需要从 AuditLog 表直接跑 SQL(或者把表同步到 OLAP)。
126+
127+
### 查看某个用户的近期活动
128+
129+
```http
130+
GET /api/v1/audit-logs?user_id=<uid>&page_size=50
131+
```
132+
133+
admin 视角可以看任何用户;普通用户只能看自己(后端强制覆盖)。
134+
135+
## 保留与清理策略
136+
137+
当前版本没有内置的保留期清理任务。所有 `AuditLog` 记录永久保存在业务数据库中。如需控制表大小:
138+
139+
- **推荐**:把 AuditLog 定期(月 / 季度)导出到冷存储(S3 / 对象存储),然后按保留策略删除。
140+
- 不推荐直接 `DELETE FROM audit_log WHERE gmt_created < ?`,因为会导致合规窗口内的证据缺失;必须在导出归档之后再清。
141+
142+
> 未来可能会提供自动归档 Job,目前先靠运维侧脚本实现。
143+
144+
## 跨 domain 边界(为什么 AuditLog 属于 governance 不属于 identity)
145+
146+
AuditLog 记录"谁在什么时间做了什么",语义上归 **governance** 域。`user_id``username` 字段是冗余存储(不是 FK 到 identity.User),这个选择有两个原因:
147+
148+
1. **审计日志必须在用户被删除后仍然保留**。如果用 FK 关联,用户删除会触发级联或者 SET NULL,污染审计证据。
149+
2. **governance 域不持有 identity.User ORM 实例**(G16 边界规则)。governance 读侧若需要展示 `username` 等识别信息,走 `governance.ports.UserView` Protocol,由 identity 域在启动时注入。
150+
151+
详见 [`architecture/identity-governance-model-platform-marketplace.md`](../architecture/identity-governance-model-platform-marketplace.md) governance 章节。
152+
153+
## 相关文档
154+
155+
- [`admin-guide/api-keys.md`](./api-keys.md) — API Key 管理(同属 governance 域)
156+
- [`architecture/identity-governance-model-platform-marketplace.md`](../architecture/identity-governance-model-platform-marketplace.md) — governance 域架构
157+
- `docs/modularization/architecture.md` — 12 域 canonical SSoT(boundary gates / UserView Protocol / G15 literal compare 规则)

0 commit comments

Comments
 (0)