@eduwork/dsh-oidc 0.3.0-dev.2 → 0.3.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 (57) hide show
  1. package/CHANGELOG.en.md +6 -0
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +9 -1
  4. package/README_EN.md +9 -1
  5. package/THIRD_PARTY_NOTICES.en.md +5 -4
  6. package/THIRD_PARTY_NOTICES.md +5 -5
  7. package/docs/account-extensions.en.md +7 -1
  8. package/docs/account-extensions.md +7 -1
  9. package/docs/compatibility.en.md +3 -1
  10. package/docs/compatibility.md +3 -1
  11. package/docs/development.en.md +1 -1
  12. package/docs/development.md +1 -1
  13. package/docs/dsh-integration.en.md +3 -3
  14. package/docs/dsh-integration.md +3 -3
  15. package/docs/enterprise-profile.en.md +47 -0
  16. package/docs/enterprise-profile.md +47 -0
  17. package/docs/gateway-auth/README.md +6 -5
  18. package/docs/gateway-auth/README_EN.md +6 -5
  19. package/docs/gateway-auth/experimental-oidc-llm.en.md +9 -7
  20. package/docs/gateway-auth/experimental-oidc-llm.md +8 -6
  21. package/docs/gateway-auth/litellm-setup.en.md +9 -3
  22. package/docs/gateway-auth/litellm-setup.md +9 -3
  23. package/docs/gateway-auth/oidc-llm-draft.en.md +89 -63
  24. package/docs/gateway-auth/oidc-llm-draft.md +86 -60
  25. package/docs/getting-started.en.md +3 -1
  26. package/docs/getting-started.md +3 -1
  27. package/docs/key-binding-protocol.en.md +1 -1
  28. package/docs/key-binding-protocol.md +1 -1
  29. package/docs/oidc-interoperability.en.md +1 -1
  30. package/docs/oidc-interoperability.md +1 -1
  31. package/docs/open-integration.en.md +3 -1
  32. package/docs/open-integration.md +3 -1
  33. package/examples/ecnu.enterprise-profile.example.json +2 -0
  34. package/examples/enterprise-profile.example.json +2 -0
  35. package/examples/litellm.enterprise-profile.example.json +9 -1
  36. package/examples/oidc-llm.enterprise-profile.example.json +33 -1
  37. package/examples/resources-discovery.example.json +7 -1
  38. package/lib/callback-page.js +9 -4
  39. package/lib/client.js +460 -360
  40. package/lib/desktop-oidc.js +2 -2
  41. package/lib/gateway-backend.js +20 -5
  42. package/lib/index.js +8 -6
  43. package/lib/litellm-protocol.js +2 -1
  44. package/lib/model-types.js +7 -0
  45. package/lib/oidc-llm-protocol.js +6 -2
  46. package/lib/oidc.js +19 -13
  47. package/lib/profile.js +24 -9
  48. package/lib/provider/authorization-scope.js +4 -0
  49. package/lib/provider/core.js +3 -3
  50. package/lib/provider/index.js +18 -2
  51. package/lib/provider/transform-adapter.js +4 -0
  52. package/lib/resources.js +12 -4
  53. package/lib/token-lifetime.js +15 -0
  54. package/lib/typert-schemas.js +14 -12
  55. package/package.json +104 -97
  56. package/protocol/resources.openapi.yaml +11 -3
  57. package/schema/enterprise-profile.v1alpha1.schema.json +36 -0
package/CHANGELOG.en.md CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  All notable changes are documented here. The format follows Keep a Changelog principles and the project uses Semantic Versioning with pre-1.0 qualifications described in `docs/compatibility.en.md`.
6
6
 
7
+ ## [0.3.0] — 2026-10-19
8
+
9
+ - Target DSH 0.2.1-rc.2 and compatible 0.2.x stable Hosts with pi-ai 1.1.0; remove retired DSH dependency declarations.
10
+ - Publish the Web-first OIDC/token-model integration, explicit extension-service authorization and typed model capabilities already used by EduWork.
11
+ - Preserve refresh-token rotation, logout isolation and reasoning replay handling. The removed legacy Key Binding/native backend must be migrated before upgrading.
12
+
7
13
  ## [0.3.0-dev.2] - 2026-09-21
8
14
 
9
15
  - Explicitly allow HTTP test services through the single `allowInsecureDevelopment` flag, disabled by default; HTTPS behavior is unchanged.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  所有重要变更均记录于此。格式遵循 Keep a Changelog 原则;项目使用语义化版本,并遵循[兼容性与发布策略](docs/compatibility.md)中对 1.0 之前版本的说明。
6
6
 
7
+ ## [0.3.0] — 2026-10-19
8
+
9
+ - 适配 DSH 0.2.1-rc.2 与兼容的 0.2.x 正式版,采用 pi-ai 1.1.0,移除已退役的 DSH 依赖声明。
10
+ - 发布已在 EduWork 使用的 Web 优先 OIDC/Token 模型接入、额外服务显式授权及模型能力声明。
11
+ - 保留刷新令牌轮换、退出登录隔离和思考历史回放处理;升级前须迁移已删除的旧 Key Binding/native backend 配置。
12
+
7
13
  ## [0.3.0-dev.2] - 2026-09-21
8
14
 
9
15
  - 使用 `allowInsecureDevelopment` 单一开关显式允许 HTTP 测试服务,默认关闭;HTTPS 行为不变。
package/README.md CHANGED
@@ -6,7 +6,13 @@
6
6
 
7
7
  当前源码提供 LiteLLM native OAuth 和显式启用的 oidc-llm 0.1 实验接入。两者共用浏览器/loopback、PKCE、Host 会话、刷新、退出与 DSH Provider;模型请求使用当前 Access Token,客户端不再申请或保存机构模型 API Key。个人 API Key 设置独立保留。
8
8
 
9
- 本分支尚未发布 npm 或桌面版本;已发布版本的行为以对应版本文档为准。旧 OIDC + Key Binding 配置在本源码中会被明确拒绝,迁移见[旧方案迁移](docs/key-binding-protocol.md)。服务端可继续保留旧接口供旧客户端使用。
9
+ 版本 `@eduwork/dsh-oidc@0.3.0` 面向 Node.js 24.18+ 和 DSH 0.2.1-rc.2,可独立安装到本机 DSH Web Profile;Web 后端不依赖 EduWork 桌面桥接。机构模型接入需要部署者提供兼容网关和公开 Profile 配置。
10
+
11
+ ```sh
12
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.3.0
13
+ ```
14
+
15
+ 启动 DSH 前,将 `EDUWORK_OIDC_PROFILE` 设为 Profile JSON 文件的绝对路径。默认 bundle 使用 Web 后端;EduWork 桌面用户继续使用发行配置。旧 Key Binding 配置需要先[迁移](docs/key-binding-protocol.md)。
10
16
 
11
17
  ## 开始接入
12
18
 
@@ -15,6 +21,8 @@
15
21
  3. 在桌面 Host 使用 backend: desktop,本机 Web 使用 backend: web。仅身份登录仍可使用[纯身份示例](examples/identity-only.example.json);该模式不提供企业模型。
16
22
  4. 登录后自动读取当前授权的模型目录。账户刷新不应覆盖用户后来选择的个人模型。
17
23
 
24
+ 当前源码按模型 `type` 注册,仅 `llm` 进入对话。服务器只返回 ID 时,升级前须按实际模型 ID 补充 `provider.models[].type`;服务端类型优先,专用及类型未知的模型不进入对话。仅返回 ID 的服务端需同时补齐配置中的模型类型。详见[模型说明](docs/enterprise-profile.md)。
25
+
18
26
  从源码验证:
19
27
 
20
28
  ~~~sh
package/README_EN.md CHANGED
@@ -6,7 +6,13 @@ Sign in with an organization and use its authorized models directly.
6
6
 
7
7
  The current source supports LiteLLM native OAuth and explicitly enabled experimental oidc-llm 0.1. Both reuse browser/loopback transport, PKCE, Host sessions, refresh, logout and the DSH Provider. Model requests use the current Access Token; this client no longer provisions or stores organization model API keys. Personal API-key settings remain independent.
8
8
 
9
- This branch has not been published to npm or a desktop release. Published versions retain their documented behavior. The current source rejects old OIDC + Key Binding profiles; see [migration](docs/key-binding-protocol.en.md). Servers may retain legacy endpoints for older clients.
9
+ Version `@eduwork/dsh-oidc@0.3.0` targets Node.js 24.18+ and DSH 0.2.1-rc.2. It supports a standalone local DSH Web profile; no EduWork desktop bridge is required for that backend. Organization model access requires a compatible gateway and a public profile configured by its operator.
10
+
11
+ ```sh
12
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.3.0
13
+ ```
14
+
15
+ Set `EDUWORK_OIDC_PROFILE` to the absolute path of your profile JSON before starting DSH. The default bundle uses the Web backend. EduWork desktop users continue to use their distribution configuration. Legacy Key Binding profiles require [migration](docs/key-binding-protocol.en.md).
10
16
 
11
17
  ## Getting started
12
18
 
@@ -15,6 +21,8 @@ This branch has not been published to npm or a desktop release. Published versio
15
21
  3. Use backend: desktop for desktop Hosts or backend: web for local Web. [Identity-only OIDC](examples/identity-only.example.json) remains available without organization models.
16
22
  4. Sign-in discovers the current authorization's model catalog. Passive account refresh must not replace a personal model selected later.
17
23
 
24
+ The current source classifies discovered models by `type`; only `llm` enters chat. If the server returns only IDs, supply `provider.models[].type` using actual model IDs before upgrading. Server type metadata takes precedence; specialist and unresolved types remain outside chat. For servers returning only IDs, update the profile model types before enabling the provider. See the [model reference](docs/enterprise-profile.en.md).
25
+
18
26
  Validate from source:
19
27
 
20
28
  ~~~sh
@@ -6,8 +6,8 @@
6
6
 
7
7
  ## Runtime peers (not copied into this repository)
8
8
 
9
- - DeepSeek Harness packages `0.1.5-rc.1` and `@deepseek-ai/cordis` `4.0.2` — MIT, Copyright (c) 2026 DeepSeek, <https://github.com/deepseek-ai/deepseek-harness>
10
- - `@earendil-works/pi-ai` `0.85.1` — MIT, <https://github.com/earendil-works/pi>
9
+ - DeepSeek Harness packages `0.2.1-rc.2` and `@deepseek-ai/cordis` `4.0.5` — MIT, Copyright (c) 2026 DeepSeek, <https://github.com/deepseek-ai/deepseek-harness>
10
+ - `@earendil-works/pi-ai` `1.1.0` — MIT, <https://github.com/earendil-works/pi>
11
11
  - React `18.x` — MIT, Copyright (c) Facebook, Inc. and its affiliates, <https://github.com/facebook/react>
12
12
 
13
13
  This repository uses public package APIs and does not vendor their source. Their presence as peer dependencies does not imply endorsement of this project.
@@ -44,10 +44,11 @@ Source: <https://github.com/colinhacks/zod>
44
44
 
45
45
  ## Development-only tools
46
46
 
47
- The lock pins the RC.1 DSH test closure plus tsdown (MIT), TypeScript and Playwright Core (Apache-2.0), Ajv (MIT), YAML (ISC), and React types (MIT). Development tools are not copied into the published runtime files. Playwright Core does not download browser binaries during installation.
47
+ The lock pins the DSH 0.2.1-rc.2 test closure plus tsdown (MIT), TypeScript and Playwright Core (Apache-2.0), Ajv (MIT), YAML (ISC), and React types (MIT). Development tools are not copied into the published runtime files. Playwright Core does not download browser binaries during installation.
48
48
 
49
49
  The current lock flags two lifecycle scripts: `@google/genai@1.52.0` has an echo-only preinstall; `protobufjs@7.6.6` reads local package manifests and may emit version-scheme warnings. Its reviewed postinstall contains no download or process execution. The local npm allow-scripts policy left these scripts unapproved; review them again when the lock changes. A successful install is not a security-audit result.
50
50
 
51
51
  `fast-sha256@1.3.0`, reached through pi-ai → Anthropic SDK → standardwebhooks, declares Unlicense. Its distributed LICENSE grants copying, modification and distribution and disclaims warranty. The license check records a package/version-specific exception, not a blanket waiver for unknown licenses; no source is copied into this repository.
52
52
 
53
- The reviewed lock has 260 licensed package entries: 0BSD (1), Apache-2.0 (46), BSD-3-Clause (12), ISC (2), MIT (197), Python-2.0 (1), Unlicense (1). Regenerate this inventory for the final release lock.
53
+
54
+ The development-only official DSH Host includes LibreOffice Kit (MPL-2.0) and sharp/libvips native packages (Apache-2.0 / LGPL-3.0-or-later). These packages are installed separately for Host tests and are not bundled in this plugin archive; their own license files remain with their packages.
@@ -6,8 +6,8 @@
6
6
 
7
7
  ## 运行时 Peer(源码未复制进本仓库)
8
8
 
9
- - DeepSeek Harness `0.1.5-rc.1` 软件包和 `@deepseek-ai/cordis` `4.0.2`——MIT,Copyright (c) 2026 DeepSeek,<https://github.com/deepseek-ai/deepseek-harness>
10
- - `@earendil-works/pi-ai` `0.85.1`——MIT,<https://github.com/earendil-works/pi>
9
+ - DeepSeek Harness `0.2.1-rc.2` 软件包和 `@deepseek-ai/cordis` `4.0.5`——MIT,Copyright (c) 2026 DeepSeek,<https://github.com/deepseek-ai/deepseek-harness>
10
+ - `@earendil-works/pi-ai` `1.1.0`——MIT,<https://github.com/earendil-works/pi>
11
11
  - React `18.x`——MIT,Copyright (c) Facebook, Inc. and its affiliates,<https://github.com/facebook/react>
12
12
 
13
13
  本仓库使用这些软件包的公开 API,不 vendor 其源码。它们作为 peer dependency 出现,不表示其作者认可本项目。
@@ -46,10 +46,10 @@ SOFTWARE.
46
46
 
47
47
  ## 仅开发使用的工具
48
48
 
49
- 锁文件固定 RC.1 DSH 测试闭包及 tsdown(MIT)、TypeScript/Playwright Core(Apache-2.0)、Ajv(MIT)、YAML(ISC)、React 类型(MIT)。开发工具不复制到发布的运行文件。Playwright Core 安装时不下载浏览器二进制。
49
+ 锁文件固定 DSH 0.2.1-rc.2 测试闭包及 tsdown(MIT)、TypeScript/Playwright Core(Apache-2.0)、Ajv(MIT)、YAML(ISC)、React 类型(MIT)。开发工具不复制到发布的运行文件。Playwright Core 安装时不下载浏览器二进制。
50
50
 
51
- 当前锁标记两个生命周期脚本:`@google/genai@1.52.0` 只有 echo 的 preinstall;`protobufjs@7.6.6` 读取本地 package manifest,必要时输出版本约定提醒,所审查 postinstall 没有下载和进程执行。此次本机 npm allow-scripts 策略仍未批准这两项;锁变化后应重新审查。安装成功不代表已完成安全审计。
52
51
 
53
52
  `fast-sha256@1.3.0` 经 pi-ai → Anthropic SDK → standardwebhooks 引入,声明 Unlicense。已核对其分发 LICENSE 中复制、修改、分发授权与免责条款;许可证检查只为该包的该版本记录例外,不放开其他未知许可证。其源码不复制进本仓库。
54
53
 
55
- 当前已审查锁共有 260 个声明许可证的软件包条目:0BSD (1), Apache-2.0 (46), BSD-3-Clause (12), ISC (2), MIT (197), Python-2.0 (1), Unlicense (1)。正式发布锁应重新生成清单。
54
+
55
+ 仅开发使用的官方 DSH Host 包括 LibreOffice Kit(MPL-2.0)与 sharp/libvips 原生包(Apache-2.0 / LGPL-3.0-or-later)。这些包单独安装用于宿主测试,不打入本插件压缩包,许可证随各自的包保留。
@@ -16,7 +16,13 @@ This Host-only method has no Remote decorator and never exposes credentials. It
16
16
 
17
17
  Logout or reauthorization during response reading invalidates the result. The extension MUST also subscribe to `oidc/accounts-changed` and `credentials/reference-updated`, invalidate its generation, and check that generation after async operations. Abort requests on disposal. The public package does not cache extension data.
18
18
 
19
- For identity-token services, use the separate `authorizedFetch(profileID, endpoint, init)` method with approved origins, token refresh and at most one 401 retry for safe reads; generation is never replayed. See [the public protocol](public-resource-protocol.en.md). Neither transport schedules business requests itself.
19
+ For OAuth Access Token services, use `authorizedFetch(profileID, endpoint, init, authorization?)`. Requests check expiry first and refresh up to 30 minutes early, capped at half the token's advertised lifetime: a ten-minute token refreshes with five minutes remaining. This avoids repeatedly refreshing newly issued short-lived tokens. The refresh timestamp is stored with Host credentials and survives restarts. Older sessions with only an expiry use the default margin until their first refresh adds the timestamp, without requiring sign-in. In `auth` mode, GET/HEAD also refresh and retry at most once after a 401.
20
+
21
+ Reviewed Host extensions calling an issuer service outside the model API prefix can specify one exact `authorization.issuerServicePath`, for example `/user/active`. Only POST is allowed, on the verified issuer origin and exact path, without queries, fragments, URL credentials or redirects. Path segments accept letters, digits, underscores and hyphens. The Host must fix this value in code rather than forward a renderer or model input; no persistent allowlist changes. The same account refresh, cancellation and response isolation apply. Replayable text bodies may use `retryUnauthorized: true` for at most one retry.
22
+
23
+ Trusted Host services may pass `{ retryUnauthorized: true }` as the fourth argument for safely repeatable POST requests such as activity heartbeats. The body must be a buffered string or absent, never a stream. This option stays out of HTTP requests and client RPC, and does not broaden the allowed origins or paths. Model generation does not opt in and is never automatically replayed. Normal token rotation or natural expiry within the same authorization does not make the client cancel an active stream; the next request checks authorization again. The refresh margin is not a maximum generation duration or a substitute for correct server handling of long streams. See [the public protocol](public-resource-protocol.en.md). Neither transport schedules business requests itself.
24
+
25
+ Completed sign-in and sign-out emit `oidc/accounts-changed` with `authorizationChanged: true`, even when both sessions have state `connected`. Extensions must invalidate previous authorization failures and in-flight results instead of deduplicating by state name. Ordinary status polling still notifies only when the state changes.
20
26
 
21
27
  ## Client account menu
22
28
 
@@ -16,7 +16,13 @@ const response = await ctx.oidcAccounts.modelResourceFetch(profileID, '/quota',
16
16
 
17
17
  读取响应期间注销或替换 Key 会拒绝结果。扩展还必须在自身层订阅 `oidc/accounts-changed` 和 `credentials/reference-updated`,失效正在请求的账户快照;每次异步操作结束后检查世代编号,不能将旧用户结果写入新用户状态。扩展卸载时中止请求。公版不缓存扩展资源。
18
18
 
19
- 需要 OIDC 身份 Token 的机构服务仍用 `authorizedFetch(profileID, endpoint, init)`:它遵循已批准的 origin、令牌刷新及一次 401 重试,与上述模型 Key 运输不同。见 [公共身份与资源协议](public-resource-protocol.md)。这两个方法都不会自动触发业务请求。
19
+ 需要 OAuth Access Token 的机构服务使用 `authorizedFetch(profileID, endpoint, init, authorization?)`。请求前检查到期时间,默认提前 30 分钟刷新;提前量不超过该 Token 实际有效期的一半(例如有效期 10 分钟时,剩余 5 分钟开始刷新),避免短有效期 Token 刚获取就反复刷新。刷新时间随凭据保存在 Host,重启后仍生效;只有到期时间的旧会话先按默认余量处理,首次刷新后自动补齐,无须重新登录。`auth` 模式 GET/HEAD 收到 401 后最多刷新并重试一次。
20
+
21
+ 已审查的 Host 扩展如需调用模型 API 前缀之外的发行者服务,可在单次请求的 `authorization.issuerServicePath` 中指定精确路径,例如 `/user/active`。仅允许 POST,目标必须与已验证 issuer 同源且路径完全一致,不接受查询串、片段、URL 凭据和重定向。路径各段只允许字母、数字、下划线和连字符。该选项由 Host 代码固定,不得转发浏览器或模型给出的值;它不修改持久化白名单。请求继续复用账号刷新、取消与响应隔离;可重复的正文可配合 `retryUnauthorized: true` 最多重试一次。
22
+
23
+ 可安全重复提交的机构请求(例如活跃心跳)可显式传入第四个参数 `{ retryUnauthorized: true }`,为 POST 启用相同的一次恢复;请求正文须为已缓冲的字符串或为空,不接受流式正文。该选项只供受信 Host 代码使用,不进入 HTTP 请求或客户端 RPC,也不扩大目标 origin/路径白名单。模型生成请求不启用此选项,不自动重放;同一授权的正常 Token 刷新或自然到期不会由客户端取消已开始的流,下一次请求重新检查授权。刷新提前量不是最长生成时间,也不能替代服务端对长流式请求的正确处理。见 [公共身份与资源协议](public-resource-protocol.md)。这两个方法都不会自动触发业务请求。
24
+
25
+ 成功重新登录或注销会发出带 `authorizationChanged: true` 的 `oidc/accounts-changed` 事件,即使前后 `state` 都是 `connected`。扩展必须清理旧授权的失败状态及在途结果,不能仅按状态名称去重;普通状态轮询仍只在状态变化时发通知。
20
26
 
21
27
  ## 客户端账户菜单
22
28
 
@@ -6,7 +6,9 @@ Runtime and DSH compatibility follow package.json, dependency locks and measured
6
6
 
7
7
  The current source supports LiteLLM native contract 1, explicitly enabled experimental oidc-llm 0.1 and standard identity-only OIDC. oidc-llm remains a draft and is disabled by default.
8
8
 
9
- This branch removes Key Binding model flows and backend: native account bridging; old profiles fail explicitly. New clients use Tokens while servers may retain legacy endpoints for released clients. This breaking change is unpublished. Choose an appropriate new package version and reviewed product locks before publication; never overwrite an existing npm version.
9
+ `@eduwork/dsh-oidc@0.3.0-dev.2` removes Key Binding model flows and backend: native account bridging; old profiles fail explicitly. EduWork `0.3.6-dev.20260921.1` uses this package. New clients use Tokens, so confirm server support and migrate old profiles before upgrading. Servers may retain legacy endpoints for older clients. Future distributions must pin reviewed package versions and product locks; never overwrite an existing npm version.
10
+
11
+ Current npm 0.3.0 requires Node.js 24.18+ and DSH `>=0.2.1-rc.2 <0.3.0-0`. The tested development baseline is 0.2.1-rc.2; other prerelease lines require separate verification. The default Web backend does not require EduWork desktop bridges.
10
12
 
11
13
  ## Validation
12
14
 
@@ -6,7 +6,9 @@
6
6
 
7
7
  当前源码支持 LiteLLM native contract 1、显式启用的 oidc-llm 0.1 实验模型接入,以及不附带模型资源的标准 OIDC 身份登录。oidc-llm 尚未定稿,默认关闭。
8
8
 
9
- 本分支已删除旧 Key Binding 模型流程和 backend: native 账户桥,旧配置会报错。新客户端使用 Token;服务端可保留旧接口兼容已经发布的老客户端。此次破坏性变更尚未发布,发布前需选择合适的新包版本并同步已审查的产品锁,不能覆盖旧 npm 版本。
9
+ `@eduwork/dsh-oidc@0.3.0-dev.2` 已删除旧 Key Binding 模型流程和 backend: native 账户桥,旧配置会报错;EduWork `0.3.6-dev.20260921.1` 使用此版本。新客户端使用 Token,升级旧配置前应先确认服务端支持并完成迁移;服务端可保留旧接口兼容老客户端。后续发行应固定已审查的包版本与产品锁,不能覆盖旧 npm 版本。
10
+
11
+ 当前 npm 0.3.0 要求 Node.js 24.18+、DSH `>=0.2.1-rc.2 <0.3.0-0`,开发验收基线为 0.2.1-rc.2。其他预发布分支须单独验证。默认 Web backend 不依赖 EduWork 桌面桥接。
10
12
 
11
13
  ## 验证要求
12
14
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  [简体中文](development.md) | **English**
4
4
 
5
- The plugin version is `0.2.3`. Its development baseline is DSH `0.1.5-rc.1`, Cordis `4.0.2`, and pi-ai `0.85.1`. Product versions do not determine plugin versions; consult the registry for npm publication status. Source is maintained in EduWork; migration does not overwrite published npm packages.
5
+ The plugin version is `0.3.0`. Its development baseline is DSH `0.2.1-rc.2`, Cordis `4.0.5`, and pi-ai `1.1.0`. Product versions do not determine plugin versions; consult the registry for npm publication status. Source is maintained in EduWork; migration does not overwrite published npm packages.
6
6
 
7
7
  ## Verify a clean checkout
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  **简体中文** | [English](development.en.md)
4
4
 
5
- 当前插件版本为 `0.2.3`,开发基线是 DSH `0.1.5-rc.1`、Cordis `4.0.2`、pi-ai `0.85.1`。产品版本不决定插件版本;npm 发布状态以 registry 为准。源码位于 EduWork 的 `packages/dsh-oidc`。
5
+ 当前插件版本为 `0.3.0`,开发基线是 DSH `0.2.1-rc.2`、Cordis `4.0.5`、pi-ai `1.1.0`。产品版本不决定插件版本;npm 发布状态以 registry 为准。源码位于 EduWork 的 `packages/dsh-oidc`。
6
6
 
7
7
  ## 从干净 checkout 验证
8
8
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Supported host baseline
6
6
 
7
- Current `0.2.0` uses the registry-published DSH `0.1.5-rc.1` development/CI closure. Historical stable `0.1.0` targets `0.1.2-rc.1`; older candidate evidence is recorded separately in the [compatibility matrix](compatibility.en.md). Never mix DSH lines. See [development preparation](development.en.md) for clean installation.
7
+ Current `0.3.0` uses registry-published DSH `0.2.1-rc.2` dependencies for package development/CI; complete EduWork distributions use their product Runtime lock. Do not mix DSH dependency versions. See [compatibility](compatibility.en.md) and [development preparation](development.en.md).
8
8
 
9
9
  The plugin uses public package exports rather than copied DSH source:
10
10
 
@@ -62,10 +62,10 @@ The client descriptor uses strict Zod codecs. Configuration sent to the browser
62
62
 
63
63
  `dsh-oidc` declares its own default local-Web Bundle patch. Install it directly from npm into the official Web profile without authoring a wrapper Bundle:
64
64
 
65
- Install exact `0.2.0` with a coherent DSH `0.1.5-rc.1` host. If the registry does not yet provide this version during release preparation, use the reviewed source/frozen artifact below.
65
+ Install exact `0.3.0` with the package's declared DSH `0.2.1-rc.2` dependency baseline. EduWork desktop distributions already include the package; desktop users only edit configuration and do not run the plugin installation command below.
66
66
 
67
67
  ```bash
68
- dsh plugin --profile web add @eduwork/dsh-oidc@0.2.0
68
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.3.0
69
69
  ```
70
70
 
71
71
  For auditing, development, or validating unpublished changes, install a reviewed local checkout instead:
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 支持的宿主基线
6
6
 
7
- 当前 `0.2.0`以 npm 已发布的 DSH `0.1.5-rc.1` 闭包作为开发/CI 基线。历史稳定版 `0.1.0` 对应 `0.1.2-rc.1`;其他旧候选证据分别记在[兼容性矩阵](compatibility.md)。不要混装 DSH 版本。干净安装见[开发准备](development.md)。
7
+ 当前 `0.3.0` 以 npm 已发布的 DSH `0.2.1-rc.2` 依赖作为包开发/CI 基线;完整 EduWork 发行的 Runtime 以产品锁为准。不要混装 DSH 依赖版本。参见[兼容性说明](compatibility.md)和[开发准备](development.md)。
8
8
 
9
9
  插件只使用公开 package export,不复制 DSH 源码:
10
10
 
@@ -62,10 +62,10 @@ Client 描述符使用严格 Zod codec。发送给浏览器的配置不包含 is
62
62
 
63
63
  `dsh-oidc` 自带默认的 local-Web Bundle patch,可以直接从 npm 安装到官方 Web Profile,无需再编写 wrapper Bundle:
64
64
 
65
- 安装精确的 `0.2.0`,宿主 DSH 依赖应统一为 `0.1.5-rc.1`。发布准备期间若 registry 尚未提供该版本,使用下方源码或已核验的冻结产物。
65
+ 安装精确的 `0.3.0`,宿主 DSH 依赖应统一为包声明的 `0.2.1-rc.2` 基线。EduWork 桌面发行已装配此包,桌面用户只需编辑配置,无需执行以下插件安装命令。
66
66
 
67
67
  ```bash
68
- dsh plugin --profile web add @eduwork/dsh-oidc@0.2.0
68
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.3.0
69
69
  ```
70
70
 
71
71
  需要审计、开发或验证尚未发布的改动时,可以安装经过审查的本地 checkout:
@@ -12,6 +12,8 @@ The canonical machine-readable schema is [`schema/enterprise-profile.v1alpha1.sc
12
12
 
13
13
  ## Trust model
14
14
 
15
+ `auth.additionalScopes` explicitly requests additional service scopes for oidc-llm integrations, such as institution search. No additional scopes are requested by default. Each must be advertised in discovery's `scopes_supported`; token and refresh responses must retain the requested scopes. Changing scope configuration requires a new sign-in rather than expanding an existing token's authority.
16
+
15
17
  Profiles are trusted deployment configuration, not user input. Nevertheless, the parser is fail-closed:
16
18
 
17
19
  - unknown keys are rejected at the root and at every executable-relevant nested object;
@@ -51,6 +53,7 @@ Branding changes only approved presentation surfaces. It does not alter authenti
51
53
  | `logoURL` | HTTPS URL or base64 PNG/WebP, at most 128 KiB as text. Remote images use `referrerPolicy=no-referrer`. |
52
54
  | `primaryColor` | Six-digit hex color. Only a bounded DSH token set is overridden. |
53
55
  | `loginTitle` | 120 characters. |
56
+ | `loginButtonLabel` | 40 characters. Sign-in button text in onboarding, settings and the account menu; omitted values use the client's default wording. |
54
57
  | `loginDescription` | 500 characters. |
55
58
  | `supportURL` | Absolute HTTPS URL opened with `noopener noreferrer`. |
56
59
 
@@ -99,6 +102,49 @@ The Provider object is data interpreted by a local audited adapter.
99
102
  | `modelSource` | no | Only discovery, the default; fetches /models with the current Access Token. |
100
103
  | `models` | no | Reviewed model capabilities; cannot expose models absent from the authorized catalog. |
101
104
 
105
+ Model purpose uses `type`: `llm`, `embedding`, `rerank`, `image`, `tts` or `unknown`. Only `llm` registers with the DSH conversation provider. The full resource catalog retains specialist types; media services keep their own model and endpoint configuration. Classifying a model does not enable a service or grant access.
106
+
107
+ An explicit `data[].type` from the authorized `/models` response takes precedence. When absent, `provider.models[].type` supplies it. Missing, invalid or unsupported server types resolve to `unknown` and stay out of chat; the resources result reports `model_types_unresolved`. The client never guesses purpose from model names, the OpenAI `object` field or input modalities. An image-capable LLM is still `llm`.
108
+
109
+ Example provider metadata for a gateway returning only model IDs (replace IDs with authorized server IDs):
110
+
111
+ ```json
112
+ {
113
+ "models": [
114
+ {
115
+ "id": "example-chat",
116
+ "type": "llm"
117
+ },
118
+ {
119
+ "id": "example-vision-chat",
120
+ "type": "llm",
121
+ "input": [
122
+ "text",
123
+ "image"
124
+ ]
125
+ },
126
+ {
127
+ "id": "example-embedding",
128
+ "type": "embedding"
129
+ },
130
+ {
131
+ "id": "example-rerank",
132
+ "type": "rerank"
133
+ },
134
+ {
135
+ "id": "example-image",
136
+ "type": "image"
137
+ },
138
+ {
139
+ "id": "example-tts",
140
+ "type": "tts"
141
+ }
142
+ ]
143
+ }
144
+ ```
145
+
146
+ This is an optional EduWork resource extension, not a standard OpenAI field or a claim that existing LiteLLM/oidc-llm servers provide it. ID-only deployments must supply local types before enabling this client behavior. Distribute typed configuration only to upgraded clients: older clients reject unknown model fields. Local declarations are intersected with the authorized server catalog; unavailable IDs are never registered. Personal API-key providers are unchanged.
147
+
102
148
  `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.
103
149
 
104
150
  `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.
@@ -108,6 +154,7 @@ The Provider object is data interpreted by a local audited adapter.
108
154
  Each model has:
109
155
 
110
156
  - required `id`;
157
+ - optional purpose `type`; unresolved types are `unknown` and only `llm` is conversational;
111
158
  - optional display `name`;
112
159
  - `input` containing `text`, `image`, or both (default `text`);
113
160
  - optional positive `contextWindow` and `maxTokens`;
@@ -12,6 +12,8 @@
12
12
 
13
13
  ## 信任模型
14
14
 
15
+ `auth.additionalScopes` 可为 oidc-llm 接入显式申请额外服务授权,例如机构提供的搜索。默认不申请额外范围;每个范围必须出现在 discovery 的 `scopes_supported` 中,Token 与刷新响应必须保持申请的范围。修改授权范围后需要重新登录取得新授权,不扩大已有 Token 权限。
16
+
15
17
  Profile 是受信任的部署配置,不是用户输入。即便如此,解析器仍以失败关闭方式工作:
16
18
 
17
19
  - 根对象和所有涉及可执行行为的嵌套对象都会拒绝未知字段;
@@ -51,6 +53,7 @@ Profile 是受信任的部署配置,不是用户输入。即便如此,解析
51
53
  | `logoURL` | HTTPS URL 或 base64 PNG/WebP;文本最多 128 KiB。远程图片使用 `referrerPolicy=no-referrer`。 |
52
54
  | `primaryColor` | 六位十六进制颜色;只覆盖一组受限 DSH 主题 token。 |
53
55
  | `loginTitle` | 最多 120 字符。 |
56
+ | `loginButtonLabel` | 最多 40 字符。首次登录、设置页和账户菜单的登录按钮文字;省略时使用客户端默认文案。 |
54
57
  | `loginDescription` | 最多 500 字符。 |
55
58
  | `supportURL` | 使用 `noopener noreferrer` 打开的绝对 HTTPS URL。 |
56
59
 
@@ -99,6 +102,49 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
99
102
  | `modelSource` | 否 | 仅支持 discovery,默认值;使用当前 Access Token 读取 /models。 |
100
103
  | `models` | 否 | 已审查的模型能力元数据,不得扩大获授权目录。 |
101
104
 
105
+ 模型用途用 `type` 区分:`llm`、`embedding`、`rerank`、`image`、`tts` 或 `unknown`。只有 `llm` 注册到 DSH 对话 Provider;完整资源目录保留专用模型分类,媒体服务仍使用各自的模型和接口配置。标注类型不会自动启用服务,也不会扩大授权。
106
+
107
+ 服务端授权目录 `/models` 的 `data[].type` 优先;未提供时使用 `provider.models[].type`。两边都缺失、服务端类型无效或尚不支持时归为 `unknown`,不进入对话,资源结果包含 `model_types_unresolved`。不按模型名称、OpenAI 的 `object` 字段或输入模态猜类型;能看图的 LLM 仍是 `llm`。
108
+
109
+ 只返回模型 ID 的网关可在 Provider 中补充以下元数据(替换为服务端授权的实际 ID):
110
+
111
+ ```json
112
+ {
113
+ "models": [
114
+ {
115
+ "id": "example-chat",
116
+ "type": "llm"
117
+ },
118
+ {
119
+ "id": "example-vision-chat",
120
+ "type": "llm",
121
+ "input": [
122
+ "text",
123
+ "image"
124
+ ]
125
+ },
126
+ {
127
+ "id": "example-embedding",
128
+ "type": "embedding"
129
+ },
130
+ {
131
+ "id": "example-rerank",
132
+ "type": "rerank"
133
+ },
134
+ {
135
+ "id": "example-image",
136
+ "type": "image"
137
+ },
138
+ {
139
+ "id": "example-tts",
140
+ "type": "tts"
141
+ }
142
+ ]
143
+ }
144
+ ```
145
+
146
+ 这是 EduWork 的可选资源扩展,不是 OpenAI 标准字段,也不代表现有 LiteLLM/oidc-llm 服务已提供它。仅返回 ID 的部署必须在启用此客户端行为前补齐本地类型。类型配置只下发给已升级客户端,旧客户端会拒绝未知模型字段。本地声明仍与服务端授权目录取交集,不注册未授权 ID;个人 API Key 提供方不受影响。
147
+
102
148
  `retryPolicy.mode` 可以是 `normal` 或 `always`。`always` 可能一直重试,直到成功、取消或销毁;没有明确产品决策时不应启用。该策略还会由 DSH 再次校验。
103
149
 
104
150
  `compat` 只接受 JSON Schema 中列出的字段。部署方必须准确描述 Provider 事实;兼容性覆盖可能改变请求语义,但不能执行代码。
@@ -108,6 +154,7 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
108
154
  每个模型包含:
109
155
 
110
156
  - 必需的 `id`;
157
+ - 可选用途 `type`;无法确定时为 `unknown`,仅 `llm` 用于对话;
111
158
  - 可选显示名称 `name`;
112
159
  - `input` 可包含 `text`、`image` 或两者,默认 `text`;
113
160
  - 可选的正数 `contextWindow` 和 `maxTokens`;
@@ -2,17 +2,18 @@
2
2
 
3
3
  **简体中文** | [English](README_EN.md)
4
4
 
5
- 本分支新增 LiteLLM native OAuth 支持,以及默认关闭的 [oidc-llm 实验适配器](experimental-oidc-llm.md),尚未发布 npm 或桌面版本。仅身份 oidc 配置保留;旧 Key Binding 模型流程已移除,迁移见[说明](../key-binding-protocol.md)。新的 **oidc-llm** 仍是[协议草案](oidc-llm-draft.md),实验实现不代表协议已定稿。
5
+ LiteLLM native OAuth 和默认关闭的 [oidc-llm 实验适配器](experimental-oidc-llm.md) 已随 `@eduwork/dsh-oidc@0.3.0-dev.2` 发布,并包含在 EduWork `0.3.6-dev.20260921.1` 中。仅身份 oidc 配置保留;旧 Key Binding 模型流程已移除,迁移见[说明](../key-binding-protocol.md)。**oidc-llm** 仍是[协议草案](oidc-llm-draft.md),实验实现不代表协议已定稿。
6
6
 
7
7
  ## 选择接入方式
8
8
 
9
- 配置已有 LiteLLM 网关请从 [LiteLLM 接入指南](litellm-setup.md)开始;本页描述底层协议和宿主集成要求。
9
+ 模型接入有两条路线:机构模型平台可参考 [oidc-llm 草案与实验接入](experimental-oidc-llm.md),已有 LiteLLM 网关可从 [LiteLLM 接入指南](litellm-setup.md)开始。本页描述底层协议和宿主集成要求。
10
10
 
11
11
  | 服务端 | 配置 | 模型凭据 | 客户端注册 |
12
12
  | --- | --- | --- | --- |
13
- | 纯身份 OIDC | 仅 oidc,不配置 provider | 无机构模型凭据 | 预注册 public client |
14
- | LiteLLM 1.101.0 native contract 1 | `auth.discoveryUrl` | 登录返回的 Access Token | 每次登录动态注册实际本机回调 |
15
13
  | oidc-llm 0.1 实验 | `auth` + 显式实验开关与身份模式 | Access Token | 已实现预注册 public client |
14
+ | LiteLLM 1.101.0 native contract 1 | `auth.discoveryUrl` | 登录返回的 Access Token | 每次登录动态注册实际本机回调 |
15
+
16
+ 另保留纯身份 OIDC:仅配置 `oidc`,不配置 `provider`,使用预注册 public client。该模式只验证身份、不提供机构模型,故不计入上述两条模型接入路线。oidc-llm 内部的 `oidc` / `oauth` 则是同一草案的身份模式。
16
17
 
17
18
  LiteLLM 不需要实现 EduWork 的 Key Binding。普通 OIDC 的 Access Token 也不会因为配置了模型 URL 就获得推理权限;须配置明确的 Token 网关契约。配额和团队管理不纳入本次统一协议;LiteLLM 自己的团队选择留在网关网页,客户端仅保存不透明的授权上下文用于防止刷新串号。
18
19
 
@@ -159,7 +160,7 @@ POST revocation endpoint,表单 `token=<refresh_token>&client_id=<registered_c
159
160
 
160
161
  纯身份 OIDC 与 oidc-llm 的 OIDC 模式共用 Discovery issuer、PKCE S256、state、nonce、RS256 ID Token 和 UserInfo sub 一致性校验。Key Binding 与旧凭据引用迁移已移除,模型授权改用网关 Token。相关接口见[服务端契约](../server-integration-contract.md)、[Profile 规范](../enterprise-profile.md)。没有为兼容 LiteLLM 放松这些检查。
161
162
 
162
- 新 oidc-llm 的 UserInfo 从发现的 `userinfo_endpoint` 获取,复用标准主体和资料字段。实验配置及实际限制见[实验接入](experimental-oidc-llm.md),尚待讨论的 scope、生命周期和撤销保证见[草案](oidc-llm-draft.md)。真实服务完成验收前,不迁移已有机构配置。
163
+ oidc-llm 已实现 Token 直连模型与可选的完整 OIDC 身份校验,ChatECNU 是采用该草案的参考部署。配置及客户端边界见[实验接入](experimental-oidc-llm.md);[草案](oidc-llm-draft.md)明确当前 scopes、静态注册、按服务端有效期提前刷新和退出撤销行为,并将动态注册、刷新家族及长流到期契约列为后续扩展。其他服务仍需单独验收,已有机构配置须显式迁移。
163
164
 
164
165
  ## 开发验证
165
166
 
@@ -2,17 +2,18 @@
2
2
 
3
3
  [简体中文](README.md) | **English**
4
4
 
5
- This branch adds LiteLLM native OAuth and an [experimental oidc-llm adapter](experimental-oidc-llm.en.md), disabled by default. Neither is included in a published npm package or desktop Release yet. Identity-only oidc profiles remain supported. Key Binding model flows are removed; see [migration](../key-binding-protocol.en.md). **oidc-llm** remains a [draft](oidc-llm-draft.en.md); the experiment does not finalize the protocol.
5
+ LiteLLM native OAuth and the opt-in [experimental oidc-llm adapter](experimental-oidc-llm.en.md) are published in `@eduwork/dsh-oidc@0.3.0-dev.2` and included in EduWork `0.3.6-dev.20260921.1`. Identity-only oidc profiles remain supported. Key Binding model flows are removed; see [migration](../key-binding-protocol.en.md). **oidc-llm** remains a [draft](oidc-llm-draft.en.md); the experiment does not finalize the protocol.
6
6
 
7
7
  ## Choose a connection
8
8
 
9
- Start with the [LiteLLM setup guide](litellm-setup.en.md) to configure an existing gateway. This page describes the underlying protocol and Host integration requirements.
9
+ There are two model-access routes: institution model platforms can consult the [oidc-llm draft and experimental adapter](experimental-oidc-llm.en.md); existing LiteLLM deployments can start with the [LiteLLM setup guide](litellm-setup.en.md). This page describes the underlying protocol and Host integration requirements.
10
10
 
11
11
  | Server | Configuration | Model credential | Client registration |
12
12
  | --- | --- | --- | --- |
13
- | Identity-only OIDC | oidc without provider | No organization model credential | Pre-registered public client |
14
- | LiteLLM 1.101.0 native contract 1 | `auth.discoveryUrl` | Login Access Token | Dynamically register the actual callback on each login |
15
13
  | Experimental oidc-llm 0.1 | `auth` with explicit opt-in and identity mode | Access Token | Static public client implemented |
14
+ | LiteLLM 1.101.0 native contract 1 | `auth.discoveryUrl` | Login Access Token | Dynamically register the actual callback on each login |
15
+
16
+ Identity-only OIDC is retained separately: configure `oidc` without `provider`, using a pre-registered public client. It authenticates identity without providing institution models, so it is not counted as a third model-access route. The `oidc` and `oauth` options within oidc-llm are identity modes of the same draft.
16
17
 
17
18
  Quota standardization and team management are outside this integration. LiteLLM handles its own team choice in the gateway page; the adapter retains its opaque authorization context solely to detect an unexpected identity change during refresh. An ordinary OIDC Access Token does not automatically authorize model inference.
18
19
 
@@ -61,7 +62,7 @@ Model calls bind to the current authorization when prepared. After logout or acc
61
62
 
62
63
  Identity-only OIDC and the oidc-llm OIDC mode share issuer, PKCE, state, nonce, RS256 ID Token and matching UserInfo subject validation. Key Binding and legacy credential-name migration have been removed; model authorization uses gateway Tokens. See the [existing server contract](../server-integration-contract.md) and [Profile reference](../enterprise-profile.md). These checks were not weakened for LiteLLM.
63
64
 
64
- The oidc-llm adapter discovers `userinfo_endpoint` and reuses standard subject and identity claims. See [experimental integration](experimental-oidc-llm.en.md) for configuration and actual limits. Scope, lifetimes and revocation guarantees remain under review in the [draft](oidc-llm-draft.en.md). Do not migrate an existing institution configuration before real-server acceptance.
65
+ The oidc-llm adapter implements Token-based model access and optional full OIDC identity validation, with ChatECNU as a reference deployment adopting the draft. See [experimental integration](experimental-oidc-llm.en.md) for configuration and client limits. The [draft](oidc-llm-draft.en.md) documents current scopes, static registration, early refresh based on server-provided expiry and logout revocation, while leaving dynamic registration, refresh families and stream behavior at expiry to future contracts. Other servers need separate acceptance, and existing deployments require explicit migration.
65
66
 
66
67
  ## Validation
67
68
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  [简体中文](experimental-oidc-llm.md) | **English**
4
4
 
5
- This branch provides an opt-in oidc-llm 0.1 adapter, disabled by default and not released. The protocol remains under review. This page describes implemented client behavior; it does not claim that the [complete draft](oidc-llm-draft.en.md) is finalized or that a server has passed acceptance.
5
+ The opt-in oidc-llm 0.1 adapter is included in `@eduwork/dsh-oidc@0.3.0-dev.2` and EduWork `0.3.6-dev.20260921.1`, and remains disabled by default. The protocol is still under review. This page describes implemented client behavior; it does not claim that the [complete draft](oidc-llm-draft.en.md) is finalized or that arbitrary servers have passed acceptance.
6
6
 
7
7
  ## Configuration
8
8
 
@@ -23,14 +23,14 @@ Add this object to desktop `organizations` or plugin `profiles`. The server must
23
23
  }
24
24
  ```
25
25
 
26
- Select `identityMode` explicitly. Neither mode falls back to the other:
26
+ For organizational sign-in, explicitly select `identityMode: "oidc"`, as EduWork@ECNU currently does. Neither mode falls back to the other:
27
27
 
28
28
  | Mode | Requested scopes | Identity validation |
29
29
  | --- | --- | --- |
30
30
  | `oidc` | `openid profile offline_access llm:models:read llm:invoke`, with consent | Initial RS256 ID Token required; signature, issuer, aud/azp, nonce, time, optional at_hash and UserInfo subject are verified |
31
31
  | `oauth` | `llm:profile llm:models:read llm:invoke` | Reads sub from the discovered UserInfo-shaped endpoint; does not claim OIDC authentication |
32
32
 
33
- Only static public-client registration is implemented; no client secret is accepted. Register the actual IPv4 loopback callback `http://127.0.0.1:<random-port>/oauth/callback`. Dynamic registration remains future work.
33
+ Only static public-client registration is implemented; no client secret is accepted. Registration must allow the actual port to vary in the IPv4 loopback callback `http://127.0.0.1:<random-port>/oauth/callback` while constraining its host and path. Dynamic registration is outside current integration requirements. See the [reference deployment](oidc-llm-draft.en.md#8-chatecnu-reference-deployment) for ChatECNU discovery, endpoints and capabilities. Public examples retain neutral domains; editions supply their own addresses and registered client IDs.
34
34
 
35
35
  When discovery declares `authorization_response_iss_parameter_supported: true`, both successful and error authorization responses must include `iss` exactly matching the discovered `issuer`. A missing value produces `gateway_callback_issuer_missing`; repeated, empty or mismatched values produce `gateway_callback_issuer_invalid`. The client does not exchange the code. Ask the authentication service administrator to align discovery and callback behavior before starting a new sign-in. The desktop callback listener closes when the flow ends; refreshing an old callback URL cannot resume sign-in.
36
36
 
@@ -40,14 +40,16 @@ When discovery declares `authorization_response_iss_parameter_supported: true`,
40
40
 
41
41
  Both gateway adapters reuse discovery transport, Code+PKCE, browser/callbacks, the Host credential vault, single-flight refresh, model catalogs, the DSH Provider and streaming authorization isolation. The OIDC identity mode directly reuses the existing strict verifier. Standalone identity-only `oidc` remains supported. Legacy model Key Binding has been removed; see the [migration guide](../key-binding-protocol.en.md).
42
42
 
43
- Access tokens stay opaque. Discovered `api_base` and UserInfo must share the resource origin; authentication endpoints only receive their designated credentials, without redirects. Changed configuration/discovery bindings cannot reuse old authorization. Token responses require actual scope, positive integer expiry and a refresh token; grants cannot expand or omit required connection permissions. The server's expiry is honored without enforcing the unagreed 15-minute proposal.
43
+ Access tokens stay opaque. Discovered `api_base` and UserInfo must share the resource origin; authentication endpoints only receive their designated credentials, without redirects. Changed configuration/discovery bindings cannot reuse old authorization. Token responses require actual scope, positive integer expiry and a refresh token; grants cannot expand or omit required connection permissions. The server's expiry is honored without a 15-minute limit. The current client accepts 1 second through 365 days as validity bounds, not recommended lifetimes.
44
+
45
+ Before using authorization, the Host attempts refresh when remaining validity reaches `min(30 minutes, half the issued Token lifetime)`, coalescing concurrent refreshes for the same authorization. This client policy does not change the server's Token lifetime. A new Token cannot replace credentials in an already-sent stream. Stream behavior across expiry requires separate server acceptance; model generation is not replayed automatically.
44
46
 
45
47
  Refresh may omit an ID Token. If present, its original issuer, subject, audience, optional auth_time and nonce are checked. Failed validation after rotation revokes the new credentials and requires sign-in instead of continuing with a possibly consumed old refresh token. Temporary Token endpoint failures preserve still-valid authorization.
46
48
 
47
- Catalogs retain shared conservative capability mapping: ID-only rows support text without inferred vision or reasoning. Optional draft model capability fields are not consumed yet; use reviewed provider configuration when needed.
49
+ The optional `/models` entry `type` classifies model purpose; reviewed `provider.models[].type` fills missing server metadata. Only `llm` registers for conversation; unresolved types are excluded. Input modalities and reasoning remain reviewed provider facts: image-capable LLMs stay conversational. See the [Profile reference](../enterprise-profile.en.md#provider-object).
48
50
 
49
- Institution extensions can use the existing Host-only `modelResourceFetch(profileID, relativePath)`. Legacy connections use their managed model Key; experimental connections use the current authorized Access Token. Both reuse path restrictions, GET, bounded bodies and logout isolation. The public plugin makes no implicit quota request and adds no quota RPC/fields. Extensions must be installed explicitly; the server must define and enforce their authorization.
51
+ Institution extensions can use the existing Host-only `modelResourceFetch(profileID, relativePath)`. Model connections use the current authorized Access Token, sharing path restrictions, GET, bounded bodies and logout isolation. The public plugin makes no implicit quota request and adds no quota RPC/fields. Extensions must be installed explicitly; the server must define and enforce their authorization.
50
52
 
51
- Logout stops local requests before submitting refresh-token revocation; 200 empty and JSON responses are accepted. Remote failure only produces a sanitized warning. A persistent revocation retry queue is not implemented, so that draft proposal is not claimed. Refresh-family revocation, remaining Access Token validity, scope enforcement and model filtering still require real-server acceptance.
53
+ Logout clears local authorization and stops related requests before attempting Refresh Token revocation; 200 empty and JSON responses are accepted. Clients accept natural server-side expiry of issued Access Tokens without requiring immediate global invalidation. Browser SSO is not signed out. Remote failure only produces a sanitized warning; no persistent revocation retry queue exists. Refresh-family reuse detection and revocation scope, scope enforcement, model filtering and stream behavior at expiry require server documentation and acceptance.
52
54
 
53
55
  References: [OIDC refresh response](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse), [authorization response issuer](https://www.rfc-editor.org/rfc/rfc9207.html).
@@ -2,7 +2,7 @@
2
2
 
3
3
  **简体中文** | [English](experimental-oidc-llm.en.md)
4
4
 
5
- 本分支提供 oidc-llm 0.1 的实验适配器,默认关闭,尚未发布。协议仍在讨论;本页描述已实现的客户端边界,不表示[完整草案](oidc-llm-draft.md)已经定稿或服务端已经通过验收。
5
+ oidc-llm 0.1 的实验适配器已包含在 `@eduwork/dsh-oidc@0.3.0-dev.2` 与 EduWork `0.3.6-dev.20260921.1` 中,默认关闭,需显式启用。协议仍在讨论;本页描述已实现的客户端边界,不表示[完整草案](oidc-llm-draft.md)已经定稿或任意服务端均已通过验收。
6
6
 
7
7
  ## 配置
8
8
 
@@ -23,14 +23,14 @@
23
23
  }
24
24
  ```
25
25
 
26
- 必须显式选择 `identityMode`。两种模式不自动互相降级:
26
+ 组织登录建议显式选择 `identityMode: "oidc"`,与 EduWork@ECNU 当前配置一致。两种模式不自动互相降级:
27
27
 
28
28
  | 模式 | 请求范围 | 身份验证 |
29
29
  | --- | --- | --- |
30
30
  | `oidc` | `openid profile offline_access llm:models:read llm:invoke`,并请求 consent | 首次必须有 RS256 ID Token;验证签名、issuer、aud/azp、nonce、时间、可选 at_hash 与 UserInfo sub |
31
31
  | `oauth` | `llm:profile llm:models:read llm:invoke` | 从发现的 UserInfo 格式接口读取 sub;不宣称完成 OIDC 身份验证 |
32
32
 
33
- 目前仅实现预注册 public client,不能填写 client secret。服务器注册须允许实际 IPv4 loopback 回调 `http://127.0.0.1:<随机端口>/oauth/callback`。动态注册留待后续实现。
33
+ 目前仅实现预注册 public client,不能填写 client secret。服务器注册须允许 IPv4 loopback 回调 `http://127.0.0.1:<随机端口>/oauth/callback` 的实际端口变化,并约束 host/path。动态注册不属于当前接入要求。ChatECNU 的公开发现、端点和能力对照见[草案参考部署](oidc-llm-draft.md#8-chatecnu-参考部署);公共示例保留中立域名,发行版自行提供地址和注册的 client ID。
34
34
 
35
35
  发现声明 `authorization_response_iss_parameter_supported: true` 时,成功和错误授权回调都必须带 `iss`,且与发现中的 `issuer` 完全一致。缺失会报告 `gateway_callback_issuer_missing`;重复、空值或不匹配会报告 `gateway_callback_issuer_invalid`。客户端不会继续换取 Token,应由认证服务管理员核对发现声明与回调实现后重新发起登录。桌面回调监听在流程结束后关闭,刷新旧回调地址不能恢复登录。
36
36
 
@@ -40,14 +40,16 @@
40
40
 
41
41
  两套网关适配器共用发现请求、Code+PKCE、浏览器/回调、Host 凭据库、并发刷新合并、模型目录、DSH Provider 与流式请求隔离。OIDC 身份分支直接复用现有严格验证器;保留独立的纯身份 `oidc` 登录;旧模型 Key Binding 已移除,见[迁移说明](../key-binding-protocol.md)。
42
42
 
43
- Access Token 按不透明 Bearer 处理。发现中的 `api_base` 与 UserInfo 必须和 resource 同源;认证端点只接收其角色对应的凭据,禁自动重定向。配置或发现绑定改变时不复用旧授权。Token 响应必须提供实际 scope、正整数有效期和 refresh token;scope 不得扩大或缺少本连接需要的权限。有效期按服务器响应执行,不把尚未议定的 15 分钟建议写成硬性上限。
43
+ Access Token 按不透明 Bearer 处理。发现中的 `api_base` 与 UserInfo 必须和 resource 同源;认证端点只接收其角色对应的凭据,禁自动重定向。配置或发现绑定改变时不复用旧授权。Token 响应必须提供实际 scope、正整数有效期和 refresh token;scope 不得扩大或缺少本连接需要的权限。有效期按服务器响应执行,不规定 15 分钟上限;当前客户端校验范围为 1 秒至 365 天,不代表推荐寿命。
44
+
45
+ 使用授权前,Host 在剩余有效期不超过 `min(30 分钟, 本次 Token 有效期的一半)` 时尝试刷新,并合并同一授权的并发刷新。这是客户端策略,不改变服务端的 Token 寿命。新 Token 不能替换已经发出的流式请求凭据;服务器是否允许长流跨越到期时刻仍需单独验收,模型生成不自动重放。
44
46
 
45
47
  刷新可以省略 ID Token;返回时检查原 issuer、sub、aud、可选 auth_time 和 nonce。轮换后的 Token 若验证失败,客户端撤销新凭据并要求重登,避免继续使用可能已消费的旧 refresh token。临时 Token endpoint 故障不会删除仍有效的旧授权。
46
48
 
47
- 模型目录仍使用共享的保守能力映射:仅有 ID 时启用文本,不从名称猜图像或思考能力。草案中的可选模型能力扩展尚未消费,需要时使用显式审核的 provider 配置。
49
+ `/models` 条目的可选 `type` 用于区分模型用途,服务端未提供时由已审核的 `provider.models[].type` 补充。仅 `llm` 注册到对话,类型无法确定时不注册。输入模态与思考能力仍使用已审核的 Provider 配置,能看图的 LLM 不会被排除。详见 [Profile 说明](../enterprise-profile.md#provider-对象)。
48
50
 
49
51
  机构扩展可以调用既有 Host-only `modelResourceFetch(profileID, relativePath)`。模型连接统一使用当前获准的 Access Token,共享路径限制、GET、正文大小限制与退出隔离。公共插件不自动查询配额,也不新增配额 RPC 或字段。扩展须显式安装,服务端须自行声明并执行其授权范围。
50
52
 
51
- 退出立即停止本机请求,再提交 refresh token 撤销;支持 200 空响应或 JSON。远端失败仅记录脱敏警告,当前没有持久化撤销重试队列,不能宣称满足草案中这项提议。服务器的 refresh 家族撤销、Access Token 剩余有效期、scope 隔离和模型过滤仍需真实验收。
53
+ 退出清除本地授权、停止关联请求,再尝试撤销 Refresh Token;支持 200 空响应或 JSON。客户端接受已签发 Access Token 在服务端自然到期,不要求立即全局失效,也不退出浏览器中的组织 SSO。远端失败仅记录脱敏警告,当前没有持久化撤销重试队列。刷新家族重用检测与撤销范围、scope 隔离、模型过滤和长流到期行为需要服务端说明并验收。
52
54
 
53
55
  参考:[OIDC 刷新响应](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse)、[授权响应 issuer](https://www.rfc-editor.org/rfc/rfc9207.html)。