@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
@@ -6,6 +6,16 @@
6
6
 
7
7
  | dsh-oidc | Node.js | DSH | pi-ai | Status |
8
8
  | --- | --- | --- | --- | --- |
9
+ | `0.2.0` stable-version freeze | Windows 24 | registry `0.1.5-rc.1` | `0.85.1` | `npm ci`, complete checks, 93 tests and 6 compiled-browser regressions pass; audit reports 0 vulnerabilities. Runtime sources match dev.7. Consult the registry for publication status; Linux/Node 22 and macOS acceptance are recorded separately. |
10
+ | dev.7 source preparation (historical validation) | Windows 24 | registry `0.1.5-rc.1` | `0.85.1` | Clean `npm ci` from the committed 61-package DSH test closure; 93 tests. This is separate from historical full-product closures; Linux/Node 22 matrix pending. |
11
+ | Frozen `0.2.0-dev.20260910.7` (unpublished) | 24 | `0.1.5-rc.1` / `183f08e9…` | `0.85.1` | 265-package product closure, 93 tests including 15 credential ownership/migration regressions and 6 tarball Host tests. Frozen artifact unchanged. |
12
+ | `0.2.0-dev.20260910.6` (unpublished) | 24 | `0.1.5-rc.1` / `183f08e9…` | `0.85.1` | 264 coherent DSH packages; 78 tests and 6 compiled-browser checks. Public identity/key/models with no quota HTTP/schema/UI. Host-only account extension transport, official child slot and logout/read races. |
13
+ | `0.2.0-dev.20260910.5` (unpublished) | 24 | `0.1.5-rc.1` / `183f08e9…` | `0.85.1` | 264 coherent DSH packages; 75 tests and 7 compiled-browser checks. Real HTTP PKCE/key/model streams, future-session default, avatar quota/keyboard/logout races, and branded callbacks. Adapts PiAi `modelErrors`; existing APIs/events/model selection remain compatible. |
14
+ | `0.2.0-dev.20260909.1` (unpublished) | 24 | `0.1.5-alpha.1` / `5dda764e…` | `0.85.1` | 257 coherent packages; 40 tests including real Host + HTTP OIDC callback, managed-key model discovery, quota, LLM SSE, host-only authorized requests and account events. Browser UI acceptance belongs to the integrating product. |
15
+ | `0.1.0-dev.20260908.1` (local candidate only) | 24 | `0.1.2-rc.1` / `0.1.3-alpha.1` / `0.1.3-alpha.2` | `^0.84.2` | All three isolated dependency trees pass the complete check and 33 tests, including 19 real PiAi HTTP requests verifying thinking-only behavior without a wire effort. Unpublished. |
16
+ | `0.1.0-dev.20260907.3` (local candidate only) | 24 | `0.1.3-alpha.2` / `82a5fd61…` | `^0.84.2` | Real module resolution across 250 coherent DSH packages; TypeScript, 32 plugin tests, Host/Provider/Client contracts, all 13 Typert Remote markers, and real pi-ai reasoning HTTP regression pass. Unpublished. |
17
+ | `0.1.0-dev.20260907.1` (local candidate only) | 24 | `0.1.3-alpha.1` / `d347e703…` | `^0.84.2` | Real module resolution across 247 coherent DSH packages; TypeScript, 29 plugin tests, Host/Provider/Client contracts, and 13 Typert Remote markers pass. Unpublished. |
18
+ | `0.1.0` | 22, 24 | `0.1.2-rc.1` / `a66e4702…` | `^0.84.2` (locked at `0.84.4`) | Exact peer closure, Host/Client contract checks, clean npm installation, and isolated Web/RPC acceptance. |
9
19
  | `0.1.0-alpha.11` | 22, 24 | Declared baseline remains `0.1.2-alpha.2`; separate mainline `0.1.2-rc.1` configuration RPC probe | `^0.84.2` | npm scope migration with persistent contracts retained; the rc.1 probe is not full compatibility acceptance. |
10
20
  | `0.1.0-alpha.10` | 22, 24 | `0.1.2-alpha.2` / `0a53fb55…` | `^0.84.2` (`0.84.4` in npm/source Runtimes) | Migrated to `SettingsProvider.installSection()`; full checks pass through both npm and source release-pack paths. |
11
21
  | `0.1.0-alpha.9` | 22, 24 | `0.1.2-alpha.1` / `cd5ef814…` | `^0.84.2` (`0.84.4` in the reviewed source Runtime) | Web and native consume only standard Enterprise Profiles; product institution-catalog conversion is completely outside the plugin. |
@@ -18,12 +28,12 @@
18
28
  | `0.1.0-alpha.2` | 22, 24 (development) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | Standard UserInfo name presentation unified across Web and native adapters; real deployment acceptance pending. |
19
29
  | `0.1.0-alpha.1` | 22, 24 (development) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | Unit/build/package baseline; real deployment acceptance still required. |
20
30
 
21
- Only exact DSH peer versions in `package.json` are supported. Other versions may install only after explicit peer override and are untested.
31
+ Historical stable `0.1.0` targets exact DSH `0.1.2-rc.1`. Current `0.2.0` keeps dev.7 runtime sources and pins DSH `0.1.5-rc.1` throughout the required development/CI closure. Its version is independent of the product version. Historical rows record their original evidence; they do not imply all old runtimes were retested in the current pass or that quota remains in the public API. See [development preparation](development.en.md).
22
32
 
23
33
  ## Contract versions
24
34
 
25
35
  - Enterprise Profile: `dsh-oidc/v1alpha1`
26
- - Key Binding: `worker-user-center-v1`
36
+ - Key Binding Profile selector: `worker-user-center-v1` or `eduwork-resources-v1`; accepted Bootstrap wire aliases: `worker.user-center.v1`, `worker-user-center/v1`, `eduwork-resources/v1`
27
37
  - Typert package/namespace: `@eduwork/dsh-oidc` / `oidcAccounts`
28
38
  - Browser management projection: `dsh-oidc/management/v1alpha1`
29
39
  - Callback path: `/oauth/callback`
@@ -56,6 +66,6 @@ No public tag/npm publish until all of the following pass:
56
66
  - native desktop no-regression acceptance;
57
67
  - OIDC negative tests and Key Binding authorization tests;
58
68
  - documentation/version/changelog update;
59
- - two-person review for authentication, credential, build, or release workflow changes.
69
+ - independent technical review, CI/focused regression evidence, and a recorded maintainer decision for authentication, credential, build, or release workflow changes; add independent human approval after a second maintainer joins.
60
70
 
61
71
  See [the public release checklist](release-checklist.en.md) for the operator checklist.
@@ -6,6 +6,16 @@
6
6
 
7
7
  | dsh-oidc | Node.js | DSH | pi-ai | 状态 |
8
8
  | --- | --- | --- | --- | --- |
9
+ | `0.2.0` 稳定版本冻结 | Windows 24 | registry `0.1.5-rc.1` | `0.85.1` | `npm ci`、完整检查、93 项测试、6 项编译浏览器回归通过,audit 为 0。运行源码与 dev.7 相同;发布状态以 registry 为准,Linux/Node 22 与 macOS 验收单独记录。 |
10
+ | dev.7 源码准备(历史验证) | Windows 24 | registry `0.1.5-rc.1` | `0.85.1` | 已提交锁的 61 包 DSH 测试闭包,干净 `npm ci`、93 项测试;与历史完整产品闭包分别记录,Linux/Node 22 矩阵待执行。 |
11
+ | 已冻结 `0.2.0-dev.20260910.7`(未发布) | 24 | `0.1.5-rc.1` / `183f08e9…` | `0.85.1` | 265 包产品闭包、93 项测试(含 15 项凭据迁移/归属回归)与 6 项 tarball Host 验证;冻结产物未替换。 |
12
+ | `0.2.0-dev.20260910.6`(未发布) | 24 | `0.1.5-rc.1` / `183f08e9…` | `0.85.1` | 264 个一致 DSH 包;78 项测试及 6 项编译浏览器检查。公版身份/Key/模型不含配额请求/类型/UI;Host 专属扩展运输、官方子插槽与注销读取竞态。 |
13
+ | `0.2.0-dev.20260910.5`(未发布) | 24 | `0.1.5-rc.1` / `183f08e9…` | `0.85.1` | 264 个一致 DSH 包;75 项测试及 7 项编译浏览器检查。覆盖真实 HTTP PKCE/Key/模型流、无会话默认值、头像菜单/配额/键盘/注销竞态与品牌回调;本轮适配 PiAi `modelErrors`,原有 API/事件/选模契约保持兼容。 |
14
+ | `0.2.0-dev.20260909.1`(未发布) | 24 | `0.1.5-alpha.1` / `5dda764e…` | `0.85.1` | 257 个一致包;40 项测试含官方 Host+HTTP 登录回调、托管 Key 自动模型目录/配额、LLM SSE、Host 专属授权请求与账号事件。产品浏览器 UI 由主线联合验收。 |
15
+ | `0.1.0-dev.20260908.1`(仅本地候选) | 24 | `0.1.2-rc.1` / `0.1.3-alpha.1` / `0.1.3-alpha.2` | `^0.84.2` | 三套隔离依赖树均通过完整检查及 33 项测试。新增 thinking-only 的 19 次真实 PiAi HTTP 请求回归,保留 thinking 且不发送 effort。未发布。 |
16
+ | `0.1.0-dev.20260907.3`(仅本地候选) | 24 | `0.1.3-alpha.2` / `82a5fd61…` | `^0.84.2` | 250 个一致的 DSH 包通过真实模块解析;TypeScript、32 个插件测试、Host/Provider/Client 契约、13 个 Typert Remote 标记和真实 pi-ai reasoning HTTP 回归通过。未发布。 |
17
+ | `0.1.0-dev.20260907.1`(仅本地候选) | 24 | `0.1.3-alpha.1` / `d347e703…` | `^0.84.2` | 247 个一致的 DSH 包通过真实模块解析;TypeScript、29 个插件测试、Host/Provider/Client 契约和 13 个 Typert Remote 标记通过。未发布。 |
18
+ | `0.1.0` | 22、24 | `0.1.2-rc.1` / `a66e4702…` | `^0.84.2`(锁定为 `0.84.4`) | 精确 peer 闭包、Host/Client 契约检查、干净 npm 安装和隔离 Web/RPC 验收。 |
9
19
  | `0.1.0-alpha.11` | 22、24 | 声明基线仍为 `0.1.2-alpha.2`;另有主线 `0.1.2-rc.1` 隔离配置 RPC 探针 | `^0.84.2` | npm 作用域迁移;保留数据协议;不将 rc.1 探针视为完整版本兼容验收。 |
10
20
  | `0.1.0-alpha.10` | 22、24 | `0.1.2-alpha.2` / `0a53fb55…` | `^0.84.2`(npm/源码 Runtime 中为 `0.84.4`) | 迁移到 `SettingsProvider.installSection()`;npm 与源码 release-pack 双路径通过完整检查。 |
11
21
  | `0.1.0-alpha.9` | 22、24 | `0.1.2-alpha.1` / `cd5ef814…` | `^0.84.2`(已审查源码 Runtime 中为 `0.84.4`) | Web/native 只消费标准 Enterprise Profile;产品机构目录转换彻底移出插件。 |
@@ -18,12 +28,12 @@
18
28
  | `0.1.0-alpha.2` | 22、24(开发) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | Web 与 native adapter 统一使用标准 UserInfo 姓名显示;尚待真实部署验收。 |
19
29
  | `0.1.0-alpha.1` | 22、24(开发) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | 单元测试、构建和打包基线;仍需真实部署验收。 |
20
30
 
21
- 仅支持 `package.json` 中声明的精确 DSH peer 版本。其他版本即使通过显式 peer override 安装,也属于未经测试的组合。
31
+ 历史稳定版 `0.1.0` 对应精确 DSH `0.1.2-rc.1`。当前 `0.2.0` 冻结保持 dev.7 运行源码,开发/CI 基线在所需测试闭包内统一锁定 `0.1.5-rc.1`,不跟随产品号。表中旧行是当时的验收事实,不表示本轮重测全部旧 Runtime,也不表示公版仍含配额。见[开发准备](development.md)。
22
32
 
23
33
  ## 契约版本
24
34
 
25
35
  - Enterprise Profile:`dsh-oidc/v1alpha1`
26
- - Key Binding:`worker-user-center-v1`
36
+ - Key Binding Profile 配置名称:`worker-user-center-v1` 或 `eduwork-resources-v1`;Bootstrap wire 兼容名称:`worker.user-center.v1`、`worker-user-center/v1`、`eduwork-resources/v1`
27
37
  - Typert 包/命名空间:`@eduwork/dsh-oidc` / `oidcAccounts`
28
38
  - 浏览器管理投影:`dsh-oidc/management/v1alpha1`
29
39
  - 回调路径:`/oauth/callback`
@@ -56,6 +66,6 @@
56
66
  - native 桌面无回退验收;
57
67
  - OIDC 反向测试和 Key Binding 授权测试;
58
68
  - 文档、版本和变更日志更新;
59
- - 对认证、凭据、构建或发布流程变更进行双人审查。
69
+ - 对认证、凭据、构建或发布流程变更完成独立技术复核、CI/专项回归并记录维护者决定;增加第二位维护者后再加入独立人工批准。
60
70
 
61
71
  操作检查项见[公开发布检查表](release-checklist.md)。
@@ -2,7 +2,7 @@
2
2
 
3
3
  [简体中文](0001-one-plugin-composition-boundary.md) | **English**
4
4
 
5
- - Status: Accepted for alpha
5
+ - Status: Accepted
6
6
  - Date: 2026-08-25
7
7
 
8
8
  ## Context
@@ -2,7 +2,7 @@
2
2
 
3
3
  **简体中文** | [English](0001-one-plugin-composition-boundary.en.md)
4
4
 
5
- - 状态:Alpha 阶段已接受
5
+ - 状态:已接受
6
6
  - 日期:2026-08-25
7
7
 
8
8
  ## 背景
@@ -0,0 +1,69 @@
1
+ # Desktop hosts without a persistent Web server
2
+
3
+ [简体中文](desktop-host.md)
4
+
5
+ Local candidate `0.2.0-dev.20260910.1` adds `backend: desktop`. OIDC validation, host credentials, Key Binding, model discovery and `authorizedFetch()` reuse the Web implementation; existing `web` and legacy native bridge modes remain supported.
6
+
7
+ ```yaml
8
+ - id: enterprise-oidc
9
+ name: '@eduwork/dsh-oidc'
10
+ config:
11
+ backend: desktop
12
+ allowEmptyProfiles: true
13
+ profilePathEnv: EDUWORK_OIDC_PROFILE
14
+ desktop:
15
+ callbackPort: 0
16
+ flowTimeoutMs: 600000
17
+ ```
18
+
19
+ The host supplies a Cordis `desktopServices` service with `openExternal(url: string): Promise<void>`. OIDC builds the authorization URL from reviewed Profile discovery; the renderer cannot submit an arbitrary URL. The shell opens the system browser, rejects non-HTTP(S) and userinfo URLs, and never logs authorization query parameters. The plugin does not execute shell commands or import Electron/Wails. The service can arrive later; removing it cancels pending sign-ins.
20
+
21
+ When the distribution provides `configFile: {path, examplesPath}`, organization settings stay read-only and are loaded again on restart. The optional Host method `openConfiguration(target: 'config' | 'examples'): Promise<void>` enables configuration-file and example-folder buttons. The RPC accepts these two fixed targets only; the host resolves its own paths, and the renderer cannot send a path or command. `configuration().configFile.canOpen` reports availability. Web hosts without this capability show the configuration-file location instead. Personal models and configured organization sign-in remain available.
22
+
23
+ Resource binding accepts the original `worker.user-center.v1`, the transitional `worker-user-center/v1`, and `eduwork-resources/v1`. Unknown versions and mismatched Provider IDs are rejected before creating a model credential. Completed identity sign-in is retained, with an error identifying the separate resource/configuration problem.
24
+
25
+ The host must implement `credentials.resolve/set/unset`, backed by its operating-system vault. The plugin has no plaintext credential file or fallback on storage failure. OAuth tokens remain Host-only. Personal API keys remain independent of the organization's managed credential. The public `oidcAccounts.authorizedFetch()` capability remains Host-only.
26
+
27
+ Only an explicit sign-in starts an IPv4 `127.0.0.1` listener. The callback is `http://127.0.0.1:<port>/oauth/callback`, using a random port by default. Register a public PKCE client supporting dynamic loopback ports with the IdP. For providers requiring an exact registered URI, a trusted `callbackPort` can pin the port; a conflict fails explicitly instead of switching to an unregistered port. Other bind addresses are not configurable. Cancellation, expiry, success, a valid failed callback, service disposal and host shutdown close the listener. Invalid Host, Origin, state, method or path cannot consume the legitimate attempt.
28
+
29
+ Shared Host/Client RPC additions:
30
+
31
+ - `begin(profileID)` returns `{mode:'external', loginID, expiresAt}` for desktop. Existing Web `redirect` and legacy `completed` variants remain supported.
32
+ - `loginStatus(loginID)` returns `{loginID, profileID, state, expiresAt, status?, errorCode?}`. State is pending/completed/cancelled/expired/failed.
33
+ - `cancelLogin(loginID)` returns the same safe projection and waits for an in-flight credential write to roll back.
34
+ - `openConfiguration(target)` returns `{opened:true}` in file-managed mode; the only targets are `config` and `examples`. System-opening failures produce a concise message.
35
+ - `selectEnterpriseModel(profileID, {onlyIfMissing?})` returns `{changed, selection?}` on DSH 0.1.5 and persists the default through `agentDefaultModel.saveSelection()`.
36
+
37
+ Sign-in, sidebar and organization settings share one account snapshot. Credential Providers should emit the official `credentials/reference-updated` event after set/unset. The client listens to that forwarded Remote event and `connection/reset`; it does not depend on a custom account event that the official Remote transport does not forward.
38
+
39
+ Explicit sign-in with a connected key, or confirmed key provisioning, selects the first resolvable enterprise model. A default is saved even when no session exists. For a current main session, the client also uses the official `modelDirectories.directoryFor(sessionID).select()` API; addressed subagents are left alone. Load the official `agentDefaultModel` and writable `settings` services. Older hosts without this capability show a message asking the user to choose from the model menu.
40
+
41
+ Initial upgrade recovery uses `onlyIfMissing:true`: it preserves an existing resolvable default and repairs only an absent or unavailable one. A valid personal selection in the current session is also preserved. Credential events, connection checks and subsequent status refreshes never select a model. Personal credentials and unrelated settings remain unchanged.
42
+
43
+ For desktop acceptance run `node scripts/serve-desktop-oidc-fixture.mjs --config <new test configuration file>`. It binds a random loopback port, serves synthetic HTTP PKCE/Key/models/quota and writes a public JSONC profile. The file must not exist; user configuration is never overwritten. Use isolated data directories for each shell and Ctrl+C to stop. No real accounts or model credits are used.
44
+
45
+ The independent random login handle is not OAuth state. Results never carry an authorization URL, code, nonce, verifier or token. The client polls once per second, displays browser completion instructions and a cancel button, and cancels on unmount. Sign-in expires within ten minutes. Closing a system browser cannot reliably be detected across platforms; the app cancel action and expiry bound the listener lifetime.
46
+
47
+ An empty Profile list is valid: no listener or organization login is needed. Identity-only profiles need no resource endpoints. Logout preserves personal keys. A resource outage after successful identity verification keeps the identity connected so resource access can be retried.
48
+
49
+ Run `node --test test/desktop.test.js test/desktop-host.test.js`. To test a frozen installation, set `DSH_OIDC_PACKAGE_ROOT` to its package directory and `DSH_OIDC_EXPECT_DSH=0.1.5-rc.1`. The latter test uses the installed package's actual Host dependencies without WebServer, optional browser-service lifecycle and HTTP PKCE. All credentials and identities are synthetic. Shell vault, window and system-browser integration still require product acceptance.
50
+
51
+ The `.20260910.6` public avatar menu provides account refresh and sign-out; quota UI requires an institution extension. A portal supports narrow sidebars; arrows, Home/End, Escape and outside click/focus are supported. Logout clears this profile's local identity, managed key and cached model metadata, serializes vault writes and rejects late writes. Personal keys remain untouched.
52
+
53
+ The temporary HTTP callback page reads `brand.productName/organizationName/logoURL/mark/primaryColor` from this attempt's Profile and chooses Chinese or English from Accept-Language. It has no external fonts, scripts or raw error reflection and directs the user back to the app. Ordinary Web validation still redirects into its local app; model keys never enter the browser.
54
+
55
+ Run `npm run check` from an isolated dependency tree coherent with the exact target DSH. Do not relabel a bundle built using old root dependencies. `npm run check:browser` additionally uses that Runtime's `playwright-core` and locally installed headless Edge (or Chrome through `DSH_OIDC_BROWSER_CHANNEL`) to load the compiled client, verify menu/shared state/logout and capture branded callback pages. It does not replace native vault/system-browser acceptance.
56
+
57
+ ## macOS handoff acceptance
58
+
59
+ The OIDC npm package is platform-independent JavaScript. It bundles no Electron, Wails, Keychain or Windows credential binary; macOS consumes the same exact version and integrity. The plugin has no platform branch: the Host interfaces above own shell differences. Windows validation does not establish macOS readiness.
60
+
61
+ Start with `npm ci` and `npm run check`. With Chrome installed, run `npm run check:browser` using `DSH_OIDC_BROWSER_CHANNEL=chrome`. The product owner must also validate a real macOS client:
62
+
63
+ - `desktopServices.openExternal` opens authorization in the system default browser; `openConfiguration` respects system file associations rather than forcing an editor.
64
+ - The Credential Provider stores, restores after restart, rotates and deletes credentials through system protection in the signed app. If the product uses Electron `safeStorage`, its Keychain behavior, unavailable encryption and denied access require main-process acceptance. The plugin never falls back to a plaintext file.
65
+ - Dynamic loopback ports, cancellation, timeout and app exit clean up correctly. The IdP registration cannot assume only the single port used in a Windows test.
66
+ - Login with and without an existing session updates shared account state and enterprise models. Restart preserves valid personal model selections.
67
+ - Validate the host, external browser and credentials separately on actual Apple Silicon and targeted Intel systems. Cross-OS history migration requires sign-in again; another machine's encrypted credential files are not portable credentials.
68
+
69
+ Signing, notarization, DMG/ZIP packaging and app/data-directory layout belong to the desktop distribution repository. This plugin adds no macOS-specific packaging branch.
@@ -0,0 +1,79 @@
1
+ # 无常驻 Web 服务的桌面宿主
2
+
3
+ [English](desktop-host.en.md)
4
+
5
+ 本地候选 `0.2.0-dev.20260910.1` 新增 `backend: desktop`。它复用 Web 后端的 OIDC 校验、Host credentials、Key Binding、模型发现协议,只替换登录回调传输。既有 `web` 和 Go 桥 `native` 配置继续可用。
6
+
7
+ ```yaml
8
+ - id: enterprise-oidc
9
+ name: '@eduwork/dsh-oidc'
10
+ config:
11
+ backend: desktop
12
+ allowEmptyProfiles: true
13
+ profilePathEnv: EDUWORK_OIDC_PROFILE
14
+ desktop:
15
+ callbackPort: 0
16
+ flowTimeoutMs: 600000
17
+ ```
18
+
19
+ 宿主应注册 Cordis `desktopServices` 服务,提供 Host-only 方法:
20
+
21
+ ```ts
22
+ openExternal(url: string): Promise<void>
23
+ // 可选:仅打开宿主预先确定的配置文件或示例目录。
24
+ openConfiguration(target: 'config' | 'examples'): Promise<void>
25
+ ```
26
+
27
+ OIDC 从受信 Profile 对应的 Discovery 构造 HTTP(S) 授权 URL。此 URL 只交给 Host 服务;浏览器侧不能传入自选 URL。外壳负责用系统浏览器打开,拒绝非 HTTP(S)、userinfo URL,并且不得记录授权查询参数。插件不自行执行系统命令,不依赖 Electron/Wails 的 JavaScript 包。服务可以稍后加载;移除服务会取消尚未完成的登录。
28
+
29
+ 发行方提供 `configFile: {path, examplesPath}` 时,企业服务保持只读,由用户编辑文件后重启应用。若宿主提供 `openConfiguration`,设置显示“打开配置文件”和“查看示例”;RPC 只接收 `config` / `examples`,由宿主解析固定路径,不允许 renderer 传路径或命令。`configuration().configFile.canOpen` 声明是否可直接打开;Web 或未提供该能力的宿主显示配置文件位置作为备用。个人 API Key 设置和已配置企业的身份登录继续可用。
30
+
31
+ 资源绑定兼容既有 `worker.user-center.v1`、过渡写法 `worker-user-center/v1` 与 `eduwork-resources/v1`。未知版本或不匹配的 Provider ID 在创建模型凭据前拒绝,保留已完成的身份登录,并提示检查模型资源服务或企业配置;它们不是身份验证失败。
32
+
33
+ 宿主必须提供 `credentials.resolve/set/unset`。本插件没有明文凭据文件或存储失败后的备用路径;桌面发行方负责接入操作系统保险库。模型调用仍使用独立运行 Key,OAuth token 不经 RPC 返回 renderer。`oidcAccounts.authorizedFetch()` 仍是 Host-only 公共授权请求入口。
34
+
35
+ 只有用户点击登录时才监听 `127.0.0.1`。默认随机端口,回调为 `http://127.0.0.1:<port>/oauth/callback`;需在身份提供方注册支持动态 loopback 端口的公共 PKCE 客户端。若身份提供方只接受精确回调端口,可在受信配置固定 `callbackPort`(端口占用时明确失败,不改用未注册端口)。不支持配置其他监听地址。取消、失效、成功、合法回调失败、服务卸载和 Host 退出均清理监听。错误路径、Host、Origin、state 或 HTTP 方法不会消费合法的待登录状态。
36
+
37
+ RPC 扩展(共用 Host/Client Typert schema):
38
+
39
+ | 方法 | 返回 |
40
+ | --- | --- |
41
+ | `begin(profileID)` | 桌面返回 `{mode:'external', loginID, expiresAt}`;Web 仍返回 `redirect`,旧 native 仍可返回 `completed`。 |
42
+ | `loginStatus(loginID)` | `{loginID, profileID, state, expiresAt, status?, errorCode?}`。state 为 pending/completed/cancelled/expired/failed。 |
43
+ | `cancelLogin(loginID)` | 同上;等待正在写入的登录撤回,避免取消后重新出现凭据。 |
44
+ | `openConfiguration(target)` | 文件管理模式下返回 `{opened:true}`;目标仅为 `config` / `examples`。系统打开失败时返回简短提示。 |
45
+ | `selectEnterpriseModel(profileID, {onlyIfMissing?})` | DSH 0.1.5 上返回 `{changed, selection?}`,通过官方 `agentDefaultModel.saveSelection()` 保存企业默认模型。 |
46
+
47
+ 客户端账号快照由登录页、侧栏和企业设置共享。宿主凭据 Provider 应在 set/unset 后按官方契约发出 `credentials/reference-updated`;客户端监听该标准 Remote 事件及 `connection/reset`,不依赖不会由官方 Remote 转发的自定义账号事件。
48
+
49
+ 明确登录并连接 Key 或确认创建 Key 后,自动选择企业目录中第一个可解析模型。还没有会话时也会保存未来会话的默认值;存在主会话时通过官方 `modelDirectories.directoryFor(sessionID).select()` 同步当前选择,不改子代理。宿主应加载官方 `agentDefaultModel` 和可写 `settings` 服务。旧宿主缺少此能力时明确提示从模型菜单选择。
50
+
51
+ 升级后的首次加载使用 `onlyIfMissing:true`:已有有效默认值则保留,缺失或已不能解析才修复;当前会话中可用的个人选择也保留。凭据事件、检查连接和后续状态刷新不会切模型,个人 Key 与其他设置不受影响。
52
+
53
+ 双桌面联调可运行 `node scripts/serve-desktop-oidc-fixture.mjs --config <新的测试配置文件>`。脚本只绑定本机随机端口,生成合成身份、完整 HTTP PKCE/Key/模型/配额服务及公开 JSONC 配置;配置文件必须不存在,不覆盖用户配置。每套外壳使用独立测试数据目录;用 Ctrl+C 关闭服务。服务不接触真实账号,也不消耗模型额度。
54
+
55
+ `loginID` 是独立随机句柄,不是 OAuth state。响应不包含授权 URL、code、nonce、PKCE verifier 或 token。前端以一秒间隔轮询,显示在浏览器中完成登录与取消按钮;登录最长十分钟,页面卸载取消尚未完成的尝试。关闭外部浏览器无法被跨平台可靠检测,用户可在应用中取消,或等待短时监听过期。
56
+
57
+ 空 Profile 是有效配置,不会监听端口,也不要求机构登录。纯身份 Profile 不要求资源端点;登出仅移除该机构的身份/托管 Key,个人 API Key 保留。身份登录成功后资源接口暂不可用时保留已登录身份,后续可以重试资源连接。
58
+
59
+ 验证入口:`node --test test/desktop.test.js test/desktop-host.test.js`。后者可通过 `DSH_OIDC_PACKAGE_ROOT` 指向安装的冻结包目录,并设置 `DSH_OIDC_EXPECT_DSH=0.1.5-rc.1`,使用该安装目录的真实 DSH 依赖运行无 WebServer 的 Host、可选浏览器服务和 loopback PKCE 验证。所有凭据与用户均为测试合成值;产品主进程保险库、窗口和操作系统浏览器行为仍由发行方联合验收。
60
+
61
+ `.20260910.6` 的公共侧栏头像显示账户刷新和注销;配额内容由可选机构扩展提供。菜单通过 portal 支持收窄侧栏;支持方向键、Home/End、Escape、外部点击/失焦关闭。注销清理该机构本地身份、模型 Key、模型元数据缓存,序列化保险库写操作并拒绝旧请求写回;个人 Key 不受影响。
62
+
63
+ 临时 HTTP 回调页读取本次 Profile 的 `brand.productName/organizationName/logoURL/mark/primaryColor`,按浏览器 Accept-Language 选择中英文。没有外部字体、脚本或原始错误回显,清楚提示返回应用。普通 Web 验证仍跳回本地应用;不会把生产模型 Key 交给浏览器。
64
+
65
+ 在与目标 DSH 完全一致的隔离依赖树运行 `npm run check`,不要从旧版本根依赖构建后标为新基线。可再运行 `npm run check:browser`:使用该 Runtime 的 `playwright-core` 和本机 Edge 无头浏览器(可用 `DSH_OIDC_BROWSER_CHANNEL` 指定 Chrome),直接加载编译客户端,验证菜单/多个组件共享状态/注销,并生成品牌回调截图。本检查不替代主进程保险库与真实操作系统浏览器联验。
66
+
67
+ ## macOS 接手验收
68
+
69
+ OIDC npm 包是平台无关的 JavaScript,不捆绑 Electron、Wails、Keychain 或 Windows 凭据二进制;macOS 使用同一个精确版本和 integrity。插件内部没有平台分支,外壳差异由上述 Host 接口承担。Windows 验证不能作为 macOS 已可用的结论。
70
+
71
+ 接手者先运行 `npm ci`、`npm run check`,安装 Chrome 后可设置 `DSH_OIDC_BROWSER_CHANNEL=chrome` 运行 `npm run check:browser`。产品方还需在真实 macOS 客户端验证:
72
+
73
+ - `desktopServices.openExternal` 用系统默认浏览器打开授权页;`openConfiguration` 遵从系统文件关联,不能固定为某个编辑器。
74
+ - Credential Provider 在签名后的应用中通过系统保护机制保存、重启恢复、轮换和删除凭据。若产品使用 Electron `safeStorage`,其 Keychain 行为、密钥不可用和拒绝访问场景由产品主进程验收;本插件不会回退到明文文件。
75
+ - 临时 loopback 回调的动态端口、取消、超时和应用退出均正确清理;身份提供方的登记不能仅支持 Windows 测试时的单个端口。
76
+ - 在没有会话时登录,及在已有会话中登录,均更新共享头像状态、配置企业模型;重启不覆盖有效的个人模型选择。
77
+ - 真实 Apple Silicon 与目标 Intel 架构的宿主、外部浏览器和凭据机制分别验收。跨操作系统迁移历史数据时重新登录,不复制另一台机器加密的凭据文件作为凭据迁移。
78
+
79
+ 应用签名、公证、DMG/ZIP、安装目录与数据目录布局由桌面发行仓库负责;本插件不增加 macOS 专用打包分支。
@@ -0,0 +1,42 @@
1
+ # Development and release preparation
2
+
3
+ [简体中文](development.md) | **English**
4
+
5
+ The plugin version is `0.2.0`. 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. This stable-version freeze does not change dev.7 runtime sources or replace earlier frozen artifacts.
6
+
7
+ ## Verify a clean checkout
8
+
9
+ Use Node.js 22 or 24 in this repository:
10
+
11
+ ```sh
12
+ npm ci
13
+ npm run check
14
+ ```
15
+
16
+ The manifest declares exact development dependencies for the required DSH test closure, and the lock records public-registry URLs and integrity. Upstream prerelease carets may select a later RC, so pinning only direct peers is insufficient. `check:lock` rejects mixed versions, machine paths and missing integrity; `check:dsh` verifies the actually loaded baseline. Do not substitute junctions into a running desktop for a clean installation, or suppress conflicts with `--force` or `--legacy-peer-deps`.
17
+
18
+ This is the plugin's development/CI closure, not a full desktop product. Consumers still reuse the host through peerDependencies. The [compatibility matrix](compatibility.en.md) distinguishes historical evidence; a historical peer declaration does not mean every old combination was rerun for each commit.
19
+
20
+ The complete check covers TypeScript, the dependency lock and official contracts, Host/Client builds and loading, Node tests, schemas/examples, document links, sensitive-data/license scans, and package inspection. Optional `npm run check:browser` uses Playwright Core with a locally installed Edge/Chrome; `DSH_OIDC_BROWSER_CHANNEL` selects the installed channel (default `msedge`). It downloads no browser and does not replace real distribution login acceptance.
21
+
22
+ ## Source map
23
+
24
+ | Path | Responsibility |
25
+ | --- | --- |
26
+ | `src/host/profile.js` | Trusted Profile, bounded branding/models and common credential reference |
27
+ | `src/host/oidc.js` | PKCE, Token/UserInfo, Key Binding, sessions and credential ownership |
28
+ | `src/host/desktop-oidc.js` | Temporary loopback login shared by both desktop shells |
29
+ | `src/host/resources.js` | Conservative model-catalog normalization |
30
+ | `src/host/provider/` | Official PiAi Provider and explicit image-transform boundary |
31
+ | `src/host/index.js`, `typert.*.js` | Host service, official lifecycle and public RPC |
32
+ | `src/client/` | Official settings slots, account/login UI and bounded branding |
33
+ | `test/` | Synthetic IdP/gateway, HTTP, Host, migration and race regressions |
34
+ | `schema/`, `protocol/` | Profile Schema and implemented resource HTTP contracts |
35
+
36
+ `scripts/build-host.mjs` copies native Host ESM to `lib`; tsdown bundles the Client. Do not edit `lib` by hand. New wire fields require corresponding implementation, Schema/OpenAPI, bilingual documentation and contract tests. Avoid mechanical tests for simple presentation/documentation changes.
37
+
38
+ ## Public scope and remaining release work
39
+
40
+ The public package owns identity, managed keys, model discovery/inference and their account UI. Quota, heartbeat, campus search and speech business services belong in institution/product plugins. [Account extensions](account-extensions.en.md) are Host transport and slot contracts, not hidden institution-feature switches. Examples contain placeholder domains, public client IDs and no secrets.
41
+
42
+ CI defines Windows/Linux × Node 22/24. A local Windows result does not cover unexecuted matrix cells. Before joint publication, complete the matrix, deployment acceptance and history/supply-chain review on the selected commit, then freeze the stable version, tag and tarball using the [release checklist](release-checklist.en.md). Existing npm versions and frozen artifacts are not rewritten. Local preparation does not push, release or publish.
@@ -0,0 +1,42 @@
1
+ # 开发与发布准备
2
+
3
+ **简体中文** | [English](development.en.md)
4
+
5
+ 当前插件版本为 `0.2.0`,开发基线是 DSH `0.1.5-rc.1`、Cordis `4.0.2`、pi-ai `0.85.1`。产品版本不决定插件版本;npm 发布状态以 registry 为准。本次稳定版本冻结不改动 dev.7 的运行源码,也不替换既有冻结 tarball。
6
+
7
+ ## 从干净 checkout 验证
8
+
9
+ 使用 Node.js 22 或 24,在本仓库执行:
10
+
11
+ ```sh
12
+ npm ci
13
+ npm run check
14
+ ```
15
+
16
+ `package.json` 为所需 DSH 测试闭包声明精确 devDependency;`package-lock.json` 记录 npm registry URL 和 integrity。上游预发布包的 caret 可能选择下一条 RC,因此只固定直接 peer 不够。`check:lock` 同时拒绝混装、机器路径和缺失完整性信息,`check:dsh` 校验实际加载版本。不要用运行中桌面安装目录或 junction 来替代干净安装结果,也不要使用 `--force` 或 `--legacy-peer-deps` 掩盖版本冲突。
17
+
18
+ 此依赖闭包仅供本插件开发/CI;它不是整个桌面产品。发布给使用方的插件仍通过 peerDependencies 复用宿主能力。历史已验收组合见[兼容性矩阵](compatibility.md),历史 peer 声明不代表每次提交都重测全部旧版。
19
+
20
+ 完整检查包含 TypeScript、依赖锁/官方接口、Host/Client 构建、编译产物加载、Node 测试、Schema/示例、文档链接、敏感信息/许可证扫描和 npm pack 内容检查。可选 `npm run check:browser` 使用 Playwright Core 与本机 Edge/Chrome;设置 `DSH_OIDC_BROWSER_CHANNEL` 可选择已安装的浏览器渠道(默认 `msedge`)。它不下载浏览器,也不代替发行客户端的实际登录验收。
21
+
22
+ ## 代码入口
23
+
24
+ | 路径 | 职责 |
25
+ | --- | --- |
26
+ | `src/host/profile.js` | 可信 Profile、受限品牌/模型配置、统一凭据引用 |
27
+ | `src/host/oidc.js` | PKCE、Token/UserInfo、Key Binding、会话与凭据归属 |
28
+ | `src/host/desktop-oidc.js` | 两种桌面外壳共用的临时 loopback 登录 |
29
+ | `src/host/resources.js` | 模型目录的保守归一化 |
30
+ | `src/host/provider/` | 官方 PiAi Provider 和显式图像转换边界 |
31
+ | `src/host/index.js`、`typert.*.js` | Host 服务、官方生命周期与公开 RPC |
32
+ | `src/client/` | 官方设置插槽、登录/账号展示、有限品牌覆盖 |
33
+ | `test/` | 合成 IdP/网关、HTTP、Host、迁移与竞态回归 |
34
+ | `schema/`、`protocol/` | Profile Schema 与当前资源 HTTP 契约 |
35
+
36
+ Host ESM 由 `scripts/build-host.mjs` 复制至 `lib`,Client 由 tsdown 打包;不要手改 `lib`。新增网络字段时应同步实现、Schema/OpenAPI、中英文规范与合约测试。UI/文档调整不需要添加机械重复实现的测试。
37
+
38
+ ## 开源边界与发布待办
39
+
40
+ 公共包只拥有身份、托管 Key、模型目录/调用及对应账号 UI。配额、心跳、校内检索和语音业务由机构/产品插件负责;[账户扩展](account-extensions.md)是 Host 运输与插槽边界,不是暗中启用机构功能的开关。所有示例均使用占位域名、Public Client ID 与无秘密配置。
41
+
42
+ CI 声明 Windows/Linux × Node 22/24;本机 Windows 的结果不能代替尚未执行的矩阵单元。下一次共同发行前,应在目标提交上完成矩阵、实际部署联调、历史与供应链审查,再按[发布检查表](release-checklist.md)冻结正式版本、tag 与 tarball。既有 npm 版本和本地冻结包不改写;本地准备不执行 push、release 或 publish。
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Supported host baseline
6
6
 
7
- The current compatibility baseline is DeepSeek Harness `0.1.2-alpha.2`, upstream commit `0a53fb55bea101816fa226bb964ae2bed71c343b`. Peer versions are exact while DSH remains prerelease software.
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.
8
8
 
9
9
  The plugin uses public package exports rather than copied DSH source:
10
10
 
@@ -43,8 +43,12 @@ The default export is `OidcAccountService`, a `TypertRemoteService` named `oidcA
43
43
  | Method | Result |
44
44
  | --- | --- |
45
45
  | `configuration()` | Public profiles with secrets and endpoint bases removed. |
46
+ | `openConfiguration(target)` | Host-backed configuration/example opening; no file contents or secrets returned. |
46
47
  | `status(profileID)` | Local session/credential state. |
47
- | `begin(profileID)` | Redirect URL for Web, completed status for native. |
48
+ | `begin(profileID)` | Web redirect, temporary desktop login ID, or legacy native completion. |
49
+ | `loginStatus(loginID)` / `cancelLogin(loginID)` | Poll or cancel the current desktop attempt. |
50
+ | `resources(profileID)` | Model metadata and issues, without quota or secrets. |
51
+ | `selectEnterpriseModel(profileID, options)` | Select a verified connected model through official defaults; no arbitrary Provider destination. |
48
52
  | `reconcile(profileID, {allowProvision})` | Bootstrap and resolve/provision/renew. |
49
53
  | `logout(profileID)` | Local cleanup and best-effort OIDC revocation. |
50
54
  | `management()` | Capability-aware projection consumed by the shared enterprise-model settings UI. |
@@ -56,10 +60,12 @@ The client descriptor uses strict Zod codecs. Configuration sent to the browser
56
60
 
57
61
  ### Direct installation
58
62
 
59
- `dsh-oidc` declares its own default Web-first Bundle patch. Install it directly from npm into the official Web profile without authoring a wrapper Bundle:
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
+
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.
60
66
 
61
67
  ```bash
62
- dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
68
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.2.0
63
69
  ```
64
70
 
65
71
  For auditing, development, or validating unpublished changes, install a reviewed local checkout instead:
@@ -72,9 +78,9 @@ npm run check
72
78
  dsh plugin --profile web add .
73
79
  ```
74
80
 
75
- The local-path install links the checkout into the Profile, so the source directory must remain available. It does not scan the current workspace. Team deployments should prefer a reviewed, exact npm version; `@eduwork/dsh-oidc@alpha` is only for deployments that intentionally follow prerelease updates.
81
+ The local-path install links the checkout into the Profile, so the source directory must remain available. It does not scan the current workspace. Team deployments should pin a reviewed, exact npm version and must not mix another DSH prerelease line into the same Profile.
76
82
 
77
- The shipped patch mounts exactly one `enterprise-oidc` instance using `DSH_OIDC_ENTERPRISE_PROFILE`. The Web backend requires the DSH WebServer to listen exactly on `127.0.0.1` and builds the fixed `/oauth/callback` from its actual port; no public callback-origin setting is accepted. It deliberately does not set `agent-default-model`, because Provider and model IDs belong to the deployment's Enterprise Profile and users can select an available enterprise model in DSH.
83
+ The shipped patch mounts exactly one `enterprise-oidc` instance using `EDUWORK_OIDC_PROFILE`. The Web backend requires the DSH WebServer to listen exactly on `127.0.0.1` and builds the fixed `/oauth/callback` from its actual port; no public callback-origin setting is accepted. The patch does not hard-code `agent-default-model`; after explicit login/key binding, the Client selects the connected organization model through official APIs. Restart recovery only repairs an unusable default and preserves personal selections. `DSH_OIDC_ENTERPRISE_PROFILE` remains a fallback.
78
84
 
79
85
  ### Product-owned Bundle
80
86
 
@@ -88,7 +94,7 @@ The shipped patch mounts exactly one `enterprise-oidc` instance using `DSH_OIDC_
88
94
  - id: enterprise-oidc
89
95
  name: '@eduwork/dsh-oidc'
90
96
  config:
91
- profilePathEnv: DSH_OIDC_ENTERPRISE_PROFILE
97
+ profilePathEnv: EDUWORK_OIDC_PROFILE
92
98
  web:
93
99
  returnPath: /
94
100
  ```
@@ -97,7 +103,13 @@ The containing DSH profile/bundle must also include the ordinary Web app, creden
97
103
 
98
104
  See the [getting-started guide](getting-started.en.md) for OIDC registration, Key Binding implementation, environment variables, acceptance, and troubleshooting.
99
105
 
100
- ## Desktop/native composition
106
+ ## Desktop composition
107
+
108
+ New Wails/Electron products use `backend: desktop`: the plugin owns a temporary loopback callback and opens the browser through official `nativeCommand`. Both shells share identity, Key Binding and model behavior. The host still provides credential storage; no new `enterpriseAccounts` bridge is required. See [desktop host integration](desktop-host.en.md).
109
+
110
+ ## Legacy native bridge
111
+
112
+ The following adapter interface is only for existing integrations. It is not required for a new desktop:
101
113
 
102
114
  ```yaml
103
115
  - insert:
@@ -169,3 +181,7 @@ For every DSH release candidate or stable upgrade:
169
181
  8. record results in `docs/compatibility.en.md` before release.
170
182
 
171
183
  No semver range should silently opt this security-sensitive plugin into an untested DSH release while DSH remains pre-1.0.
184
+
185
+ ## Credential reads for institution adapters
186
+
187
+ Explicitly installed local adapters may call `ctx.oidcAccounts.resolveBoundCredential(profileID, { credentialRef: "EDUWORK_API_KEY", runtimeBaseURL })`. The runtime URL must exactly match the reviewed Profile model-service URL. The result is a DSH credential record verified against the session, issuer/client ID, complete resource binding and credential fingerprint, or `undefined`. Use this same snapshot rather than checking status and resolving the name separately, which can race with a login change. This is Host-only, with no Typert/RPC registration and no addition to the server protocol. Adapters remain responsible for restricting request destinations. Desktop/Web support the method; the legacy native bridge does not fall back to an unverified key.
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 支持的宿主基线
6
6
 
7
- 当前兼容基线为 DeepSeek Harness `0.1.2-alpha.2`,上游 commit `0a53fb55bea101816fa226bb964ae2bed71c343b`。DSH 仍处于预发布阶段,因此 peer version 使用精确版本。
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)。
8
8
 
9
9
  插件只使用公开 package export,不复制 DSH 源码:
10
10
 
@@ -43,8 +43,12 @@ OpenAI-compatible 网络实现来自 `@earendil-works/pi-ai`,它也是 DSH 官
43
43
  | 方法 | 结果 |
44
44
  | --- | --- |
45
45
  | `configuration()` | 删除秘密和 endpoint 基址后的公开 Profile。 |
46
+ | `openConfiguration(target)` | 通过宿主打开配置/示例;不返回文件内容或秘密。 |
46
47
  | `status(profileID)` | 本地 session/凭据状态。 |
47
- | `begin(profileID)` | Web 返回重定向 URL,native 返回完成状态。 |
48
+ | `begin(profileID)` | Web 重定向、临时 desktop 登录 ID 或旧 native 完成状态。 |
49
+ | `loginStatus(loginID)` / `cancelLogin(loginID)` | 查询或取消当前桌面登录。 |
50
+ | `resources(profileID)` | 模型元数据与问题,不含配额或秘密。 |
51
+ | `selectEnterpriseModel(profileID, options)` | 通过官方默认值选择已验证连接的模型,不接受任意 Provider 目的地。 |
48
52
  | `reconcile(profileID, {allowProvision})` | 执行 bootstrap 和 resolve/provision/renew。 |
49
53
  | `logout(profileID)` | 本地清理,并尽力执行 OIDC 撤销。 |
50
54
  | `management()` | 共用企业模型设置 UI 使用的宿主能力投影。 |
@@ -56,10 +60,12 @@ Client 描述符使用严格 Zod codec。发送给浏览器的配置不包含 is
56
60
 
57
61
  ### 直接安装
58
62
 
59
- `dsh-oidc` 自带默认的 Web-first Bundle patch,可以直接从 npm 安装到官方 Web Profile,无需再编写 wrapper Bundle:
63
+ `dsh-oidc` 自带默认的 local-Web Bundle patch,可以直接从 npm 安装到官方 Web Profile,无需再编写 wrapper Bundle:
64
+
65
+ 安装精确的 `0.2.0`,宿主 DSH 依赖应统一为 `0.1.5-rc.1`。发布准备期间若 registry 尚未提供该版本,使用下方源码或已核验的冻结产物。
60
66
 
61
67
  ```bash
62
- dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
68
+ dsh plugin --profile web add @eduwork/dsh-oidc@0.2.0
63
69
  ```
64
70
 
65
71
  需要审计、开发或验证尚未发布的改动时,可以安装经过审查的本地 checkout:
@@ -72,9 +78,9 @@ npm run check
72
78
  dsh plugin --profile web add .
73
79
  ```
74
80
 
75
- 本地路径安装会把 checkout 链接到 Profile,因此源码目录必须持续存在。它不会扫描当前工作区。团队部署应优先固定经过复核的 npm 精确版本;`@eduwork/dsh-oidc@alpha` 只适合明确希望跟随预发布更新的场景。
81
+ 本地路径安装会把 checkout 链接到 Profile,因此源码目录必须持续存在。它不会扫描当前工作区。团队部署应固定经过复核的 npm 精确版本;不要在同一 Profile 中混装其他 DSH 预发布线。
76
82
 
77
- 随包 patch 使用 `DSH_OIDC_ENTERPRISE_PROFILE` 挂载且只挂载一个 `enterprise-oidc` 实例。Web backend 要求 DSH WebServer 精确监听 `127.0.0.1`,并从实际端口构造固定 `/oauth/callback`;不接受公网回调源配置。它有意不设置 `agent-default-model`,因为 Provider 和模型 ID 属于部署方 Enterprise Profile,用户可在 DSH 中选择可用企业模型。
83
+ 随包 patch 使用 `EDUWORK_OIDC_PROFILE` 挂载且只挂载一个 `enterprise-oidc` 实例。Web backend 要求 DSH WebServer 精确监听 `127.0.0.1`,并从实际端口构造固定 `/oauth/callback`;不接受公网回调源配置。patch 不硬编码 `agent-default-model`;完成显式登录/Key 绑定后,Client 使用官方选择接口应用已连接机构默认模型。重启后的恢复仅修复不可用默认值,不覆盖个人模型选择。旧 `DSH_OIDC_ENTERPRISE_PROFILE` 环境变量仍兼容。
78
84
 
79
85
  ### 产品自有 Bundle
80
86
 
@@ -88,7 +94,7 @@ dsh plugin --profile web add .
88
94
  - id: enterprise-oidc
89
95
  name: '@eduwork/dsh-oidc'
90
96
  config:
91
- profilePathEnv: DSH_OIDC_ENTERPRISE_PROFILE
97
+ profilePathEnv: EDUWORK_OIDC_PROFILE
92
98
  web:
93
99
  returnPath: /
94
100
  ```
@@ -97,7 +103,13 @@ dsh plugin --profile web add .
97
103
 
98
104
  OIDC 注册、Key Binding 实现、环境变量、验收和排障见[接入指南](getting-started.md)。
99
105
 
100
- ## Desktop/native 组合
106
+ ## Desktop 组合
107
+
108
+ 新 Wails/Electron 产品使用 `backend: desktop`:插件管理临时 loopback 回调,通过官方 `nativeCommand` 打开浏览器。两壳共享身份、Key Binding 和模型行为;宿主仍提供凭据存储,无需另写 `enterpriseAccounts`。见[桌面 Host 集成](desktop-host.md)。
109
+
110
+ ## 旧 native 桥兼容
111
+
112
+ 以下 adapter 仅用于已有集成,不是新桌面的必做项:
101
113
 
102
114
  ```yaml
103
115
  - insert:
@@ -155,6 +167,10 @@ const dispose = ctx.enterpriseTransforms.register({
155
167
 
156
168
  转换是可执行本地插件,必须单独审查,绝不会从 Enterprise Profile 加载。
157
169
 
170
+ ## 机构适配器的凭据读取
171
+
172
+ 显式安装的本地适配器可调用 `ctx.oidcAccounts.resolveBoundCredential(profileID, { credentialRef: "EDUWORK_API_KEY", runtimeBaseURL })`。`runtimeBaseURL` 必须精确等于该 Profile 已审查的模型服务基址;返回已同时验证 session、issuer/client ID、完整资源绑定和 Key 指纹的 DSH credential record,未满足条件则返回 `undefined`。适配器直接使用这份 record,不应在检查状态后另行解析同名 Key,避免两个读操作之间发生账户切换。此方法只在 Host 存在,没有 Typert/RPC 注册,也不属于服务端协议。适配器仍负责限制其请求目的地址;当前桌面/Web 后端支持该方法,旧 native 桥不会降级返回未经验证的 Key。
173
+
158
174
  ## DSH 升级流程
159
175
 
160
176
  每次升级 DSH release candidate 或 stable 版本时:
@@ -8,7 +8,7 @@ The reference file is [`examples/ecnu.enterprise-profile.example.json`](../examp
8
8
 
9
9
  ## Intended composition
10
10
 
11
- The existing ChatECNU Work product can be expressed as a composition rather than a monolith:
11
+ EduWork@ECNU composes the public core with institution extensions:
12
12
 
13
13
  ```text
14
14
  DeepSeek Harness
@@ -22,12 +22,12 @@ DeepSeek Harness
22
22
  - image-understanding fallback for text-only ecnu-max
23
23
  - enterprise search route and official DSH result rendering
24
24
  - product presets/skills/resources
25
- - native desktop account adapter and OS credential vault
25
+ - legacy native account bridge only (new desktops use the public desktop backend)
26
26
  - quota or institution-specific business UI
27
27
  + desktop shell/packaging/updater
28
28
  ```
29
29
 
30
- Pure Web DSH uses the Web backend and a host-appropriate Credential Provider. ChatECNU Work desktop uses the native backend and keeps its existing Wails implementation behind `enterpriseAccounts`. Both render the enterprise-model section through `dsh-oidc`; the desktop adapter merely advertises additional mutation/restart capabilities. Neither mode changes OIDC or Key Binding server contracts.
30
+ New desktop compositions use the public `desktop` backend and host browser service for temporary loopback login; local functional validation uses `web`. The older Wails `native`/`enterpriseAccounts` bridge is a migration compatibility path, not a requirement for another institution. Trusted files manage organization configuration, while UI shows status and sign-in. Explicit institution plugins own quota, heartbeat and campus search; the public package does not request them. All modes follow the `EDUWORK_API_KEY` rules and complete deployment-binding checks without changing the existing OIDC/Key Binding wire.
31
31
 
32
32
  ## Identity expectation
33
33
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  ## 预期组合
10
10
 
11
- 现有 ChatECNU Work 产品可以表达为组合结构,而不是单体实现:
11
+ EduWork@ECNU 使用公共核心加机构扩展的组合:
12
12
 
13
13
  ```text
14
14
  DeepSeek Harness
@@ -22,12 +22,12 @@ DeepSeek Harness
22
22
  - 面向纯文本 ecnu-max 的图像理解回退
23
23
  - 企业搜索通路和 DSH 官方结果渲染
24
24
  - 产品预设、Skill 和资源
25
- - native 桌面账号 adapter 与操作系统凭据保险库
25
+ - 仅旧版需要的 native 账号桥(新桌面使用公共 desktop 后端)
26
26
  - 配额或机构特有业务 UI
27
27
  + 桌面外壳、打包与更新器
28
28
  ```
29
29
 
30
- 纯 Web DSH 使用 Web 后端和适合宿主的 Credential Provider。ChatECNU Work 桌面端使用 native 后端,并把现有 Wails 实现保留在 `enterpriseAccounts` 后面。两者都通过 `dsh-oidc` 渲染企业模型区域;桌面 adapter 只额外声明可变配置和重启能力。两种模式都不改变 OIDC 或 Key Binding 服务端契约。
30
+ 新桌面组合使用公共 `desktop` 后端,通过宿主浏览器服务完成临时 loopback 登录;本机功能验证用 `web` 后端。旧 Wails 发行版的 `native`/`enterpriseAccounts` 桥属于迁移兼容路径,不是新机构接入要求。企业配置由可信文件管理,界面负责展示和登录。配额、心跳、校内搜索由明确安装的机构插件提供;公版不请求这些服务。所有模式共用 `EDUWORK_API_KEY` 规则和完整部署绑定校验,不改变现有 OIDC/Key Binding wire。
31
31
 
32
32
  ## 身份预期
33
33