@eduwork/dsh-oidc 0.1.0-alpha.11
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/CHANGELOG.en.md +120 -0
- package/CHANGELOG.md +120 -0
- package/LICENSE +21 -0
- package/README.en.md +184 -0
- package/README.md +143 -0
- package/THIRD_PARTY_NOTICES.en.md +51 -0
- package/THIRD_PARTY_NOTICES.md +53 -0
- package/cordis.patch.yml +8 -0
- package/docs/EDUWORK-MIGRATION.en.md +23 -0
- package/docs/EDUWORK-MIGRATION.md +23 -0
- package/docs/architecture.en.md +125 -0
- package/docs/architecture.md +125 -0
- package/docs/compatibility.en.md +61 -0
- package/docs/compatibility.md +61 -0
- package/docs/decisions/0001-one-plugin-composition-boundary.en.md +34 -0
- package/docs/decisions/0001-one-plugin-composition-boundary.md +34 -0
- package/docs/dsh-integration.en.md +171 -0
- package/docs/dsh-integration.md +171 -0
- package/docs/ecnu-reference.en.md +66 -0
- package/docs/ecnu-reference.md +66 -0
- package/docs/enterprise-profile.en.md +159 -0
- package/docs/enterprise-profile.md +159 -0
- package/docs/getting-started.en.md +137 -0
- package/docs/getting-started.md +239 -0
- package/docs/key-binding-protocol.en.md +227 -0
- package/docs/key-binding-protocol.md +227 -0
- package/docs/oidc-interoperability.en.md +100 -0
- package/docs/oidc-interoperability.md +100 -0
- package/docs/release-checklist.en.md +60 -0
- package/docs/release-checklist.md +60 -0
- package/docs/security-model.en.md +138 -0
- package/docs/security-model.md +138 -0
- package/docs/server-integration-contract.en.md +706 -0
- package/docs/server-integration-contract.md +706 -0
- package/examples/ecnu.enterprise-profile.example.json +81 -0
- package/examples/enterprise-profile.example.json +77 -0
- package/lib/client.js +5855 -0
- package/lib/index.js +59 -0
- package/lib/oidc.js +649 -0
- package/lib/profile.js +371 -0
- package/lib/provider/core.js +138 -0
- package/lib/provider/index.js +156 -0
- package/lib/provider/transform-adapter.js +65 -0
- package/lib/provider/transforms.js +59 -0
- package/lib/typert-schemas.js +84 -0
- package/lib/typert.host.js +38 -0
- package/lib/typert.remote-client.js +37 -0
- package/package.json +120 -0
- package/protocol/openapi.yaml +257 -0
- package/schema/enterprise-profile.v1alpha1.schema.json +174 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# DSH integration and extension seams
|
|
2
|
+
|
|
3
|
+
[简体中文](dsh-integration.md) | **English**
|
|
4
|
+
|
|
5
|
+
## Supported host baseline
|
|
6
|
+
|
|
7
|
+
The current compatibility baseline is DeepSeek Harness `0.1.2-alpha.2`, upstream commit `0a53fb55bea101816fa226bb964ae2bed71c343b`. Peer versions are exact while DSH remains prerelease software.
|
|
8
|
+
|
|
9
|
+
The plugin uses public package exports rather than copied DSH source:
|
|
10
|
+
|
|
11
|
+
| DSH service/package | Use |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `dsh-typert-protocol` | Host/client RPC descriptors. |
|
|
14
|
+
| `dsh-host-webserver` | Exact `/oauth/callback` route. |
|
|
15
|
+
| `dsh-credentials` | Session and runtime API-key storage. |
|
|
16
|
+
| `dsh-llm` | Adapter registry, credentials, retry policy, stable errors. |
|
|
17
|
+
| `dsh-llm-pi-ai` | Official `PiAiAdapter`. |
|
|
18
|
+
| `dsh-settings` | Provider directory/readiness facts. |
|
|
19
|
+
| `dsh-launch-environment` | Credential fallback when no Credential Provider service is present. |
|
|
20
|
+
| client runtime/remotes/slots/theme | Browser bundle and bounded UI/brand surfaces. |
|
|
21
|
+
|
|
22
|
+
The OpenAI-compatible wire implementation comes from `@earendil-works/pi-ai`, which is already the basis of DSH's official Pi adapter.
|
|
23
|
+
|
|
24
|
+
## Why the Provider adapter is inside this package
|
|
25
|
+
|
|
26
|
+
OIDC authentication alone does not yield a callable enterprise model. A closed-loop integration also needs a stable Provider route whose credential reference matches Key Binding output. Publishing a second organization-specific Provider package would recreate the coupling this repository is meant to remove.
|
|
27
|
+
|
|
28
|
+
The adapter is therefore an internal module of `dsh-oidc`, but its behavior is constrained:
|
|
29
|
+
|
|
30
|
+
- one audited `openai-compatible` implementation;
|
|
31
|
+
- declarative Provider/model facts only;
|
|
32
|
+
- official DSH LLM registry and Pi adapter;
|
|
33
|
+
- no second HTTP stack;
|
|
34
|
+
- no ambient pi-ai credential discovery;
|
|
35
|
+
- DSH-owned retry policy and attachment resolution.
|
|
36
|
+
|
|
37
|
+
It remains exported as `@eduwork/dsh-oidc/provider` for tests and advanced local composition, but Enterprise Profiles cannot replace it.
|
|
38
|
+
|
|
39
|
+
## Cordis service entry
|
|
40
|
+
|
|
41
|
+
The default export is `OidcAccountService`, a `TypertRemoteService` named `oidcAccounts`. Remote methods are:
|
|
42
|
+
|
|
43
|
+
| Method | Result |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `configuration()` | Public profiles with secrets and endpoint bases removed. |
|
|
46
|
+
| `status(profileID)` | Local session/credential state. |
|
|
47
|
+
| `begin(profileID)` | Redirect URL for Web, completed status for native. |
|
|
48
|
+
| `reconcile(profileID, {allowProvision})` | Bootstrap and resolve/provision/renew. |
|
|
49
|
+
| `logout(profileID)` | Local cleanup and best-effort OIDC revocation. |
|
|
50
|
+
| `management()` | Capability-aware projection consumed by the shared enterprise-model settings UI. |
|
|
51
|
+
| `activate/configure/addCustom/updateCustom/removeProfile/configureModels/restart` | Optional native management operations; Web profiles reject mutation. |
|
|
52
|
+
|
|
53
|
+
The client descriptor uses strict Zod codecs. Configuration sent to the browser excludes issuer, client ID, Key Binding base, model base URL, tokens, and keys.
|
|
54
|
+
|
|
55
|
+
## Web composition
|
|
56
|
+
|
|
57
|
+
### Direct installation
|
|
58
|
+
|
|
59
|
+
`dsh-oidc` declares its own default Web-first Bundle patch. Install it directly from npm into the official Web profile without authoring a wrapper Bundle:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For auditing, development, or validating unpublished changes, install a reviewed local checkout instead:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/freedomkk-qfeng/dsh-oidc.git
|
|
69
|
+
cd dsh-oidc
|
|
70
|
+
npm ci
|
|
71
|
+
npm run check
|
|
72
|
+
dsh plugin --profile web add .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The local-path install links the checkout into the Profile, so the source directory must remain available. It does not scan the current workspace. Team deployments should prefer a reviewed, exact npm version; `@eduwork/dsh-oidc@alpha` is only for deployments that intentionally follow prerelease updates.
|
|
76
|
+
|
|
77
|
+
The shipped patch mounts exactly one `enterprise-oidc` instance using `DSH_OIDC_ENTERPRISE_PROFILE`. The Web backend requires the DSH WebServer to listen exactly on `127.0.0.1` and builds the fixed `/oauth/callback` from its actual port; no public callback-origin setting is accepted. It deliberately does not set `agent-default-model`, because Provider and model IDs belong to the deployment's Enterprise Profile and users can select an available enterprise model in DSH.
|
|
78
|
+
|
|
79
|
+
### Product-owned Bundle
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
- id: agent-default-model
|
|
83
|
+
config:
|
|
84
|
+
provider: example-ai
|
|
85
|
+
model: example-max
|
|
86
|
+
|
|
87
|
+
- insert:
|
|
88
|
+
- id: enterprise-oidc
|
|
89
|
+
name: '@eduwork/dsh-oidc'
|
|
90
|
+
config:
|
|
91
|
+
profilePathEnv: DSH_OIDC_ENTERPRISE_PROFILE
|
|
92
|
+
web:
|
|
93
|
+
returnPath: /
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The containing DSH profile/bundle must also include the ordinary Web app, credentials, LLM/Pi adapter dependencies, settings, attachment services, and client surfaces. `dsh-oidc` is not a complete DSH distribution.
|
|
97
|
+
|
|
98
|
+
See the [getting-started guide](getting-started.en.md) for OIDC registration, Key Binding implementation, environment variables, acceptance, and troubleshooting.
|
|
99
|
+
|
|
100
|
+
## Desktop/native composition
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
- insert:
|
|
104
|
+
- id: enterprise-oidc
|
|
105
|
+
name: '@eduwork/dsh-oidc'
|
|
106
|
+
config:
|
|
107
|
+
backend: native
|
|
108
|
+
uiMode: models-only
|
|
109
|
+
profilePathEnv: PRODUCT_ENTERPRISE_PROFILE
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The host supplies Cordis service `enterpriseAccounts`. Any product-owned institution catalog MUST first be converted by the host or assembly layer into a standard Enterprise Profile; `dsh-oidc` does not read or interpret product catalogs:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
interface EnterpriseAccounts {
|
|
116
|
+
status(institutionID: string): Promise<NativeStatus>
|
|
117
|
+
login(institutionID: string, options: { allowProvision: false }): Promise<NativeStatus>
|
|
118
|
+
reconcile(institutionID: string, options: { allowProvision: boolean }): Promise<NativeStatus>
|
|
119
|
+
logout(institutionID: string): Promise<NativeStatus>
|
|
120
|
+
configuration(): Promise<NativeManagement>
|
|
121
|
+
activate(institutionID: string): Promise<NativeManagement>
|
|
122
|
+
configure(institutionID: string): Promise<NativeManagement>
|
|
123
|
+
addCustom(baseURL: string): Promise<NativeManagement>
|
|
124
|
+
updateCustom(institutionID: string, baseURL: string): Promise<NativeManagement>
|
|
125
|
+
removeInstitution(institutionID: string): Promise<NativeManagement>
|
|
126
|
+
configureCustomModels(institutionID: string, mode: 'discovery' | 'manual', models: RuntimeModel[]): Promise<NativeManagement>
|
|
127
|
+
restart(): Promise<{restarting: true}>
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`NativeStatus` may include `displayName`, `organization`, `state`, `userName`, `affiliation`, `accessExpiresAt`, `runtimeCredentialRef`, `credentialReady`, `credentialState`, and `capabilities`. `runtimeCredentialRef` is only a host status assertion; when present, it MUST equal the normalized Enterprise Profile `keyBinding.credentialRef`. Credential naming belongs to the Profile, not to Wails, Electron, or any other host implementation.
|
|
132
|
+
|
|
133
|
+
Only the first four lifecycle operations are required for a native identity backend. Management operations are capability-detected: when absent, the same UI remains a read-only profile/model viewer. This is a host adapter, not part of OIDC or Key Binding wire standards. It can be implemented by Wails, Electron, Tauri, a mobile bridge, or another local host.
|
|
134
|
+
|
|
135
|
+
The public browser projection is versioned as `dsh-oidc/management/v1alpha1`. It deliberately excludes tokens and credentials. Web Enterprise Profiles set all mutation capabilities to false; a native adapter may set `manageProfiles`, `manageModels`, and `restart` according to the methods it actually provides.
|
|
136
|
+
|
|
137
|
+
## Model capability transforms
|
|
138
|
+
|
|
139
|
+
The plugin exposes a Cordis service named `enterpriseTransforms`:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
const dispose = ctx.enterpriseTransforms.register({
|
|
143
|
+
provider: 'example-ai',
|
|
144
|
+
model: 'example-max',
|
|
145
|
+
inputModalities: ['image'],
|
|
146
|
+
when: ({ inputModalities }) => !inputModalities.includes('image'),
|
|
147
|
+
transform: async (request, nativeModelInfo) => {
|
|
148
|
+
// Return a provider-bound request. Do not mutate request/transcript in place.
|
|
149
|
+
return request
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Route-wide and model-specific transforms run in that order. Duplicate registrations at the same scope are rejected. Registration changes emit `llm/adapters-updated`.
|
|
155
|
+
|
|
156
|
+
Transforms are executable local plugins and must be reviewed separately. They are never loaded from an Enterprise Profile.
|
|
157
|
+
|
|
158
|
+
## DSH upgrade procedure
|
|
159
|
+
|
|
160
|
+
For every DSH release candidate or stable upgrade:
|
|
161
|
+
|
|
162
|
+
1. update exact peer versions in a branch;
|
|
163
|
+
2. diff the public exports and relevant types used above;
|
|
164
|
+
3. run unit and package tests;
|
|
165
|
+
4. launch a plain Web DSH profile and complete login, provisioning, model call, refresh, logout;
|
|
166
|
+
5. launch the desktop/native composition and compare user-visible behavior;
|
|
167
|
+
6. verify client loader format and slot names;
|
|
168
|
+
7. review whether official DSH capability supersedes any local adapter code;
|
|
169
|
+
8. record results in `docs/compatibility.en.md` before release.
|
|
170
|
+
|
|
171
|
+
No semver range should silently opt this security-sensitive plugin into an untested DSH release while DSH remains pre-1.0.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# DSH 集成与扩展边界
|
|
2
|
+
|
|
3
|
+
**简体中文** | [English](dsh-integration.en.md)
|
|
4
|
+
|
|
5
|
+
## 支持的宿主基线
|
|
6
|
+
|
|
7
|
+
当前兼容基线为 DeepSeek Harness `0.1.2-alpha.2`,上游 commit `0a53fb55bea101816fa226bb964ae2bed71c343b`。DSH 仍处于预发布阶段,因此 peer version 使用精确版本。
|
|
8
|
+
|
|
9
|
+
插件只使用公开 package export,不复制 DSH 源码:
|
|
10
|
+
|
|
11
|
+
| DSH 服务/软件包 | 用途 |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `dsh-typert-protocol` | Host/Client RPC 描述符。 |
|
|
14
|
+
| `dsh-host-webserver` | 精确 `/oauth/callback` 路由。 |
|
|
15
|
+
| `dsh-credentials` | Session 和运行时 API Key 存储。 |
|
|
16
|
+
| `dsh-llm` | Adapter 注册、凭据、重试策略和稳定错误。 |
|
|
17
|
+
| `dsh-llm-pi-ai` | 官方 `PiAiAdapter`。 |
|
|
18
|
+
| `dsh-settings` | Provider 目录和就绪状态。 |
|
|
19
|
+
| `dsh-launch-environment` | Credential Provider 服务不存在时的凭据降级。 |
|
|
20
|
+
| Client runtime/remotes/slots/theme | 浏览器 bundle 和有边界的 UI/品牌表面。 |
|
|
21
|
+
|
|
22
|
+
OpenAI-compatible 网络实现来自 `@earendil-works/pi-ai`,它也是 DSH 官方 Pi adapter 的基础。
|
|
23
|
+
|
|
24
|
+
## 为什么 Provider adapter 位于本包内
|
|
25
|
+
|
|
26
|
+
只有 OIDC 认证还不能获得可调用的企业模型。闭环集成还需要稳定 Provider 路由,并确保其凭据引用与 Key Binding 输出一致。再发布一个机构特有 Provider 包,会重新制造本仓库要消除的耦合。
|
|
27
|
+
|
|
28
|
+
因此 adapter 是 `dsh-oidc` 内部模块,但其行为受到严格约束:
|
|
29
|
+
|
|
30
|
+
- 只有一个经过审查的 `openai-compatible` 实现;
|
|
31
|
+
- 只接受声明式 Provider/模型事实;
|
|
32
|
+
- 使用 DSH 官方 LLM 注册和 Pi adapter;
|
|
33
|
+
- 不维护第二套 HTTP 栈;
|
|
34
|
+
- 不自动发现环境中的 pi-ai 凭据;
|
|
35
|
+
- 重试策略和附件解析由 DSH 负责。
|
|
36
|
+
|
|
37
|
+
它仍以 `@eduwork/dsh-oidc/provider` 导出,供测试和高级本地组合使用,但 Enterprise Profile 无法替换它。
|
|
38
|
+
|
|
39
|
+
## Cordis 服务入口
|
|
40
|
+
|
|
41
|
+
默认导出为 `OidcAccountService`,这是名为 `oidcAccounts` 的 `TypertRemoteService`。远程方法包括:
|
|
42
|
+
|
|
43
|
+
| 方法 | 结果 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `configuration()` | 删除秘密和 endpoint 基址后的公开 Profile。 |
|
|
46
|
+
| `status(profileID)` | 本地 session/凭据状态。 |
|
|
47
|
+
| `begin(profileID)` | Web 返回重定向 URL,native 返回完成状态。 |
|
|
48
|
+
| `reconcile(profileID, {allowProvision})` | 执行 bootstrap 和 resolve/provision/renew。 |
|
|
49
|
+
| `logout(profileID)` | 本地清理,并尽力执行 OIDC 撤销。 |
|
|
50
|
+
| `management()` | 共用企业模型设置 UI 使用的宿主能力投影。 |
|
|
51
|
+
| `activate/configure/addCustom/updateCustom/removeProfile/configureModels/restart` | 可选 native 管理操作;Web Profile 拒绝修改。 |
|
|
52
|
+
|
|
53
|
+
Client 描述符使用严格 Zod codec。发送给浏览器的配置不包含 issuer、client ID、Key Binding base、模型 base URL、Token 或 Key。
|
|
54
|
+
|
|
55
|
+
## Web 组合
|
|
56
|
+
|
|
57
|
+
### 直接安装
|
|
58
|
+
|
|
59
|
+
`dsh-oidc` 自带默认的 Web-first Bundle patch,可以直接从 npm 安装到官方 Web Profile,无需再编写 wrapper Bundle:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
需要审计、开发或验证尚未发布的改动时,可以安装经过审查的本地 checkout:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/freedomkk-qfeng/dsh-oidc.git
|
|
69
|
+
cd dsh-oidc
|
|
70
|
+
npm ci
|
|
71
|
+
npm run check
|
|
72
|
+
dsh plugin --profile web add .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
本地路径安装会把 checkout 链接到 Profile,因此源码目录必须持续存在。它不会扫描当前工作区。团队部署应优先固定经过复核的 npm 精确版本;`@eduwork/dsh-oidc@alpha` 只适合明确希望跟随预发布更新的场景。
|
|
76
|
+
|
|
77
|
+
随包 patch 使用 `DSH_OIDC_ENTERPRISE_PROFILE` 挂载且只挂载一个 `enterprise-oidc` 实例。Web backend 要求 DSH WebServer 精确监听 `127.0.0.1`,并从实际端口构造固定 `/oauth/callback`;不接受公网回调源配置。它有意不设置 `agent-default-model`,因为 Provider 和模型 ID 属于部署方 Enterprise Profile,用户可在 DSH 中选择可用企业模型。
|
|
78
|
+
|
|
79
|
+
### 产品自有 Bundle
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
- id: agent-default-model
|
|
83
|
+
config:
|
|
84
|
+
provider: example-ai
|
|
85
|
+
model: example-max
|
|
86
|
+
|
|
87
|
+
- insert:
|
|
88
|
+
- id: enterprise-oidc
|
|
89
|
+
name: '@eduwork/dsh-oidc'
|
|
90
|
+
config:
|
|
91
|
+
profilePathEnv: DSH_OIDC_ENTERPRISE_PROFILE
|
|
92
|
+
web:
|
|
93
|
+
returnPath: /
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
所属 DSH Profile/Bundle 还必须包含普通 Web 应用、credentials、LLM/Pi adapter 依赖、settings、attachment 服务和 Client 界面。`dsh-oidc` 不是完整 DSH 发行版。
|
|
97
|
+
|
|
98
|
+
OIDC 注册、Key Binding 实现、环境变量、验收和排障见[接入指南](getting-started.md)。
|
|
99
|
+
|
|
100
|
+
## Desktop/native 组合
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
- insert:
|
|
104
|
+
- id: enterprise-oidc
|
|
105
|
+
name: '@eduwork/dsh-oidc'
|
|
106
|
+
config:
|
|
107
|
+
backend: native
|
|
108
|
+
uiMode: models-only
|
|
109
|
+
profilePathEnv: PRODUCT_ENTERPRISE_PROFILE
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
宿主提供 Cordis 服务 `enterpriseAccounts`。产品自有机构目录必须由宿主或装配层先转换为标准 Enterprise Profile;`dsh-oidc` 不读取或解释产品目录:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
interface EnterpriseAccounts {
|
|
116
|
+
status(institutionID: string): Promise<NativeStatus>
|
|
117
|
+
login(institutionID: string, options: { allowProvision: false }): Promise<NativeStatus>
|
|
118
|
+
reconcile(institutionID: string, options: { allowProvision: boolean }): Promise<NativeStatus>
|
|
119
|
+
logout(institutionID: string): Promise<NativeStatus>
|
|
120
|
+
configuration(): Promise<NativeManagement>
|
|
121
|
+
activate(institutionID: string): Promise<NativeManagement>
|
|
122
|
+
configure(institutionID: string): Promise<NativeManagement>
|
|
123
|
+
addCustom(baseURL: string): Promise<NativeManagement>
|
|
124
|
+
updateCustom(institutionID: string, baseURL: string): Promise<NativeManagement>
|
|
125
|
+
removeInstitution(institutionID: string): Promise<NativeManagement>
|
|
126
|
+
configureCustomModels(institutionID: string, mode: 'discovery' | 'manual', models: RuntimeModel[]): Promise<NativeManagement>
|
|
127
|
+
restart(): Promise<{restarting: true}>
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`NativeStatus` 可以包含 `displayName`、`organization`、`state`、`userName`、`affiliation`、`accessExpiresAt`、`runtimeCredentialRef`、`credentialReady`、`credentialState` 和 `capabilities`。`runtimeCredentialRef` 只是宿主状态回报;若提供,必须等于 Enterprise Profile 规范化后的 `keyBinding.credentialRef`。凭据命名策略属于 Profile,不属于 Wails、Electron 或其他宿主实现。
|
|
132
|
+
|
|
133
|
+
Native 身份后端只必须实现前四项生命周期操作。管理操作通过能力探测:缺少这些方法时,同一 UI 会保持为只读 Profile/模型查看器。这是宿主 adapter,不属于 OIDC 或 Key Binding 网络标准;Wails、Electron、Tauri、移动桥接或其他本地宿主均可实现。
|
|
134
|
+
|
|
135
|
+
浏览器公共投影版本为 `dsh-oidc/management/v1alpha1`,有意排除 Token 和凭据。Web Enterprise Profile 的所有修改能力为 false;native adapter 可以根据实际方法声明 `manageProfiles`、`manageModels` 和 `restart`。
|
|
136
|
+
|
|
137
|
+
## 模型能力转换
|
|
138
|
+
|
|
139
|
+
插件提供名为 `enterpriseTransforms` 的 Cordis 服务:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
const dispose = ctx.enterpriseTransforms.register({
|
|
143
|
+
provider: 'example-ai',
|
|
144
|
+
model: 'example-max',
|
|
145
|
+
inputModalities: ['image'],
|
|
146
|
+
when: ({ inputModalities }) => !inputModalities.includes('image'),
|
|
147
|
+
transform: async (request, nativeModelInfo) => {
|
|
148
|
+
// 返回将要发送给 Provider 的请求,不要原地修改 request/transcript。
|
|
149
|
+
return request
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
路由级转换先执行,模型级转换后执行。同一 scope 的重复注册会被拒绝。注册变化触发 `llm/adapters-updated`。
|
|
155
|
+
|
|
156
|
+
转换是可执行本地插件,必须单独审查,绝不会从 Enterprise Profile 加载。
|
|
157
|
+
|
|
158
|
+
## DSH 升级流程
|
|
159
|
+
|
|
160
|
+
每次升级 DSH release candidate 或 stable 版本时:
|
|
161
|
+
|
|
162
|
+
1. 在分支中更新精确 peer version;
|
|
163
|
+
2. 对比上述公开 export 和相关类型;
|
|
164
|
+
3. 运行单元测试和打包测试;
|
|
165
|
+
4. 启动纯 Web DSH Profile,完成登录、provision、模型调用、刷新和退出;
|
|
166
|
+
5. 启动 Desktop/native 组合并比较用户可见行为;
|
|
167
|
+
6. 验证 Client loader 格式和 slot 名称;
|
|
168
|
+
7. 审查 DSH 官方能力是否已替代任何本地 adapter 代码;
|
|
169
|
+
8. 发布前在 `docs/compatibility.md` 记录结果。
|
|
170
|
+
|
|
171
|
+
DSH 仍处于 1.0 之前时,不应使用 semver 范围让该安全敏感插件静默升级到未经测试的 DSH 版本。
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# ECNU reference composition
|
|
2
|
+
|
|
3
|
+
[简体中文](ecnu-reference.md) | **English**
|
|
4
|
+
|
|
5
|
+
This repository uses East China Normal University / ChatECNU only as a concrete reference for the generic standard. The public example contains placeholders and no production endpoint, OIDC client identifier, API key, token, personal data, or logo asset.
|
|
6
|
+
|
|
7
|
+
The reference file is [`examples/ecnu.enterprise-profile.example.json`](../examples/ecnu.enterprise-profile.example.json).
|
|
8
|
+
|
|
9
|
+
## Intended composition
|
|
10
|
+
|
|
11
|
+
The existing ChatECNU Work product can be expressed as a composition rather than a monolith:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
DeepSeek Harness
|
|
15
|
+
+ dsh-oidc
|
|
16
|
+
- standard OIDC identity
|
|
17
|
+
- worker-user-center-v1 Key Binding
|
|
18
|
+
- ECNU Enterprise Profile
|
|
19
|
+
- declarative ChatECNU Provider/models
|
|
20
|
+
- bounded brand/account UI and shared enterprise-model settings UI
|
|
21
|
+
+ ECNU product plugins
|
|
22
|
+
- image-understanding fallback for text-only ecnu-max
|
|
23
|
+
- enterprise search route and official DSH result rendering
|
|
24
|
+
- product presets/skills/resources
|
|
25
|
+
- native desktop account adapter and OS credential vault
|
|
26
|
+
- quota or institution-specific business UI
|
|
27
|
+
+ desktop shell/packaging/updater
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Pure Web DSH uses the Web backend and a host-appropriate Credential Provider. ChatECNU Work desktop uses the native backend and keeps its existing Wails implementation behind `enterpriseAccounts`. Both render the enterprise-model section through `dsh-oidc`; the desktop adapter merely advertises additional mutation/restart capabilities. Neither mode changes OIDC or Key Binding server contracts.
|
|
31
|
+
|
|
32
|
+
## Identity expectation
|
|
33
|
+
|
|
34
|
+
The OIDC Provider should return standard UserInfo:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"sub": "opaque-stable-subject",
|
|
39
|
+
"name": "Display Name"
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If `name` is absent, UI falls back to `sub`. The plugin does not call an ECNU-private profile endpoint and does not map `data.attributes.XM` or similar paths. This is deliberate: the organization OIDC service should expose the standard claim.
|
|
44
|
+
|
|
45
|
+
## Model example
|
|
46
|
+
|
|
47
|
+
The placeholder shows two common facts:
|
|
48
|
+
|
|
49
|
+
- `ecnu-max`: text-only, large context, selectable reasoning efforts;
|
|
50
|
+
- `ecnu-plus`: native text/image input, thinking enabled but no selectable reasoning-effort parameter.
|
|
51
|
+
|
|
52
|
+
For `ecnu-plus`, `supportsReasoningEffort: false` removes the unsupported effort while preserving thinking behavior. For `ecnu-max`, a separate ECNU image-understanding plugin can register `enterpriseTransforms` to add an aggregate image capability without altering the profile or replacing the Provider route.
|
|
53
|
+
|
|
54
|
+
## Before any public release
|
|
55
|
+
|
|
56
|
+
ECNU maintainers must separately approve:
|
|
57
|
+
|
|
58
|
+
- the GitHub organization and repository visibility;
|
|
59
|
+
- copyright holder wording;
|
|
60
|
+
- use of university/ChatECNU names and brand values;
|
|
61
|
+
- public support and security contact addresses;
|
|
62
|
+
- publication of the npm package name;
|
|
63
|
+
- removal of every internal endpoint, identifier, log, archive, and credential;
|
|
64
|
+
- the production deployment's privacy/security review.
|
|
65
|
+
|
|
66
|
+
The existence of this reference document is not authorization to publish institutional infrastructure details or brand assets.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# 华东师范大学参考组合
|
|
2
|
+
|
|
3
|
+
**简体中文** | [English](ecnu-reference.en.md)
|
|
4
|
+
|
|
5
|
+
本仓库仅以华东师范大学 / ChatECNU 作为通用标准的一项具体参考实现。公开示例全部使用占位符,不包含生产 endpoint、OIDC Client ID、API Key、Token、个人数据或 Logo 资产。
|
|
6
|
+
|
|
7
|
+
参考文件为 [`examples/ecnu.enterprise-profile.example.json`](../examples/ecnu.enterprise-profile.example.json)。
|
|
8
|
+
|
|
9
|
+
## 预期组合
|
|
10
|
+
|
|
11
|
+
现有 ChatECNU Work 产品可以表达为组合结构,而不是单体实现:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
DeepSeek Harness
|
|
15
|
+
+ dsh-oidc
|
|
16
|
+
- 标准 OIDC 身份
|
|
17
|
+
- worker-user-center-v1 Key Binding
|
|
18
|
+
- ECNU Enterprise Profile
|
|
19
|
+
- 声明式 ChatECNU Provider/模型
|
|
20
|
+
- 有边界的品牌/账号 UI 和共用企业模型设置 UI
|
|
21
|
+
+ ECNU 产品插件
|
|
22
|
+
- 面向纯文本 ecnu-max 的图像理解回退
|
|
23
|
+
- 企业搜索通路和 DSH 官方结果渲染
|
|
24
|
+
- 产品预设、Skill 和资源
|
|
25
|
+
- native 桌面账号 adapter 与操作系统凭据保险库
|
|
26
|
+
- 配额或机构特有业务 UI
|
|
27
|
+
+ 桌面外壳、打包与更新器
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
纯 Web DSH 使用 Web 后端和适合宿主的 Credential Provider。ChatECNU Work 桌面端使用 native 后端,并把现有 Wails 实现保留在 `enterpriseAccounts` 后面。两者都通过 `dsh-oidc` 渲染企业模型区域;桌面 adapter 只额外声明可变配置和重启能力。两种模式都不改变 OIDC 或 Key Binding 服务端契约。
|
|
31
|
+
|
|
32
|
+
## 身份预期
|
|
33
|
+
|
|
34
|
+
OIDC Provider 应返回标准 UserInfo:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"sub": "opaque-stable-subject",
|
|
39
|
+
"name": "Display Name"
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
如果没有 `name`,UI 会降级显示 `sub`。插件不会调用 ECNU 私有人员信息接口,也不会映射 `data.attributes.XM` 等路径。这是有意设计:机构 OIDC 服务应提供标准 claim。
|
|
44
|
+
|
|
45
|
+
## 模型示例
|
|
46
|
+
|
|
47
|
+
占位示例展示了两类常见模型事实:
|
|
48
|
+
|
|
49
|
+
- `ecnu-max`:纯文本、大上下文、支持选择 reasoning effort;
|
|
50
|
+
- `ecnu-plus`:原生文本/图片输入,支持 thinking,但不支持选择 reasoning-effort 参数。
|
|
51
|
+
|
|
52
|
+
对 `ecnu-plus` 设置 `supportsReasoningEffort: false`,会移除不支持的 effort 参数但保留 thinking。对 `ecnu-max`,独立的 ECNU 图像理解插件可注册 `enterpriseTransforms`,在不修改 Profile、不替换 Provider 路由的情况下增加聚合图像能力。
|
|
53
|
+
|
|
54
|
+
## 任何公开发布之前
|
|
55
|
+
|
|
56
|
+
ECNU 维护者必须另行批准:
|
|
57
|
+
|
|
58
|
+
- GitHub 组织和仓库可见性;
|
|
59
|
+
- 版权主体表述;
|
|
60
|
+
- 校名、ChatECNU 名称和品牌值的使用;
|
|
61
|
+
- 公开支持和安全联系地址;
|
|
62
|
+
- npm 包名发布;
|
|
63
|
+
- 清除全部内部 endpoint、标识符、日志、归档和凭据;
|
|
64
|
+
- 生产部署的隐私与安全审查。
|
|
65
|
+
|
|
66
|
+
存在这份参考文档不代表已获准发布任何机构基础设施细节或品牌资产。
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Enterprise Profile specification (`dsh-oidc/v1alpha1`)
|
|
2
|
+
|
|
3
|
+
[简体中文](enterprise-profile.md) | **English**
|
|
4
|
+
|
|
5
|
+
## Status and conformance
|
|
6
|
+
|
|
7
|
+
This document specifies the data contract consumed by `dsh-oidc` `0.1.x`. The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHOULD**, **SHOULD NOT**, and **MAY** are interpreted as described by RFC 2119 and RFC 8174.
|
|
8
|
+
|
|
9
|
+
The canonical machine-readable schema is [`schema/enterprise-profile.v1alpha1.schema.json`](../schema/enterprise-profile.v1alpha1.schema.json). Runtime validation is intentionally stricter in several security-sensitive URL cases. A conforming profile MUST pass both JSON Schema validation and `normalizeEnterpriseProfile()`.
|
|
10
|
+
|
|
11
|
+
## Trust model
|
|
12
|
+
|
|
13
|
+
Profiles are trusted deployment configuration, not user input. Nevertheless, the parser is fail-closed:
|
|
14
|
+
|
|
15
|
+
- unknown keys are rejected at the root and at every executable-relevant nested object;
|
|
16
|
+
- total serialized profile size is limited to 512 KiB;
|
|
17
|
+
- production URLs require HTTPS;
|
|
18
|
+
- development HTTP is accepted only for explicit loopback hosts;
|
|
19
|
+
- URL credentials, fragments, and endpoint-base query strings are rejected;
|
|
20
|
+
- only the built-in `openai-compatible` adapter can be selected;
|
|
21
|
+
- Key Binding accepts only its protocol base and an optional local DSH credential reference; network paths and fields remain fixed;
|
|
22
|
+
- logo data URLs accept PNG/WebP only, not SVG.
|
|
23
|
+
|
|
24
|
+
A remote administration system MAY distribute profile JSON only if the host authenticates the source, verifies integrity, and stages changes through review. Downloaded JSON does not become safe merely because it contains no JavaScript.
|
|
25
|
+
|
|
26
|
+
## Root object
|
|
27
|
+
|
|
28
|
+
| Field | Required | Meaning |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `schemaVersion` | yes | Exact string `dsh-oidc/v1alpha1`. |
|
|
31
|
+
| `id` | yes | Profile ID matching `^[a-z][a-z0-9-]{0,63}$`. |
|
|
32
|
+
| `displayName` | yes | Human-readable integration name. |
|
|
33
|
+
| `organization` | no | Organization label; defaults to `displayName`. |
|
|
34
|
+
| `nativeInstitutionID` | no | Identifier passed only to a native backend; defaults to `id`. |
|
|
35
|
+
| `allowInsecureDevelopment` | no | Enables loopback HTTP for local development. Network HTTP additionally requires `insecureDevelopmentOrigin`. |
|
|
36
|
+
| `insecureDevelopmentOrigin` | no | Exact non-TLS development origin. It is accepted only together with `allowInsecureDevelopment: true`, and every HTTP OIDC/key-binding/provider endpoint must use this exact origin. Never ship it in a production profile. |
|
|
37
|
+
| `brand` | yes | Bounded presentational values. |
|
|
38
|
+
| `oidc` | yes | OIDC public-client facts. |
|
|
39
|
+
| `keyBinding` | yes | Key Binding base URL and optional local DSH credential reference. |
|
|
40
|
+
| `provider` | yes | One local OpenAI-compatible Provider route and model list. |
|
|
41
|
+
|
|
42
|
+
## Branding
|
|
43
|
+
|
|
44
|
+
Branding changes only approved presentation surfaces. It does not alter authentication or executable behavior.
|
|
45
|
+
|
|
46
|
+
| Field | Limit / behavior |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `productName` | 80 characters; document/sidebar label. |
|
|
49
|
+
| `organizationName` | 120 characters. |
|
|
50
|
+
| `mark` | 1–4 characters used when no logo is supplied. |
|
|
51
|
+
| `logoURL` | HTTPS URL or base64 PNG/WebP, at most 128 KiB as text. Remote images use `referrerPolicy=no-referrer`. |
|
|
52
|
+
| `primaryColor` | Six-digit hex color. Only a bounded DSH token set is overridden. |
|
|
53
|
+
| `loginTitle` | 120 characters. |
|
|
54
|
+
| `loginDescription` | 500 characters. |
|
|
55
|
+
| `supportURL` | Absolute HTTPS URL opened with `noopener noreferrer`. |
|
|
56
|
+
|
|
57
|
+
Profiles MUST NOT include logos or names without permission from the rights holder. Operators concerned about remote-image tracking SHOULD package a base64 PNG/WebP or host the asset on a controlled origin with a restrictive CSP.
|
|
58
|
+
|
|
59
|
+
## OIDC object
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"issuer": "https://id.example.edu/oidc",
|
|
64
|
+
"clientId": "dsh-web-public-client",
|
|
65
|
+
"scopes": ["openid", "profile", "offline_access"]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `issuer` is an OIDC Issuer Identifier. Paths are supported; query and fragment are not. Exact string equality with Discovery metadata is required.
|
|
70
|
+
- `clientId` identifies a public client. No client secret belongs in a profile or this plugin.
|
|
71
|
+
- `scopes` MUST contain `openid` and `profile`, contain no whitespace within an item, and contain no duplicates.
|
|
72
|
+
- `offline_access` SHOULD be requested when the Provider issues refresh tokens and policy allows it.
|
|
73
|
+
- Key Binding authorization scopes are deployment-specific but SHOULD use the names in the reference example.
|
|
74
|
+
|
|
75
|
+
The Web redirect URI is fixed to `http://127.0.0.1:<DSH-port>/oauth/callback`. The host and path are not configurable; the port follows the DSH WebServer's actual listening port.
|
|
76
|
+
|
|
77
|
+
## Key Binding object
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"baseURL": "https://ai.example.edu/api/worker/v1",
|
|
82
|
+
"credentialRef": "EXAMPLE_AI_TEST_API_KEY"
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Field | Required | Meaning |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| `baseURL` | yes | Base URL of the `worker-user-center-v1` Key Binding interface group. |
|
|
89
|
+
| `credentialRef` | no | Local DSH Credential Provider name under which the bound model API key is stored. It must match `^[A-Za-z_][A-Za-z0-9_]*$` and is limited to 128 characters. |
|
|
90
|
+
|
|
91
|
+
The protocol type is fixed to `worker-user-center-v1`, and the Provider ID sent on the wire is always `provider.id`. When `credentialRef` is omitted, the parser preserves the backward-compatible default: uppercase the Provider ID, replace non-alphanumerics with `_`, and append `_API_KEY`. For example, `example-ai` defaults to `EXAMPLE_AI_API_KEY`.
|
|
92
|
+
|
|
93
|
+
`credentialRef` is only the name of a local secret-store entry. It is not an API key and is never sent to OIDC, Key Binding, or the model service. A normal single-environment deployment SHOULD omit it. Deployments that reuse one Provider ID across production and test MUST configure distinct references, for example `EXAMPLE_AI_API_KEY` and `EXAMPLE_AI_TEST_API_KEY`, so one environment cannot resolve another environment's key.
|
|
94
|
+
|
|
95
|
+
Endpoint paths, request/response fields, and Provider ID semantics are protocol facts and MUST NOT be customized by profiles. If a native host returns `runtimeCredentialRef`, it MUST equal the normalized profile value or the plugin fails closed.
|
|
96
|
+
|
|
97
|
+
## Provider object
|
|
98
|
+
|
|
99
|
+
The Provider object is data interpreted by a local audited adapter.
|
|
100
|
+
|
|
101
|
+
| Field | Required | Meaning |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `id` | yes | DSH route ID and source of the default credential reference. Must be unique across loaded profiles. |
|
|
104
|
+
| `displayName` | no | User-facing Provider name. |
|
|
105
|
+
| `adapter` | yes | Exact string `openai-compatible`. |
|
|
106
|
+
| `baseURL` | yes | HTTPS OpenAI-compatible API base. |
|
|
107
|
+
| `reasoning` | no | Default DSH/pi-ai reasoning level, default `high`. |
|
|
108
|
+
| `defaultContextWindow` | no | Positive safe integer, default 262144. |
|
|
109
|
+
| `defaultMaxTokens` | no | Positive safe integer, default 32768. |
|
|
110
|
+
| `maxRequestImageBytes` | no | Accumulated native-image request budget. |
|
|
111
|
+
| `requestImagePixelBudget` | no | Image normalization pixel budget. |
|
|
112
|
+
| `requestImageMaxBytes` | no | Per-normalized-image byte budget. |
|
|
113
|
+
| `streamIdleTimeoutMs` | no | Positive idle timeout, default 300000. |
|
|
114
|
+
| `retryPolicy` | no | DSH provider-owned retry policy; default normal/2 retries. |
|
|
115
|
+
| `compat` | no | Bounded pi-ai OpenAI compatibility facts. |
|
|
116
|
+
| `models` | yes | 1–128 unique model entries. |
|
|
117
|
+
|
|
118
|
+
`retryPolicy.mode` is `normal` or `always`. `always` can retry indefinitely until success, cancellation, or disposal and SHOULD NOT be enabled without an explicit product decision. The policy is validated again by DSH.
|
|
119
|
+
|
|
120
|
+
`compat` accepts only the keys enumerated in the JSON Schema. Operators MUST describe provider facts accurately; a compatibility override can change request semantics, though it cannot execute code.
|
|
121
|
+
|
|
122
|
+
## Model entries
|
|
123
|
+
|
|
124
|
+
Each model has:
|
|
125
|
+
|
|
126
|
+
- required `id`;
|
|
127
|
+
- optional display `name`;
|
|
128
|
+
- `input` containing `text`, `image`, or both (default `text`);
|
|
129
|
+
- optional positive `contextWindow` and `maxTokens`;
|
|
130
|
+
- optional `reasoning` boolean;
|
|
131
|
+
- optional `reasoningEfforts` object, or `false`;
|
|
132
|
+
- optional bounded `compat` overrides.
|
|
133
|
+
|
|
134
|
+
If a model supports thinking but not selectable reasoning effort, set:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"compat": { "supportsReasoningEffort": false }
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The adapter then enables the profile's thinking behavior while removing an unsupported user-selected effort before validation and transport. The request is not rejected merely because the provider lacks an effort parameter.
|
|
143
|
+
|
|
144
|
+
## Secret prohibition
|
|
145
|
+
|
|
146
|
+
Profiles MUST NOT contain:
|
|
147
|
+
|
|
148
|
+
- OIDC client secrets;
|
|
149
|
+
- access, refresh, or ID tokens;
|
|
150
|
+
- model API keys;
|
|
151
|
+
- private signing keys;
|
|
152
|
+
- session cookies;
|
|
153
|
+
- personal identity data.
|
|
154
|
+
|
|
155
|
+
The OIDC client is public. Runtime secrets are created after login and stored only by the active DSH Credential Provider.
|
|
156
|
+
|
|
157
|
+
## Versioning
|
|
158
|
+
|
|
159
|
+
Unknown `schemaVersion` values are rejected. During alpha, any field may change between `v1alphaN` versions. A stable `v1` will use additive optional fields for minor releases and a new schema version for incompatible changes. See [Compatibility](compatibility.en.md).
|