@oj-module/cli 0.2.68 → 0.2.71

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 (153) hide show
  1. package/devkit/README.md +10 -8
  2. package/devkit/framework-dev.md +1 -1
  3. package/devkit/manual.md +45 -19
  4. package/devkit/module-dev-and-cdn-playground.md +20 -14
  5. package/devkit/publish-walkthrough.md +132 -43
  6. package/devkit/wecom-customer-reauth-guide.md +110 -0
  7. package/package.json +2 -2
  8. package/shell-dist/assets/{runtime.1xzahckt10.js → runtime.7x99hmm020.js} +2 -2
  9. package/shell-dist/bundles/oj-market-0.2.0.tgz +0 -0
  10. package/shell-dist/bundles/oj-market-0.2.0.tgz.sig +8 -0
  11. package/shell-dist/index.html +4 -4
  12. package/shell-dist/versions.json +3 -3
  13. package/src/__tests__/list.test.ts +7 -7
  14. package/src/__tests__/oj-health-host.test.ts +19 -0
  15. package/src/__tests__/site-tenant-header.test.ts +2 -2
  16. package/src/__tests__/templates-builtin-list.test.ts +47 -0
  17. package/src/__tests__/templates-schema-columns.test.ts +11 -2
  18. package/src/__tests__/templates-tenant-scope.test.ts +2 -3
  19. package/src/__tests__/users-roles-display.test.ts +84 -0
  20. package/src/bundle.ts +1 -1
  21. package/src/contract/__tests__/market-client.integration.test.ts +23 -22
  22. package/src/enable.ts +2 -2
  23. package/src/init.ts +45 -0
  24. package/src/install.ts +5 -5
  25. package/src/lifecycle/__tests__/install.test.ts +29 -29
  26. package/src/lifecycle/__tests__/market-bundle.test.ts +87 -0
  27. package/src/lifecycle/__tests__/publish.test.ts +8 -10
  28. package/src/lifecycle/__tests__/trust.test.ts +14 -14
  29. package/src/lifecycle/__tests__/uninstall.test.ts +4 -4
  30. package/src/list.ts +3 -3
  31. package/src/market/__tests__/bootstrap.test.ts +24 -7
  32. package/src/market/__tests__/failure-playbook.test.ts +0 -1
  33. package/src/market/__tests__/remote-push.test.ts +228 -0
  34. package/src/market/__tests__/verify.test.ts +45 -207
  35. package/src/market/bootstrap.ts +12 -7
  36. package/src/market/command.ts +33 -35
  37. package/src/market/db-seed.ts +129 -0
  38. package/src/market/failure-playbook.ts +3 -9
  39. package/src/market/fixture.ts +2 -6
  40. package/src/market/publish.ts +145 -89
  41. package/src/market/remote-push.ts +236 -0
  42. package/src/market/trial.ts +2 -2
  43. package/src/market/verify.ts +17 -270
  44. package/src/market/walkthrough.ts +38 -63
  45. package/src/oj.ts +13 -2
  46. package/src/preview.ts +5 -3
  47. package/src/publish.ts +3 -2
  48. package/src/scaffold-guard.ts +4 -0
  49. package/src/site.ts +1 -1
  50. package/src/trust.ts +8 -8
  51. package/src/uninstall.ts +2 -2
  52. package/src/usage.ts +23 -21
  53. package/templates/config.yaml +22 -3
  54. package/templates/global.d.ts +6 -4
  55. package/templates/init.include.yaml +16 -11
  56. package/templates/openapi.json +3971 -3663
  57. package/templates/src/.ojm-builtin.json +13 -0
  58. package/templates/src/README.md +5 -2
  59. package/templates/src/app/api/_platform/README.md +3 -2
  60. package/templates/src/app/api/_platform/_lifecycle/atomic.ts +7 -2
  61. package/templates/src/app/api/_platform/_lifecycle/bundle-converge.ts +158 -0
  62. package/templates/src/app/api/_platform/_lifecycle/history.ts +3 -2
  63. package/templates/src/app/api/_platform/_lifecycle/installer.ts +25 -5
  64. package/templates/src/app/api/_platform/_lifecycle/local-archive.ts +61 -0
  65. package/templates/src/app/api/_platform/_lifecycle/manifest-of-upload.ts +62 -0
  66. package/templates/src/app/api/_platform/_lifecycle/steps/preflight.ts +12 -2
  67. package/templates/src/app/api/_platform/_lifecycle/steps/reload.ts +4 -1
  68. package/templates/src/app/api/_platform/_lifecycle/steps/smoke.ts +8 -2
  69. package/templates/src/app/api/_platform/_lifecycle/types.ts +1 -1
  70. package/templates/src/app/api/_platform/_lifecycle/uninstall.ts +14 -5
  71. package/templates/src/app/api/_platform/_shared/service/domain/users.ts +7 -1
  72. package/templates/src/app/api/_platform/_shared/site-facade.ts +31 -0
  73. package/templates/src/app/api/_platform/manifest.yaml +1 -2
  74. package/templates/src/app/api/_platform/migrations/0003__market_catalog.mysql.sql +6 -0
  75. package/templates/src/app/api/_platform/migrations/0003__market_catalog.pg.sql +6 -0
  76. package/templates/src/app/api/_platform/migrations/0003__market_catalog.sql +18 -0
  77. package/templates/src/app/api/_platform/migrations/0004__market_drop_source_seq.mysql.sql +6 -0
  78. package/templates/src/app/api/_platform/migrations/0004__market_drop_source_seq.pg.sql +6 -0
  79. package/templates/src/app/api/_platform/migrations/0004__market_drop_source_seq.sql +6 -0
  80. package/templates/src/app/api/_platform/migrations/0005__market_sig_registry.mysql.sql +8 -0
  81. package/templates/src/app/api/_platform/migrations/0005__market_sig_registry.pg.sql +8 -0
  82. package/templates/src/app/api/_platform/migrations/0005__market_sig_registry.sql +8 -0
  83. package/templates/src/app/api/_platform/schema.yaml +8 -11
  84. package/templates/src/app/api/_platform/seed.mysql.sql +1 -1
  85. package/templates/src/app/api/_platform/seed.pg.sql +1 -1
  86. package/templates/src/app/api/_platform/seed.sql +1 -1
  87. package/templates/src/app/api/auth/_shared/wecom/sync.ts +6 -0
  88. package/templates/src/app/api/system/users/api.ts +3 -0
  89. package/templates/src/app/web/_platform/__client/api.schemas.ts +0 -113
  90. package/templates/src/app/web/_platform/__client/index.ts +1 -333
  91. package/templates/src/app/web/system/__client/api.schemas.ts +2 -0
  92. package/templates/src/app/web/system/locales/en-US.json +15 -1
  93. package/templates/src/app/web/system/locales/zh-CN.json +15 -1
  94. package/templates/src/app/web/system/pages/departments/sync-bar.tsx +9 -3
  95. package/templates/src/app/web/system/pages/roles/index.tsx +4 -8
  96. package/templates/src/app/web/system/pages/roles/role-label.ts +26 -0
  97. package/templates/src/app/web/system/pages/solutions/index.tsx +110 -0
  98. package/templates/src/app/web/system/pages/solutions/market-entry.ts +46 -0
  99. package/templates/src/app/web/system/pages/users/index.tsx +12 -2
  100. package/templates/src/app/web/system/pages/users/match-keyword.ts +19 -0
  101. package/templates/src/app/web/system/pages/users/roles.tsx +43 -14
  102. package/templates/src/app/web/system/routes.ts +18 -1
  103. package/templates/src/{app/api/_platform/market → oj-market/api}/api.ts +475 -592
  104. package/templates/src/oj-market/api/backfill.ts +221 -0
  105. package/templates/src/{app/api/_platform/market → oj-market/api}/bootstrap.ts +2 -2
  106. package/templates/src/oj-market/api/cdn/api.ts +312 -0
  107. package/templates/src/oj-market/api/cdn/shared.ts +104 -0
  108. package/templates/src/oj-market/api/cdn/signed-auth.ts +75 -0
  109. package/templates/src/oj-market/api/manifest.yaml +8 -0
  110. package/templates/src/oj-market/solution.yaml +21 -0
  111. package/templates/src/oj-market/web/__client/api.schemas.ts +167 -0
  112. package/templates/src/oj-market/web/__client/index.ts +509 -0
  113. package/templates/src/oj-market/web/__tests__/marketClient.fake.ts +6 -6
  114. package/templates/src/oj-market/web/api/client.ts +6 -6
  115. package/templates/src/oj-market/web/api/defaultClient.ts +31 -25
  116. package/templates/src/oj-market/web/entry.ts +5 -3
  117. package/templates/src/oj-market/web/hooks/useMarket.ts +6 -6
  118. package/templates/src/oj-market/web/pages/MarketApp.tsx +20 -3
  119. package/templates/src/oj-market/web/publish/locales/en-US.json +1 -1
  120. package/templates/src/oj-market/web/publish/locales/zh-CN.json +1 -1
  121. package/templates/src/oj-market/web/publish/pages/history.tsx +2 -11
  122. package/templates/src/oj-market/web/routes.ts +12 -0
  123. package/templates/src/oj-market/web/types.ts +14 -8
  124. package/templates/tests/lifecycle/anonymous-wiring.spec.ts +65 -0
  125. package/templates/tests/lifecycle/backfill.spec.ts +392 -0
  126. package/templates/tests/lifecycle/bootstrap.spec.ts +1 -1
  127. package/templates/tests/lifecycle/bundle-converge.spec.ts +264 -0
  128. package/templates/tests/lifecycle/cdn-upload.spec.ts +661 -0
  129. package/templates/tests/lifecycle/deploy-smoke.spec.ts +25 -0
  130. package/templates/tests/lifecycle/exec-grant.spec.ts +38 -0
  131. package/templates/tests/lifecycle/installer.spec.ts +36 -0
  132. package/templates/tests/lifecycle/market-api.spec.ts +448 -803
  133. package/templates/tests/lifecycle/preflight.spec.ts +18 -0
  134. package/templates/tests/lifecycle/trust.spec.ts +2 -2
  135. package/templates/tests/lifecycle/uninstall.spec.ts +36 -2
  136. package/templates/tests/lifecycle/verify-checks.spec.ts +1 -1
  137. package/templates/tests/rbac-users.spec.ts +8 -0
  138. package/templates/tests/solutions-entry.spec.ts +55 -0
  139. package/templates/tsconfig.paths.json +1 -0
  140. package/templates/types/stream-probes/stream-handlers.ts +34 -0
  141. package/templates/web.config.ts +6 -6
  142. package/vendor/host-versions.json +3 -3
  143. package/bin/oj +0 -4
  144. package/src/market/__tests__/build-index.test.ts +0 -641
  145. package/src/market/__tests__/sharding.test.ts +0 -90
  146. package/src/market/__tests__/yank-ledger.test.ts +0 -60
  147. package/src/market/build-index.ts +0 -526
  148. package/src/market/index-builder.ts +0 -149
  149. package/src/market/sharding.ts +0 -94
  150. package/src/market/yank-ledger.ts +0 -91
  151. package/templates/src/app/api/_platform/_lifecycle/source-seq.ts +0 -88
  152. package/templates/src/app/api/_platform/market/index-source.ts +0 -112
  153. package/templates/tests/lifecycle/source-seq.spec.ts +0 -55
@@ -1,5 +1,5 @@
1
1
  name: _platform
2
- desc: 平台内核(非业务模块、无自身业务路由前缀)。含三类:① 跨模块服务 _shared/service(infra 基础设施 + domain 管理域);② 生命周期引擎 _lifecycle(方案安装/卸载/注册/验签/信任状态机);③ 平台编排 API 面 /api/_platform/{contacts,market,solutions}(由 market/api.ts、contacts/api.ts、solutions/api.ts 暴露,全 superadmin 门禁)。运行时安装的方案包不在此树。
2
+ desc: 平台内核(非业务模块、无自身业务路由前缀)。含三类:① 跨模块服务 _shared/service(infra 基础设施 + domain 管理域);② 生命周期引擎 _lifecycle(方案安装/卸载/注册/验签/信任状态机);③ 平台编排 API 面 /api/_platform/{contacts,solutions}(由 contacts/api.ts、solutions/api.ts 暴露,全 superadmin 门禁)。市场域 api(市场目录/发布推送/方案生命周期编排/信任库)自 v4 起归 oj-market 模块(src/oj-market/api/,路由 /api/oj-market/*,deps 声明依赖本内核)。运行时安装的方案包不在此树。
3
3
  version: 0.1.0
4
4
  tables:
5
5
  - _oj_migrations
@@ -16,7 +16,6 @@ tables:
16
16
  - market_release
17
17
  - sys_rate_window
18
18
  - sys_login_throttle
19
- - reg_source_seq
20
19
  # 0016 组织架构领域(CRUD 基线 + 外部源适配器的落点;两张都是租户表)
21
20
  - sys_department
22
21
  - sys_dept_member
@@ -0,0 +1,6 @@
1
+ -- 0003__market_catalog(mysql 方言):列语义同 0003__market_catalog.sql 头注释。
2
+ -- 差异(沿用 0002 既有惯例):短文本收窄 VARCHAR;签名 value ≤ 255 base64 够用。
3
+ ALTER TABLE market_release ADD COLUMN sig_alg VARCHAR(16);
4
+ ALTER TABLE market_release ADD COLUMN sig_value VARCHAR(255);
5
+ ALTER TABLE market_release ADD COLUMN sig_public_key VARCHAR(64);
6
+ ALTER TABLE market_release ADD COLUMN manifest TEXT;
@@ -0,0 +1,6 @@
1
+ -- 0003__market_catalog(postgres 方言):列语义同 0003__market_catalog.sql 头注释。
2
+ -- 差异(沿用 0002 既有惯例):TEXT 全保留。
3
+ ALTER TABLE market_release ADD COLUMN sig_alg TEXT;
4
+ ALTER TABLE market_release ADD COLUMN sig_value TEXT;
5
+ ALTER TABLE market_release ADD COLUMN sig_public_key TEXT;
6
+ ALTER TABLE market_release ADD COLUMN manifest TEXT;
@@ -0,0 +1,18 @@
1
+ -- 0003__market_catalog(sqlite 方言):market_release 扩列演化(v4 DB 目录化)。
2
+ --
3
+ -- 定性:**表演化,非新建**——market_release 已存在于 0002(四方评审共同指认的 P0 修正:
4
+ -- v3 原拟新建同名表照写必炸)。此处仅 ALTER 扩四列,把「签名索引文件派生物」升级为
5
+ -- 「签名推送直写的目录真源」:
6
+ -- · sig_alg/sig_value/sig_public_key = 上传端点验收的发布签名三字段(Ed25519,
7
+ -- 与 .sig 侧车同构;canon/key_id 不列存——canonical 由 (registry_id,name,sha256)
8
+ -- 服务端重算重建,key_id 已有专列)
9
+ -- · manifest = 包内嵌 manifest.yaml 抽取物(JSON 文本;安装解析/卡片字段数据源,
10
+ -- 坏包被 pair 约束挡在库外,见上传端点处理顺序)
11
+ -- · published_at 两列保留语义不变;上传写入行 published_at_source='upload'
12
+ -- · syncReleases 时代旧行此四列 = NULL,由站点侧扫描回填命令补齐(计划 §六,三用命令)
13
+ --
14
+ -- 方言差异照 0002 惯例:mysql 收窄 VARCHAR / pg 全 TEXT,见同名 .mysql/.pg 文件。
15
+ ALTER TABLE market_release ADD COLUMN sig_alg TEXT;
16
+ ALTER TABLE market_release ADD COLUMN sig_value TEXT;
17
+ ALTER TABLE market_release ADD COLUMN sig_public_key TEXT;
18
+ ALTER TABLE market_release ADD COLUMN manifest TEXT;
@@ -0,0 +1,6 @@
1
+ -- 0004__market_drop_source_seq(mysql 方言):退役 reg_source_seq 水位表(v4 §四索引机制整建制退役)。
2
+ --
3
+ -- 定性:签名索引(catalog.yaml + shards/<n>.yaml + 代次水位防回放)随 DB 目录化退役——
4
+ -- install 解析/index 卡片/releases 历史全部直读 market_release 表,水位失去消费方。
5
+ -- DROP IF EXISTS 幂等:回填/回滚场景重复应用不炸。三方言同形(无方言差异)。
6
+ DROP TABLE IF EXISTS reg_source_seq;
@@ -0,0 +1,6 @@
1
+ -- 0004__market_drop_source_seq(pg 方言):退役 reg_source_seq 水位表(v4 §四索引机制整建制退役)。
2
+ --
3
+ -- 定性:签名索引(catalog.yaml + shards/<n>.yaml + 代次水位防回放)随 DB 目录化退役——
4
+ -- install 解析/index 卡片/releases 历史全部直读 market_release 表,水位失去消费方。
5
+ -- DROP IF EXISTS 幂等:回填/回滚场景重复应用不炸。三方言同形(无方言差异)。
6
+ DROP TABLE IF EXISTS reg_source_seq;
@@ -0,0 +1,6 @@
1
+ -- 0004__market_drop_source_seq(sqlite 方言):退役 reg_source_seq 水位表(v4 §四索引机制整建制退役)。
2
+ --
3
+ -- 定性:签名索引(catalog.yaml + shards/<n>.yaml + 代次水位防回放)随 DB 目录化退役——
4
+ -- install 解析/index 卡片/releases 历史全部直读 market_release 表,水位失去消费方。
5
+ -- DROP IF EXISTS 幂等:回填/回滚场景重复应用不炸。三方言同形(无方言差异)。
6
+ DROP TABLE IF EXISTS reg_source_seq;
@@ -0,0 +1,8 @@
1
+ -- 0005__market_sig_registry(mysql 方言):market_release 补 sig_registry_id 列(v4 §四 A5 增补)。
2
+ --
3
+ -- 定性:**A5 实施期修正**——安装解析改走 DB 目录行(formBEntryOf 服务端合成 Form B 条目),
4
+ -- install verify 段重构包级规范串 `<registry_id>:<name>@<version>:<sha256>` 需要签发方
5
+ -- registry 身份;0003 落列时裁定「registry_id 不进合成签名」被本修正取代(DB 行即安装
6
+ -- manifest 真源,签名必须可验)。列值 = 上传 .sig 旁车第六字段(上传端点结构校验落列)。
7
+ -- 方言差异照 0003 惯例:mysql 收窄 VARCHAR / pg 全 TEXT。
8
+ ALTER TABLE market_release ADD COLUMN sig_registry_id VARCHAR(255);
@@ -0,0 +1,8 @@
1
+ -- 0005__market_sig_registry(pg 方言):market_release 补 sig_registry_id 列(v4 §四 A5 增补)。
2
+ --
3
+ -- 定性:**A5 实施期修正**——安装解析改走 DB 目录行(formBEntryOf 服务端合成 Form B 条目),
4
+ -- install verify 段重构包级规范串 `<registry_id>:<name>@<version>:<sha256>` 需要签发方
5
+ -- registry 身份;0003 落列时裁定「registry_id 不进合成签名」被本修正取代(DB 行即安装
6
+ -- manifest 真源,签名必须可验)。列值 = 上传 .sig 旁车第六字段(上传端点结构校验落列)。
7
+ -- 方言差异照 0003 惯例:mysql 收窄 VARCHAR / pg 全 TEXT。
8
+ ALTER TABLE market_release ADD COLUMN sig_registry_id TEXT;
@@ -0,0 +1,8 @@
1
+ -- 0005__market_sig_registry(sqlite 方言):market_release 补 sig_registry_id 列(v4 §四 A5 增补)。
2
+ --
3
+ -- 定性:**A5 实施期修正**——安装解析改走 DB 目录行(formBEntryOf 服务端合成 Form B 条目),
4
+ -- install verify 段重构包级规范串 `<registry_id>:<name>@<version>:<sha256>` 需要签发方
5
+ -- registry 身份;0003 落列时裁定「registry_id 不进合成签名」被本修正取代(DB 行即安装
6
+ -- manifest 真源,签名必须可验)。列值 = 上传 .sig 旁车第六字段(上传端点结构校验落列)。
7
+ -- 方言差异照 0003 惯例:mysql 收窄 VARCHAR / pg 全 TEXT。
8
+ ALTER TABLE market_release ADD COLUMN sig_registry_id TEXT;
@@ -185,17 +185,14 @@ tables:
185
185
  published_at_source: {type: text, null: false}
186
186
  yanked: {type: integer, null: false}
187
187
  first_seen_at: {type: integer, null: false}
188
- # REG-CS2 索引新鲜度:站点按源记住见过的最大 seq(防回放/降级,回退即拒)。
189
- # 读写由 _lifecycle/source-seq.ts 落到本表;source_url 为业务主键(无自增 id)。
190
- reg_source_seq:
191
- # 共享表(B 组):索引新鲜度水位属于**站点**(受害者是站点,防回放/降级),
192
- # 与租户无关;source-seq.ts 的设计注释即写明「记在站点 DB」。
193
- tenant: false
194
- pk: source_url
195
- columns:
196
- source_url: {type: text, null: false}
197
- max_seq: {type: integer, null: false}
198
- updated_at: {type: integer, null: false}
188
+ # v4 DB 目录化(0003 扩列):签名推送直写的目录真源——签名三字段 + 包内嵌 manifest
189
+ # 抽取物。旧行(syncReleases 时代)此四列 = NULL,由站点侧扫描回填命令补齐(计划 §六)。
190
+ sig_alg: {type: text}
191
+ sig_value: {type: text}
192
+ sig_public_key: {type: text}
193
+ # A5 增补:包级 canonical 首段(签发方 registry 身份)——install verify 重构规范串用
194
+ sig_registry_id: {type: text}
195
+ manifest: {type: text}
199
196
  # ---- 0016:组织架构领域(CRUD 基线 + 外部源适配器的落点)----
200
197
  # 定位(方案 §14):CRUD 是基线,企微 / LDAP 只是适配器 → 表里不出现任何 wecom_* / ldap_* 字段。
201
198
  # origin 是**归属权**标识(D13):local = 本站管理员全权;wecom/ldap/sso = 该适配器管辖,
@@ -4,7 +4,7 @@ INSERT IGNORE INTO users (username, password_hash, must_change) VALUES ('superad
4
4
  INSERT IGNORE INTO users (username, password_hash, must_change) VALUES ('admin', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0);
5
5
  INSERT IGNORE INTO users (username, password_hash, must_change) VALUES ('editor', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0);
6
6
  INSERT IGNORE INTO users (username, password_hash, must_change) VALUES ('viewer', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0);
7
- DELETE FROM sys_user_role WHERE role_name = 'superadmin' AND user_id = (SELECT id FROM users WHERE username = 'admin');
7
+ DELETE FROM sys_user_role WHERE role_name = 'superadmin' AND user_id IN (SELECT id FROM users WHERE username = 'admin');
8
8
  UPDATE users SET must_change = 0 WHERE username IN ('superadmin', 'admin', 'editor', 'viewer');
9
9
  INSERT IGNORE INTO sys_role (name, module, title, builtin) VALUES ('superadmin', 'framework', '超级管理员', 1);
10
10
  INSERT IGNORE INTO sys_role (name, module, title, builtin) VALUES ('admin', 'framework', '系统管理员', 1);
@@ -4,7 +4,7 @@ INSERT INTO users (username, password_hash, must_change) VALUES ('superadmin', '
4
4
  INSERT INTO users (username, password_hash, must_change) VALUES ('admin', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0) ON CONFLICT DO NOTHING;
5
5
  INSERT INTO users (username, password_hash, must_change) VALUES ('editor', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0) ON CONFLICT DO NOTHING;
6
6
  INSERT INTO users (username, password_hash, must_change) VALUES ('viewer', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0) ON CONFLICT DO NOTHING;
7
- DELETE FROM sys_user_role WHERE role_name = 'superadmin' AND user_id = (SELECT id FROM users WHERE username = 'admin');
7
+ DELETE FROM sys_user_role WHERE role_name = 'superadmin' AND user_id IN (SELECT id FROM users WHERE username = 'admin');
8
8
  UPDATE users SET must_change = 0 WHERE username IN ('superadmin', 'admin', 'editor', 'viewer');
9
9
  INSERT INTO sys_role (name, module, title, builtin) VALUES ('superadmin', 'framework', '超级管理员', 1) ON CONFLICT DO NOTHING;
10
10
  INSERT INTO sys_role (name, module, title, builtin) VALUES ('admin', 'framework', '系统管理员', 1) ON CONFLICT DO NOTHING;
@@ -11,7 +11,7 @@ INSERT OR IGNORE INTO users (username, password_hash, must_change) VALUES ('edit
11
11
  INSERT OR IGNORE INTO users (username, password_hash, must_change) VALUES ('viewer', '$2y$10$9HEtASi9jG0VIBMMVqxAmOqrE4f6wiezhGmi50iPG1s1MXlncSO0e', 0);
12
12
  -- 历史 seed 把 admin 绑在 superadmin 上;收敛为账号名=角色名(幂等 DELETE,每次重放生效)。
13
13
  -- 已存在库中 admin 行可能残留 must_change=1,UPDATE 统一收敛为 0(四个均为 seed 自有开发账号)
14
- DELETE FROM sys_user_role WHERE role_name = 'superadmin' AND user_id = (SELECT id FROM users WHERE username = 'admin');
14
+ DELETE FROM sys_user_role WHERE role_name = 'superadmin' AND user_id IN (SELECT id FROM users WHERE username = 'admin');
15
15
  UPDATE users SET must_change = 0 WHERE username IN ('superadmin', 'admin', 'editor', 'viewer');
16
16
  -- 框架内置角色(ROLES 单一真相:superadmin 安全敏感项 / admin 日常管理 / editor、viewer 页面门)
17
17
  INSERT OR IGNORE INTO sys_role (name, module, title, builtin) VALUES ('superadmin', 'framework', '超级管理员', 1);
@@ -400,6 +400,12 @@ async function runSlice(
400
400
  for (const d of ordered) {
401
401
  if (d.name)
402
402
  continue;
403
+ // 受同片预算约束:预算耗尽就跳过剩余名字回源(名字留空非致命,下轮/事件增量会补)。
404
+ // 否则无名字的部门一多(每个 department/get 最多等 5s 软超时),departments 阶段会
405
+ // 跑出 12s 预算、甚至超过客户端/路由超时——外层切片本就为「可控时长」而设计,
406
+ // 这里若不拦,整片就失去时长上界(members 阶段有同款 deadline 守卫,这里原本漏了)。
407
+ if (deps.now() >= deadline)
408
+ continue;
403
409
  try {
404
410
  const detail = await deps.client.departmentDetail(corpId, agentId, secret, d.id);
405
411
  if (detail.name)
@@ -25,6 +25,9 @@ get.response = {
25
25
  display_name: { type: ["string", "null"] },
26
26
  email: { type: ["string", "null"] },
27
27
  position: { type: ["string", "null"] },
28
+ // U3:users 表既有列透出(工号 tenant 内唯一);未设置为 null,故为可选字段
29
+ employee_no: { type: ["string", "null"] },
30
+ phone_number: { type: ["string", "null"] },
28
31
  // 所属部门(主部门在前);未加入任何部门即空数组。带 id 供前端按部门筛选
29
32
  departments: {
30
33
  type: "array",
@@ -25,119 +25,6 @@ export const schemas = {
25
25
  "display_name": z.string().nullable(),
26
26
  "email": z.string().nullable(),
27
27
  "avatar_base64": z.string().nullable()
28
- }),
29
- },
30
- "platformMarketInstallPost": {
31
- body: z.object({
32
- "source": z.enum(["cdn", "file"]),
33
- "name": z.string(),
34
- "version": z.string().nullable().optional()
35
- }),
36
- data: z.object({
37
- "task_id": z.string().optional()
38
- }).catchall(z.unknown()),
39
- },
40
- "platformMarketInstallCancelPost": {
41
- body: z.object({
42
- "name": z.string()
43
- }),
44
- data: z.object({
45
- "ok": z.boolean().optional(),
46
- "name": z.string().optional(),
47
- "requested": z.boolean().optional()
48
- }).catchall(z.unknown()),
49
- },
50
- "platformMarketTaskGet": {
51
- query: z.object({
52
- "id": z.string()
53
- }),
54
- data: z.object({
55
-
56
- }).catchall(z.unknown()),
57
- },
58
- "platformMarketEnablePost": {
59
- body: z.object({
60
- "name": z.string(),
61
- "enabled": z.boolean()
62
- }),
63
- data: z.object({
64
-
65
- }).catchall(z.unknown()),
66
- },
67
- "platformMarketMetaGet": {
68
- data: z.object({
69
- "apiVersion": z.string().optional()
70
- }).catchall(z.unknown()),
71
- },
72
- "platformMarketTrustGet": {
73
- data: z.object({
74
-
75
- }).catchall(z.unknown()),
76
- },
77
- "platformMarketTrustPost": {
78
- body: z.object({
79
- "task_id": z.string()
80
- }),
81
- data: z.object({
82
-
83
- }).catchall(z.unknown()),
84
- },
85
- "platformMarketTrustKeyPost": {
86
- body: z.object({
87
- "key_id": z.string(),
88
- "public_key": z.string()
89
- }),
90
- data: z.object({
91
-
92
- }).catchall(z.unknown()),
93
- },
94
- "platformMarketTrustKeyDelete": {
95
- query: z.object({
96
- "key_id": z.string()
97
- }),
98
- data: z.object({
99
-
100
- }).catchall(z.unknown()),
101
- },
102
- "platformMarketIndexGet": {
103
- data: z.array(z.object({
104
-
105
- }).catchall(z.unknown())),
106
- },
107
- "platformMarketUninstallImpactGet": {
108
- query: z.object({
109
- "name": z.string()
110
- }),
111
- data: z.object({
112
-
113
- }).catchall(z.unknown()),
114
- },
115
- "platformMarketUninstallPost": {
116
- body: z.object({
117
- "name": z.string()
118
- }),
119
- data: z.object({
120
-
121
- }).catchall(z.unknown()),
122
- },
123
- "platformMarketHistoryGet": {
124
- data: z.array(z.object({
125
-
126
- }).catchall(z.unknown())),
127
- },
128
- "platformMarketReleasesGet": {
129
- query: z.object({
130
- "page": z.number().min(1).optional(),
131
- "limit": z.number().min(1).max(200).optional()
132
- }),
133
- data: z.object({
134
- "list": z.array(z.object({
135
-
136
- }).catchall(z.unknown())),
137
- "total": z.number(),
138
- "page": z.number(),
139
- "size": z.number(),
140
- "syncError": z.string().nullable().optional()
141
28
  }),
142
29
  },
143
30
  "platformOrgDepartmentsGet": {