cabloy 5.1.136 → 5.1.138

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 (617) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +13 -0
  3. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +11 -0
  4. package/.claude/skills/cabloy-contract-loop/SKILL.md +17 -0
  5. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +35 -0
  6. package/.claude/skills/cabloy-frontend-scaffold/evals/evals.json +1 -1
  7. package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +4 -0
  8. package/.claude/skills/cabloy-zova-source-reading/SKILL.md +21 -0
  9. package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +26 -0
  10. package/CHANGELOG.md +31 -0
  11. package/CLAUDE.md +5 -1
  12. package/cabloy-docs/.vitepress/config.mjs +1 -0
  13. package/cabloy-docs/.vitepress/theme/custom.css +124 -0
  14. package/cabloy-docs/backend/auth-guide.md +8 -0
  15. package/cabloy-docs/backend/config-guide.md +2 -0
  16. package/cabloy-docs/backend/controller-aop-guide.md +8 -0
  17. package/cabloy-docs/backend/controller-guide.md +33 -0
  18. package/cabloy-docs/backend/event-guide.md +3 -3
  19. package/cabloy-docs/backend/mail-guide.md +1 -1
  20. package/cabloy-docs/backend/markdown-guide.md +1 -1
  21. package/cabloy-docs/backend/runtime-and-flavors.md +29 -0
  22. package/cabloy-docs/backend/user-access-guide.md +2 -2
  23. package/cabloy-docs/blogs/ai-react-nextjs-enterprise-architecture-cabloy/cover-en-v1.png +0 -0
  24. package/cabloy-docs/blogs/ai-react-nextjs-enterprise-architecture-cabloy/index.md +177 -0
  25. package/cabloy-docs/blogs/cabloy-fullstack-resource-addressing/cover-en-v1.png +0 -0
  26. package/cabloy-docs/blogs/cabloy-fullstack-resource-addressing/index.md +430 -0
  27. package/cabloy-docs/blogs/index.md +69 -0
  28. package/cabloy-docs/blogs/nextjs-integrated-fullstack-cabloy-contract-loop/cover-en-v1.png +0 -0
  29. package/cabloy-docs/blogs/nextjs-integrated-fullstack-cabloy-contract-loop/index.md +195 -0
  30. package/cabloy-docs/blogs/vue-object-oriented-zova-beginner-mental-model/cover-en-v1.png +0 -0
  31. package/cabloy-docs/blogs/vue-object-oriented-zova-beginner-mental-model/index.md +483 -0
  32. package/cabloy-docs/frontend/a-openapi-under-the-hood.md +13 -0
  33. package/cabloy-docs/frontend/api-schema-guide.md +79 -0
  34. package/cabloy-docs/frontend/environment-config-guide.md +2 -0
  35. package/cabloy-docs/frontend/form-guide.md +37 -0
  36. package/cabloy-docs/frontend/markdown-guide.md +3 -0
  37. package/cabloy-docs/frontend/model-resource-owner-pattern.md +26 -1
  38. package/cabloy-docs/frontend/module-scope.md +24 -0
  39. package/cabloy-docs/frontend/modules-and-suites.md +23 -1
  40. package/cabloy-docs/frontend/navigation-guards-guide.md +2 -0
  41. package/cabloy-docs/frontend/page-params-guide.md +2 -0
  42. package/cabloy-docs/frontend/page-route-guide.md +10 -3
  43. package/cabloy-docs/frontend/route-alias-guide.md +12 -6
  44. package/cabloy-docs/frontend/ssr-env.md +15 -6
  45. package/cabloy-docs/frontend/ssr-overview.md +10 -0
  46. package/cabloy-docs/frontend/ssr-review-checklist.md +1 -0
  47. package/cabloy-docs/frontend/zova-form-under-the-hood.md +6 -0
  48. package/cabloy-docs/frontend/zova-router-under-the-hood.md +4 -5
  49. package/cabloy-docs/fullstack/a-pay-payment-suite.md +1 -1
  50. package/cabloy-docs/fullstack/deploy-cloudflare-docker.md +14 -8
  51. package/e2e/specs/a-commerce/commerce.spec.ts +17 -2
  52. package/e2e/specs/cabloy-basic/account.spec.ts +519 -0
  53. package/e2e/specs/cabloy-basic/basic.spec.ts +15 -3
  54. package/package.json +1 -1
  55. package/vona/env/.env +2 -0
  56. package/vona/packages-cli/cli/package.json +1 -1
  57. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/controller/{{resourceName}}.ts_ +14 -11
  58. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/3-en-us.ts +11 -1
  59. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/4-zh-cn.ts +11 -1
  60. package/vona/packages-cli/cli-set-api/package.json +1 -1
  61. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.metadata.ts +1 -0
  62. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsMetadata/generateOnions.ts +4 -3
  63. package/vona/packages-vona/vona/package.json +1 -1
  64. package/vona/pnpm-lock.yaml +237 -66
  65. package/vona/pnpm-workspace.yaml +1 -1
  66. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +33 -37
  67. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectResItem.tsx +3 -0
  68. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuView.tsx +3 -0
  69. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/sku.tsx +17 -2
  70. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/sku.ts +12 -2
  71. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/skuPresentation.test.ts +52 -4
  72. package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +34 -36
  73. package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +29 -33
  74. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +34 -37
  75. package/vona/src/suite/a-commerce/modules/commerce-seed/src/.metadata/index.ts +8 -9
  76. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/index.ts +33 -35
  77. package/vona/src/suite/a-commerce/modules/commerce-siteweb/src/.metadata/index.ts +11 -11
  78. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +45 -42
  79. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectResItem.tsx +4 -0
  80. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditView.tsx +6 -1
  81. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectResItem.tsx +4 -0
  82. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceView.tsx +6 -1
  83. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockSkuRef.tsx +16 -0
  84. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockAudit.tsx +17 -2
  85. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockBalance.tsx +17 -2
  86. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockAudit.ts +31 -2
  87. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockBalance.ts +31 -2
  88. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockPresentation.test.ts +116 -4
  89. package/vona/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +11 -11
  90. package/vona/src/suite/a-home/modules/home-base/src/.metadata/index.ts +0 -3
  91. package/vona/src/suite/a-home/modules/home-index/src/.metadata/index.ts +12 -13
  92. package/vona/src/suite/a-home/modules/home-user/package.json +9 -1
  93. package/vona/src/suite/a-home/modules/home-user/src/.metadata/index.ts +333 -78
  94. package/vona/src/suite/a-home/modules/home-user/src/bean/cacheRedis.activation.ts +21 -0
  95. package/vona/src/suite/a-home/modules/home-user/src/bean/cacheRedis.activationCurrent.ts +15 -0
  96. package/vona/src/{suite-vendor/a-vona/modules/a-mailconfirm → suite/a-home/modules/home-user}/src/bean/cacheRedis.passwordReset.ts +6 -2
  97. package/vona/src/suite/a-home/modules/home-user/src/bean/cacheRedis.passwordResetCurrent.ts +15 -0
  98. package/vona/src/suite/a-home/modules/home-user/src/bean/cacheRedis.passwordResetRecipient.ts +13 -0
  99. package/vona/src/suite/a-home/modules/home-user/src/bean/cacheRedis.passwordSet.ts +22 -0
  100. package/vona/src/suite/a-home/modules/home-user/src/bean/cacheRedis.passwordSetCurrent.ts +15 -0
  101. package/vona/src/suite/a-home/modules/home-user/src/bean/imageScene.homeUserAvatar.ts +18 -0
  102. package/vona/src/suite/a-home/modules/home-user/src/bean/meta.redlock.ts +18 -0
  103. package/vona/src/suite/a-home/modules/home-user/src/bean/meta.version.ts +0 -1
  104. package/vona/src/suite/a-home/modules/home-user/src/bean/zodRefine.passwordConfirm.ts +8 -4
  105. package/vona/src/suite/a-home/modules/home-user/src/config/config.ts +10 -1
  106. package/vona/src/suite/a-home/modules/home-user/src/config/locale/en-us.ts +35 -3
  107. package/vona/src/suite/a-home/modules/home-user/src/config/locale/zh-cn.ts +35 -3
  108. package/vona/src/suite/a-home/modules/home-user/src/controller/account.ts +147 -0
  109. package/vona/src/suite/a-home/modules/home-user/src/controller/passport.ts +27 -7
  110. package/vona/src/suite/a-home/modules/home-user/src/dto/accountActivation.ts +12 -0
  111. package/vona/src/suite/a-home/modules/home-user/src/dto/accountCurrent.ts +31 -0
  112. package/vona/src/suite/a-home/modules/home-user/src/dto/accountPasswordChange.ts +41 -0
  113. package/vona/src/suite/a-home/modules/home-user/src/dto/accountPasswordReset.ts +35 -0
  114. package/vona/src/suite/a-home/modules/home-user/src/dto/accountPasswordResetRequest.ts +20 -0
  115. package/vona/src/suite/a-home/modules/home-user/src/dto/accountPasswordResetRequestResult.ts +13 -0
  116. package/vona/src/suite/a-home/modules/home-user/src/dto/accountPasswordSet.ts +35 -0
  117. package/vona/src/suite/a-home/modules/home-user/src/dto/accountPasswordSetIssue.ts +15 -0
  118. package/vona/src/suite/a-home/modules/home-user/src/dto/accountProfileUpdate.ts +53 -0
  119. package/vona/src/suite/a-home/modules/home-user/src/dto/accountRelogin.ts +12 -0
  120. package/vona/src/suite/a-home/modules/home-user/src/dto/passport.ts +2 -2
  121. package/vona/src/suite/a-home/modules/home-user/src/dto/passportUser.ts +43 -0
  122. package/vona/src/suite/a-home/modules/home-user/src/dto/register.ts +40 -5
  123. package/vona/src/suite/a-home/modules/home-user/src/service/account.ts +693 -0
  124. package/vona/src/suite/a-home/modules/home-user/test/account.test.ts +249 -0
  125. package/vona/src/suite/a-home/modules/home-user/test/accountActivation.test.ts +344 -0
  126. package/vona/src/suite/a-home/modules/home-user/test/accountOpenapi.test.ts +158 -0
  127. package/vona/src/suite/a-home/modules/home-user/test/accountPasswordReset.test.ts +724 -0
  128. package/vona/src/suite/a-home/modules/home-user/test/accountPasswordSet.test.ts +799 -0
  129. package/vona/src/suite/a-training/modules/training-record/src/.metadata/index.ts +73 -65
  130. package/vona/src/suite/a-training/modules/training-recordsubject/src/.metadata/index.ts +26 -17
  131. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +47 -39
  132. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/index.ts +22 -23
  133. package/vona/src/suite/cabloy-basic/modules/basic-siteadmin/src/.metadata/index.ts +15 -15
  134. package/vona/src/suite/cabloy-basic/modules/basic-siteweb/src/.metadata/index.ts +11 -11
  135. package/vona/src/suite-vendor/a-auth/modules/a-auth/package.json +1 -1
  136. package/vona/src/suite-vendor/a-auth/modules/a-auth/src/.metadata/index.ts +55 -41
  137. package/vona/src/suite-vendor/a-auth/modules/auth-oauth/package.json +1 -1
  138. package/vona/src/suite-vendor/a-auth/modules/auth-oauth/src/.metadata/index.ts +8 -8
  139. package/vona/src/suite-vendor/a-auth/modules/auth-simple/package.json +4 -2
  140. package/vona/src/suite-vendor/a-auth/modules/auth-simple/src/.metadata/index.ts +51 -27
  141. package/vona/src/suite-vendor/a-auth/modules/auth-simple/src/bean/meta.redlock.ts +11 -0
  142. package/vona/src/suite-vendor/a-auth/modules/auth-simple/src/service/authSimple.ts +53 -2
  143. package/vona/src/suite-vendor/a-auth/modules/auth-simple/test/authSimple.test.ts +56 -0
  144. package/vona/src/suite-vendor/a-auth/package.json +2 -2
  145. package/vona/src/suite-vendor/a-cabloy/modules/a-cabloy/package.json +1 -1
  146. package/vona/src/suite-vendor/a-cabloy/modules/a-cabloy/src/.metadata/index.ts +4 -4
  147. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/package.json +1 -1
  148. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/src/.metadata/index.ts +23 -24
  149. package/vona/src/suite-vendor/a-cabloy/modules/a-datasource/package.json +1 -1
  150. package/vona/src/suite-vendor/a-cabloy/modules/a-datasource/src/.metadata/index.ts +31 -22
  151. package/vona/src/suite-vendor/{a-vona/modules/a-mailconfirm → a-cabloy/modules/a-rbac}/package.json +13 -5
  152. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/.metadata/index.ts +147 -0
  153. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/.metadata/this.ts +2 -0
  154. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/bean/bean.rbacCatalog.ts +95 -0
  155. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/bean/bean.rbacScope.ts +218 -0
  156. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/bean/event.policyInvalidated.ts +17 -0
  157. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/bean/event.resolvePolicy.ts +13 -0
  158. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/bean/guard.rbac.ts +102 -0
  159. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/bean/index.ts +5 -0
  160. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/config/config.ts +10 -0
  161. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/index.ts +3 -0
  162. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/lib/index.ts +1 -0
  163. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/lib/rbac.ts +46 -0
  164. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/types/index.ts +2 -0
  165. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/types/rbac.ts +46 -0
  166. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/src/types/scope.ts +27 -0
  167. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/test/rbacCatalogGuard.test.ts +445 -0
  168. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/test/rbacScopeCurrent.test.ts +172 -0
  169. package/vona/src/suite-vendor/a-cabloy/modules/a-socket/package.json +1 -1
  170. package/vona/src/suite-vendor/a-cabloy/modules/a-socket/src/.metadata/index.ts +27 -31
  171. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/package.json +1 -1
  172. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/.metadata/index.ts +37 -45
  173. package/vona/src/suite-vendor/a-cabloy/modules/a-ssrhmr/package.json +1 -1
  174. package/vona/src/suite-vendor/a-cabloy/modules/a-ssrhmr/src/.metadata/index.ts +12 -12
  175. package/vona/src/suite-vendor/a-cabloy/modules/a-status/package.json +1 -1
  176. package/vona/src/suite-vendor/a-cabloy/modules/a-status/src/.metadata/index.ts +27 -19
  177. package/vona/src/suite-vendor/a-cabloy/package.json +2 -1
  178. package/vona/src/suite-vendor/a-cabloy/tsconfig.json +3 -0
  179. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
  180. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/src/.metadata/index.ts +27 -29
  181. package/vona/src/suite-vendor/a-captcha/modules/captcha-simple/package.json +1 -1
  182. package/vona/src/suite-vendor/a-captcha/modules/captcha-simple/src/.metadata/index.ts +16 -17
  183. package/vona/src/suite-vendor/a-captcha/package.json +1 -1
  184. package/vona/src/suite-vendor/a-file/modules/a-file/package.json +1 -1
  185. package/vona/src/suite-vendor/a-file/modules/a-file/src/.metadata/index.ts +56 -38
  186. package/vona/src/suite-vendor/a-file/modules/file-cloudflare/package.json +1 -1
  187. package/vona/src/suite-vendor/a-file/modules/file-cloudflare/src/.metadata/index.ts +12 -13
  188. package/vona/src/suite-vendor/a-file/modules/file-native/package.json +1 -1
  189. package/vona/src/suite-vendor/a-file/modules/file-native/src/.metadata/index.ts +11 -12
  190. package/vona/src/suite-vendor/a-file/package.json +4 -4
  191. package/vona/src/suite-vendor/a-image/modules/a-image/package.json +1 -1
  192. package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/index.ts +56 -38
  193. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/package.json +1 -1
  194. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/.metadata/index.ts +12 -13
  195. package/vona/src/suite-vendor/a-image/modules/image-native/package.json +1 -1
  196. package/vona/src/suite-vendor/a-image/modules/image-native/src/.metadata/index.ts +11 -12
  197. package/vona/src/suite-vendor/a-image/package.json +1 -1
  198. package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
  199. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +0 -8
  200. package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
  201. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +21 -22
  202. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +1 -1
  203. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +8 -8
  204. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +1 -1
  205. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +8 -8
  206. package/vona/src/suite-vendor/a-pay/package.json +5 -5
  207. package/vona/src/suite-vendor/a-paypal/modules/a-paypal/package.json +1 -1
  208. package/vona/src/suite-vendor/a-paypal/modules/a-paypal/src/.metadata/index.ts +46 -40
  209. package/vona/src/suite-vendor/a-paypal/package.json +1 -1
  210. package/vona/src/suite-vendor/a-vona/modules/a-aspect/cli/guard/boilerplate/{{sceneName}}.{{beanName}}.ts_ +6 -8
  211. package/vona/src/suite-vendor/a-vona/modules/a-aspect/package.json +1 -1
  212. package/vona/src/suite-vendor/a-vona/modules/a-aspect/src/.metadata/index.ts +8 -16
  213. package/vona/src/suite-vendor/a-vona/modules/a-aspect/src/lib/utils/guardBase.ts +22 -0
  214. package/vona/src/suite-vendor/a-vona/modules/a-aspect/src/lib/utils/index.ts +1 -0
  215. package/vona/src/suite-vendor/a-vona/modules/a-aspect/src/types/guard.ts +4 -1
  216. package/vona/src/suite-vendor/a-vona/modules/a-aspectutils/package.json +1 -1
  217. package/vona/src/suite-vendor/a-vona/modules/a-aspectutils/src/.metadata/index.ts +8 -10
  218. package/vona/src/suite-vendor/a-vona/modules/a-bean/package.json +1 -1
  219. package/vona/src/suite-vendor/a-vona/modules/a-bean/src/.metadata/index.ts +4 -4
  220. package/vona/src/suite-vendor/a-vona/modules/a-beanmutate/package.json +1 -1
  221. package/vona/src/suite-vendor/a-vona/modules/a-beanmutate/src/.metadata/index.ts +17 -19
  222. package/vona/src/suite-vendor/a-vona/modules/a-body/package.json +1 -1
  223. package/vona/src/suite-vendor/a-vona/modules/a-body/src/.metadata/index.ts +12 -12
  224. package/vona/src/suite-vendor/a-vona/modules/a-body/src/bean/interceptor.bodyReq.ts +1 -1
  225. package/vona/src/suite-vendor/a-vona/modules/a-body/src/types/bodyParser.ts +1 -1
  226. package/vona/src/suite-vendor/a-vona/modules/a-broadcast/package.json +1 -1
  227. package/vona/src/suite-vendor/a-vona/modules/a-broadcast/src/.metadata/index.ts +8 -9
  228. package/vona/src/suite-vendor/a-vona/modules/a-cache/package.json +1 -1
  229. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/.metadata/index.ts +14 -14
  230. package/vona/src/suite-vendor/a-vona/modules/a-caching/package.json +1 -1
  231. package/vona/src/suite-vendor/a-vona/modules/a-caching/src/.metadata/index.ts +8 -8
  232. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  233. package/vona/src/suite-vendor/a-vona/modules/a-core/src/.metadata/index.ts +20 -22
  234. package/vona/src/suite-vendor/a-vona/modules/a-election/package.json +1 -1
  235. package/vona/src/suite-vendor/a-vona/modules/a-election/src/.metadata/index.ts +15 -16
  236. package/vona/src/suite-vendor/a-vona/modules/a-error/package.json +1 -1
  237. package/vona/src/suite-vendor/a-vona/modules/a-error/src/.metadata/index.ts +19 -21
  238. package/vona/src/suite-vendor/a-vona/modules/a-event/package.json +1 -1
  239. package/vona/src/suite-vendor/a-vona/modules/a-event/src/.metadata/index.ts +16 -18
  240. package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +1 -1
  241. package/vona/src/suite-vendor/a-vona/modules/a-executor/src/.metadata/index.ts +12 -13
  242. package/vona/src/suite-vendor/a-vona/modules/a-hmr/package.json +1 -1
  243. package/vona/src/suite-vendor/a-vona/modules/a-hmr/src/.metadata/index.ts +24 -28
  244. package/vona/src/suite-vendor/a-vona/modules/a-hmrbase/package.json +1 -1
  245. package/vona/src/suite-vendor/a-vona/modules/a-hmrbase/src/.metadata/index.ts +4 -4
  246. package/vona/src/suite-vendor/a-vona/modules/a-index/package.json +1 -1
  247. package/vona/src/suite-vendor/a-vona/modules/a-index/src/.metadata/index.ts +11 -13
  248. package/vona/src/suite-vendor/a-vona/modules/a-instance/package.json +1 -1
  249. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/.metadata/index.ts +42 -35
  250. package/vona/src/suite-vendor/a-vona/modules/a-jwt/package.json +1 -1
  251. package/vona/src/suite-vendor/a-vona/modules/a-jwt/src/.metadata/index.ts +15 -17
  252. package/vona/src/suite-vendor/a-vona/modules/a-locale/package.json +1 -1
  253. package/vona/src/suite-vendor/a-vona/modules/a-locale/src/.metadata/index.ts +3 -3
  254. package/vona/src/suite-vendor/a-vona/modules/a-locale/src/main.ts +4 -1
  255. package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
  256. package/vona/src/suite-vendor/a-vona/modules/a-logger/src/.metadata/index.ts +20 -20
  257. package/vona/src/suite-vendor/a-vona/modules/a-mail/package.json +3 -3
  258. package/vona/src/suite-vendor/a-vona/modules/a-mail/src/.metadata/index.ts +38 -30
  259. package/vona/src/suite-vendor/a-vona/modules/a-mail/src/types/config.ts +1 -0
  260. package/vona/src/suite-vendor/a-vona/modules/a-menu/package.json +1 -1
  261. package/vona/src/suite-vendor/a-vona/modules/a-menu/src/.metadata/index.ts +8 -8
  262. package/vona/src/suite-vendor/a-vona/modules/a-meta/package.json +1 -1
  263. package/vona/src/suite-vendor/a-vona/modules/a-meta/src/.metadata/index.ts +4 -4
  264. package/vona/src/suite-vendor/a-vona/modules/a-metrics/package.json +1 -1
  265. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/.metadata/index.ts +15 -18
  266. package/vona/src/suite-vendor/a-vona/modules/a-onion/package.json +1 -1
  267. package/vona/src/suite-vendor/a-vona/modules/a-onion/src/.metadata/index.ts +11 -11
  268. package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
  269. package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/.metadata/index.ts +15 -16
  270. package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/types/decorator.ts +2 -1
  271. package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/types/permissions.ts +24 -1
  272. package/vona/src/suite-vendor/a-vona/modules/a-openapischema/package.json +1 -1
  273. package/vona/src/suite-vendor/a-vona/modules/a-openapischema/src/.metadata/index.ts +17 -17
  274. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/package.json +1 -1
  275. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/.metadata/index.ts +3 -3
  276. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  277. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/.metadata/index.ts +34 -39
  278. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_view.ts +10 -6
  279. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/columns_.ts +1 -2
  280. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/databaseDialectBase_.ts +37 -1
  281. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/transactionFiber_.ts +8 -2
  282. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/transaction_.ts +5 -8
  283. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/columns.ts +1 -0
  284. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
  285. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/.metadata/index.ts +8 -8
  286. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.mysql.ts +28 -0
  287. package/vona/src/suite-vendor/a-vona/modules/a-ormutils/package.json +1 -1
  288. package/vona/src/suite-vendor/a-vona/modules/a-ormutils/src/.metadata/index.ts +4 -4
  289. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +4 -1
  290. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/.metadata/index.ts +35 -22
  291. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +61 -8
  292. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/event.retrievePermissionAction.ts +2 -2
  293. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permissionActionByUser.ts +24 -0
  294. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/dto/permissions.tsx +18 -1
  295. package/vona/src/suite-vendor/a-vona/modules/a-permission/test/permission.test.ts +340 -0
  296. package/vona/src/suite-vendor/a-vona/modules/a-play/package.json +1 -1
  297. package/vona/src/suite-vendor/a-vona/modules/a-play/src/.metadata/index.ts +13 -13
  298. package/vona/src/suite-vendor/a-vona/modules/a-printtip/package.json +1 -1
  299. package/vona/src/suite-vendor/a-vona/modules/a-printtip/src/.metadata/index.ts +11 -12
  300. package/vona/src/suite-vendor/a-vona/modules/a-queue/package.json +1 -1
  301. package/vona/src/suite-vendor/a-vona/modules/a-queue/src/.metadata/index.ts +15 -17
  302. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/package.json +1 -1
  303. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/.metadata/index.ts +0 -1
  304. package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
  305. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/.metadata/index.ts +12 -13
  306. package/vona/src/suite-vendor/a-vona/modules/a-redlock/package.json +1 -1
  307. package/vona/src/suite-vendor/a-vona/modules/a-redlock/src/.metadata/index.ts +7 -8
  308. package/vona/src/suite-vendor/a-vona/modules/a-retryable/package.json +1 -1
  309. package/vona/src/suite-vendor/a-vona/modules/a-retryable/src/.metadata/index.ts +8 -8
  310. package/vona/src/suite-vendor/a-vona/modules/a-runtime/package.json +1 -1
  311. package/vona/src/suite-vendor/a-vona/modules/a-runtime/src/.metadata/index.ts +12 -13
  312. package/vona/src/suite-vendor/a-vona/modules/a-schedule/package.json +1 -1
  313. package/vona/src/suite-vendor/a-vona/modules/a-schedule/src/.metadata/index.ts +23 -26
  314. package/vona/src/suite-vendor/a-vona/modules/a-security/package.json +1 -1
  315. package/vona/src/suite-vendor/a-vona/modules/a-security/src/.metadata/index.ts +12 -12
  316. package/vona/src/suite-vendor/a-vona/modules/a-security/src/bean/bean.security.ts +78 -0
  317. package/vona/src/suite-vendor/a-vona/modules/a-security/src/bean/middlewareSystem.cors.ts +4 -2
  318. package/vona/src/suite-vendor/a-vona/modules/a-security/src/index.ts +1 -0
  319. package/vona/src/suite-vendor/a-vona/modules/a-security/src/types/index.ts +7 -0
  320. package/vona/src/suite-vendor/a-vona/modules/a-security/test/origin.test.ts +178 -0
  321. package/vona/src/suite-vendor/a-vona/modules/a-serialization/package.json +1 -1
  322. package/vona/src/suite-vendor/a-vona/modules/a-serialization/src/.metadata/index.ts +16 -16
  323. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  324. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/.metadata/index.ts +19 -22
  325. package/vona/src/suite-vendor/a-vona/modules/a-static/package.json +1 -1
  326. package/vona/src/suite-vendor/a-vona/modules/a-static/src/.metadata/index.ts +13 -14
  327. package/vona/src/suite-vendor/a-vona/modules/a-summer/package.json +1 -1
  328. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/.metadata/index.ts +10 -10
  329. package/vona/src/suite-vendor/a-vona/modules/a-swagger/package.json +1 -1
  330. package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/.metadata/index.ts +16 -17
  331. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/package.json +1 -1
  332. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/.metadata/index.ts +15 -16
  333. package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +1 -1
  334. package/vona/src/suite-vendor/a-vona/modules/a-upload/src/.metadata/index.ts +8 -8
  335. package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
  336. package/vona/src/suite-vendor/a-vona/modules/a-user/src/.metadata/index.ts +26 -35
  337. package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/guard.passport.ts +4 -2
  338. package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/guard.roleName.ts +5 -23
  339. package/vona/src/suite-vendor/a-vona/modules/a-user/src/lib/passport.ts +17 -2
  340. package/vona/src/suite-vendor/a-vona/modules/a-validation/package.json +1 -1
  341. package/vona/src/suite-vendor/a-vona/modules/a-validation/src/.metadata/index.ts +7 -7
  342. package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
  343. package/vona/src/suite-vendor/a-vona/modules/a-version/src/.metadata/index.ts +62 -37
  344. package/vona/src/suite-vendor/a-vona/modules/a-vona/package.json +1 -2
  345. package/vona/src/suite-vendor/a-vona/modules/a-vona/src/.metadata/index.ts +4 -4
  346. package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
  347. package/vona/src/suite-vendor/a-vona/modules/a-web/src/.metadata/index.ts +27 -30
  348. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/arguments.ts +5 -0
  349. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/pipesArgument.ts +3 -1
  350. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/middleware/extractValue.ts +5 -0
  351. package/vona/src/suite-vendor/a-vona/modules/a-web/src/types/controller.ts +3 -0
  352. package/vona/src/suite-vendor/a-vona/modules/a-worker/package.json +1 -1
  353. package/vona/src/suite-vendor/a-vona/modules/a-worker/src/.metadata/index.ts +15 -15
  354. package/vona/src/suite-vendor/a-vona/modules/a-zod/package.json +1 -1
  355. package/vona/src/suite-vendor/a-vona/modules/a-zod/src/.metadata/index.ts +4 -4
  356. package/vona/src/suite-vendor/a-vona/package.json +2 -3
  357. package/vona/src/suite-vendor/a-vona/tsconfig.json +0 -3
  358. package/zova/env/.env.admin +1 -0
  359. package/zova/env/.env.ssr.web +0 -1
  360. package/zova/env/.env.web +1 -0
  361. package/zova/package.original.json +1 -1
  362. package/zova/packages-cli/cli/package.json +2 -2
  363. package/zova/packages-cli/cli-set-front/package.json +1 -1
  364. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +15 -4
  365. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.tools.metadata.ts +1 -0
  366. package/zova/packages-utils/zova-jsx/package.json +2 -2
  367. package/zova/packages-zova/zova/package.json +3 -3
  368. package/zova/packages-zova/zova-core/package.json +1 -1
  369. package/zova/packages-zova/zova-core/src/core/component/locale.ts +10 -3
  370. package/zova/packages-zova/zova-core/src/core/sys/util.ts +6 -0
  371. package/zova/pnpm-lock.yaml +94 -25
  372. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +21 -21
  373. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/schemas.ts +92 -46
  374. package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/types.ts +834 -499
  375. package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +22 -22
  376. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +104 -50
  377. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +1202 -667
  378. package/zova/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +5 -5
  379. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +18 -18
  380. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/schemas.ts +136 -62
  381. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +1564 -874
  382. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/index.ts +24 -24
  383. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/schemas.ts +413 -59
  384. package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/types.ts +6290 -1946
  385. package/zova/src/suite/a-commerce/modules/commerce-siteweb/src/.metadata/index.ts +5 -5
  386. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +29 -29
  387. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +112 -58
  388. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +980 -721
  389. package/zova/src/suite/a-commerce/modules/commerce-trade/src/bean/tableCell.actionRefund.tsx +1 -1
  390. package/zova/src/suite/a-commerce/modules/commerce-trade/src/bean/tableCell.actionShip.tsx +1 -1
  391. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +1 -3
  392. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +23 -23
  393. package/zova/src/suite/a-demo/modules/demo-todo/src/.metadata/index.ts +17 -17
  394. package/zova/src/suite/a-devui/modules/devui-adapter/src/.metadata/index.ts +10 -10
  395. package/zova/src/suite/a-home/modules/home-api/cli/openapi.config.ts +1 -0
  396. package/zova/src/suite/a-home/modules/home-api/mock/passport.fake.ts +1 -1
  397. package/zova/src/suite/a-home/modules/home-api/src/.metadata/index.ts +61 -31
  398. package/zova/src/suite/a-home/modules/home-api/src/api/homeUserAccount.ts +171 -0
  399. package/zova/src/suite/a-home/modules/home-api/src/api/openapi/schemas.ts +96 -50
  400. package/zova/src/suite/a-home/modules/home-api/src/api/openapi/types.ts +857 -504
  401. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/homeUserAccount.ts +62 -0
  402. package/zova/src/suite/a-home/modules/home-base/assets/img/avatar_user.png +0 -0
  403. package/zova/src/suite/a-home/modules/home-base/src/.metadata/index.ts +16 -16
  404. package/zova/src/suite/a-home/modules/home-base/src/config/config.ts +5 -0
  405. package/zova/src/suite/a-home/modules/home-base/src/service/routerGuards.ts +1 -8
  406. package/zova/src/suite/a-home/modules/home-icon/src/.metadata/index.ts +5 -5
  407. package/zova/src/suite/a-home/modules/home-indexadmin/src/.metadata/index.ts +11 -11
  408. package/zova/src/suite/a-home/modules/home-indexweb/src/.metadata/index.ts +9 -9
  409. package/zova/src/suite/a-home/modules/home-layoutadmin/src/.metadata/index.ts +19 -19
  410. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.user.tsx +19 -2
  411. package/zova/src/suite/a-home/modules/home-layoutadmin/src/config/locale/en-us.ts +1 -0
  412. package/zova/src/suite/a-home/modules/home-layoutadmin/src/config/locale/zh-cn.ts +1 -0
  413. package/zova/src/suite/a-home/modules/home-layoutempty/src/.metadata/index.ts +7 -7
  414. package/zova/src/suite/a-home/modules/home-layoutweb/src/.metadata/component/layoutWeb.ts +1 -0
  415. package/zova/src/suite/a-home/modules/home-layoutweb/src/.metadata/index.ts +23 -15
  416. package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/render.header.tsx +1 -0
  417. package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/render.tsx +4 -0
  418. package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/render.user.tsx +68 -0
  419. package/zova/src/suite/a-home/modules/home-layoutweb/src/config/locale/en-us.ts +11 -8
  420. package/zova/src/suite/a-home/modules/home-layoutweb/src/config/locale/zh-cn.ts +11 -8
  421. package/zova/src/suite/a-home/modules/home-login/src/.metadata/index.ts +38 -18
  422. package/zova/src/suite/a-home/modules/home-login/src/.metadata/page/passwordResetRequest.ts +9 -0
  423. package/zova/src/suite/a-home/modules/home-login/src/.metadata/page/register.ts +5 -0
  424. package/zova/src/suite/a-home/modules/home-login/src/config/locale/en-us.ts +14 -0
  425. package/zova/src/suite/a-home/modules/home-login/src/config/locale/zh-cn.ts +12 -0
  426. package/zova/src/suite/a-home/modules/home-login/src/page/login/controller.tsx +10 -0
  427. package/zova/src/suite/a-home/modules/home-login/src/page/login/render.tsx +14 -0
  428. package/zova/src/suite/a-home/modules/home-login/src/page/passwordResetRequest/controller.tsx +130 -0
  429. package/zova/src/suite/a-home/modules/home-login/src/page/register/controller.tsx +124 -0
  430. package/zova/src/suite/a-home/modules/home-login/src/routes.ts +20 -0
  431. package/zova/src/suite/a-home/modules/home-passport/src/.metadata/index.ts +8 -8
  432. package/zova/src/suite/a-home/modules/home-passport/src/lib/permissionActionMatcher.ts +37 -0
  433. package/zova/src/suite/a-home/modules/home-passport/src/model/passport.ts +32 -12
  434. package/zova/src/suite/a-home/modules/home-passport/test/lib/permissionActionMatcher.test.ts +80 -0
  435. package/zova/src/suite/a-home/modules/home-theme/src/.metadata/index.ts +13 -13
  436. package/zova/src/suite/a-home/modules/home-user/package.json +60 -0
  437. package/zova/src/suite/a-home/modules/home-user/src/.metadata/index.ts +168 -0
  438. package/zova/src/suite/a-home/modules/home-user/src/.metadata/locales.ts +7 -0
  439. package/zova/src/suite/a-home/modules/home-user/src/.metadata/page/account.ts +5 -0
  440. package/zova/src/suite/a-home/modules/home-user/src/.metadata/page/activation.ts +16 -0
  441. package/zova/src/suite/a-home/modules/home-user/src/.metadata/page/passwordReset.ts +16 -0
  442. package/zova/src/suite/a-home/modules/home-user/src/.metadata/page/passwordSet.ts +16 -0
  443. package/zova/src/suite/a-home/modules/home-user/src/.metadata/this.ts +2 -0
  444. package/zova/src/suite/a-home/modules/home-user/src/config/locale/en-us.ts +52 -0
  445. package/zova/src/suite/a-home/modules/home-user/src/config/locale/zh-cn.ts +49 -0
  446. package/zova/src/suite/a-home/modules/home-user/src/index.ts +2 -0
  447. package/zova/src/suite/a-home/modules/home-user/src/model/account.ts +126 -0
  448. package/zova/src/suite/a-home/modules/home-user/src/page/account/controller.tsx +357 -0
  449. package/zova/src/suite/a-home/modules/home-user/src/page/activation/controller.tsx +83 -0
  450. package/zova/src/suite/a-home/modules/home-user/src/page/passwordReset/controller.tsx +138 -0
  451. package/zova/src/suite/a-home/modules/home-user/src/page/passwordSet/controller.tsx +138 -0
  452. package/zova/src/suite/a-home/modules/home-user/src/routes.ts +44 -0
  453. package/zova/src/suite/a-home/modules/home-user/tsconfig.build.json +13 -0
  454. package/zova/src/suite/a-home/modules/home-user/tsconfig.json +5 -0
  455. package/zova/src/suite/a-home/package.json +2 -1
  456. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +25 -25
  457. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +136 -62
  458. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +1601 -884
  459. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionDeleteForce.tsx +1 -1
  460. package/zova/src/suite/cabloy-basic/modules/basic-adapter/src/.metadata/index.ts +4 -4
  461. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/index.ts +12 -12
  462. package/zova/src/suite/cabloy-basic/modules/basic-captcha/src/.metadata/index.ts +8 -8
  463. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/.metadata/index.ts +9 -9
  464. package/zova/src/suite/cabloy-basic/modules/basic-commandssync/src/.metadata/index.ts +9 -9
  465. package/zova/src/suite/cabloy-basic/modules/basic-currency/src/.metadata/index.ts +13 -13
  466. package/zova/src/suite/cabloy-basic/modules/basic-date/src/.metadata/index.ts +13 -13
  467. package/zova/src/suite/cabloy-basic/modules/basic-details/src/.metadata/index.ts +21 -21
  468. package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/index.ts +26 -26
  469. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/schemas.ts +417 -59
  470. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/types.ts +6316 -1926
  471. package/zova/src/suite/cabloy-basic/modules/basic-form/src/.metadata/index.ts +12 -12
  472. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/component/imageUploader.ts +31 -0
  473. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/index.ts +39 -26
  474. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/schemas.ts +417 -59
  475. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/types.ts +6316 -1926
  476. package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx +194 -514
  477. package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/imageUploader/controller.tsx +386 -0
  478. package/zova/src/suite/cabloy-basic/modules/basic-image/src/config/locale/en-us.ts +1 -0
  479. package/zova/src/suite/cabloy-basic/modules/basic-image/src/config/locale/zh-cn.ts +1 -0
  480. package/zova/src/suite/cabloy-basic/modules/basic-image/src/lib/imageTransform.tsx +296 -0
  481. package/zova/src/suite/cabloy-basic/modules/basic-image/src/lib/index.ts +1 -0
  482. package/zova/src/suite/cabloy-basic/modules/basic-input/src/.metadata/index.ts +9 -9
  483. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/index.ts +19 -19
  484. package/zova/src/suite/cabloy-basic/modules/basic-page/src/.metadata/index.ts +8 -8
  485. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/.metadata/index.ts +8 -8
  486. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockToolbarRow/controller.tsx +9 -2
  487. package/zova/src/suite/cabloy-basic/modules/basic-resource/src/.metadata/index.ts +13 -13
  488. package/zova/src/suite/cabloy-basic/modules/basic-select/src/.metadata/index.ts +13 -13
  489. package/zova/src/suite/cabloy-basic/modules/basic-select/src/bean/tableCell.select.tsx +2 -3
  490. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +2 -3
  491. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/select/controller.tsx +7 -7
  492. package/zova/src/suite/cabloy-basic/modules/basic-select/src/lib/utils.ts +5 -0
  493. package/zova/src/suite/cabloy-basic/modules/basic-select/test/lib/utils.test.ts +28 -0
  494. package/zova/src/suite/cabloy-basic/modules/basic-table/src/.metadata/index.ts +16 -16
  495. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionOperationsRow.tsx +3 -1
  496. package/zova/src/suite/cabloy-basic/modules/basic-text/src/.metadata/index.ts +13 -13
  497. package/zova/src/suite-vendor/a-cabloy/modules/a-rbac/package.json +52 -0
  498. package/zova/src/suite-vendor/a-cabloy/modules/a-rbac/src/.metadata/index.ts +26 -0
  499. package/zova/src/suite-vendor/a-cabloy/modules/a-rbac/src/.metadata/this.ts +2 -0
  500. package/zova/src/suite-vendor/a-cabloy/modules/a-rbac/src/index.ts +1 -0
  501. package/zova/src/suite-vendor/a-cabloy/modules/a-rbac/tsconfig.build.json +13 -0
  502. package/zova/src/suite-vendor/a-cabloy/modules/a-rbac/tsconfig.json +5 -0
  503. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  504. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/.metadata/index.ts +15 -15
  505. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/lib/deleteRequest.ts +12 -0
  506. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +12 -6
  507. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/test/lib/deleteRequest.test.ts +37 -0
  508. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/test/model/resource.types.ts +24 -0
  509. package/zova/src/suite-vendor/a-cabloy/package.json +3 -2
  510. package/zova/src/suite-vendor/a-pay/modules/a-pay/cli/openapi.config.ts +1 -1
  511. package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
  512. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +43 -43
  513. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/schemas.ts +120 -58
  514. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/types.ts +1408 -938
  515. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/payPaymentSession.ts +74 -0
  516. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/apiSchema/payPaymentSession.ts +25 -0
  517. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +3 -3
  518. package/zova/src/suite-vendor/a-pay/modules/pay-mock/cli/openapi.config.ts +1 -1
  519. package/zova/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
  520. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +34 -34
  521. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/schemas.ts +140 -66
  522. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/types.ts +1621 -891
  523. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockMockPayment.ts +34 -0
  524. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockMockPayment.ts +13 -0
  525. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/model/payMockPayment.ts +3 -3
  526. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/package.json +1 -1
  527. package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +4 -4
  528. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/package.json +1 -1
  529. package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +4 -4
  530. package/zova/src/suite-vendor/a-pay/package.json +5 -5
  531. package/zova/src/suite-vendor/a-zova/modules/a-api/package.json +1 -1
  532. package/zova/src/suite-vendor/a-zova/modules/a-api/src/.metadata/index.ts +7 -7
  533. package/zova/src/suite-vendor/a-zova/modules/a-app/package.json +1 -1
  534. package/zova/src/suite-vendor/a-zova/modules/a-app/src/.metadata/index.ts +8 -8
  535. package/zova/src/suite-vendor/a-zova/modules/a-bean/package.json +1 -1
  536. package/zova/src/suite-vendor/a-zova/modules/a-bean/src/.metadata/index.ts +15 -15
  537. package/zova/src/suite-vendor/a-zova/modules/a-behavior/package.json +1 -1
  538. package/zova/src/suite-vendor/a-zova/modules/a-behavior/src/.metadata/index.ts +25 -25
  539. package/zova/src/suite-vendor/a-zova/modules/a-behaviors/package.json +1 -1
  540. package/zova/src/suite-vendor/a-zova/modules/a-behaviors/src/.metadata/index.ts +9 -9
  541. package/zova/src/suite-vendor/a-zova/modules/a-boundary/package.json +1 -1
  542. package/zova/src/suite-vendor/a-zova/modules/a-boundary/src/.metadata/index.ts +5 -5
  543. package/zova/src/suite-vendor/a-zova/modules/a-command/package.json +1 -1
  544. package/zova/src/suite-vendor/a-zova/modules/a-command/src/.metadata/index.ts +5 -5
  545. package/zova/src/suite-vendor/a-zova/modules/a-fetch/package.json +1 -1
  546. package/zova/src/suite-vendor/a-zova/modules/a-fetch/src/.metadata/index.ts +14 -14
  547. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
  548. package/zova/src/suite-vendor/a-zova/modules/a-form/src/.metadata/index.ts +12 -12
  549. package/zova/src/suite-vendor/a-zova/modules/a-icon/package.json +1 -1
  550. package/zova/src/suite-vendor/a-zova/modules/a-icon/src/.metadata/index.ts +18 -18
  551. package/zova/src/suite-vendor/a-zova/modules/a-interceptor/package.json +1 -1
  552. package/zova/src/suite-vendor/a-zova/modules/a-interceptor/src/.metadata/index.ts +8 -8
  553. package/zova/src/suite-vendor/a-zova/modules/a-logger/package.json +1 -1
  554. package/zova/src/suite-vendor/a-zova/modules/a-logger/src/.metadata/index.ts +9 -9
  555. package/zova/src/suite-vendor/a-zova/modules/a-meta/package.json +1 -1
  556. package/zova/src/suite-vendor/a-zova/modules/a-meta/src/.metadata/index.ts +5 -5
  557. package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
  558. package/zova/src/suite-vendor/a-zova/modules/a-model/src/.metadata/index.ts +12 -12
  559. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +3 -2
  560. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/.metadata/index.ts +13 -13
  561. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/monkey.ts +16 -27
  562. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/permissions.ts +18 -1
  563. package/zova/src/suite-vendor/a-zova/modules/a-router/package.json +1 -1
  564. package/zova/src/suite-vendor/a-zova/modules/a-router/src/.metadata/index.ts +27 -27
  565. package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkey.ts +9 -6
  566. package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkeySys.ts +15 -5
  567. package/zova/src/suite-vendor/a-zova/modules/a-router/src/types/router.ts +2 -2
  568. package/zova/src/suite-vendor/a-zova/modules/a-routerstack/package.json +1 -1
  569. package/zova/src/suite-vendor/a-zova/modules/a-routerstack/src/.metadata/index.ts +13 -13
  570. package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
  571. package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/.metadata/index.ts +13 -13
  572. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  573. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/.metadata/index.ts +9 -9
  574. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +15 -4
  575. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssrNavigation.ts +40 -0
  576. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssrProfile.ts +6 -1
  577. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/monkey.ts +20 -6
  578. package/zova/src/suite-vendor/a-zova/modules/a-ssr/test/lib/ssrNavigation.test.ts +69 -0
  579. package/zova/src/suite-vendor/a-zova/modules/a-ssr/test/lib/ssrProfile.test.ts +25 -6
  580. package/zova/src/suite-vendor/a-zova/modules/a-ssrhmr/package.json +1 -1
  581. package/zova/src/suite-vendor/a-zova/modules/a-ssrhmr/src/.metadata/index.ts +4 -4
  582. package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/package.json +1 -1
  583. package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/src/.metadata/index.ts +10 -10
  584. package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/src/service/ssrHandler.ts +1 -2
  585. package/zova/src/suite-vendor/a-zova/modules/a-style/package.json +1 -1
  586. package/zova/src/suite-vendor/a-zova/modules/a-style/src/.metadata/index.ts +9 -9
  587. package/zova/src/suite-vendor/a-zova/modules/a-style/src/bean/bean.theme.ts +2 -2
  588. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  589. package/zova/src/suite-vendor/a-zova/modules/a-table/src/.metadata/index.ts +12 -12
  590. package/zova/src/suite-vendor/a-zova/modules/a-zod/package.json +1 -1
  591. package/zova/src/suite-vendor/a-zova/modules/a-zod/src/.metadata/index.ts +9 -9
  592. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  593. package/zova/src/suite-vendor/a-zova/modules/a-zova/src/.metadata/index.ts +5 -5
  594. package/zova/src/suite-vendor/a-zova/package.json +26 -26
  595. package/vona/src/suite/a-home/modules/home-user/src/bean/eventListener.emailConfirmCallback.ts +0 -32
  596. package/vona/src/suite/a-home/modules/home-user/src/bean/eventListener.passwordResetCallback.ts +0 -30
  597. package/vona/src/suite/a-home/modules/home-user/src/bean/eventListener.register.ts +0 -27
  598. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/.metadata/index.ts +0 -207
  599. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/.metadata/locales.ts +0 -18
  600. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/.metadata/this.ts +0 -2
  601. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/bean.mailConfirm.ts +0 -63
  602. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.emailConfirm.ts +0 -17
  603. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/event.emailConfirmCallback.ts +0 -13
  604. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/event.passwordResetCallback.ts +0 -13
  605. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/config/locale/en-us.ts +0 -13
  606. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/config/locale/mail/en-us.ts +0 -29
  607. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/config/locale/mail/zh-cn.ts +0 -29
  608. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/config/locale/zh-cn.ts +0 -13
  609. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/controller/mail.ts +0 -34
  610. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/index.ts +0 -2
  611. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/paymentSession.ts +0 -74
  612. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/apiSchema/paymentSession.ts +0 -25
  613. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockPayment.ts +0 -34
  614. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockPayment.ts +0 -13
  615. /package/vona/patches/{zova-core@5.1.84.patch → zova-core@5.1.85.patch} +0 -0
  616. /package/vona/src/suite-vendor/{a-vona/modules/a-mailconfirm → a-cabloy/modules/a-rbac}/tsconfig.build.json +0 -0
  617. /package/vona/src/suite-vendor/{a-vona/modules/a-mailconfirm → a-cabloy/modules/a-rbac}/tsconfig.json +0 -0
@@ -0,0 +1,177 @@
1
+ ---
2
+ title: 'Why Is AI So Good at React/Next.js, Yet Truly Useful Open-Source Next.js Projects Are Rare?'
3
+ titleEn: 'Why Is AI So Good at React/Next.js, Yet Truly Useful Open-Source Next.js Projects Are Rare?'
4
+ subtitle: AI is excellent at completing local React/Next.js code, but that does not mean it has learned the architecture of enterprise applications.
5
+ summary: React/Next.js has abundant public training material, so AI is highly capable at components, Hooks, routes, and CRUD. Enterprise systems, however, depend on permissions, multitenancy, modularity, contracts, and long-term evolution. The article closes by introducing how CabloyJS uses Vona, Zova, and fullstack collaboration workflows to provide clearer structure for this kind of work.
6
+ tags:
7
+ - AI Coding
8
+ - React
9
+ - Next.js
10
+ - Enterprise Architecture
11
+ - CabloyJS
12
+ - Vona
13
+ - Zova
14
+ - Fullstack
15
+ slug: ai-react-nextjs-enterprise-architecture-cabloy-en
16
+ cover: ./cover-en-v1.png
17
+ date: 2026-08-04
18
+ ---
19
+
20
+ # Why Is AI So Good at React/Next.js, Yet Truly Useful Open-Source Next.js Projects Are Rare?
21
+
22
+ This is an interesting question because it exposes a distinction that is often blurred:
23
+
24
+ > **“AI is best at writing React/Next.js” does not mean “AI is best at building large Next.js projects.”**
25
+
26
+ ## 1. React/Next.js really does have the most training material
27
+
28
+ GitHub contains an enormous number of React/Next.js projects, tutorials, blog posts, and examples. As a result, AI performs exceptionally well on local development tasks involving components, Hooks, Tailwind, routing, Server Actions, and similar work.
29
+
30
+ But that does not mean AI has learned the overall architecture of enterprise applications.
31
+
32
+ ## 2. Most of what AI has learned is “local code”
33
+
34
+ Training data contains large numbers of files such as:
35
+
36
+ - `Button.tsx`
37
+ - `LoginForm.tsx`
38
+ - `UserTable.tsx`
39
+ - `useFetch.ts`
40
+
41
+ It contains far fewer complete, long-lived ERP, CRM, e-commerce, or CMS systems.
42
+
43
+ Commercial projects are usually not open source, so the large-scale engineering examples available for AI to learn from are relatively limited.
44
+
45
+ ## 3. Much of the Next.js community is built around demos and starters
46
+
47
+ Many high-star projects are essentially combinations of:
48
+
49
+ - Login
50
+ - Blogs
51
+ - Dashboards
52
+ - Stripe payments
53
+ - Prisma
54
+ - Basic authentication
55
+
56
+ They demonstrate a technology stack, rather than an enterprise system that has evolved over many years.
57
+
58
+ ## 4. Next.js itself is not an enterprise framework
59
+
60
+ Next.js has always positioned itself as a React framework. It primarily addresses:
61
+
62
+ - Routing
63
+ - Rendering
64
+ - Builds
65
+ - Images
66
+ - Server Functions
67
+
68
+ What makes enterprise applications genuinely complex is different:
69
+
70
+ - Permission systems
71
+ - Multitenancy
72
+ - Plugin mechanisms
73
+ - Modularity
74
+ - Workflows
75
+ - Data permissions
76
+ - Auditing
77
+ - Messaging systems
78
+ - Transactions
79
+ - Internationalization
80
+
81
+ Real projects therefore usually require a substantial surrounding stack as well.
82
+
83
+ ## 5. React’s greatest strength is also its greatest challenge
84
+
85
+ React is highly flexible. You can freely combine:
86
+
87
+ - Redux, Zustand, MobX, and more
88
+ - React Hook Form, TanStack Form, and more
89
+ - SWR, TanStack Query, and more
90
+ - Prisma, Drizzle, and more
91
+
92
+ That rich ecosystem means there is no single best practice. It also means AI is more likely to learn many different styles than one unified architecture.
93
+
94
+ ## 6. The difficult part is architecture, not code
95
+
96
+ AI can already generate CRUD and components quickly.
97
+
98
+ What is genuinely difficult is answering questions such as:
99
+
100
+ - Why are the modules split this way?
101
+ - Why is the lifecycle designed this way?
102
+ - Why does the permission model take this form?
103
+ - Why is the plugin extension point located here?
104
+
105
+ Those answers come from long-term practice and continuous evolution, not from code statistics alone.
106
+
107
+ ## Summary
108
+
109
+ A more accurate way to understand “AI is good at React” is:
110
+
111
+ > **AI is very good at completing React/Next.js code, but that does not mean it has learned to design large React/Next.js applications.**
112
+
113
+ Rich training material improves local code generation. Mature enterprise systems, however, depend on long-term architectural design, accumulated business knowledge, and continuous evolution. That is also why truly strong, long-maintained, open-source Next.js projects are relatively uncommon.
114
+
115
+ ---
116
+
117
+ ## If Your Goal Is an Enterprise Fullstack System, Try CabloyJS
118
+
119
+ The conclusion above is not that React or Next.js is bad. They remain excellent tools. If you need the React ecosystem, want to build pages quickly, or are working on a web application with well-bounded requirements, Next.js can be a very direct choice.
120
+
121
+ But when the goal shifts from “build an application” to “evolve an enterprise system for years,” generating components and endpoints is not enough. You also need a fullstack framework that can answer questions such as:
122
+
123
+ - Where should a business capability belong?
124
+ - How can backend DTOs, OpenAPI, and frontend calls avoid becoming separate hand-maintained copies?
125
+ - When a frontend resource changes, how do backend metadata or SSR consumers stay synchronized?
126
+ - How can multiple business modules, Admin, Web, SSR, and SPA applications work together in one project?
127
+ - How can AI-generated code follow the existing modules, commands, and verification paths instead of being assembled arbitrarily across the repository?
128
+
129
+ Those are the problems **CabloyJS** aims to address.
130
+
131
+ CabloyJS is a Node.js fullstack framework system:
132
+
133
+ - **Vona** provides backend runtime, business-service, data, and contract capabilities.
134
+ - **Zova** provides frontend application capabilities.
135
+ - **Suites and modules** give business domains and capabilities stable organizational boundaries.
136
+ - The **contract loop** lets backend OpenAPI contracts generate frontend SDKs, while frontend resources and metadata can also return to the backend side through explicit handoff paths.
137
+ - A **CLI-first workflow** makes creation, generation, builds, and verification discoverable and repeatable within the repository.
138
+
139
+ Its value is not that AI can design your architecture for you. The real value is that, once a project has clear module boundaries, contract sources, generation paths, and verification requirements, AI no longer has to guess from a temporary prompt alone. It can participate within the same fullstack rules.
140
+
141
+ Of course, that also means CabloyJS is not the lightest choice. It requires learning the Vona, Zova, suite/module, and contract-loop models. For a one-off page, a simple site, or a project deliberately centered only on React/Next.js, staying lightweight may be the better choice.
142
+
143
+ But when you need a multi-module business system, long-term frontend/backend synchronization, Admin, Web, SSR, and SPA delivery, or want AI to do more than generate isolated code and gradually follow the collaboration rules of the whole repository, CabloyJS is worth trying.
144
+
145
+ ## Start with a small experiment
146
+
147
+ The public starting point for Cabloy Basic is:
148
+
149
+ ```bash
150
+ npm create cabloy
151
+ ```
152
+
153
+ After entering the generated project, start the backend:
154
+
155
+ ```bash
156
+ npm run dev
157
+ ```
158
+
159
+ You can also start Cabloy Basic’s Zova Admin or Web frontend separately:
160
+
161
+ ```bash
162
+ npm run dev:zova:admin
163
+ npm run dev:zova:web
164
+ ```
165
+
166
+ Then follow the [Cabloy Fullstack Quick Start Tutorials](https://docs.cabloy.com/fullstack/tutorials-overview). Start with a small module and experience how CRUD, frontend/backend contract sharing, and a fullstack workflow connect in practice.
167
+
168
+ If you are looking not for another component library or another Next.js starter, but for a framework built for enterprise fullstack collaboration, start with the [Cabloy Fullstack Quickstart](https://docs.cabloy.com/fullstack/quickstart) and give CabloyJS a try.
169
+
170
+ ## Further reading
171
+
172
+ - [Cabloy Fullstack Introduction](https://docs.cabloy.com/fullstack/introduction)
173
+ - [Cabloy Fullstack Quickstart](https://docs.cabloy.com/fullstack/quickstart)
174
+ - [Cabloy Suites and Modules](https://docs.cabloy.com/fullstack/suites-and-modules)
175
+ - [Cabloy Vona + Zova Integration](https://docs.cabloy.com/fullstack/vona-zova-integration)
176
+ - [Cabloy Contract Loop Playbook](https://docs.cabloy.com/fullstack/contract-loop-playbook)
177
+ - [Cabloy Fullstack Quick Start Tutorials](https://docs.cabloy.com/fullstack/tutorials-overview)
@@ -0,0 +1,430 @@
1
+ ---
2
+ title: 'Beyond IoC: CabloyJS as a Full-Stack Resource Addressing System'
3
+ titleZh: CabloyJS 强大之处不仅仅是 IoC,而是全栈资源的寻址体系
4
+ titleEn: 'Beyond IoC: CabloyJS as a Full-Stack Resource Addressing System'
5
+ subtitle: Follow one business capability from suite and module ownership through Beans, Resources, contracts, routes, state owners, and rendering metadata.
6
+ summary: IoC answers how code obtains runtime collaborators. In a full-stack system that evolves over time, the harder question is how a business capability remains identifiable across modules, backend resources, HTTP and OpenAPI contracts, routes, state ownership, and rendering. Using `training-student:student`, this article maps the constrained address spaces that let CabloyJS preserve one business meaning across Vona and Zova.
7
+ tags:
8
+ - Cabloy
9
+ - Vona
10
+ - Zova
11
+ - IoC
12
+ - Fullstack Architecture
13
+ - OpenAPI
14
+ - TypeScript
15
+ - Metadata-driven Architecture
16
+ slug: cabloy-fullstack-resource-addressing-en
17
+ cover: ./cover-en-v1.png
18
+ date: 2026-08-16
19
+ ---
20
+
21
+ # Beyond IoC: CabloyJS as a Full-Stack Resource Addressing System
22
+
23
+ > IoC answers “how a runtime collaborator is obtained.” Full-stack resource addressing answers “which business capability this is, where it enters the system, how each layer locates it, and how it retains one business meaning.”
24
+
25
+ In a new application, tracing a feature is usually straightforward: find a component, follow an import to its request function, then follow that function to a backend Controller. As a system grows into multiple business domains and modules—with admin resource pages, Web self-service pages, SSR, OpenAPI contracts, and frontend rendering resources—the harder question is no longer simply whether a Service can be injected.
26
+
27
+ Consider a Student capability. Which business domain owns it? Which module implements it? How does the backend expose it? How does a menu enter it? How does a generic Resource page know what it is displaying? And how do frontend requests, Schemas, permissions, forms, caches, and custom rendering continue to refer to the same business meaning?
28
+
29
+ IoC matters to all of those questions: it provides object ownership, lifecycle, scope, and dependency resolution. But Cabloy becomes more interesting when IoC is not viewed in isolation. Together with suites, modules, Bean identities, business Resources, OpenAPI, route parameters, selector-backed Models, and rendering metadata, it forms a set of **constrained, mappable addressing coordinates**.
30
+
31
+ This is not one universal string that travels through every layer, nor is it zero-configuration magic. Vona and Zova have independent runtime containers. Backend and frontend cooperate through contracts, metadata, generated artifacts, and build outputs. This article uses “full-stack resource addressing system” as a lens for understanding Cabloy architecture—not as the name of an official API that replaces existing terminology.
32
+
33
+ ---
34
+
35
+ ## Separate IoC from addressing first
36
+
37
+ IoC asks a focused question: **who creates, owns, disposes of, and supplies a runtime capability?**
38
+
39
+ In Zova, a Bean may be held in the `sys`, `app`, or `ctx` container scope. Code can use `@Use` for injection or use containers and Scope for dependency lookup. This single model keeps state sharing, lifecycle behavior, and cross-module collaboration from drifting into unrelated mechanisms. [IoC and Beans](https://docs.cabloy.com/frontend/ioc-and-beans) explains that model in detail.
40
+
41
+ Addressing asks a broader question: **when one layer needs something, which identity expresses the target, who resolves it, and what kind of resource results?**
42
+
43
+ The current repository’s Student sample includes related but non-interchangeable values:
44
+
45
+ | Layer | Example | Question answered |
46
+ | --------------------------------------- | ---------------------------------- | ------------------------------------------------------------- |
47
+ | Business domain / suite | `a-training` | Which business domain owns this family of capabilities? |
48
+ | Feature module | `training-student` | Which capability boundary owns Student? |
49
+ | Bean full name | `training-student.service.student` | Which runtime Service should the container resolve? |
50
+ | Business Resource identity (onion name) | `training-student:student` | Which module-qualified business Resource is under discussion? |
51
+ | Route entry | `:resource/:id/:formScene?` | Which page scene is being entered? |
52
+ | HTTP API path | `/api/training/student` | Where should the request be sent? |
53
+ | Resource Model selector | `training-student:student` | Which Resource is the generic owner maintaining state for? |
54
+ | Render resource | `training-student:formFieldLevel` | Which frontend scene capability renders the field? |
55
+
56
+ Think of these as different coordinate systems for the same place: an administrative region, street, building number, navigation entry, delivery address, and room number are related, but they solve different problems. Calling them all an “ID” hides the boundaries that matter.
57
+
58
+ Let us follow `training-student:student` through the system.
59
+
60
+ ## Coordinate one: suites and modules answer “who owns it?”
61
+
62
+ Cabloy defines a **suite** as a business-domain composition boundary and a **module** as a feature implementation boundary within that domain. In other words:
63
+
64
+ - a suite answers, “which business domain does this group of capabilities belong to?”
65
+ - a module answers, “within that domain, which capability owns this implementation?”
66
+
67
+ In the Student sample, the domain is `a-training` and the module is `training-student`. Vona and Zova both have corresponding suite/module structures, so backend Controllers, Services, Models, Entities, and DTOs can evolve along the same business boundary as frontend pages, APIs, Models, and metadata. What is shared first is a **business coordinate**, not a block of memory shared by Node.js and the browser.
68
+
69
+ That is why a module name matters more than a directory position. Directories can be reorganized and implementation files can move, while a stable module namespace can continue to carry the logical identity of Services, Models, APIs, locales, errors, Resources, and frontend render resources. See [Suites and Modules](https://docs.cabloy.com/fullstack/suites-and-modules) for the boundary between suites and modules.
70
+
71
+ ## Coordinate two: Bean full names and the Scope facade
72
+
73
+ At runtime, one module still needs to locate different families of capabilities. Most scene-based Vona Beans use this full identity:
74
+
75
+ ```text
76
+ {moduleName}.{sceneName}.{beanName}
77
+ ```
78
+
79
+ For example:
80
+
81
+ ```text
82
+ training-student.controller.student
83
+ training-student.service.student
84
+ training-student.model.student
85
+ ```
86
+
87
+ Here, `sceneName` distinguishes capability families such as controllers, services, and models. Two related facts must therefore remain separate:
88
+
89
+ - `training-student:student` is a module-qualified onion name;
90
+ - `training-student.service.student` is a Bean full name whose scene has already been specified.
91
+
92
+ An onion name is not merely a global Bean key with some characters omitted. A consumer must identify a scene such as `service`, `model`, or `controller` before the framework can resolve the corresponding full Bean name.
93
+
94
+ Business code usually does not need to write full names everywhere. Scope supplies a typed facade over module resources:
95
+
96
+ ```ts
97
+ // Business orchestration in the current module
98
+ const students = await this.scope.model.student.select();
99
+
100
+ // A known cross-module target
101
+ const sku = await this.$scope.commerceCatalog.model.sku.getById(id);
102
+ ```
103
+
104
+ Scope does not create another identity system. It raises a container-level full name into an everyday way to navigate a module’s resource catalog. Backend Scope can organize services, models, entities, configuration, locales, and errors; frontend Scope commonly exposes facades for configuration, constants, locales, errors, APIs, and API Schemas. Both [Vona Backend Foundation](https://docs.cabloy.com/backend/foundation) and [Zova Module Scope](https://docs.cabloy.com/frontend/module-scope) describe that division of responsibility.
105
+
106
+ There is an important limit: Scope lookup can resolve only resources from modules that have already been composed into the active application. A correct string does not install, load, or order an absent module. Module dependencies, suite/application composition, and runtime lookup are related but different concerns. The first establishes availability, ordering, and versioning; only then can the latter retrieve a resource from the composed modules.
107
+
108
+ ## Coordinate three: `@Resource()` connects business identity to an HTTP contract
109
+
110
+ The Student backend Controller uses `@Controller('student')` and `@Resource()`. This is a trimmed version of the current implementation, retaining only the roles relevant here:
111
+
112
+ ```ts
113
+ @Controller('student')
114
+ @Resource()
115
+ export class ControllerStudent extends BeanBase {
116
+ @Web.get()
117
+ @Api.body(DtoStudentSelectRes)
118
+ async select(
119
+ @Arg.filter(DtoStudentSelectReq) params: IQueryParams<ModelStudent>,
120
+ ): Promise<DtoStudentSelectRes> {
121
+ return await this.scope.service.student.select(params);
122
+ }
123
+ }
124
+ ```
125
+
126
+ This is not just a class with two decorators. It connects at least three responsibilities:
127
+
128
+ 1. the Controller exposes an HTTP-facing action;
129
+ 2. DTOs, Entity fields, and validation shape a machine-readable contract;
130
+ 3. `@Resource()` registers the Controller’s onion identity as a business Resource.
131
+
132
+ When Vona processes the Controller decorator, it derives the onion name from the Bean full name, combines module and controller-path metadata to compute the API path, and records the resource-to-route mapping. `training-student:student` can therefore remain a stable business Resource identity, while the HTTP path is a transport address derived from backend route metadata.
133
+
134
+ Avoid saying:
135
+
136
+ ```text
137
+ training-student:student === /api/training/student
138
+ ```
139
+
140
+ A more accurate relationship is:
141
+
142
+ ```text
143
+ training-student:student
144
+ ──resolved through Resource registration and bootstrap metadata──▶
145
+ /api/training/student
146
+ ```
147
+
148
+ The first expresses _which business Resource_ is involved; the second expresses _where the request goes_. This is one reason a Resource identity is often safer than scattering HTTP strings when frontend state, permissions, Schemas, or route context need to carry business meaning.
149
+
150
+ ## Coordinate four: one field contract does not need to be copied into separate knowledge
151
+
152
+ The value of resource addressing is not limited to finding an endpoint. It also allows one business contract to be recognized and projected by different consumers.
153
+
154
+ A backend field can participate in:
155
+
156
+ 1. validation;
157
+ 2. OpenAPI generation;
158
+ 3. form and table rendering;
159
+ 4. serialization or desensitization.
160
+
161
+ Take `mobile` from the Student Entity in `training-student`. This is a trimmed version of the current source:
162
+
163
+ ```ts
164
+ @Api.field(
165
+ v.title($locale('Mobile')), // OpenAPI field title
166
+ v.required(), // validation
167
+ v.min(11), // validation
168
+ v.serializerReplace({ // response-time desensitization
169
+ patternFrom: /^(\d{3})\d{4}(\d+)$/,
170
+ patternTo: '$1****$2',
171
+ }),
172
+ ZovaRender.order(3), // display order for generic table and field surfaces
173
+ )
174
+ mobile: string;
175
+ ```
176
+
177
+ This declaration does not merely describe an isolated string. It is projected through DTOs and the Resource Schema: create, update, and view DTO layouts place `{ type: 'field', name: 'mobile' }` in Student Profile; the list-row Schema inherits the field and orders it through `order(3)`. With no specialized Renderer, the generic form uses the default `Input` and the generic table uses a plain-text Cell. A query response with `@Core.serializer()` returns `13812345678` as `138****5678`, while the persisted raw value remains unchanged.
178
+
179
+ | Capability | `mobile` declaration or projection | Consumer |
180
+ | ------------------------------- | ------------------------------------------------------- | ----------------------------------------------------- |
181
+ | Validation | `v.required()` and `v.min(11)` | Request/DTO validation boundary |
182
+ | OpenAPI generation | `@Api.field(...)`, title, and string Schema | OpenAPI and downstream SDK/Schema consumers |
183
+ | Form and table rendering | DTO layout’s `field: mobile` plus `ZovaRender.order(3)` | Generic Resource UI’s default Input and text Cell |
184
+ | Serialization / desensitization | `v.serializerReplace(...)` | Response serialization before data reaches the client |
185
+
186
+ If this field needs specialized controls instead of the default Renderer, it can additionally declare `ZovaRender.field('training-student:formFieldLevel', ...)` and `ZovaRender.cell('training-student:level', ...)`, as `level` does in the same Entity. The point is not that every property must carry all four concerns or use a custom component. The point is that these concerns can be composed around the same field contract when they apply.
187
+
188
+ That does not mean each field automatically grows a complete UI, nor that every presentation decision belongs in the backend. It means the field’s business meaning, data contract, and permitted exposure do not have to be copied into backend DTOs, frontend request types, form rules, table columns, and response post-processing—and then manually kept aligned.
189
+
190
+ In this **forward contract chain**, backend Controllers, DTOs, Entities, and validation rules are the source of truth. Vona generates OpenAPI; Zova then generates or consumes SDK/Schema contract material. When a backend contract changes, the recommended path is to propagate that truth forward rather than hand-edit multiple frontend copies. [Backend OpenAPI to Frontend SDK](https://docs.cabloy.com/fullstack/openapi-to-sdk) and [One Contract Surface, Four Uses](https://docs.cabloy.com/fullstack/tutorial-6-one-contract-four-uses) describe the boundary of that chain.
191
+
192
+ ## Coordinate five: routes choose a UI scene; Resource identities choose business context
193
+
194
+ The generic Resource page makes clear why a page address and a business Resource identity need to remain separate.
195
+
196
+ `rest-resource` defines generic routes with dynamic parameters:
197
+
198
+ ```ts
199
+ export const routes: IModuleRoute[] = [
200
+ { name: 'resource', path: ':resource', component: ZPageResource },
201
+ { name: 'entryCreate', path: ':resource/create', component: ZPageEntryCreate },
202
+ { name: 'entry', path: ':resource/:id/:formScene?', component: ZPageEntry },
203
+ ];
204
+ ```
205
+
206
+ Dynamic-parameter routes explicitly declare `name`, which establishes a type contract for page parameters. The route answers whether the active scene is a resource list, a create form, or a form scene for one record. The route itself does not yet know the business meaning of Student, Course, or any other Resource.
207
+
208
+ The Student SSR menu supplies that context:
209
+
210
+ ```ts
211
+ @SsrMenu({
212
+ items: {
213
+ student: {
214
+ link: 'presetResource',
215
+ meta: {
216
+ params: {
217
+ resource: 'training-student:student',
218
+ },
219
+ },
220
+ },
221
+ },
222
+ })
223
+ export class SsrMenuStudent extends BeanBase {}
224
+ ```
225
+
226
+ The menu does not directly render a Student page, nor does it grant authorization. It passes the `resource` parameter to the predefined generic Resource route:
227
+
228
+ ```text
229
+ SSR menu
230
+ → presetResource
231
+ → :resource route parameter
232
+ → Page Controller’s $params.resource
233
+ ```
234
+
235
+ The URL and route locate a page scene; `$params.resource` brings in business Resource context. Route names, route parameters, menu metadata, and permissions are still four separate objects that must each be verified.
236
+
237
+ ## Coordinate six: the Resource identity becomes a selector-backed Model owner
238
+
239
+ Once the generic page receives its parameter, it does not duplicate a page Controller for every Resource. It injects the current identity into one generic Model:
240
+
241
+ ```ts
242
+ @Controller()
243
+ export class ControllerPageResource extends BeanControllerPageBase {
244
+ @Use({ beanFullName: 'rest-resource.model.resource' })
245
+ get $$modelResource(): ModelResource {
246
+ return usePrepareArg(this.$params.resource, true);
247
+ }
248
+
249
+ protected async __init__() {
250
+ await $QueryEnsureLoaded(() => this.$$modelResource.apiSchemasSelect.sdk);
251
+ }
252
+ }
253
+ ```
254
+
255
+ There are two addresses at different levels:
256
+
257
+ ```text
258
+ Generic Model Bean: rest-resource.model.resource
259
+ Current selector: training-student:student
260
+ ```
261
+
262
+ `ModelResource` is registered with `enableSelector: true`. It is not a vague global CRUD singleton; it is a selector-backed owner. `ModelResource(training-student:student)` and `ModelResource(other-module:other-resource)` can share an implementation while owning distinct Resource contexts.
263
+
264
+ During initialization, the owner requests bootstrap information with the Resource identity and stores the resolved `resourceApi`. It then centralizes permissions, form providers, view/create/update/filter/row/page Schemas, and list/item query and mutation capabilities in the same owner.
265
+
266
+ The conceptual chain is:
267
+
268
+ ```text
269
+ $params.resource
270
+ → ModelResource(resource selector)
271
+ → bootstrap(resource)
272
+ → resourceApi
273
+ → schemas / permissions / forms / queries / mutations
274
+ ```
275
+
276
+ This has two practical benefits:
277
+
278
+ - a page does not need to copy the same API path, Schema-loading rule, permission lookup, and cache-invalidation policy into multiple Controllers;
279
+ - a custom operation for the same Resource can be a thin semantic facade that reuses the existing Resource owner instead of creating a competing query-cache owner.
280
+
281
+ For example, a `training-student` frontend Model can initialize the generic owner with `training-student:student`, then add semantic entry points for business actions such as `summary(id)` or `deleteForce(id)` while reusing that owner’s item query, mutation, and invalidation boundary.
282
+
283
+ One more distinction matters: a call-site value such as `['select', ...]` or `['item', id, action]` is only a logical query key. The effective cache identity also incorporates Model Bean identity and selector. A short query key is therefore not an address that is globally unique across the application. [Model Resource Internals Deep Dive](https://docs.cabloy.com/frontend/model-resource-internals-deep-dive) and [Model State Guide](https://docs.cabloy.com/frontend/model-state-guide) explain this owner/state identity layer.
284
+
285
+ ## Coordinate seven: Schema metadata selects concrete UI capabilities
286
+
287
+ A generic Resource Page stays deliberately thin: it loads the current Resource Schema, reads `schemaRow?.rest?.blocks`, and renders what the block metadata specifies. The page shell owns the question, “what is the current context?” Schema and metadata answer, “which blocks should this Resource compose in this scene?”
288
+
289
+ Where does `schemaRow?.rest?.blocks` come from? It is not an array assembled ad hoc by a frontend page. For the list page, the current Student sample defines it in the **list-row DTO** through `@Dto({ blocks })`:
290
+
291
+ ```tsx
292
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
293
+
294
+ import { $Dto } from 'vona-module-a-orm';
295
+ import { Dto } from 'vona-module-a-web';
296
+ import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
297
+
298
+ import { ModelStudent } from '../model/student.ts';
299
+
300
+ @Dto<IDecoratorDtoOptions>({
301
+ blocks: [
302
+ ZovaRender.block('basic-page:blockPage', {
303
+ blocks: [
304
+ ZovaRender.block('basic-page:blockFilter', {
305
+ formFieldLayout: { inline: true },
306
+ // The full sample also declares the filter form layout here.
307
+ }),
308
+ ZovaRender.block('basic-page:blockToolbarBulk', {
309
+ actions: [ZovaRender.tableActionBulk('basic-table:actionCreate')],
310
+ }),
311
+ ZovaRender.block('basic-page:blockTable'),
312
+ ZovaRender.block('basic-page:blockPager'),
313
+ ],
314
+ }),
315
+ ],
316
+ })
317
+ export class DtoStudentSelectResItem extends $Dto.get(() => ModelStudent) {
318
+ // List-row fields and each field’s ZovaRender.* metadata.
319
+ }
320
+ ```
321
+
322
+ This code is deliberately abbreviated. It retains the important structure: the root `basic-page:blockPage` composes registered frontend block resources for filtering, bulk toolbar actions, a table, and a pager. It does not mean every DTO should own these blocks, nor that the frontend implementations of those blocks live in Vona. The DTO declares, in backend-generated contract metadata, which rendering capabilities the current Resource list page should select.
323
+
324
+ The full chain that explains `blocks` is:
325
+
326
+ ```text
327
+ DtoStudentSelectResItem’s @Dto({ blocks })
328
+ → Vona merges blocks into the DTO OpenAPI metadata as rest.blocks
329
+ → the GET select response’s data.list.items references the row DTO Schema
330
+ → ModelResource.apiSchemasSelect.row resolves as schemaRow
331
+ → schemaRow?.rest?.blocks
332
+ → ControllerPageResource calls ZovaJsx.render(...) for each block
333
+ ```
334
+
335
+ In other words, `schemaRow` is the current select-response row Schema, and `rest.blocks` is the page-composition declaration attached to that Schema. `basic-page:blockTable` in `ZovaRender.block('basic-page:blockTable')` is another module-qualified render-resource identity, resolved by an implementation registered on the Zova side. The backend selects it; the frontend executes it. Neither side directly calls the other side’s objects across processes.
336
+
337
+ Cabloy resource addressing therefore does not stop at an API. Table cells, form fields, image scenes, and Behaviors can also be selected through module-qualified, scene-aware frontend resource identities. Field metadata can, for example, refer to `training-student:formFieldLevel`, which a registered frontend capability resolves and renders.
338
+
339
+ This does not mean backend code executes frontend components. More precisely, backend contracts or metadata can declare which frontend rendering resource should be selected at a point; the frontend still owns the renderer implementation and runtime. Frontend-owned facts such as routes, components, icons, table cells, and form fields also have a reverse contract handoff: refresh the frontend metadata/build output first, then let Vona consume the synchronized local dependency result. [Frontend Metadata Back to Backend](https://docs.cabloy.com/fullstack/frontend-metadata-to-backend) describes that reverse chain.
340
+
341
+ The two directions are distinct:
342
+
343
+ ```text
344
+ Forward: Vona Controller / DTO / Entity
345
+ → OpenAPI
346
+ → Zova SDK / Schema / API consumers
347
+
348
+ Reverse: Zova route / component / renderer / metadata
349
+ → frontend metadata or build output
350
+ → Vona-side metadata, tooling, and type consumers
351
+ ```
352
+
353
+ Together they support full-stack collaboration, but neither means that saving arbitrary source on one side automatically teaches the other side everything. Each chain has its own source of truth, generation step, shared handoff, and verification points.
354
+
355
+ ## IoC’s actual position on this map
356
+
357
+ Saying Cabloy is “more than IoC” does not diminish IoC. On the contrary, IoC is the runtime foundation that lets many of these coordinates work:
358
+
359
+ - a Bean’s container scope determines lifecycle and sharing boundaries;
360
+ - `@Use` and `beanFullName` support explicit, resolvable collaboration;
361
+ - Scope lets everyday business code access capabilities through a module-resource facade;
362
+ - parameterized injection lets generic `ModelResource` be reused with the current Resource selector;
363
+ - lifecycle and Model query/cache mechanisms turn “a resource was found” into “this owner is responsible for its state.”
364
+
365
+ But treating this only as convenient dependency injection misses the larger collaboration structure. Business domains and modules assign capabilities an owner first; Bean/Scope gives runtime capabilities a resolution boundary; Resource and OpenAPI project a data contract for transport; route parameters bring context into a page; selectors and effective query keys isolate state to the current Resource.
366
+
367
+ > IoC makes a capability obtainable. Resource addressing makes that capability retain its business meaning after it crosses modules, contracts, routes, state, and rendering.
368
+
369
+ ## When this is useful—and when it should not be forced
370
+
371
+ A multi-layer addressing system has a learning cost. Developers need to distinguish suites, modules, Beans, scenes, Resources, routes, selectors, Schemas, and generated artifacts. When debugging, they must begin from the correct coordinate instead of only searching for a component file.
372
+
373
+ It is usually most valuable for systems that evolve over time, have many modules or consumers, or need a clear contract loop:
374
+
375
+ | Situation | Prefer | Why |
376
+ | ------------------------------------------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------- |
377
+ | One-off page-local UI state | Page/controller-local state | There is no need to introduce reusable Resource semantics. |
378
+ | Reusable asynchronous, persistent, or cross-page state | Model Bean | The state needs an explicit identity, lifecycle, and cache/persistence boundary. |
379
+ | An Admin-style entity with Schemas, permissions, forms, and list/item lifecycle | Existing `ModelResource` or a thin facade | Reuse one Resource owner and a unified invalidation policy. |
380
+ | A custom operation on the same Resource | A semantic facade on the existing owner | Avoid competing request, state, and cache owners. |
381
+ | A distinct Web self-service experience | Dedicated API/DTOs, Model, and page state | One persisted Resource does not require one frontend experience. |
382
+ | A cross-cutting rule around an existing rendering target | Behavior | This is a rendering-boundary concern, not business Resource ownership. |
383
+
384
+ The final two rows are especially important. One business Resource can share a domain and persistence boundary between Admin and Web while using different API/DTO contracts, server-side scopes, state owners, and page architecture. Good resource addressing does not force everything into one generic CRUD page. It lets each boundary state clearly who it serves.
385
+
386
+ ## Trace one Resource with seven questions
387
+
388
+ To validate this mental model in an existing project, choose any registered Resource and follow it through these questions:
389
+
390
+ 1. Which suite/module owns it?
391
+ 2. What is its business Resource identity?
392
+ 3. Which Controller/DTO/Entity brings it into the backend contract?
393
+ 4. Which menu, route name, and parameters bring it into a page?
394
+ 5. Which Bean/Model owner receives it with which selector?
395
+ 6. After bootstrap, where do `resourceApi`, Schemas, permissions, and render metadata come from?
396
+ 7. Should this change follow the forward chain, the reverse chain, or first investigate generated/local dependency drift?
397
+
398
+ The point is not to memorize more names. It is to break “why does this page work?” into a sequence of verifiable resolutions. Instead of asking only, “where is this component?”, you can ask: **what is this Resource’s business identity, how is it mapped at this layer, and who owns its state and meaning?**
399
+
400
+ ## Conclusion
401
+
402
+ Cabloy does not rule every layer with one global ID. A more accurate description is that it uses the module as an important naming anchor and connects multiple address spaces—suite/module ownership, Bean scenes, Scope, business Resources, OpenAPI, route parameters, Model selectors, query caches, and render metadata—into a traceable full-stack chain.
403
+
404
+ IoC is one runtime foundation of that chain, but not the whole chain. The engineering benefit is that a business capability can cross backend and frontend, generated artifacts, and distinct runtimes without degrading into scattered URLs, repeated imports, hand-written requests, and disconnected state. Each layer retains its own responsibility and address while still mapping to the same business meaning.
405
+
406
+ ## Further reading
407
+
408
+ ### Concepts and workflows
409
+
410
+ - [Cabloy: Suites and Modules](https://docs.cabloy.com/fullstack/suites-and-modules)
411
+ - [Cabloy: Vona Backend Foundation](https://docs.cabloy.com/backend/foundation)
412
+ - [Cabloy: Zova IoC and Beans](https://docs.cabloy.com/frontend/ioc-and-beans)
413
+ - [Cabloy: Zova Module Scope](https://docs.cabloy.com/frontend/module-scope)
414
+ - [Cabloy: Backend OpenAPI to Frontend SDK](https://docs.cabloy.com/fullstack/openapi-to-sdk)
415
+ - [Cabloy: Frontend Metadata Back to Backend](https://docs.cabloy.com/fullstack/frontend-metadata-to-backend)
416
+ - [Cabloy: Model Resource Internals Deep Dive](https://docs.cabloy.com/frontend/model-resource-internals-deep-dive)
417
+
418
+ ### Source samples verified for this article
419
+
420
+ The implementation-level statements in this article were verified against Cabloy Basic revision [`e8994f63dfffc7be2657cc4c7cb6687a89b63dec`](https://github.com/cabloy/cabloy/tree/e8994f63dfffc7be2657cc4c7cb6687a89b63dec).
421
+
422
+ - [Student Resource Controller](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/vona/src/suite/a-training/modules/training-student/src/controller/student.ts)
423
+ - [Student Entity field-contract sample](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx)
424
+ - [Student SSR menu](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/vona/src/suite/a-training/modules/training-student/src/bean/ssrMenu.student.ts)
425
+ - [Vona Resource-to-route mapping](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/bean.ts)
426
+ - [Generic Resource routes](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/routes.ts)
427
+ - [Generic Resource page controller](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/resource/controller.tsx)
428
+ - [ModelResource owner](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts)
429
+ - [Student select-row DTO blocks](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx)
430
+ - [Vona DTO blocks to OpenAPI metadata bridge](https://github.com/cabloy/cabloy/blob/e8994f63dfffc7be2657cc4c7cb6687a89b63dec/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/bean.ts)