@h-ai/cli 0.1.0-alpha9 → 1.0.0-beta.2

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 (438) hide show
  1. package/README.en.md +229 -0
  2. package/README.ja.md +229 -0
  3. package/README.md +175 -113
  4. package/dist/chunk-AKV2CQZV.js +1497 -0
  5. package/dist/chunk-AKV2CQZV.js.map +1 -0
  6. package/dist/chunk-EF7WOFWZ.js +7557 -0
  7. package/dist/chunk-EF7WOFWZ.js.map +1 -0
  8. package/dist/chunk-MUHRBJSW.js +29272 -0
  9. package/dist/chunk-MUHRBJSW.js.map +1 -0
  10. package/dist/chunk-ZSDEVXZ7.js +38 -0
  11. package/dist/{chunk-2H7UOFLK.js.map → chunk-ZSDEVXZ7.js.map} +1 -1
  12. package/dist/cli-config-templates-HHFHNXBN.js +5 -0
  13. package/dist/cli-config-templates-HHFHNXBN.js.map +1 -0
  14. package/dist/cli-skill-templates-PN4FLGBC.js +5 -0
  15. package/dist/cli-skill-templates-PN4FLGBC.js.map +1 -0
  16. package/dist/index.js +4444 -554
  17. package/dist/index.js.map +1 -1
  18. package/dist/metafile-esm.json +1 -0
  19. package/dist/src-TEBHR5I5.js +5 -0
  20. package/dist/src-TEBHR5I5.js.map +1 -0
  21. package/package.json +35 -15
  22. package/templates/README.md +56 -114
  23. package/templates/apps/admin/messages/en-US.json +7 -0
  24. package/templates/apps/admin/messages/ja-JP.json +40 -0
  25. package/templates/apps/admin/messages/zh-CN.json +7 -0
  26. package/templates/apps/admin/src/routes/+layout.svelte.hbs +65 -8
  27. package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -14
  28. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +54 -22
  29. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
  30. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
  31. package/templates/apps/api/.dockerignore.hbs +25 -0
  32. package/templates/apps/api/.gitignore.hbs +22 -0
  33. package/templates/apps/api/.npmrc.hbs +1 -0
  34. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +39 -0
  35. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +41 -0
  36. package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
  37. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +28 -0
  38. package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +5 -0
  39. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +16 -0
  40. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
  41. package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
  42. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
  43. package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
  44. package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +60 -0
  45. package/templates/apps/api/apps/{{projectName}}-serv/config/_core.yml.hbs +17 -0
  46. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +54 -0
  47. package/templates/apps/api/apps/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
  48. package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +66 -0
  49. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +119 -0
  50. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
  51. package/templates/apps/api/apps/{{projectName}}-serv/src/index.ts.hbs +41 -0
  52. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +165 -0
  53. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +57 -0
  54. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +41 -0
  55. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +176 -0
  56. package/templates/apps/api/apps/{{projectName}}-serv/tsconfig.json.hbs +16 -0
  57. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +20 -0
  58. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
  59. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +113 -0
  60. package/templates/apps/api/e2e/capture-evidence.ts.hbs +23 -0
  61. package/templates/apps/api/eslint.config.js.hbs +30 -0
  62. package/templates/apps/api/hai.json.hbs +4 -0
  63. package/templates/apps/api/images/serv.Dockerfile.hbs +37 -0
  64. package/templates/apps/api/package.json.hbs +53 -0
  65. package/templates/apps/api/playwright.config.ts.hbs +67 -0
  66. package/templates/apps/api/pnpm-workspace.yaml.hbs +40 -0
  67. package/templates/apps/api/tsconfig.base.json +14 -0
  68. package/templates/apps/fullstack/.dockerignore.hbs +25 -0
  69. package/templates/apps/fullstack/.gitignore.hbs +38 -0
  70. package/templates/apps/fullstack/.npmrc.hbs +1 -0
  71. package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
  72. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +67 -0
  73. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +20 -0
  74. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +20 -0
  75. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +22 -0
  76. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +7 -0
  77. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
  78. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +7 -0
  79. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +86 -0
  80. package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
  81. package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
  82. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +59 -0
  83. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +20 -0
  84. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +8 -0
  85. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +9 -0
  86. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +19 -0
  87. package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +21 -0
  88. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +16 -0
  89. package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +23 -0
  90. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +74 -0
  91. package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
  92. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +64 -0
  93. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +20 -0
  94. package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +20 -0
  95. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +7 -0
  96. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
  97. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +7 -0
  98. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +66 -0
  99. package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
  100. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +25 -0
  101. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.css.hbs +18 -0
  102. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +8 -0
  103. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +9 -0
  104. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +20 -0
  105. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +33 -0
  106. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
  107. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +16 -0
  108. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
  109. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
  110. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
  111. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
  112. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
  113. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +91 -0
  114. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
  115. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +46 -0
  116. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +14 -0
  117. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +22 -0
  118. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +89 -0
  119. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +25 -0
  120. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
  121. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
  122. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/zh-CN.json.hbs +12 -0
  123. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/project.inlang/settings.json.hbs +17 -0
  124. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +54 -0
  125. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +20 -0
  126. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +21 -0
  127. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +7 -0
  128. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
  129. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +7 -0
  130. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +53 -0
  131. package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
  132. package/templates/apps/fullstack/apps/{{projectName}}-web/public/runtime-config.js.hbs +1 -0
  133. package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +18 -0
  134. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.css.hbs +18 -0
  135. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +8 -0
  136. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +9 -0
  137. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
  138. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +16 -0
  139. package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +23 -0
  140. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +76 -0
  141. package/templates/apps/fullstack/docs/security-configuration.md.hbs +349 -0
  142. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +988 -0
  143. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +119 -0
  144. package/templates/apps/fullstack/eslint.config.js.hbs +41 -0
  145. package/templates/apps/fullstack/hai.json.hbs +11 -0
  146. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +38 -0
  147. package/templates/apps/fullstack/images/web/19-runtime-config.envsh.hbs +5 -0
  148. package/templates/apps/fullstack/images/web/nginx.conf.hbs +24 -0
  149. package/templates/apps/fullstack/images/web/runtime-config.js.template.hbs +3 -0
  150. package/templates/apps/fullstack/images/web.Dockerfile.hbs +37 -0
  151. package/templates/apps/fullstack/package.json.hbs +61 -0
  152. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +40 -0
  153. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +30 -0
  154. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +78 -0
  155. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +134 -0
  156. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +20 -0
  157. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +35 -0
  158. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +7 -0
  159. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +23 -0
  160. package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +31 -0
  161. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsconfig.json.hbs +9 -0
  162. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +9 -0
  163. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +84 -0
  164. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_ai.yml.hbs +1 -0
  165. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +1 -0
  166. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +1 -0
  167. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +22 -0
  168. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +1 -0
  169. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_feedback.yml.hbs +1 -0
  170. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +1 -0
  171. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_payment.yml.hbs +1 -0
  172. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +60 -0
  173. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_scheduler.yml.hbs +1 -0
  174. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +64 -0
  175. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +1 -0
  176. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_vecdb.yml.hbs +1 -0
  177. package/templates/apps/fullstack/packages/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
  178. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +62 -0
  179. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +115 -0
  180. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
  181. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +40 -0
  182. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +294 -0
  183. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/audit-jobs.ts.hbs +28 -0
  184. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +50 -0
  185. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +50 -0
  186. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +106 -0
  187. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +49 -0
  188. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +34 -0
  189. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +159 -0
  190. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +73 -0
  191. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +505 -0
  192. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +72 -0
  193. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +183 -0
  194. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
  195. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +18 -0
  196. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
  197. package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +10 -0
  198. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +97 -0
  199. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +164 -0
  200. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +164 -0
  201. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +164 -0
  202. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +55 -0
  203. package/templates/apps/fullstack/packages/{{projectName}}-shared/project.inlang/settings.json.hbs +11 -0
  204. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +7 -0
  205. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +94 -0
  206. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +36 -0
  207. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +16 -0
  208. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/session-recovery.svelte.ts.hbs +4 -0
  209. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +122 -0
  210. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +90 -0
  211. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +86 -0
  212. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +94 -0
  213. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/configuration.svelte.hbs +25 -0
  214. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +157 -0
  215. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +77 -0
  216. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +44 -0
  217. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +216 -0
  218. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +12 -0
  219. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +55 -0
  220. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +614 -0
  221. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +23 -0
  222. package/templates/apps/fullstack/packages/{{projectName}}-shared/svelte.config.js.hbs +1 -0
  223. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +150 -0
  224. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +253 -0
  225. package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
  226. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
  227. package/templates/apps/fullstack/playwright.config.ts.hbs +114 -0
  228. package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +18 -0
  229. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +38 -0
  230. package/templates/apps/fullstack/tsconfig.base.json +14 -0
  231. package/templates/apps/h5/messages/en-US.json +3 -0
  232. package/templates/apps/h5/messages/ja-JP.json +40 -0
  233. package/templates/apps/h5/messages/zh-CN.json +3 -0
  234. package/templates/apps/h5/src/routes/+layout.svelte.hbs +85 -30
  235. package/templates/apps/h5/src/routes/+page.svelte.hbs +20 -8
  236. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
  237. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
  238. package/templates/apps/mobile-app/.env.hbs +3 -0
  239. package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
  240. package/templates/apps/mobile-app/index.html.hbs +14 -0
  241. package/templates/apps/mobile-app/messages/en-US.json +36 -0
  242. package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
  243. package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
  244. package/templates/apps/mobile-app/public/runtime-config.js +1 -0
  245. package/templates/apps/mobile-app/src/App.svelte.hbs +153 -0
  246. package/templates/apps/mobile-app/src/lib/api.ts.hbs +213 -0
  247. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +14 -0
  248. package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
  249. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +58 -0
  250. package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -0
  251. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +16 -0
  252. package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
  253. package/templates/apps/website/messages/en-US.json +4 -2
  254. package/templates/apps/website/messages/ja-JP.json +34 -0
  255. package/templates/apps/website/messages/zh-CN.json +4 -2
  256. package/templates/apps/website/scripts/static-website.mjs.hbs +67 -0
  257. package/templates/apps/website/src/routes/+layout.svelte.hbs +77 -26
  258. package/templates/apps/website/src/routes/+layout.ts +3 -0
  259. package/templates/apps/website/src/routes/+page.svelte.hbs +31 -12
  260. package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
  261. package/templates/apps/website/src/routes/api/health/+server.ts +3 -0
  262. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +44 -34
  263. package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
  264. package/templates/base/.dockerignore.hbs +27 -0
  265. package/templates/base/.gitignore.hbs +41 -0
  266. package/templates/base/.npmrc.hbs +1 -0
  267. package/templates/base/e2e/app.spec.ts.hbs +213 -0
  268. package/templates/base/e2e/helpers.ts +1 -1
  269. package/templates/base/eslint-rules.js +45 -0
  270. package/templates/base/eslint.config.js.hbs +34 -0
  271. package/templates/base/hai.json.hbs +4 -0
  272. package/templates/base/images/web/nginx.conf.hbs +24 -0
  273. package/templates/base/images/web.Dockerfile.hbs +72 -0
  274. package/templates/base/package.json.hbs +125 -49
  275. package/templates/base/playwright.config.ts +44 -6
  276. package/templates/base/pnpm-workspace.yaml.hbs +40 -0
  277. package/templates/base/src/app.css.hbs +40 -0
  278. package/templates/base/src/app.d.ts.hbs +14 -1
  279. package/templates/base/src/app.html.hbs +13 -0
  280. package/templates/base/src/hooks.server.ts.hbs +115 -43
  281. package/templates/base/src/lib/build-metadata.ts.hbs +7 -0
  282. package/templates/base/src/lib/server/init.ts.hbs +125 -152
  283. package/templates/base/src/lib/server/kit-config.ts.hbs +40 -0
  284. package/templates/base/src/routes/+layout.server.ts.hbs +35 -0
  285. package/templates/base/static/favicon.png +0 -0
  286. package/templates/base/svelte.config.js.hbs +84 -5
  287. package/templates/base/tests/scaffold.test.ts.hbs +102 -0
  288. package/templates/base/tsconfig.json.hbs +50 -0
  289. package/templates/base/vite.config.ts.hbs +117 -12
  290. package/templates/base/vitest.config.ts.hbs +19 -0
  291. package/templates/features/ai/routes/api/chat/+server.ts +6 -7
  292. package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +3 -17
  293. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +10 -0
  294. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +9 -96
  295. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +9 -122
  296. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +10 -0
  297. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +10 -0
  298. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +9 -96
  299. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +9 -112
  300. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +10 -0
  301. package/templates/features/iam/routes-shared/api/auth/captcha/+server.ts.hbs +4 -0
  302. package/templates/features/iam/routes-shared/api/auth/config/+server.ts +4 -0
  303. package/templates/features/iam/routes-shared/api/auth/login/+server.ts +1 -29
  304. package/templates/features/iam/routes-shared/api/auth/login/ldap/+server.ts +4 -0
  305. package/templates/features/iam/routes-shared/api/auth/login/otp/+server.ts +4 -0
  306. package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +13 -6
  307. package/templates/features/iam/routes-shared/api/auth/otp/send/+server.ts +4 -0
  308. package/templates/features/iam/routes-shared/api/auth/password/renew/+server.ts +5 -0
  309. package/templates/features/iam/routes-shared/api/auth/password-reset/confirm/+server.ts +4 -0
  310. package/templates/features/iam/routes-shared/api/auth/password-reset/request/+server.ts +4 -0
  311. package/templates/features/iam/routes-shared/api/auth/reauthenticate/+server.ts +5 -0
  312. package/templates/features/iam/routes-shared/api/auth/register/+server.ts +1 -23
  313. package/templates/features/iam/routes-shared/api/auth/session/close/+server.ts.hbs +4 -0
  314. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +10 -0
  315. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +11 -0
  316. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +11 -0
  317. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +10 -0
  318. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +25 -23
  319. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +5 -2
  320. package/templates/features/storage/routes/api/upload/+server.ts +10 -8
  321. package/templates/i18n/project.inlang/settings.json +2 -2
  322. package/templates/shared/.gitattributes +11 -0
  323. package/templates/shared/build-metadata.ts +42 -0
  324. package/templates/shared/container-runtime-config.sh +30 -0
  325. package/templates/shared/e2e-env.ts +98 -0
  326. package/templates/shared/hash-router.svelte.ts +83 -0
  327. package/templates/shared/public-base-path.mjs +19 -0
  328. package/templates/shared/run-e2e.mjs +104 -0
  329. package/templates/shared/vite-runtime-config.ts +56 -0
  330. package/templates/skills/AGENTS.md +75 -16
  331. package/templates/skills/CLAUDE.md +0 -11
  332. package/templates/skills/bridges/admin/AGENTS.md +89 -0
  333. package/templates/skills/bridges/api/AGENTS.md +83 -0
  334. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +102 -0
  335. package/templates/skills/bridges/h5/AGENTS.md +88 -0
  336. package/templates/skills/bridges/mobile-app/AGENTS.md +100 -0
  337. package/templates/skills/bridges/website/AGENTS.md +88 -0
  338. package/templates/skills/copilot-instructions.md +3 -59
  339. package/templates/skills/hai-ai/SKILL.md +44 -715
  340. package/templates/skills/hai-ai/guide.md +457 -0
  341. package/templates/skills/hai-ai/reference.md +292 -0
  342. package/templates/skills/hai-api-client/SKILL.md +26 -339
  343. package/templates/skills/hai-api-client/reference.md +180 -0
  344. package/templates/skills/hai-api-contract/SKILL.md +36 -0
  345. package/templates/skills/hai-api-contract/reference.md +280 -0
  346. package/templates/skills/hai-app-create/SKILL.md +38 -351
  347. package/templates/skills/hai-app-create/collaboration.md +52 -0
  348. package/templates/skills/hai-app-create/development.md +243 -0
  349. package/templates/skills/hai-app-create/reference.md +376 -0
  350. package/templates/skills/hai-app-review/SKILL.md +57 -126
  351. package/templates/skills/hai-app-review/differential.md +34 -0
  352. package/templates/skills/hai-app-tests/SKILL.md +34 -454
  353. package/templates/skills/hai-app-tests/reference.md +462 -0
  354. package/templates/skills/hai-app-tests/validation.md +42 -0
  355. package/templates/skills/hai-audit/SKILL.md +37 -122
  356. package/templates/skills/hai-audit/reference.md +184 -0
  357. package/templates/skills/hai-build/SKILL.md +62 -315
  358. package/templates/skills/hai-build/paths.md +30 -0
  359. package/templates/skills/hai-build/reference.md +353 -0
  360. package/templates/skills/hai-cache/SKILL.md +26 -175
  361. package/templates/skills/hai-cache/reference.md +229 -0
  362. package/templates/skills/hai-capacitor/SKILL.md +24 -364
  363. package/templates/skills/hai-capacitor/reference.md +358 -0
  364. package/templates/skills/hai-change-plan/SKILL.md +46 -0
  365. package/templates/skills/hai-ci/SKILL.md +114 -0
  366. package/templates/skills/hai-core/SKILL.md +31 -469
  367. package/templates/skills/hai-core/reference.md +557 -0
  368. package/templates/skills/hai-core/request-access.md +65 -0
  369. package/templates/skills/hai-crypto/SKILL.md +29 -180
  370. package/templates/skills/hai-crypto/reference.md +317 -0
  371. package/templates/skills/hai-datapipe/SKILL.md +24 -207
  372. package/templates/skills/hai-datapipe/reference.md +204 -0
  373. package/templates/skills/hai-deploy/SKILL.md +53 -178
  374. package/templates/skills/hai-deploy/credentials.md +19 -0
  375. package/templates/skills/hai-deploy/middleware.md +129 -0
  376. package/templates/skills/hai-feedback/SKILL.md +85 -0
  377. package/templates/skills/hai-framework-sync/SKILL.md +105 -0
  378. package/templates/skills/hai-framework-sync/sync.md +49 -0
  379. package/templates/skills/hai-iam/SKILL.md +53 -325
  380. package/templates/skills/hai-iam/reference.md +535 -0
  381. package/templates/skills/hai-kit/SKILL.md +33 -329
  382. package/templates/skills/hai-kit/reference.md +202 -0
  383. package/templates/skills/hai-payment/SKILL.md +28 -262
  384. package/templates/skills/hai-payment/reference.md +295 -0
  385. package/templates/skills/hai-pr-review/SKILL.md +41 -0
  386. package/templates/skills/hai-reach/SKILL.md +28 -300
  387. package/templates/skills/hai-reach/reference.md +363 -0
  388. package/templates/skills/hai-reldb/SKILL.md +28 -449
  389. package/templates/skills/hai-reldb/reference.md +500 -0
  390. package/templates/skills/hai-scheduler/SKILL.md +26 -174
  391. package/templates/skills/hai-scheduler/reference.md +216 -0
  392. package/templates/skills/hai-serv/SKILL.md +60 -0
  393. package/templates/skills/hai-serv/reference.md +792 -0
  394. package/templates/skills/hai-spec-implement/SKILL.md +50 -0
  395. package/templates/skills/hai-spec-implement/changes.md +67 -0
  396. package/templates/skills/hai-spec-implement/evaluation.md +18 -0
  397. package/templates/skills/hai-spec-implement/handoff.md +47 -0
  398. package/templates/skills/hai-spec-implement/templates.md +117 -0
  399. package/templates/skills/hai-spec-implement/workflow.md +56 -0
  400. package/templates/skills/hai-spec-review/SKILL.md +57 -0
  401. package/templates/skills/hai-spec-review/checklist.md +71 -0
  402. package/templates/skills/hai-storage/SKILL.md +31 -262
  403. package/templates/skills/hai-storage/reference.md +284 -0
  404. package/templates/skills/hai-ui/SKILL.md +62 -238
  405. package/templates/skills/hai-ui/guide.md +81 -0
  406. package/templates/skills/hai-ui/reference.md +705 -0
  407. package/templates/skills/hai-ui-design/SKILL.md +31 -0
  408. package/templates/skills/hai-ui-design/patterns.md +31 -0
  409. package/templates/skills/hai-ui-review/SKILL.md +32 -0
  410. package/templates/skills/hai-ui-review/checklist.md +29 -0
  411. package/templates/skills/hai-vecdb/SKILL.md +25 -267
  412. package/templates/skills/hai-vecdb/reference.md +325 -0
  413. package/templates/skills/opencode.json +0 -5
  414. package/dist/chunk-2H7UOFLK.js +0 -10
  415. package/dist/chunk-LANIDJC7.js +0 -659
  416. package/dist/chunk-LANIDJC7.js.map +0 -1
  417. package/dist/chunk-YV7WPUI6.js +0 -206
  418. package/dist/chunk-YV7WPUI6.js.map +0 -1
  419. package/dist/config-templates-S5RI2MC6.js +0 -5
  420. package/dist/config-templates-S5RI2MC6.js.map +0 -1
  421. package/dist/skill-templates-N5DU5FNX.js +0 -5
  422. package/dist/skill-templates-N5DU5FNX.js.map +0 -1
  423. package/dist/src-XJ6YXNAF.js +0 -15030
  424. package/dist/src-XJ6YXNAF.js.map +0 -1
  425. package/templates/apps/android-app/.env.hbs +0 -3
  426. package/templates/apps/android-app/messages/en-US.json +0 -24
  427. package/templates/apps/android-app/messages/zh-CN.json +0 -24
  428. package/templates/apps/android-app/src/lib/api.ts.hbs +0 -30
  429. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
  430. package/templates/apps/android-app/src/routes/+layout.ts +0 -7
  431. package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
  432. package/templates/apps/api/src/routes/+layout.svelte +0 -14
  433. package/templates/apps/api/src/routes/+page.svelte +0 -11
  434. package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
  435. package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
  436. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
  437. package/templates/base/src/app.css +0 -2
  438. package/templates/base/tsconfig.json +0 -8
@@ -0,0 +1,20 @@
1
+ import { apiContract } from '@h-ai/api-contract'
2
+ import { AppEchoInputSchema, AppEchoOutputDataSchema, AppInfoOutputDataSchema } from './app-schemas.js'
3
+
4
+ /** app 领域 API contract:路径、方法、输入输出 Schema 的单一来源。 */
5
+ export const appContract = {
6
+ info: apiContract.route({
7
+ method: 'POST',
8
+ path: '/app/info',
9
+ operationId: 'app.info',
10
+ tags: ['app'],
11
+ summary: 'Get application runtime information',
12
+ }).output(apiContract.haiResultSchema(AppInfoOutputDataSchema)),
13
+ echo: apiContract.route({
14
+ method: 'POST',
15
+ path: '/app/echo',
16
+ operationId: 'app.echo',
17
+ tags: ['app'],
18
+ summary: 'Echo a message through the generated service route',
19
+ }).input(AppEchoInputSchema).output(apiContract.haiResultSchema(AppEchoOutputDataSchema)),
20
+ }
@@ -0,0 +1,35 @@
1
+ import type { HaiResult } from '@h-ai/core'
2
+ import { z } from 'zod'
3
+
4
+ export const AppFrontendTargetSchema = z.enum(['web', 'app', 'miniapp', 'desktop'])
5
+
6
+ /** 服务信息响应数据。 */
7
+ export const AppInfoOutputDataSchema = z.object({
8
+ notice: z.string().max(200),
9
+ name: z.string(),
10
+ version: z.string(),
11
+ env: z.string(),
12
+ defaultLocale: z.string(),
13
+ supportedLocales: z.array(z.string()),
14
+ startedAt: z.string().datetime(),
15
+ frontends: z.array(AppFrontendTargetSchema),
16
+ })
17
+
18
+ /** Echo 请求体。 */
19
+ export const AppEchoInputSchema = z.object({
20
+ message: z.string().min(1).max(200),
21
+ })
22
+
23
+ /** Echo 响应数据。 */
24
+ export const AppEchoOutputDataSchema = z.object({
25
+ message: z.string(),
26
+ echoedAt: z.string().datetime(),
27
+ requestId: z.string(),
28
+ })
29
+
30
+ export type AppFrontendTarget = z.infer<typeof AppFrontendTargetSchema>
31
+ export type AppInfoOutputData = z.infer<typeof AppInfoOutputDataSchema>
32
+ export type AppInfoOutput = HaiResult<AppInfoOutputData>
33
+ export type AppEchoInput = z.infer<typeof AppEchoInputSchema>
34
+ export type AppEchoOutputData = z.infer<typeof AppEchoOutputDataSchema>
35
+ export type AppEchoOutput = HaiResult<AppEchoOutputData>
@@ -0,0 +1,7 @@
1
+ export * from './app-contract.js'
2
+ export * from './app-schemas.js'
3
+ export * from './admin-contract.js'
4
+ export * from './admin-schemas.js'
5
+ export * from './{{fullstack.contractPackageName}}.js'
6
+
7
+ // @hai-generator:contracts:exports
@@ -0,0 +1,23 @@
1
+ import { apiContract } from '@h-ai/api-contract'
2
+ import { adminContract, authContract, profileContract } from './admin-contract.js'
3
+ import { appContract } from './app-contract.js'
4
+
5
+ // @hai-generator:contracts:imports
6
+
7
+ /** 当前工程启用的前端目标。 */
8
+ export const ENABLED_FRONTENDS = {{{fullstack.selectedFrontendsJson}}} as const
9
+ export const SUPPORTED_LOCALES = [{{#each fullstack.i18n.locales}}'{{this}}'{{#unless @last}}, {{/unless}}{{/each}}] as const
10
+
11
+ /** 工程级 API contract,前端 typed client 与后端 service 共用。 */
12
+ export const {{fullstack.contractExportName}} = apiContract.create({
13
+ // @hai-generator:contracts:entries
14
+ app: appContract,
15
+ iam: { auth: authContract },
16
+ admin: adminContract,
17
+ profile: profileContract,
18
+ {{#if features.feedback}}
19
+ feedback: apiContract.feedback,
20
+ {{/if}}
21
+ })
22
+
23
+ export type FullstackContract = typeof {{fullstack.contractExportName}}
@@ -0,0 +1,31 @@
1
+ import { apiContract } from '@h-ai/api-contract'
2
+ import { describe, expect, it } from 'vitest'
3
+ import * as contracts from '../src/index.js'
4
+
5
+ describe('{{fullstack.contractPackageName}}', () => {
6
+ it('defines app contract routes', () => {
7
+ expect(contracts.{{fullstack.contractExportName}}.app).toBeDefined()
8
+ expect(contracts.appContract.info).toBeDefined()
9
+ expect(apiContract.pathOf(contracts.appContract.info)).toBe('/app/info')
10
+ })
11
+
12
+ it('validates app info payload', () => {
13
+ const result = contracts.AppInfoOutputDataSchema.safeParse({
14
+ name: '{{fullstack.servPackageName}}',
15
+ version: '0.1.0',
16
+ env: 'test',
17
+ defaultLocale: 'zh-CN',
18
+ supportedLocales: ['zh-CN', 'en-US'],
19
+ startedAt: '2026-01-01T00:00:00.000Z',
20
+ frontends: [...contracts.ENABLED_FRONTENDS],
21
+ notice: '',
22
+ })
23
+
24
+ expect(result.success).toBe(true)
25
+ })
26
+
27
+ it('validates echo input boundaries', () => {
28
+ expect(contracts.AppEchoInputSchema.safeParse({ message: 'hello' }).success).toBe(true)
29
+ expect(contracts.AppEchoInputSchema.safeParse({ message: '' }).success).toBe(false)
30
+ })
31
+ })
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "outDir": "./dist"
6
+ },
7
+ "include": ["src/**/*", "tests/**/*"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: { compilerOptions: { ignoreDeprecations: '6.0' } },
7
+ sourcemap: true,
8
+ clean: true,
9
+ })
@@ -0,0 +1,84 @@
1
+ # {{fullstack.servPackageName}}
2
+
3
+ ## 简介
4
+
5
+ 后端 API Service,基于 `@h-ai/serv` 将共享 contract 装配为最小 HTTP App 抽象,不在应用代码中直接暴露 Hono。
6
+
7
+ ## 核心功能清单
8
+
9
+ - HTTP 服务、健康检查和共享 contract 的 procedure 实现。
10
+ - 用户、角色、审计与个人设置的示例业务。
11
+ - 模块配置、加密传输与服务端权限校验。
12
+
13
+ ## 使用入门
14
+
15
+ ### 默认功能与配置
16
+
17
+ 以下是可运行示例的初始实现,角色/权限、管理流程、头像限额、分页、审计策略及部署方案均可按用户需求调整。需求与代码或模板规则不一致时,以需求为业务基线同步实现、测试与过期说明;实际框架 API 契约和服务端安全校验仍需满足。
18
+
19
+ - `config/_core.yml`:应用元信息(名称 / 版本 / 环境 / 语言),启动时由 `core.config` 加载。
20
+ - `config/_serv.yml`:服务端运行时设置(CORS 来源等)。
21
+ - `config/_db.yml` / `_cache.yml` / `_iam.yml` / `_storage.yml` / `_audit.yml` / `_reach.yml`:管理及开发通知配置,初始化前使用模块公开 Schema 验证。Reach 默认控制台 Provider,生产按注释替换为 SMTP/短信/API。
22
+ - `config/_ai.yml` / `_vecdb.yml` / `_payment.yml` / `_scheduler.yml`:保留未启用模块的完整注释示例;配置文件存在不代表模块已接入。先在本 workspace 安装对应依赖,再在 `src/server/runtime.ts` 按公开 Schema 校验、初始化并反序关闭,接入实际业务后按需取消注释。整份注释先去掉一层外层注释,可选字段继续按需开启。
23
+ - `src/index.ts`:进程入口,先 `core.init({ configDir: './config' })`,再初始化 reldb → cache → crypto → storage → reach(有配置时)→ audit → iam → scheduler(有任务时);启动失败及退出反序释放。
24
+ - 选择 AI 时自动安装 reldb/vecdb/AI,并在 reldb/cache 之后初始化 vecdb、在其余依赖之后初始化 AI;关闭时先释放 AI,最后释放 vecdb/关系库,关闭失败会返回错误并保留重试义务。生产环境必须使用共享后端,根 `.env.prod` 默认连接 Compose `db/cache/storage/vecdb`,凭据和真实 Reach Provider JSON 私有注入。
25
+ - `src/app-server.ts`:服务装配入口,挂载健康检查、OpenAPI、docs 与 procedures;应用名称 / 版本与 CORS 来源均取自上述配置。
26
+ - `src/server/procedures/app-procedures.ts`:app 领域 procedures,对应 contract 中的 `app.info` / `app.echo` 路由。
27
+ - `src/server/procedures/admin-procedures.ts`:认证、管理员用户/角色/审计管理和个人设置,使用 `.auth()` / `.permission(...)` 守卫。每个请求读取用户最新启用状态、角色和权限。
28
+ - 标准认证 procedures 复用 `@h-ai/serv/features/iam`,注册、登录方式、重置与协议由 `_iam.yml` 控制;登录、退出、修改密码追加业务审计。HTTP App 类型复用公开 `ServHttpApp`。
29
+ - `src/server/admin-service.ts`:角色分配、头像上传和审计编排,全部底层操作复用 hai 模块。初始使用 admin、audit_admin、config_admin、business_operator 和 user 五种角色,四类职责及基础成员权限由 security-roles.ts 配置;锁内重新鉴权,默认禁止管理员自删、自禁用、自降级,并补偿用户更新失败后的角色变更。业务规则可按需求替换,保留的不变量需验证并发与失败路径。
30
+ - `tests/app-server.test.ts`:真实加密 HTTP 测试,覆盖 Cookie/受信原生刷新、RBAC、旧会话权限、并发管理操作、补偿、头像安全、偏好、审计及会话失效。
31
+
32
+ CLI 已在根目录 `.env.dev/.env.test/.env.prod` 为每个环境的 admin、audit_admin、config_admin、business_operator 分别生成独立随机强密码,对应 `HAI_ADMIN_DEFAULT_PASSWORD`、`HAI_AUDIT_ADMIN_PASSWORD`、`HAI_CONFIG_ADMIN_PASSWORD`、`HAI_BUSINESS_OPERATOR_PASSWORD`。已有账号不改密或重新分配职责;未配置密码的独立职责账号不创建;`dev`/`start` 自动读取,首次登录使用用户名 `admin` 和该密码。仅在没有用户时创建管理员,不重设已有用户密码。密码不符合 `_iam.yml` 策略时,启动日志显示具体原因及错误码。环境文件随项目提交供克隆后共享;私有文件或进程变量可覆盖,`.env.example` 不含真实密码。所有业务 JSON 请求和响应强制加密;健康检查和随机路径的只读头像图片可直接访问。头像支持 PNG/JPEG/WebP,最大 512 KiB,校验内容特征和大小后由服务端生成 key,不能指定任意文件路径。
33
+
34
+ 默认 SQLite + 本地 storage + memory cache 仅适合本地开发与显式测试,管理写入仅支持单写实例:进程内保护无过期时间,共享 cache 锁定期续租,丢失锁或释放失败会记录错误。多实例读取可使用共享数据库、Redis cache 和 S3 storage,但管理写请求必须统一路由到同一写实例;仅更换 Redis 不提供任意多写副本的最后管理员原子保证。传输在所有节点共享受管版本化密钥环与 registry,不依赖会话粘性;重启加载原 ring,轮换先分发新旧版本再切 activeKeyId。Web 使用 HttpOnly refresh Cookie + 内存 access token;仅同时满足客户端标识、body 通道头与受信原生 Origin 的 App/Desktop 请求返回 refresh token body。
35
+
36
+ 业务公告配置与审计在同一事务提交,失败回滚。其他已经提交的管理修改,其补充审计记录采用最大努力策略:写入失败输出包含操作及资源的结构化错误日志,业务仍返回原操作结果,避免将已经完成的变更误报为失败;应用启动时 audit 初始化失败则停止启动。
37
+
38
+ ### 开发
39
+
40
+ 所有配置字段以模块 Schema 为准;未使用字段和替代 Provider 用注释保留。叶子环境变量只覆盖已有 YAML 路径,先取消相应键的注释,或用 `HAI_DB` / `HAI_CACHE` 等整体对象覆盖;`connectTimeout` 对应 `HAI_CACHE_CONNECTTIMEOUT`。凭据示例在根 `.env.example`,初始管理员密码和传输密钥环按环境生成到 `.env.dev/.env.test/.env.prod`;其他私有值或覆盖值保存在忽略的 `.env.local` 或部署环境。`.gitignore` 的 `**/data/` 忽略所有运行数据及 `.gitkeep`;运行时会创建目录。`crypto.init()` 无配置参数,datapipe 为纯函数,不提供虚构配置。
41
+
42
+ CLI 同时在根 `.env.dev/.env.test/.env.prod` 分别生成独立的 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING`,结构为 `{activeKeyId,keys:{id:{publicKey,privateKey}}}`,运行时不隐式生成。同一环境所有节点从环境文件加载相同 ring,也可由 Secret Manager 统一覆盖,客户端 registry 复用共享 reldb。私钥不进入普通 YAML、PUBLIC_/VITE_、日志或公开响应。轮换先分发含新旧版本的 ring,再切 activeKeyId 并滚动重建;过渡期后删除旧 ID,旧客户端 destroy 后重协商。没有 sticky session 依赖。
43
+
44
+ 自动生成的 `.env` 包含已启用模块的环境参数;YAML 显式引用相同变量并保留本地回退。使用 `start:test` / `start:prod` 加载对应环境覆盖。
45
+
46
+ - `pnpm --filter {{fullstack.servPackageName}} dev`
47
+ - `pnpm --filter {{fullstack.servPackageName}} test`
48
+
49
+ ### 容器运行
50
+
51
+ 从工程根运行 `pnpm build --target docker` 导出镜像。默认带部署工具,可运行 `pnpm run deploy --env test --build` 一次完成构建发布,或 `pnpm run deploy --env prod --bundle-only` 交付已有镜像及跨平台脚本。完整包包含自建中间件,人工部署与按服务更新见工程根 README。
52
+
53
+ - 服务镜像直接由 `@h-ai/serv` 对外监听,配置挂载点为 `/app/config`,数据目录为 `/app/data`,不包含额外转发进程。
54
+ - Web 镜像不烘焙 API 地址;启动时使用 `-e PUBLIC_API_BASE=https://api.example.com` 注入,同一镜像可部署到不同环境。未设置时 Web 默认请求自身 origin。
55
+ - YAML 配置使用 `${ENV_NAME:default}` 接收运行时环境变量;不要把密钥写入镜像。
56
+
57
+ ### IAM 认证配置
58
+
59
+ 服务端 `config/_iam.yml` 统一控制登录、注册、重置、协议与 `ui` 品牌。邮件/短信可用 `_reach.yml` 中的 Provider/标准模板或自定义发送回调。`AuthPanel` 使用安全公开配置及框架认证动作;无需在页面适配 Token、验证码倒计时和错误提示。Memory 仅用于本地开发和显式测试;生产环境即使只有一个实例,也须使用框架支持的共享数据库与 Redis,并按工程根 README 配置写入路由和传输会话。
60
+
61
+ LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise;回调第三参数 context 提供 expiresAt/idempotencyKey,发送服务按稳定键持久化去重,异常/超时为结果未知且不自动重发。协议在 Modal 显示;LoginForm/RegisterForm 提供 header/extraFields/footer,AuthPanel 透传 loginHeader/loginFields/loginFooter 和 registerHeader/registerFields/registerFooter。配置及例子见生成项目的 hai-iam/hai-ui skills。
62
+
63
+ 协议支持配置中的 userAgreementMarkdown/privacyPolicyMarkdown 正文及 URL;同主题优先 Markdown,由安全渲染器在弹窗显示。
64
+
65
+ 增强安全按 _iam.yml/_audit.yml 启用,包含账号生命周期、密码期限/复杂度、ALTCHA、失败窗口锁定、一次性邀请、首次改密、用途绑定再认证、时段/IP、闲置/绝对期限和并发会话策略。页面离开撤销默认关闭且只最佳努力。审计查询支持分类、结果、等级、排序及最近7天统计;私有备份返回 key/数量/SHA-256 回执,失败复用编号,不通过头像资源路由公开。自动备份与轻量告警复用 Scheduler/Reach;归档不是数据库原子快照,恢复在独立环境进行。
66
+
67
+ 完整契约见生成应用的 `.agents/skills/hai-iam/reference.md`。
68
+
69
+ ## 反馈现场与交付检查
70
+
71
+ feedback.init(config, { collectEvidence }) 支持等待业务 text/data 与文本/ZIP/GZIP 附件;_feedback.yml 提供业务采集超时和 Webhook URL/签名密钥/请求超时。密钥仅放服务端私有环境。Webhook 持久重试,详情展示状态并允许管理员重试。
72
+
73
+ 反馈的 console/disabled/reach 独立选择;SDK getView/ratio/saveDraft 与 createFeedbackReview 统一预览、标注、保存及轮询。退出身份清理草稿和观察器。宿主生命周期由 core.module.createRuntime 处理,框架表升级前备份停旧写入并运行各模块 dryRun 预检。
74
+
75
+ ## 开发测试
76
+
77
+ ```sh
78
+ pnpm --filter {{fullstack.servPackageName}} typecheck
79
+ pnpm --filter {{fullstack.servPackageName}} test
80
+ ```
81
+
82
+ ## 许可证
83
+
84
+ Apache-2.0
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'ai' features.ai}}}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'audit' true}}}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'cache' true}}}
@@ -0,0 +1,22 @@
1
+ # =============================================================================
2
+ # {{fullstack.servPackageName}} - 应用配置
3
+ # =============================================================================
4
+ #
5
+ # 后端服务的应用级配置,由 core.config 在启动时加载。
6
+ # 每个叶子项都可由约定式 HAI 环境变量覆盖,敏感值不要写入文件。
7
+ # =============================================================================
8
+
9
+ {{yaml 'name' fullstack.appName}}
10
+ version: 0.1.0
11
+ env: development
12
+
13
+ defaultLocale: {{fullstack.i18n.baseLocale}}
14
+ logging:
15
+ level: info
16
+ format: pretty
17
+ # context:
18
+ # service: api
19
+ redact:
20
+ - password
21
+ - token
22
+ - secret
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'db' true}}}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'feedback' features.feedback}}}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'iam' true}}}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'payment' features.payment}}}
@@ -0,0 +1,60 @@
1
+ # 开发触达示例;生产环境改为 SMTP、短信或 API Provider。
2
+ providers:
3
+ - name: email
4
+ type: console
5
+ - name: sms
6
+ type: console
7
+ # SMTP 替换 email 控制台 Provider;同名 Provider 只保留一个。
8
+ # - name: email
9
+ # type: smtp
10
+ # host: ${HAI_REACH_PROVIDERS_0_HOST:smtp.example.com}
11
+ # port: ${HAI_REACH_PROVIDERS_0_PORT:465}
12
+ # secure: true
13
+ # user: ${HAI_REACH_PROVIDERS_0_USER:}
14
+ # pass: ${HAI_REACH_PROVIDERS_0_PASS:}
15
+ # from: ${HAI_REACH_PROVIDERS_0_FROM:noreply@example.com}
16
+ # 阿里云短信替换 sms 控制台 Provider。
17
+ # - name: sms
18
+ # type: aliyun-sms
19
+ # accessKeyId: ${HAI_REACH_PROVIDERS_0_ACCESSKEYID}
20
+ # accessKeySecret: ${HAI_REACH_PROVIDERS_0_ACCESSKEYSECRET}
21
+ # signName: MyApp
22
+ # endpoint: dysmsapi.aliyuncs.com
23
+ # 自有发送服务:按需将 template.provider 改为 custom。
24
+ # - name: custom
25
+ # type: api
26
+ # url: https://notify.example.com/send
27
+ # method: POST # POST | PUT
28
+ # headers:
29
+ # Authorization: '${HAI_REACH_PROVIDERS_0_HEADERS_AUTHORIZATION}'
30
+ # timeout: 10000
31
+ # idempotent: ${HAI_REACH_PROVIDERS_0_IDEMPOTENT:false} # 仅接收端具备原子持久去重时启用;默认在途不明结果转 unknown
32
+ templates:
33
+ - name: otp_email
34
+ provider: email
35
+ subject: Verification code
36
+ body: 'Your verification code is {code}.'
37
+ - name: otp_sms
38
+ provider: sms
39
+ body: 'Your verification code is {code}.'
40
+ - name: password_reset
41
+ provider: email
42
+ subject: Password reset
43
+ body: 'Reset your password: {resetUrl}. Expires at {expiresAt}.'
44
+ - name: password_reset_sms
45
+ provider: sms
46
+ body: 'Reset your password: {resetUrl}. Expires at {expiresAt}.'
47
+
48
+ # 免打扰可选;验证码应避免 delay,以免延迟到失效后投递。
49
+ # dnd:
50
+ # enabled: false
51
+ # strategy: discard # discard | delay
52
+ # start: '22:00'
53
+ # end: '08:00'
54
+
55
+ # 延迟队列策略随每条消息保存;最多领取 5 次,指数退避 1 分钟至 1 小时。
56
+ # 超限 dead 只经可信服务端人工恢复;unknown 不允许自动重发。
57
+ queue:
58
+ maxAttempts: ${HAI_REACH_QUEUE_MAXATTEMPTS:5}
59
+ retryDelayMs: ${HAI_REACH_QUEUE_RETRYDELAYMS:60000}
60
+ maxRetryDelayMs: ${HAI_REACH_QUEUE_MAXRETRYDELAYMS:3600000}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'scheduler' features.scheduler}}}
@@ -0,0 +1,64 @@
1
+ # =============================================================================
2
+ # {{fullstack.servPackageName}} - Serv / HTTP 入口配置
3
+ # =============================================================================
4
+ #
5
+ # 业务接口路径直接写在对应 *-contract.ts;公共 HTTP 传输配置以本文件为准。
6
+ # =============================================================================
7
+
8
+ server:
9
+ host: 127.0.0.1
10
+ port: 3000
11
+
12
+ http:
13
+ # auto 仅在受管私有 Compose 代理中采用容器网段;普通宿主忽略转发头。
14
+ # 自建代理填写明确 IP/CIDR;[] 显式忽略转发头。
15
+ trustedProxies: auto
16
+ access: false
17
+ # access:
18
+ # file: ./config/security/request-access.yml
19
+ apiPrefix: /api/v1
20
+ openapi:
21
+ path: /openapi.json
22
+ docs:
23
+ path: /docs
24
+ # requireAuth: true
25
+ health:
26
+ path: /health
27
+ readyPath: /ready
28
+ rpc: false
29
+ # 内部 RPC 可选;启用时用对象替换 false,gateway-only 必须配置网关密钥。
30
+ # rpc:
31
+ # prefix: /api/rpc
32
+ # access: gateway-only # loopback | private-network | gateway-only
33
+ # gatewayHeader: X-Gateway-Key
34
+ # gatewaySecret: ${HAI_SERV_HTTP_RPC_GATEWAYSECRET}
35
+
36
+ cors:
37
+ origin: ${HAI_SERV_CORS_ORIGIN:*}
38
+ nativeOrigins: ${HAI_SERV_CORS_NATIVEORIGINS:http://localhost,https://localhost,http://tauri.localhost,https://tauri.localhost,tauri://localhost,capacitor://localhost}
39
+ credentials: ${HAI_SERV_CORS_CREDENTIALS:true}
40
+ allowedHeaders:
41
+ - Authorization
42
+ - Content-Type
43
+ - X-Request-Id
44
+ - X-Requested-With
45
+ - X-Request-Client
46
+ - X-Hai-Terminal
47
+ - X-HAI-Token-Transport
48
+ - X-Client-Id
49
+ - X-Encrypted
50
+ - X-Hai-Transport
51
+ exposedHeaders:
52
+ - X-Request-Id
53
+ - X-Encrypted
54
+ - X-Hai-Transport
55
+
56
+ transport:
57
+ # 双向业务明文 UTF-8 字节;默认 {{#if features.feedback}}auto(按反馈预算推导){{else}}1 MiB{{/if}},范围 1 KiB~64 MiB,密文容量自动推导。
58
+ {{#if features.feedback}}
59
+ maxPlaintextBytes: ${HAI_SERV_TRANSPORT_MAXPLAINTEXTBYTES:auto}
60
+ {{else}}
61
+ maxPlaintextBytes: ${HAI_SERV_TRANSPORT_MAXPLAINTEXTBYTES:1048576}
62
+ {{/if}}
63
+ keyExchangePath: /_hai/key-exchange
64
+ # excludePaths: [/health, /ready]
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'storage' true}}}
@@ -0,0 +1 @@
1
+ {{{moduleConfig 'vecdb' features.vecdb}}}
@@ -0,0 +1,62 @@
1
+ {
2
+ "engines": { "node": "^22.23.4 || ^24.22.1 || ^26.12.1" },
3
+ "name": "{{fullstack.servPackageName}}",
4
+ "type": "module",
5
+ "version": "0.1.0",
6
+ "private": true,
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "files": [
16
+ "config",
17
+ "data",
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "check": "pnpm typecheck",
24
+ "typecheck": "tsc --noEmit",
25
+ "lint": "eslint .",
26
+ "lint:fix": "eslint . --fix",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "clean": "rimraf dist .turbo",
30
+ "dev": "pnpm build && node --env-file=../../.env --env-file=../../.env.dev --env-file-if-exists=../../.env.local dist/index.js",
31
+ "start": "node --env-file=../../.env --env-file=../../.env.prod --env-file-if-exists=../../.env.local dist/index.js",
32
+ "dev:test": "pnpm build && node --env-file=../../.env --env-file=../../.env.test --env-file-if-exists=../../.env.local dist/index.js",
33
+ "dev:prod": "pnpm build && pnpm start",
34
+ "start:test": "node --env-file=../../.env --env-file=../../.env.test --env-file-if-exists=../../.env.local dist/index.js",
35
+ "start:prod": "pnpm start"
36
+ },
37
+ "dependencies": {
38
+ "pino-pretty": "{{fullstack.packageSpecifiers.pinoPretty}}",
39
+ {{#if features.ai}}
40
+ "@h-ai/ai": "{{haiPackageSpecifier}}",
41
+ {{/if}}
42
+ "@h-ai/audit": "{{haiPackageSpecifier}}",
43
+ "@h-ai/cache": "{{haiPackageSpecifier}}",
44
+ "@h-ai/core": "{{haiPackageSpecifier}}",
45
+ "@h-ai/crypto": "{{haiPackageSpecifier}}",
46
+ {{#if features.feedback}}
47
+ "@h-ai/api-contract": "{{haiPackageSpecifier}}",
48
+ "@h-ai/feedback": "{{haiPackageSpecifier}}",
49
+ {{/if}}
50
+ "@h-ai/iam": "{{haiPackageSpecifier}}",
51
+ "@h-ai/reach": "{{haiPackageSpecifier}}",
52
+ "@h-ai/reldb": "{{haiPackageSpecifier}}",
53
+ "@h-ai/scheduler": "{{haiPackageSpecifier}}",
54
+ "@h-ai/serv": "{{haiPackageSpecifier}}",
55
+ "@h-ai/storage": "{{haiPackageSpecifier}}",
56
+ {{#if features.vecdb}}
57
+ "@h-ai/vecdb": "{{haiPackageSpecifier}}",
58
+ {{/if}}
59
+ "zod": "{{fullstack.packageSpecifiers.zod}}",
60
+ "{{fullstack.contractPackageName}}": "workspace:*"
61
+ }
62
+ }
@@ -0,0 +1,115 @@
1
+ import type { CoreConfig } from '@h-ai/core'
2
+ import type { {{#if features.feedback}}CreateServContext, {{/if}}ServHttpApp } from '@h-ai/serv'
3
+ import process from 'node:process'
4
+ {{#if features.feedback}}import { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'
5
+ {{/if}}import { core } from '@h-ai/core'
6
+ import { createReldbTransportKeyStore, crypto, parseTransportServerKeyRing } from '@h-ai/crypto'
7
+ {{#if features.feedback}}
8
+ import { FeedbackConfigSchema } from '@h-ai/feedback'
9
+ {{/if}}
10
+ import { iam } from '@h-ai/iam'
11
+ import { reldb } from '@h-ai/reldb'
12
+ import { serv, ServConfigSchema } from '@h-ai/serv'
13
+ import { storage } from '@h-ai/storage'
14
+ import * as contracts from '{{fullstack.contractPackageName}}'
15
+ import { createServerProcedures } from './server/procedures/index.js'
16
+
17
+ const STARTED_AT = new Date().toISOString()
18
+
19
+ /** 创建后端 HTTP App;与 @h-ai/serv 的 createApp 返回语义保持一致。 */
20
+ export function createServerApp(): ServHttpApp {
21
+ const coreConfig = core.config.getOrThrow<CoreConfig>('core')
22
+ const servConfig = ServConfigSchema.parse(core.config.getOrThrow('serv'))
23
+ if (servConfig.transport === false)
24
+ throw new Error('Fullstack management requires transport encryption; configure scoped access.rules[].encryption: disabled for plaintext external endpoints')
25
+ const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
26
+ if (!ring.success)
27
+ throw new Error(`HAI_CRYPTO_TRANSPORT_SERVERKEYRING: ${ring.error.message} (${ring.error.code})`)
28
+ {{#if features.feedback}} // 可选反馈故障重试期间仍使用配置预算,避免缓存默认容量。
29
+ const feedbackSettings = FeedbackConfigSchema.safeParse(core.config.get('feedback'))
30
+ const feedbackBudget = resolveFeedbackBudget(feedbackSettings.success ? feedbackSettings.data : {})
31
+ {{/if}} const security = serv.createRuntimeSecurityPolicy({
32
+ environment: coreConfig.env,
33
+ corsOrigin: servConfig.cors.origin,
34
+ nativeOrigins: servConfig.cors.nativeOrigins,
35
+ })
36
+ const publicPaths = [
37
+ `${servConfig.http.apiPrefix}/assets`,
38
+ ...(servConfig.http.health ? [servConfig.http.health.path, servConfig.http.health.readyPath].filter((path): path is `/${string}` => Boolean(path)) : []),
39
+ ...(servConfig.http.openapi && security.exposeApiDocs ? [servConfig.http.openapi.path] : []),
40
+ ...(servConfig.http.docs && security.exposeApiDocs ? [servConfig.http.docs.path] : []),
41
+ ]
42
+ {{#if features.feedback}}
43
+ // 普通业务日志与反馈使用同一可信应用范围;身份仍由 IAM 验证。
44
+ const authenticatedContext = serv.buildAuthContextFactory(token => iam.auth.verifyToken(token))
45
+ const createContext: CreateServContext = async input => ({
46
+ ...await authenticatedContext(input),
47
+ scopeId: '{{projectName}}',
48
+ })
49
+ {{/if}}
50
+
51
+ return serv.createApp({
52
+ contract: contracts.{{fullstack.contractExportName}},
53
+ procedures: createServerProcedures({
54
+ app: {
55
+ name: coreConfig.name,
56
+ version: coreConfig.version,
57
+ env: coreConfig.env,
58
+ defaultLocale: coreConfig.defaultLocale,
59
+ supportedLocales: contracts.SUPPORTED_LOCALES,
60
+ startedAt: STARTED_AT,
61
+ frontends: [...contracts.ENABLED_FRONTENDS],
62
+ },
63
+ }),
64
+ iam,
65
+ {{#if features.feedback}}
66
+ createContext,
67
+ {{/if}}
68
+ refreshCookie: {
69
+ secure: security.secureRefreshCookie,
70
+ nativeTokenTransport: { isRequest: request => request.headers.get('x-hai-token-transport') === 'body'
71
+ && ['{{projectName}}-app', '{{projectName}}-desktop'].includes(request.headers.get('x-request-client') ?? '')
72
+ && security.isNativeOrigin(request.headers.get('origin') ?? '') },
73
+ },
74
+ // 管理业务默认强制双向加密;各节点复用受管服务端密钥环与共享 reldb 客户端 registry。
75
+ transport: {
76
+ ...servConfig.transport,
77
+ {{#if features.feedback}}
78
+ routePlaintextBytes: {
79
+ [`${servConfig.http.apiPrefix}/feedback/reports`]: feedbackBudget.maxTransportBytes,
80
+ [`${servConfig.http.apiPrefix}/feedback/reports/*/evidence`]: feedbackBudget.maxTransportBytes,
81
+ [`${servConfig.http.apiPrefix}/feedback/reports/*/attachments/*`]: feedbackBudget.maxTransportBytes,
82
+ [`${servConfig.http.apiPrefix}/feedback/reports/*/exports/*`]: feedbackBudget.maxTransportBytes,
83
+ ...servConfig.transport.routePlaintextBytes,
84
+ },
85
+ {{/if}}
86
+ excludePaths: [...new Set([...publicPaths, ...servConfig.transport.excludePaths])],
87
+ crypto,
88
+ serverKeyRing: ring.data,
89
+ keyStore: createReldbTransportKeyStore({ reldb, ttlSeconds: 3600 }),
90
+ },
91
+ http: {
92
+ ...servConfig.http,
93
+ openapi: security.exposeApiDocs ? servConfig.http.openapi : false,
94
+ docs: security.exposeApiDocs ? servConfig.http.docs : false,
95
+ },
96
+ middlewares: [{
97
+ middleware: serv.cors({
98
+ origin: security.allowOrigin,
99
+ credentials: servConfig.cors.credentials,
100
+ allowedHeaders: [...new Set([...servConfig.cors.allowedHeaders, 'X-Client-Id', 'X-Encrypted', 'X-Hai-Transport', 'X-Request-Client', 'X-HAI-Token-Transport', 'X-Hai-Reauthentication', 'X-Hai-Terminal'])],
101
+ exposedHeaders: [...new Set([...servConfig.cors.exposedHeaders, 'X-Encrypted', 'X-Hai-Transport'])],
102
+ }),
103
+ }, {
104
+ path: `${servConfig.http.apiPrefix}/assets/*`,
105
+ middleware: serv.storageAssets({
106
+ storage,
107
+ pathPrefix: `${servConfig.http.apiPrefix}/assets/`,
108
+ keyPattern: /^avatars\/[\w-]+\/[\w-]+\.(png|jpg|webp)$/,
109
+ allowedContentTypes: ['image/png', 'image/jpeg', 'image/webp'],
110
+ cacheControl: 'public, max-age=31536000, immutable',
111
+ crossOriginResourcePolicy: 'cross-origin',
112
+ }),
113
+ }],
114
+ })
115
+ }
@@ -0,0 +1,7 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if features.feedback}}
3
+ /** 当前应用编译时烘焙的产物身份;运行时配置不能覆盖。 */
4
+ declare const __HAI_BUILD_METADATA__: { appVersion: string, buildId: string, commit: string }
5
+
6
+ export const buildMetadata = __HAI_BUILD_METADATA__
7
+ {{/if}}
@@ -0,0 +1,40 @@
1
+ import type { CoreConfig } from '@h-ai/core'
2
+ import type { ServConfigInput } from '@h-ai/serv'
3
+ import process from 'node:process'
4
+ import { core } from '@h-ai/core'
5
+ import { serv, ServConfigSchema } from '@h-ai/serv'
6
+ import { createServerApp } from './app-server.js'
7
+ import { closeModules, initializeModules } from './server/runtime.js'
8
+
9
+ async function startServer(): Promise<void> {
10
+ // 加载配置后按依赖顺序初始化;日志设置沿用 _core.yml。
11
+ core.init({ configDir: './config' })
12
+ await initializeModules()
13
+ try {
14
+ // HOST/PORT 环境变量优先于 config/_serv.yml。
15
+ const { server } = ServConfigSchema.parse(core.config.getOrThrow<ServConfigInput>('serv'))
16
+ const app = createServerApp()
17
+ await new Promise<void>((resolve, reject) => {
18
+ const listener = serv.listen(app, {
19
+ host: server.host,
20
+ port: server.port,
21
+ onListening: (info) => {
22
+ core.logger.info('Application listening', { name: core.config.getOrThrow<CoreConfig>('core').name, host: server.host, port: info.port })
23
+ resolve()
24
+ },
25
+ onClose: closeModules,
26
+ })
27
+ listener.server.once('error', reject)
28
+ listener.server.once('listening', () => listener.server.off('error', reject))
29
+ })
30
+ }
31
+ catch (error) {
32
+ await closeModules()
33
+ throw error
34
+ }
35
+ }
36
+
37
+ void startServer().catch((error: unknown) => {
38
+ core.logger.fatal('Application startup failed', { error })
39
+ process.exitCode = 1
40
+ })