@eduwork/dsh-oidc 0.1.0-alpha.11 → 0.2.0

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.
Files changed (72) hide show
  1. package/CHANGELOG.en.md +58 -1
  2. package/CHANGELOG.md +58 -1
  3. package/CODE_OF_CONDUCT.en.md +17 -0
  4. package/CODE_OF_CONDUCT.md +17 -0
  5. package/CONTRIBUTING.en.md +56 -0
  6. package/CONTRIBUTING.md +56 -0
  7. package/GOVERNANCE.en.md +41 -0
  8. package/GOVERNANCE.md +41 -0
  9. package/MAINTAINERS.en.md +13 -0
  10. package/MAINTAINERS.md +13 -0
  11. package/README.en.md +24 -22
  12. package/README.md +18 -16
  13. package/SECURITY.en.md +45 -0
  14. package/SECURITY.md +45 -0
  15. package/SUPPORT.en.md +15 -0
  16. package/SUPPORT.md +15 -0
  17. package/THIRD_PARTY_NOTICES.en.md +7 -5
  18. package/THIRD_PARTY_NOTICES.md +7 -5
  19. package/cordis.patch.yml +2 -1
  20. package/docs/EDUWORK-MIGRATION.en.md +17 -5
  21. package/docs/EDUWORK-MIGRATION.md +17 -5
  22. package/docs/account-extensions.en.md +40 -0
  23. package/docs/account-extensions.md +42 -0
  24. package/docs/architecture.en.md +9 -9
  25. package/docs/architecture.md +11 -10
  26. package/docs/compatibility.en.md +13 -3
  27. package/docs/compatibility.md +13 -3
  28. package/docs/decisions/0001-one-plugin-composition-boundary.en.md +1 -1
  29. package/docs/decisions/0001-one-plugin-composition-boundary.md +1 -1
  30. package/docs/desktop-host.en.md +69 -0
  31. package/docs/desktop-host.md +79 -0
  32. package/docs/development.en.md +42 -0
  33. package/docs/development.md +42 -0
  34. package/docs/dsh-integration.en.md +24 -8
  35. package/docs/dsh-integration.md +24 -8
  36. package/docs/ecnu-reference.en.md +3 -3
  37. package/docs/ecnu-reference.md +3 -3
  38. package/docs/enterprise-profile.en.md +21 -13
  39. package/docs/enterprise-profile.md +20 -12
  40. package/docs/getting-started.en.md +13 -17
  41. package/docs/getting-started.md +17 -19
  42. package/docs/key-binding-protocol.en.md +2 -2
  43. package/docs/key-binding-protocol.md +2 -2
  44. package/docs/oidc-interoperability.en.md +3 -3
  45. package/docs/oidc-interoperability.md +2 -2
  46. package/docs/public-resource-protocol.en.md +51 -0
  47. package/docs/public-resource-protocol.md +50 -0
  48. package/docs/release-checklist.en.md +13 -8
  49. package/docs/release-checklist.md +13 -8
  50. package/docs/server-integration-contract.en.md +124 -8
  51. package/docs/server-integration-contract.md +136 -8
  52. package/examples/ecnu.enterprise-profile.example.json +2 -2
  53. package/examples/enterprise-profile.example.json +78 -77
  54. package/examples/identity-only.example.json +10 -0
  55. package/examples/resources-discovery.example.json +20 -0
  56. package/lib/callback-page.js +42 -0
  57. package/lib/client.js +938 -294
  58. package/lib/desktop-oidc.js +205 -0
  59. package/lib/index.js +148 -18
  60. package/lib/oidc.js +314 -58
  61. package/lib/profile.js +96 -39
  62. package/lib/provider/core.js +76 -15
  63. package/lib/provider/index.js +54 -22
  64. package/lib/provider/transform-adapter.js +32 -11
  65. package/lib/resources.js +23 -0
  66. package/lib/typert-schemas.js +34 -3
  67. package/lib/typert.host.js +42 -36
  68. package/lib/typert.remote-client.js +41 -35
  69. package/package.json +117 -23
  70. package/protocol/openapi.yaml +2 -2
  71. package/protocol/resources.openapi.yaml +51 -0
  72. package/schema/enterprise-profile.v1alpha1.schema.json +193 -174
@@ -1,10 +1,12 @@
1
1
  # Enterprise Profile specification (`dsh-oidc/v1alpha1`)
2
2
 
3
+ > Candidate extension: omit both keyBinding/provider for identity-only OIDC; brand is optional. Resource mode accepts keyBinding.type=eduwork-resources-v1 (default worker-user-center-v1). provider.modelSource=discovery may omit models; normal profile mode requires models. See [Public resource protocol](public-resource-protocol.en.md).
4
+
3
5
  [简体中文](enterprise-profile.md) | **English**
4
6
 
5
7
  ## Status and conformance
6
8
 
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.
9
+ This document specifies the data contract consumed by `dsh-oidc` `0.2.x`. The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHOULD**, **SHOULD NOT**, and **MAY** are interpreted as described by RFC 2119 and RFC 8174.
8
10
 
9
11
  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
12
 
@@ -15,7 +17,7 @@ Profiles are trusted deployment configuration, not user input. Nevertheless, the
15
17
  - unknown keys are rejected at the root and at every executable-relevant nested object;
16
18
  - total serialized profile size is limited to 512 KiB;
17
19
  - production URLs require HTTPS;
18
- - development HTTP is accepted only for explicit loopback hosts;
20
+ - development HTTP needs an explicit loopback allowance or exact development-origin allowlist;
19
21
  - URL credentials, fragments, and endpoint-base query strings are rejected;
20
22
  - only the built-in `openai-compatible` adapter can be selected;
21
23
  - Key Binding accepts only its protocol base and an optional local DSH credential reference; network paths and fields remain fixed;
@@ -34,10 +36,10 @@ A remote administration system MAY distribute profile JSON only if the host auth
34
36
  | `nativeInstitutionID` | no | Identifier passed only to a native backend; defaults to `id`. |
35
37
  | `allowInsecureDevelopment` | no | Enables loopback HTTP for local development. Network HTTP additionally requires `insecureDevelopmentOrigin`. |
36
38
  | `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. |
39
+ | `brand` | no | Bounded presentational values. |
38
40
  | `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
+ | `keyBinding` | resource mode | Key Binding base URL and optional local DSH credential reference. |
42
+ | `provider` | resource mode | One local OpenAI-compatible Provider route and model list. |
41
43
 
42
44
  ## Branding
43
45
 
@@ -79,7 +81,7 @@ The Web redirect URI is fixed to `http://127.0.0.1:<DSH-port>/oauth/callback`. T
79
81
  ```json
80
82
  {
81
83
  "baseURL": "https://ai.example.edu/api/worker/v1",
82
- "credentialRef": "EXAMPLE_AI_TEST_API_KEY"
84
+ "credentialRef": "EDUWORK_API_KEY"
83
85
  }
84
86
  ```
85
87
 
@@ -88,9 +90,11 @@ The Web redirect URI is fixed to `http://127.0.0.1:<DSH-port>/oauth/callback`. T
88
90
  | `baseURL` | yes | Base URL of the `worker-user-center-v1` Key Binding interface group. |
89
91
  | `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
92
 
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`.
93
+ The Provider ID sent on the wire is always `provider.id`. An omitted `credentialRef` now defaults to `EDUWORK_API_KEY`. Legacy automatic references derived from this Profile’s `id` or `provider.id` (uppercase, non-alphanumerics replaced with `_`, followed by `_API_KEY`) normalize to this common name. Other explicit references remain unchanged.
94
+
95
+ `credentialRef` names a local secret-store entry; it is not a key and is never sent over the network. Normal deployments use `EDUWORK_API_KEY`; explicit independent overrides such as `MY_TEST_MODEL_KEY` remain supported. With a shared reference, only a verified login whose bound credential fingerprint matches the current key may read it. Rebinding leaves other profiles disconnected from that key, and their logout cannot delete a key written by another login. Independently configured personal model credentials are unaffected.
92
96
 
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.
97
+ An upgrade imports an old key only when issuer, client ID, management URL, runtime URL and Provider ID all match and only the automatic reference changed. It neither overwrites nor adopts an occupied target. Unproven ownership retains identity but requires reconnecting model resources. Pre-fingerprint sessions are accepted only with an identical complete binding and unambiguous reference ownership.
94
98
 
95
99
  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
100
 
@@ -100,11 +104,11 @@ The Provider object is data interpreted by a local audited adapter.
100
104
 
101
105
  | Field | Required | Meaning |
102
106
  | --- | --- | --- |
103
- | `id` | yes | DSH route ID and source of the default credential reference. Must be unique across loaded profiles. |
107
+ | `id` | yes | DSH route ID, independent of the shared default credential reference. Must be unique across loaded profiles. |
104
108
  | `displayName` | no | User-facing Provider name. |
105
109
  | `adapter` | yes | Exact string `openai-compatible`. |
106
110
  | `baseURL` | yes | HTTPS OpenAI-compatible API base. |
107
- | `reasoning` | no | Default DSH/pi-ai reasoning level, default `high`. |
111
+ | `reasoning` | no | Default DSH/pi-ai reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`; default `high`. |
108
112
  | `defaultContextWindow` | no | Positive safe integer, default 262144. |
109
113
  | `defaultMaxTokens` | no | Positive safe integer, default 32768. |
110
114
  | `maxRequestImageBytes` | no | Accumulated native-image request budget. |
@@ -113,7 +117,8 @@ The Provider object is data interpreted by a local audited adapter.
113
117
  | `streamIdleTimeoutMs` | no | Positive idle timeout, default 300000. |
114
118
  | `retryPolicy` | no | DSH provider-owned retry policy; default normal/2 retries. |
115
119
  | `compat` | no | Bounded pi-ai OpenAI compatibility facts. |
116
- | `models` | yes | 1–128 unique model entries. |
120
+ | `modelSource` | no | `profile` (default) or `discovery`; discovery requests `/models` with the managed key. |
121
+ | `models` | profile mode | 1–128 unique entries; discovery may omit them, and configured entries supply reviewed capabilities. |
117
122
 
118
123
  `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
124
 
@@ -128,9 +133,12 @@ Each model has:
128
133
  - `input` containing `text`, `image`, or both (default `text`);
129
134
  - optional positive `contextWindow` and `maxTokens`;
130
135
  - optional `reasoning` boolean;
131
- - optional `reasoningEfforts` object, or `false`;
136
+ - optional `reasoningEfforts` object, or `false`; object keys are limited to `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`, and only `off` may have a null wire value;
137
+ - optional `defaultReasoningEffort`, which must name an effort declared by that model; when omitted, the historical provider-level `reasoning` preference falls back to the nearest supported effort, choosing the lower effort on a tie;
132
138
  - optional bounded `compat` overrides.
133
139
 
140
+ Once `reasoningEfforts` is declared, every omitted effort is explicitly unsupported. Effort IDs and wire values remain distinct, so `xhigh` is never silently rewritten as `max`. For thinking without a user-selectable effort, set only `compat.supportsReasoningEffort` to `false`; for a model with no thinking capability, set `reasoning` or `reasoningEfforts` to `false`.
141
+
134
142
  If a model supports thinking but not selectable reasoning effort, set:
135
143
 
136
144
  ```json
@@ -139,7 +147,7 @@ If a model supports thinking but not selectable reasoning effort, set:
139
147
  }
140
148
  ```
141
149
 
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.
150
+ The adapter preserves the profile's thinking behavior: historical user-selected efforts are ignored, the profile default is resolved against that model's supported levels, and only an internal enabling signal is passed to PiAi. `compat.supportsReasoningEffort: false` keeps `reasoning_effort` out of the HTTP request. This signal does not create selectable UI efforts; a profile default of `off` still disables models that support it. The request is not rejected merely because the provider lacks an effort parameter.
143
151
 
144
152
  ## Secret prohibition
145
153
 
@@ -1,10 +1,12 @@
1
1
  # Enterprise Profile 规范(`dsh-oidc/v1alpha1`)
2
2
 
3
+ > 当前候选扩展:纯身份模式同时省略 keyBinding/provider;brand 可省略。资源模式支持 keyBinding.type=eduwork-resources-v1,默认兼容 worker-user-center-v1。provider.modelSource=discovery 时 models 可省略;默认 profile 模式仍要求模型列表。见 [公共资源协议](public-resource-protocol.md)。
4
+
3
5
  **简体中文** | [English](enterprise-profile.en.md)
4
6
 
5
7
  ## 状态与符合性
6
8
 
7
- 本文规定 `dsh-oidc` `0.1.x` 使用的数据契约。关键词 **必须(MUST)**、**不得(MUST NOT)**、**必需(REQUIRED)**、**应该(SHOULD)**、**不应该(SHOULD NOT)** 和 **可以(MAY)** 按 RFC 2119 与 RFC 8174 解释。
9
+ 本文规定 `dsh-oidc` `0.2.x` 使用的数据契约。关键词 **必须(MUST)**、**不得(MUST NOT)**、**必需(REQUIRED)**、**应该(SHOULD)**、**不应该(SHOULD NOT)** 和 **可以(MAY)** 按 RFC 2119 与 RFC 8174 解释。
8
10
 
9
11
  权威机器可读 Schema 为 [`schema/enterprise-profile.v1alpha1.schema.json`](../schema/enterprise-profile.v1alpha1.schema.json)。运行时对若干安全敏感 URL 的校验有意比 JSON Schema 更严格。符合规范的 Profile 必须同时通过 JSON Schema 和 `normalizeEnterpriseProfile()` 校验。
10
12
 
@@ -34,10 +36,10 @@ Profile 是受信任的部署配置,不是用户输入。即便如此,解析
34
36
  | `nativeInstitutionID` | 否 | 仅传给 native 后端的标识符;默认使用 `id`。 |
35
37
  | `allowInsecureDevelopment` | 否 | 为本地开发启用 loopback HTTP。网络 HTTP 还必须配置 `insecureDevelopmentOrigin`。 |
36
38
  | `insecureDevelopmentOrigin` | 否 | 精确的非 TLS 开发 origin。只有与 `allowInsecureDevelopment: true` 一起使用时才有效,且所有 HTTP OIDC/Key Binding/Provider endpoint 必须使用该 origin。不得放入生产 Profile。 |
37
- | `brand` | 是 | 有边界的展示配置。 |
39
+ | `brand` | 否 | 有边界的展示配置。 |
38
40
  | `oidc` | 是 | OIDC public client 配置事实。 |
39
- | `keyBinding` | 是 | Key Binding 基础 URL,以及可选的本地 DSH 凭据引用。 |
40
- | `provider` | 是 | 一个本地 OpenAI-compatible Provider 路由和模型列表。 |
41
+ | `keyBinding` | 资源模式 | Key Binding 基础 URL,以及可选的本地 DSH 凭据引用。 |
42
+ | `provider` | 资源模式 | 一个本地 OpenAI-compatible Provider 路由和模型列表。 |
41
43
 
42
44
  ## 品牌替换
43
45
 
@@ -79,7 +81,7 @@ Web 重定向地址固定为 `http://127.0.0.1:<DSH端口>/oauth/callback`。hos
79
81
  ```json
80
82
  {
81
83
  "baseURL": "https://ai.example.edu/api/worker/v1",
82
- "credentialRef": "EXAMPLE_AI_TEST_API_KEY"
84
+ "credentialRef": "EDUWORK_API_KEY"
83
85
  }
84
86
  ```
85
87
 
@@ -88,9 +90,11 @@ Web 重定向地址固定为 `http://127.0.0.1:<DSH端口>/oauth/callback`。hos
88
90
  | `baseURL` | 是 | `worker-user-center-v1` Key Binding 接口组的基址。 |
89
91
  | `credentialRef` | 否 | 保存绑定后模型 API Key 的本地 DSH Credential Provider 名称。必须匹配 `^[A-Za-z_][A-Za-z0-9_]*$`,最长 128 字符。 |
90
92
 
91
- 协议类型固定为 `worker-user-center-v1`,请求中的 Provider ID 固定取 `provider.id`。如果省略 `credentialRef`,解析器保持向后兼容:将 Provider ID 转为大写、把非字母数字替换为 `_`,再追加 `_API_KEY`。例如 `example-ai` 默认对应 `EXAMPLE_AI_API_KEY`。
93
+ 请求中的 Provider ID 固定取 `provider.id`。`credentialRef` 省略时统一为 `EDUWORK_API_KEY`。旧配置中按本 Profile 的 `id` 或 `provider.id` 大写、非字母数字替换为 `_` 后追加 `_API_KEY` 的引用,按兼容别名规范化到同一默认值,不再按企业生成名称。其他显式引用原样保留。
94
+
95
+ `credentialRef` 只是本地秘密存储的引用名,不是 API Key,不发送给 OIDC、Key Binding 或模型服务。常规部署使用 `EDUWORK_API_KEY`;需要额外独立管理的显式引用仍可使用例如 `MY_TEST_MODEL_KEY`。默认槽位记录当前绑定的企业 Key;多个 Profile 共用时,仅凭据指纹与当前 Key 匹配的已验证登录可以读取它。重新绑定后,其他 Profile 不会借用该 Key,登出也不会删除其他登录写入的新 Key。个人模型使用的独立引用不受影响。
92
96
 
93
- `credentialRef` 只是本地秘密存储的引用名,不是 API Key,不发送给 OIDC、Key Binding 或模型服务。普通单环境部署应该省略它并使用默认值;同一 Provider ID 在生产和测试部署间复用时,必须为不同环境配置不同引用,例如 `CHATECNU_API_KEY` 与 `CHATECNU_QUOTA_TEST_API_KEY`,避免一个环境读取另一环境的 Key。
97
+ 升级只在同一 issuer、client ID、资源管理基址、模型服务基址、Provider ID 且仅旧自动引用改名时迁移原 Key。新槽位已有值时既不覆盖也不自动接管;无法证明归属时保留身份并重新连接模型资源。旧会话缺少指纹时,仅完整绑定相同且引用归属无歧义才兼容。
94
98
 
95
99
  Endpoint 路径、请求/响应字段和 Provider ID 语义属于协议事实,不得由 Profile 自定义。Native 宿主若返回 `runtimeCredentialRef`,其值必须与本字段规范化后的结果一致,否则插件失败关闭。
96
100
 
@@ -100,11 +104,11 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
100
104
 
101
105
  | 字段 | 必需 | 含义 |
102
106
  | --- | --- | --- |
103
- | `id` | 是 | DSH 路由 ID,也是默认凭据引用的来源;在所有已加载 Profile 中必须唯一。 |
107
+ | `id` | 是 | DSH 路由 ID;在所有已加载 Profile 中必须唯一。 |
104
108
  | `displayName` | 否 | 面向用户的 Provider 名称。 |
105
109
  | `adapter` | 是 | 精确字符串 `openai-compatible`。 |
106
110
  | `baseURL` | 是 | HTTPS OpenAI-compatible API 基址。 |
107
- | `reasoning` | 否 | 默认 DSH/pi-ai reasoning level,默认为 `high`。 |
111
+ | `reasoning` | 否 | 默认 DSH/pi-ai reasoning level,取值为 `off`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`,默认为 `high`。 |
108
112
  | `defaultContextWindow` | 否 | 正安全整数,默认 262144。 |
109
113
  | `defaultMaxTokens` | 否 | 正安全整数,默认 32768。 |
110
114
  | `maxRequestImageBytes` | 否 | 单次原生图片请求的累计大小预算。 |
@@ -113,7 +117,8 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
113
117
  | `streamIdleTimeoutMs` | 否 | 正数空闲超时,默认 300000。 |
114
118
  | `retryPolicy` | 否 | 由 DSH Provider 管理的重试策略;默认 normal/重试 2 次。 |
115
119
  | `compat` | 否 | 有边界的 pi-ai OpenAI 兼容事实。 |
116
- | `models` | 是 | 1–128 个唯一模型条目。 |
120
+ | `modelSource` | 否 | `profile`(默认)或 `discovery`;后者通过受管 Key 请求 `/models`。 |
121
+ | `models` | `profile` 模式 | 1–128 个唯一模型条目;`discovery` 可省略,已配置条目作为能力声明。 |
117
122
 
118
123
  `retryPolicy.mode` 可以是 `normal` 或 `always`。`always` 可能一直重试,直到成功、取消或销毁;没有明确产品决策时不应启用。该策略还会由 DSH 再次校验。
119
124
 
@@ -128,9 +133,12 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
128
133
  - `input` 可包含 `text`、`image` 或两者,默认 `text`;
129
134
  - 可选的正数 `contextWindow` 和 `maxTokens`;
130
135
  - 可选 `reasoning` 布尔值;
131
- - 可选 `reasoningEfforts` 对象或 `false`;
136
+ - 可选 `reasoningEfforts` 对象或 `false`;对象键限于 `off`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`,且只有 `off` 的过线值可以为 `null`;
137
+ - 可选 `defaultReasoningEffort`,且必须是该模型在 `reasoningEfforts` 中声明的档位;若省略,旧的 Provider 级 `reasoning` 会就近回落到模型的有效档位,同距时取较低档;
132
138
  - 可选的受限 `compat` 覆盖。
133
139
 
140
+ 声明 `reasoningEfforts` 后,未列出的档位会被显式标记为不支持;档位 ID 与过线值分开保存,因此 `xhigh` 不会被静默改成 `max`。若模型支持 thinking 但不支持用户选择档位,可只将 `compat.supportsReasoningEffort` 设为 `false`;若模型完全不支持 thinking,则将 `reasoning` 或 `reasoningEfforts` 设为 `false`。
141
+
134
142
  若模型支持 thinking,但不支持选择 reasoning effort,请设置:
135
143
 
136
144
  ```json
@@ -139,7 +147,7 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
139
147
  }
140
148
  ```
141
149
 
142
- Adapter 会保留 Profile 的 thinking 行为,并在校验和传输前移除不支持的用户所选 effort。不会因为 Provider 不支持 effort 参数而拒绝整个请求。
150
+ Adapter 会保留 Profile 的 thinking 行为:忽略历史会话中用户选择的 effort,按该模型可用档位解析 Profile 默认值,仅向 PiAi 传递内部启用信号;`compat.supportsReasoningEffort: false` 保证 HTTP 请求不包含 `reasoning_effort`。该信号不会变成用户可选档位,Profile 的 `off` 仍可关闭支持关闭的模型。不会因为 Provider 不支持 effort 参数而拒绝整个请求。
143
151
 
144
152
  ## 禁止写入的秘密
145
153
 
@@ -4,14 +4,14 @@
4
4
 
5
5
  This guide is for operators integrating `dsh-oidc` into their own DeepSeek Harness deployment. The result is a closed loop: users sign in through the organization's OIDC Provider, explicitly bind a revocable model runtime credential, inspect the enterprise Provider and model catalog, and call those models from ordinary DSH Web.
6
6
 
7
- `dsh-oidc` is Web-first and does not require Wails or ChatECNU Work. ECNU is only a reference deployment.
7
+ The same OIDC implementation supports both desktop shells and local Web validation. It does not require Wails or an ECNU service. This guide uses Web commands; new desktop compositions use `backend: desktop` as described in [desktop integration](desktop-host.en.md).
8
8
 
9
9
  ## 1. Prerequisites
10
10
 
11
11
  | Component | Minimum requirement |
12
12
  | --- | --- |
13
- | DSH Host | DeepSeek Harness `0.1.2-alpha.2` on Node.js 22+. |
14
- | Institutional enterprise-model integration service | One accountable owner jointly delivers the OIDC Provider, fixed Key Binding API, and OpenAI-compatible model gateway; all three are required. |
13
+ | DSH Host | This candidate targets DeepSeek Harness `0.1.5-rc.1` on Node.js 22+; do not mix it with the historical stable package. |
14
+ | Institutional enterprise-model integration service | Identity-only mode needs OIDC. Managed models additionally require the fixed Key Binding API and OpenAI-compatible gateway. |
15
15
  | Enterprise Profile | Trusted local JSON containing public configuration only. |
16
16
  | Credential Provider | The current Web backend supports trusted single-user local storage only. |
17
17
 
@@ -25,13 +25,13 @@ Register a public client without a client secret. Its redirect URI must exactly
25
25
  http://127.0.0.1:3080/oauth/callback
26
26
  ```
27
27
 
28
- `127.0.0.1` and `/oauth/callback` are fixed. `3080` is the recommended DSH port; if the DSH WebServer port changes, the registered URI must use the same port. Do not register `localhost`, a LAN address, or a public address. Discovery must publish `authorization_endpoint`, `token_endpoint`, `jwks_uri`, and `userinfo_endpoint`. UserInfo must contain a non-empty `sub` matching the ID Token; provide the standard `name` claim for a human-readable label. The current release accepts RS256 ID Tokens only.
28
+ This fixed-port example is for local Web validation. New desktops default to a temporary random port; see [desktop integration](desktop-host.en.md) for fixed-port IdPs. `127.0.0.1` and `/oauth/callback` are fixed. `3080` is the recommended DSH port; if the DSH WebServer port changes, the registered URI must use the same port. Do not register `localhost`, a LAN address, or a public address. Discovery must publish `authorization_endpoint`, `token_endpoint`, `jwks_uri`, and `userinfo_endpoint`. UserInfo must contain a non-empty `sub` matching the ID Token; provide the standard `name` claim for a human-readable label. The current release accepts RS256 ID Tokens only.
29
29
 
30
30
  See the complete [OIDC interoperability profile](oidc-interoperability.en.md).
31
31
 
32
32
  ## 3. Implement the complete institutional service
33
33
 
34
- One institutional delivery must provide the OIDC interface group above, the Key Binding interface group below, and an OpenAI-compatible model gateway that accepts the bound credentials. Internal systems may host different interfaces, but versioning, security, and operations have one accountable integration boundary. See the [server API specification](server-integration-contract.en.md).
34
+ For managed enterprise models, provide OIDC, the Key Binding group below and an OpenAI-compatible gateway accepting the bound key. Identity-only deployments may skip this section. Internal systems may host different interfaces, but versioning, security, and operations have one accountable integration boundary. See the [server API specification](server-integration-contract.en.md).
35
35
 
36
36
  The configured `keyBinding.baseURL` has four fixed operations:
37
37
 
@@ -42,7 +42,7 @@ POST /runtime-credential/resolve
42
42
  POST /runtime-credential/renew
43
43
  ```
44
44
 
45
- The Profile may additionally use optional `keyBinding.credentialRef` to isolate entries in the local DSH Credential Provider. It is not sent over the network and does not alter these operations. Omit it for an ordinary single-environment deployment; use distinct references when production and test reuse the same Provider ID.
45
+ The Profile may additionally use optional `keyBinding.credentialRef` to isolate entries in the local DSH Credential Provider. It is not sent over the network and does not alter these operations. Its default is `EDUWORK_API_KEY`; explicit use of that name is also accepted. Use another reference only for independently managed credentials. See the [Profile specification](enterprise-profile.en.md) for legacy migration and ownership checks.
46
46
 
47
47
  Every request carries the OIDC Access Token as a Bearer credential. The service must validate issuer, audience, expiry, scopes, subject, and organization authorization. It must not trust `provider_id` by itself. Credential responses are `no-store`, and `api_key` must never enter logs, metrics labels, or error details.
48
48
 
@@ -56,10 +56,10 @@ The Profile is trusted deployment data, not a secret store. It must not contain
56
56
 
57
57
  ## 5. Install into ordinary DSH Web
58
58
 
59
- The package is itself an installable DSH Bundle. Team deployments should install the reviewed, exact version from npm:
59
+ The package is an installable DSH Bundle. Pin `0.2.0` with a coherent DSH `0.1.5-rc.1` host. Consult the npm registry for publication status; during release preparation use a frozen candidate or source checkout if the version is unavailable:
60
60
 
61
61
  ```bash
62
- dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
62
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.2.0
63
63
  ```
64
64
 
65
65
  For auditing, development, or testing unpublished changes, install from a local checkout instead:
@@ -78,16 +78,12 @@ From the parent directory, the equivalent explicit relative-path command is:
78
78
  dsh plugin --profile web add ./dsh-oidc
79
79
  ```
80
80
 
81
- DSH links the checkout into `$DSH_HOME/profiles/web`; it does not scan or copy the invoking directory. Keep the checkout in place and pin a reviewed commit for source-based deployments. To intentionally follow alpha updates, use:
82
-
83
- ```bash
84
- dsh plugin --profile web add @eduwork/dsh-oidc@alpha
85
- ```
81
+ DSH links the checkout into `$DSH_HOME/profiles/web`; it does not scan or copy the invoking directory. Keep the checkout in place and pin a reviewed commit for source-based deployments. Production and team Profiles should use an exact npm version and must not mix another DSH prerelease line.
86
82
 
87
83
  Set the trusted local Profile path and start DSH on the fixed loopback host:
88
84
 
89
85
  ```bash
90
- export DSH_OIDC_ENTERPRISE_PROFILE=/etc/dsh/enterprise-profile.json
86
+ export EDUWORK_OIDC_PROFILE=/etc/dsh/enterprise-profile.json
91
87
  dsh --profile web --host 127.0.0.1 --port 3080 --no-open
92
88
  ```
93
89
 
@@ -104,12 +100,12 @@ A product-owned Bundle may mount the plugin explicitly instead of using the defa
104
100
  - id: enterprise-oidc
105
101
  name: '@eduwork/dsh-oidc'
106
102
  config:
107
- profilePathEnv: DSH_OIDC_ENTERPRISE_PROFILE
103
+ profilePathEnv: EDUWORK_OIDC_PROFILE
108
104
  web:
109
105
  returnPath: /
110
106
  ```
111
107
 
112
- Desktop products may use `backend: native`, point `profilePathEnv` at the same standard Enterprise Profile used by Web, and supply the capability-detected `enterpriseAccounts` service. Product-owned institution, tenant, or account catalogs MUST be converted to an Enterprise Profile by the product assembly layer before `dsh-oidc` reads them. Wails, Electron, Tauri, and other hosts can implement that boundary; the plugin depends on neither a desktop framework nor a product catalog format. See [DSH integration](dsh-integration.en.md).
108
+ New desktop products should use `backend: desktop`, sharing the temporary loopback callback and official `nativeCommand`; see [desktop integration](desktop-host.en.md). Legacy hosts may still use `backend: native`, point `profilePathEnv` at the same standard Enterprise Profile used by Web, and supply the capability-detected `enterpriseAccounts` service. Product-owned institution, tenant, or account catalogs MUST be converted to an Enterprise Profile by the product assembly layer before `dsh-oidc` reads them. Wails, Electron, Tauri, and other hosts can implement that boundary; the plugin depends on neither a desktop framework nor a product catalog format. See [DSH integration](dsh-integration.en.md).
113
109
 
114
110
  ## 7. Acceptance checklist
115
111
 
@@ -134,4 +130,4 @@ The current Web backend does not support shared Web. A shared scenario needs a n
134
130
  - **A subject string is shown instead of a name:** return a non-empty standard `name` from UserInfo under the `profile` scope; private JSON-path mappings are intentionally unsupported.
135
131
  - **Login works but models do not:** inspect `/bootstrap`, explicit provisioning state, exact `provider_id` equality, and whether the model gateway accepts the bound key.
136
132
  - **Thinking works but selectable effort does not:** set model `compat.supportsReasoningEffort` to `false`; thinking remains enabled while the unsupported effort parameter is removed.
137
- - **Why the enterprise controls are inside Models:** DSH `0.1.2-alpha.2` exposes the official `settings.models.footer` extension slot. `dsh-oidc` mounts its management UI there and leaves the upstream Models page enabled; no product-private Models-page fork is required.
133
+ - **Where enterprise controls live:** the official `settings.models.footer` slot displays configured institutions while keeping personal API keys in the upstream Models settings. Institutions come from trusted distribution files; products may offer a file-opening action. The plugin does not expose a form for arbitrary endpoint changes.
@@ -16,8 +16,8 @@
16
16
 
17
17
  | 组件 | 谁提供 | 最低要求 |
18
18
  | --- | --- | --- |
19
- | DSH Host | 部署方 | DeepSeek Harness `0.1.2-alpha.2`,Node.js 22+。 |
20
- | 机构企业模型集成服务 | 同一服务所有者 | 共同提供 OIDC Provider、固定 Key Binding 和 OpenAI-compatible 模型网关;三者全部必需。 |
19
+ | DSH Host | 部署方 | 本版基线 DeepSeek Harness `0.1.5-rc.1`,Node.js 22+;不要与历史稳定包混用。 |
20
+ | 机构企业模型集成服务 | 同一服务所有者 | 纯身份档提供 OIDC;托管模型档再联合提供固定 Key Binding 与 OpenAI-compatible 模型网关。 |
21
21
  | Enterprise Profile | 部署方 | 一份受信任的本地 JSON,只存公开配置,不存密钥或个人信息。 |
22
22
  | Credential Provider | DSH Host | 当前 Web backend 仅支持可信单用户本机存储。 |
23
23
 
@@ -31,7 +31,7 @@
31
31
  http://127.0.0.1:3080/oauth/callback
32
32
  ```
33
33
 
34
- `127.0.0.1` 和 `/oauth/callback` 固定不可配置。`3080` 是推荐的 DSH 端口;若修改 DSH WebServer 端口,OIDC 注册值必须使用相同端口。不要登记 `localhost`、局域网地址或公网地址。
34
+ 以下固定端口用于本机 Web 验证。新桌面默认临时随机端口,固定端口 IdP 的配置方法见 [桌面宿主接入](desktop-host.md)。`127.0.0.1` 和 `/oauth/callback` 固定不可配置。`3080` 是推荐的 DSH 端口;若修改 DSH WebServer 端口,OIDC 注册值必须使用相同端口。不要登记 `localhost`、局域网地址或公网地址。
35
35
 
36
36
  OIDC Provider 必须通过 Discovery 发布 `authorization_endpoint`、`token_endpoint`、`jwks_uri` 和 `userinfo_endpoint`,支持 PKCE `S256`,并返回:
37
37
 
@@ -43,7 +43,7 @@ OIDC Provider 必须通过 Discovery 发布 `authorization_endpoint`、`token_en
43
43
 
44
44
  ## 3. 实现完整机构服务端
45
45
 
46
- 同一机构服务交付必须完整提供上一节的 OIDC、下面的 Key Binding,以及接受绑定凭据的 OpenAI-compatible 模型网关。它们可以由内部不同系统承载,但必须有统一的版本、安全和运维责任。接口定义见[服务端接口规范](server-integration-contract.md)。
46
+ 本节针对托管企业模型能力:需要上一节的 OIDC、下面的 Key Binding,以及接受绑定凭据的 OpenAI-compatible 模型网关。纯身份档可跳过本节。它们可以由内部不同系统承载,但必须有统一的版本、安全和运维责任。接口定义见[服务端接口规范](server-integration-contract.md)。
47
47
 
48
48
  Key Binding 不是 OIDC 标准的一部分,而是 `dsh-oidc` 定义的企业模型凭据协议。Enterprise Profile 用 `baseURL` 指定接口组基址,插件固定调用:
49
49
 
@@ -54,7 +54,7 @@ POST {baseURL}/runtime-credential/resolve
54
54
  POST {baseURL}/runtime-credential/renew
55
55
  ```
56
56
 
57
- Profile 还可以用可选的 `keyBinding.credentialRef` 隔离本地 DSH Credential Provider 中的秘密条目。它不参与网络请求,也不改变下列接口;普通单环境部署省略即可。生产/测试复用相同 Provider ID 时,应使用不同的引用名。
57
+ Profile 还可以用可选的 `keyBinding.credentialRef` 隔离本地 DSH Credential Provider 中的秘密条目。它不参与网络请求,也不改变下列接口;默认统一为 `EDUWORK_API_KEY`,也接受同名显式配置;只有需要独立管理的自定义引用才另行指定。旧自动名称兼容迁移和身份归属校验见 [Profile 规范](enterprise-profile.md)。
58
58
 
59
59
  每个请求都携带 OIDC Access Token:
60
60
 
@@ -117,12 +117,14 @@ Authorization: Bearer <oidc-access-token>
117
117
 
118
118
  Profile 是部署配置,不是用户输入。它可以声明模型事实和有限品牌 token,但不能加载脚本、CSS、工具、Skill 或远程 Provider adapter。字段全集和安全限制见 [Enterprise Profile 规范](enterprise-profile.md)。
119
119
 
120
- ## 5. 安装到普通 DSH Web
120
+ ## 5. 安装到本机 DSH Web
121
+
122
+ 本版采用精确的 `0.2.0` 与统一 DSH `0.1.5-rc.1`。发布状态以 npm registry 为准;若准备期间尚未发布,使用本地冻结候选或下方源码方式,不混装旧 DSH 依赖。
121
123
 
122
124
  `dsh-oidc` 本身是可直接安装的 DSH Bundle。团队部署应从 npm 安装经过复核的精确版本:
123
125
 
124
126
  ```bash
125
- dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
127
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.2.0
126
128
  ```
127
129
 
128
130
  需要审计、开发或测试尚未发布的改动时,再从本地 checkout 安装:
@@ -141,23 +143,19 @@ dsh plugin --profile web add .
141
143
  dsh plugin --profile web add ./dsh-oidc
142
144
  ```
143
145
 
144
- DSH 会把本地 checkout 链接到 `$DSH_HOME/profiles/web`,不会扫描或复制当前目录;安装完成后不要移动或删除 checkout。源码部署应固定经过审核的 commit。若明确希望持续跟随 alpha 更新,也可以使用:
145
-
146
- ```bash
147
- dsh plugin --profile web add @eduwork/dsh-oidc@alpha
148
- ```
146
+ DSH 会把本地 checkout 链接到 `$DSH_HOME/profiles/web`,不会扫描或复制当前目录;安装完成后不要移动或删除 checkout。源码部署应固定经过审核的 commit。生产或团队 Profile 应使用精确 npm 版本,不要混装其他 DSH 预发布线。
149
147
 
150
148
  设置 Enterprise Profile 路径,并让 DSH 监听固定 loopback host:
151
149
 
152
150
  ```bash
153
- export DSH_OIDC_ENTERPRISE_PROFILE=/etc/dsh/enterprise-profile.json
151
+ export EDUWORK_OIDC_PROFILE=/etc/dsh/enterprise-profile.json
154
152
  dsh --profile web --host 127.0.0.1 --port 3080 --no-open
155
153
  ```
156
154
 
157
155
  PowerShell 示例:
158
156
 
159
157
  ```powershell
160
- $env:DSH_OIDC_ENTERPRISE_PROFILE = 'C:\dsh-config\enterprise-profile.json'
158
+ $env:EDUWORK_OIDC_PROFILE = 'C:\dsh-config\enterprise-profile.json'
161
159
  dsh --profile web --host 127.0.0.1 --port 3080 --no-open
162
160
  ```
163
161
 
@@ -174,12 +172,12 @@ dsh --profile web --host 127.0.0.1 --port 3080 --no-open
174
172
  - id: enterprise-oidc
175
173
  name: '@eduwork/dsh-oidc'
176
174
  config:
177
- profilePathEnv: DSH_OIDC_ENTERPRISE_PROFILE
175
+ profilePathEnv: EDUWORK_OIDC_PROFILE
178
176
  web:
179
177
  returnPath: /
180
178
  ```
181
179
 
182
- 桌面宿主可以切换到 native backend:
180
+ 仅为兼容旧宿主,仍保留以下 native backend 示例:
183
181
 
184
182
  ```yaml
185
183
  - insert:
@@ -191,7 +189,7 @@ dsh --profile web --host 127.0.0.1 --port 3080 --no-open
191
189
  profilePathEnv: PRODUCT_ENTERPRISE_PROFILE
192
190
  ```
193
191
 
194
- native backend 必须提供 `enterpriseAccounts` 服务,并与 Web 一样传入标准 Enterprise Profile。产品自有目录、租户或账号配置必须先由产品装配层转换为该 Profile,不能交给 `dsh-oidc` 解释。宿主可以由 Wails、Electron、Tauri 或其他技术实现;插件本身不依赖任何桌面框架或产品目录格式。接口和能力探测见 [DSH 集成说明](dsh-integration.md)。
192
+ 上面是旧版 `native` 桥接示例;新 Wails/Electron 组合应使用 `backend: desktop`,共用临时 loopback 回调与官方 `nativeCommand`,无需另写认证桥。见 [桌面 Host 集成](desktop-host.md)。旧 native backend 必须提供 `enterpriseAccounts` 服务,并与 Web 一样传入标准 Enterprise Profile。产品自有目录、租户或账号配置必须先由产品装配层转换为该 Profile,不能交给 `dsh-oidc` 解释。宿主可以由 Wails、Electron、Tauri 或其他技术实现;插件本身不依赖任何桌面框架或产品目录格式。接口和能力探测见 [DSH 集成说明](dsh-integration.md)。
195
193
 
196
194
  ## 7. 上线前验收
197
195
 
@@ -234,6 +232,6 @@ native backend 必须提供 `enterpriseAccounts` 服务,并与 Web 一样传
234
232
 
235
233
  插件会保留 thinking 行为并移除不受支持的 effort 参数,不会因此拒绝调用。
236
234
 
237
- ### 为什么企业服务是单独的设置页
235
+ ### 企业服务设置在哪里
238
236
 
239
- 当前 DSH `0.1.2-alpha.2` 已提供正式的 `settings.models.footer` 插槽。插件直接把企业模型管理能力挂载到官方“模型”页,并保持官方模型页启用,不再依赖产品私有的模型页 fork。
237
+ 插件通过官方 `settings.models.footer` 插槽显示已配置机构,保留官方“模型”设置页和个人 API Key。机构配置来自发行方的可信文件;产品可以提供打开配置文件的入口,插件不提供任意创建或修改机构端点的表单。
@@ -6,7 +6,7 @@
6
6
 
7
7
  This document defines `worker-user-center-v1`, the enterprise management protocol used by `dsh-oidc` to bind an OIDC-authenticated subject to a model runtime API key. It is not part of OIDC.
8
8
 
9
- It is a required part of the [server API specification](server-integration-contract.en.md). An implementation must also provide the OIDC Provider and model gateway required by that specification; implementing only the API below is not a complete `dsh-oidc` server.
9
+ It is part of the managed-model tier of the [server API specification](server-integration-contract.en.md), delivered together with the OIDC Provider and model gateway. Identity-only Profiles do not require Key Binding.
10
10
 
11
11
  The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHALL**, **SHALL NOT**, **SHOULD**, **SHOULD NOT**, **RECOMMENDED**, **NOT RECOMMENDED**, **MAY**, and **OPTIONAL** are interpreted as described by RFC 2119 and RFC 8174.
12
12
 
@@ -105,7 +105,7 @@ Valid `runtime_credential.status` values are:
105
105
 
106
106
  `subject` MAY carry informational management-plane display data. The client MUST NOT use it to replace OIDC `sub` or `name`.
107
107
 
108
- `protocol_version`, if present, MUST be `worker-user-center/v1`. It is optional during v1 adoption; a future major protocol can require explicit negotiation.
108
+ `protocol_version`, if present, MUST be `worker.user-center.v1`, `worker-user-center/v1` or `eduwork-resources/v1` (aliases of the same v1 wire; unknown versions are rejected). It is optional during v1 adoption; a future major protocol can require explicit negotiation.
109
109
 
110
110
  ## 6. Provision
111
111
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  本文定义 `worker-user-center-v1`:`dsh-oidc` 用它把经 OIDC 认证的 subject 与模型运行时 API Key 绑定。这是企业管理协议,不属于 OIDC 标准。
8
8
 
9
- 它是[服务端接口规范](server-integration-contract.md)的必需组成部分。实现方必须同时提供该规范要求的 OIDC Provider 与模型网关;只实现以下 API 不构成完整的 `dsh-oidc` 服务端。
9
+ 它是[服务端接口规范](server-integration-contract.md)中托管模型能力档的组成部分,需与 OIDC Provider 和模型网关共同实现。纯身份 Profile 不要求 Key Binding。
10
10
 
11
11
  关键词 **必须(MUST)**、**不得(MUST NOT)**、**必需(REQUIRED)**、**应该(SHOULD)**、**不应该(SHOULD NOT)**、**建议(RECOMMENDED)**、**不建议(NOT RECOMMENDED)**、**可以(MAY)** 和 **可选(OPTIONAL)** 按 RFC 2119 与 RFC 8174 解释。
12
12
 
@@ -105,7 +105,7 @@ Accept: application/json
105
105
 
106
106
  `subject` 可以携带仅供管理面显示的信息。客户端不得用它替换 OIDC `sub` 或 `name`。
107
107
 
108
- 若返回 `protocol_version`,其值必须是 `worker-user-center/v1`。该字段在 v1 采用阶段可选;未来 major 协议可以要求显式协商。
108
+ 若返回 `protocol_version`,其值必须是 `worker.user-center.v1`、`worker-user-center/v1` 或 `eduwork-resources/v1`(三个别名共享同一组 v1 字段与路径,未知版本拒绝)。该字段在 v1 采用阶段可选;未来 major 协议可以要求显式协商。
109
109
 
110
110
  ## 6. Provision
111
111
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  [简体中文](oidc-interoperability.md) | **English**
4
4
 
5
- OIDC is one part of the [server API specification](server-integration-contract.en.md). A conforming integration also requires the same accountable service owner to jointly deliver fixed Key Binding and the model gateway; implementing this document alone is not complete.
5
+ OIDC is the identity tier of the [server API specification](server-integration-contract.en.md). An identity-only Profile may implement this tier alone. Managed enterprise keys and automatic model setup additionally require Key Binding and the model gateway.
6
6
 
7
7
  ## Standards
8
8
 
@@ -93,8 +93,8 @@ The plugin intentionally has no JSON path mapping or private profile endpoint. O
93
93
 
94
94
  ## Refresh and logout
95
95
 
96
- If the access token is within 90 seconds of expiry and a refresh token exists, the plugin refreshes it. On `invalid_grant`, the stored OIDC session and local model credential are removed and login is required. A rotated refresh token replaces the previous one. An expired session without a refresh token is handled the same way when an active session is next required.
96
+ If the access token is within 90 seconds of expiry and a refresh token exists, the plugin refreshes it. On `invalid_grant`, the stored OIDC session and its still-owned local model credential are removed and login is required. A rotated refresh token replaces the previous one. An expired session without a refresh token is handled the same way when an active session is next required.
97
97
 
98
- Logout attempts RFC 7009 revocation when Discovery publishes `revocation_endpoint`, then removes both the OIDC session record and the derived model credential locally. Remote revocation failure is logged without blocking local cleanup.
98
+ Logout attempts RFC 7009 revocation when Discovery publishes `revocation_endpoint`, then removes the OIDC session record and only a model credential still owned by that session. A key written by another profile into the shared reference is preserved. Remote revocation failure is logged without blocking local cleanup.
99
99
 
100
100
  The plugin does not implement RP-Initiated Logout or front/back-channel logout in this version.
@@ -2,7 +2,7 @@
2
2
 
3
3
  **简体中文** | [English](oidc-interoperability.en.md)
4
4
 
5
- OIDC 是[服务端接口规范](server-integration-contract.md)的一部分。合格的机构接入还必须由同一服务所有者联合提供固定 Key Binding 和模型网关能力;只实现本文件并不构成完整接入。
5
+ OIDC 是[服务端接口规范](server-integration-contract.md)的身份能力档,纯身份 Profile 可只实现本文件。只有需要托管模型 Key 和自动配置企业模型时,才必须同时提供 Key Binding 和模型网关。
6
6
 
7
7
  ## 标准依据
8
8
 
@@ -95,6 +95,6 @@ TLS 信任和 DNS 解析仍由 Node.js 宿主和操作系统负责。
95
95
 
96
96
  当 access token 距离过期不足 90 秒且存在 refresh token 时,插件会刷新会话。若收到 `invalid_grant`,会删除已存 OIDC 会话和本地模型凭据,并要求重新登录。轮换后的 refresh token 会替换旧值。没有 refresh token 的过期会话在下次需要活动会话时按同样方式处理。
97
97
 
98
- 退出登录时,如果 Discovery 发布 `revocation_endpoint`,插件会尝试按 RFC 7009 撤销 token;随后在本地删除 OIDC 会话记录和派生模型凭据。远程撤销失败会被记录,但不阻止本地清理。
98
+ 退出登录时,如果 Discovery 发布 `revocation_endpoint`,插件会尝试按 RFC 7009 撤销 token;随后在本地删除该 Profile 的 OIDC 会话与归属于它的托管模型凭据;共享引用已被其他登录改写时不会删除另一方的 Key。远程撤销失败会被记录,但不阻止本地清理。
99
99
 
100
100
  当前版本不实现 RP-Initiated Logout、front-channel logout 或 back-channel logout。
@@ -0,0 +1,51 @@
1
+ # EduWork public identity and resource protocol v1
2
+
3
+ [简体中文](public-resource-protocol.md) | **English**
4
+
5
+ The public `@eduwork/dsh-oidc` package owns identity login, managed model keys and model configuration. Quota and heartbeat are institution-only extensions; the public package neither requests nor renders quota. Remote speech, institution activity heartbeats and institution-specific tools belong in separate plugins. Each deployment is a local single-user client; the browser connects to the local Runtime.
6
+
7
+ ## Modes and configuration
8
+
9
+ Identity-only profiles omit both `keyBinding` and `provider`; successful OIDC login completes identity integration. Users configure personal API keys through ordinary DSH model settings. Organization logout leaves those personal credentials alone. See the [identity-only example](../examples/identity-only.example.json).
10
+
11
+ Full integration includes both fields. `keyBinding.type` defaults to `worker-user-center-v1`, while `eduwork-resources-v1` explicitly names the public resource contract. Both use the existing deployed wire paths; current institutions do not need new endpoint URLs. See the [discovery example](../examples/resources-discovery.example.json).
12
+
13
+ Both modes permit other models and personal API keys. Optional `brand` only controls presentation; an empty brand leaves the host product name unchanged.
14
+
15
+ ## Endpoints and credentials
16
+
17
+ | Capability | Endpoint | Authentication |
18
+ | --- | --- | --- |
19
+ | Identity | OIDC Discovery, Authorization Code + PKCE S256, Token, JWKS, UserInfo | OIDC |
20
+ | Credential state | `GET {keyBinding.baseURL}/bootstrap` | OIDC access token |
21
+ | Provision, resolve, renew | `POST {keyBinding.baseURL}/runtime-credential/{provision,resolve,renew}` | OIDC access token |
22
+ | Models | `GET {provider.baseURL}/models` | Managed model API key |
23
+ | Inference | `POST {provider.baseURL}/chat/completions` | Managed model API key |
24
+
25
+ The [Key Binding OpenAPI](../protocol/openapi.yaml) retains existing lifecycle fields and idempotency requirements. The [resource OpenAPI](../protocol/resources.openapi.yaml) defines model discovery. Optional bootstrap `protocol_version` accepts `worker.user-center.v1`, `worker-user-center/v1` or `eduwork-resources/v1`; unknown versions fail closed. Bootstrap never replaces verified OIDC identity, trusted endpoint configuration or executable components. Resource HTTP requests do not follow redirects.
26
+
27
+ ## Model discovery
28
+
29
+ `provider.modelSource` defaults to `profile`, preserving reviewed distribution metadata. With `discovery`, `/models` is read after managed key resolution; initial `models` may be omitted and no fake route is registered before discovery.
30
+
31
+ The response is `{"data":[{"id":"model-a"}]}` with up to 128 unique model IDs. IDs already declared in the trusted Profile retain their capabilities. New IDs are conservatively text-only with reasoning disabled; model names are not capability evidence. Arbitrary URLs, scripts and adapter configuration in remote responses are ignored.
32
+
33
+ Empty or invalid discovery preserves the last usable catalog and returns `models_unavailable`. Successful discovery replaces the provider snapshot for new calls; prepared calls retain their earlier snapshot. After restart the first signed-in status read rediscovers models. Personal provider routes are unaffected.
34
+
35
+ ## Host integration
36
+
37
+ The plugin is `@eduwork/dsh-oidc`, with bundle layer ID `enterprise-oidc`. Use `backend: web` and `uiMode: standard` for the public interface; `external` keeps public RPC while allowing a product-owned UI. `allowEmptyProfiles: true` supports a public client using only personal keys.
38
+
39
+ `EDUWORK_OIDC_PROFILE` names a single profile, an array, or a `{ "profiles": [...] }` file. When absent, `DSH_OIDC_ENTERPRISE_PROFILE` remains a compatible fallback. Explicit `profilePathEnv` names remain supported.
40
+
41
+ Existing `oidcAccounts.configuration/status/begin/reconcile/logout/management` RPCs remain available. New `resources(profileID)` returns `{profileID, modelSource, models, issues}` without secrets. `reconcile` automatically refreshes model metadata. The legacy native backend does not call its former quota method; new `backend: desktop` shares the Web OIDC implementation but uses a temporary loopback callback without requiring a persistent WebServer.
42
+
43
+ Institution plugins may call Host-only `ctx.oidcAccounts.authorizedFetch(profileID, endpoint, init)` to reuse the current OIDC access token, refresh and one 401 retry. It returns a regular `Response`, has no Remote marker, and never exposes tokens to the browser. Allowed origins default to the configured issuer and Key Binding origins. Additional exact HTTPS origins require trusted host `authorizedOrigins` configuration and cannot be set by browser RPC. Concurrent requests share one rotating refresh operation. This is an authenticated transport seam, not a heartbeat or speech business protocol.
44
+
45
+ Host event `oidc/accounts-changed` carries `{profileID, state}`. Both `authenticated` and `connected` mean identity is signed in; identity-only `connected` does not require a model key. `signed_out` means signed out. Authorized requests without a usable identity throw `oidc_login_required`; forbidden origins throw `oidc_authorized_origin_denied`. A second HTTP 401 remains a Response for the caller to handle. Explicit sign-out should not automatically produce an expiry warning.
46
+
47
+ Changed issuer, client ID or resource endpoints prevent stale managed keys from reaching a different deployment. Existing Web identity records can retain identity while reacquiring the managed model key. Personal API keys remain unaffected by organization logout or resource-binding changes.
48
+
49
+
50
+
51
+ Institution account extensions use the [Host transport and account-menu slot contract](account-extensions.en.md). A configured capability string does not activate an extension; install and configure the institution plugin explicitly.