Skip to content

Commit d959775

Browse files
dengzhaofunclaude
andauthored
Add fumadocs developer documentation with unified theme system (#10)
Integrate fumadocs (fumadocs-core, fumadocs-mdx, fumadocs-ui) into the admin TanStack Start app for developer-facing module docs. Write comprehensive documentation for all modules: authentication, check-in, exchange, item, and TypeScript SDK. Unify theme management around next-themes (via fumadocs RootProvider): - Replace custom DOM-based ThemeToggle with next-themes useTheme() hook - Align CSS dark mode selectors to .dark class (was [data-theme="dark"]) - Add blocking head script for FOUC prevention - Fix prose dark mode contrast with fumadocs fd-* variable overrides - Fix shiki code block color collision in dark mode Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4fffdd0 commit d959775

19 files changed

Lines changed: 3298 additions & 133 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,6 @@ yarn-error.log*
4040
# Cloudflare
4141
.dev.vars
4242
.wrangler
43+
44+
# Fumadocs MDX (auto-generated)
45+
.source
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
---
2+
title: 认证与凭证
3+
description: 管理端认证、API 密钥、客户端凭证与 HMAC 身份验证
4+
---
5+
6+
ApolloKit 有两套认证体系:**管理端认证**(面向 SaaS 运营方)和**客户端凭证**(面向终端用户请求)。
7+
8+
## 管理端认证
9+
10+
### Session 认证
11+
12+
管理端 Web 控制台使用 Better Auth 的 Session Cookie 认证。登录后请求自动携带 `Cookie: auth-token=...`
13+
14+
Session 中包含 `activeOrganizationId`,所有业务操作自动限定在当前组织范围内。
15+
16+
### Admin API Key
17+
18+
组织可以生成 Admin API Key(前缀 `ak_`)用于程序化访问管理端 API。
19+
20+
```http
21+
GET /api/check-in/configs
22+
Authorization: Bearer ak_your_api_key_here
23+
```
24+
25+
Admin API Key 拥有与 Session 认证等同的权限,适用于 CI/CD、脚本、后端服务对接等场景。
26+
27+
---
28+
29+
## 客户端凭证 (Client Credentials)
30+
31+
客户端凭证用于终端用户请求(如签到、兑换、查询背包等)。每对凭证包含:
32+
33+
- **Publishable Key** (`cpk_*`): 可公开的标识符,放在请求头 `x-api-key`
34+
- **Secret** (`csk_*`): 仅在创建/轮换时返回一次,用于计算 HMAC
35+
36+
### 认证流程
37+
38+
所有客户端 API(`/api/client/*`)需要:
39+
40+
```http
41+
POST /api/client/check-in/check-ins
42+
x-api-key: cpk_your_publishable_key
43+
Content-Type: application/json
44+
45+
{
46+
"configKey": "daily_login",
47+
"endUserId": "user-42",
48+
"userHash": "hmac_sha256_hex_string"
49+
}
50+
```
51+
52+
### HMAC 身份验证
53+
54+
为防止终端用户伪造身份,客户端请求需携带 HMAC 签名:
55+
56+
```
57+
userHash = HMAC-SHA256(endUserId, secret)
58+
```
59+
60+
- **POST 请求**: `userHash` 放在请求体中
61+
- **GET 请求**: `x-user-hash` 放在请求头中
62+
63+
```http
64+
GET /api/client/item/users/user-42/inventory
65+
x-api-key: cpk_your_publishable_key
66+
x-user-hash: a1b2c3d4e5f6...
67+
```
68+
69+
### 开发模式 (Dev Mode)
70+
71+
凭证开启 `devMode` 后跳过 HMAC 验证,方便本地开发调试。**生产环境务必关闭。**
72+
73+
---
74+
75+
## 凭证管理 API
76+
77+
### 创建凭证
78+
79+
```http
80+
POST /api/client-credentials/
81+
Authorization: Bearer ak_...
82+
Content-Type: application/json
83+
84+
{
85+
"name": "Production Keys",
86+
"expiresAt": "2027-01-01T00:00:00.000Z",
87+
"metadata": {}
88+
}
89+
```
90+
91+
**响应** (201):
92+
93+
```json
94+
{
95+
"id": "uuid",
96+
"name": "Production Keys",
97+
"publishableKey": "cpk_abc123...",
98+
"secret": "csk_xyz789...",
99+
"devMode": false,
100+
"enabled": true,
101+
"expiresAt": "2027-01-01T00:00:00.000Z",
102+
"createdAt": "2026-01-01T00:00:00.000Z"
103+
}
104+
```
105+
106+
> **Secret 仅在创建时返回一次**,请妥善保存。
107+
108+
### 列出凭证
109+
110+
```http
111+
GET /api/client-credentials/
112+
```
113+
114+
响应中不包含 Secret。
115+
116+
### 轮换密钥
117+
118+
```http
119+
POST /api/client-credentials/{id}/rotate
120+
```
121+
122+
生成新的 `publishableKey``secret`,旧密钥立即失效。
123+
124+
### 吊销凭证
125+
126+
```http
127+
POST /api/client-credentials/{id}/revoke
128+
```
129+
130+
软吊销,将 `enabled` 设为 `false`。使用该密钥的请求将返回 401。
131+
132+
### 切换开发模式
133+
134+
```http
135+
PATCH /api/client-credentials/{id}/dev-mode
136+
Content-Type: application/json
137+
138+
{
139+
"devMode": true
140+
}
141+
```
142+
143+
### 删除凭证
144+
145+
```http
146+
DELETE /api/client-credentials/{id}
147+
```
148+
149+
永久删除,不可恢复。
150+
151+
---
152+
153+
## HMAC 计算示例
154+
155+
### Node.js
156+
157+
```typescript
158+
import { createHmac } from 'crypto';
159+
160+
const secret = 'csk_your_secret';
161+
const endUserId = 'user-42';
162+
const userHash = createHmac('sha256', secret)
163+
.update(endUserId)
164+
.digest('hex');
165+
```
166+
167+
### Python
168+
169+
```python
170+
import hmac, hashlib
171+
172+
secret = b'csk_your_secret'
173+
end_user_id = b'user-42'
174+
user_hash = hmac.new(secret, end_user_id, hashlib.sha256).hexdigest()
175+
```
176+
177+
### Go
178+
179+
```go
180+
import (
181+
"crypto/hmac"
182+
"crypto/sha256"
183+
"encoding/hex"
184+
)
185+
186+
func computeHash(secret, endUserId string) string {
187+
mac := hmac.New(sha256.New, []byte(secret))
188+
mac.Write([]byte(endUserId))
189+
return hex.EncodeToString(mac.Sum(nil))
190+
}
191+
```

0 commit comments

Comments
 (0)