@oj-module/cli 0.2.54 → 0.2.56

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 (289) hide show
  1. package/devkit/SKILL.md +3 -3
  2. package/devkit/manual.md +59 -52
  3. package/package.json +2 -2
  4. package/shell-dist/assets/{index-e_Mp2mb5.js → index-CImwskAz.js} +24 -11
  5. package/shell-dist/assets/runtime.js +2 -2
  6. package/shell-dist/index.html +3 -3
  7. package/shell-dist/versions.json +3 -3
  8. package/src/__tests__/layout.test.ts +30 -1
  9. package/src/__tests__/templates-schema-columns.test.ts +99 -0
  10. package/src/alias-paths.ts +11 -12
  11. package/src/builtin.ts +10 -3
  12. package/src/contract/__tests__/emit-client.test.ts +4 -4
  13. package/src/contract/__tests__/market-client.integration.test.ts +2 -2
  14. package/src/contract/__tests__/run-api.test.ts +2 -2
  15. package/src/contract/check.ts +6 -2
  16. package/src/contract/emit-client.ts +10 -3
  17. package/src/contract/run.ts +10 -2
  18. package/src/init.ts +19 -11
  19. package/src/layout.ts +72 -16
  20. package/src/lifecycle/__tests__/manifest-contract.test.ts +2 -2
  21. package/src/market/__tests__/bootstrap.test.ts +1 -1
  22. package/src/site.ts +1 -1
  23. package/templates/README.md +30 -20
  24. package/templates/init.include.yaml +19 -11
  25. package/templates/openapi.json +95 -86
  26. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/users.ts +27 -0
  27. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/oplog.ts +4 -2
  28. package/templates/src/app/api/_platform/migrations/0017__users_employee_no.mysql.sql +7 -0
  29. package/templates/src/app/api/_platform/migrations/0017__users_employee_no.pg.sql +4 -0
  30. package/templates/src/app/api/_platform/migrations/0017__users_employee_no.sql +8 -0
  31. package/templates/src/{_platform/api → app/api/_platform}/schema.yaml +5 -0
  32. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/replay.ts +9 -3
  33. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/tenant-admin.ts +18 -27
  34. package/templates/src/{system/api → app/api/system}/oplog/api.ts +5 -3
  35. package/templates/src/{_platform/web/__client/api.ts → app/web/_platform/__client/index.ts} +5 -2
  36. package/templates/src/{auth/web/__client/api.ts → app/web/auth/__client/index.ts} +5 -2
  37. package/templates/src/app/web/notification/pages/center/index.tsx +1 -1
  38. package/templates/src/app/web/notification/routes.ts +1 -1
  39. package/templates/src/app/web/personal-center/pages/my-profile/index.tsx +1 -1
  40. package/templates/src/app/web/personal-center/routes.ts +1 -1
  41. package/templates/src/app/web/system/__client/api.schemas.ts +1 -0
  42. package/templates/src/app/web/system/locales/en-US.json +2 -3
  43. package/templates/src/app/web/system/locales/zh-CN.json +2 -3
  44. package/templates/src/app/web/system/pages/departments/index.tsx +2 -2
  45. package/templates/src/app/web/system/pages/login-methods/index.tsx +1 -1
  46. package/templates/src/app/web/system/pages/oplog/index.tsx +44 -19
  47. package/templates/src/app/web/system/pages/roles/index.tsx +5 -3
  48. package/templates/src/app/web/system/pages/roles/visible-roles.ts +14 -0
  49. package/templates/src/app/web/system/pages/settings/index.tsx +2 -2
  50. package/templates/src/app/web/system/pages/users/can-manage.ts +21 -0
  51. package/templates/src/app/web/system/pages/users/index.tsx +25 -17
  52. package/templates/src/app/web/system/pages/users/roles.tsx +1 -1
  53. package/templates/src/app/web/system/routes.ts +1 -1
  54. package/templates/src/{web/web/__client/api.ts → app/web/web/__client/index.ts} +5 -2
  55. package/templates/src/oj-market/web/api/defaultClient.ts +1 -1
  56. package/templates/tests/auth-ldap.spec.ts +2 -2
  57. package/templates/tests/auth-session.spec.ts +3 -3
  58. package/templates/tests/auth-throttle.spec.ts +1 -1
  59. package/templates/tests/fixture.ts +6 -4
  60. package/templates/tests/guard.spec.ts +1 -1
  61. package/templates/tests/lifecycle/atomic-state.spec.ts +3 -3
  62. package/templates/tests/lifecycle/bootstrap.spec.ts +3 -3
  63. package/templates/tests/lifecycle/deploy-smoke.spec.ts +8 -8
  64. package/templates/tests/lifecycle/installer.spec.ts +10 -10
  65. package/templates/tests/lifecycle/market-api.spec.ts +14 -14
  66. package/templates/tests/lifecycle/migrate.spec.ts +6 -6
  67. package/templates/tests/lifecycle/preflight.spec.ts +3 -3
  68. package/templates/tests/lifecycle/register.spec.ts +1 -1
  69. package/templates/tests/lifecycle/semver.spec.ts +1 -1
  70. package/templates/tests/lifecycle/sha384.spec.ts +1 -1
  71. package/templates/tests/lifecycle/solutions-api.spec.ts +1 -1
  72. package/templates/tests/lifecycle/source-seq.spec.ts +1 -1
  73. package/templates/tests/lifecycle/steps-fs.spec.ts +9 -9
  74. package/templates/tests/lifecycle/text-edit.spec.ts +1 -1
  75. package/templates/tests/lifecycle/tgz-guard.spec.ts +2 -2
  76. package/templates/tests/lifecycle/trust.spec.ts +5 -5
  77. package/templates/tests/lifecycle/uninstall.spec.ts +7 -7
  78. package/templates/tests/lifecycle/verify-checks.spec.ts +5 -5
  79. package/templates/tests/lifecycle/verify-report.spec.ts +4 -4
  80. package/templates/tests/org-departments.spec.ts +10 -6
  81. package/templates/tests/org-read.spec.ts +7 -7
  82. package/templates/tests/query-utils.spec.ts +1 -1
  83. package/templates/tests/rbac-audit.spec.ts +1 -1
  84. package/templates/tests/rbac-contacts.spec.ts +2 -2
  85. package/templates/tests/rbac-guard.spec.ts +1 -1
  86. package/templates/tests/rbac-roles.spec.ts +10 -2
  87. package/templates/tests/rbac-seed.spec.ts +1 -1
  88. package/templates/tests/rbac-settings.spec.ts +77 -7
  89. package/templates/tests/rbac-solution-perms.spec.ts +1 -1
  90. package/templates/tests/rbac-tables.spec.ts +29 -0
  91. package/templates/tests/rbac-users.spec.ts +55 -3
  92. package/templates/tests/roles-page.spec.ts +40 -0
  93. package/templates/tests/seed-role-accounts.spec.ts +1 -1
  94. package/templates/tests/tenant-access-cache.spec.ts +1 -1
  95. package/templates/tests/tenant-forgery.spec.ts +5 -5
  96. package/templates/tests/tenant-isolation.spec.ts +5 -4
  97. package/templates/tests/username-namespace.spec.ts +3 -3
  98. package/templates/tests/users-page.spec.ts +39 -0
  99. package/templates/tests/wecom-admin.spec.ts +6 -6
  100. package/templates/tests/wecom-client-timeout.spec.ts +1 -1
  101. package/templates/tests/wecom-connector.spec.ts +9 -9
  102. package/templates/tests/wecom-corp.spec.ts +9 -9
  103. package/templates/tests/wecom-crypt.spec.ts +1 -1
  104. package/templates/tests/wecom-endpoints.spec.ts +2 -2
  105. package/templates/tests/wecom-landing.spec.ts +1 -1
  106. package/templates/tests/wecom-org-sync.spec.ts +7 -7
  107. package/templates/tests/wecom-sync.spec.ts +3 -3
  108. package/templates/tsconfig.paths.json +11 -11
  109. package/templates/vitest.config.ts +2 -2
  110. package/templates/web.config.ts +5 -2
  111. package/vendor/host-versions.json +3 -3
  112. package/templates/src/{_platform/api → app/api/_platform}/README.md +0 -0
  113. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/atomic.ts +0 -0
  114. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/history.ts +0 -0
  115. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/installer.ts +0 -0
  116. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/limits.ts +0 -0
  117. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/lock.ts +0 -0
  118. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/semver.ts +0 -0
  119. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/sha384.ts +0 -0
  120. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/source-seq.ts +0 -0
  121. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/state.ts +0 -0
  122. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/deploy-web.ts +0 -0
  123. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/download.ts +0 -0
  124. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/extract.ts +0 -0
  125. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/migrate.ts +0 -0
  126. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/preflight.ts +0 -0
  127. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/register.ts +0 -0
  128. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/reload.ts +0 -0
  129. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/smoke.ts +0 -0
  130. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/verify.ts +0 -0
  131. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/tasks.ts +0 -0
  132. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/text-edit.ts +0 -0
  133. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/tgz-guard.ts +0 -0
  134. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/trust.ts +0 -0
  135. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/types.ts +0 -0
  136. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/uninstall.ts +0 -0
  137. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/verify-checks.ts +0 -0
  138. package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/verify-report.ts +0 -0
  139. package/templates/src/{_platform/api → app/api/_platform}/_shared/respond.ts +0 -0
  140. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/contacts.ts +0 -0
  141. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/org-read.ts +0 -0
  142. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/org.ts +0 -0
  143. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/roles.ts +0 -0
  144. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/settings.ts +0 -0
  145. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/solution-perms.ts +0 -0
  146. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/access.ts +0 -0
  147. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/audit.ts +0 -0
  148. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/guard.ts +0 -0
  149. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/query.ts +0 -0
  150. package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/rate.ts +0 -0
  151. package/templates/src/{_platform/api → app/api/_platform}/_shared/site-facade.ts +0 -0
  152. package/templates/src/{_platform/api → app/api/_platform}/contacts/api.ts +0 -0
  153. package/templates/src/{_platform/api → app/api/_platform}/contacts/detail/api.ts +0 -0
  154. package/templates/src/{_platform/api → app/api/_platform}/fixtures/l1-test-user.sql +0 -0
  155. package/templates/src/{_platform/api → app/api/_platform}/manifest.yaml +0 -0
  156. package/templates/src/{_platform/api → app/api/_platform}/market/api.ts +0 -0
  157. package/templates/src/{_platform/api → app/api/_platform}/market/bootstrap.ts +0 -0
  158. package/templates/src/{_platform/api → app/api/_platform}/market/index-source.ts +0 -0
  159. package/templates/src/{_platform/api → app/api/_platform}/migrations/0001__create_users.mysql.sql +0 -0
  160. package/templates/src/{_platform/api → app/api/_platform}/migrations/0001__create_users.pg.sql +0 -0
  161. package/templates/src/{_platform/api → app/api/_platform}/migrations/0001__create_users.sql +0 -0
  162. package/templates/src/{_platform/api → app/api/_platform}/migrations/0002__add_users_avatar_base64.mysql.sql +0 -0
  163. package/templates/src/{_platform/api → app/api/_platform}/migrations/0002__add_users_avatar_base64.sql +0 -0
  164. package/templates/src/{_platform/api → app/api/_platform}/migrations/0003__users_source_display_name.mysql.sql +0 -0
  165. package/templates/src/{_platform/api → app/api/_platform}/migrations/0003__users_source_display_name.sql +0 -0
  166. package/templates/src/{_platform/api → app/api/_platform}/migrations/0004__sys_rbac.mysql.sql +0 -0
  167. package/templates/src/{_platform/api → app/api/_platform}/migrations/0004__sys_rbac.pg.sql +0 -0
  168. package/templates/src/{_platform/api → app/api/_platform}/migrations/0004__sys_rbac.sql +0 -0
  169. package/templates/src/{_platform/api → app/api/_platform}/migrations/0005__users_must_change.mysql.sql +0 -0
  170. package/templates/src/{_platform/api → app/api/_platform}/migrations/0005__users_must_change.sql +0 -0
  171. package/templates/src/{_platform/api → app/api/_platform}/migrations/0006__users_is_forbidden.mysql.sql +0 -0
  172. package/templates/src/{_platform/api → app/api/_platform}/migrations/0006__users_is_forbidden.sql +0 -0
  173. package/templates/src/{_platform/api → app/api/_platform}/migrations/0007__users_email.sql +0 -0
  174. package/templates/src/{_platform/api → app/api/_platform}/migrations/0008__sys_refresh_token.mysql.sql +0 -0
  175. package/templates/src/{_platform/api → app/api/_platform}/migrations/0008__sys_refresh_token.pg.sql +0 -0
  176. package/templates/src/{_platform/api → app/api/_platform}/migrations/0008__sys_refresh_token.sql +0 -0
  177. package/templates/src/{_platform/api → app/api/_platform}/migrations/0009__sys_throttle.mysql.sql +0 -0
  178. package/templates/src/{_platform/api → app/api/_platform}/migrations/0009__sys_throttle.pg.sql +0 -0
  179. package/templates/src/{_platform/api → app/api/_platform}/migrations/0009__sys_throttle.sql +0 -0
  180. package/templates/src/{_platform/api → app/api/_platform}/migrations/0010__sys_solution_route.mysql.sql +0 -0
  181. package/templates/src/{_platform/api → app/api/_platform}/migrations/0010__sys_solution_route.pg.sql +0 -0
  182. package/templates/src/{_platform/api → app/api/_platform}/migrations/0010__sys_solution_route.sql +0 -0
  183. package/templates/src/{_platform/api → app/api/_platform}/migrations/0011__sys_setting_group_label.mysql.sql +0 -0
  184. package/templates/src/{_platform/api → app/api/_platform}/migrations/0011__sys_setting_group_label.sql +0 -0
  185. package/templates/src/{_platform/api → app/api/_platform}/migrations/0012__market_history.mysql.sql +0 -0
  186. package/templates/src/{_platform/api → app/api/_platform}/migrations/0012__market_history.pg.sql +0 -0
  187. package/templates/src/{_platform/api → app/api/_platform}/migrations/0012__market_history.sql +0 -0
  188. package/templates/src/{_platform/api → app/api/_platform}/migrations/0013__users_profile.sql +0 -0
  189. package/templates/src/{_platform/api → app/api/_platform}/migrations/0014__reg_source_seq.mysql.sql +0 -0
  190. package/templates/src/{_platform/api → app/api/_platform}/migrations/0014__reg_source_seq.pg.sql +0 -0
  191. package/templates/src/{_platform/api → app/api/_platform}/migrations/0014__reg_source_seq.sql +0 -0
  192. package/templates/src/{_platform/api → app/api/_platform}/migrations/0015__tenant.mysql.sql +0 -0
  193. package/templates/src/{_platform/api → app/api/_platform}/migrations/0015__tenant.pg.sql +0 -0
  194. package/templates/src/{_platform/api → app/api/_platform}/migrations/0015__tenant.sql +0 -0
  195. package/templates/src/{_platform/api → app/api/_platform}/migrations/0016__org.mysql.sql +0 -0
  196. package/templates/src/{_platform/api → app/api/_platform}/migrations/0016__org.pg.sql +0 -0
  197. package/templates/src/{_platform/api → app/api/_platform}/migrations/0016__org.sql +0 -0
  198. package/templates/src/{_platform/api → app/api/_platform}/org/departments/api.ts +0 -0
  199. package/templates/src/{_platform/api → app/api/_platform}/org/is-member/api.ts +0 -0
  200. package/templates/src/{_platform/api → app/api/_platform}/org/members/api.ts +0 -0
  201. package/templates/src/{_platform/api → app/api/_platform}/org/picker/api.ts +0 -0
  202. package/templates/src/{_platform/api → app/api/_platform}/org/resolve/api.ts +0 -0
  203. package/templates/src/{_platform/api → app/api/_platform}/org/tree/api.ts +0 -0
  204. package/templates/src/{_platform/api → app/api/_platform}/org/user/api.ts +0 -0
  205. package/templates/src/{_platform/api → app/api/_platform}/seed.mysql.sql +0 -0
  206. package/templates/src/{_platform/api → app/api/_platform}/seed.pg.sql +0 -0
  207. package/templates/src/{_platform/api → app/api/_platform}/seed.sql +0 -0
  208. package/templates/src/{_platform/api → app/api/_platform}/solutions/api.ts +0 -0
  209. package/templates/src/{auth/api → app/api/auth}/_shared/ldap-login.ts +0 -0
  210. package/templates/src/{auth/api → app/api/auth}/_shared/ldap.ts +0 -0
  211. package/templates/src/{auth/api → app/api/auth}/_shared/login-throttle.ts +0 -0
  212. package/templates/src/{auth/api → app/api/auth}/_shared/session.ts +0 -0
  213. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/admin.ts +1 -1
  214. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/client.ts +0 -0
  215. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/config.ts +0 -0
  216. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/contacts.ts +0 -0
  217. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/crypt.ts +0 -0
  218. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/events.ts +1 -1
  219. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/login.ts +0 -0
  220. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/payload.ts +0 -0
  221. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/store.ts +0 -0
  222. package/templates/src/{auth/api → app/api/auth}/_shared/wecom/sync.ts +0 -0
  223. package/templates/src/{auth/api → app/api/auth}/api.ts +0 -0
  224. package/templates/src/{auth/api → app/api/auth}/ldap-login/api.ts +0 -0
  225. package/templates/src/{auth/api → app/api/auth}/manifest.yaml +0 -0
  226. package/templates/src/{auth/api → app/api/auth}/migrations/0001__wecom.mysql.sql +0 -0
  227. package/templates/src/{auth/api → app/api/auth}/migrations/0001__wecom.pg.sql +0 -0
  228. package/templates/src/{auth/api → app/api/auth}/migrations/0001__wecom.sql +0 -0
  229. package/templates/src/{auth/api → app/api/auth}/migrations/0002__org_sync.mysql.sql +0 -0
  230. package/templates/src/{auth/api → app/api/auth}/migrations/0002__org_sync.pg.sql +0 -0
  231. package/templates/src/{auth/api → app/api/auth}/migrations/0002__org_sync.sql +0 -0
  232. package/templates/src/{auth/api → app/api/auth}/migrations/0003__credential_kind.mysql.sql +0 -0
  233. package/templates/src/{auth/api → app/api/auth}/migrations/0003__credential_kind.pg.sql +0 -0
  234. package/templates/src/{auth/api → app/api/auth}/migrations/0003__credential_kind.sql +0 -0
  235. package/templates/src/{auth/api → app/api/auth}/schema.yaml +0 -0
  236. package/templates/src/{auth/api → app/api/auth}/wecom/admin/api.ts +0 -0
  237. package/templates/src/{auth/api → app/api/auth}/wecom/admin/tenant-admin/api.ts +1 -1
  238. package/templates/src/{auth/api → app/api/auth}/wecom/admin/tenant-admin/password/api.ts +1 -1
  239. /package/templates/src/{auth/api → app/api/auth}/wecom/api.ts +0 -0
  240. /package/templates/src/{auth/api → app/api/auth}/wecom/sync/api.ts +0 -0
  241. /package/templates/src/{home/api → app/api/home}/line/api.ts +0 -0
  242. /package/templates/src/{home/api → app/api/home}/manifest.yaml +0 -0
  243. /package/templates/src/{home/api → app/api/home}/migrations/0001__create_home_tables.sql +0 -0
  244. /package/templates/src/{home/api → app/api/home}/migrations/0002__tenant.mysql.sql +0 -0
  245. /package/templates/src/{home/api → app/api/home}/migrations/0002__tenant.sql +0 -0
  246. /package/templates/src/{home/api → app/api/home}/pie/api.ts +0 -0
  247. /package/templates/src/{home/api → app/api/home}/schema.yaml +0 -0
  248. /package/templates/src/{home/api → app/api/home}/seed.sql +0 -0
  249. /package/templates/src/{notification/api → app/api/notification}/_shared/notify.ts +0 -0
  250. /package/templates/src/{notification/api → app/api/notification}/api.ts +0 -0
  251. /package/templates/src/{notification/api → app/api/notification}/del/api.ts +0 -0
  252. /package/templates/src/{notification/api → app/api/notification}/manifest.yaml +0 -0
  253. /package/templates/src/{notification/api → app/api/notification}/migrations/0001__create_notifications.sql +0 -0
  254. /package/templates/src/{notification/api → app/api/notification}/migrations/0002__notifications_user.sql +0 -0
  255. /package/templates/src/{notification/api → app/api/notification}/migrations/0003__notifications_broadcast.sql +0 -0
  256. /package/templates/src/{notification/api → app/api/notification}/migrations/0004__notifications_broadcast_hidden.sql +0 -0
  257. /package/templates/src/{notification/api → app/api/notification}/migrations/0005__tenant.mysql.sql +0 -0
  258. /package/templates/src/{notification/api → app/api/notification}/migrations/0005__tenant.sql +0 -0
  259. /package/templates/src/{notification/api → app/api/notification}/schema.yaml +0 -0
  260. /package/templates/src/{notification/api → app/api/notification}/seed.sql +0 -0
  261. /package/templates/src/{personal-center/api → app/api/personal-center}/manifest.yaml +0 -0
  262. /package/templates/src/{personal-center/api → app/api/personal-center}/profile/api.ts +0 -0
  263. /package/templates/src/{personal-center/api → app/api/personal-center}/upload/api.ts +0 -0
  264. /package/templates/src/{system/api → app/api/system}/departments/api.ts +0 -0
  265. /package/templates/src/{system/api → app/api/system}/departments/detach/api.ts +0 -0
  266. /package/templates/src/{system/api → app/api/system}/departments/members/api.ts +0 -0
  267. /package/templates/src/{system/api → app/api/system}/departments/move/api.ts +0 -0
  268. /package/templates/src/{system/api → app/api/system}/login-methods/api.ts +0 -0
  269. /package/templates/src/{system/api → app/api/system}/manifest.yaml +0 -0
  270. /package/templates/src/{system/api → app/api/system}/permissions/api.ts +0 -0
  271. /package/templates/src/{system/api → app/api/system}/roles/api.ts +0 -0
  272. /package/templates/src/{system/api → app/api/system}/roles/bindings/api.ts +0 -0
  273. /package/templates/src/{system/api → app/api/system}/settings/api.ts +0 -0
  274. /package/templates/src/{system/api → app/api/system}/users/api.ts +0 -0
  275. /package/templates/src/{system/api → app/api/system}/users/forbidden/api.ts +0 -0
  276. /package/templates/src/{system/api → app/api/system}/users/password/api.ts +0 -0
  277. /package/templates/src/{system/api → app/api/system}/users/profile/api.ts +0 -0
  278. /package/templates/src/{system/api → app/api/system}/users/roles/api.ts +0 -0
  279. /package/templates/src/{web/api → app/api/web}/get-async-routes/api.ts +0 -0
  280. /package/templates/src/{web/api → app/api/web}/hello/api.ts +0 -0
  281. /package/templates/src/{web/api → app/api/web}/manifest.yaml +0 -0
  282. /package/templates/src/{web/api → app/api/web}/user-info/api.ts +0 -0
  283. /package/templates/src/{_platform/web → app/web/_platform}/__client/api.schemas.ts +0 -0
  284. /package/templates/src/{auth/web → app/web/auth}/__client/api.schemas.ts +0 -0
  285. /package/templates/src/app/web/home/__client/{api.ts → index.ts} +0 -0
  286. /package/templates/src/app/web/notification/__client/{api.ts → index.ts} +0 -0
  287. /package/templates/src/app/web/personal-center/__client/{api.ts → index.ts} +0 -0
  288. /package/templates/src/app/web/system/__client/{api.ts → index.ts} +0 -0
  289. /package/templates/src/{web → app/web}/web/__client/api.schemas.ts +0 -0
@@ -1,4 +1,4 @@
1
- import type { SystemUsersGetData } from "../../__client/api";
1
+ import type { SystemUsersGetData } from "../../__client";
2
2
 
3
3
  import { PlusOutlined } from "@ant-design/icons";
4
4
  import { useUserStore } from "@oj-module/runtime";
@@ -9,16 +9,19 @@ import { useTranslation } from "react-i18next";
9
9
 
10
10
  import { useNavigate } from "react-router";
11
11
 
12
- import { systemDepartmentsGet, systemUsersForbiddenPut, systemUsersGet, systemUsersPasswordPut, systemUsersPost } from "../../__client/api";
12
+ import { systemDepartmentsGet, systemUsersForbiddenPut, systemUsersGet, systemUsersPasswordPut, systemUsersPost } from "../../__client";
13
13
  import { buildTreeData, subtreeIds } from "../departments/tree";
14
14
  import { explainError, isForbidden } from "../errors";
15
15
  import { ForbiddenPanel } from "../forbidden";
16
+ import { canManageUser } from "./can-manage";
16
17
 
17
18
  type UserRow = SystemUsersGetData[number];
18
19
 
19
20
  /**
20
21
  * 用户管理(C1):GET /system/users 列表 + 建号 / 禁用切换 / 重置口令。
21
22
  * 本人行禁用一切自操作(后端 assertNotSelf 400 兜底,前端不给会失败的按钮,R3);
23
+ * superadmin 行也禁用一切操作,除非当前登录者是 superadmin(红线:只有 superadmin 能改
24
+ * superadmin——后端 assertCanManageTarget 403 兜底,前端把按钮置灰);
22
25
  * 成员资格入口:superadmin 与 **本租户 admin** 均可见(授予 admin 已下放到租户内,
23
26
  * 但授予 superadmin 仍只许 superadmin——见 domain/users.ts::assertMembershipAllowed)。
24
27
  * 部门列标出主部门,顶部可按部门筛选(含子部门)——筛选在前端做,名单本来就是一页全量。
@@ -117,8 +120,10 @@ export default function UsersPage() {
117
120
  title={t("system:users.forbidden")}
118
121
  description={`${row.username} → ${forbidden ? "false" : "true"}`}
119
122
  onConfirm={() => forbiddenMut.mutate({ uid: row.id, forbidden: !forbidden })}
123
+ // 置灰的 Switch 不会触发 Popconfirm,这里只是把「为什么点不了」挡在确认框之前
124
+ disabled={String(row.id) === me || !canManageUser(myRoles, row.roles)}
120
125
  >
121
- <Switch size="small" checked={forbidden} disabled={String(row.id) === me} />
126
+ <Switch size="small" checked={forbidden} disabled={String(row.id) === me || !canManageUser(myRoles, row.roles)} />
122
127
  </Popconfirm>
123
128
  {row.must_change ? <Tag color="orange">{t("system:users.firstLoginHint")}</Tag> : null}
124
129
  </Space>
@@ -127,20 +132,23 @@ export default function UsersPage() {
127
132
  {
128
133
  title: t("system:users.columns.actions"),
129
134
  key: "actions",
130
- render: (_: unknown, row: UserRow) => (
131
- <Space>
132
- <Button size="small" disabled={String(row.id) === me} onClick={() => setPwdTarget(row)}>
133
- {t("system:users.resetPwd")}
134
- </Button>
135
- {canManageMembership
136
- ? (
137
- <Button size="small" type="link" onClick={() => navigate(`/system/users/${row.id}/roles`)}>
138
- {t("system:users.membership")}
139
- </Button>
140
- )
141
- : null}
142
- </Space>
143
- ),
135
+ render: (_: unknown, row: UserRow) => {
136
+ const manageable = canManageUser(myRoles, row.roles);
137
+ return (
138
+ <Space>
139
+ <Button size="small" disabled={String(row.id) === me || !manageable} onClick={() => setPwdTarget(row)}>
140
+ {t("system:users.resetPwd")}
141
+ </Button>
142
+ {canManageMembership
143
+ ? (
144
+ <Button size="small" type="link" disabled={!manageable} onClick={() => navigate(`/system/users/${row.id}/roles`)}>
145
+ {t("system:users.membership")}
146
+ </Button>
147
+ )
148
+ : null}
149
+ </Space>
150
+ );
151
+ },
144
152
  },
145
153
  ];
146
154
 
@@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next";
6
6
 
7
7
  import { useNavigate, useParams } from "react-router";
8
8
 
9
- import { systemRolesGet, systemUsersGet, systemUsersRolesPut } from "../../__client/api";
9
+ import { systemRolesGet, systemUsersGet, systemUsersRolesPut } from "../../__client";
10
10
  import { explainError, isForbidden } from "../errors";
11
11
  import { ForbiddenPanel } from "../forbidden";
12
12
 
@@ -4,7 +4,7 @@ import { SettingOutlined } from "@ant-design/icons";
4
4
 
5
5
  import { createElement, lazy } from "react";
6
6
 
7
- import { createSystemClient } from "./__client/api";
7
+ import { createSystemClient } from "./__client";
8
8
 
9
9
  const Users = lazy(() => import("./pages/users"));
10
10
  const UserRoles = lazy(() => import("./pages/users/roles"));
@@ -17,6 +17,9 @@ export const API_PREFIX = "/web";
17
17
  /** 认领身份前缀(契约 apiPrefix,字面等于模块目录名):跨模块认领护栏对比基准 */
18
18
  export const MODULE_PREFIX = "/web";
19
19
 
20
+ /** 认领方模块(web.config clientOwners 指定):跨模块认领护栏对比基准 */
21
+ export const MODULE_OWNER = "/app";
22
+
20
23
  /**
21
24
  * 模块 entry 的 onInit 里一行创建(构造即 install):完成 apiPrefix 登记 +
22
25
  * scoped request 绑定,返回绑好前缀的端点函数集合。一模块一 client;
@@ -28,8 +31,8 @@ export function createWebClient(ctx: ModuleContext) {
28
31
  // 单槽、卸载互相耦合;跨模块需求应由本模块创建后经 provider 暴露。
29
32
  // 注意对比基准是 MODULE_PREFIX(目录名)而非 API_PREFIX——D-M8 映射时线上前缀
30
33
  // 属于别的命名空间,认领身份仍按目录名。
31
- if (import.meta.env.DEV && ctx.module.name !== MODULE_PREFIX.slice(1)) {
32
- console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${MODULE_PREFIX.slice(1)}" 模块在自身 onInit 创建,跨模块需求经 provider 暴露。`);
34
+ if (import.meta.env.DEV && ctx.module.name !== MODULE_OWNER.slice(1)) {
35
+ console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${MODULE_OWNER.slice(1)}" 模块在自身 onInit 创建,跨模块需求经 provider 暴露。`);
33
36
  }
34
37
  ctx.register.apiPrefix(API_PREFIX);
35
38
  bindRequest(ctx.utils.request);
@@ -28,7 +28,7 @@ import {
28
28
  platformMarketTrustPost,
29
29
  platformMarketUninstallImpactGet,
30
30
  platformMarketUninstallPost,
31
- } from "../../../_platform/web/__client/api";
31
+ } from "../../../app/web/_platform/__client";
32
32
 
33
33
  // 绑定运行时 request 到生成 client 的模块级单槽(生成 client 是静态单例,必须由某处
34
34
  // bindRequest;此处兜底确保市场子应用无论挂载顺序都能拿到请求实例)。与 _platform 模块
@@ -4,8 +4,8 @@
4
4
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
5
5
  import { afterEach, beforeAll, describe, expect, it } from "vitest";
6
6
 
7
- import { esc, firstAttr } from "../src/auth/api/_shared/ldap";
8
- import { createLdapLogin } from "../src/auth/api/_shared/ldap-login";
7
+ import { esc, firstAttr } from "../src/app/api/auth/_shared/ldap";
8
+ import { createLdapLogin } from "../src/app/api/auth/_shared/ldap-login";
9
9
  import { installDb } from "./fixture";
10
10
 
11
11
  let dbo: ReturnType<typeof installDb>;
@@ -1,11 +1,11 @@
1
1
  // BDD:登录链——B1 登录顺序(D14 统一 401)、B2 首登改密(AC1-27)、B3 refresh 轮换/reuse 检测(AC1-13)、B4 JWT 仅 sub。
2
2
  // deps 全注入(Node 侧 crypto 只读不可 stub,设计 §9.1);fake bcrypt 以 `hashed:<pw>` 为口令哈希约定。
3
3
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
4
- import type { SessionDeps } from "../src/auth/api/_shared/session";
4
+ import type { SessionDeps } from "../src/app/api/auth/_shared/session";
5
5
 
6
6
  import { afterEach, beforeAll, describe, expect, it } from "vitest";
7
- import { assertPermission } from "../src/_platform/api/_shared/service/infra/access";
8
- import { createSession } from "../src/auth/api/_shared/session";
7
+ import { assertPermission } from "../src/app/api/_platform/_shared/service/infra/access";
8
+ import { createSession } from "../src/app/api/auth/_shared/session";
9
9
  import { installDb } from "./fixture";
10
10
 
11
11
  let dbo: ReturnType<typeof installDb>;
@@ -5,7 +5,7 @@
5
5
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
6
6
  import { afterEach, beforeAll, describe, expect, it } from "vitest";
7
7
 
8
- import { loginBlocked, loginFailed, loginSucceeded, resetLoginThrottle } from "../src/_platform/api/_shared/service/infra/rate";
8
+ import { loginBlocked, loginFailed, loginSucceeded, resetLoginThrottle } from "../src/app/api/_platform/_shared/service/infra/rate";
9
9
  import { installDb } from "./fixture";
10
10
 
11
11
  let dbo: ReturnType<typeof installDb>;
@@ -1,6 +1,6 @@
1
1
  // 后端 BDD 夹具:node:sqlite 内存库 + **真实迁移文件**建表,装到 globalThis.db——
2
2
  // 与 oj 运行时注入的全局同名同面,service 代码不改一行即可被测。
3
- // 夹具直接读 src/<模块>/api/migrations/*.sql,与迁移不可能漂移(沿用 oj-wiki 先例)。
3
+ // 夹具直接读 src/app/api/<模块>/migrations/*.sql,与迁移不可能漂移(沿用 oj-wiki 先例)。
4
4
  //
5
5
  // **构造器垫片(db.table / listTables)**:oj 的构造器是二进制内的 Rust 实现,Node 侧无可复用
6
6
  // 模块,故这里按手册契约(oj-api-dev api-manual「查询构造器」)写一层**最小 JS 渲染层**——
@@ -33,6 +33,8 @@ const { join, dirname } = req("node:path");
33
33
  const { fileURLToPath } = req("node:url");
34
34
 
35
35
  const SRC = join(dirname(fileURLToPath(import.meta.url)), "..", "src");
36
+ /** 后端模块根(0.2.55 布局:`src/app/api/<模块>`);迁移按目录发现,不在夹具里抄模块清单。 */
37
+ const API_ROOT = join(SRC, "app", "api");
36
38
 
37
39
  export const ADMIN = 1;
38
40
 
@@ -465,9 +467,9 @@ function listTables(dbo: any, prefix?: string): string[] {
465
467
  /** 建内存库 + 注入全局;返回 DatabaseSync 供用例直插数据/断言。 */
466
468
  export function installDb(): any {
467
469
  const dbo = new DatabaseSync(":memory:");
468
- // 重放 src 下全部模块的迁移(方言专属文件除外)
469
- for (const mod of readdirSync(SRC)) {
470
- const dir = join(SRC, mod, "api", "migrations");
470
+ // 重放 src/app/api 下全部模块的迁移(方言专属文件除外)
471
+ for (const mod of readdirSync(API_ROOT)) {
472
+ const dir = join(API_ROOT, mod, "migrations");
471
473
  if (!existsSync(dir))
472
474
  continue;
473
475
  for (const f of readdirSync(dir).filter((f: string) => f.endsWith(".sql") && !/\.(?:mysql|pg)\.sql$/.test(f)).sort())
@@ -3,7 +3,7 @@
3
3
  // (真实迁移建表 / 运行时全局 db 同面 / 事务往返)——S0 spike 的「一条真实判权 AC + 形态证明」。
4
4
  import { beforeAll, describe, expect, it } from "vitest";
5
5
 
6
- import { decideAccess, moduleOf } from "../src/_platform/api/_shared/service/infra/guard";
6
+ import { decideAccess, moduleOf } from "../src/app/api/_platform/_shared/service/infra/guard";
7
7
  import { ADMIN, installDb } from "./fixture";
8
8
 
9
9
  const as = (roles: string[], bindings: Record<string, string[]> = {}) => ({ roles, bindings });
@@ -4,14 +4,14 @@
4
4
  // 只保证读回自己写出的内容;任何不符格式的字节一律视为损坏 → 空状态,损坏上下文并入
5
5
  // 读结果(corruptNote 出口,禁 console——release isolate console 抛 BadResource,Finding A)。
6
6
  // fs 依赖经 globalThis.fs 注入(平台 isolate 注入 FsApi;测试注入 node:fs/promises 适配)。
7
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
7
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
8
8
  import * as fsp from "node:fs/promises";
9
9
  import { tmpdir } from "node:os";
10
10
  import { join } from "node:path";
11
11
 
12
12
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
13
- import { atomicWriteText } from "../../src/_platform/api/_lifecycle/atomic";
14
- import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
13
+ import { atomicWriteText } from "../../src/app/api/_platform/_lifecycle/atomic";
14
+ import { createStateStore } from "../../src/app/api/_platform/_lifecycle/state";
15
15
 
16
16
  const g = globalThis as any;
17
17
 
@@ -5,14 +5,14 @@
5
5
  // 与 PEM 私钥块实体(header 后跟 ≥100 字符 base64 体;tasks.ts redact 正则与测试假体
6
6
  // 体长 <100 不误伤)双口径扫描。
7
7
  // ③ 集成(market-api.spec):信任库为空 + bootstrapKey 注入 → cdn 安装直达 done 不落 needs_trust。
8
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
8
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
9
9
  import * as fsp from "node:fs/promises";
10
10
  import { tmpdir } from "node:os";
11
11
  import { dirname, join } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
14
- import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
15
- import { BOOTSTRAP_KEY, seedBootstrapKey } from "../../src/_platform/api/market/bootstrap";
14
+ import { createTrustStore } from "../../src/app/api/_platform/_lifecycle/trust";
15
+ import { BOOTSTRAP_KEY, seedBootstrapKey } from "../../src/app/api/_platform/market/bootstrap";
16
16
 
17
17
  const g = globalThis as any;
18
18
 
@@ -8,19 +8,19 @@
8
8
  // 快照逐数组 ⊇ 声明,少 = 注册丢失判失败)collect-all 全败齐报。
9
9
  // entry 浏览器加载不在安装器验(Node import 必假绿——设计 §4.1),注释钉口径。
10
10
  // fetch/sha384/query/reload 面经 ctx 注入 stub(同 steps-fs 范式),fs 为 globalThis.fs 面。
11
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
12
- import type { StateStore } from "../../src/_platform/api/_lifecycle/state";
13
- import type { DeployWebContext, ModuleEntry } from "../../src/_platform/api/_lifecycle/steps/deploy-web";
14
- import type { ReloadContext, ReloadFace, ReloadResult } from "../../src/_platform/api/_lifecycle/steps/reload";
15
- import type { SmokeContext } from "../../src/_platform/api/_lifecycle/steps/smoke";
11
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
12
+ import type { StateStore } from "../../src/app/api/_platform/_lifecycle/state";
13
+ import type { DeployWebContext, ModuleEntry } from "../../src/app/api/_platform/_lifecycle/steps/deploy-web";
14
+ import type { ReloadContext, ReloadFace, ReloadResult } from "../../src/app/api/_platform/_lifecycle/steps/reload";
15
+ import type { SmokeContext } from "../../src/app/api/_platform/_lifecycle/steps/smoke";
16
16
  import { createHash } from "node:crypto";
17
17
  import * as fsp from "node:fs/promises";
18
18
  import { tmpdir } from "node:os";
19
19
  import { join } from "node:path";
20
20
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
21
- import { deployWeb, posixPath, upsertModulesJson } from "../../src/_platform/api/_lifecycle/steps/deploy-web";
22
- import { reloadAndAssert } from "../../src/_platform/api/_lifecycle/steps/reload";
23
- import { probeUrlOf, smoke } from "../../src/_platform/api/_lifecycle/steps/smoke";
21
+ import { deployWeb, posixPath, upsertModulesJson } from "../../src/app/api/_platform/_lifecycle/steps/deploy-web";
22
+ import { reloadAndAssert } from "../../src/app/api/_platform/_lifecycle/steps/reload";
23
+ import { probeUrlOf, smoke } from "../../src/app/api/_platform/_lifecycle/steps/smoke";
24
24
 
25
25
  const g = globalThis as any;
26
26
 
@@ -12,22 +12,22 @@
12
12
  // 过期(30min)可接管。setEnabled 四处同写(D12/AC-P1-6):锁摘除/恢复 + sidecar + route + modules。
13
13
  // 步骤面全 stub 注入(DIP):fetch/exec/tar/reload 不真跑;register/smoke/audit 走真实内存库夹具。
14
14
  /* eslint-disable test/prefer-lowercase-title -- 任务/AC 编号是验收锚点,保留大写(register.spec 同约定) */
15
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
16
- import type { InstallRequest } from "../../src/_platform/api/_lifecycle/installer";
17
- import type { StateStore } from "../../src/_platform/api/_lifecycle/state";
18
- import type { ExecFace } from "../../src/_platform/api/_lifecycle/steps/extract";
15
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
16
+ import type { InstallRequest } from "../../src/app/api/_platform/_lifecycle/installer";
17
+ import type { StateStore } from "../../src/app/api/_platform/_lifecycle/state";
18
+ import type { ExecFace } from "../../src/app/api/_platform/_lifecycle/steps/extract";
19
19
  import { createHash } from "node:crypto";
20
20
  import * as fsp from "node:fs/promises";
21
21
  import { tmpdir } from "node:os";
22
22
  import { join } from "node:path";
23
23
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
24
24
  import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../src/lifecycle/__tests__/helpers";
25
- import { atomicWriteText } from "../../src/_platform/api/_lifecycle/atomic";
26
- import { gcVersions, reconcile, runInstall, setEnabled, STAGES } from "../../src/_platform/api/_lifecycle/installer";
27
- import { acquireTaskLock, commitLockEntry, parseLock, readLock, serializeLock, writeLock } from "../../src/_platform/api/_lifecycle/lock";
28
- import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
29
- import { getTask, readTasks, redact, sweepTimedOut, writeTask } from "../../src/_platform/api/_lifecycle/tasks";
30
- import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
25
+ import { atomicWriteText } from "../../src/app/api/_platform/_lifecycle/atomic";
26
+ import { gcVersions, reconcile, runInstall, setEnabled, STAGES } from "../../src/app/api/_platform/_lifecycle/installer";
27
+ import { acquireTaskLock, commitLockEntry, parseLock, readLock, serializeLock, writeLock } from "../../src/app/api/_platform/_lifecycle/lock";
28
+ import { createStateStore } from "../../src/app/api/_platform/_lifecycle/state";
29
+ import { getTask, readTasks, redact, sweepTimedOut, writeTask } from "../../src/app/api/_platform/_lifecycle/tasks";
30
+ import { createTrustStore } from "../../src/app/api/_platform/_lifecycle/trust";
31
31
  import { installDb } from "../fixture";
32
32
 
33
33
  const g = globalThis as any;
@@ -7,11 +7,11 @@
7
7
  // 简报 `task/:id` 段参数形态在模板 http 面无先例(contacts/detail?id= 同款 query 惯例),备案于任务报告。
8
8
  // 步骤面全 stub 注入(DIP):fetch/exec/reload 不真跑;register/smoke/audit 走真实内存库夹具。
9
9
  /* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(installer.spec 同约定) */
10
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
11
- import type { FetchFace } from "../../src/_platform/api/_lifecycle/steps/download";
12
- import type { ExecFace } from "../../src/_platform/api/_lifecycle/steps/extract";
13
- import type { ReloadFace } from "../../src/_platform/api/_lifecycle/steps/reload";
14
- import type { MarketEnv } from "../../src/_platform/api/market/api";
10
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
11
+ import type { FetchFace } from "../../src/app/api/_platform/_lifecycle/steps/download";
12
+ import type { ExecFace } from "../../src/app/api/_platform/_lifecycle/steps/extract";
13
+ import type { ReloadFace } from "../../src/app/api/_platform/_lifecycle/steps/reload";
14
+ import type { MarketEnv } from "../../src/app/api/_platform/market/api";
15
15
  import { createHash } from "node:crypto";
16
16
  import { readFileSync } from "node:fs";
17
17
  import * as fsp from "node:fs/promises";
@@ -22,14 +22,14 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
22
22
  import { parse } from "yaml";
23
23
  import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../src/lifecycle/__tests__/helpers";
24
24
  import { signIndex } from "../../../src/publish";
25
- import { readLock, writeLock } from "../../src/_platform/api/_lifecycle/lock";
26
- import { compareVersions } from "../../src/_platform/api/_lifecycle/semver";
27
- import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
28
- import { getTask, writeTask } from "../../src/_platform/api/_lifecycle/tasks";
29
- import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
30
- import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
31
- import { createMarketApi, marketEnv, parseVersionsJson, versionsJsonPathOf } from "../../src/_platform/api/market/api";
32
- import { localIndexSource } from "../../src/_platform/api/market/index-source";
25
+ import { readLock, writeLock } from "../../src/app/api/_platform/_lifecycle/lock";
26
+ import { compareVersions } from "../../src/app/api/_platform/_lifecycle/semver";
27
+ import { createStateStore } from "../../src/app/api/_platform/_lifecycle/state";
28
+ import { getTask, writeTask } from "../../src/app/api/_platform/_lifecycle/tasks";
29
+ import { createTrustStore } from "../../src/app/api/_platform/_lifecycle/trust";
30
+ import { invalidateAllUsers } from "../../src/app/api/_platform/_shared/service/infra/access";
31
+ import { createMarketApi, marketEnv, parseVersionsJson, versionsJsonPathOf } from "../../src/app/api/_platform/market/api";
32
+ import { localIndexSource } from "../../src/app/api/_platform/market/index-source";
33
33
  import { installDb } from "../fixture";
34
34
 
35
35
  function hexToBytes(hex: string): Uint8Array {
@@ -305,7 +305,7 @@ describe("权限门(R9:市场编排 superadmin 独占,meta 登录即可)
305
305
  it("pair-pin:meta apiVersion === _platform/manifest.yaml version(手工镜像漂移防护,P2-9)", async () => {
306
306
  // API_VERSION(market/api.ts)与 _platform/manifest.yaml version 为手工同步的双真源;
307
307
  // 本测试经 meta 端点间接钉住 API_VERSION,漂移即红(peerPlatform 预检口径失真)。
308
- const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "../../src/_platform/api/manifest.yaml");
308
+ const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "../../src/app/api/_platform/manifest.yaml");
309
309
  const manifestVersion = (parse(readFileSync(manifestPath, "utf8")) as { version: string }).version;
310
310
  const api = createMarketApi(makeEnv());
311
311
  g.http = { user: { id: 1 } };
@@ -7,16 +7,16 @@
7
7
  // rollbackGuard 纯函数:目标产物 max seq < 账本 head = 降版部署,禁止(OJ-9/M003 同源红线);
8
8
  // seq 为数值非版本号,直接数值比较(semver.ts 不适用)。
9
9
  // exec/fs 面注入 stub(同 steps-fs 范式),不真跑 oj/sqlite。
10
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
11
- import type { StateStore } from "../../src/_platform/api/_lifecycle/state";
12
- import type { ExecFace } from "../../src/_platform/api/_lifecycle/steps/extract";
13
- import type { MigrateContext } from "../../src/_platform/api/_lifecycle/steps/migrate";
10
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
11
+ import type { StateStore } from "../../src/app/api/_platform/_lifecycle/state";
12
+ import type { ExecFace } from "../../src/app/api/_platform/_lifecycle/steps/extract";
13
+ import type { MigrateContext } from "../../src/app/api/_platform/_lifecycle/steps/migrate";
14
14
  import * as fsp from "node:fs/promises";
15
15
  import { tmpdir } from "node:os";
16
16
  import { join } from "node:path";
17
17
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
18
- import { parseLock } from "../../src/_platform/api/_lifecycle/lock";
19
- import { buildMigrateCmd, maxAppliedSeq, migrate, migrateSvcDirOf, parseMigrateOutput, rollbackGuard } from "../../src/_platform/api/_lifecycle/steps/migrate";
18
+ import { parseLock } from "../../src/app/api/_platform/_lifecycle/lock";
19
+ import { buildMigrateCmd, maxAppliedSeq, migrate, migrateSvcDirOf, parseMigrateOutput, rollbackGuard } from "../../src/app/api/_platform/_lifecycle/steps/migrate";
20
20
 
21
21
  const g = globalThis as any;
22
22
  const DB_BYTES = new TextEncoder().encode("sqlite-header-bytes\n");
@@ -1,5 +1,5 @@
1
- import type { SolutionState, StateStore } from "../../src/_platform/api/_lifecycle/state";
2
- import type { InstallContext } from "../../src/_platform/api/_lifecycle/steps/preflight";
1
+ import type { SolutionState, StateStore } from "../../src/app/api/_platform/_lifecycle/state";
2
+ import type { InstallContext } from "../../src/app/api/_platform/_lifecycle/steps/preflight";
3
3
  // BDD:安装预检规则引擎(P1-5,R7/R8/R9/R24,十阶段状态机 stage 1)。
4
4
  // 规则真源:docs/prd/solution/202610171254-lifecycle-manifest-contract.md(C2-01~33 安装列);
5
5
  // 期望真源:packages/cli/src/lifecycle/__tests__/fixtures/(fixture-valid 零违规、fixture-invalid 七码齐报)。
@@ -12,7 +12,7 @@ import { fileURLToPath } from "node:url";
12
12
 
13
13
  import { describe, expect, it } from "vitest";
14
14
  import { parse } from "yaml";
15
- import { preflight } from "../../src/_platform/api/_lifecycle/steps/preflight";
15
+ import { preflight } from "../../src/app/api/_platform/_lifecycle/steps/preflight";
16
16
 
17
17
  const FIXTURES = join(dirname(fileURLToPath(import.meta.url)), "../../../src/lifecycle/__tests__/fixtures");
18
18
  const VALID = parse(readFileSync(join(FIXTURES, "fixture-valid/manifest.yaml"), "utf8")) as any;
@@ -8,7 +8,7 @@
8
8
  /* eslint-disable test/prefer-lowercase-title -- 任务/AC 编号是验收锚点,保留大写(DB/P1-5) */
9
9
  import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
10
10
 
11
- import { checkOccupancy, queryAllRegistered, queryRegistered, registerSolution } from "../../src/_platform/api/_lifecycle/steps/register";
11
+ import { checkOccupancy, queryAllRegistered, queryRegistered, registerSolution } from "../../src/app/api/_platform/_lifecycle/steps/register";
12
12
  import { installDb } from "../fixture";
13
13
 
14
14
  let dbo: ReturnType<typeof installDb>;
@@ -3,7 +3,7 @@
3
3
  // 无 prerelease > 有 prerelease;「1.0」「1.0.0」「1.0.0.0」视为相等(安装器容错口径)。
4
4
  import { describe, expect, it } from "vitest";
5
5
 
6
- import { compareVersions } from "../../src/_platform/api/_lifecycle/semver";
6
+ import { compareVersions } from "../../src/app/api/_platform/_lifecycle/semver";
7
7
 
8
8
  const cases: Array<[a: string, b: string, expected: -1 | 0 | 1]> = [
9
9
  // 主版本数值比较(非字典序)
@@ -4,7 +4,7 @@
4
4
  import { Buffer } from "node:buffer";
5
5
  import { createHash } from "node:crypto";
6
6
  import { describe, expect, it } from "vitest";
7
- import { bytesToBase64, sha384B64, sha384Bytes } from "../../src/_platform/api/_lifecycle/sha384";
7
+ import { bytesToBase64, sha384B64, sha384Bytes } from "../../src/app/api/_platform/_lifecycle/sha384";
8
8
 
9
9
  const hex = (bytes: Uint8Array): string => Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
10
10
 
@@ -5,7 +5,7 @@
5
5
  /* eslint-disable test/prefer-lowercase-title -- 端点路径是验收锚点 */
6
6
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
7
7
 
8
- import api from "../../src/_platform/api/solutions/api";
8
+ import api from "../../src/app/api/_platform/solutions/api";
9
9
  import { installDb } from "../fixture";
10
10
 
11
11
  let dbo: ReturnType<typeof installDb>;
@@ -4,7 +4,7 @@
4
4
  // 四条负向是 G7 的重点:水位写坏 / 表不存在 / 值非法都必须**拒**,不能静默当「第一次见」——
5
5
  // 静默重置等于把「防回放」降级成「每次都当第一次见」,攻击者先破坏状态再回放即可穿透。
6
6
  import { beforeEach, describe, expect, it } from "vitest";
7
- import { guardAndRecordSourceSeq, readSourceSeq, SOURCE_SEQ_TABLE } from "../../src/_platform/api/_lifecycle/source-seq";
7
+ import { guardAndRecordSourceSeq, readSourceSeq, SOURCE_SEQ_TABLE } from "../../src/app/api/_platform/_lifecycle/source-seq";
8
8
  import { installDb } from "../fixture";
9
9
 
10
10
  const SRC = "https://cdn.example.com/solutions";
@@ -6,11 +6,11 @@
6
6
  // 命令构造为纯函数,argv 逐字断言(与平台 exec 白名单逐字对齐,S1-2 基座);
7
7
  // exec/fetch/sha256 面经 ctx 注入 stub,不真跑网络;合法夹具集成用例的 exec stub 落到真实系统 tar
8
8
  // (与生产同路径:isolate 不内嵌解压,exec.run 系统 tar)。
9
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
10
- import type { StateStore } from "../../src/_platform/api/_lifecycle/state";
11
- import type { DownloadContext } from "../../src/_platform/api/_lifecycle/steps/download";
12
- import type { ExecFace, ExtractContext } from "../../src/_platform/api/_lifecycle/steps/extract";
13
- import type { VerifyContext } from "../../src/_platform/api/_lifecycle/steps/verify";
9
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
10
+ import type { StateStore } from "../../src/app/api/_platform/_lifecycle/state";
11
+ import type { DownloadContext } from "../../src/app/api/_platform/_lifecycle/steps/download";
12
+ import type { ExecFace, ExtractContext } from "../../src/app/api/_platform/_lifecycle/steps/extract";
13
+ import type { VerifyContext } from "../../src/app/api/_platform/_lifecycle/steps/verify";
14
14
  import { execFile as execFileCb } from "node:child_process";
15
15
  import { createHash } from "node:crypto";
16
16
  import * as fsp from "node:fs/promises";
@@ -19,10 +19,10 @@ import { join } from "node:path";
19
19
  import { promisify } from "node:util";
20
20
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
21
21
  import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../src/lifecycle/__tests__/helpers";
22
- import { archiveFileOf, download } from "../../src/_platform/api/_lifecycle/steps/download";
23
- import { buildExtractCmd, buildListCmd, checkModuleManifest, extract } from "../../src/_platform/api/_lifecycle/steps/extract";
24
- import { verify } from "../../src/_platform/api/_lifecycle/steps/verify";
25
- import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
22
+ import { archiveFileOf, download } from "../../src/app/api/_platform/_lifecycle/steps/download";
23
+ import { buildExtractCmd, buildListCmd, checkModuleManifest, extract } from "../../src/app/api/_platform/_lifecycle/steps/extract";
24
+ import { verify } from "../../src/app/api/_platform/_lifecycle/steps/verify";
25
+ import { createTrustStore } from "../../src/app/api/_platform/_lifecycle/trust";
26
26
 
27
27
  const execFileP = promisify(execFileCb);
28
28
  const g = globalThis as any;
@@ -5,7 +5,7 @@
5
5
  import * as fsp from "node:fs/promises";
6
6
  import { describe, expect, it } from "vitest";
7
7
 
8
- import { appendAnonymousPaths, bumpInstallSeq, ensureReloadApi, hasAnchor, insertAnchor } from "../../src/_platform/api/_lifecycle/text-edit";
8
+ import { appendAnonymousPaths, bumpInstallSeq, ensureReloadApi, hasAnchor, insertAnchor } from "../../src/app/api/_platform/_lifecycle/text-edit";
9
9
 
10
10
  describe("insertAnchor(R18)", () => {
11
11
  it("带注释的 config.yaml 插入后注释/缩进/空行/键序逐字保留", () => {
@@ -4,8 +4,8 @@
4
4
  // 拒绝:绝对路径、任何 `..` 段、l/h 条目、空成员名、反斜杠路径;`./` 前缀相对合法。
5
5
  import { describe, expect, it } from "vitest";
6
6
 
7
- import { MAX_ENTRIES, MAX_PACKAGE_BYTES, MAX_SINGLE_ENTRY_BYTES, MAX_UNPACKED_BYTES } from "../../src/_platform/api/_lifecycle/limits";
8
- import { accumulateTarVolume, checkTarVolumeLimits, extractTarEntrySize, validateTarListing } from "../../src/_platform/api/_lifecycle/tgz-guard";
7
+ import { MAX_ENTRIES, MAX_PACKAGE_BYTES, MAX_SINGLE_ENTRY_BYTES, MAX_UNPACKED_BYTES } from "../../src/app/api/_platform/_lifecycle/limits";
8
+ import { accumulateTarVolume, checkTarVolumeLimits, extractTarEntrySize, validateTarListing } from "../../src/app/api/_platform/_lifecycle/tgz-guard";
9
9
 
10
10
  describe("validateTarListing(R1)", () => {
11
11
  it("正常成员列表通过", () => {
@@ -2,17 +2,17 @@
2
2
  // store 层:空库/幂等/首次绑定不可改/多 key/吊销/损坏 fail-closed/.bak 回落/并发读不见半截/审计。
3
3
  // 端点层:GET /market/trust、POST /market/trust/key、DELETE /market/trust/key?key_id=(del 动词 + query,system/roles 同款先例)。
4
4
  /* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(market-api.spec 同约定) */
5
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
6
- import type { MarketEnv } from "../../src/_platform/api/market/api";
5
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
6
+ import type { MarketEnv } from "../../src/app/api/_platform/market/api";
7
7
  import { Buffer } from "node:buffer";
8
8
  import { createHash } from "node:crypto";
9
9
  import * as fsp from "node:fs/promises";
10
10
  import { tmpdir } from "node:os";
11
11
  import { join } from "node:path";
12
12
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
13
- import { createTrustStore, isValidKeyId } from "../../src/_platform/api/_lifecycle/trust";
14
- import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
15
- import { createMarketApi, marketEnv } from "../../src/_platform/api/market/api";
13
+ import { createTrustStore, isValidKeyId } from "../../src/app/api/_platform/_lifecycle/trust";
14
+ import { invalidateAllUsers } from "../../src/app/api/_platform/_shared/service/infra/access";
15
+ import { createMarketApi, marketEnv } from "../../src/app/api/_platform/market/api";
16
16
  import { installDb } from "../fixture";
17
17
 
18
18
  const g = globalThis as any;
@@ -5,17 +5,17 @@
5
5
  // 夹具:本仓范式(node:sqlite 真实迁移建表 + 真实 fs 面 g.fs);market_history 表由平台迁移
6
6
  // 0012(IF NOT EXISTS)随 installDb 重放建立,守卫语义(表不存在静默跳过)单列一例。
7
7
  /* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(market-api.spec 同约定) */
8
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
9
- import type { MarketEnv } from "../../src/_platform/api/market/api";
8
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
9
+ import type { MarketEnv } from "../../src/app/api/_platform/market/api";
10
10
  import * as fsp from "node:fs/promises";
11
11
  import { tmpdir } from "node:os";
12
12
  import { dirname, join } from "node:path";
13
13
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
14
- import { readLock, writeLock } from "../../src/_platform/api/_lifecycle/lock";
15
- import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
16
- import { collectRetainedTables, moduleTablePrefix } from "../../src/_platform/api/_lifecycle/uninstall";
17
- import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
18
- import { createMarketApi } from "../../src/_platform/api/market/api";
14
+ import { readLock, writeLock } from "../../src/app/api/_platform/_lifecycle/lock";
15
+ import { createStateStore } from "../../src/app/api/_platform/_lifecycle/state";
16
+ import { collectRetainedTables, moduleTablePrefix } from "../../src/app/api/_platform/_lifecycle/uninstall";
17
+ import { invalidateAllUsers } from "../../src/app/api/_platform/_shared/service/infra/access";
18
+ import { createMarketApi } from "../../src/app/api/_platform/market/api";
19
19
  import { installDb } from "../fixture";
20
20
 
21
21
  const g = globalThis as any;
@@ -1,8 +1,8 @@
1
1
  // BDD:深检后端四项 + 端点(P2-7,C2-42)+ SSRF 三钉。
2
2
  // 纯 diff 函数 / 探针分类 / SSRF 钉(出站拦截 / header 清洗 / 不跟随重定向)+ 端点门(401/403/404)+ 编排。
3
3
  /* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(market-api.spec 同约定) */
4
- import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
5
- import type { SolutionRouteRow } from "../../src/_platform/api/_lifecycle/verify-checks";
4
+ import type { FsFace } from "../../src/app/api/_platform/_lifecycle/atomic";
5
+ import type { SolutionRouteRow } from "../../src/app/api/_platform/_lifecycle/verify-checks";
6
6
  import * as fsp from "node:fs/promises";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
@@ -18,9 +18,9 @@ import {
18
18
  sha384B64,
19
19
 
20
20
  verifyRouteReachability,
21
- } from "../../src/_platform/api/_lifecycle/verify-checks";
22
- import { siteOrigin } from "../../src/_platform/api/market/api";
23
- import { createSolutionsApi, solutionsEnv } from "../../src/_platform/api/solutions/api";
21
+ } from "../../src/app/api/_platform/_lifecycle/verify-checks";
22
+ import { siteOrigin } from "../../src/app/api/_platform/market/api";
23
+ import { createSolutionsApi, solutionsEnv } from "../../src/app/api/_platform/solutions/api";
24
24
  import { installDb } from "../fixture";
25
25
 
26
26
  const g = globalThis as any;