@downcity/city 0.2.200 → 0.2.211
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -13
- package/bin/client/bureau.d.ts +41 -0
- package/bin/client/bureau.d.ts.map +1 -0
- package/bin/client/bureau.js +240 -0
- package/bin/client/bureau.js.map +1 -0
- package/bin/client/city.d.ts +15 -79
- package/bin/client/city.d.ts.map +1 -1
- package/bin/client/city.js +15 -99
- package/bin/client/city.js.map +1 -1
- package/bin/client/federation-admin.d.ts +32 -0
- package/bin/client/federation-admin.d.ts.map +1 -0
- package/bin/client/federation-admin.js +54 -0
- package/bin/client/federation-admin.js.map +1 -0
- package/bin/client/types.d.ts +10 -70
- package/bin/client/types.d.ts.map +1 -1
- package/bin/client/types.js +3 -3
- package/bin/federation/auth/authenticator.d.ts +17 -13
- package/bin/federation/auth/authenticator.d.ts.map +1 -1
- package/bin/federation/auth/authenticator.js +38 -27
- package/bin/federation/auth/authenticator.js.map +1 -1
- package/bin/federation/auth/bureau-token-schema.d.ts +274 -0
- package/bin/federation/auth/bureau-token-schema.d.ts.map +1 -0
- package/bin/federation/auth/bureau-token-schema.js +43 -0
- package/bin/federation/auth/bureau-token-schema.js.map +1 -0
- package/bin/federation/auth/bureau-token-store.d.ts +22 -0
- package/bin/federation/auth/bureau-token-store.d.ts.map +1 -0
- package/bin/federation/auth/bureau-token-store.js +122 -0
- package/bin/federation/auth/bureau-token-store.js.map +1 -0
- package/bin/federation/auth/federation-key-store.d.ts +26 -0
- package/bin/federation/auth/federation-key-store.d.ts.map +1 -0
- package/bin/federation/auth/federation-key-store.js +96 -0
- package/bin/federation/auth/federation-key-store.js.map +1 -0
- package/bin/federation/auth/key-schema.d.ts +275 -0
- package/bin/federation/auth/key-schema.d.ts.map +1 -0
- package/bin/federation/auth/key-schema.js +44 -0
- package/bin/federation/auth/key-schema.js.map +1 -0
- package/bin/federation/auth/types.d.ts +62 -4
- package/bin/federation/auth/types.d.ts.map +1 -1
- package/bin/federation/auth/user-token-authority.d.ts +26 -0
- package/bin/federation/auth/user-token-authority.d.ts.map +1 -0
- package/bin/federation/auth/user-token-authority.js +179 -0
- package/bin/federation/auth/user-token-authority.js.map +1 -0
- package/bin/federation/federation-init.d.ts.map +1 -1
- package/bin/federation/federation-init.js +23 -4
- package/bin/federation/federation-init.js.map +1 -1
- package/bin/federation/federation-router.d.ts +3 -1
- package/bin/federation/federation-router.d.ts.map +1 -1
- package/bin/federation/federation-router.js +17 -0
- package/bin/federation/federation-router.js.map +1 -1
- package/bin/federation/federation-runtime.d.ts.map +1 -1
- package/bin/federation/federation-runtime.js +14 -2
- package/bin/federation/federation-runtime.js.map +1 -1
- package/bin/federation/federation.d.ts.map +1 -1
- package/bin/federation/federation.js +2 -0
- package/bin/federation/federation.js.map +1 -1
- package/bin/federation/runtime.d.ts +4 -0
- package/bin/federation/runtime.d.ts.map +1 -1
- package/bin/index.d.ts +11 -10
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +5 -3
- package/bin/index.js.map +1 -1
- package/bin/pact/admin/index.d.ts +7 -19
- package/bin/pact/admin/index.d.ts.map +1 -1
- package/bin/pact/admin/index.js +10 -18
- package/bin/pact/admin/index.js.map +1 -1
- package/bin/pact/admin/types.d.ts +4 -10
- package/bin/pact/admin/types.d.ts.map +1 -1
- package/bin/pact/invoker/ai/CityModel.d.ts +1 -1
- package/bin/pact/invoker/ai/CityModel.d.ts.map +1 -1
- package/bin/pact/invoker/ai/CityModel.js +3 -65
- package/bin/pact/invoker/ai/CityModel.js.map +1 -1
- package/bin/pact/invoker/ai/types.d.ts +1 -1
- package/bin/pact/invoker/ai/types.js +1 -1
- package/bin/pact/invoker/bureaus/index.d.ts +25 -0
- package/bin/pact/invoker/bureaus/index.d.ts.map +1 -0
- package/bin/pact/invoker/bureaus/index.js +36 -0
- package/bin/pact/invoker/bureaus/index.js.map +1 -0
- package/bin/pact/invoker/cities/types.d.ts +2 -2
- package/bin/pact/invoker/cities/types.d.ts.map +1 -1
- package/bin/pact/invoker/user/index.d.ts +19 -0
- package/bin/pact/invoker/user/index.d.ts.map +1 -0
- package/bin/pact/invoker/user/index.js +24 -0
- package/bin/pact/invoker/user/index.js.map +1 -0
- package/bin/pact/user/index.d.ts +2 -1
- package/bin/pact/user/index.d.ts.map +1 -1
- package/bin/pact/user/index.js +7 -3
- package/bin/pact/user/index.js.map +1 -1
- package/bin/pact/user/types.d.ts +11 -6
- package/bin/pact/user/types.d.ts.map +1 -1
- package/bin/service/ai/AIChannel.d.ts +57 -0
- package/bin/service/ai/AIChannel.d.ts.map +1 -0
- package/bin/service/ai/AIChannel.js +151 -0
- package/bin/service/ai/AIChannel.js.map +1 -0
- package/bin/service/ai/OpenAIChatCompletionsAdapter.d.ts +23 -0
- package/bin/service/ai/OpenAIChatCompletionsAdapter.d.ts.map +1 -0
- package/bin/service/ai/OpenAIChatCompletionsAdapter.js +503 -0
- package/bin/service/ai/OpenAIChatCompletionsAdapter.js.map +1 -0
- package/bin/service/ai/ai-service-values.d.ts +16 -19
- package/bin/service/ai/ai-service-values.d.ts.map +1 -1
- package/bin/service/ai/ai-service-values.js +9 -13
- package/bin/service/ai/ai-service-values.js.map +1 -1
- package/bin/service/ai/ai-service.d.ts +16 -15
- package/bin/service/ai/ai-service.d.ts.map +1 -1
- package/bin/service/ai/ai-service.js +97 -106
- package/bin/service/ai/ai-service.js.map +1 -1
- package/bin/service/ai/helpers.d.ts +8 -35
- package/bin/service/ai/helpers.d.ts.map +1 -1
- package/bin/service/ai/helpers.js +8 -140
- package/bin/service/ai/helpers.js.map +1 -1
- package/bin/service/ai/image-job-store.d.ts +2 -3
- package/bin/service/ai/image-job-store.d.ts.map +1 -1
- package/bin/service/ai/image-job-store.js.map +1 -1
- package/bin/service/ai/language-model-stream.d.ts +9 -4
- package/bin/service/ai/language-model-stream.d.ts.map +1 -1
- package/bin/service/ai/language-model-stream.js +8 -4
- package/bin/service/ai/language-model-stream.js.map +1 -1
- package/bin/service/ai/language-model-text.d.ts +15 -0
- package/bin/service/ai/language-model-text.d.ts.map +1 -0
- package/bin/service/ai/language-model-text.js +67 -0
- package/bin/service/ai/language-model-text.js.map +1 -0
- package/bin/service/ai/model-context-window.d.ts +2 -2
- package/bin/service/ai/model-context-window.d.ts.map +1 -1
- package/bin/service/ai/model-context-window.js.map +1 -1
- package/bin/service/ai/model-registry.d.ts +9 -8
- package/bin/service/ai/model-registry.d.ts.map +1 -1
- package/bin/service/ai/model-registry.js +1 -5
- package/bin/service/ai/model-registry.js.map +1 -1
- package/bin/service/ai/model-routing.d.ts +1 -1
- package/bin/service/ai/model-routing.d.ts.map +1 -1
- package/bin/service/ai/model-routing.js +1 -1
- package/bin/service/ai/model-routing.js.map +1 -1
- package/bin/service/ai/reasoning.d.ts +4 -4
- package/bin/service/ai/reasoning.d.ts.map +1 -1
- package/bin/service/ai/reasoning.js.map +1 -1
- package/bin/service/bureaus/bureaus-service.d.ts +15 -0
- package/bin/service/bureaus/bureaus-service.d.ts.map +1 -0
- package/bin/service/bureaus/bureaus-service.js +55 -0
- package/bin/service/bureaus/bureaus-service.js.map +1 -0
- package/bin/service/installable-service.d.ts +5 -2
- package/bin/service/installable-service.d.ts.map +1 -1
- package/bin/service/installable-service.js +1 -0
- package/bin/service/installable-service.js.map +1 -1
- package/bin/service/instruction.js +1 -1
- package/bin/service/instruction.js.map +1 -1
- package/bin/service/service.d.ts +15 -2
- package/bin/service/service.d.ts.map +1 -1
- package/bin/service/service.js +2 -0
- package/bin/service/service.js.map +1 -1
- package/bin/types/AI.d.ts +289 -0
- package/bin/types/AI.d.ts.map +1 -0
- package/bin/types/AI.js +8 -0
- package/bin/types/AI.js.map +1 -0
- package/bin/types/AITransport.d.ts +251 -0
- package/bin/types/AITransport.d.ts.map +1 -0
- package/bin/types/AITransport.js +12 -0
- package/bin/types/AITransport.js.map +1 -0
- package/bin/types/Bureau.d.ts +96 -0
- package/bin/types/Bureau.d.ts.map +1 -0
- package/bin/types/Bureau.js +8 -0
- package/bin/types/Bureau.js.map +1 -0
- package/bin/types/FederationAdmin.d.ts +16 -0
- package/bin/types/FederationAdmin.d.ts.map +1 -0
- package/bin/types/FederationAdmin.js +7 -0
- package/bin/types/FederationAdmin.js.map +1 -0
- package/bin/types/Metering.d.ts +2 -2
- package/bin/types/Metering.d.ts.map +1 -1
- package/bin/types/User.d.ts +24 -0
- package/bin/types/User.d.ts.map +1 -0
- package/bin/types/User.js +8 -0
- package/bin/types/User.js.map +1 -0
- package/bin/utils/CityLanguageModelCodec.d.ts +1 -1
- package/bin/utils/CityLanguageModelCodec.d.ts.map +1 -1
- package/bin/utils/CityLanguageModelResult.d.ts +11 -0
- package/bin/utils/CityLanguageModelResult.d.ts.map +1 -0
- package/bin/utils/CityLanguageModelResult.js +76 -0
- package/bin/utils/CityLanguageModelResult.js.map +1 -0
- package/package.json +4 -3
- package/bin/federation/auth/token-signer.d.ts +0 -27
- package/bin/federation/auth/token-signer.d.ts.map +0 -1
- package/bin/federation/auth/token-signer.js +0 -116
- package/bin/federation/auth/token-signer.js.map +0 -1
- package/bin/service/ai/charge.d.ts +0 -76
- package/bin/service/ai/charge.d.ts.map +0 -1
- package/bin/service/ai/charge.js +0 -10
- package/bin/service/ai/charge.js.map +0 -1
- package/bin/service/ai/job-types.d.ts +0 -69
- package/bin/service/ai/job-types.d.ts.map +0 -1
- package/bin/service/ai/job-types.js +0 -9
- package/bin/service/ai/job-types.js.map +0 -1
- package/bin/service/ai/provider.d.ts +0 -143
- package/bin/service/ai/provider.d.ts.map +0 -1
- package/bin/service/ai/provider.js +0 -221
- package/bin/service/ai/provider.js.map +0 -1
- package/bin/service/ai/types.d.ts +0 -174
- package/bin/service/ai/types.d.ts.map +0 -1
- package/bin/service/ai/types.js +0 -7
- package/bin/service/ai/types.js.map +0 -1
- package/bin/types/AIImageJobClaim.d.ts +0 -14
- package/bin/types/AIImageJobClaim.d.ts.map +0 -1
- package/bin/types/AIImageJobClaim.js +0 -7
- package/bin/types/AIImageJobClaim.js.map +0 -1
- package/bin/types/AIReasoning.d.ts +0 -25
- package/bin/types/AIReasoning.d.ts.map +0 -1
- package/bin/types/AIReasoning.js +0 -7
- package/bin/types/AIReasoning.js.map +0 -1
- package/bin/types/AIRouting.d.ts +0 -37
- package/bin/types/AIRouting.d.ts.map +0 -1
- package/bin/types/AIRouting.js +0 -7
- package/bin/types/AIRouting.js.map +0 -1
- package/bin/types/CityLanguageModelRuntime.d.ts +0 -46
- package/bin/types/CityLanguageModelRuntime.d.ts.map +0 -1
- package/bin/types/CityLanguageModelRuntime.js +0 -8
- package/bin/types/CityLanguageModelRuntime.js.map +0 -1
- package/bin/types/CityLanguageModelTransport.d.ts +0 -49
- package/bin/types/CityLanguageModelTransport.d.ts.map +0 -1
- package/bin/types/CityLanguageModelTransport.js +0 -9
- package/bin/types/CityLanguageModelTransport.js.map +0 -1
- package/bin/types/CityModelRuntime.d.ts +0 -17
- package/bin/types/CityModelRuntime.d.ts.map +0 -1
- package/bin/types/CityModelRuntime.js +0 -8
- package/bin/types/CityModelRuntime.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- 挂载 `Service` / `AIService`
|
|
8
8
|
- 初始化内置 `cities` / `env` 表
|
|
9
|
-
- 校验 `user_token`
|
|
9
|
+
- 校验 `user_token`、`bureau_token` 和控制面凭证
|
|
10
10
|
- 暴露统一的 `/v1/*` HTTP 路由
|
|
11
11
|
- 提供 env、数据库、hook 和鉴权上下文
|
|
12
12
|
|
|
@@ -114,7 +114,7 @@ console.log(text);
|
|
|
114
114
|
GET /v1/federation/instruction
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
这个接口只允许携带 Federation `admin_secret_key` 的控制面请求访问,返回 `text/plain`。
|
|
118
118
|
|
|
119
119
|
## Service
|
|
120
120
|
|
|
@@ -149,19 +149,37 @@ City 会自动映射为:
|
|
|
149
149
|
`AIService` 负责模型目录和模态路由:
|
|
150
150
|
|
|
151
151
|
```ts
|
|
152
|
-
import {
|
|
152
|
+
import {
|
|
153
|
+
AIChannel,
|
|
154
|
+
AIService,
|
|
155
|
+
type AIChannelStreamInput,
|
|
156
|
+
type LanguageModelV3StreamResult,
|
|
157
|
+
} from "@downcity/city";
|
|
158
|
+
|
|
159
|
+
class DeepSeekChannel extends AIChannel {
|
|
160
|
+
constructor() {
|
|
161
|
+
super({
|
|
162
|
+
id: "deepseek",
|
|
163
|
+
base_url: "https://api.deepseek.com/v1",
|
|
164
|
+
env_key: "DEEPSEEK_API_KEY",
|
|
165
|
+
ai_sdk_provider_id: "deepseek",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
153
168
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
169
|
+
protected stream(
|
|
170
|
+
input: AIChannelStreamInput,
|
|
171
|
+
): Promise<LanguageModelV3StreamResult> {
|
|
172
|
+
return myStreamAction(input);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const deepseek = new DeepSeekChannel();
|
|
160
177
|
|
|
161
178
|
const ai = new AIService();
|
|
162
179
|
ai.use(
|
|
163
180
|
deepseek.model({
|
|
164
181
|
id: "deepseek-v4-flash",
|
|
182
|
+
upstream_model: "deepseek-chat",
|
|
165
183
|
name: "DeepSeek V4 Flash",
|
|
166
184
|
context_window: 128_000,
|
|
167
185
|
}),
|
|
@@ -190,10 +208,67 @@ base.use(usageService());
|
|
|
190
208
|
## 鉴权语义
|
|
191
209
|
|
|
192
210
|
- 默认 action 需要 `user_token`
|
|
193
|
-
- `auth: ["admin"]`
|
|
211
|
+
- `auth: ["admin"]` 只允许携带 Federation `admin_secret_key` 的控制面请求
|
|
194
212
|
- `auth: []` 表示免登录
|
|
195
213
|
|
|
196
|
-
|
|
214
|
+
Federation 首次启动会自动生成并持久化 Ed25519 Key Ring。私钥只用于 Federation
|
|
215
|
+
签发 `user_token`,公开公钥通过以下接口发布:
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
GET /.well-known/downcity.json
|
|
219
|
+
GET /.well-known/jwks.json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
用户侧 `City` 只需要 Federation 地址和登录后获得的 token:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
const city = new City({
|
|
226
|
+
federation_url: "https://fed.example.com",
|
|
227
|
+
user_token,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const profile = await city.user().profile();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
`city_id` 由 Federation 验签后从 token 中读取,客户端不再重复传入。
|
|
234
|
+
|
|
235
|
+
City 直接访问 Federation,不依赖 Bureau。只有产品需要自己的后端能力时,才通过
|
|
236
|
+
`fed bureau token` 登记并部署 Bureau:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
fed bureau token --city city_product
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
命令生成的高熵 `bureau_token` 只显示一次,Federation 数据库只保存 hash。将明文
|
|
243
|
+
配置到 Bureau 所在服务器:
|
|
244
|
+
|
|
245
|
+
```env
|
|
246
|
+
DOWNCITY_FEDERATION_URL=https://fed.example.com
|
|
247
|
+
DOWNCITY_BUREAU_TOKEN=fb_br_xxx.secret
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Bureau 获取绑定的 City 上下文与 JWKS,并在本地识别请求身份:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
const bureau = new Bureau({
|
|
254
|
+
federation_url: "https://fed.example.com",
|
|
255
|
+
bureau_token,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const identity = await bureau.identify(request);
|
|
259
|
+
const profile = await (await bureau.user(request)).profile();
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Federation 管理控制面使用独立的 `FederationAdmin`:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
const admin = new FederationAdmin({
|
|
266
|
+
federation_url: "https://fed.example.com",
|
|
267
|
+
admin_secret_key,
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
await admin.bureaus.list();
|
|
271
|
+
```
|
|
197
272
|
|
|
198
273
|
## 主要导出
|
|
199
274
|
|
|
@@ -202,10 +277,11 @@ base.use(usageService());
|
|
|
202
277
|
- `Service`
|
|
203
278
|
- `ServiceDefinition`
|
|
204
279
|
- `AIService`
|
|
205
|
-
- `
|
|
280
|
+
- `AIChannel`
|
|
206
281
|
- `CityModel`
|
|
207
282
|
- `CityModelDescriptor`
|
|
208
|
-
- `
|
|
283
|
+
- `Bureau`
|
|
284
|
+
- `FederationAdmin`
|
|
209
285
|
- `EnvService`
|
|
210
286
|
- `CitiesService`
|
|
211
287
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bureau 产品后端客户端。
|
|
3
|
+
*
|
|
4
|
+
* Bureau 是某个 City 的可选后端入口:启动时使用 Bureau Token 获取自身
|
|
5
|
+
* City 上下文,运行时使用 Federation 公钥在本地验证 user_token。它不承载
|
|
6
|
+
* Federation 管理能力,也不会把 user_token 发送到在线 identify 接口。
|
|
7
|
+
*/
|
|
8
|
+
import type { BureauContext, BureauFetch, BureauIdentity, BureauOptions } from "../types/Bureau.js";
|
|
9
|
+
import type { UserProfile } from "../types/User.js";
|
|
10
|
+
/** 已通过本地验签的用户后端会话。 */
|
|
11
|
+
export declare class BureauUser {
|
|
12
|
+
private readonly federation_url;
|
|
13
|
+
private readonly user_token;
|
|
14
|
+
private readonly fetcher;
|
|
15
|
+
/** 当前用户身份。 */
|
|
16
|
+
readonly identity: BureauIdentity;
|
|
17
|
+
constructor(identity: BureauIdentity, federation_url: string, user_token: string, fetcher: BureauFetch);
|
|
18
|
+
/** 在线读取 Federation 当前用户 Profile。 */
|
|
19
|
+
profile(): Promise<UserProfile | null>;
|
|
20
|
+
}
|
|
21
|
+
/** Bureau 产品后端客户端。 */
|
|
22
|
+
export declare class Bureau {
|
|
23
|
+
/** 当前 Bureau 绑定的 City ID;首次读取上下文后可用。 */
|
|
24
|
+
get city_id(): string | undefined;
|
|
25
|
+
private readonly federation_url;
|
|
26
|
+
private readonly bureau_token;
|
|
27
|
+
private readonly fetcher;
|
|
28
|
+
private readonly cache_ttl;
|
|
29
|
+
private cache?;
|
|
30
|
+
private refresh_promise?;
|
|
31
|
+
constructor(options: BureauOptions);
|
|
32
|
+
/** 获取当前 Bureau 在 Federation 中注册的可信 City 上下文。 */
|
|
33
|
+
context(): Promise<BureauContext>;
|
|
34
|
+
/** 从 HTTP Request 或 user_token 中本地识别 Federation 用户。 */
|
|
35
|
+
identify(input: Request | string): Promise<BureauIdentity>;
|
|
36
|
+
/** 验证请求并创建一个可读取 Federation 用户数据的会话。 */
|
|
37
|
+
user(input: Request | string): Promise<BureauUser>;
|
|
38
|
+
private get_cache;
|
|
39
|
+
private refresh_cache;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=bureau.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bureau.d.ts","sourceRoot":"","sources":["../../src/client/bureau.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAsBpD,sBAAsB;AACtB,qBAAa,UAAU;IAMnB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAP1B,cAAc;IACd,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;gBAGhC,QAAQ,EAAE,cAAc,EACP,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW;IAKvC,oCAAoC;IAC9B,OAAO,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;CAW7C;AAED,sBAAsB;AACtB,qBAAa,MAAM;IACjB,wCAAwC;IACxC,IAAI,OAAO,IAAI,MAAM,GAAG,SAAS,CAEhC;IAED,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,eAAe,CAAC,CAAuB;gBAEnC,OAAO,EAAE,aAAa;IAUlC,gDAAgD;IAC1C,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IAKvC,uDAAuD;IACjD,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmChE,uCAAuC;IACjC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;YAM1C,SAAS;YAUT,aAAa;CAgC5B"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bureau 产品后端客户端。
|
|
3
|
+
*
|
|
4
|
+
* Bureau 是某个 City 的可选后端入口:启动时使用 Bureau Token 获取自身
|
|
5
|
+
* City 上下文,运行时使用 Federation 公钥在本地验证 user_token。它不承载
|
|
6
|
+
* Federation 管理能力,也不会把 user_token 发送到在线 identify 接口。
|
|
7
|
+
*/
|
|
8
|
+
import { decodeProtectedHeader, importJWK, jwtVerify } from "jose";
|
|
9
|
+
import { httpError } from "../utils/helpers.js";
|
|
10
|
+
import { USER_TOKEN_ALGORITHM } from "../federation/auth/federation-key-store.js";
|
|
11
|
+
import { normalize_user_token, read_user_token_payload } from "../federation/auth/user-token-authority.js";
|
|
12
|
+
const DEFAULT_CACHE_TTL = 5 * 60 * 1000;
|
|
13
|
+
/** 已通过本地验签的用户后端会话。 */
|
|
14
|
+
export class BureauUser {
|
|
15
|
+
federation_url;
|
|
16
|
+
user_token;
|
|
17
|
+
fetcher;
|
|
18
|
+
/** 当前用户身份。 */
|
|
19
|
+
identity;
|
|
20
|
+
constructor(identity, federation_url, user_token, fetcher) {
|
|
21
|
+
this.federation_url = federation_url;
|
|
22
|
+
this.user_token = user_token;
|
|
23
|
+
this.fetcher = fetcher;
|
|
24
|
+
this.identity = identity;
|
|
25
|
+
}
|
|
26
|
+
/** 在线读取 Federation 当前用户 Profile。 */
|
|
27
|
+
async profile() {
|
|
28
|
+
const response = await this.fetcher(`${this.federation_url}/v1/accounts/me`, {
|
|
29
|
+
method: "GET",
|
|
30
|
+
headers: { authorization: `Bearer ${this.user_token}` },
|
|
31
|
+
});
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
throw httpError(response.status, "Federation user profile unavailable");
|
|
34
|
+
}
|
|
35
|
+
const body = await response.json();
|
|
36
|
+
return body.profile ?? null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Bureau 产品后端客户端。 */
|
|
40
|
+
export class Bureau {
|
|
41
|
+
/** 当前 Bureau 绑定的 City ID;首次读取上下文后可用。 */
|
|
42
|
+
get city_id() {
|
|
43
|
+
return this.cache?.context.city_id;
|
|
44
|
+
}
|
|
45
|
+
federation_url;
|
|
46
|
+
bureau_token;
|
|
47
|
+
fetcher;
|
|
48
|
+
cache_ttl;
|
|
49
|
+
cache;
|
|
50
|
+
refresh_promise;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
if (!options || typeof options !== "object") {
|
|
53
|
+
throw new TypeError("Bureau options are required");
|
|
54
|
+
}
|
|
55
|
+
this.federation_url = normalize_federation_url(options.federation_url);
|
|
56
|
+
this.bureau_token = read_required_string(options.bureau_token, "bureau_token");
|
|
57
|
+
this.fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
58
|
+
this.cache_ttl = read_cache_ttl(options.jwks_cache_ttl);
|
|
59
|
+
}
|
|
60
|
+
/** 获取当前 Bureau 在 Federation 中注册的可信 City 上下文。 */
|
|
61
|
+
async context() {
|
|
62
|
+
const context = (await this.get_cache(false)).context;
|
|
63
|
+
return { ...context, capabilities: [...context.capabilities] };
|
|
64
|
+
}
|
|
65
|
+
/** 从 HTTP Request 或 user_token 中本地识别 Federation 用户。 */
|
|
66
|
+
async identify(input) {
|
|
67
|
+
const user_token = typeof input === "string" ? read_token_string(input) : read_request_token(input);
|
|
68
|
+
const normalized_token = normalize_user_token(user_token);
|
|
69
|
+
let cache = await this.get_cache(false);
|
|
70
|
+
let key = find_jwk(cache.jwks, normalized_token);
|
|
71
|
+
if (!key) {
|
|
72
|
+
cache = await this.get_cache(true);
|
|
73
|
+
key = find_jwk(cache.jwks, normalized_token);
|
|
74
|
+
}
|
|
75
|
+
if (!key)
|
|
76
|
+
throw httpError(401, "Unknown token signing key");
|
|
77
|
+
try {
|
|
78
|
+
const public_key = await importJWK(key, USER_TOKEN_ALGORITHM);
|
|
79
|
+
const result = await jwtVerify(normalized_token, public_key, {
|
|
80
|
+
algorithms: [USER_TOKEN_ALGORITHM],
|
|
81
|
+
audience: cache.discovery.user_token_audience,
|
|
82
|
+
issuer: cache.discovery.issuer,
|
|
83
|
+
});
|
|
84
|
+
const payload = read_user_token_payload(result.payload);
|
|
85
|
+
if (payload.city_id !== cache.context.city_id) {
|
|
86
|
+
throw httpError(403, "Token does not belong to this City");
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
user_id: payload.user_id,
|
|
90
|
+
city_id: payload.city_id,
|
|
91
|
+
metadata: payload.metadata ?? {},
|
|
92
|
+
token_id: payload.jti,
|
|
93
|
+
expires_at: payload.exp,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (is_http_error(error))
|
|
98
|
+
throw error;
|
|
99
|
+
throw map_identify_error(error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** 验证请求并创建一个可读取 Federation 用户数据的会话。 */
|
|
103
|
+
async user(input) {
|
|
104
|
+
const user_token = typeof input === "string" ? read_token_string(input) : read_request_token(input);
|
|
105
|
+
const identity = await this.identify(user_token);
|
|
106
|
+
return new BureauUser(identity, this.federation_url, user_token, this.fetcher);
|
|
107
|
+
}
|
|
108
|
+
async get_cache(force_refresh) {
|
|
109
|
+
if (!force_refresh && this.cache && this.cache.expires_at > Date.now())
|
|
110
|
+
return this.cache;
|
|
111
|
+
if (!this.refresh_promise) {
|
|
112
|
+
this.refresh_promise = this.refresh_cache().finally(() => {
|
|
113
|
+
this.refresh_promise = undefined;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return this.refresh_promise;
|
|
117
|
+
}
|
|
118
|
+
async refresh_cache() {
|
|
119
|
+
const discovery = await read_json(this.fetcher, `${this.federation_url}/.well-known/downcity.json`, "Federation discovery unavailable");
|
|
120
|
+
validate_discovery(discovery, this.federation_url);
|
|
121
|
+
const [jwks, context] = await Promise.all([
|
|
122
|
+
read_json(this.fetcher, discovery.jwks_uri, "Federation signing keys unavailable"),
|
|
123
|
+
read_json(this.fetcher, `${this.federation_url}/v1/bureaus/context`, "Bureau context unavailable", { authorization: `Bearer ${this.bureau_token}` }),
|
|
124
|
+
]);
|
|
125
|
+
validate_jwks(jwks);
|
|
126
|
+
validate_context(context);
|
|
127
|
+
const cache = {
|
|
128
|
+
discovery,
|
|
129
|
+
jwks,
|
|
130
|
+
context,
|
|
131
|
+
expires_at: Date.now() + this.cache_ttl,
|
|
132
|
+
};
|
|
133
|
+
this.cache = cache;
|
|
134
|
+
return cache;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function find_jwk(jwks, jwt) {
|
|
138
|
+
const header = decodeProtectedHeader(jwt);
|
|
139
|
+
if (header.alg !== USER_TOKEN_ALGORITHM)
|
|
140
|
+
throw httpError(401, "Invalid user token algorithm");
|
|
141
|
+
const key_id = typeof header.kid === "string" ? header.kid : "";
|
|
142
|
+
if (!key_id)
|
|
143
|
+
throw httpError(401, "Unknown token signing key");
|
|
144
|
+
return jwks.keys.find((key) => key.kid === key_id);
|
|
145
|
+
}
|
|
146
|
+
function read_request_token(request) {
|
|
147
|
+
const authorization = request.headers.get("authorization") ?? "";
|
|
148
|
+
if (!authorization.startsWith("Bearer "))
|
|
149
|
+
throw httpError(401, "Authentication required");
|
|
150
|
+
return read_required_string(authorization.slice("Bearer ".length), "user_token");
|
|
151
|
+
}
|
|
152
|
+
function read_token_string(value) {
|
|
153
|
+
const token = value.trim();
|
|
154
|
+
return read_required_string(token.startsWith("Bearer ") ? token.slice("Bearer ".length) : token, "user_token");
|
|
155
|
+
}
|
|
156
|
+
function normalize_federation_url(value) {
|
|
157
|
+
const input = read_required_string(value, "federation_url").replace(/\/+$/, "");
|
|
158
|
+
const url = new URL(input);
|
|
159
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
160
|
+
throw new TypeError("federation_url must use http or https");
|
|
161
|
+
}
|
|
162
|
+
if (url.username || url.password)
|
|
163
|
+
throw new TypeError("federation_url must not contain credentials");
|
|
164
|
+
return input;
|
|
165
|
+
}
|
|
166
|
+
function validate_discovery(discovery, federation_url) {
|
|
167
|
+
if (!discovery || typeof discovery !== "object")
|
|
168
|
+
throw httpError(503, "Federation discovery unavailable");
|
|
169
|
+
read_required_string(discovery.issuer, "Federation issuer");
|
|
170
|
+
if (discovery.user_token_audience !== "downcity:user")
|
|
171
|
+
throw httpError(503, "Invalid Federation user token audience");
|
|
172
|
+
const expected = new URL(`${federation_url}/.well-known/jwks.json`);
|
|
173
|
+
const actual = new URL(discovery.jwks_uri);
|
|
174
|
+
if (actual.origin !== expected.origin || actual.pathname !== expected.pathname) {
|
|
175
|
+
throw httpError(503, "Invalid Federation JWKS location");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function validate_jwks(jwks) {
|
|
179
|
+
if (!jwks || !Array.isArray(jwks.keys))
|
|
180
|
+
throw httpError(503, "Federation signing keys unavailable");
|
|
181
|
+
for (const key of jwks.keys) {
|
|
182
|
+
if (key.kty !== "OKP" || key.crv !== "Ed25519" || key.alg !== USER_TOKEN_ALGORITHM
|
|
183
|
+
|| key.use !== "sig" || typeof key.kid !== "string" || typeof key.x !== "string") {
|
|
184
|
+
throw httpError(503, "Invalid Federation signing key");
|
|
185
|
+
}
|
|
186
|
+
if ("d" in key)
|
|
187
|
+
throw httpError(503, "Federation JWKS exposed a private key");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function validate_context(context) {
|
|
191
|
+
if (!context || typeof context !== "object")
|
|
192
|
+
throw httpError(503, "Bureau context unavailable");
|
|
193
|
+
read_required_string(context.token_id, "Bureau token_id");
|
|
194
|
+
read_required_string(context.city_id, "Bureau city_id");
|
|
195
|
+
if (!Array.isArray(context.capabilities))
|
|
196
|
+
throw httpError(503, "Invalid Bureau capabilities");
|
|
197
|
+
}
|
|
198
|
+
async function read_json(fetcher, url, error_message, extra_headers = {}) {
|
|
199
|
+
let response;
|
|
200
|
+
try {
|
|
201
|
+
response = await fetcher(url, { headers: { accept: "application/json", ...extra_headers } });
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
throw httpError(503, error_message);
|
|
205
|
+
}
|
|
206
|
+
if (!response.ok)
|
|
207
|
+
throw httpError(response.status === 401 ? 401 : 503, error_message);
|
|
208
|
+
try {
|
|
209
|
+
return await response.json();
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
throw httpError(503, error_message);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function read_required_string(value, name) {
|
|
216
|
+
if (typeof value !== "string" || !value.trim())
|
|
217
|
+
throw new TypeError(`${name} must be a non-empty string`);
|
|
218
|
+
return value.trim();
|
|
219
|
+
}
|
|
220
|
+
function read_cache_ttl(value) {
|
|
221
|
+
if (value === undefined)
|
|
222
|
+
return DEFAULT_CACHE_TTL;
|
|
223
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
224
|
+
throw new TypeError("jwks_cache_ttl must be a positive number");
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
function is_http_error(error) {
|
|
228
|
+
return error instanceof Error && typeof error.statusCode === "number";
|
|
229
|
+
}
|
|
230
|
+
function map_identify_error(error) {
|
|
231
|
+
const code = error && typeof error === "object" ? String(error.code ?? "") : "";
|
|
232
|
+
if (code === "ERR_JWT_EXPIRED")
|
|
233
|
+
return httpError(401, "User token expired");
|
|
234
|
+
if (code === "ERR_JWS_SIGNATURE_VERIFICATION_FAILED")
|
|
235
|
+
return httpError(401, "Invalid user token signature");
|
|
236
|
+
if (code === "ERR_JWT_CLAIM_VALIDATION_FAILED")
|
|
237
|
+
return httpError(401, "Invalid user token claims");
|
|
238
|
+
return httpError(401, "Invalid user token");
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=bureau.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bureau.js","sourceRoot":"","sources":["../../src/client/bureau.ts"],"names":[],"mappings":"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"}
|
package/bin/client/city.d.ts
CHANGED
|
@@ -1,90 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* City
|
|
2
|
+
* City 终端用户客户端。
|
|
3
3
|
*
|
|
4
|
-
* City
|
|
5
|
-
*
|
|
4
|
+
* City 只持有 Federation 地址与可选 user_token。city_id 由 Federation 在服务端
|
|
5
|
+
* 验签后从 token 中读取,客户端不能重复声明或覆盖。
|
|
6
6
|
*/
|
|
7
|
-
import { AdminPactAccess } from "../pact/admin/index.js";
|
|
8
7
|
import { UserPactAccess } from "../pact/user/index.js";
|
|
9
8
|
import type { ServiceClient } from "../pact/invoker/invoker.js";
|
|
10
|
-
import type {
|
|
11
|
-
import type { AdminModelRecord, AdminServiceSummary } from "../pact/admin/types.js";
|
|
9
|
+
import type { CityOptions } from "./types.js";
|
|
12
10
|
import type { UserServiceSummary } from "../pact/user/types.js";
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 当前 City 客户端的访问角色。
|
|
19
|
-
*/
|
|
20
|
-
readonly role: TRole;
|
|
21
|
-
/**
|
|
22
|
-
* Admin 能力面。
|
|
23
|
-
*
|
|
24
|
-
* 仅 `role: "admin"` 时可用。
|
|
25
|
-
*/
|
|
26
|
-
private readonly admin_access?;
|
|
27
|
-
/**
|
|
28
|
-
* User 能力面。
|
|
29
|
-
*
|
|
30
|
-
* 仅 `role: "user"` 时可用。
|
|
31
|
-
*/
|
|
32
|
-
private readonly user_access?;
|
|
33
|
-
constructor(options: CityOptionsForRole<TRole>);
|
|
34
|
-
/**
|
|
35
|
-
* User 角色的 AI 调用入口。
|
|
36
|
-
*/
|
|
11
|
+
/** Downcity City 用户客户端。 */
|
|
12
|
+
export declare class City {
|
|
13
|
+
private readonly user_access;
|
|
14
|
+
constructor(options: CityOptions);
|
|
15
|
+
/** 用户侧 AI 调用入口。 */
|
|
37
16
|
get ai(): UserPactAccess["ai"];
|
|
38
|
-
/**
|
|
39
|
-
* User 角色的支付入口。
|
|
40
|
-
*/
|
|
17
|
+
/** 用户侧支付入口。 */
|
|
41
18
|
get payment(): UserPactAccess["payment"];
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
get balance(): AdminPactAccess["balance"];
|
|
46
|
-
/**
|
|
47
|
-
* Admin 角色的 City 管理入口。
|
|
48
|
-
*/
|
|
49
|
-
get cities(): AdminPactAccess["cities"];
|
|
50
|
-
/**
|
|
51
|
-
* Admin 角色的环境变量服务入口。
|
|
52
|
-
*/
|
|
53
|
-
get env(): AdminPactAccess["env"];
|
|
54
|
-
/**
|
|
55
|
-
* Token 管理入口。
|
|
56
|
-
*
|
|
57
|
-
* 不需要传 city_id,构造时传入的 city_id 会自动注入。
|
|
58
|
-
*/
|
|
59
|
-
get tokens(): {
|
|
60
|
-
apply: (input: {
|
|
61
|
-
user_id: string;
|
|
62
|
-
metadata?: Record<string, unknown>;
|
|
63
|
-
ttl?: string | number;
|
|
64
|
-
}) => Promise<{
|
|
65
|
-
user_token: string;
|
|
66
|
-
city_id: string;
|
|
67
|
-
user_id: string;
|
|
68
|
-
expires_at?: string;
|
|
69
|
-
}>;
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* 获取普通 service 调用器。
|
|
73
|
-
*/
|
|
19
|
+
/** Federation 当前用户数据入口。 */
|
|
20
|
+
user(): UserPactAccess["user"];
|
|
21
|
+
/** 获取普通 Service 调用器。 */
|
|
74
22
|
service(name: string): ServiceClient;
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
*/
|
|
78
|
-
listServices(): Promise<AdminServiceSummary[] | UserServiceSummary[]>;
|
|
79
|
-
/**
|
|
80
|
-
* 列出 Federation 模型目录。
|
|
81
|
-
*/
|
|
82
|
-
listModels(): Promise<AdminModelRecord[]>;
|
|
83
|
-
/**
|
|
84
|
-
* 读取 Federation 聚合说明文档。
|
|
85
|
-
*/
|
|
86
|
-
instruction(): Promise<string>;
|
|
87
|
-
private require_admin;
|
|
88
|
-
private require_user;
|
|
23
|
+
/** 列出 Federation 暴露的 Service。 */
|
|
24
|
+
listServices(): Promise<UserServiceSummary[]>;
|
|
89
25
|
}
|
|
90
26
|
//# sourceMappingURL=city.d.ts.map
|
package/bin/client/city.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"city.d.ts","sourceRoot":"","sources":["../../src/client/city.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"city.d.ts","sourceRoot":"","sources":["../../src/client/city.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,2BAA2B;AAC3B,qBAAa,IAAI;IACf,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiB;gBAEjC,OAAO,EAAE,WAAW;IAWhC,mBAAmB;IACnB,IAAI,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,CAE7B;IAED,eAAe;IACf,IAAI,OAAO,IAAI,cAAc,CAAC,SAAS,CAAC,CAEvC;IAED,2BAA2B;IAC3B,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC;IAI9B,wBAAwB;IACxB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAIpC,iCAAiC;IACjC,YAAY,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;CAG9C"}
|