@oj-module/cli 0.2.18 → 0.2.20

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 (331) 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 +259 -161
  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 +2 -2
  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__/layout.test.ts +176 -0
  14. package/src/__tests__/module-list.test.ts +66 -0
  15. package/src/__tests__/oj-caps.test.ts +114 -0
  16. package/src/alias-paths.ts +102 -0
  17. package/src/build.ts +41 -9
  18. package/src/bundle.ts +25 -13
  19. package/src/config.ts +82 -9
  20. package/src/contract/__tests__/market-client.integration.test.ts +2 -2
  21. package/src/contract/check.ts +56 -28
  22. package/src/contract/emit-stub.ts +21 -9
  23. package/src/contract/handler-scan.ts +19 -10
  24. package/src/contract/run.ts +14 -4
  25. package/src/dev.ts +22 -7
  26. package/src/index.ts +1 -1
  27. package/src/info.ts +20 -3
  28. package/src/init.ts +91 -21
  29. package/src/layout.ts +282 -24
  30. package/src/lifecycle/__tests__/bundle.test.ts +16 -1
  31. package/src/lifecycle/__tests__/manifest-contract.test.ts +2 -2
  32. package/src/market/__tests__/bootstrap.test.ts +17 -9
  33. package/src/market/bootstrap.ts +30 -17
  34. package/src/oj-caps.ts +133 -0
  35. package/src/oj.ts +27 -4
  36. package/src/preview-config.ts +1 -1
  37. package/src/preview.ts +2 -1
  38. package/src/site.ts +2 -2
  39. package/src/usage.ts +6 -6
  40. package/src/vendor.ts +5 -1
  41. package/templates/{api/config.yaml → config.yaml} +13 -8
  42. package/templates/global.d.ts +7 -6
  43. package/templates/init.include.yaml +41 -36
  44. package/templates/package.json +1 -1
  45. package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/installer.ts +4 -0
  46. package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/smoke.ts +21 -2
  47. package/templates/{api/src/_platform → src/_platform/api}/market/api.ts +25 -15
  48. package/templates/{api/src/_platform → src/_platform/api}/solutions/api.ts +7 -3
  49. package/templates/{api/src/auth → src/auth/api}/_shared/login-throttle.ts +2 -2
  50. package/templates/{api/src/auth → src/auth/api}/_shared/session.ts +2 -2
  51. package/templates/{api/src/auth → src/auth/api}/api.ts +1 -1
  52. package/templates/{api/src/auth → src/auth/api}/ldap-login/api.ts +1 -1
  53. package/templates/src/auth/api/manifest.yaml +6 -0
  54. package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/InstallDialog.test.tsx +53 -1
  55. package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/marketClient.fake.ts +6 -0
  56. package/templates/{web/src/oj-market → src/oj-market/web}/api/client.ts +5 -0
  57. package/templates/{web/src/oj-market → src/oj-market/web}/api/defaultClient.ts +7 -1
  58. package/templates/{web/src/oj-market → src/oj-market/web}/components/InstallDialog.tsx +80 -5
  59. package/templates/{web/src/oj-market → src/oj-market/web}/hooks/useMarket.ts +6 -1
  60. package/templates/{web/src/oj-market → src/oj-market/web}/locales/en-US.json +10 -1
  61. package/templates/{web/src/oj-market → src/oj-market/web}/locales/zh-CN.json +10 -1
  62. package/templates/{web/src/oj-market → src/oj-market/web}/types.ts +15 -2
  63. package/templates/{api/src/system → src/system/api}/login-methods/api.ts +2 -2
  64. package/templates/src/system/api/manifest.yaml +6 -0
  65. package/templates/{api/src/system → src/system/api}/oplog/api.ts +4 -4
  66. package/templates/{api/src/system → src/system/api}/permissions/api.ts +3 -3
  67. package/templates/{api/src/system → src/system/api}/roles/api.ts +3 -3
  68. package/templates/{api/src/system → src/system/api}/roles/bindings/api.ts +3 -3
  69. package/templates/{api/src/system → src/system/api}/settings/api.ts +3 -3
  70. package/templates/{api/src/system → src/system/api}/users/api.ts +3 -3
  71. package/templates/{api/src/system → src/system/api}/users/forbidden/api.ts +3 -3
  72. package/templates/{api/src/system → src/system/api}/users/password/api.ts +3 -3
  73. package/templates/{api/src/system → src/system/api}/users/roles/api.ts +3 -3
  74. package/templates/src/tsconfig.json +16 -0
  75. package/templates/{api/tests → tests}/auth-ldap.spec.ts +2 -2
  76. package/templates/{api/tests → tests}/auth-session.spec.ts +3 -3
  77. package/templates/{api/tests → tests}/auth-throttle.spec.ts +1 -1
  78. package/templates/tests/fixture.ts +434 -0
  79. package/templates/{api/tests → tests}/guard.spec.ts +1 -1
  80. package/templates/{api/tests → tests}/lifecycle/atomic-state.spec.ts +3 -3
  81. package/templates/{api/tests → tests}/lifecycle/bootstrap.spec.ts +8 -4
  82. package/templates/{api/tests → tests}/lifecycle/deploy-smoke.spec.ts +31 -8
  83. package/templates/{api/tests → tests}/lifecycle/installer.spec.ts +15 -15
  84. package/templates/{api/tests → tests}/lifecycle/market-api.spec.ts +30 -29
  85. package/templates/{api/tests → tests}/lifecycle/migrate.spec.ts +6 -6
  86. package/templates/{api/tests → tests}/lifecycle/preflight.spec.ts +4 -4
  87. package/templates/{api/tests → tests}/lifecycle/register.spec.ts +1 -1
  88. package/templates/{api/tests → tests}/lifecycle/semver.spec.ts +1 -1
  89. package/templates/{api/tests → tests}/lifecycle/sha384.spec.ts +1 -1
  90. package/templates/{api/tests → tests}/lifecycle/sig-fixtures.spec.ts +1 -1
  91. package/templates/{api/tests → tests}/lifecycle/solutions-api.spec.ts +1 -1
  92. package/templates/{api/tests → tests}/lifecycle/steps-fs.spec.ts +12 -12
  93. package/templates/{api/tests → tests}/lifecycle/text-edit.spec.ts +1 -1
  94. package/templates/{api/tests → tests}/lifecycle/tgz-guard.spec.ts +1 -1
  95. package/templates/{api/tests → tests}/lifecycle/trust.spec.ts +5 -5
  96. package/templates/{api/tests → tests}/lifecycle/uninstall.spec.ts +7 -7
  97. package/templates/{api/tests → tests}/lifecycle/verify-checks.spec.ts +9 -6
  98. package/templates/{api/tests → tests}/lifecycle/verify-report.spec.ts +7 -5
  99. package/templates/{api/tests → tests}/query-utils.spec.ts +1 -1
  100. package/templates/{api/tests → tests}/rbac-audit.spec.ts +1 -1
  101. package/templates/{api/tests → tests}/rbac-contacts.spec.ts +2 -2
  102. package/templates/{api/tests → tests}/rbac-guard.spec.ts +1 -1
  103. package/templates/{api/tests → tests}/rbac-roles.spec.ts +2 -2
  104. package/templates/{api/tests → tests}/rbac-seed.spec.ts +1 -1
  105. package/templates/{api/tests → tests}/rbac-settings.spec.ts +2 -2
  106. package/templates/{api/tests → tests}/rbac-solution-perms.spec.ts +1 -1
  107. package/templates/{api/tests → tests}/rbac-users.spec.ts +3 -3
  108. package/templates/tsconfig.json +5 -1
  109. package/templates/tsconfig.paths.json +19 -0
  110. package/templates/types/oj-modules.d.ts +17 -0
  111. package/templates/vitest.config.ts +22 -0
  112. package/templates/web.config.ts +23 -13
  113. package/vendor/host-versions.json +3 -3
  114. package/templates/api/src/auth/manifest.yaml +0 -5
  115. package/templates/api/src/system/manifest.yaml +0 -5
  116. package/templates/api/tests/fixture.ts +0 -58
  117. package/templates/api/tsconfig.json +0 -8
  118. package/templates/api/vitest.config.ts +0 -12
  119. package/templates/logs/task-events.jsonl +0 -0
  120. /package/templates/{api/.ojm-api-exempt.json → .ojm-api-exempt.json} +0 -0
  121. /package/templates/{api/seed.mysql.sql → seed.mysql.sql} +0 -0
  122. /package/templates/{api/seed.pg.sql → seed.pg.sql} +0 -0
  123. /package/templates/{api/src/_platform → src/_platform/api}/README.md +0 -0
  124. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/atomic.ts +0 -0
  125. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/history.ts +0 -0
  126. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/lock.ts +0 -0
  127. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/semver.ts +0 -0
  128. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/sha384.ts +0 -0
  129. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/state.ts +0 -0
  130. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/deploy-web.ts +0 -0
  131. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/download.ts +0 -0
  132. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/extract.ts +0 -0
  133. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/migrate.ts +0 -0
  134. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/preflight.ts +0 -0
  135. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/register.ts +0 -0
  136. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/reload.ts +0 -0
  137. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/verify.ts +0 -0
  138. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/tasks.ts +0 -0
  139. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/text-edit.ts +0 -0
  140. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/tgz-guard.ts +0 -0
  141. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/trust.ts +0 -0
  142. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/types.ts +0 -0
  143. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/uninstall.ts +0 -0
  144. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/verify-checks.ts +0 -0
  145. /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/verify-report.ts +0 -0
  146. /package/templates/{api/src/_platform → src/_platform/api}/_shared/respond.ts +0 -0
  147. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/contacts.ts +0 -0
  148. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/roles.ts +0 -0
  149. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/settings.ts +0 -0
  150. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/solution-perms.ts +0 -0
  151. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/users.ts +0 -0
  152. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/access.ts +0 -0
  153. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/audit.ts +0 -0
  154. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/guard.ts +0 -0
  155. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/oplog.ts +0 -0
  156. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/query.ts +0 -0
  157. /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/rate.ts +0 -0
  158. /package/templates/{api/src/_platform → src/_platform/api}/_shared/site-facade.ts +0 -0
  159. /package/templates/{api/src/_platform → src/_platform/api}/contacts/api.ts +0 -0
  160. /package/templates/{api/src/_platform → src/_platform/api}/contacts/detail/api.ts +0 -0
  161. /package/templates/{api/src/_platform → src/_platform/api}/fixtures/l1-test-user.sql +0 -0
  162. /package/templates/{api/src/_platform → src/_platform/api}/manifest.yaml +0 -0
  163. /package/templates/{api/src/_platform → src/_platform/api}/market/bootstrap.ts +0 -0
  164. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.mysql.sql +0 -0
  165. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.pg.sql +0 -0
  166. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.sql +0 -0
  167. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0002__add_users_avatar_base64.mysql.sql +0 -0
  168. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0002__add_users_avatar_base64.sql +0 -0
  169. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0003__users_source_display_name.mysql.sql +0 -0
  170. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0003__users_source_display_name.sql +0 -0
  171. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.mysql.sql +0 -0
  172. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.pg.sql +0 -0
  173. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.sql +0 -0
  174. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0005__users_must_change.mysql.sql +0 -0
  175. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0005__users_must_change.sql +0 -0
  176. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0006__users_is_forbidden.mysql.sql +0 -0
  177. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0006__users_is_forbidden.sql +0 -0
  178. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0007__users_email.sql +0 -0
  179. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.mysql.sql +0 -0
  180. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.pg.sql +0 -0
  181. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.sql +0 -0
  182. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.mysql.sql +0 -0
  183. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.pg.sql +0 -0
  184. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.sql +0 -0
  185. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.mysql.sql +0 -0
  186. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.pg.sql +0 -0
  187. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.sql +0 -0
  188. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0011__sys_setting_group_label.mysql.sql +0 -0
  189. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0011__sys_setting_group_label.sql +0 -0
  190. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.mysql.sql +0 -0
  191. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.pg.sql +0 -0
  192. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.sql +0 -0
  193. /package/templates/{api/src/_platform → src/_platform/api}/migrations/0013__users_profile.sql +0 -0
  194. /package/templates/{api/src/_platform → src/_platform/api}/schema.yaml +0 -0
  195. /package/templates/{api/src/_platform → src/_platform/api}/seed.mysql.sql +0 -0
  196. /package/templates/{api/src/_platform → src/_platform/api}/seed.pg.sql +0 -0
  197. /package/templates/{api/src/_platform → src/_platform/api}/seed.sql +0 -0
  198. /package/templates/{web/src/_platform → src/_platform/web}/__client/api.schemas.ts +0 -0
  199. /package/templates/{web/src/_platform → src/_platform/web}/__client/api.ts +0 -0
  200. /package/templates/{web/src/about → src/about/web}/entry.ts +0 -0
  201. /package/templates/{web/src/about → src/about/web}/locales/en-US.json +0 -0
  202. /package/templates/{web/src/about → src/about/web}/locales/zh-CN.json +0 -0
  203. /package/templates/{web/src/about → src/about/web}/pages/constants.ts +0 -0
  204. /package/templates/{web/src/about → src/about/web}/pages/index.tsx +0 -0
  205. /package/templates/{web/src/access → src/access/web}/entry.ts +0 -0
  206. /package/templates/{web/src/access → src/access/web}/locales/en-US.json +0 -0
  207. /package/templates/{web/src/access → src/access/web}/locales/zh-CN.json +0 -0
  208. /package/templates/{web/src/access → src/access/web}/pages/access-mode/index.tsx +0 -0
  209. /package/templates/{web/src/access → src/access/web}/pages/admin-visible/index.tsx +0 -0
  210. /package/templates/{web/src/access → src/access/web}/pages/button-control/index.tsx +0 -0
  211. /package/templates/{web/src/access → src/access/web}/pages/common-visible/index.tsx +0 -0
  212. /package/templates/{web/src/access → src/access/web}/pages/page-control/index.tsx +0 -0
  213. /package/templates/{api/src/auth → src/auth/api}/_shared/ldap-login.ts +0 -0
  214. /package/templates/{api/src/auth → src/auth/api}/_shared/ldap.ts +0 -0
  215. /package/templates/{web/src/auth → src/auth/web}/__client/api.schemas.ts +0 -0
  216. /package/templates/{web/src/auth → src/auth/web}/__client/api.ts +0 -0
  217. /package/templates/{api/src/demo → src/demo/api}/manifest.yaml +0 -0
  218. /package/templates/{api/src/demo → src/demo/api}/migrations/0001__create_todos.sql +0 -0
  219. /package/templates/{api/src/demo → src/demo/api}/schema.yaml +0 -0
  220. /package/templates/{api/src/demo → src/demo/api}/seed.sql +0 -0
  221. /package/templates/{api/src/demo → src/demo/api}/todos/api.ts +0 -0
  222. /package/templates/{web/src/demo → src/demo/web}/__client/api.schemas.ts +0 -0
  223. /package/templates/{web/src/demo → src/demo/web}/__client/api.ts +0 -0
  224. /package/templates/{web/src/demo → src/demo/web}/entry.ts +0 -0
  225. /package/templates/{web/src/demo → src/demo/web}/locales/en-US.json +0 -0
  226. /package/templates/{web/src/demo → src/demo/web}/locales/zh-CN.json +0 -0
  227. /package/templates/{web/src/demo → src/demo/web}/pages/index.tsx +0 -0
  228. /package/templates/{web/src/exception → src/exception/web}/entry.ts +0 -0
  229. /package/templates/{web/src/exception → src/exception/web}/locales/en-US.json +0 -0
  230. /package/templates/{web/src/exception → src/exception/web}/locales/zh-CN.json +0 -0
  231. /package/templates/{web/src/exception → src/exception/web}/pages/403/index.tsx +0 -0
  232. /package/templates/{web/src/exception → src/exception/web}/pages/404/index.tsx +0 -0
  233. /package/templates/{web/src/exception → src/exception/web}/pages/500/index.tsx +0 -0
  234. /package/templates/{web/src/exception → src/exception/web}/pages/unknown-component/index.tsx +0 -0
  235. /package/templates/{api/src/home → src/home/api}/line/api.ts +0 -0
  236. /package/templates/{api/src/home → src/home/api}/manifest.yaml +0 -0
  237. /package/templates/{api/src/home → src/home/api}/migrations/0001__create_home_tables.sql +0 -0
  238. /package/templates/{api/src/home → src/home/api}/pie/api.ts +0 -0
  239. /package/templates/{api/src/home → src/home/api}/schema.yaml +0 -0
  240. /package/templates/{api/src/home → src/home/api}/seed.sql +0 -0
  241. /package/templates/{web/src/home → src/home/web}/__client/api.schemas.ts +0 -0
  242. /package/templates/{web/src/home → src/home/web}/__client/api.ts +0 -0
  243. /package/templates/{web/src/home → src/home/web}/entry.ts +0 -0
  244. /package/templates/{web/src/home → src/home/web}/locales/en-US.json +0 -0
  245. /package/templates/{web/src/home → src/home/web}/locales/zh-CN.json +0 -0
  246. /package/templates/{web/src/home → src/home/web}/pages/components/bar-chart.tsx +0 -0
  247. /package/templates/{web/src/home → src/home/web}/pages/components/card-list.tsx +0 -0
  248. /package/templates/{web/src/home → src/home/web}/pages/components/line-chart.tsx +0 -0
  249. /package/templates/{web/src/home → src/home/web}/pages/components/pie-chart.tsx +0 -0
  250. /package/templates/{web/src/home → src/home/web}/pages/index.tsx +0 -0
  251. /package/templates/{web/src/login → src/login/web}/entry.ts +0 -0
  252. /package/templates/{web/src/login → src/login/web}/locales/en-US.json +0 -0
  253. /package/templates/{web/src/login → src/login/web}/locales/zh-CN.json +0 -0
  254. /package/templates/{web/src/login → src/login/web}/pages/change-password.tsx +0 -0
  255. /package/templates/{web/src/login → src/login/web}/pages/login.tsx +0 -0
  256. /package/templates/{api/src/notification → src/notification/api}/_shared/notify.ts +0 -0
  257. /package/templates/{api/src/notification → src/notification/api}/api.ts +0 -0
  258. /package/templates/{api/src/notification → src/notification/api}/del/api.ts +0 -0
  259. /package/templates/{api/src/notification → src/notification/api}/manifest.yaml +0 -0
  260. /package/templates/{api/src/notification → src/notification/api}/migrations/0001__create_notifications.sql +0 -0
  261. /package/templates/{api/src/notification → src/notification/api}/migrations/0002__notifications_user.sql +0 -0
  262. /package/templates/{api/src/notification → src/notification/api}/migrations/0003__notifications_broadcast.sql +0 -0
  263. /package/templates/{api/src/notification → src/notification/api}/migrations/0004__notifications_broadcast_hidden.sql +0 -0
  264. /package/templates/{api/src/notification → src/notification/api}/schema.yaml +0 -0
  265. /package/templates/{api/src/notification → src/notification/api}/seed.sql +0 -0
  266. /package/templates/{web/src/notification → src/notification/web}/__client/api.schemas.ts +0 -0
  267. /package/templates/{web/src/notification → src/notification/web}/__client/api.ts +0 -0
  268. /package/templates/{web/src/notification → src/notification/web}/entry.ts +0 -0
  269. /package/templates/{web/src/notification → src/notification/web}/locales/en-US.json +0 -0
  270. /package/templates/{web/src/notification → src/notification/web}/locales/zh-CN.json +0 -0
  271. /package/templates/{web/src/notification → src/notification/web}/pages/center/index.tsx +0 -0
  272. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/CardGrid.test.tsx +0 -0
  273. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/HistoryDrawer.test.tsx +0 -0
  274. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/RollbackDialog.test.tsx +0 -0
  275. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/UninstallConfirm.test.tsx +0 -0
  276. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/poll.test.ts +0 -0
  277. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/render.tsx +0 -0
  278. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/runtime-stub.ts +0 -0
  279. /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/semver.test.ts +0 -0
  280. /package/templates/{web/src/oj-market → src/oj-market/web}/api/MarketClientProvider.tsx +0 -0
  281. /package/templates/{web/src/oj-market → src/oj-market/web}/api/context.ts +0 -0
  282. /package/templates/{web/src/oj-market → src/oj-market/web}/components/CardGrid.tsx +0 -0
  283. /package/templates/{web/src/oj-market → src/oj-market/web}/components/CardItem.tsx +0 -0
  284. /package/templates/{web/src/oj-market → src/oj-market/web}/components/DetailDrawer.tsx +0 -0
  285. /package/templates/{web/src/oj-market → src/oj-market/web}/components/HistoryDrawer.tsx +0 -0
  286. /package/templates/{web/src/oj-market → src/oj-market/web}/components/RollbackDialog.tsx +0 -0
  287. /package/templates/{web/src/oj-market → src/oj-market/web}/components/UninstallConfirm.tsx +0 -0
  288. /package/templates/{web/src/oj-market → src/oj-market/web}/entry.ts +0 -0
  289. /package/templates/{web/src/oj-market → src/oj-market/web}/pages/MarketApp.tsx +0 -0
  290. /package/templates/{web/src/oj-market → src/oj-market/web}/utils/poll.ts +0 -0
  291. /package/templates/{web/src/oj-market → src/oj-market/web}/utils/semver.ts +0 -0
  292. /package/templates/{web/src/outside → src/outside/web}/entry.ts +0 -0
  293. /package/templates/{web/src/outside → src/outside/web}/locales/en-US.json +0 -0
  294. /package/templates/{web/src/outside → src/outside/web}/locales/zh-CN.json +0 -0
  295. /package/templates/{api/src/personal-center → src/personal-center/api}/manifest.yaml +0 -0
  296. /package/templates/{api/src/personal-center → src/personal-center/api}/profile/api.ts +0 -0
  297. /package/templates/{api/src/personal-center → src/personal-center/api}/upload/api.ts +0 -0
  298. /package/templates/{web/src/personal-center → src/personal-center/web}/__client/api.schemas.ts +0 -0
  299. /package/templates/{web/src/personal-center → src/personal-center/web}/__client/api.ts +0 -0
  300. /package/templates/{web/src/personal-center → src/personal-center/web}/entry.ts +0 -0
  301. /package/templates/{web/src/personal-center → src/personal-center/web}/locales/en-US.json +0 -0
  302. /package/templates/{web/src/personal-center → src/personal-center/web}/locales/zh-CN.json +0 -0
  303. /package/templates/{web/src/personal-center → src/personal-center/web}/pages/my-profile/index.tsx +0 -0
  304. /package/templates/{web/src/route-nest → src/route-nest/web}/entry.ts +0 -0
  305. /package/templates/{web/src/route-nest → src/route-nest/web}/locales/en-US.json +0 -0
  306. /package/templates/{web/src/route-nest → src/route-nest/web}/locales/zh-CN.json +0 -0
  307. /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu1/menu1-1/index.tsx +0 -0
  308. /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu1/menu1-2/index.tsx +0 -0
  309. /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu2/index.tsx +0 -0
  310. /package/templates/{web/src → src}/styles.css +0 -0
  311. /package/templates/{web/src/system → src/system/web}/__client/api.schemas.ts +0 -0
  312. /package/templates/{web/src/system → src/system/web}/__client/api.ts +0 -0
  313. /package/templates/{web/src/system → src/system/web}/entry.ts +0 -0
  314. /package/templates/{web/src/system → src/system/web}/locales/en-US.json +0 -0
  315. /package/templates/{web/src/system → src/system/web}/locales/zh-CN.json +0 -0
  316. /package/templates/{web/src/system → src/system/web}/pages/errors.ts +0 -0
  317. /package/templates/{web/src/system → src/system/web}/pages/forbidden.tsx +0 -0
  318. /package/templates/{web/src/system → src/system/web}/pages/login-methods/index.tsx +0 -0
  319. /package/templates/{web/src/system → src/system/web}/pages/oplog/index.tsx +0 -0
  320. /package/templates/{web/src/system → src/system/web}/pages/roles/index.tsx +0 -0
  321. /package/templates/{web/src/system → src/system/web}/pages/settings/index.tsx +0 -0
  322. /package/templates/{web/src/system → src/system/web}/pages/users/index.tsx +0 -0
  323. /package/templates/{web/src/system → src/system/web}/pages/users/roles.tsx +0 -0
  324. /package/templates/{api/src/web → src/web/api}/get-async-routes/api.ts +0 -0
  325. /package/templates/{api/src/web → src/web/api}/hello/api.ts +0 -0
  326. /package/templates/{api/src/web → src/web/api}/manifest.yaml +0 -0
  327. /package/templates/{api/src/web → src/web/api}/user-info/api.ts +0 -0
  328. /package/templates/{web/src → src/web}/web/__client/api.schemas.ts +0 -0
  329. /package/templates/{web/src → src/web}/web/__client/api.ts +0 -0
  330. /package/templates/{api/tests → tests}/l1-builder.test.ts +0 -0
  331. /package/templates/{api/tests → tests}/rbac-tables.spec.ts +0 -0
@@ -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/_lifecycle/atomic";
12
- import type { StateStore } from "../../src/_platform/_lifecycle/state";
13
- import type { DeployWebContext, ModuleEntry } from "../../src/_platform/_lifecycle/steps/deploy-web";
14
- import type { ReloadContext, ReloadFace, ReloadResult } from "../../src/_platform/_lifecycle/steps/reload";
15
- import type { SmokeContext } from "../../src/_platform/_lifecycle/steps/smoke";
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";
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/_lifecycle/steps/deploy-web";
22
- import { reloadAndAssert } from "../../src/_platform/_lifecycle/steps/reload";
23
- import { probeUrlOf, smoke } from "../../src/_platform/_lifecycle/steps/smoke";
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";
24
24
 
25
25
  const g = globalThis as any;
26
26
 
@@ -326,6 +326,29 @@ describe("smoke 探活(D14/Q-A:health 不强制)", () => {
326
326
  expect(r.ok).toBe(true);
327
327
  });
328
328
 
329
+ it("health 401 且路径属本次新增 anonymous(restart_pending)→ 判通过 + 落待重启提示", async () => {
330
+ await seedDeployed();
331
+ const r = await smoke(smCtx({
332
+ manifest: solManifest({ health: "/demo-solution/ping" }),
333
+ fetch: async () => ({ ok: false, status: 401 }),
334
+ deferredAnonymous: ["/demo-solution/ping"],
335
+ }));
336
+ expect(r.ok).toBe(true);
337
+ expect(r.message).toContain("restart_pending");
338
+ expect(r.message).toContain("重启宿主后生效");
339
+ });
340
+
341
+ it("health 401 但路径不是本次新增(已在配置里)→ 仍判失败(不放宽真失败)", async () => {
342
+ await seedDeployed();
343
+ const r = await smoke(smCtx({
344
+ manifest: solManifest({ health: "/demo-solution/ping" }),
345
+ fetch: async () => ({ ok: false, status: 401 }),
346
+ deferredAnonymous: ["/demo-solution/other"],
347
+ }));
348
+ expect(r.ok).toBe(false);
349
+ expect(r.message).toContain("401");
350
+ });
351
+
329
352
  it("health 非 2xx → 探活失败", async () => {
330
353
  await seedDeployed();
331
354
  const r = await smoke(smCtx({
@@ -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/_lifecycle/atomic";
16
- import type { InstallRequest } from "../../src/_platform/_lifecycle/installer";
17
- import type { StateStore } from "../../src/_platform/_lifecycle/state";
18
- import type { ExecFace } from "../../src/_platform/_lifecycle/steps/extract";
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";
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
- import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../../src/lifecycle/__tests__/helpers";
25
- import { atomicWriteText } from "../../src/_platform/_lifecycle/atomic";
26
- import { gcVersions, reconcile, runInstall, setEnabled, STAGES } from "../../src/_platform/_lifecycle/installer";
27
- import { acquireTaskLock, commitLockEntry, parseLock, readLock, serializeLock, writeLock } from "../../src/_platform/_lifecycle/lock";
28
- import { createStateStore } from "../../src/_platform/_lifecycle/state";
29
- import { getTask, readTasks, redact, sweepTimedOut, writeTask } from "../../src/_platform/_lifecycle/tasks";
30
- import { createTrustStore } from "../../src/_platform/_lifecycle/trust";
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";
31
31
  import { installDb } from "../fixture";
32
32
 
33
33
  const g = globalThis as any;
@@ -532,8 +532,8 @@ describe("U5 取消安装(P3-8):cancel token → h.kill + staging 清场 +
532
532
 
533
533
  describe("第五终态 needs_trust(P2-3,G3 TOFU:未知 key_id 待确认,staging 不清场)", () => {
534
534
  it("未知 key 装 → needs_trust + trust 三元组 + unknown_key 指引;锁/库表/sidecar/审计零改动,staging 留存", async () => {
535
- const { generateKeyPair } = await import("../../../../src/lifecycle/keygen");
536
- const { signedArchiveFor: signFor } = await import("../../../../src/lifecycle/__tests__/helpers");
535
+ const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
536
+ const { signedArchiveFor: signFor } = await import("../../../src/lifecycle/__tests__/helpers");
537
537
  const stranger = signFor(ARCHIVE, "demo-solution", "0.1.0", { keyPair: generateKeyPair(), keyId: "stranger.pub" });
538
538
  const m = manifestFixture("0.1.0");
539
539
  m.archive = { ...m.archive, signature: stranger.sig };
@@ -562,8 +562,8 @@ describe("第五终态 needs_trust(P2-3,G3 TOFU:未知 key_id 待确认,
562
562
  });
563
563
 
564
564
  it("TOFU 全链:确认入信任库(端点同路径 store.add)后原样重试 → done", async () => {
565
- const { generateKeyPair } = await import("../../../../src/lifecycle/keygen");
566
- const { signedArchiveFor: signFor } = await import("../../../../src/lifecycle/__tests__/helpers");
565
+ const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
566
+ const { signedArchiveFor: signFor } = await import("../../../src/lifecycle/__tests__/helpers");
567
567
  const stranger = signFor(ARCHIVE, "demo-solution", "0.1.0", { keyPair: generateKeyPair(), keyId: "stranger.pub" });
568
568
  const m = manifestFixture("0.1.0");
569
569
  m.archive = { ...m.archive, signature: stranger.sig };
@@ -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>;
@@ -7,7 +7,7 @@ import { beforeAll, describe, expect, it } from "vitest";
7
7
 
8
8
  import { installDb } from "./fixture";
9
9
 
10
- const SEED = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "_platform", "seed.sql");
10
+ const SEED = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "_platform", "api", "seed.sql");
11
11
  let dbo: ReturnType<typeof installDb>;
12
12
 
13
13
  beforeAll(() => {