@oj-module/cli 0.2.47 → 0.2.48

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 (94) hide show
  1. package/devkit/SKILL.md +1 -1
  2. package/devkit/framework-dev.md +2 -2
  3. package/devkit/manual.md +24 -14
  4. package/devkit/module-dev-and-cdn-playground.md +2 -2
  5. package/devkit/wecom-daikaifa.md +237 -14
  6. package/package.json +2 -2
  7. package/shell-dist/assets/runtime.js +2 -2
  8. package/shell-dist/index.html +2 -2
  9. package/shell-dist/versions.json +3 -3
  10. package/src/__tests__/templates-tenant-scope.test.ts +7 -2
  11. package/src/init.ts +1 -1
  12. package/src/market/__tests__/bootstrap.test.ts +1 -1
  13. package/src/market/__tests__/setup.test.ts +7 -7
  14. package/src/market/bootstrap.ts +1 -1
  15. package/templates/README.md +1 -1
  16. package/templates/init.include.yaml +12 -0
  17. package/templates/openapi.json +2863 -549
  18. package/templates/src/_platform/api/_shared/service/domain/contacts.ts +7 -0
  19. package/templates/src/_platform/api/_shared/service/domain/org-read.ts +451 -0
  20. package/templates/src/_platform/api/_shared/service/domain/org.ts +566 -0
  21. package/templates/src/_platform/api/_shared/service/domain/users.ts +140 -2
  22. package/templates/src/_platform/api/_shared/service/infra/query.ts +2 -1
  23. package/templates/src/_platform/api/fixtures/l1-test-user.sql +1 -1
  24. package/templates/src/_platform/api/manifest.yaml +3 -0
  25. package/templates/src/_platform/api/migrations/0016__org.mysql.sql +41 -0
  26. package/templates/src/_platform/api/migrations/0016__org.pg.sql +40 -0
  27. package/templates/src/_platform/api/migrations/0016__org.sql +62 -0
  28. package/templates/src/_platform/api/org/departments/api.ts +51 -0
  29. package/templates/src/_platform/api/org/is-member/api.ts +33 -0
  30. package/templates/src/_platform/api/org/members/api.ts +55 -0
  31. package/templates/src/_platform/api/org/picker/api.ts +59 -0
  32. package/templates/src/_platform/api/org/resolve/api.ts +38 -0
  33. package/templates/src/_platform/api/org/tree/api.ts +37 -0
  34. package/templates/src/_platform/api/org/user/api.ts +46 -0
  35. package/templates/src/_platform/api/schema.yaml +48 -0
  36. package/templates/src/_platform/api/seed.mysql.sql +10 -5
  37. package/templates/src/_platform/api/seed.pg.sql +10 -5
  38. package/templates/src/_platform/api/seed.sql +13 -5
  39. package/templates/src/_platform/web/__client/api.schemas.ts +126 -0
  40. package/templates/src/_platform/web/__client/api.ts +170 -1
  41. package/templates/src/auth/api/_shared/ldap-login.ts +2 -0
  42. package/templates/src/auth/api/_shared/session.ts +5 -1
  43. package/templates/src/auth/api/_shared/wecom/admin.ts +3 -1
  44. package/templates/src/auth/api/_shared/wecom/client.ts +243 -31
  45. package/templates/src/auth/api/_shared/wecom/config.ts +12 -1
  46. package/templates/src/auth/api/_shared/wecom/contacts.ts +263 -0
  47. package/templates/src/auth/api/_shared/wecom/crypt.ts +17 -7
  48. package/templates/src/auth/api/_shared/wecom/events.ts +111 -26
  49. package/templates/src/auth/api/_shared/wecom/login.ts +152 -1
  50. package/templates/src/auth/api/_shared/wecom/payload.ts +116 -0
  51. package/templates/src/auth/api/_shared/wecom/store.ts +65 -0
  52. package/templates/src/auth/api/_shared/wecom/sync.ts +487 -0
  53. package/templates/src/auth/api/manifest.yaml +3 -0
  54. package/templates/src/auth/api/migrations/0002__org_sync.mysql.sql +28 -0
  55. package/templates/src/auth/api/migrations/0002__org_sync.pg.sql +27 -0
  56. package/templates/src/auth/api/migrations/0002__org_sync.sql +41 -0
  57. package/templates/src/auth/api/schema.yaml +31 -0
  58. package/templates/src/auth/api/wecom/admin/api.ts +3 -1
  59. package/templates/src/auth/api/wecom/api.ts +100 -18
  60. package/templates/src/auth/api/wecom/sync/api.ts +199 -0
  61. package/templates/src/auth/web/__client/api.schemas.ts +97 -0
  62. package/templates/src/auth/web/__client/api.ts +73 -1
  63. package/templates/src/notification/api/seed.sql +1 -1
  64. package/templates/src/system/api/departments/api.ts +142 -0
  65. package/templates/src/system/api/departments/detach/api.ts +34 -0
  66. package/templates/src/system/api/departments/members/api.ts +142 -0
  67. package/templates/src/system/api/departments/move/api.ts +39 -0
  68. package/templates/src/system/api/users/api.ts +45 -5
  69. package/templates/src/system/api/users/profile/api.ts +44 -0
  70. package/templates/src/system/web/__client/api.schemas.ts +143 -0
  71. package/templates/src/system/web/__client/api.ts +293 -1
  72. package/templates/src/system/web/entry.ts +6 -0
  73. package/templates/src/system/web/locales/en-US.json +112 -6
  74. package/templates/src/system/web/locales/zh-CN.json +112 -6
  75. package/templates/src/system/web/pages/departments/index.tsx +346 -0
  76. package/templates/src/system/web/pages/departments/sync-bar.tsx +257 -0
  77. package/templates/src/system/web/pages/departments/tree.ts +66 -0
  78. package/templates/src/system/web/pages/errors.ts +1 -1
  79. package/templates/src/system/web/pages/users/index.tsx +49 -7
  80. package/templates/src/system/web/pages/wecom/index.tsx +14 -0
  81. package/templates/tests/l1-builder.test.ts +1 -1
  82. package/templates/tests/org-departments.spec.ts +311 -0
  83. package/templates/tests/org-read.spec.ts +469 -0
  84. package/templates/tests/rbac-contacts.spec.ts +13 -3
  85. package/templates/tests/rbac-seed.spec.ts +11 -0
  86. package/templates/tests/seed-role-accounts.spec.ts +6 -2
  87. package/templates/tests/wecom-admin.spec.ts +1 -0
  88. package/templates/tests/wecom-connector.spec.ts +115 -8
  89. package/templates/tests/wecom-crypt.spec.ts +12 -3
  90. package/templates/tests/wecom-endpoints.spec.ts +182 -14
  91. package/templates/tests/wecom-org-sync.spec.ts +598 -0
  92. package/templates/tests/wecom-sync.spec.ts +286 -0
  93. package/vendor/host-versions.json +3 -3
  94. package/templates/src/auth/api/_shared/wecom/xml.ts +0 -36
@@ -7,9 +7,9 @@
7
7
  "react-router": "7.18.2",
8
8
  "react-router/dom": "7.18.2",
9
9
  "@tanstack/react-query": "5.102.8",
10
- "@oj-module/runtime": "0.2.47",
11
- "@oj-module/runtime/contract": "0.2.47",
12
- "@oj-module/runtime/contract/errors": "0.2.47",
10
+ "@oj-module/runtime": "0.2.48",
11
+ "@oj-module/runtime/contract": "0.2.48",
12
+ "@oj-module/runtime/contract/errors": "0.2.48",
13
13
  "@plane/kit": "0.1.20",
14
14
  "@plane/editor": "0.1.20",
15
15
  "antd": "6.6.1",
@@ -115,11 +115,16 @@ describe("templates 租户定性(A 租户表 / B 共享表)", () => {
115
115
  expect(unknown).toEqual([]);
116
116
  });
117
117
 
118
- it("t-4 24 张表的 A/B 分组与方案 v3 §5.2 一致(新增表须先定性)", () => {
118
+ it("t-4 28 张表的 A/B 分组与方案 v3 §5.2 一致(新增表须先定性)", () => {
119
119
  const { tables } = loadSchemaTables();
120
120
  const shared = [...tables].filter(([, d]) => d.tenant === false).map(([n]) => n).sort();
121
121
  // Phase 0 落地 21 张(11 A + 10 B);Phase 1 加企微三表,全部 B 组(D9:查它们时必然还没有租户上下文)
122
- expect(tables.size).toBe(24);
122
+ // 0016 组织架构加 sys_department / sys_dept_member 两张,均 A 组租户表(组织架构天然按租户隔离,
123
+ // 企微部署下 tenant_id = corp_id;只在有租户上下文时被读写,与 users / sys_oplog 同口径)。
124
+ // auth/0002 加 wecom_sync_job / wecom_sync_lock 两张,同属 A 组:同步只在调用方自己的租户内跑
125
+ // (D7 不接受 corpId 参数),故不进 shared_allow——跨租户读元数据那条另走显式 tenant_id 的裸 SQL。
126
+ // 改这张表清单 = 改租户隔离边界,必须同步 config.yaml 的 tenant.shared_allow(t-2/t-3 会把关)。
127
+ expect(tables.size).toBe(28);
123
128
  expect(shared).toEqual([
124
129
  "_oj_migrations",
125
130
  "market_history",
package/src/init.ts CHANGED
@@ -245,7 +245,7 @@ export async function initProject(destDir: string, opts: InitOptions = {}): Prom
245
245
  console.log(`[ojm] · 跳过 ${item}`);
246
246
  for (const item of report.warnings)
247
247
  console.warn(`[ojm] ! ${item}`);
248
- console.log("[ojm] 下一步:pnpm install && pnpm dev(登录 superadmin / 123456,角色账号见 devkit 手册 §1.1)");
248
+ console.log("[ojm] 下一步:pnpm install && pnpm dev(登录 superadmin / aA123456,角色账号见 devkit 手册 §1.1)");
249
249
  }
250
250
 
251
251
  /** 默认密封器:bin/oj secret keygen + seal(失败返回 null,不抛) */
@@ -120,7 +120,7 @@ describe("given 一个装了 oj 二进制的源工程 When 自举隔离站点",
120
120
  const site = await bootstrapIsolatedSite({ projectRoot: src, starter });
121
121
 
122
122
  expect(site.admin.user).toBe("superadmin");
123
- expect(site.admin.pass).toBe("123456");
123
+ expect(site.admin.pass).toBe("aA123456");
124
124
  await site.cleanup();
125
125
  });
126
126
 
@@ -62,7 +62,7 @@ describe("given 站点可直连且凭据未悬挂 When setup", () => {
62
62
  const root = newProject();
63
63
  const site = fakeSite();
64
64
 
65
- const result = await setupMarketUrl({ projectRoot: root, user: "admin", pass: "123456", siteUrl: "http://127.0.0.1:9778", fetchFn: site.fetchFn });
65
+ const result = await setupMarketUrl({ projectRoot: root, user: "admin", pass: "aA123456", siteUrl: "http://127.0.0.1:9778", fetchFn: site.fetchFn });
66
66
 
67
67
  expect(result.cdnBaseUrl).toBe("http://127.0.0.1:9778/cdn");
68
68
  const put = site.calls.find(c => c.url.endsWith("/api/system/settings"))!;
@@ -77,12 +77,12 @@ describe("given seed admin 处于 must_change 悬挂期 When setup", () => {
77
77
  const root = newProject();
78
78
  const site = fakeSite({ restricted: true });
79
79
 
80
- const result = await setupMarketUrl({ projectRoot: root, user: "admin", pass: "123456", newPass: "newpass-123", siteUrl: "http://127.0.0.1:9778", fetchFn: site.fetchFn });
80
+ const result = await setupMarketUrl({ projectRoot: root, user: "admin", pass: "aA123456", newPass: "newpass-123", siteUrl: "http://127.0.0.1:9778", fetchFn: site.fetchFn });
81
81
 
82
82
  expect(result.changedPassword).toBe(true);
83
83
  const pwd = site.calls.find(c => c.url.endsWith("/api/auth/password"))!;
84
84
  expect(pwd.method).toBe("PUT");
85
- expect(pwd.body).toEqual({ old_password: "123456", new_password: "newpass-123" });
85
+ expect(pwd.body).toEqual({ old_password: "aA123456", new_password: "newpass-123" });
86
86
  const put = site.calls.find(c => c.url.endsWith("/api/system/settings"))!;
87
87
  expect(put.auth).toBe("Bearer token-full");
88
88
  });
@@ -96,7 +96,7 @@ describe("given 站点不可达 When setup", () => {
96
96
  };
97
97
  const fetchFn = failing as unknown as typeof fetch;
98
98
 
99
- await expect(setupMarketUrl({ projectRoot: root, user: "admin", pass: "123456", siteUrl: "http://127.0.0.1:9778", fetchFn }))
99
+ await expect(setupMarketUrl({ projectRoot: root, user: "admin", pass: "aA123456", siteUrl: "http://127.0.0.1:9778", fetchFn }))
100
100
  .rejects
101
101
  .toThrow(/ojm dev/);
102
102
  });
@@ -107,7 +107,7 @@ describe("given 改密后写设置仍被拒 When setup", () => {
107
107
  const root = newProject();
108
108
  const site = fakeSite({ restricted: true, rejectSettings: true });
109
109
 
110
- await expect(setupMarketUrl({ projectRoot: root, user: "admin", pass: "123456", newPass: "newpass-123", siteUrl: "http://127.0.0.1:9778", fetchFn: site.fetchFn }))
110
+ await expect(setupMarketUrl({ projectRoot: root, user: "admin", pass: "aA123456", newPass: "newpass-123", siteUrl: "http://127.0.0.1:9778", fetchFn: site.fetchFn }))
111
111
  .rejects
112
112
  .toThrow(/must_change|权限|设置/);
113
113
  });
@@ -115,7 +115,7 @@ describe("given 改密后写设置仍被拒 When setup", () => {
115
115
 
116
116
  describe("given setup 返回 changedPassword When 选 setup 后的登录口令", () => {
117
117
  it("then 改密已发生用 newPass,未改密用原种子口令(must_change=0 是当前 seed 常态)", () => {
118
- expect(loginPasswordAfterSetup({ siteUrl: "", cdnBaseUrl: "", changedPassword: true }, "new-pass", "123456")).toBe("new-pass");
119
- expect(loginPasswordAfterSetup({ siteUrl: "", cdnBaseUrl: "", changedPassword: false }, "new-pass", "123456")).toBe("123456");
118
+ expect(loginPasswordAfterSetup({ siteUrl: "", cdnBaseUrl: "", changedPassword: true }, "new-pass", "aA123456")).toBe("new-pass");
119
+ expect(loginPasswordAfterSetup({ siteUrl: "", cdnBaseUrl: "", changedPassword: false }, "new-pass", "aA123456")).toBe("aA123456");
120
120
  });
121
121
  });
@@ -39,7 +39,7 @@ import { publishPackage } from "./publish";
39
39
  // 种子管理员 = superadmin:模板 seed 账号名=角色名(3d93063f 起 admin 被幂等解绑 superadmin
40
40
  // 角色),写 market 安全设置要求 actor 持 superadmin 角色——用 admin 会 403(2026-10-23 演练实踩)。
41
41
  const SEED_ADMIN_USER = "superadmin";
42
- const SEED_ADMIN_PASS = "123456";
42
+ const SEED_ADMIN_PASS = "aA123456";
43
43
 
44
44
  /** Ed25519 PKCS#8 DER 前缀(RFC 8410 固定头;与 gen-signed-fixtures.mjs 同一手法) */
45
45
  const ED25519_PKCS8_PREFIX = "302e020100300506032b657004220420";
@@ -11,7 +11,7 @@ pnpm build # 构建:oj build + 前端全站合并到 dist/web
11
11
  pnpm preview # 预览:oj migrate + server(release 产物)
12
12
  ```
13
13
 
14
- 登录账号:`admin` / `123456`(见 `api/src/_platform/seed.sql`)。
14
+ 登录账号:`admin` / `aA123456`(见 `api/src/_platform/seed.sql`)。
15
15
 
16
16
  ## 系统管理模块
17
17
 
@@ -59,6 +59,8 @@ include:
59
59
  - tests/auth-throttle.spec.ts
60
60
  - tests/guard.spec.ts
61
61
  - tests/l1-builder.test.ts
62
+ - tests/org-departments.spec.ts
63
+ - tests/org-read.spec.ts
62
64
  - tests/query-utils.spec.ts
63
65
  - tests/rbac-audit.spec.ts
64
66
  - tests/rbac-contacts.spec.ts
@@ -70,6 +72,16 @@ include:
70
72
  - tests/rbac-tables.spec.ts
71
73
  - tests/rbac-users.spec.ts
72
74
  - tests/seed-role-accounts.spec.ts
75
+ # 企微连接器与组织同步:源码本就分发(src/auth/api),对应回归也必须跟着走,
76
+ # 否则用户工程升级后改配置/换套件时没有任何本地自检手段。
77
+ - tests/wecom-admin.spec.ts
78
+ - tests/wecom-client-timeout.spec.ts
79
+ - tests/wecom-connector.spec.ts
80
+ - tests/wecom-crypt.spec.ts
81
+ - tests/wecom-endpoints.spec.ts
82
+ - tests/wecom-landing.spec.ts
83
+ - tests/wecom-org-sync.spec.ts
84
+ - tests/wecom-sync.spec.ts
73
85
  - tests/lifecycle/atomic-state.spec.ts
74
86
  - tests/lifecycle/deploy-smoke.spec.ts
75
87
  - tests/lifecycle/migrate.spec.ts