@h-ai/cli 1.0.0-beta.2 → 1.0.0-beta.21

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 (254) hide show
  1. package/README.en.md +74 -154
  2. package/README.ja.md +74 -154
  3. package/README.md +74 -154
  4. package/dist/{chunk-AKV2CQZV.js → chunk-2ZL5ORQ2.js} +316 -97
  5. package/dist/chunk-2ZL5ORQ2.js.map +1 -0
  6. package/dist/{chunk-EF7WOFWZ.js → chunk-L53P43B2.js} +1312 -163
  7. package/dist/chunk-L53P43B2.js.map +1 -0
  8. package/dist/cli-config-templates-LWMD2I6V.js +5 -0
  9. package/dist/{cli-config-templates-HHFHNXBN.js.map → cli-config-templates-LWMD2I6V.js.map} +1 -1
  10. package/dist/{cli-skill-templates-PN4FLGBC.js → cli-skill-templates-D6S2OQ6X.js} +3 -3
  11. package/dist/{cli-skill-templates-PN4FLGBC.js.map → cli-skill-templates-D6S2OQ6X.js.map} +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +30118 -3253
  14. package/dist/index.js.map +1 -1
  15. package/dist/metafile-esm.json +1 -1
  16. package/package.json +22 -18
  17. package/templates/README.md +45 -30
  18. package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -10
  19. package/templates/apps/admin/src/routes/+page.svelte.hbs +4 -4
  20. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +17 -7
  21. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +26 -6
  22. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +2 -2
  23. package/templates/apps/api/.dockerignore.hbs +10 -0
  24. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +8 -0
  25. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +6 -1
  26. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +13 -5
  27. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +13 -5
  28. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  29. package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +6 -2
  30. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +24 -2
  31. package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +4 -4
  32. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +74 -24
  33. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  34. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +153 -37
  35. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +39 -13
  36. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +106 -33
  37. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +3 -1
  38. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  39. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +20 -3
  40. package/templates/apps/api/e2e/capture-evidence.ts.hbs +4 -1
  41. package/templates/apps/api/eslint.config.js.hbs +3 -1
  42. package/templates/apps/api/images/serv.Dockerfile.hbs +15 -10
  43. package/templates/apps/api/playwright.config.ts.hbs +23 -19
  44. package/templates/apps/api/pnpm-workspace.yaml.hbs +27 -16
  45. package/templates/apps/fullstack/.dockerignore.hbs +10 -0
  46. package/templates/apps/fullstack/.gitignore.hbs +7 -2
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +14 -12
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +5 -3
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +10 -2
  50. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -1
  51. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +10 -2
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +0 -1
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +0 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +4 -1
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +16 -4
  56. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +10 -8
  57. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +3 -3
  58. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +8 -2
  59. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +0 -1
  60. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +0 -2
  61. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +4 -1
  62. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +16 -4
  63. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +2 -0
  64. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +9 -9
  65. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +10 -2
  66. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +1 -0
  67. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +0 -1
  68. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +0 -2
  69. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +4 -1
  70. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +19 -5
  71. package/templates/apps/fullstack/docs/security-configuration.md.hbs +4 -1
  72. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +140 -28
  73. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +19 -5
  74. package/templates/apps/fullstack/eslint.config.js.hbs +3 -1
  75. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +19 -11
  76. package/templates/apps/fullstack/images/web.Dockerfile.hbs +17 -8
  77. package/templates/apps/fullstack/package.json.hbs +2 -1
  78. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +7 -5
  79. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +114 -23
  80. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +57 -11
  81. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  82. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +17 -7
  83. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +13 -7
  84. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +17 -7
  85. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +10 -4
  86. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +65 -30
  87. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  88. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -2
  89. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +69 -21
  90. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +21 -5
  91. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +63 -11
  92. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -1
  93. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -1
  94. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +147 -33
  95. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +43 -12
  96. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +146 -30
  97. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +33 -10
  98. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +142 -26
  99. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +6 -2
  100. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  101. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +48 -66
  102. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +1 -0
  103. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +1 -0
  104. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +1 -0
  105. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +9 -2
  106. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +0 -3
  107. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +15 -3
  108. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +33 -7
  109. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +16 -2
  110. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +104 -13
  111. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +37 -7
  112. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +9 -3
  113. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +25 -3
  114. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +133 -19
  115. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +14 -2
  116. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +66 -34
  117. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +132 -30
  118. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +8 -2
  119. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +23 -5
  120. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +143 -21
  121. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -2
  122. package/templates/apps/fullstack/playwright.config.ts.hbs +25 -3
  123. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +30 -14
  124. package/templates/apps/h5/src/routes/+layout.svelte.hbs +74 -30
  125. package/templates/apps/h5/src/routes/+page.svelte.hbs +2 -2
  126. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +2 -2
  127. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +2 -2
  128. package/templates/apps/mobile-app/capacitor.config.ts.hbs +5 -2
  129. package/templates/apps/mobile-app/messages/en-US.json +2 -2
  130. package/templates/apps/mobile-app/messages/ja-JP.json +2 -2
  131. package/templates/apps/mobile-app/messages/zh-CN.json +2 -2
  132. package/templates/apps/mobile-app/src/App.svelte.hbs +17 -5
  133. package/templates/apps/mobile-app/src/lib/api.ts.hbs +20 -6
  134. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +8 -1
  135. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +6 -2
  136. package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -1
  137. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +5 -1
  138. package/templates/apps/website/scripts/static-website.mjs.hbs +19 -6
  139. package/templates/apps/website/src/routes/+layout.svelte.hbs +56 -29
  140. package/templates/apps/website/src/routes/+page.svelte.hbs +4 -4
  141. package/templates/apps/website/src/routes/about/+page.svelte.hbs +2 -2
  142. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +2 -2
  143. package/templates/apps/website/src/routes/services/+page.svelte.hbs +20 -5
  144. package/templates/base/.dockerignore.hbs +10 -0
  145. package/templates/base/.gitignore.hbs +7 -2
  146. package/templates/base/e2e/app.spec.ts.hbs +130 -36
  147. package/templates/base/eslint-rules.js +44 -25
  148. package/templates/base/eslint.config.js.hbs +3 -1
  149. package/templates/base/images/web.Dockerfile.hbs +25 -14
  150. package/templates/base/package.json.hbs +13 -7
  151. package/templates/base/patches/daisyui-5.7.50.patch +8 -0
  152. package/templates/base/patches/deepmerge-4.3.1.patch +51 -0
  153. package/templates/base/playwright.config.ts +3 -1
  154. package/templates/base/pnpm-workspace.yaml.hbs +33 -16
  155. package/templates/base/src/app.d.ts.hbs +1 -1
  156. package/templates/base/src/app.html.hbs +1 -0
  157. package/templates/base/src/hooks.server.ts.hbs +44 -33
  158. package/templates/base/src/lib/build-metadata.ts.hbs +0 -1
  159. package/templates/base/src/lib/server/init.ts.hbs +146 -35
  160. package/templates/base/src/lib/server/kit-config.ts.hbs +7 -4
  161. package/templates/base/src/routes/+layout.server.ts.hbs +2 -2
  162. package/templates/base/svelte.config.js.hbs +10 -100
  163. package/templates/base/tests/scaffold.test.ts.hbs +12 -3
  164. package/templates/base/tsconfig.json.hbs +7 -4
  165. package/templates/base/vite.config.ts.hbs +108 -14
  166. package/templates/base/vitest.config.ts.hbs +6 -2
  167. package/templates/features/ai/routes/api/chat/+server.ts +3 -1
  168. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +3 -3
  169. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +3 -3
  170. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +3 -3
  171. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +3 -3
  172. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +3 -3
  173. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +3 -3
  174. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +3 -3
  175. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +3 -3
  176. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +3 -3
  177. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +3 -3
  178. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +3 -3
  179. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +3 -3
  180. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +14 -3
  181. package/templates/shared/browser-check/startup.js +115 -0
  182. package/templates/shared/browser-check/update.css +37 -0
  183. package/templates/shared/browser-check/update.html +19 -0
  184. package/templates/shared/browser-startup.spec.ts +23 -0
  185. package/templates/shared/build-metadata.ts +18 -4
  186. package/templates/shared/e2e-env.ts +22 -6
  187. package/templates/shared/native-name.d.mts +5 -0
  188. package/templates/shared/native-name.mjs +94 -0
  189. package/templates/shared/public-base-path.mjs +17 -4
  190. package/templates/shared/run-e2e.mjs +46 -12
  191. package/templates/shared/run-node.mjs +56 -0
  192. package/templates/shared/run-tauri.mjs +74 -0
  193. package/templates/shared/vite-runtime-config.ts +9 -3
  194. package/templates/skills/AGENTS.md +10 -73
  195. package/templates/skills/bridges/admin/AGENTS.md +9 -65
  196. package/templates/skills/bridges/api/AGENTS.md +8 -59
  197. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +9 -54
  198. package/templates/skills/bridges/h5/AGENTS.md +8 -63
  199. package/templates/skills/bridges/mobile-app/AGENTS.md +8 -62
  200. package/templates/skills/bridges/website/AGENTS.md +8 -63
  201. package/templates/skills/hai-ai/SKILL.md +6 -2
  202. package/templates/skills/hai-ai/acp.md +153 -0
  203. package/templates/skills/hai-ai/guide.md +27 -12
  204. package/templates/skills/hai-ai/reference.md +24 -15
  205. package/templates/skills/hai-ai/resources.md +69 -0
  206. package/templates/skills/hai-api-client/SKILL.md +1 -1
  207. package/templates/skills/hai-api-client/reference.md +3 -1
  208. package/templates/skills/hai-app-create/collaboration.md +7 -0
  209. package/templates/skills/hai-app-create/development.md +19 -10
  210. package/templates/skills/hai-app-create/project.md +33 -0
  211. package/templates/skills/hai-app-create/reference.md +10 -10
  212. package/templates/skills/hai-app-tests/reference.md +1 -1
  213. package/templates/skills/hai-app-tests/validation.md +1 -0
  214. package/templates/skills/hai-build/SKILL.md +19 -9
  215. package/templates/skills/hai-build/paths.md +4 -2
  216. package/templates/skills/hai-build/reference.md +26 -8
  217. package/templates/skills/hai-cache/reference.md +6 -2
  218. package/templates/skills/hai-capacitor/SKILL.md +1 -0
  219. package/templates/skills/hai-capacitor/reference.md +24 -0
  220. package/templates/skills/hai-ci/SKILL.md +3 -0
  221. package/templates/skills/hai-core/SKILL.md +9 -4
  222. package/templates/skills/hai-core/reference.md +40 -10
  223. package/templates/skills/hai-core/request-access.md +2 -2
  224. package/templates/skills/hai-crypto/SKILL.md +2 -2
  225. package/templates/skills/hai-crypto/reference.md +7 -3
  226. package/templates/skills/hai-deploy/SKILL.md +41 -5
  227. package/templates/skills/hai-deploy/middleware.md +26 -14
  228. package/templates/skills/hai-framework-sync/SKILL.md +13 -9
  229. package/templates/skills/hai-framework-sync/sync.md +2 -0
  230. package/templates/skills/hai-iam/reference.md +2 -2
  231. package/templates/skills/hai-kit/SKILL.md +1 -1
  232. package/templates/skills/hai-kit/reference.md +19 -5
  233. package/templates/skills/hai-payment/reference.md +41 -17
  234. package/templates/skills/hai-reach/SKILL.md +3 -1
  235. package/templates/skills/hai-reach/reference.md +29 -9
  236. package/templates/skills/hai-reldb/SKILL.md +1 -1
  237. package/templates/skills/hai-reldb/reference.md +9 -2
  238. package/templates/skills/hai-scheduler/reference.md +1 -1
  239. package/templates/skills/hai-serv/SKILL.md +2 -1
  240. package/templates/skills/hai-serv/reference.md +26 -15
  241. package/templates/skills/hai-storage/reference.md +23 -6
  242. package/templates/skills/hai-ui/SKILL.md +11 -6
  243. package/templates/skills/hai-ui/charts.md +51 -0
  244. package/templates/skills/hai-ui/guide.md +1 -1
  245. package/templates/skills/hai-ui/reference.md +58 -38
  246. package/templates/skills/hai-vecdb/reference.md +8 -3
  247. package/dist/chunk-AKV2CQZV.js.map +0 -1
  248. package/dist/chunk-EF7WOFWZ.js.map +0 -1
  249. package/dist/chunk-MUHRBJSW.js +0 -29272
  250. package/dist/chunk-MUHRBJSW.js.map +0 -1
  251. package/dist/cli-config-templates-HHFHNXBN.js +0 -5
  252. package/dist/src-TEBHR5I5.js +0 -5
  253. package/dist/src-TEBHR5I5.js.map +0 -1
  254. package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +0 -18
@@ -1,14 +1,27 @@
1
1
  import type { CoreConfig } from '@h-ai/core'
2
2
  import type { {{#if features.feedback}}CreateServContext, {{/if}}ServConfig{{#if features.crypto}}, ServTransportConfig{{/if}} } from '@h-ai/serv'
3
- {{#if features.crypto}}import process from 'node:process'
4
- {{/if}}
5
- {{#if features.feedback}}import { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'
6
- {{/if}}import { core } from '@h-ai/core'
7
- {{#if features.crypto}}import { {{#if features.db}}createReldbTransportKeyStore{{else}}createInMemoryKeyStore{{/if}}, crypto, parseTransportServerKeyRing } from '@h-ai/crypto'
8
- {{/if}}{{#if features.feedback}}import { FeedbackConfigSchema } from '@h-ai/feedback'
9
- {{/if}}{{#if features.iam}}import { iam } from '@h-ai/iam'
10
- {{/if}}{{#if features.crypto}}{{#if features.db}}import { reldb } from '@h-ai/reldb'
11
- {{/if}}{{/if}}import { serv } from '@h-ai/serv'
3
+ {{#if features.crypto}}
4
+ import process from 'node:process'
5
+ {{/if}}
6
+ {{#if features.feedback}}
7
+ import { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'
8
+ {{/if}}
9
+ import { core } from '@h-ai/core'
10
+ {{#if features.crypto}}
11
+ import { {{#if features.db}}createReldbTransportKeyStore{{else}}createInMemoryKeyStore{{/if}}, crypto, parseTransportServerKeyRing } from '@h-ai/crypto'
12
+ {{/if}}
13
+ {{#if features.feedback}}
14
+ import { FeedbackConfigSchema } from '@h-ai/feedback'
15
+ {{/if}}
16
+ {{#if features.iam}}
17
+ import { iam } from '@h-ai/iam'
18
+ {{/if}}
19
+ {{#if features.crypto}}
20
+ {{#if features.db}}
21
+ import { reldb } from '@h-ai/reldb'
22
+ {{/if}}
23
+ {{/if}}
24
+ import { serv } from '@h-ai/serv'
12
25
  import { {{api.contractExportName}} } from '{{api.contractPackageName}}'
13
26
  import { {{api.serviceProceduresFactoryName}} } from './server/procedures/index.js'
14
27
 
@@ -28,45 +41,80 @@ export function {{api.serviceAppFactoryName}}(_options: CreateApiServiceAppOptio
28
41
  corsOrigin: servConfig.cors.origin,
29
42
  nativeOrigins: servConfig.cors.nativeOrigins,
30
43
  })
31
- {{#if features.crypto}} const transportMode = _options.transport ?? 'config'
44
+ {{#if features.crypto}}
45
+ const transportMode = _options.transport ?? 'config'
32
46
  let transport: ServTransportConfig | undefined
33
47
  if (transportMode !== 'disabled' && servConfig.transport !== false) {
34
- {{#unless features.db}} if (coreConfig.env !== 'development' && coreConfig.env !== 'test')
35
- throw new Error('Production transport requires a shared registry; enable the db feature and configure a shared database')
48
+ {{#unless features.db}}
49
+ if (coreConfig.env !== 'development' && coreConfig.env !== 'test')
50
+ throw new Error('Production transport requires a shared registry; enable the db feature and configure a shared database')
36
51
  {{/unless}}
37
52
  const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
38
53
  if (!ring.success)
39
54
  throw new Error(`HAI_CRYPTO_TRANSPORT_SERVERKEYRING: ${ring.error.message} (${ring.error.code})`)
40
- {{#if features.feedback}} // 可选反馈故障重试期间仍使用配置预算,避免缓存默认容量。
55
+ {{#if features.feedback}}
56
+ // 可选反馈故障重试期间仍使用配置预算,避免缓存默认容量。
41
57
  const feedbackSettings = FeedbackConfigSchema.safeParse(core.config.get('feedback'))
42
- const feedbackBudget = resolveFeedbackBudget(feedbackSettings.success ? feedbackSettings.data : {})
43
- {{/if}} transport = {
58
+ const feedbackBudget = resolveFeedbackBudget(feedbackSettings.success
59
+ ? feedbackSettings.data
60
+ : {})
61
+ {{/if}}
62
+ transport = {
44
63
  crypto,
45
64
  serverKeyRing: ring.data,
46
- {{#if features.db}} keyStore: createReldbTransportKeyStore({ reldb, ttlSeconds: 3600 }),
47
- {{else}} keyStore: createInMemoryKeyStore(), // 无 db 的模板仅在 development/test 使用内存 registry。
65
+ {{#if features.db}}
66
+ keyStore: createReldbTransportKeyStore({ reldb, ttlSeconds: 3600 }),
67
+ {{else}}
68
+ keyStore: createInMemoryKeyStore(), // 无 db 的模板仅在 development/test 使用内存 registry。
48
69
  {{/if}}
49
70
  keyExchangePath: servConfig.transport.keyExchangePath,
50
71
  maxPlaintextBytes: servConfig.transport.maxPlaintextBytes,
51
- {{#if features.feedback}} routePlaintextBytes: {
72
+ maxFutureSkewSeconds: servConfig.transport.maxFutureSkewSeconds,
73
+ maxRequestAgeSeconds: servConfig.transport.maxRequestAgeSeconds,
74
+ {{#if features.feedback}}
75
+ routePlaintextBytes: {
52
76
  [`${servConfig.http.apiPrefix}/feedback/reports`]: feedbackBudget.maxTransportBytes,
53
77
  [`${servConfig.http.apiPrefix}/feedback/reports/*/evidence`]: feedbackBudget.maxTransportBytes,
54
78
  [`${servConfig.http.apiPrefix}/feedback/reports/*/attachments/*`]: feedbackBudget.maxTransportBytes,
55
79
  [`${servConfig.http.apiPrefix}/feedback/reports/*/exports/*`]: feedbackBudget.maxTransportBytes,
56
80
  ...servConfig.transport.routePlaintextBytes,
57
81
  },
58
- {{else}} routePlaintextBytes: servConfig.transport.routePlaintextBytes,
82
+ {{else}}
83
+ routePlaintextBytes: servConfig.transport.routePlaintextBytes,
59
84
  {{/if}}
60
- excludePaths: [...servConfig.transport.excludePaths],
85
+ excludePaths: [
86
+ ...new Set([
87
+ ...servConfig.transport.excludePaths,
88
+ ...(servConfig.http.health
89
+ ? [servConfig.http.health.path, servConfig.http.health.readyPath].filter((path): path is `/${string}` => Boolean(path))
90
+ : []),
91
+ ...(servConfig.http.openapi && security.exposeApiDocs
92
+ ? [servConfig.http.openapi.path]
93
+ : []),
94
+ ...(servConfig.http.docs && security.exposeApiDocs
95
+ ? [servConfig.http.docs.path, `${servConfig.http.docs.path.slice(0, servConfig.http.docs.path.lastIndexOf('/') + 1)}_hai/scalar.js`]
96
+ : []),
97
+ ]),
98
+ ],
61
99
  }
62
100
  }
63
- {{else}} const transport = undefined
101
+ {{else}}
102
+ const transport = undefined
64
103
  {{/if}}
65
104
  {{#if features.iam}}
66
- const refreshCookie = _options.refreshCookie === 'disabled' ? undefined : { secure: security.secureRefreshCookie }
105
+ const refreshCookie = _options.refreshCookie === 'disabled'
106
+ ? undefined
107
+ : {
108
+ secure: security.secureRefreshCookie,
109
+ nativeTokenTransport: {
110
+ isRequest: (request: Request) => request.headers.get('x-hai-token-transport') === 'body'
111
+ && ['hai-mobile-app', 'hai-desktop-app'].includes(request.headers.get('x-request-client') ?? '')
112
+ && security.isNativeOrigin(request.headers.get('origin') ?? ''),
113
+ },
114
+ }
67
115
  {{/if}}
68
116
  {{#if features.feedback}}
69
- // 普通业务日志与反馈使用同一可信应用范围;身份仍由 IAM 验证。
117
+ // 普通业务日志与反馈使用同一可信应用范围;身份仍由 IAM 验证。
70
118
  const authenticatedContext = serv.buildAuthContextFactory(token => iam.auth.verifyToken(token))
71
119
  const createContext: CreateServContext = async input => ({
72
120
  ...await authenticatedContext(input),
@@ -108,7 +156,9 @@ export function {{api.serviceAppFactoryName}}(_options: CreateApiServiceAppOptio
108
156
  middleware: serv.cors({
109
157
  origin: security.allowOrigin,
110
158
  credentials: servConfig.cors.credentials,
111
- allowedHeaders: [...servConfig.cors.allowedHeaders],
159
+ allowedHeaders: [
160
+ ...new Set([...servConfig.cors.allowedHeaders, 'x-request-client', 'x-hai-token-transport']),
161
+ ],
112
162
  exposedHeaders: [...servConfig.cors.exposedHeaders],
113
163
  }),
114
164
  },
@@ -2,6 +2,5 @@
2
2
  {{#if features.feedback}}
3
3
  /** 当前应用编译时烘焙的产物身份;运行时配置不能覆盖。 */
4
4
  declare const __HAI_BUILD_METADATA__: { appVersion: string, buildId: string, commit: string }
5
-
6
5
  export const buildMetadata = __HAI_BUILD_METADATA__
7
6
  {{/if}}
@@ -13,7 +13,7 @@ import { core } from '@h-ai/core'
13
13
  import { crypto } from '@h-ai/crypto'
14
14
  {{/if}}
15
15
  {{#if features.feedback}}
16
- import { feedback } from '@h-ai/feedback'
16
+ import { feedback, FeedbackConfigSchema } from '@h-ai/feedback'
17
17
  {{/if}}
18
18
  {{#if features.iam}}
19
19
  import { iam, IamConfigSchema } from '@h-ai/iam'
@@ -24,12 +24,12 @@ import { reach, ReachConfigSchema } from '@h-ai/reach'
24
24
  {{#if features.db}}
25
25
  import { reldb, ReldbConfigSchema } from '@h-ai/reldb'
26
26
  {{/if}}
27
- import { ServConfigSchema } from '@h-ai/serv'
28
27
  {{#if features.audit}}
29
28
  {{#if features.scheduler}}
30
29
  import { scheduler, SchedulerConfigSchema } from '@h-ai/scheduler'
31
30
  {{/if}}
32
31
  {{/if}}
32
+ import { ServConfigSchema } from '@h-ai/serv'
33
33
  {{#if features.storage}}
34
34
  import { storage, StorageConfigSchema } from '@h-ai/storage'
35
35
  {{/if}}
@@ -53,7 +53,10 @@ function startFeedback(): Promise<void> {
53
53
  feedbackClosing = false
54
54
  feedbackStarting = (async () => {
55
55
  try {
56
- const result = await feedback.init({ ...core.config.getOrThrow<import('@h-ai/feedback').FeedbackConfigInput>('feedback'), ...buildMetadata })
56
+ const result = await feedback.init({
57
+ ...core.config.getOrThrow<import('@h-ai/feedback').FeedbackConfigInput>('feedback'),
58
+ ...buildMetadata,
59
+ })
57
60
  if (!result.success) {
58
61
  if (feedbackFailure !== result.error.code)
59
62
  core.logger.warn('Optional feedback unavailable; business runtime remains ready', { module: 'feedback', code: result.error.code })
@@ -87,67 +90,180 @@ async function closeFeedback() {
87
90
  await feedbackStarting
88
91
  return feedback.close()
89
92
  }
90
-
91
93
  {{/if}}
92
94
 
93
95
  const runtime = core.module.createRuntime([
94
- { name: 'configuration', start: () => { core.init({ configDir: './config' }) }, close: () => {} },
95
- { name: 'serv-config', start: () => core.config.validate('serv', ServConfigSchema), close: () => {} },
96
+ {
97
+ name: 'configuration',
98
+ start: () => {
99
+ core.init({
100
+ configDir: './config',
101
+ configSchemas: {
102
+ serv: ServConfigSchema,
103
+ {{#if features.ai}}
104
+ ai: AIConfigSchema,
105
+ {{/if}}
106
+ {{#if features.audit}}
107
+ audit: AuditInitConfigSchema,
108
+ {{/if}}
109
+ {{#if features.cache}}
110
+ cache: CacheConfigSchema,
111
+ {{/if}}
112
+ {{#if features.feedback}}
113
+ feedback: FeedbackConfigSchema,
114
+ {{/if}}
115
+ {{#if features.iam}}
116
+ iam: IamConfigSchema,
117
+ {{/if}}
118
+ {{#if features.reach}}
119
+ reach: ReachConfigSchema,
120
+ {{/if}}
96
121
  {{#if features.db}}
97
- { name: 'reldb', start: async () => {
98
- const config = ReldbConfigSchema.parse(core.config.getOrThrow('db'))
99
- if (config.type === 'sqlite' && config.database !== ':memory:') {
100
- const { mkdir } = await import('node:fs/promises')
101
- const { dirname } = await import('node:path')
102
- await mkdir(dirname(config.database), { recursive: true })
103
- }
104
- return reldb.init(config)
105
- }, close: () => reldb.close() },
122
+ db: ReldbConfigSchema,
123
+ {{/if}}
124
+ {{#if features.audit}}
125
+ {{#if features.scheduler}}
126
+ scheduler: SchedulerConfigSchema,
127
+ {{/if}}
128
+ {{/if}}
129
+ {{#if features.storage}}
130
+ storage: StorageConfigSchema,
131
+ {{/if}}
132
+ {{#if features.vecdb}}
133
+ vecdb: VecdbConfigSchema,
134
+ {{/if}}
135
+ },
136
+ })
137
+ },
138
+ close: () => { },
139
+ },
140
+ {
141
+ name: 'serv-config',
142
+ start: () => core.config.validate('serv', ServConfigSchema),
143
+ close: () => { },
144
+ },
145
+ {{#if features.db}}
146
+ {
147
+ name: 'reldb',
148
+ start: async () => {
149
+ const config = ReldbConfigSchema.parse(core.config.getOrThrow('db'))
150
+ if (config.type === 'sqlite' && config.database !== ':memory:') {
151
+ const { mkdir } = await import('node:fs/promises')
152
+ const { dirname } = await import('node:path')
153
+ await mkdir(dirname(config.database), { recursive: true })
154
+ }
155
+ return reldb.init(config)
156
+ },
157
+ close: () => reldb.close(),
158
+ },
106
159
  {{/if}}
107
160
  {{#if features.cache}}
108
- { name: 'cache', start: () => cache.init(CacheConfigSchema.parse(core.config.getOrThrow('cache'))), close: () => cache.close() },
161
+ {
162
+ name: 'cache',
163
+ start: () => cache.init(CacheConfigSchema.parse(core.config.getOrThrow('cache'))),
164
+ close: () => cache.close(),
165
+ },
109
166
  {{/if}}
110
167
  {{#if features.vecdb}}
111
- { name: 'vecdb', start: () => vecdb.init(VecdbConfigSchema.parse(core.config.getOrThrow('vecdb'))), close: () => vecdb.close() },
168
+ {
169
+ name: 'vecdb',
170
+ start: () => vecdb.init(VecdbConfigSchema.parse(core.config.getOrThrow('vecdb'))),
171
+ close: () => vecdb.close(),
172
+ },
112
173
  {{/if}}
113
174
  {{#if features.crypto}}
114
- { name: 'crypto', start: () => crypto.init(), close: () => crypto.close() },
175
+ {
176
+ name: 'crypto',
177
+ start: () => crypto.init(),
178
+ close: () => crypto.close(),
179
+ },
115
180
  {{/if}}
116
181
  {{#if features.storage}}
117
- { name: 'storage', start: () => storage.init(StorageConfigSchema.parse(core.config.getOrThrow('storage'))), close: () => storage.close() },
182
+ {
183
+ name: 'storage',
184
+ start: () => storage.init(StorageConfigSchema.parse(core.config.getOrThrow('storage'))),
185
+ close: () => storage.close(),
186
+ },
118
187
  {{/if}}
119
188
  {{#if features.reach}}
120
- { name: 'reach', enabled: () => Boolean(core.config.get('reach')), start: () => reach.init(ReachConfigSchema.parse(core.config.getOrThrow('reach'))), close: () => reach.close() },
189
+ {
190
+ name: 'reach',
191
+ enabled: () => Boolean(core.config.get('reach')),
192
+ start: () => reach.init(ReachConfigSchema.parse(core.config.getOrThrow('reach'))),
193
+ close: () => reach.close(),
194
+ },
121
195
  {{/if}}
122
196
  {{#if features.audit}}
123
- { name: 'audit', start: () => audit.init({ ...AuditInitConfigSchema.parse(core.config.get('audit') ?? {}){{#if features.storage}}, storage{{/if}}{{#if features.reach}}, reach{{/if}} }), close: () => audit.close() },
197
+ {
198
+ name: 'audit',
199
+ start: () => audit.init({
200
+ ...AuditInitConfigSchema.parse(core.config.get('audit') ?? {}),
201
+ {{#if features.storage}}
202
+ storage,
203
+ {{/if}}
204
+ {{#if features.reach}}
205
+ reach,
206
+ {{/if}}
207
+ }),
208
+ close: () => audit.close(),
209
+ },
124
210
  {{/if}}
125
211
  {{#if features.iam}}
126
- { name: 'iam', start: () => iam.init({ ...IamConfigSchema.parse(core.config.getOrThrow('iam')){{#if features.reach}}, reach{{/if}} }), close: () => iam.close() },
212
+ {
213
+ name: 'iam',
214
+ start: () => iam.init({
215
+ ...IamConfigSchema.parse(core.config.getOrThrow('iam')),
216
+ {{#if features.reach}}
217
+ reach,
218
+ {{/if}}
219
+ }),
220
+ close: () => iam.close(),
221
+ },
127
222
  {{/if}}
128
223
  {{#if features.audit}}
129
224
  {{#if features.scheduler}}
130
- { name: 'audit-jobs', enabled: () => Boolean(audit.schedulerPlan), start: async () => {
131
- const schedule = audit.schedulerPlan
132
- if (!schedule)
133
- return
134
- const initialized = await scheduler.init({ ...SchedulerConfigSchema.parse(core.config.get('scheduler') ?? {}), ...schedule })
135
- if (!initialized.success)
136
- return initialized
137
- const started = scheduler.start()
138
- if (!started.success)
139
- await scheduler.close()
140
- return started
141
- }, close: () => scheduler.close() },
225
+ {
226
+ name: 'audit-jobs',
227
+ enabled: () => Boolean(audit.schedulerPlan),
228
+ start: async () => {
229
+ const schedule = audit.schedulerPlan
230
+ if (!schedule)
231
+ return
232
+ const initialized = await scheduler.init({
233
+ ...SchedulerConfigSchema.parse(core.config.get('scheduler') ?? {}),
234
+ ...schedule,
235
+ })
236
+ if (!initialized.success)
237
+ return initialized
238
+ const started = scheduler.start()
239
+ if (!started.success)
240
+ await scheduler.close()
241
+ return started
242
+ },
243
+ close: () => scheduler.close(),
244
+ },
142
245
  {{/if}}
143
246
  {{/if}}
144
247
  {{#if features.feedback}}
145
- { name: 'feedback', enabled: () => Boolean(core.config.get('feedback')), start: startFeedback, close: closeFeedback },
248
+ {
249
+ name: 'feedback',
250
+ enabled: () => Boolean(core.config.get('feedback')),
251
+ start: startFeedback,
252
+ close: closeFeedback,
253
+ },
146
254
  {{/if}}
147
255
  {{#if features.ai}}
148
- { name: 'ai', start: () => ai.init(AIConfigSchema.parse(core.config.getOrThrow('ai'))), close: () => ai.close() },
256
+ {
257
+ name: 'ai',
258
+ start: () => ai.init(AIConfigSchema.parse(core.config.getOrThrow('ai'))),
259
+ close: () => ai.close(),
260
+ },
149
261
  {{/if}}
150
- { name: 'bootstrap', start: () => { core.logger.info('API service initialized') }, close: () => {} },
262
+ {
263
+ name: 'bootstrap',
264
+ start: () => { core.logger.info('API service initialized') },
265
+ close: () => { },
266
+ },
151
267
  ])
152
268
 
153
269
  /** 启动失败只报告模块、错误码和配置路径,私密值不进入错误上下文。 */
@@ -1,13 +1,27 @@
1
1
  import type { AppProcedureDeps } from './app-procedures.js'
2
- {{#if features.ai}}import { ai } from '@h-ai/ai'
3
- {{/if}}{{#if features.feedback}}import { feedback } from '@h-ai/feedback'
4
- {{/if}}{{#if features.iam}}import { iam } from '@h-ai/iam'
5
- {{/if}}{{#if features.ai}}import { createAiProcedures } from '@h-ai/serv/features/ai'
6
- {{/if}}{{#if features.feedback}}import { createFeedbackProcedures } from '@h-ai/serv/features/feedback'
7
- {{/if}}{{#if features.iam}}import { createIamProcedures } from '@h-ai/serv/features/iam'
8
- {{/if}}{{#if features.storage}}import { createStorageProcedures } from '@h-ai/serv/features/storage'
2
+ {{#if features.ai}}
3
+ import { ai } from '@h-ai/ai'
4
+ {{/if}}
5
+ {{#if features.feedback}}
6
+ import { feedback } from '@h-ai/feedback'
7
+ {{/if}}
8
+ {{#if features.iam}}
9
+ import { iam } from '@h-ai/iam'
10
+ {{/if}}
11
+ {{#if features.ai}}
12
+ import { createAiProcedures } from '@h-ai/serv/features/ai'
13
+ {{/if}}
14
+ {{#if features.feedback}}
15
+ import { createFeedbackProcedures } from '@h-ai/serv/features/feedback'
16
+ {{/if}}
17
+ {{#if features.iam}}
18
+ import { createIamProcedures } from '@h-ai/serv/features/iam'
19
+ {{/if}}
20
+ {{#if features.storage}}
21
+ import { createStorageProcedures } from '@h-ai/serv/features/storage'
9
22
  import { storage } from '@h-ai/storage'
10
- {{/if}}import { createAppProcedures } from './app-procedures.js'
23
+ {{/if}}
24
+ import { createAppProcedures } from './app-procedures.js'
11
25
 
12
26
  // @hai-generator:procedures:imports
13
27
 
@@ -15,15 +29,21 @@ import { storage } from '@h-ai/storage'
15
29
  export function {{api.serviceProceduresFactoryName}}(deps: { app: AppProcedureDeps }) {
16
30
  return {
17
31
  // @hai-generator:procedures:entries
18
- {{#if features.iam}} iam: createIamProcedures({ iam }),
19
- {{/if}}{{#if features.storage}} storage: createStorageProcedures({
32
+ {{#if features.iam}}
33
+ iam: createIamProcedures({ iam }),
34
+ {{/if}}
35
+ {{#if features.storage}}
36
+ storage: createStorageProcedures({
20
37
  storage,
21
38
  authorize: ({ context, keys }) => keys.every(key =>
22
39
  key.startsWith(`users/${encodeURIComponent(context.session.userId)}/`)),
23
40
  }),
24
- {{/if}}{{#if features.ai}} // AI 默认绑定可信 session.userId,跨主体访问需另行提供 authorizeObject 策略。
41
+ {{/if}}
42
+ {{#if features.ai}}
43
+ // AI 默认绑定可信 session.userId,跨主体访问需另行提供 authorizeObject 策略。
25
44
  ai: createAiProcedures({ ai }),
26
- {{/if}}{{#if features.feedback}}
45
+ {{/if}}
46
+ {{#if features.feedback}}
27
47
  feedback: createFeedbackProcedures({
28
48
  feedback,
29
49
  resolveContext: ({ session }) => ({
@@ -31,7 +51,13 @@ export function {{api.serviceProceduresFactoryName}}(deps: { app: AppProcedureDe
31
51
  userId: session.userId,
32
52
  // 示例角色映射;实际产品应从可信租户与资源权限确定范围。
33
53
  permissions: session.roles.includes('admin')
34
- ? ['feedback:create', 'feedback:read', 'feedback:process', 'feedback:reopen', 'feedback:export']
54
+ ? [
55
+ 'feedback:create',
56
+ 'feedback:read',
57
+ 'feedback:process',
58
+ 'feedback:reopen',
59
+ 'feedback:export',
60
+ ]
35
61
  : ['feedback:create'],
36
62
  }),
37
63
  }),