@oj-module/cli 0.2.18 → 0.2.23

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 (345) hide show
  1. package/devkit/README.md +4 -4
  2. package/devkit/SKILL.md +41 -37
  3. package/devkit/framework-dev.md +6 -5
  4. package/devkit/manual.md +352 -168
  5. package/devkit/menu-rules.md +3 -3
  6. package/devkit/module-dev-and-cdn-playground.md +31 -22
  7. package/devkit/sql-builder-missing-capabilities-pr.md +11 -6
  8. package/package.json +2 -2
  9. package/shell-dist/assets/runtime.js +59 -34
  10. package/shell-dist/index.html +2 -2
  11. package/shell-dist/versions.json +3 -3
  12. package/src/__tests__/build-backend.test.ts +54 -0
  13. package/src/__tests__/init-packagejson.test.ts +29 -0
  14. package/src/__tests__/layout.test.ts +176 -0
  15. package/src/__tests__/module-list.test.ts +66 -0
  16. package/src/__tests__/oj-caps.test.ts +114 -0
  17. package/src/alias-paths.ts +102 -0
  18. package/src/args.ts +54 -4
  19. package/src/build.ts +41 -9
  20. package/src/builtin.ts +93 -0
  21. package/src/bundle.ts +254 -38
  22. package/src/config.ts +82 -9
  23. package/src/contract/__tests__/market-client.integration.test.ts +14 -14
  24. package/src/contract/check.ts +56 -28
  25. package/src/contract/emit-stub.ts +21 -9
  26. package/src/contract/handler-scan.ts +19 -10
  27. package/src/contract/run.ts +14 -4
  28. package/src/dev.ts +80 -9
  29. package/src/index.ts +27 -7
  30. package/src/info.ts +69 -10
  31. package/src/init.ts +114 -28
  32. package/src/layout.ts +282 -24
  33. package/src/lifecycle/__tests__/args.test.ts +20 -0
  34. package/src/lifecycle/__tests__/builtin.test.ts +97 -0
  35. package/src/lifecycle/__tests__/bundle.test.ts +184 -6
  36. package/src/lifecycle/__tests__/manifest-contract.test.ts +2 -2
  37. package/src/lifecycle/__tests__/new.test.ts +129 -0
  38. package/src/lifecycle/__tests__/smoke.test.ts +2 -1
  39. package/src/manifest-contract.ts +16 -3
  40. package/src/market/__tests__/bootstrap.test.ts +17 -9
  41. package/src/market/bootstrap.ts +30 -17
  42. package/src/market/publish.ts +10 -2
  43. package/src/new.ts +208 -0
  44. package/src/oj-caps.ts +133 -0
  45. package/src/oj.ts +27 -4
  46. package/src/preview-config.ts +1 -1
  47. package/src/preview.ts +2 -1
  48. package/src/site.ts +2 -2
  49. package/src/usage.ts +24 -12
  50. package/src/vendor.ts +5 -1
  51. package/templates/{api/config.yaml → config.yaml} +13 -8
  52. package/templates/global.d.ts +7 -6
  53. package/templates/init.include.yaml +41 -36
  54. package/templates/package.json +3 -1
  55. package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/installer.ts +4 -0
  56. package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/smoke.ts +21 -2
  57. package/templates/{api/src/_platform → src/_platform/api}/fixtures/l1-test-user.sql +4 -5
  58. package/templates/{api/src/_platform → src/_platform/api}/market/api.ts +25 -15
  59. package/templates/src/_platform/api/seed.mysql.sql +16 -0
  60. package/templates/src/_platform/api/seed.pg.sql +16 -0
  61. package/templates/{api/src/_platform → src/_platform/api}/seed.sql +16 -5
  62. package/templates/{api/src/_platform → src/_platform/api}/solutions/api.ts +7 -3
  63. package/templates/{api/src/auth → src/auth/api}/_shared/login-throttle.ts +2 -2
  64. package/templates/{api/src/auth → src/auth/api}/_shared/session.ts +2 -2
  65. package/templates/{api/src/auth → src/auth/api}/api.ts +1 -1
  66. package/templates/{api/src/auth → src/auth/api}/ldap-login/api.ts +1 -1
  67. package/templates/src/auth/api/manifest.yaml +6 -0
  68. package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/InstallDialog.test.tsx +53 -1
  69. package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/marketClient.fake.ts +6 -0
  70. package/templates/{web/src/oj-market → src/oj-market/web}/api/client.ts +5 -0
  71. package/templates/{web/src/oj-market → src/oj-market/web}/api/context.ts +2 -2
  72. package/templates/{web/src/oj-market → src/oj-market/web}/api/defaultClient.ts +7 -1
  73. package/templates/src/oj-market/web/components/InstallDialog.tsx +194 -0
  74. package/templates/{web/src/oj-market → src/oj-market/web}/components/RollbackDialog.tsx +7 -3
  75. package/templates/{web/src/oj-market → src/oj-market/web}/components/UninstallConfirm.tsx +18 -7
  76. package/templates/{web/src/oj-market → src/oj-market/web}/hooks/useMarket.ts +29 -12
  77. package/templates/{web/src/oj-market → src/oj-market/web}/locales/en-US.json +10 -1
  78. package/templates/{web/src/oj-market → src/oj-market/web}/locales/zh-CN.json +10 -1
  79. package/templates/{web/src/oj-market → src/oj-market/web}/types.ts +15 -2
  80. package/templates/{api/src/system → src/system/api}/login-methods/api.ts +2 -2
  81. package/templates/src/system/api/manifest.yaml +6 -0
  82. package/templates/{api/src/system → src/system/api}/oplog/api.ts +4 -4
  83. package/templates/{api/src/system → src/system/api}/permissions/api.ts +3 -3
  84. package/templates/{api/src/system → src/system/api}/roles/api.ts +3 -3
  85. package/templates/{api/src/system → src/system/api}/roles/bindings/api.ts +3 -3
  86. package/templates/{api/src/system → src/system/api}/settings/api.ts +3 -3
  87. package/templates/{api/src/system → src/system/api}/users/api.ts +3 -3
  88. package/templates/{api/src/system → src/system/api}/users/forbidden/api.ts +3 -3
  89. package/templates/{api/src/system → src/system/api}/users/password/api.ts +3 -3
  90. package/templates/{api/src/system → src/system/api}/users/roles/api.ts +3 -3
  91. package/templates/{web/src/system → src/system/web}/locales/en-US.json +1 -1
  92. package/templates/{web/src/system → src/system/web}/locales/zh-CN.json +1 -1
  93. package/templates/src/tsconfig.json +16 -0
  94. package/templates/{api/tests → tests}/auth-ldap.spec.ts +2 -2
  95. package/templates/{api/tests → tests}/auth-session.spec.ts +3 -3
  96. package/templates/{api/tests → tests}/auth-throttle.spec.ts +1 -1
  97. package/templates/tests/fixture.ts +434 -0
  98. package/templates/{api/tests → tests}/guard.spec.ts +1 -1
  99. package/templates/{api/tests → tests}/l1-builder.test.ts +2 -2
  100. package/templates/{api/tests → tests}/lifecycle/atomic-state.spec.ts +3 -3
  101. package/templates/{api/tests → tests}/lifecycle/bootstrap.spec.ts +8 -4
  102. package/templates/{api/tests → tests}/lifecycle/deploy-smoke.spec.ts +31 -8
  103. package/templates/{api/tests → tests}/lifecycle/installer.spec.ts +15 -15
  104. package/templates/{api/tests → tests}/lifecycle/market-api.spec.ts +30 -29
  105. package/templates/{api/tests → tests}/lifecycle/migrate.spec.ts +6 -6
  106. package/templates/{api/tests → tests}/lifecycle/preflight.spec.ts +4 -4
  107. package/templates/{api/tests → tests}/lifecycle/register.spec.ts +1 -1
  108. package/templates/{api/tests → tests}/lifecycle/semver.spec.ts +1 -1
  109. package/templates/{api/tests → tests}/lifecycle/sha384.spec.ts +1 -1
  110. package/templates/{api/tests → tests}/lifecycle/sig-fixtures.spec.ts +1 -1
  111. package/templates/{api/tests → tests}/lifecycle/solutions-api.spec.ts +1 -1
  112. package/templates/{api/tests → tests}/lifecycle/steps-fs.spec.ts +12 -12
  113. package/templates/{api/tests → tests}/lifecycle/text-edit.spec.ts +1 -1
  114. package/templates/{api/tests → tests}/lifecycle/tgz-guard.spec.ts +1 -1
  115. package/templates/{api/tests → tests}/lifecycle/trust.spec.ts +5 -5
  116. package/templates/{api/tests → tests}/lifecycle/uninstall.spec.ts +7 -7
  117. package/templates/{api/tests → tests}/lifecycle/verify-checks.spec.ts +9 -6
  118. package/templates/{api/tests → tests}/lifecycle/verify-report.spec.ts +7 -5
  119. package/templates/{api/tests → tests}/query-utils.spec.ts +1 -1
  120. package/templates/{api/tests → tests}/rbac-audit.spec.ts +1 -1
  121. package/templates/{api/tests → tests}/rbac-contacts.spec.ts +2 -2
  122. package/templates/{api/tests → tests}/rbac-guard.spec.ts +1 -1
  123. package/templates/{api/tests → tests}/rbac-roles.spec.ts +2 -2
  124. package/templates/{api/tests → tests}/rbac-seed.spec.ts +13 -11
  125. package/templates/{api/tests → tests}/rbac-settings.spec.ts +2 -2
  126. package/templates/{api/tests → tests}/rbac-solution-perms.spec.ts +1 -1
  127. package/templates/{api/tests → tests}/rbac-users.spec.ts +3 -3
  128. package/templates/tests/seed-role-accounts.spec.ts +87 -0
  129. package/templates/tsconfig.json +5 -1
  130. package/templates/tsconfig.paths.json +19 -0
  131. package/templates/types/oj-modules.d.ts +17 -0
  132. package/templates/vitest.config.ts +22 -0
  133. package/templates/web.config.ts +23 -13
  134. package/vendor/host-versions.json +3 -3
  135. package/templates/api/src/_platform/seed.mysql.sql +0 -8
  136. package/templates/api/src/_platform/seed.pg.sql +0 -8
  137. package/templates/api/src/auth/manifest.yaml +0 -5
  138. package/templates/api/src/system/manifest.yaml +0 -5
  139. package/templates/api/tests/fixture.ts +0 -58
  140. package/templates/api/tsconfig.json +0 -8
  141. package/templates/api/vitest.config.ts +0 -12
  142. package/templates/logs/task-events.jsonl +0 -0
  143. package/templates/web/src/oj-market/components/InstallDialog.tsx +0 -112
  144. /package/templates/{api/.ojm-api-exempt.json → .ojm-api-exempt.json} +0 -0
  145. /package/templates/{api/seed.mysql.sql → seed.mysql.sql} +0 -0
  146. /package/templates/{api/seed.pg.sql → seed.pg.sql} +0 -0
  147. /package/templates/{api/src/_platform → src/_platform/api}/README.md +0 -0
  148. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/atomic.ts +0 -0
  149. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/history.ts +0 -0
  150. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/lock.ts +0 -0
  151. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/semver.ts +0 -0
  152. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/sha384.ts +0 -0
  153. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/state.ts +0 -0
  154. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/deploy-web.ts +0 -0
  155. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/download.ts +0 -0
  156. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/extract.ts +0 -0
  157. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/migrate.ts +0 -0
  158. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/preflight.ts +0 -0
  159. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/register.ts +0 -0
  160. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/reload.ts +0 -0
  161. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/verify.ts +0 -0
  162. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/tasks.ts +0 -0
  163. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/text-edit.ts +0 -0
  164. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/tgz-guard.ts +0 -0
  165. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/trust.ts +0 -0
  166. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/types.ts +0 -0
  167. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/uninstall.ts +0 -0
  168. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/verify-checks.ts +0 -0
  169. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/verify-report.ts +0 -0
  170. /package/templates/{api/src/_platform → src/_platform/api}/_shared/respond.ts +0 -0
  171. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/contacts.ts +0 -0
  172. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/roles.ts +0 -0
  173. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/settings.ts +0 -0
  174. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/solution-perms.ts +0 -0
  175. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/users.ts +0 -0
  176. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/access.ts +0 -0
  177. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/audit.ts +0 -0
  178. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/guard.ts +0 -0
  179. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/oplog.ts +0 -0
  180. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/query.ts +0 -0
  181. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/rate.ts +0 -0
  182. /package/templates/{api/src/_platform → src/_platform/api}/_shared/site-facade.ts +0 -0
  183. /package/templates/{api/src/_platform → src/_platform/api}/contacts/api.ts +0 -0
  184. /package/templates/{api/src/_platform → src/_platform/api}/contacts/detail/api.ts +0 -0
  185. /package/templates/{api/src/_platform → src/_platform/api}/manifest.yaml +0 -0
  186. /package/templates/{api/src/_platform → src/_platform/api}/market/bootstrap.ts +0 -0
  187. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.mysql.sql +0 -0
  188. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.pg.sql +0 -0
  189. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.sql +0 -0
  190. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0002__add_users_avatar_base64.mysql.sql +0 -0
  191. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0002__add_users_avatar_base64.sql +0 -0
  192. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0003__users_source_display_name.mysql.sql +0 -0
  193. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0003__users_source_display_name.sql +0 -0
  194. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.mysql.sql +0 -0
  195. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.pg.sql +0 -0
  196. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.sql +0 -0
  197. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0005__users_must_change.mysql.sql +0 -0
  198. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0005__users_must_change.sql +0 -0
  199. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0006__users_is_forbidden.mysql.sql +0 -0
  200. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0006__users_is_forbidden.sql +0 -0
  201. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0007__users_email.sql +0 -0
  202. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.mysql.sql +0 -0
  203. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.pg.sql +0 -0
  204. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.sql +0 -0
  205. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.mysql.sql +0 -0
  206. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.pg.sql +0 -0
  207. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.sql +0 -0
  208. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.mysql.sql +0 -0
  209. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.pg.sql +0 -0
  210. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.sql +0 -0
  211. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0011__sys_setting_group_label.mysql.sql +0 -0
  212. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0011__sys_setting_group_label.sql +0 -0
  213. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.mysql.sql +0 -0
  214. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.pg.sql +0 -0
  215. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.sql +0 -0
  216. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0013__users_profile.sql +0 -0
  217. /package/templates/{api/src/_platform → src/_platform/api}/schema.yaml +0 -0
  218. /package/templates/{web/src/_platform → src/_platform/web}/__client/api.schemas.ts +0 -0
  219. /package/templates/{web/src/_platform → src/_platform/web}/__client/api.ts +0 -0
  220. /package/templates/{web/src/about → src/about/web}/entry.ts +0 -0
  221. /package/templates/{web/src/about → src/about/web}/locales/en-US.json +0 -0
  222. /package/templates/{web/src/about → src/about/web}/locales/zh-CN.json +0 -0
  223. /package/templates/{web/src/about → src/about/web}/pages/constants.ts +0 -0
  224. /package/templates/{web/src/about → src/about/web}/pages/index.tsx +0 -0
  225. /package/templates/{web/src/access → src/access/web}/entry.ts +0 -0
  226. /package/templates/{web/src/access → src/access/web}/locales/en-US.json +0 -0
  227. /package/templates/{web/src/access → src/access/web}/locales/zh-CN.json +0 -0
  228. /package/templates/{web/src/access → src/access/web}/pages/access-mode/index.tsx +0 -0
  229. /package/templates/{web/src/access → src/access/web}/pages/admin-visible/index.tsx +0 -0
  230. /package/templates/{web/src/access → src/access/web}/pages/button-control/index.tsx +0 -0
  231. /package/templates/{web/src/access → src/access/web}/pages/common-visible/index.tsx +0 -0
  232. /package/templates/{web/src/access → src/access/web}/pages/page-control/index.tsx +0 -0
  233. /package/templates/{api/src/auth → src/auth/api}/_shared/ldap-login.ts +0 -0
  234. /package/templates/{api/src/auth → src/auth/api}/_shared/ldap.ts +0 -0
  235. /package/templates/{web/src/auth → src/auth/web}/__client/api.schemas.ts +0 -0
  236. /package/templates/{web/src/auth → src/auth/web}/__client/api.ts +0 -0
  237. /package/templates/{api/src/demo → src/demo/api}/manifest.yaml +0 -0
  238. /package/templates/{api/src/demo → src/demo/api}/migrations/0001__create_todos.sql +0 -0
  239. /package/templates/{api/src/demo → src/demo/api}/schema.yaml +0 -0
  240. /package/templates/{api/src/demo → src/demo/api}/seed.sql +0 -0
  241. /package/templates/{api/src/demo → src/demo/api}/todos/api.ts +0 -0
  242. /package/templates/{web/src/demo → src/demo/web}/__client/api.schemas.ts +0 -0
  243. /package/templates/{web/src/demo → src/demo/web}/__client/api.ts +0 -0
  244. /package/templates/{web/src/demo → src/demo/web}/entry.ts +0 -0
  245. /package/templates/{web/src/demo → src/demo/web}/locales/en-US.json +0 -0
  246. /package/templates/{web/src/demo → src/demo/web}/locales/zh-CN.json +0 -0
  247. /package/templates/{web/src/demo → src/demo/web}/pages/index.tsx +0 -0
  248. /package/templates/{web/src/exception → src/exception/web}/entry.ts +0 -0
  249. /package/templates/{web/src/exception → src/exception/web}/locales/en-US.json +0 -0
  250. /package/templates/{web/src/exception → src/exception/web}/locales/zh-CN.json +0 -0
  251. /package/templates/{web/src/exception → src/exception/web}/pages/403/index.tsx +0 -0
  252. /package/templates/{web/src/exception → src/exception/web}/pages/404/index.tsx +0 -0
  253. /package/templates/{web/src/exception → src/exception/web}/pages/500/index.tsx +0 -0
  254. /package/templates/{web/src/exception → src/exception/web}/pages/unknown-component/index.tsx +0 -0
  255. /package/templates/{api/src/home → src/home/api}/line/api.ts +0 -0
  256. /package/templates/{api/src/home → src/home/api}/manifest.yaml +0 -0
  257. /package/templates/{api/src/home → src/home/api}/migrations/0001__create_home_tables.sql +0 -0
  258. /package/templates/{api/src/home → src/home/api}/pie/api.ts +0 -0
  259. /package/templates/{api/src/home → src/home/api}/schema.yaml +0 -0
  260. /package/templates/{api/src/home → src/home/api}/seed.sql +0 -0
  261. /package/templates/{web/src/home → src/home/web}/__client/api.schemas.ts +0 -0
  262. /package/templates/{web/src/home → src/home/web}/__client/api.ts +0 -0
  263. /package/templates/{web/src/home → src/home/web}/entry.ts +0 -0
  264. /package/templates/{web/src/home → src/home/web}/locales/en-US.json +0 -0
  265. /package/templates/{web/src/home → src/home/web}/locales/zh-CN.json +0 -0
  266. /package/templates/{web/src/home → src/home/web}/pages/components/bar-chart.tsx +0 -0
  267. /package/templates/{web/src/home → src/home/web}/pages/components/card-list.tsx +0 -0
  268. /package/templates/{web/src/home → src/home/web}/pages/components/line-chart.tsx +0 -0
  269. /package/templates/{web/src/home → src/home/web}/pages/components/pie-chart.tsx +0 -0
  270. /package/templates/{web/src/home → src/home/web}/pages/index.tsx +0 -0
  271. /package/templates/{web/src/login → src/login/web}/entry.ts +0 -0
  272. /package/templates/{web/src/login → src/login/web}/locales/en-US.json +0 -0
  273. /package/templates/{web/src/login → src/login/web}/locales/zh-CN.json +0 -0
  274. /package/templates/{web/src/login → src/login/web}/pages/change-password.tsx +0 -0
  275. /package/templates/{web/src/login → src/login/web}/pages/login.tsx +0 -0
  276. /package/templates/{api/src/notification → src/notification/api}/_shared/notify.ts +0 -0
  277. /package/templates/{api/src/notification → src/notification/api}/api.ts +0 -0
  278. /package/templates/{api/src/notification → src/notification/api}/del/api.ts +0 -0
  279. /package/templates/{api/src/notification → src/notification/api}/manifest.yaml +0 -0
  280. /package/templates/{api/src/notification → src/notification/api}/migrations/0001__create_notifications.sql +0 -0
  281. /package/templates/{api/src/notification → src/notification/api}/migrations/0002__notifications_user.sql +0 -0
  282. /package/templates/{api/src/notification → src/notification/api}/migrations/0003__notifications_broadcast.sql +0 -0
  283. /package/templates/{api/src/notification → src/notification/api}/migrations/0004__notifications_broadcast_hidden.sql +0 -0
  284. /package/templates/{api/src/notification → src/notification/api}/schema.yaml +0 -0
  285. /package/templates/{api/src/notification → src/notification/api}/seed.sql +0 -0
  286. /package/templates/{web/src/notification → src/notification/web}/__client/api.schemas.ts +0 -0
  287. /package/templates/{web/src/notification → src/notification/web}/__client/api.ts +0 -0
  288. /package/templates/{web/src/notification → src/notification/web}/entry.ts +0 -0
  289. /package/templates/{web/src/notification → src/notification/web}/locales/en-US.json +0 -0
  290. /package/templates/{web/src/notification → src/notification/web}/locales/zh-CN.json +0 -0
  291. /package/templates/{web/src/notification → src/notification/web}/pages/center/index.tsx +0 -0
  292. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/CardGrid.test.tsx +0 -0
  293. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/HistoryDrawer.test.tsx +0 -0
  294. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/RollbackDialog.test.tsx +0 -0
  295. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/UninstallConfirm.test.tsx +0 -0
  296. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/poll.test.ts +0 -0
  297. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/render.tsx +0 -0
  298. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/runtime-stub.ts +0 -0
  299. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/semver.test.ts +0 -0
  300. /package/templates/{web/src/oj-market → src/oj-market/web}/api/MarketClientProvider.tsx +0 -0
  301. /package/templates/{web/src/oj-market → src/oj-market/web}/components/CardGrid.tsx +0 -0
  302. /package/templates/{web/src/oj-market → src/oj-market/web}/components/CardItem.tsx +0 -0
  303. /package/templates/{web/src/oj-market → src/oj-market/web}/components/DetailDrawer.tsx +0 -0
  304. /package/templates/{web/src/oj-market → src/oj-market/web}/components/HistoryDrawer.tsx +0 -0
  305. /package/templates/{web/src/oj-market → src/oj-market/web}/entry.ts +0 -0
  306. /package/templates/{web/src/oj-market → src/oj-market/web}/pages/MarketApp.tsx +0 -0
  307. /package/templates/{web/src/oj-market → src/oj-market/web}/utils/poll.ts +0 -0
  308. /package/templates/{web/src/oj-market → src/oj-market/web}/utils/semver.ts +0 -0
  309. /package/templates/{web/src/outside → src/outside/web}/entry.ts +0 -0
  310. /package/templates/{web/src/outside → src/outside/web}/locales/en-US.json +0 -0
  311. /package/templates/{web/src/outside → src/outside/web}/locales/zh-CN.json +0 -0
  312. /package/templates/{api/src/personal-center → src/personal-center/api}/manifest.yaml +0 -0
  313. /package/templates/{api/src/personal-center → src/personal-center/api}/profile/api.ts +0 -0
  314. /package/templates/{api/src/personal-center → src/personal-center/api}/upload/api.ts +0 -0
  315. /package/templates/{web/src/personal-center → src/personal-center/web}/__client/api.schemas.ts +0 -0
  316. /package/templates/{web/src/personal-center → src/personal-center/web}/__client/api.ts +0 -0
  317. /package/templates/{web/src/personal-center → src/personal-center/web}/entry.ts +0 -0
  318. /package/templates/{web/src/personal-center → src/personal-center/web}/locales/en-US.json +0 -0
  319. /package/templates/{web/src/personal-center → src/personal-center/web}/locales/zh-CN.json +0 -0
  320. /package/templates/{web/src/personal-center → src/personal-center/web}/pages/my-profile/index.tsx +0 -0
  321. /package/templates/{web/src/route-nest → src/route-nest/web}/entry.ts +0 -0
  322. /package/templates/{web/src/route-nest → src/route-nest/web}/locales/en-US.json +0 -0
  323. /package/templates/{web/src/route-nest → src/route-nest/web}/locales/zh-CN.json +0 -0
  324. /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu1/menu1-1/index.tsx +0 -0
  325. /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu1/menu1-2/index.tsx +0 -0
  326. /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu2/index.tsx +0 -0
  327. /package/templates/{web/src → src}/styles.css +0 -0
  328. /package/templates/{web/src/system → src/system/web}/__client/api.schemas.ts +0 -0
  329. /package/templates/{web/src/system → src/system/web}/__client/api.ts +0 -0
  330. /package/templates/{web/src/system → src/system/web}/entry.ts +0 -0
  331. /package/templates/{web/src/system → src/system/web}/pages/errors.ts +0 -0
  332. /package/templates/{web/src/system → src/system/web}/pages/forbidden.tsx +0 -0
  333. /package/templates/{web/src/system → src/system/web}/pages/login-methods/index.tsx +0 -0
  334. /package/templates/{web/src/system → src/system/web}/pages/oplog/index.tsx +0 -0
  335. /package/templates/{web/src/system → src/system/web}/pages/roles/index.tsx +0 -0
  336. /package/templates/{web/src/system → src/system/web}/pages/settings/index.tsx +0 -0
  337. /package/templates/{web/src/system → src/system/web}/pages/users/index.tsx +0 -0
  338. /package/templates/{web/src/system → src/system/web}/pages/users/roles.tsx +0 -0
  339. /package/templates/{api/src/web → src/web/api}/get-async-routes/api.ts +0 -0
  340. /package/templates/{api/src/web → src/web/api}/hello/api.ts +0 -0
  341. /package/templates/{api/src/web → src/web/api}/manifest.yaml +0 -0
  342. /package/templates/{api/src/web → src/web/api}/user-info/api.ts +0 -0
  343. /package/templates/{web/src → src/web}/web/__client/api.schemas.ts +0 -0
  344. /package/templates/{web/src → src/web}/web/__client/api.ts +0 -0
  345. /package/templates/{api/tests → tests}/rbac-tables.spec.ts +0 -0
@@ -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/_lifecycle/atomic";
11
- import type { FetchFace } from "../../src/_platform/_lifecycle/steps/download";
12
- import type { ExecFace } from "../../src/_platform/_lifecycle/steps/extract";
13
- import type { ReloadFace } from "../../src/_platform/_lifecycle/steps/reload";
14
- import type { MarketEnv } from "../../src/_platform/market/api";
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";
15
15
  import { createHash } from "node:crypto";
16
16
  import { readFileSync } from "node:fs";
17
17
  import * as fsp from "node:fs/promises";
@@ -20,14 +20,14 @@ import { dirname, join } from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
21
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
22
22
  import { parse } from "yaml";
23
- import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../../src/lifecycle/__tests__/helpers";
24
- import { signIndex } from "../../../../src/publish";
25
- import { readLock, writeLock } from "../../src/_platform/_lifecycle/lock";
26
- import { createStateStore } from "../../src/_platform/_lifecycle/state";
27
- import { getTask, writeTask } from "../../src/_platform/_lifecycle/tasks";
28
- import { createTrustStore } from "../../src/_platform/_lifecycle/trust";
29
- import { invalidateAllUsers } from "../../src/_platform/_shared/service/infra/access";
30
- import { createMarketApi, marketEnv, parseVersionsJson, versionsJsonPathOf } from "../../src/_platform/market/api";
23
+ import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../src/lifecycle/__tests__/helpers";
24
+ import { signIndex } from "../../../src/publish";
25
+ import { readLock, writeLock } from "../../src/_platform/api/_lifecycle/lock";
26
+ import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
27
+ import { getTask, writeTask } from "../../src/_platform/api/_lifecycle/tasks";
28
+ import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
29
+ import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
30
+ import { createMarketApi, marketEnv, parseVersionsJson, versionsJsonPathOf } from "../../src/_platform/api/market/api";
31
31
  import { installDb } from "../fixture";
32
32
 
33
33
  function hexToBytes(hex: string): Uint8Array {
@@ -274,7 +274,7 @@ describe("权限门(R9:市场编排 superadmin 独占,meta 登录即可)
274
274
  it("pair-pin:meta apiVersion === _platform/manifest.yaml version(手工镜像漂移防护,P2-9)", async () => {
275
275
  // API_VERSION(market/api.ts)与 _platform/manifest.yaml version 为手工同步的双真源;
276
276
  // 本测试经 meta 端点间接钉住 API_VERSION,漂移即红(peerPlatform 预检口径失真)。
277
- const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "../../src/_platform/manifest.yaml");
277
+ const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "../../src/_platform/api/manifest.yaml");
278
278
  const manifestVersion = (parse(readFileSync(manifestPath, "utf8")) as { version: string }).version;
279
279
  const api = createMarketApi(makeEnv());
280
280
  g.http = { user: { id: 1 } };
@@ -503,7 +503,7 @@ describe("POST /market/trust {task_id}(P2-3 TOFU 确认:混淆代理防线
503
503
 
504
504
  it("确认成功:任务 needs_trust → 指纹复算一致 → 入信任库 added", async () => {
505
505
  const api = createMarketApi(makeEnv());
506
- const { generateKeyPair } = await import("../../../../src/lifecycle/keygen");
506
+ const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
507
507
  const kp = generateKeyPair();
508
508
  const id = await seedNeedsTrust("stranger.pub", kp.publicKeyHex);
509
509
  g.http = { user: { id: 1 }, body: { task_id: id } };
@@ -539,7 +539,7 @@ describe("POST /market/trust {task_id}(P2-3 TOFU 确认:混淆代理防线
539
539
 
540
540
  it("混淆代理:任务记录指纹与公钥不符 → 409 拒,信任库零变化", async () => {
541
541
  const api = createMarketApi(makeEnv());
542
- const { generateKeyPair } = await import("../../../../src/lifecycle/keygen");
542
+ const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
543
543
  const kp = generateKeyPair();
544
544
  const id = await seedNeedsTrust("stranger.pub", kp.publicKeyHex, "f".repeat(64)); // 指纹造假
545
545
  g.http = { user: { id: 1 }, body: { task_id: id } };
@@ -552,7 +552,7 @@ describe("POST /market/trust {task_id}(P2-3 TOFU 确认:混淆代理防线
552
552
 
553
553
  it("撞绑定:key_id 已绑其他公钥 → 409 trust_bound_mismatch,库内不动", async () => {
554
554
  const api = createMarketApi(makeEnv());
555
- const { generateKeyPair } = await import("../../../../src/lifecycle/keygen");
555
+ const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
556
556
  const kp = generateKeyPair();
557
557
  const id = await seedNeedsTrust("test.publisher", kp.publicKeyHex); // 已播种的 key_id
558
558
  g.http = { user: { id: 1 }, body: { task_id: id } };
@@ -815,10 +815,11 @@ describe("P3-7 索引签名校验(G4 fail-closed:署名相符采用 / 篡改
815
815
  });
816
816
 
817
817
  describe("hostVersions 缺省接线(B-11:C2-09 比对真源 = <dist>/versions.json,ojm 宿主构建产物)", () => {
818
- it("versionsJsonPathOf 布局推导:modules.json 同目录 versions.json(相对/绝对同构)", () => {
819
- expect(versionsJsonPathOf("dist/modules.json")).toBe("dist/versions.json");
820
- expect(versionsJsonPathOf("/site/dist/modules.json")).toBe("/site/dist/versions.json");
821
- expect(versionsJsonPathOf("modules.json")).toBe("versions.json");
818
+ it("versionsJsonPathOf 布局推导:release 根下的 versions.json(相对/绝对/尾斜杠同构)", () => {
819
+ expect(versionsJsonPathOf("api/dist")).toBe("api/dist/versions.json");
820
+ expect(versionsJsonPathOf("/site/api/dist")).toBe("/site/api/dist/versions.json");
821
+ expect(versionsJsonPathOf("api/dist/")).toBe("api/dist/versions.json");
822
+ expect(versionsJsonPathOf("")).toBe("versions.json");
822
823
  });
823
824
 
824
825
  it("parseVersionsJson:{packageName: version} 全字符串表 → 解析;任何违约(非对象/值非字符串/坏 JSON)→ undefined(fail-closed 不猜)", () => {
@@ -829,9 +830,9 @@ describe("hostVersions 缺省接线(B-11:C2-09 比对真源 = <dist>/version
829
830
  }
830
831
  });
831
832
 
832
- it("集成:env 未注入 hostVersions + dist/versions.json 在盘 → install 全链 done(C2-09 比对走缺省真源)", async () => {
833
- await fsp.mkdir(dirname(modulesJsonPath), { recursive: true });
834
- await fsp.writeFile(join(dirname(modulesJsonPath), "versions.json"), JSON.stringify({ "@oj-module/runtime": "0.1.77" }));
833
+ it("集成:env 未注入 hostVersions + <release 根>/versions.json 在盘 → install 全链 done(C2-09 比对走缺省真源)", async () => {
834
+ await fsp.mkdir(sharedRoot, { recursive: true });
835
+ await fsp.writeFile(join(sharedRoot, "versions.json"), JSON.stringify({ "@oj-module/runtime": "0.1.77" }));
835
836
  const env = makeEnv();
836
837
  delete (env as Partial<MarketEnv>).hostVersions;
837
838
  const api = createMarketApi(env);
@@ -857,12 +858,12 @@ describe("hostVersions 缺省接线(B-11:C2-09 比对真源 = <dist>/version
857
858
  });
858
859
 
859
860
  describe("P1-16 接线:marketEnv 生产口径 / exec opts 转发 / operator 通道 / 账本真源 / index 即对账入口", () => {
860
- it("marketEnv() 缺省 = oj serve release 布局:锁与版本目录在 serve 根 dist(B3),versions.json 同根推导(B4);暂存/任务/sidecar 留根外", () => {
861
+ it("marketEnv() 缺省 = 布局 v2 生产口径:版本目录与 versions.json 在 release 根 api/dist,站点 modules 在 web/dist;暂存/任务/sidecar 留 jail 根", () => {
861
862
  const env = marketEnv();
862
- expect(env.sharedRoot).toBe("dist");
863
- expect(env.siteModulesDir).toBe("dist/modules");
864
- expect(env.modulesJsonPath).toBe("dist/modules.json");
865
- expect(versionsJsonPathOf(env.modulesJsonPath)).toBe("dist/versions.json");
863
+ expect(env.sharedRoot).toBe("api/dist");
864
+ expect(env.siteModulesDir).toBe("web/dist/modules");
865
+ expect(env.modulesJsonPath).toBe("web/dist/modules.json");
866
+ expect(versionsJsonPathOf(env.sharedRoot)).toBe("api/dist/versions.json");
866
867
  expect(env.staging).toBe("modules/.staging");
867
868
  expect(env.taskDir).toBe("modules/.install-tasks");
868
869
  expect(env.statePath).toBe("modules/.solutions/state.yaml");
@@ -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/_lifecycle/atomic";
11
- import type { StateStore } from "../../src/_platform/_lifecycle/state";
12
- import type { ExecFace } from "../../src/_platform/_lifecycle/steps/extract";
13
- import type { MigrateContext } from "../../src/_platform/_lifecycle/steps/migrate";
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";
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/_lifecycle/lock";
19
- import { buildMigrateCmd, maxAppliedSeq, migrate, migrateSvcDirOf, parseMigrateOutput, rollbackGuard } from "../../src/_platform/_lifecycle/steps/migrate";
18
+ import { parseLock } from "../../src/_platform/api/_lifecycle/lock";
19
+ import { buildMigrateCmd, maxAppliedSeq, migrate, migrateSvcDirOf, parseMigrateOutput, rollbackGuard } from "../../src/_platform/api/_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/_lifecycle/state";
2
- import type { InstallContext } from "../../src/_platform/_lifecycle/steps/preflight";
1
+ import type { SolutionState, StateStore } from "../../src/_platform/api/_lifecycle/state";
2
+ import type { InstallContext } from "../../src/_platform/api/_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,9 +12,9 @@ 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/_lifecycle/steps/preflight";
15
+ import { preflight } from "../../src/_platform/api/_lifecycle/steps/preflight";
16
16
 
17
- const FIXTURES = join(dirname(fileURLToPath(import.meta.url)), "../../../../src/lifecycle/__tests__/fixtures");
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;
19
19
 
20
20
  /** 宿主 versions.json 假数据(C2-09 真源键:@oj-module/runtime,shell/src/manifest.ts P7.6) */
@@ -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/_lifecycle/steps/register";
11
+ import { checkOccupancy, queryAllRegistered, queryRegistered, registerSolution } from "../../src/_platform/api/_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/_lifecycle/semver";
6
+ import { compareVersions } from "../../src/_platform/api/_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/_lifecycle/sha384";
7
+ import { bytesToBase64, sha384B64, sha384Bytes } from "../../src/_platform/api/_lifecycle/sha384";
8
8
 
9
9
  const hex = (bytes: Uint8Array): string => Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
10
10
 
@@ -10,7 +10,7 @@ import { fileURLToPath } from "node:url";
10
10
  import { describe, expect, it } from "vitest";
11
11
 
12
12
  const HERE = path.dirname(fileURLToPath(import.meta.url));
13
- const SIG_DIR = path.resolve(HERE, "../../../../src/lifecycle/__tests__/fixtures/sig");
13
+ const SIG_DIR = path.resolve(HERE, "../../../src/lifecycle/__tests__/fixtures/sig");
14
14
  const GEN = path.join(SIG_DIR, "gen-signed-fixtures.mjs");
15
15
 
16
16
  const HEX64 = /^[0-9a-f]{64}$/;
@@ -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/solutions/api";
8
+ import api from "../../src/_platform/api/solutions/api";
9
9
  import { installDb } from "../fixture";
10
10
 
11
11
  let dbo: ReturnType<typeof installDb>;
@@ -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/_lifecycle/atomic";
10
- import type { StateStore } from "../../src/_platform/_lifecycle/state";
11
- import type { DownloadContext } from "../../src/_platform/_lifecycle/steps/download";
12
- import type { ExecFace, ExtractContext } from "../../src/_platform/_lifecycle/steps/extract";
13
- import type { VerifyContext } from "../../src/_platform/_lifecycle/steps/verify";
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";
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";
@@ -18,11 +18,11 @@ import { tmpdir } from "node:os";
18
18
  import { join } from "node:path";
19
19
  import { promisify } from "node:util";
20
20
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
21
- import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../../src/lifecycle/__tests__/helpers";
22
- import { archiveFileOf, download } from "../../src/_platform/_lifecycle/steps/download";
23
- import { buildExtractCmd, buildListCmd, checkModuleManifest, extract } from "../../src/_platform/_lifecycle/steps/extract";
24
- import { verify } from "../../src/_platform/_lifecycle/steps/verify";
25
- import { createTrustStore } from "../../src/_platform/_lifecycle/trust";
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";
26
26
 
27
27
  const execFileP = promisify(execFileCb);
28
28
  const g = globalThis as any;
@@ -352,8 +352,8 @@ describe("verify(stage=verifying,C2-29 sha256 fail-closed + P2-3 六码验
352
352
  it("sig_key:已信任 key_id 但包内公钥与库绑定不一致(首次绑定不可改族)", async () => {
353
353
  await seed();
354
354
  // 另一把私钥冒用已信任 key_id(trusted key_id + 异公钥 = 绑定不一致)
355
- const { signedArchiveFor: signFor } = await import("../../../../src/lifecycle/__tests__/helpers");
356
- const { generateKeyPair } = await import("../../../../src/lifecycle/keygen");
355
+ const { signedArchiveFor: signFor } = await import("../../../src/lifecycle/__tests__/helpers");
356
+ const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
357
357
  const impostor = signFor(BYTES, "demo-solution", "0.1.0", { keyPair: generateKeyPair(), keyId: "test.publisher" });
358
358
  const r = await verify(vfCtx({ manifest: manifest({ ...manifest().archive, signature: impostor.sig }) }));
359
359
  expect(r).toMatchObject({ ok: false, code: "sig_key" });
@@ -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/_lifecycle/text-edit";
8
+ import { appendAnonymousPaths, bumpInstallSeq, ensureReloadApi, hasAnchor, insertAnchor } from "../../src/_platform/api/_lifecycle/text-edit";
9
9
 
10
10
  describe("insertAnchor(R18)", () => {
11
11
  it("带注释的 config.yaml 插入后注释/缩进/空行/键序逐字保留", () => {
@@ -4,7 +4,7 @@
4
4
  // 拒绝:绝对路径、任何 `..` 段、l/h 条目、空成员名、反斜杠路径;`./` 前缀相对合法。
5
5
  import { describe, expect, it } from "vitest";
6
6
 
7
- import { validateTarListing } from "../../src/_platform/_lifecycle/tgz-guard";
7
+ import { validateTarListing } from "../../src/_platform/api/_lifecycle/tgz-guard";
8
8
 
9
9
  describe("validateTarListing(R1)", () => {
10
10
  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/_lifecycle/atomic";
6
- import type { MarketEnv } from "../../src/_platform/market/api";
5
+ import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
6
+ import type { MarketEnv } from "../../src/_platform/api/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/_lifecycle/trust";
14
- import { invalidateAllUsers } from "../../src/_platform/_shared/service/infra/access";
15
- import { createMarketApi, marketEnv } from "../../src/_platform/market/api";
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";
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/_lifecycle/atomic";
9
- import type { MarketEnv } from "../../src/_platform/market/api";
8
+ import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
9
+ import type { MarketEnv } from "../../src/_platform/api/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/_lifecycle/lock";
15
- import { createStateStore } from "../../src/_platform/_lifecycle/state";
16
- import { collectRetainedTables, moduleTablePrefix } from "../../src/_platform/_lifecycle/uninstall";
17
- import { invalidateAllUsers } from "../../src/_platform/_shared/service/infra/access";
18
- import { createMarketApi } from "../../src/_platform/market/api";
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";
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/_lifecycle/atomic";
5
- import type { SolutionRouteRow } from "../../src/_platform/_lifecycle/verify-checks";
4
+ import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
5
+ import type { SolutionRouteRow } from "../../src/_platform/api/_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/_lifecycle/verify-checks";
22
- import { siteOrigin } from "../../src/_platform/market/api";
23
- import { createSolutionsApi, solutionsEnv } from "../../src/_platform/solutions/api";
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";
24
24
  import { installDb } from "../fixture";
25
25
 
26
26
  const g = globalThis as any;
@@ -278,7 +278,10 @@ function setHttp(over: Record<string, unknown>) {
278
278
  }
279
279
 
280
280
  function makeEnv() {
281
- return { ...solutionsEnv(), sharedRoot: root, statePath: join(root, "state.yaml") };
281
+ // modulesJsonPath 钉进临时目录(readFile 失败 → 不打 web 项):默认值 `web/dist/modules.json`
282
+ // 是相对 cwd 的,会把模板本机构建产物卷进用例,全绿用例随「模板 build 过没有」摇摆。
283
+ // P4-2 两条 integrity 用例显式覆盖它。
284
+ return { ...solutionsEnv(), sharedRoot: root, statePath: join(root, "state.yaml"), modulesJsonPath: join(root, "modules.json") };
282
285
  }
283
286
 
284
287
  describe("深检端点门(admin 域)", () => {
@@ -1,8 +1,8 @@
1
1
  // BDD:P2-8 深检报告结构 + 留存 N=10 + 可信性项(trust_state)+ i18n 降级项 + 设值不进报告。
2
2
  // 纯模块单测(verify-report.ts)+ 端点编排(persist-on-POST / GET verify/last / 降级项 / secret 不泄漏)。
3
3
  /* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(verify-checks.spec 同约定) */
4
- import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
5
- import type { VerifyReport } from "../../src/_platform/_lifecycle/verify-report";
4
+ import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
5
+ import type { VerifyReport } from "../../src/_platform/api/_lifecycle/verify-report";
6
6
  import * as fsp from "node:fs/promises";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
@@ -12,8 +12,8 @@ import {
12
12
  persistReport,
13
13
  VERIFY_REPORTS_KEEP,
14
14
  verifyReportsDirOf,
15
- } from "../../src/_platform/_lifecycle/verify-report";
16
- import { createSolutionsApi, solutionsEnv } from "../../src/_platform/solutions/api";
15
+ } from "../../src/_platform/api/_lifecycle/verify-report";
16
+ import { createSolutionsApi, solutionsEnv } from "../../src/_platform/api/solutions/api";
17
17
  import { installDb } from "../fixture";
18
18
 
19
19
  const g = globalThis as any;
@@ -127,7 +127,9 @@ function setHttp(over: Record<string, unknown> = {}) {
127
127
  }
128
128
 
129
129
  function makeEnv() {
130
- return { ...solutionsEnv(), sharedRoot: root, statePath: join(root, "state.yaml"), verifyReportsDir: reportsDir };
130
+ // modulesJsonPath 同 verify-checks.spec:钉进临时目录(缺文件 → 跳过 web 项),
131
+ // 不吃模板本机 `web/dist/modules.json`。
132
+ return { ...solutionsEnv(), sharedRoot: root, statePath: join(root, "state.yaml"), modulesJsonPath: join(root, "modules.json"), verifyReportsDir: reportsDir };
131
133
  }
132
134
 
133
135
  async function insertRoute(perm: string | null) {
@@ -3,7 +3,7 @@
3
3
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
4
4
  import { beforeAll, describe, expect, it } from "vitest";
5
5
 
6
- import { likePattern, paged, pagedFactory } from "../src/_platform/_shared/service/infra/query";
6
+ import { likePattern, paged, pagedFactory } from "../src/_platform/api/_shared/service/infra/query";
7
7
  import { installDb } from "./fixture";
8
8
 
9
9
  let dbo: ReturnType<typeof installDb>;
@@ -3,7 +3,7 @@
3
3
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
4
4
  import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
5
5
 
6
- import { auditDeny, auditOp, recordOp, resetDenyAudit } from "../src/_platform/_shared/service/infra/audit";
6
+ import { auditDeny, auditOp, recordOp, resetDenyAudit } from "../src/_platform/api/_shared/service/infra/audit";
7
7
  import { installDb } from "./fixture";
8
8
 
9
9
  let dbo: ReturnType<typeof installDb>;
@@ -4,7 +4,7 @@
4
4
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
5
5
  import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
6
6
 
7
- import { contactDetail, searchContacts } from "../src/_platform/_shared/service/domain/contacts";
7
+ import { contactDetail, searchContacts } from "../src/_platform/api/_shared/service/domain/contacts";
8
8
  import { installDb } from "./fixture";
9
9
 
10
10
  let dbo: ReturnType<typeof installDb>;
@@ -74,7 +74,7 @@ describe("详情与限速", () => {
74
74
  it("接口级限速:同用户突发超限 → 429", async () => {
75
75
  const uid = mkUser("c_rate");
76
76
  g.http = { user: { id: uid } };
77
- const { rateLimit } = await import("../src/_platform/_shared/service/infra/rate");
77
+ const { rateLimit } = await import("../src/_platform/api/_shared/service/infra/rate");
78
78
  // 窗口 60s / 限额 3(测试参数;生产端点各自定额)
79
79
  for (let i = 0; i < 3; i++)
80
80
  await rateLimit(`contacts:${uid}`, 3, 60_000);
@@ -4,7 +4,7 @@
4
4
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
5
5
  import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
6
6
 
7
- import { assertPermission, assertSuperAdmin, assertSystemAdmin, invalidateUser } from "../src/_platform/_shared/service/infra/access";
7
+ import { assertPermission, assertSuperAdmin, assertSystemAdmin, invalidateUser } from "../src/_platform/api/_shared/service/infra/access";
8
8
  import { installDb } from "./fixture";
9
9
 
10
10
  let dbo: ReturnType<typeof installDb>;
@@ -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 { createRole, deleteRole, listPermissions, listRoles, updateBindings } from "../src/_platform/_shared/service/domain/roles";
8
- import { assertPermission } from "../src/_platform/_shared/service/infra/access";
7
+ import { createRole, deleteRole, listPermissions, listRoles, updateBindings } from "../src/_platform/api/_shared/service/domain/roles";
8
+ import { assertPermission } from "../src/_platform/api/_shared/service/infra/access";
9
9
  import { installDb } from "./fixture";
10
10
 
11
11
  let dbo: ReturnType<typeof installDb>;
@@ -1,13 +1,14 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- // BDD:seed 契约——框架内置角色 + seed 超管绑定 + must_change 首登改密(D12/AC1-27)。
4
+ // BDD:seed 契约——框架内置角色 + 内置角色开发账号(账号名=角色名,must_change=0,
5
+ // 2026-10-22 口径,替代原「admin 绑 superadmin + must_change=1」的 D12 旧钉)。
5
6
  // 夹具重放真实 migrations + seed.sql 文件,本 spec 即「seed 与文件不漂移」的钉子。
6
7
  import { beforeAll, describe, expect, it } from "vitest";
7
8
 
8
9
  import { installDb } from "./fixture";
9
10
 
10
- const SEED = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "_platform", "seed.sql");
11
+ const SEED = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "_platform", "api", "seed.sql");
11
12
  let dbo: ReturnType<typeof installDb>;
12
13
 
13
14
  beforeAll(() => {
@@ -38,17 +39,18 @@ describe("框架内置角色(ROLES 常量单一真相,PRD §4.2)", () => {
38
39
  });
39
40
  });
40
41
 
41
- describe("seed 超管(D12)", () => {
42
- // AUTOINCREMENT 不复用 id(sqlite_sequence 语义),统一按 username 动态解析,不钉死 id
43
- const adminId = () => (dbo.prepare("SELECT id FROM users WHERE username = 'admin'").get() as { id: number }).id;
44
-
45
- it("admin 账号绑定 superadmin 角色(sys_user_role 权威源)", () => {
46
- const row = dbo.prepare("SELECT * FROM sys_user_role WHERE user_id = ? AND role_name = 'superadmin'").get(adminId());
42
+ describe("seed 内置角色开发账号(账号名=角色名,2026-10-22 口径)", () => {
43
+ it.each(["superadmin", "admin", "editor", "viewer"])("账号 %s 绑定同名角色且 must_change=0", (name) => {
44
+ const uid = (dbo.prepare("SELECT id FROM users WHERE username = ?").get(name) as { id: number }).id;
45
+ const row = dbo.prepare("SELECT * FROM sys_user_role WHERE user_id = ? AND role_name = ?").get(uid, name);
47
46
  expect(row).toBeDefined();
47
+ const mc = dbo.prepare("SELECT must_change FROM users WHERE id = ?").get(uid) as { must_change: number };
48
+ expect(Number(mc.must_change)).toBe(0);
48
49
  });
49
50
 
50
- it("must_change=1:首登强制改密(AC1-27 前提)", () => {
51
- const row = dbo.prepare("SELECT must_change FROM users WHERE id = ?").get(adminId()) as { must_change: number };
52
- expect(Number(row.must_change)).toBe(1);
51
+ it("admin 不再绑 superadmin(旧 D12 绑定已被幂等 DELETE 收敛)", () => {
52
+ const uid = (dbo.prepare("SELECT id FROM users WHERE username = 'admin'").get() as { id: number }).id;
53
+ const row = dbo.prepare("SELECT * FROM sys_user_role WHERE user_id = ? AND role_name = 'superadmin'").get(uid);
54
+ expect(row).toBeUndefined();
53
55
  });
54
56
  });
@@ -2,8 +2,8 @@
2
2
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
3
3
  import { afterEach, beforeAll, describe, expect, it } from "vitest";
4
4
 
5
- import { listLoginMethods, listSettings, updateSetting } from "../src/_platform/_shared/service/domain/settings";
6
- import { searchOplog } from "../src/_platform/_shared/service/infra/oplog";
5
+ import { listLoginMethods, listSettings, updateSetting } from "../src/_platform/api/_shared/service/domain/settings";
6
+ import { searchOplog } from "../src/_platform/api/_shared/service/infra/oplog";
7
7
  import { installDb } from "./fixture";
8
8
 
9
9
  let dbo: ReturnType<typeof installDb>;
@@ -4,7 +4,7 @@
4
4
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
5
5
  import { afterEach, beforeAll, describe, expect, it } from "vitest";
6
6
 
7
- import { uninstallSolution, upsertSolutionPerms } from "../src/_platform/_shared/service/domain/solution-perms";
7
+ import { uninstallSolution, upsertSolutionPerms } from "../src/_platform/api/_shared/service/domain/solution-perms";
8
8
  import { installDb } from "./fixture";
9
9
 
10
10
  let dbo: ReturnType<typeof installDb>;
@@ -3,11 +3,11 @@
3
3
  // 禁止操作自己(AC1-10 注);roles 写 sys_user_role 唯一权威源 + 写时失效(AC1-7/D10);
4
4
  // 禁用/重置口令级联删 refresh(§3.1 吊销联动)。
5
5
  /* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
6
- import type { SessionDeps } from "../src/auth/_shared/session";
6
+ import type { SessionDeps } from "../src/auth/api/_shared/session";
7
7
 
8
8
  import { afterEach, beforeAll, describe, expect, it } from "vitest";
9
- import { changePasswordByAdmin, createUser, listUsers, setForbidden, updateUserRoles } from "../src/_platform/_shared/service/domain/users";
10
- import { createSession } from "../src/auth/_shared/session";
9
+ import { changePasswordByAdmin, createUser, listUsers, setForbidden, updateUserRoles } from "../src/_platform/api/_shared/service/domain/users";
10
+ import { createSession } from "../src/auth/api/_shared/session";
11
11
  import { installDb } from "./fixture";
12
12
 
13
13
  let dbo: ReturnType<typeof installDb>;