@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
@@ -1,216 +1,91 @@
1
1
  ---
2
+
2
3
  name: hai-deploy
3
- description: 使用 @h-ai/deploy 进行自动化部署:Vercel 部署 + 基础设施开通(Neon/Upstash/R2/Resend/Aliyun);当需求涉及应用部署、环境配置、凭证管理或云服务开通时使用。
4
+ description: "构建并发布或交付已有镜像:完整离线包、按服务更新、SSH 密钥/密码与跨平台手工部署、失败恢复;也支持 Vercel prebuilt。"
4
5
  ---
5
6
 
6
7
  # hai-deploy
7
8
 
8
- > `@h-ai/deploy` 提供自动化部署能力,将 SvelteKit 应用部署到 Vercel,并自动开通 PostgreSQL (Neon)、Redis (Upstash)、S3 (Cloudflare R2)、邮件 (Resend)、短信 (阿里云) 等基础设施服务。
9
-
10
- ---
11
-
12
- ## 运行环境
13
-
14
- > ⚠️ **Node.js CLI / 服务端模块。** 通过 `hai deploy` CLI 命令或在 Node.js 脚本中使用。
15
-
16
- ---
17
-
18
- ## 适用场景
9
+ 交付角色统一为 `serv`(独立 API 后端)、`web`(静态或 SSR 浏览器站点)、`app`(Android/iOS 手机安装包)、`desktop`(桌面安装包)。Fullstack 容器为 serv + 可选 web,API 为 serv,admin/website/h5/mobile-app 的浏览器镜像为 web;原生 app/desktop 不作为服务器 Compose 服务。`--images` 与 `--services` 使用 serv/web,`--target app` 与 `--target desktop` 生成原生包。API workspace 的服务目录为 `apps/<项目>-serv`。镜像与容器共用工程根 `package.json.name` 的归一化身份(去 scope、转小写、非法字符合并为连字符);名称缺失或无效时报错,不回退目录名。镜像为 `localhost/hai-<项目>-<角色>:<buildId>`,容器为 `hai-<项目>-<环境>-<角色>`,镜像可跨环境复用。
19
10
 
20
- - 一键部署 SvelteKit 应用到 Vercel
21
- - 自动开通 PostgreSQL、Redis、S3 等云服务
22
- - 管理部署凭证(~/.hai/credentials.yml)
23
- - 扫描应用依赖,自动检测所需服务
24
- - CLI 部署流程(`hai deploy`)
11
+ ## 能力契约
25
12
 
26
- ---
13
+ | 项目 | 契约 |
14
+ | --- | --- |
15
+ | 能力 | 配置环境与中间件,交付完整离线包或发布选中服务 |
16
+ | 适用场景 | 一体化构建发布、独立打包、隔离网络手工部署、增量更新与故障排查 |
17
+ | 输入 | package.json、hai.json、运行依赖锁文件、目标环境、已有制品或明确构建要求 |
18
+ | 输出 | 含 tar、清单、配置和跨平台入口的单一交付目录与分步结果,或经过 HTTP 检查的部署结果 |
19
+ | 限制 | SDK 只消费产物;CLI --build 显式先构建。首次安装必须完整交付,packaged 不代表服务器 ready。云资源需要外网。 |
27
20
 
28
- ## 使用步骤
29
-
30
- ### 1. 配置
31
-
32
- ```yaml
33
- # config/_deploy.yml
34
- provider:
35
- type: vercel
36
- token: ${HAI_DEPLOY_VERCEL_TOKEN}
37
-
38
- services:
39
- db:
40
- provisioner: neon
41
- apiKey: ${HAI_DEPLOY_NEON_API_KEY}
42
- cache:
43
- provisioner: upstash
44
- email: ${HAI_DEPLOY_UPSTASH_EMAIL}
45
- apiKey: ${HAI_DEPLOY_UPSTASH_API_KEY}
46
- storage:
47
- provisioner: cloudflare-r2
48
- accountId: ${HAI_DEPLOY_CF_ACCOUNT_ID}
49
- apiToken: ${HAI_DEPLOY_CF_API_TOKEN}
50
- email:
51
- provisioner: resend
52
- apiKey: ${HAI_DEPLOY_RESEND_API_KEY}
53
- sms:
54
- provisioner: aliyun
55
- accessKeyId: ${HAI_DEPLOY_ALIYUN_ACCESS_KEY_ID}
56
- accessKeySecret: ${HAI_DEPLOY_ALIYUN_ACCESS_KEY_SECRET}
57
- ```
21
+ --plan 和 --inspect-remote 从 CLI 完整透传,只读失败不得退回部署。target.runtime 只表示远端配置。旧凭据用服务器本机 `hai deploy-secrets <directory> --import <private.json>` 预检,--apply 才导入;SDK importDeploymentSecrets 默认 dryRun:true,验证项目/卷/实际凭据、共享 flock、v2 状态特殊字符与原子 0600 写入,缺状态的普通部署仍拒绝。完整格式和恢复步骤见 [凭据导入](credentials.md)。
58
22
 
59
- ### 2. 初始化与关闭
23
+ ## 操作流程
60
24
 
61
- ```typescript
62
- import { deploy } from '@h-ai/deploy'
25
+ 全量与增量都须在变更前核对实际卷和后端家族。服务器 `persistent-backends` 在任何启动前保存绑定,服务移除、首次失败及恢复均保留;与 `managed-secrets.env`、数据卷成套保护和备份。不能删除或编辑账本强行认领,不把“移除 PostgreSQL 再加 MySQL”视为新环境。旧 active 只有已知家族和唯一真实服务容器的 Mounts、Config.Image 同时吻合才能补证;未知 dormant 旧卷拒绝猜测,活动卷缺失拒绝空库自愈。新 release 的 `previous-state-backends` 仅供恢复前核验旧 tuple、账本与实际卷,不回退永久记录。此私有元数据没有新增公开配置 API。
63
26
 
64
- await deploy.init({
65
- provider: { type: 'vercel', token: 'vel_xxx' },
66
- services: {
67
- db: { provisioner: 'neon', apiKey: 'neon_xxx' },
68
- },
69
- })
27
+ 受控导入 v2 可为未认领旧卷补证,但须项目/凭据组/精确卷绑定与唯一运行原容器的真实角色标签、Mounts、Image 家族完全一致;Docker/Podman namespace冲突拒绝,已知 ledger/context/daemon 冲突不覆盖。导入不创建 current,缺成功基线时必须当前 CLI 新 ID 完整全量包,完整成功后才可增量。详见[凭据导入](credentials.md),不得把导入或接管称作数据库数据恢复。
70
28
 
71
- // 使用后关闭
72
- await deploy.close()
73
- ```
29
+ 身份限制只发生在 SSH 目标 Linux 服务器执行 `apply.sh`:固定 SSH uid、本地默认 Docker context 或实际本地 Podman,以及 daemon/store;远程连接、非默认 context、显式存储覆盖拒绝。生产显式 pin `remote.runtime`;auto 因新装 Podman 换引擎时,先恢复原 runtime/用户/store。Windows/macOS 操作机用 Docker Desktop/Podman VM 构建打包再 SSH 发布不受限。有意更换 daemon、服务器或恢复/替换数据时单独迁移,不能用 uid、路径或家族相同证明数据格式兼容;主版本和 Schema 兼容仍须单独确认。
74
30
 
75
- ### 3. 扫描应用
31
+ 排错与交付按[沟通与同步维护](../hai-app-create/collaboration.md)先说明实际影响、恢复步骤和验证边界,再附脱敏错误码/traceId/日志;配置、使用文档和截图随实际部署流程同步。
76
32
 
77
- ```typescript
78
- const scanResult = await deploy.scan('./apps/my-app')
79
- if (scanResult.success) {
80
- const { appName, isSvelteKit, requiredServices } = scanResult.data
81
- }
82
- ```
33
+ 1. 读取项目 scripts、images/ 中的 Dockerfile、项目根 hai.json 的 build/deploy 与服务目录运行配置。构建与部署属于整个项目;服务目录只用于扫描运行依赖。创建默认带开发期部署工具;用户明确 --no-deploy 时不生成部署入口。构建细节见 [hai-build](../hai-build/SKILL.md)。
34
+ 2. 选择环境,验证 .env.<mode> 存在,再处理部署目标与必要中间件。SSH 支持 key/agent 或 password,缺项按说明补齐,有效完整配置直接复用;--bundle-only 在构建和中间件配置后、打包前最后询问是否添加或修改 SSH 信息,保存并用于本次和后续 target;--yes 或跳过时复用已有配置。新私有参数写 .env.<mode>.local,旧 .env.local 保留兼容回退;私钥仅引用路径,密码隐藏输入并保留原值。该按环境私有层仅由部署 SDK 加载,不改变 Core 运行规则。优先级与认证边界见 [middleware.md](middleware.md)。
35
+ 3. 先校验所选制品、版本、服务和SHA-256。--build只构建所选应用镜像;不带它时缺产物明确失败,不隐式补构建。根目录使用格式4,非根目录使用格式5及webBasePath;两者都记录appVersion、buildId、partial、hasWeb、镜像归档及显式配置的servContainerPort/webContainerPort,部分构建也保留未选镜像端口,缺省使用部署默认值。网站目录由构建进程PUBLIC_BASE_PATH确定,所有部分构建须保持一致;目录变化必须全量,健康与恢复按制品记录处理。具体步骤见[网站挂载目录](../hai-build/paths.md)。同一应用版本可重建,镜像引用区分实际内容;禁止latest与无版本镜像。
36
+ 4. 完整包自动导出实际自建中间件镜像并去重;只更新 Web 不重新打包 API/中间件。打包机需容器引擎导出中间件,服务器仅 load,禁止 pull/build。外部连接及云开通不能伪称为离线自包含服务。
37
+ 5. --services 使用目标服务器最后成功状态为基线,检查端口/拓扑及未选依赖,保留未选配置、凭据、网络和卷。脚本先按项目/服务标签仅删除选中旧容器(保留卷),再 up -d --no-deps --no-build --pull never --no-recreate 创建新容器并保留其他容器;先等待选中中间件健康,再启动 serv/Web,失败恢复同序,避免 Compose Provider 连带重建反向依赖,禁止整个项目 down。S3 可选 createBucket 在 storage.init 中检查并创建缺失桶,自建 S3 注入 HAI_STORAGE_CREATEBUCKET=true;仅更新 storage 无须应用镜像,新桶在下次应用初始化时创建。Compose 网络统一 hai-app,序列化不使用 YAML 锚点。
38
+ 6. 每次交付只生成工程根 .hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/ 一个目录,外层仅含 tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh 和 README.txt;Compose、运行环境、web.conf 和 manifest 仅在 tar 内,README 记录部署 ID。--output release.tar 生成同目录的 release-<版本>/release-<版本>.tar,不能覆盖已有交付。--bundle-only 不连接 SSH,生成带逐项说明的 deploy-target.json,只引用 passwordEnv 而不含 SSH 密码值;修改 target 仅影响本包。Windows PowerShell 5+ deploy.ps1、Linux/macOS deploy.sh 读取该文件,上传并自动解包部署;隔离服务器复制整个目录后执行 sh deploy-local.sh,自动解包再执行 apply.sh。脚本不依赖源码、Node 或 pnpm;本机运行 deploy.sh 需 sh、awk、ssh、scp。manifest.partial/selectedServices 固化模式:完整构建且无 --services 为全量;部分构建或显式 --services 为增量,必须匹配服务器成功基线。
39
+ 7. 工具预检、基线、上传、校验、镜像导入、服务更新和 HTTP 检查分别报告。失败返回非零退出码,结果文件保留失败阶段;只有检查成功才更新服务器 current。已有部署失败尝试恢复所选服务的旧容器和配置,并按旧发布端口/路径验证容器和 HTTP;result 的 recoveryStatus 为 not-needed/passed/failed/stopped。数据卷保留,已写业务数据和不兼容 Schema 迁移不回退。恢复验证失败不能表述为已回滚成功。禁止把本地打包记录当服务器成功状态。
40
+ 8. 部署及恢复全程用 Linux flock 持有固定 `.deploy.lock`;不得删除/替换文件或按时间抢锁。父进程强杀后,继承 FD 的活跃子命令仍持锁;所有持有进程退出或重启后自动释放。旧 `.deploy-lock` 目录保持原样,升级前结束旧版部署进程。强杀/断电不执行恢复 trap,缺结果文件须人工核对容器、镜像和 current 后用新包恢复,锁释放不代表副作用已回退。
83
41
 
84
- ### 4. 开通基础设施
42
+ 成功后手工回退使用**当前 CLI**、旧应用 build 制品和匹配配置,省略 `--build`、`--services` 生成新全量 ID;离线也须重新打包,不能运行旧 bundle 或旧工具绕过账本。旧制品通常只保留 serv/web 镜像,中间件仍按当前 CLI 固定版本规划,不承诺精确回退全部中间件版本、DDL 或业务数据。确认主版本、Schema、拓扑和数据兼容并准备备份,再发布和验证。
85
43
 
86
- ```typescript
87
- const provResults = await deploy.provisionAll('my-project')
88
- if (provResults.success) {
89
- for (const prov of provResults.data) {
90
- // prov.envVars 包含需要注入的环境变量
91
- }
92
- }
93
- ```
44
+ ## CLI
94
45
 
95
- ### 5. 完整部署
96
-
97
- ```typescript
98
- const result = await deploy.deployApp('./apps/my-app', {
99
- projectName: 'my-project',
100
- skipProvision: false,
101
- skipBuild: false,
102
- })
103
- if (result.success) {
104
- // result.data.url — 部署地址
105
- // result.data.deploymentId — 部署 ID
106
- // result.data.envVarsSet — 已设置的环境变量列表
107
- }
46
+ ```sh
47
+ pnpm run deploy --env prod --build
48
+ pnpm build --target docker
49
+ pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId>
50
+ pnpm run deploy --env prod --bundle-only
51
+ pnpm build --target docker --images web
52
+ pnpm run deploy --env prod --services web
108
53
  ```
109
54
 
110
- ---
111
-
112
- ## 核心 API
113
-
114
- | 方法 | 签名 | 说明 |
115
- | ---------------------- | -------------------------------------------------------------------------- | ------------ |
116
- | `deploy.init` | `(config: DeployConfigInput) => Promise<HaiResult<void>>` | 初始化模块 |
117
- | `deploy.close` | `() => Promise<void>` | 关闭模块 |
118
- | `deploy.scan` | `(appDir: string) => Promise<HaiResult<ScanResult>>` | 扫描应用 |
119
- | `deploy.provisionAll` | `(projectName: string) => Promise<HaiResult<ProvisionResult[]>>` | 开通所有服务 |
120
- | `deploy.deployApp` | `(appDir: string, options?) => Promise<HaiResult<DeployResult>>` | 完整部署 |
121
- | `deploy.config` | `DeployConfig \| null` | 当前配置 |
122
- | `deploy.isInitialized` | `boolean` | 初始化状态 |
55
+ 制品格式4和5都记录primaryService(serv/web),hasWeb表示完整工程是否包含浏览器端;格式5另记录非根目录webBasePath。只有serv + web生成同源API代理;格式1至3须重新构建。CLI的--project-name与SDK的DeployAppOptions.projectName覆盖入口已移除,旧参数明确报错,请在工程根package.json.name维护身份。迁移旧工程先同步build.images、Dockerfile及API workspace的-serv包名与引用,重新安装依赖并重建完整制品。旧部署先备份、核对项目名、卷和受管凭据,再建立完整基线。工具不自动跨项目迁移数据;完整部署仍按Compose规则清理同项目旧服务,不能仅改deploy-target.json.directory完成迁移。
123
56
 
124
- ---
125
-
126
- ## 凭证管理
127
-
128
- | 函数 | 说明 |
129
- | ---------------------------- | ------------------------------------------ |
130
- | `loadCredentials()` | 加载 ~/.hai/credentials.yml 到 process.env |
131
- | `saveCredential(key, value)` | 保存单个凭证 |
132
- | `saveCredentials(entries)` | 批量保存凭证 |
133
- | `getCredentialsPath()` | 获取凭证文件路径 |
134
-
135
- ---
136
-
137
- ## 错误码 — `HaiDeployError`
138
-
139
- | 错误码 | code | 说明 |
140
- | --------------------------------------- | ------------------ | ------------------------ |
141
- | `HaiDeployError.DEPLOY_FAILED` | `hai:deploy:001` | 部署失败(通用) |
142
- | `HaiDeployError.PROJECT_CREATE_FAILED` | `hai:deploy:002` | 平台项目创建失败 |
143
- | `HaiDeployError.BUILD_FAILED` | `hai:deploy:003` | 应用构建失败 |
144
- | `HaiDeployError.UPLOAD_FAILED` | `hai:deploy:004` | 构建产物上传失败 |
145
- | `HaiDeployError.AUTH_REQUIRED` | `hai:deploy:005` | 未认证 |
146
- | `HaiDeployError.AUTH_FAILED` | `hai:deploy:006` | 认证失败 |
147
- | `HaiDeployError.PROVISION_FAILED` | `hai:deploy:007` | 基础设施开通失败 |
148
- | `HaiDeployError.ADAPTER_MISSING` | `hai:deploy:008` | SvelteKit adapter 未安装 |
149
- | `HaiDeployError.SCAN_FAILED` | `hai:deploy:009` | 应用扫描失败 |
150
- | `HaiDeployError.ENV_VAR_FAILED` | `hai:deploy:010` | 环境变量设置失败 |
151
- | `HaiDeployError.NOT_INITIALIZED` | `hai:deploy:011` | 模块未初始化 |
152
- | `HaiDeployError.UNSUPPORTED_TYPE` | `hai:deploy:012` | 不支持的类型 |
153
- | `HaiDeployError.CONFIG_ERROR` | `hai:deploy:013` | 配置错误 |
154
- | `HaiDeployError.CREDENTIAL_ERROR` | `hai:deploy:014` | 凭证读写失败 |
155
-
156
- ---
57
+ 上传脚本先复用操作机密码;缺失或为空时直接隐藏输入并继续本次部署,输入不落盘;非交互调用明确失败且不等待。无效输入显示变量名和约束;SCP 上传期间通过 SSH 查询远端归档大小,显示已接收/总字节与百分比,成功后才显示 100%。增量部署先恢复已停止或 Compose down 的既有完整基线,复用本地镜像且不重建正在运行的容器,再检查依赖和更新选中服务;恢复失败须检查诊断,不能推进 current。
157
58
 
158
- ## CLI 命令
59
+ 成功发布后需回退业务版本时,使用保留的旧完整制品和与其匹配的配置/私有环境备份,恢复配置后执行 `pnpm run deploy --env prod --artifact-dir .hai/build/docker/<previousBuildId>`。省略 --build 和 --services,以旧制品创建新的全量交付包和部署 ID,再经历锁、校验、健康验证。不要重跑已使用的旧包、手动覆盖 current 或只改镜像 tag。发布前验证数据库迁移向后兼容或准备匹配的数据备份;保留外部服务凭据与卷身份,未知状态先检查实际服务。此路径不是自动的数据恢复命令。
159
60
 
160
- ```bash
161
- # 部署当前目录
162
- hai deploy
61
+ ## 请求访问策略
163
62
 
164
- # 部署指定应用
165
- hai deploy ./apps/admin-console
63
+ Serv/SvelteKit 后端的策略快照、只读挂载、环境覆盖、代理信任和增量保留见[请求访问配置手册](https://hai-series.github.io/hai-framework/docs/configuration/request-access/),也可读取工程交付的 `hai-core/request-access.md`;纯客户端由实际后端管理这些设置。默认快照模式通过新包更新,恢复使用原成功发布文件,不覆盖旧发布目录。需要运维文件重启加载时,先按变更方案确认流程说明启动方式和优先级变化;独立外部文件需另行备份,SDK 回滚不恢复它。
166
64
 
167
- # 跳过基础设施开通
168
- hai deploy --skip-provision
65
+ ## 自建对象存储直连
169
66
 
170
- # 跳过构建
171
- hai deploy --skip-build
67
+ S3 的内部 endpoint 与预签名 publicEndpoint 分开;后者无默认,填用户可访问的 HTTP(S) origin,不含桶名或网站目录。全栈 Web Nginx 及 SSR/API gateway 将实际桶路径原样代理至 storage,不经过 Serv,保留签名 Host/URI/query,关闭对象缓冲和签名日志。桶与网站/API 路径不能重叠;外层反向代理也须转发桶路径,不能把网站 base 加到签名 URL。跨源 CORS 在 S3 配置,私有桶保持签名授权;外部 S3 不生成本地路由,Local 不开放目录。
172
68
 
173
- # 自定义项目名
174
- hai deploy --project-name my-custom-name
175
- ```
176
-
177
- ---
178
-
179
- ## 常见模式
69
+ 自建保留 bucket/region/prefix/publicEndpoint/publicUrl/operationLog。增加 gateway 或改变这些访问配置需全量基线,增量摘要不一致在更新前拒绝;选中范围不改变完整拓扑规划。应用/Storage 增量刷新保留代理 DNS,恢复使用旧发布拓扑。验证真实 S3+Nginx 大文件、Range、PUT、匿名/篡改/过期拒绝,并核对外层日志和回滚;不能用只检查生成字符串代替网络验证。
180
70
 
181
- ### 仅部署(跳过基础设施)
71
+ ## SDK
182
72
 
183
- ```typescript
184
- await deploy.deployApp('./apps/my-app', { skipProvision: true })
185
- ```
73
+ deploy.init 后检查 HaiResult.success,deploy.deployApp 接收 artifactDir、bundleOnly、selectedServices、runtime 与 onProgress;finally 中 deploy.close。deploy.scan 和 deploy.credentials.* 不依赖 init。Vercel 只消费已有 .vercel/output,不执行源码构建,也不支持 Compose 离线/部分更新。
186
74
 
187
- ### 仅开通基础设施
75
+ 内部命令工具须显式枚举 `secrets`(包括转换后的敏感字面量),成功/失败/回调均跨块脱敏;不得向日志附加原始异常 cause。捕获默认每流末尾 1 Mi 字符,结构化消费先检查截断标志;异步输出回调按序等待并保持 pipe 背压。进度每行最多解析 512 字符,超时后确认远程执行状态。详细边界见 [middleware.md](middleware.md#命令输出)。
188
76
 
189
- ```typescript
190
- await deploy.init(config)
191
- const result = await deploy.provisionAll('my-project')
192
- // 手动使用 result.data 中的环境变量
193
- await deploy.close()
194
- ```
77
+ 超时或输入/输出失败会终止本地受管理 Job/进程组并等待核验;Windows 用系统 PowerShell/.NET 内嵌 Job,先挂起创建、分配成功才恢复,失败不降级裸进程;POSIX 后代须保留继承的进程组。`terminationTimeoutMs` 默认 10000、最大 60000 毫秒,核验失败返回 unknown。失败分支用 `getDeployCommandState(error)` 读取 localTermination 和 remoteExecution;CLI 分别显示。本地已退出不能证明 SSH 远端停止;仅新连接读到完整、ID 匹配的原子结果才确认 finished,给出结果路径/退出码。未知状态不自动重跑发布或回滚,先核对 current、步骤和实际服务。
195
78
 
196
- ### 自定义部署流程
79
+ 终态包含 credentials/recover 等真实阶段。`remoteRecovery` 透传已匹配结果的恢复状态;passed 只证明旧容器和 HTTP 通过。服务器本地健康通过并提交 current 后,SDK 还从操作机检查公开地址;此时网络/防火墙造成失败会保留 remoteStage=complete、remoteExitCode=0,不自动撤销服务器成功部署,须核对结果和外部网络。
197
80
 
198
- ```typescript
199
- import { deploy } from '@h-ai/deploy'
81
+ ## 离线交付与验证
200
82
 
201
- // Provider 通过 init 配置自动创建,不需要手动导入
202
- await deploy.init({
203
- provider: { type: 'vercel', token: 'vel_xxx' },
204
- })
83
+ Linux 预备 Docker/Podman、支持 --pull never 的 Compose(Docker Compose v2 或 podman-compose 1.6.0 及以上)、sh、tar、sha256sum、awk、curl、util-linux flock 及目录/容器权限,部署目录文件系统须支持 flock。完整 tar 包含全部自建中间件归档;目标架构须匹配。包中有私有配置,安全搬运,不提交 Git。离线构建额外准备基础镜像、Linux 依赖缓存、工具链与原生预编译包;Windows node_modules 不能替代。
205
84
 
206
- // 使用 deploy API 部署
207
- const result = await deploy.deployApp('./apps/my-app')
208
- ```
85
+ 按 [分轮验证与集中修复](../hai-app-tests/validation.md) 收集适用的 typecheck、lint、build、test、scaffold gates 和 test:deploy-gates,汇总后集中修复、再验证。实际验证无 registry 网络的首次部署、登录刷新、同版本重发、只更新 Web/API、停止/down 后增量恢复、缺密码隐藏输入、上传进度、损坏归档、缺基线、健康失败与恢复。Windows/Linux/macOS 上传入口分别执行验收;原生安装包在对应 OS 验证。测试临时工程、容器、镜像、数据和进程在 finally/teardown 清理,只清理测试拥有的资源;日志、截图和报告保留到分析和交付结束再清理。
209
86
 
210
- ---
87
+ 部署前可 hai deploy --env prod --plan,只读校验真实制品和执行范围,显示项目/环境、版本/构建、配置文件及键名、保留范围、基线要求和恢复目录;不构建、不创建凭据、不连接或改变目标。远端 current 未读取标 not-inspected;不得把计划或本地打包当真实基线成功。数据库与业务数据不随 Compose 恢复回退。
211
88
 
212
- ## 相关 Skills
89
+ 需要核对目标真实基线时加 --inspect-remote(必须配合 --plan),仅 SSH 读取 current/成功发布目录,按 verified/missing/unavailable 与真实发布 ID 报告,不写目标;不能把未检查当作成功。
213
90
 
214
- - **hai-core** — 配置加载、日志、HaiResult 类型
215
- - **hai-reldb** — 数据库(Neon PostgreSQL)
216
- - **hai-cache** — 缓存(Upstash Redis)
91
+ 资源名称取实际编排规则:containers 只列显式名称,LDAP/SMTP 等由 Compose 命名的服务见 composeManagedServices;logicalVolumes 是逻辑键,不能冒充引擎卷名。核对 keep 内部连接、跳过、局部更新与云开通配置;只读计划不创建或读取中间件凭据缓存文件。
@@ -0,0 +1,19 @@
1
+ # 旧部署凭据导入
2
+
3
+ 缺状态且已有卷时必须继续拒绝普通部署,不能删除卷或拿新随机密码替代。导入工具在目标 Linux 服务器运行,需要受支持的 Node 及同版本 CLI/deploy;常规离线部署仍无需 Node。
4
+
5
+ 先停止业务写入、排除旧部署进程,备份 DB、对象、数据卷、凭据、current 和成功发布目录。原服务保持运行用于只读认证;S3 还需要同项目且共享网络的 `hai-<projectName>-app` Node 容器。
6
+
7
+ 准备非软链接、0600 的私有 JSON:version=1,projectName 为含环境后缀但不含 hai- 前缀的部署名;credentials 只列 DB_PASSWORD / STORAGE_PASSWORD / LDAP_PASSWORD 中实际需要的组;services 列 service、kind、container、volumes。db/vecdb 对应同一 DB_PASSWORD,kind 支持 postgresql/mysql;storage 对应 s3;ldap 对应 ldap。用户名/数据库默认 hai;S3 accessKeyId/bucket/region 默认 hai-storage/hai/us-east-1;LDAP bindDn 默认 cn=admin,dc=example,dc=org。这些是受管 sidecar 固定身份,自定义账户/库/桶/region/DN 不导入,应继续作为外部中间件配置保留。MySQL app/root 必须使用同一凭据,且分别通过正确密码成功、错误密码认证拒绝的正反验证。PostgreSQL 预检需要支持 require_auth 的 libpq 16+ 客户端,连接非 loopback 容器地址并要求实际密码认证,不能用 trust 成功代替密码有效。所有值和实际旧服务核对,不从不可信旧包猜测密码。
8
+
9
+ ```sh
10
+ hai deploy-secrets /opt/hai/apps/shop-test --import /private/shop-import.json --runtime docker
11
+ # 预检核验项目标签、服务标签、实际卷和真实凭据,不写状态或锁。
12
+ hai deploy-secrets /opt/hai/apps/shop-test --import /private/shop-import.json --runtime docker --apply
13
+ ```
14
+
15
+ SDK `importDeploymentSecrets({ directory, inputFile, runtime })` 默认 dryRun:true;只有显式 false 提交。提交在固定部署 flock 内由持锁进程原子写入 v2 状态,权限0600。密码保留特殊字符和 Unicode,但拒绝空值/控制字符;十六进制只是编码,状态和备份仍须作为秘密保护。工具不停止服务、不轮换密码、不推进 current、不创建成功基线,不接受不同项目/卷或损坏状态。
16
+
17
+ 后续用当前 CLI、原项目/卷身份生成新 ID 完整包;无 current 的首次接管必须全量,不带 --services,不用部分制品,完整成功后才可增量。对于账本未认领的 db/storage/vecdb 卷,合法 v2 的项目、组、精确卷绑定须与唯一运行原容器的真实角色标签(Docker/Podman namespace均不得冲突)、Mounts、Config.Image 家族全部吻合;db/vecdb 共组不等于同角色。FORMAT1、停止容器或任一证据缺失均拒绝,已知 ledger/context/daemon 身份冲突不能用导入覆盖。
18
+
19
+ 失败时检查 error.ext.phase/state;unknown 先核对服务器状态,不能据此自动重复部署。相同输入可重复核验。中断 next 文件不作为已提交状态;确认无相关进程后只清理本次文件。状态丢失优先恢复受保护备份,或用可信旧凭据重新验证导入。核对旧 DB/S3 数据后再恢复写入;导入不恢复数据或执行格式迁移,轮换另行计划。
@@ -0,0 +1,129 @@
1
+ # 部署环境与中间件
2
+
3
+ 交付角色统一为 `serv`(独立 API 后端)、`web`(静态或 SSR 浏览器站点)、`app`(Android/iOS 手机安装包)、`desktop`(桌面安装包)。Fullstack 容器为 serv + 可选 web,API 为 serv,admin/website/h5/mobile-app 的浏览器镜像为 web;原生 app/desktop 不作为服务器 Compose 服务。`--images` 与 `--services` 使用 serv/web,`--target app` 与 `--target desktop` 生成原生包。API workspace 的服务目录为 `apps/<项目>-serv`。镜像与容器共用工程根 `package.json.name` 的归一化身份(去 scope、转小写、非法字符合并为连字符);名称缺失或无效时报错,不回退目录名。镜像为 `localhost/hai-<项目>-<角色>:<buildId>`,容器为 `hai-<项目>-<环境>-<角色>`,镜像可跨环境复用。
4
+
5
+ ## 环境先行
6
+
7
+ 自建 S3 还要区分内部 endpoint 和浏览器 publicEndpoint;后者是 HTTP(S) origin,无默认、不含桶或网站目录。全栈 Web Nginx 或 SSR/API gateway 将桶路径直接转至 storage,存储端口与控制台不直接发布。外层入口保持 Host/URI/query 并转发桶路径,精确 CORS 在实际 S3 设置。增加网关或改变自建访问配置需全量基线,应用增量仅复用原配置;外部 S3 不生成本地路由,local 不公开目录。操作与验证见 [Storage skill](../hai-storage/SKILL.md)。
8
+
9
+ 默认部署名取工程根(最近的 `hai.json` 或锁文件所在目录)的 `package.json.name`,缺失时报错,再附加显式环境后缀。例如 fullstack 工程 `hai-delivery` 扫描 `packages/hai-delivery-serv`,`--env test` 生成 `/opt/hai/apps/hai-delivery-test` 和 `bundle-hai-delivery-test-<部署ID>-<版本>.tar`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
10
+
11
+ 资源身份和制品格式沿用[构建技能](../hai-build/SKILL.md)及[网站挂载目录](../hai-build/paths.md):根目录格式4,非根目录格式5,两者都有primaryService/hasWeb;webBasePath仅格式5。旧工程同步镜像角色、Dockerfile、-serv包名与引用后重建,不手改清单。旧部署先核对项目名、卷和受管凭据,再建立完整基线;工具不跨项目迁移数据,改target目录不能完成迁移。
12
+
13
+ `hai deploy` 首先输入部署环境,或用 `hai deploy --env test` 指定。`.env.test` / `.env.prod` 必须由用户先创建;缺失时停止,不代替用户创建一个空文件继续部署。指定要部署的目录,例如 `hai deploy packages/my-app-serv --env test`,该目录必须对应 lockfile 的一个 importer;不遍历 apps/packages 或猜测 fullstack 布局。环境文件默认取当前目录(有 `.env` 时)或 lockfile 根目录,必要时传 `--env-dir`。
14
+
15
+ 构建与部署配置统一在项目根 `hai.json`:`build` 保存 images/desktop,`deploy` 保存 provider/container/services 等项目级配置。服务目录只扫描运行依赖与模块 YAML。`deploy` 支持 `${变量:回退值}` 和 `HAI_DEPLOY_*` 分层覆盖;父对象可用 JSON 整体覆盖,缺省 SSH 节点可由 Schema 已知字段补齐,不接受未知字段。高层来源父对象覆盖低层叶字段,同一来源叶字段优先。凭据不要直接写入 hai.json。构建不读取部署环境或密钥。
16
+
17
+ 公共文件沿用 `.env.example` 清单、`.env` 基础和 `.env.dev/test/prod` 环境覆盖。部署 SDK 新保存的 SSH 连接、密码、API Key 和含认证 URL 写忽略 Git 的 `.env.<mode>.local`;公共后端和地址写目标环境文件。旧 `.env.local` 保留为共享兼容回退,不猜测其环境归属、不强制迁移、不删除旧值。CLI 不打印秘密值。调用 deploy API 时显式传 `{ environment: 'test', envDir: '/workspace/app' }`,不要用调用者的 `NODE_ENV` 猜测部署目标。
18
+
19
+ 部署 SDK 的来源优先级从高到低为:
20
+
21
+ - `HAI_DEPLOY_*`:进程 > `.env.<mode>.local` > `.env.<mode>` > 旧 `.env.local` > `.env`,所选环境明确目标胜过旧全局目标。
22
+ - 普通模块:进程 > `.env.<mode>.local` > 旧 `.env.local` > `.env.<mode>` > `.env`,保留旧私有凭据优先级。
23
+
24
+ `.env.<mode>.local` 仅属于部署 SDK 的配置读取和记忆;Core 的普通应用加载规则不变,不能据此宣称 dev/start 会读取这个文件。
25
+
26
+ 交付 tar 内的 `.env.runtime` 是按上述配置生成的 Compose 运行文件,不是下次部署的配置源。`NODE_ENV` 默认按目标模式选择:test 为 test,dev/development 为 development,其余为 production;显式应用配置仍可覆盖。构建保持正式优化模式,旧包需重新生成。完整配置使用 `--env test --yes` 复用;需要保持中间件时追加 `--skip-middleware`。自建中间件的密码由服务器 `<remoteDir>/managed-secrets.env` 持久保存(权限 0600),应与数据卷一起备份。每次打包只生成首次初始化的随机候选,不依赖打包机缓存;在线 SDK、deploy.sh、deploy.ps1 和 deploy-local.sh 都在部署锁内复用服务器值,同时更新应用连接配置及中间件原生变量。交付 tar 保持不可变,只有服务器私有运行文件使用定稿值。若状态缺失而对应数据卷已存在,部署在变更服务前明确停止,须恢复服务器凭据备份;不会自动换密或删除数据。旧版本可通过显式预检和凭据导入流程迁移,缺状态的普通部署仍拒绝。
27
+
28
+ 自建或云开通的整体 `HAI_*` 配置会清除被替换的旧叶字段,例如 Redis 覆盖后不再留下 `HAI_CACHE_TYPE=memory`。全局 `~/.hai/credentials.yml` 只补缺项,不能覆盖当前环境/进程的同名键或父配置。部署先启动选中中间件,等待 PostgreSQL/MySQL/Redis/S3 健康,再启动 serv/Web;增量和失败恢复沿用此顺序,未选容器保持不变。
29
+
30
+ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,不依赖 systemd 自动调度;当前探测失败时,即使旧状态为 `healthy` 也不能放行 app 启动。
31
+
32
+ 分批启动仅在首批清理孤立容器,后续 serv/Web 启动必须保留已经就绪的中间件。
33
+
34
+ 生成时为 `.env.dev/.env.test/.env.prod` 分别生成独立的初始管理员密码和传输密钥环;环境文件随项目提交,克隆后可共享,并可通过本机私有文件或进程环境覆盖。启用 transport 的应用缺少/错误配置 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING` 时,部署在上传前指出配置来源;同一环境的所有节点可直接加载环境文件中的同一有效密钥环,也可由 Secret Manager 覆盖;不为每个节点临时生成。CLI 完成部署后提示 `HAI_ADMIN_DEFAULT_PASSWORD` 的实际来源,不打印密码,不依赖日志级别;该密码仅在首次创建管理员时生效。 离线入口也会提示服务器私有 `.env.runtime` 中的密码变量位置。
35
+
36
+ ## 识别与逐项选择
37
+
38
+ 框架 `HAI_*` 连接配置与镜像原生变量分开:PostgreSQL/MySQL/RustFS/MinIO/LDAP 的原生键必须按镜像契约命名,只写私有 `middleware-runtime.env`、只让中间件加载。不得改成镜像不识别的 HAI 前缀,也不得写回工程 `.env.<mode>` / 私有覆盖或注入应用 `.env.runtime`。应用的增量覆盖文件 `middleware.env` 只含 `HAI_*`。旧工程原生字段不自动删除,新应用环境忽略框架曾生成的已知原生键;不要批量过滤其他业务变量。
39
+
40
+ 数据库连接保存前复用所选后端的公开配置 Schema;MySQL `ssl` 仅 `false` 或严格对象,`{}` 默认验证证书链和 DNS 身份,`ca/cert/key` 为 PEM 内容且 `cert/key` 必须成对;私钥仅进入私有环境。PostgreSQL 保留其布尔值/字符串模式/对象契约。CLI 内联 `@h-ai/reldb/schemas` 与 Zod,无需为配置校验给目标应用额外安装数据库包或驱动;部署本身仍需已安装的 `@h-ai/deploy`,实际运行应用仍需其数据库依赖。
41
+
42
+ 先用 `deploy.scan(appDir, { environment, envDir })` 核对实际依赖、配置与环境值。扫描从目标 workspace 的 `pnpm-lock.yaml` importer 出发,沿 dependencies/optionalDependencies 遍历,排除 devDependencies、peerDependencies 和其他应用未被引用的依赖;workspace link 只沿运行依赖继续。pnpm 12 的工具链 YAML 文档不能混入应用图。lockfile、目标 importer 或依赖节点缺失时先执行 `pnpm install` 修复;依赖图不读取 package.json、pnpm-workspace.yaml 或项目目录布局。配置文件决定已识别模块的后端,保留的旧配置不能自行启用未依赖的模块。
43
+
44
+ `ScanResult.haiModules` 列出所有实际运行依赖中的 Hai 模块;`ScanResult.middlewares` 提供服务、后端、来源、配置路径和变量前缀;连接配置可能含凭据,不能整体记入日志。`DEPLOY_MIDDLEWARE` 是后端和连接字段的公共目录,字段名称、类型与约束须与模块 Schema 同步。
45
+
46
+ | 来源 | 后端选项 | 默认 Compose 行为 | 云自动开通 |
47
+ | ------------------------------------------ | ------------------------------------- | ------------------------------------------------------------- | ----------------------------------- |
48
+ | reldb;IAM/audit;启用 DB 日志的 scheduler | SQLite / MySQL / PostgreSQL | SQLite 数据卷;mysql / postgres 服务 | PostgreSQL → Neon |
49
+ | cache;IAM;scheduler 可选分布式锁 | memory / Redis | memory 无服务;redis 服务 | Redis → Upstash |
50
+ | storage | local / S3 | 本地数据卷;RustFS(默认)/MinIO + bucket 初始化 | S3 → Cloudflare R2 |
51
+ | vecdb | LanceDB / pgvector / Qdrant / Chroma | 本地卷或对应容器 | 自定义已有服务 |
52
+ | IAM 可选目录认证 | disabled / LDAP | 禁用无服务;OpenLDAP | 自定义已有目录 |
53
+ | Reach Provider 数组 | console / SMTP / HTTP API;阿里云 SMS | console 无服务;SMTP 用 Mailpit 捕获测试邮件;HTTP/SMS 自定义 | SMTP → Resend;SMS → 阿里云凭据接入 |
54
+
55
+ `serv` 声明 AI peer 不代表应用启用了 AI,不应因此安装 AI/ONNX/CUDA 或开通向量服务。LDAP 需要在应用安装 IAM 的可选 peer `ldapts`,并显式设置 `login.ldap=true`;安装 IAM 不代表启用了 LDAP。Reach 每个 Provider 保留独立数组索引及名称;通用 Console/HTTP API 按应用模板约定将 `name: sms` 归为短信,其他名称归为邮件服务,SMTP 和 aliyun-sms 按实际 type 分类,不能把 HTTP 回调当作 SMTP。email/sms 的 Console 均只输出日志,不实际投递。默认目录没有业务账号;Mailpit 不会对外投递生产邮件。生产应配置企业 LDAP/SMTP,或使用对应云服务。
56
+
57
+ 每项都展示当前生效后端和用途,例如 PostgreSQL,再选择:
58
+
59
+ 1. **使用默认配置**:选择后端;Compose 生成匹配容器/卷,云平台调用已支持的 Provisioner,并保存实际连接配置。MySQL、LDAP、向量库等没有云自动开通器时,明确提示改用自定义连接;不能声称已经创建云资源。Resend 需要已验证的发件域名,R2 需要已有 S3 访问密钥,阿里云短信需要签名/模板与额度。
60
+ 2. **使用自定义配置**:逐项输入所选后端的连接字段,展示字段用途与约束,校验必填项、端口、布尔和 URL;凭据用密码输入。保存配置后跳过该服务的开通与 sidecar。
61
+ 3. **保持不变**:仅在目标 `.env.<mode>` 显式声明当前后端及完整连接配置时出现;私有凭据可来自 `.env.<mode>.local`、兼容 `.env.local` 或进程。选择后不修改该项、不认证其 Provisioner、不创建或移除已有中间件容器,继续下一项。只有 `.env` 或其他环境有配置不满足此条件。
62
+
63
+ 逐项配置前提供“环境配置已完备,直接部署”。选择后跳过全部中间件提示、变量改写、云资源与 sidecar 创建,保留已有服务;仍校验已有构建产物并执行部署及健康检查。命令行使用唯一的 `--skip-middleware`,SDK 使用 `skipMiddleware`。不要因为缺少某项中间件的目标文件声明而阻止用户主动跳过。
64
+
65
+ `--yes` 用于已授权的自动化:目标环境已有完整配置时保持不变,否则使用当前后端默认配置;不支持的云后端或缺少必需凭据直接失败。自动化直接部署用 `hai deploy packages/my-app-serv --env prod --yes --skip-middleware`。跳过不作为配置完整性或连接成功的证明。
66
+
67
+ 直接部署的目标不完整时,先引导选择 SSH/Vercel。SSH 补齐主机、端口、用户名、认证方式、对应凭据、known_hosts 路径、远程目录/运行时及容器/主机端口;端口范围 1–65535。`auth: key` 使用私钥/agent,密钥路径留空使用 ssh-agent/默认密钥;`auth: password` 使用隐藏输入的密码。省略 auth 时,仅非空 password 启用密码方式,否则保持 key/agent;显式 key 忽略残留密码。密码原样保留空格、前导零,不经 YAML 类型转换;有效密码拒绝 CR/LF/NUL,UTF-8 最多 1023 字节。known_hosts 留空使用 OpenSSH 默认文件,不关闭主机键校验。
68
+
69
+ 完整有效目标自动复用,`--yes` 不重新询问;修改选中环境 `.env.<mode>.local` 的 `HAI_DEPLOY_PROVIDER` 可切换连接。新填写的目标(含地址、端口、路径、Token、密码)只保存该环境私有文件并添加 Git 忽略。`--bundle-only` 在构建和中间件配置后、打包前最后询问是否添加或修改 SSH 信息,写入同一环境私有文件,并用于本次和后续 `deploy-target.json`;`--yes` 或跳过时复用已有参数,缺项仍可在上传前填写到 target。SDK 使用 `saveDeploymentEnvironment(snapshot, variables, { private: true })` 可显式保存本机参数。禁止读取、复制或打印私钥内容。
70
+
71
+ ### Hai 模块与中间件的关系
72
+
73
+ 识别依据是运行图中的所有节点,不按应用直接依赖硬编码消费者名单。下面按当前公开依赖和功能说明;新增模块/后端时同步此表、连接目录与真实运行测试。
74
+
75
+ | 模块 | 中间件来源或外部能力 |
76
+ | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
77
+ | reldb / cache / storage / vecdb | 分别拥有关系库、缓存、对象存储、向量库连接契约 |
78
+ | iam / kit | IAM 运行依赖 audit/reldb/cache/crypto;kit 经 IAM 继承。LDAP 按 login.ldap 开关启用,Reach peer 只有另行实际依赖时进入运行图 |
79
+ | audit / payment | audit 经 reldb 持久化;Stripe payment 直接依赖先初始化的共享 reldb 保存渠道映射和幂等结果,审计可选。微信、支付宝、Stripe 是已有商户 API,沿 payment 配置接入,不生成假云服务或容器 |
80
+ | scheduler / reach | 两者实际依赖 reldb/cache;Reach 另按启用的 SMTP/HTTP/短信渠道配置 |
81
+ | ai | 实际依赖 reldb/vecdb/datapipe。LLM、图像、音频端点及模型来自 AI 配置,不能仅凭包名选择模型镜像或 CUDA;不自动创建付费厂商账号 |
82
+ | crypto / serv | crypto 的可选运行依赖按 lockfile 解析,serv 经 crypto 继承;serv 的 IAM/storage/AI peer 不作为启用证据 |
83
+ | core / datapipe / api-contract / api-client / ui / capacitor / cli / deploy | 本身没有额外专用中间件;仍沿实际运行依赖继续遍历,例如 api-client/capacitor 的 crypto 分支。UI/设备能力、部署目标/Provisioner 凭据按各自配置处理 |
84
+
85
+ S3 是协议,不是某个容器产品。默认配置时另选 RustFS/MinIO,保存到 HAI_DEPLOY_CONTAINER_S3ENGINE(rustfs | minio,默认 rustfs),应用始终写 HAI_STORAGE_TYPE=s3 或 HAI_STORAGE。自定义 AWS S3、OSS、R2 等端点不生成 sidecar。镜像使用与 storage 集成测试一致的 RustFS 官方版本和 MinIO 社区版本;存储桶初始化复用应用镜像里的 S3 SDK,无需额外 mc 镜像,必须幂等且不能吞掉失败。
86
+
87
+ AI 使用 MySQL 的首次建表需 CREATE 与 INDEX 权限,节点可并发初始化;仅明确重复索引且重查真实结构一致时继续,错误同名索引、权限和其他 DDL 故障必须阻止应用启动。DDL 不回滚,失败后检查初始化结果、逆序清理连接,再修复结构/权限重试,不能删库或吞错视为成功。
88
+
89
+ ## 连接字段
90
+
91
+ 以下是自定义向导的连接字段;完整可用项、枚举与范围仍以项目 `.env.example` 和公开 Schema 为准。变量前缀为 `HAI_DB`、`HAI_CACHE`、`HAI_STORAGE`、`HAI_VECDB`、`HAI_IAM_LDAP`;Reach 使用实际索引 `HAI_REACH_PROVIDERS_<index>`。camelCase 不拆词,例如 `bindPassword` → `BINDPASSWORD`。
92
+
93
+ | 后端 | 连接字段 |
94
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
95
+ | SQLite | database(文件路径或 `:memory:`) |
96
+ | MySQL / PostgreSQL | url(优先)、host、port(1–65535)、database、user、password、ssl |
97
+ | Redis | url(优先)、host、port、password、db、tls、keyPrefix、connectTimeout、commandTimeout |
98
+ | local / LanceDB | root / path |
99
+ | S3 | endpoint、bucket、region、accessKeyId、secretAccessKey、forcePathStyle |
100
+ | Qdrant / Chroma | url;Qdrant 可选 apiKey;Chroma apiKey 用于 Bearer 自托管网关,URL 仅支持 HTTP(S) 根端点,不提供 Cloud 契约 |
101
+ | pgvector | url(优先)或 host/port/user/password,以及 database |
102
+ | LDAP | url、bindDn、bindPassword、searchBase、searchFilter、usernameAttribute、emailAttribute、displayNameAttribute、useTls、connectTimeout |
103
+ | SMTP | host、port、secure、user、pass、from |
104
+ | HTTP API | url、method(POST / PUT)、headers(JSON)、timeout |
105
+ | 阿里云 SMS | accessKeyId、accessKeySecret、signName、endpoint |
106
+
107
+ ## 离线准备与验收
108
+
109
+ 构建与部署可分开,也可通过 pnpm run deploy --build 明确串联。构建保持环境无关;部署选择环境并只消费所选镜像。完整包自动包含 Compose 自建中间件镜像,因此导出阶段需要本地 Podman/Docker,缺镜像在打包阶段准备,不能留给隔离服务器下载。
110
+
111
+ 每次离线交付都放在单一 .hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/ 目录,外层仅含 tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh 和 README.txt;Compose、运行环境、web.conf 和 manifest 仅保存在 tar 内,README 也记录部署 ID。--output release.tar 相对命令目录生成 release-<版本>/release-<版本>.tar,禁止覆盖已有交付目录。--bundle-only 只生成交付物,不连接服务器。操作目录含 Windows deploy.ps1、Linux/macOS deploy.sh 和带逐项配置说明的 deploy-target.json;运行上传脚本前先修改并核对该 JSON,两个脚本均读取此文件。本机运行 deploy.sh 需 sh、awk、ssh、scp;sh deploy.sh 主机 [端口] [用户] 可覆盖连接地址,HAI_DEPLOY_IDENTITY_FILE 和 HAI_DEPLOY_KNOWN_HOSTS_FILE 可覆盖两脚本的私钥及指纹文件路径。隔离服务器直接复制整个目录并运行 sh deploy-local.sh,由脚本自动解包并执行部署。每步失败返回非零,结果写 result-<部署ID>.json;只有 HTTP 检查通过才更新服务器 current。
112
+
113
+ 离线 target 保存 auth 和 passwordEnv,不保存密码值;passwordEnv 默认 HAI_DEPLOY_PROVIDER_SSH_PASSWORD。优先复用操作机环境变量,Windows 也可读取用户持久环境;缺失或为空时,sh/PowerShell 入口直接隐藏输入并继续本次部署,输入不落盘。非交互模式明确失败,不挂起等待。POSIX 交互需要终端和 stty。密码仅进入本次 SSH/SCP 子进程环境,不进入参数、helper 源码、应用环境、tar、manifest 或公开 JSON。Windows 入口要求 PowerShell 5+ 和 OpenSSH,Linux/macOS 使用 sh、awk、ssh、scp,两者均不需要 Node/pnpm。target 的修改只影响本交付目录,不回写工程;新包仍从工程保存的选中环境配置生成。
114
+
115
+ manifest.json 的 partial 与 selectedServices、apply 脚本共同记录部署模式:完整构建且未指定 --services 为全量;显式 --services 或部分构建为增量。增量使用服务器成功基线保留未选服务和中间件凭据,首次安装拒绝增量包。S3 createBucket 默认 false,自建 S3 注入 HAI_STORAGE_CREATEBUCKET=true,由 storage.init 检查并创建缺失桶;仅更新 storage 不需要应用镜像,新桶在下次应用初始化时创建。Compose 网络统一 hai-app,不输出 YAML 锚点。失败恢复尝试还原容器和配置,保留数据卷,不回退已写业务数据。
116
+
117
+ 服务器需要 Linux、Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux flock、支持 flock 的持久化文件系统和容器/目录权限。部署和恢复使用固定 `.deploy.lock` 内核锁,不可删除/替换或按时间抢锁;活跃子命令继承 FD,全部持有进程退出或重启后自动释放。强杀/断电后的执行状态需核对结果文件、current 和容器,不能将锁释放当作恢复成功。完整交付包含自建服务镜像;自定义外部连接仍需准备服务、账号和网络可达性。云 Provider/Provisioner 需要外网,不能用于完全离线。
118
+
119
+ 生成 web.conf 时从目标环境解析后的 _serv.yml 读取 transport.maxPlaintextBytes,调用 crypto.resolveTransportBodyLimits 推导 client_max_body_size;默认 2129920 字节,8 MiB 明文对应 16809984 字节。请求/响应 buffering 关闭,认证头缓冲固定。SvelteKit 从 _kit.yml 自动推导 adapter-node BODY_SIZE_LIMIT。app 增量包携带代理配置;容量变化时复用现有 Web 镜像重建代理并纳入失败恢复,容量不变保留 Web 容器。容量变化须选择 app;路由/端口/其他代理策略改变仍要求全量部署。应用继续独立限制业务文件、解压和行数。自管代理调用 resolveTransportBodyLimits 获取同一预算。
120
+
121
+ 完全离线构建另需基础镜像、Linux 依赖缓存、pnpm 和匹配驱动/Node ABI/架构/libc 的原生预编译包。构建可用 --sqlite-prebuild-mirror,Podman 代理不可达可用 --no-http-proxy;不要改系统代理或让 deploy 下载编译环境。生产 HTTPS、CORS、证书、DNS 另行准备。实际断网验收登录、刷新、重启和数据持久化。
122
+
123
+ ## 命令输出
124
+
125
+ 内部 `runCommand` / `SshExecutor.exec` 先 UTF-8 解码,再对每条逻辑流跨块精确脱敏;成功 stdout/stderr、错误、onOutput 均为安全结果。`secrets` 不推断全部进程环境,调用方列出秘密及可能输出的编码/转换值;总长不超过 1 Mi UTF-16 单元,脱敏异常失败关闭且不暴露原 cause。`maxCaptureChars` 默认 1048576、最大 16777216,捕获尾部并返回 stdoutTruncated/stderrTruncated,结构化解析先拒绝截断。onOutput 支持 Promise,顺序等待并保持 pipe 背压;异常回调使执行失败。异常终止不释放未完成的秘密尾部。部署进度仅解析每行前 512 字符。超时不能证明远端工作已终止。
126
+
127
+ deadline 包括 helper 启动和输出处理。异常后 `terminationTimeoutMs` 另等待本地终止核验,默认 10000、上限 60000 毫秒。POSIX 用独立继承进程组;Windows 用隐藏且不加载 profile 的 PowerShell/.NET Job,挂起创建 → 分配成功 → 恢复,禁止 breakaway,helper/编译/分配失败拒绝执行。已脱离组的系统 daemon、现有容器和远端服务不在本地确认范围。只有受管理 Job/组无活动成员才是 confirmed;未证明为 unknown,启动前为 not-started。输入、回调和流异常同样经过此路径,已经进入的回调不能撤销,但不再交付新块。
128
+
129
+ 公开 `getDeployCommandState(result.error)` 在失败分支读取原因、本地状态、远端状态、deploymentId 和 resultFile。SSH 中断默认为远端 unknown;docker-ssh 新连接只读解析原子 `result-<ID>.json`,完整/未截断/ID 匹配才为 finished,并返回实际阶段、退出码。finished 指脚本及恢复结束,容器可以继续运行;即使终态为 0,原连接/输出失败仍保留。缺失、旧记录、损坏或重连失败保持 unknown,不自动重试写入。按 ID 核对步骤、current 和服务,再恢复。
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: hai-feedback
3
+ description: "接入 @h-ai/feedback 用户反馈、业务异步证据、Webhook、管理员处理、独立通知与离线诊断包。"
4
+ ---
5
+
6
+ # hai-feedback
7
+
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 用户低门槛反馈、有界诊断证据、私有附件、分页处理、通知和离线分析 |
13
+ | 适用场景 | 收集问题、接入反馈 UI/API、管理处理或分析自包含问题包 |
14
+ | 输入 | 已初始化 reldb/storage,Reach 仅在 reach 模式需要、feedback 配置、可信用户范围、可选用户说明 |
15
+ | 输出 | HaiResult、受理编号、独立材料/通知状态、受权证据及离线 ZIP |
16
+ | 限制 | 采集与 UI 解耦;默认不保存凭证或全量 Cookie/环境变量;页面回放不等同重新执行;不依赖通用 telemetry |
17
+
18
+ 普通业务仍使用 `transport.maxPlaintextBytes`(auto/省略为 1 MiB);Feedback 的报告受理、证据、附件及 ZIP 下载路由通过 `routePlaintextBytes` 单独声明由已校验反馈配置派生的 `maxTransportBytes`,不依赖反馈初始化/重试状态。路径中的 `*` 仅匹配一个完整路径段;宿主显式路由值优先。握手、adapter-node 与代理使用各路由最大容量,普通业务不会随材料预算扩大。HTTP 适配器为单独声明且大于 1 MiB 的材料路由保留最多 2 个槽,普通业务另有 16 个槽,完整响应/失败后释放;忙碌返回 503 / `hai:crypto:072`,不自动重放业务写入。
19
+
20
+ 宿主启动时用 `@h-ai/api-contract/feedback` 的 `resolveFeedbackBudget(已校验反馈配置)` 预计算材料路由容量,不读取未就绪反馈模块的默认 `budget`;可选反馈失败/重试不改变普通业务上限或已配置材料容量。
21
+
22
+ ## 使用路径
23
+
24
+ 1. 先初始化 core、reldb 和私有 storage。notificationMode 选择 disabled/console/reach;console 默认仅输出 metadata,摘要需 consoleContent: summary 显式启用,无邮箱或 Reach 依赖;reach 模式才要求已初始化 Provider/recipients。默认 reach,生成项目显式 console。DND 由 feedback 自己的 outbox 等待,不进入 Reach 延迟队列,也不改全局通知策略。最后 feedback.init(config, { collectEvidence? }),关闭先于依赖。
25
+ 2. 挂载 apiContract.feedback 与 createFeedbackProcedures;resolveContext 从服务端确定 scopeId、userId、permissions,不能相信客户端的租户、requestId 或 S3 key。创建者可补自己的材料,管理操作另检查 read/process/reopen/export。
26
+ 3. createFeedbackClient 的 actions 接 typed API,policy 读取 reports.policy({});prepare 后打开 FeedbackModal。getView() 提供附件 URL/证据/预算;annotate 支持 coordinateSpace: ratio,saveDraft 负责跨端保存,业务不自行解码图片或管理 Blob URL。onfileschange 接 addFiles 后刷新视图;首次包络冻结,重试编辑冲突保留输入。
27
+ 4. FeedbackModal 内材料独立滚动、操作栏常驻;FeedbackList 不重复显示标题,由宿主提供页面标题。复用 FeedbackList/FeedbackDetail,服务端分页并按需加载材料;setStatus 带 expectedVersion。处理、材料、通知状态分别展示,上传或通知失败不抹掉已受理反馈。
28
+ 5. 同一 submissionId 和证据来源/序号重试,持久化 ACK 前不释放待传材料。附件取实际 checksum,不保存公开 URL;数据库、对象存储与外部通知通道无共同事务,依靠持久任务和补偿核对。
29
+ 6. 普通界面导出只传 id,由服务端当前事务固定证据快照;只有用户显式选择历史修订时才传 evidenceRevision,不沿用列表中的陈旧修订。导出固定证据修订;getExport 仅在有效快照 pending/running 时返回 CONFLICT/409,调用方只对此状态有界轮询;failed 为 OPERATION_FAILED/500,缺失/归属不符/未完成快照过期为 NOT_FOUND/404,缺少导出权限为 FORBIDDEN/403。当前修订快照过期可重新 export。离线包包含附件/查看器/索引/checksum,开发侧不持有生产凭据。用 hai feedback summary/inspect/evidence/view 或 /bundle 入口读取,不能执行导入包自带的任意脚本。
30
+ 7. 验证正常、越权、容量、崩溃、断线、重复提交、租约接管和离线查看;明确真实 S3/SMTP 与 mock 的不同证据。
31
+ 8. errorId 按锚点 source/request/sequence 查询前后各100条日志,不以首次归属丢弃重叠窗口上下文。到期删除报告、证据、附件、历史及含快照的任务,按前缀删除孤立 attempt;只保留前缀/24小时截止的最小墓碑清扫迟到对象,完成后删除,清理失败持续重试。
32
+
33
+ 范围/用户/应用和证据关联 ID 精确匹配,不能依赖 MySQL 默认排序规则放宽相等。附件 ID 为区分大小写的有效 Unicode(1–128 字符);ZIP 路径由摘要生成,读取 manifest 中的路径,不从 ID 或名称推导。文本脱敏覆盖常见凭据键、JSON/转义 JSON、Bearer/Basic,业务专有敏感内容仍需宿主白名单与 DOM 标记。
34
+
35
+ 构建标识来自实际产物的 appVersion/buildId/commit,浏览器不能使用服务端返回的版本。CLI/base/API/fullstack 模板在编译时内联,Docker 经 build args 传入;每个目标读取自己的 package.json,同一 SSR 的 client/server 共享 buildId,无所属 Git 提交时明确 unknown。模板的 build-metadata.json 只记录这三个非敏感字段。验收需把反馈 API/ZIP 中前后端证据分别与对应产物、manifest、实际源码提交核对,不能只比较两个空值或只检查旁证文件。
36
+
37
+ annotate(id, { ...rect, mode, coordinateSpace: 'ratio' }) 直接接受 UI 的 0–1 坐标,SDK 按解码后的原图换算;省略该字段仍为像素。小数、微小、边缘、反向拖动和缩放均须验收。getView 管理预览,替换、删除和关闭时释放 URL。
38
+
39
+ 草稿由 SDK 持有并通过 annotate/addFiles 等方法更新;Svelte 保存引用时使用 `$state.raw<FeedbackDraft>()`,操作成功后从 getDraft() 刷新附件视图。不要把该草稿放入深度 `$state` 代理,避免 SDK 替换图片字节后视图继续读取代理缓存的旧 bytes。
40
+
41
+ text/plain 附件在 5 MiB 范围内全文脱敏并保留安全正文,超限原文件在读取前拒绝,脱敏后字节数也不能超限;在线上传与冻结草稿后的本地追加采用同一规则。JSON 附件和结构化证据仍遵守字段长度、深度与数量限制,不能把证据字段的截断策略用于普通日志文件。
42
+
43
+ addFiles 按批次原子加入附件:任一文件失败不改变原草稿的附件或缺失标记,也不保存半批材料;成功后合并最新草稿,保留并发批次新增且总数最多 20 项。读取期间草稿切换或首次提交已冻结则返回 CONFLICT,调用方保留待选输入并让用户重新准备,不得在界面删除后继续上传隐藏文件。
44
+
45
+ 并发 `init` 返回 `INIT_IN_PROGRESS`;`close` 等待有界截图退出后清理会话。截图期间关闭使 `prepare` 返回失败,不复活草稿。异步标注完成时若草稿已冻结、关闭、删除图片或被另一标注更新,则返回 `CONFLICT`,不改变已提交附件的字节或 checksum。
46
+
47
+ captureConsole/persistDraft/keyScreenshots 默认 false;持久化启用时由宿主提供非凭据用户/租户 persistenceKey。关键截图受 screenshot 总开关控制,maxKeyScreenshots 默认3/上限5,keyScreenshotThrottleMs 默认10000ms。data-feedback-action 标记关键操作,data-feedback-private 遮挡敏感区域,data-feedback-ignore 排除反馈界面自身。回放、普通 Cookie 白名单和持久化由产品明确启用。
48
+
49
+ 自动截图使用 html2canvas 渲染遮挡后的克隆 DOM;跨域图片、iframe/video、未就绪网络字体可能缺失。浏览器或 CSP 限制失败时标 missing 并保留手动附件入口。
50
+
51
+ 本地附件支持 PNG/JPEG/WebP、WebM/MP4、TXT/LOG、JSON、PDF、ZIP/GZ/TGZ;空 MIME 或 application/octet-stream 按受支持扩展名识别,常见别名规范化,服务端仍校验实际字节/checksum。普通输入框截图保留底色与边框,内容替换为固定遮罩字符;密码框、data-feedback-private、rr-block/rr-mask 整块遮挡。原 DOM/输入值不变,页面回放仍 maskAllInputs。验证须覆盖本地选择、实际上传、离线导出及普通/私密控件的截图像素。
52
+
53
+ ## 业务补采与 Webhook
54
+
55
+ - 用 init 的第二参数 collectEvidence({ report, signal }),直接返回或 await `{ text?, data?, attachments?: [{ id, name, contentType, bytes: Uint8Array }] }`。持久 collect 任务在受理后执行,无须进程内事件总线或另建通知队列;所有同 appId 实例必须注册相同函数。按 report.id 幂等并将 signal 传给异步 I/O;businessCollectionTimeoutMs 默认 30000ms(1–300000),关闭/超时停止等待。
56
+ - text/data 作为 server:business 来源的 business 证据,FeedbackDetail 的“业务信息”页签分页展示;成功标记入库后不重复采集;附件全部保存后在持有租约的同一事务关联,详情和离线包均可读取。失败按 maxAttempts 重试并显示 collecting/failed,管理员 retry target: collect。附件 ID 稳定且 1–100 字符,server:business: 前缀由框架保留;所有附件共用 20 项和容量预算。TXT 全文脱敏;ZIP/GZIP 不解压、执行或内部脱敏,业务须压缩前脱敏。
57
+ - webhookUrl 默认空(禁用);配置可信 HTTP(S) 目的地后独立持久 webhook 任务等待采集终态(包括失败),发送 feedback.created。notificationMode/Reach/DND 不控制 Webhook。webhookSecret 用服务端私有环境;webhookTimeoutMs 默认 10000ms(1–60000)。只接受 2xx,不跟随重定向,失败指数退避到 60s、最多 maxAttempts。
58
+ - FeedbackWebhookEvent 包含 event/eventId/createdAt/report/evidence/detailUrl?;evidence 只有修订、业务采集成功和附件元数据,无正文、存储 key 或配置凭据。首次发送冻结载荷,重试/重启复用正文及 Idempotency-Key: eventId,接收方按此持久去重;至少一次投递。旧任务的 URL 与新配置不一致会失败,不自动转投。
59
+ - 署名头 X-Hai-Feedback-Signature = sha256=HMAC-SHA256(secret, X-Hai-Feedback-Timestamp + '.' + 原始正文),时间戳为 Unix 秒;接收方验证原始字节、恒定时间比较、时间偏差并防重放。get().jobs 提供 webhook 状态/attempts/安全 lastError;FeedbackDetail.webhook 传对应任务,管理员 retry target: webhook,需要 feedback:process 权限。
60
+ - YAML/环境映射同步 HAI_FEEDBACK_BUSINESSCOLLECTIONTIMEOUTMS、HAI_FEEDBACK_WEBHOOKURL、HAI_FEEDBACK_WEBHOOKSECRET、HAI_FEEDBACK_WEBHOOKTIMEOUTMS。函数不放 YAML 或 PUBLIC_;示例见已安装模块 README 的业务证据与 Webhook 章节。
61
+
62
+ Web 不导入原生插件。原生入口分别为 @h-ai/feedback/tauri 与 /capacitor,启动时 configureFeedbackSaving(saveTauriFeedbackFile/saveCapacitorFeedbackFile),生成工程自动配置。平台适配拥有保存对话框、缓存与取消清理;业务仅调用 SDK。
63
+
64
+ ## 资源与可用性约束
65
+
66
+ - 未提交或采集完成后不进行后台补传;临时故障(网络、5xx、408、429)按 1/2/4/8/16 秒退避,连续六次失败暂停,其他 4xx 立即暂停。材料保持不变,显式 flush/prepare 恢复;禁止在页面每秒调用 flush 绕过退避。退出身份必须 await close({ discard:true }),只等待在途请求、不再补传旧材料。验收空闲、持续故障、恢复和退出期间的请求次数与身份隔离。
67
+
68
+ - `keyScreenshots` 默认 false,需显式开启自动关键截图;手动 `prepare()` 仍可截图。截图超时会传递 AbortSignal,底层尚未结束时不允许重叠截图。默认渲染最多 10000 DOM 节点,继续受画布像素预算限制。`replay:true` 的默认 `replayStart` 为 `prepare`,打开反馈时才录制;明确需要预录时配置 `replayStart: init`。关闭反馈界面调用 `pause()` 停止 DOM 回放和截图,保留轻量日志、草稿及上传;退出身份仍调用 `close({ discard:true })`。自定义 `captureScreenshot({ signal })` 应尊重取消信号。
69
+ - 反馈是可选辅助能力,启动失败须独立标记不可用/重试;不能回滚或拖垮业务模块。服务端默认按用户日累计及 scope 存储预留限制,超额为 QUOTA_EXCEEDED/429;默认值和保守预留公式见已安装 README。固定业务文件清单、ZIP 快照和创建时间,重试不能制造新对象;导出24小时过期、报告默认30天保留,专用 worker 必须持续执行清理。不要增加正常空闲或逐请求 info 日志。
70
+
71
+ ## 按需参考
72
+
73
+ - 已安装包的 README 和公开 /client、/bundle、api-contract/feedback、serv/features/feedback 类型。
74
+ - 数据库、对象存储和通知分别读取 [hai-reldb](../hai-reldb/SKILL.md)、[hai-storage](../hai-storage/SKILL.md)、[hai-reach](../hai-reach/SKILL.md)。
75
+ - 带前端的工程按其 `hai-ui` Skill 复用界面组件;纯 API 只接入服务端能力。验证遵循[分轮流程](../hai-app-tests/validation.md)。
76
+
77
+ 反馈交互:当前截图优先;FeedbackModal.oncapture 连接 captureScreenshot(id?),选择时隐藏弹窗,允许换页后补图/替换并保留输入。FeedbackForm.evidence 展开实际脱敏内容,不能把全部事件数量称作日志。onfileschange 接入后支持用户主动无声短录屏(60秒/5 MiB),视频不自动遮挡,必须支持预览/删除;停止共享、取消、超时和销毁释放流。WebM/MP4 的私有读授权、容器字节/checksum 校验、上传和离线查看须一并验证。
78
+
79
+ 参考管理台和 feedback fullstack 模板显式 replay:true;SDK 缺省仍为 false。FeedbackDetail.onreplay 必须按需取得 kind:replay 的全部分页,详情“页面回放”提供播放/定位与无记录提示;原始录屏在操作现场播放。保存反馈到本地后用 hai feedback view <zip> 查看;本地包标记尚未取得的服务端证据。环境只展示实际构建/页面与服务端 envAllowlist 非凭据键,不能臆造全量环境已采集。
80
+
81
+ 保存与退出:saveDraft 及 saveFeedbackFile 选择 Web 下载、Tauri 原生保存、Capacitor 缓存分享,取消返回 cancelled;生成原生工程配置 optional peer 插件及最小权限。createFeedbackReview(typedClient.feedback.reports) 负责全部回放分页、导出轮询及 retryReport(id) 失败任务重试;退出身份调用 review.close()、client.close({ discard: true }) 清理采集、草稿、预览和旧轮询。服务端环境只采实际 envAllowlist 非敏感值;verificationCode/otpCode 等默认脱敏,不把数目当材料正文。
82
+
83
+ 服务策略不可用时仍可本地准备/保存,明确 server-policy-unavailable;在线提交重新校验,不能以本地预算伪装服务端受理成功。onfileschange 的第二参数 removedAttachmentIds 透传 addFiles,删除与新增原子合并且按有效容量检查。
84
+
85
+ Reach 为 optional peer,console/disabled 不安装或初始化它;reach 模式须显式安装并初始化 @h-ai/reach。凭据通知只有安全 receiptId,不保存/回传 Provider messageId。