@h-ai/cli 0.1.0-alpha.66 → 0.1.0-alpha.68

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 (198) hide show
  1. package/README.en.md +86 -241
  2. package/README.ja.md +86 -241
  3. package/README.md +86 -241
  4. package/dist/{src-RDQ2EIBT.js → chunk-FI56GONY.js} +32 -2669
  5. package/dist/chunk-FI56GONY.js.map +1 -0
  6. package/dist/chunk-MBPB37FR.js +1348 -0
  7. package/dist/chunk-MBPB37FR.js.map +1 -0
  8. package/dist/{chunk-QYX6V7H2.js → chunk-ZFNBUF77.js} +347 -276
  9. package/dist/chunk-ZFNBUF77.js.map +1 -0
  10. package/dist/cli-config-templates-W2LLPMB6.js +5 -0
  11. package/dist/{cli-config-templates-3XSFIXBP.js.map → cli-config-templates-W2LLPMB6.js.map} +1 -1
  12. package/dist/{cli-skill-templates-TSYEQTCY.js → cli-skill-templates-US5CCAJ4.js} +3 -3
  13. package/dist/{cli-skill-templates-TSYEQTCY.js.map → cli-skill-templates-US5CCAJ4.js.map} +1 -1
  14. package/dist/index.js +1304 -532
  15. package/dist/index.js.map +1 -1
  16. package/dist/metafile-esm.json +1 -0
  17. package/dist/src-DSJJXM2F.js +3849 -0
  18. package/dist/src-DSJJXM2F.js.map +1 -0
  19. package/package.json +9 -8
  20. package/templates/README.md +48 -145
  21. package/templates/apps/admin/messages/ja-JP.json +38 -0
  22. package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -6
  23. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +3 -3
  24. package/templates/apps/api/.dockerignore.hbs +14 -7
  25. package/templates/apps/api/.gitignore.hbs +7 -0
  26. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +23 -2
  27. package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +2 -0
  28. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +4 -1
  29. package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +33 -8
  30. package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +0 -10
  31. package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +2 -1
  32. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +1 -2
  33. package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +24 -11
  34. package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +8 -1
  35. package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +68 -11
  36. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +10 -2
  37. package/templates/apps/api/e2e/api-service.spec.ts.hbs +2 -2
  38. package/templates/apps/api/hai.build.json.hbs +1 -1
  39. package/templates/apps/api/images/app.Dockerfile.hbs +35 -0
  40. package/templates/apps/api/package.json.hbs +6 -1
  41. package/templates/apps/api/playwright.config.ts.hbs +15 -7
  42. package/templates/apps/fullstack/.dockerignore.hbs +14 -9
  43. package/templates/apps/fullstack/.gitignore.hbs +7 -0
  44. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -6
  45. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +1 -0
  46. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +7 -1
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +2 -2
  50. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +23 -5
  51. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
  52. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +1 -1
  53. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +16 -6
  54. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
  55. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +24 -6
  56. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
  57. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +2 -2
  58. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +30 -9
  59. package/templates/apps/fullstack/hai.build.json.hbs +2 -2
  60. package/templates/apps/fullstack/images/app.Dockerfile.hbs +36 -0
  61. package/templates/apps/fullstack/images/web.Dockerfile.hbs +34 -0
  62. package/templates/apps/fullstack/package.json.hbs +3 -1
  63. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +23 -2
  64. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +1 -1
  65. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +2 -0
  66. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +3 -0
  67. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +32 -8
  68. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +0 -6
  69. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +8 -0
  70. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +2 -1
  71. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +6 -0
  72. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +9 -5
  73. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +3 -2
  74. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +16 -1
  75. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +7 -3
  76. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -0
  77. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +58 -7
  78. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +13 -3
  79. package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +7 -0
  80. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +40 -14
  81. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +105 -0
  82. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +3 -3
  83. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +6 -6
  84. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +7 -7
  85. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +4 -4
  86. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +8 -8
  87. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +13 -14
  88. package/templates/apps/fullstack/playwright.config.ts.hbs +15 -6
  89. package/templates/apps/h5/messages/ja-JP.json +40 -0
  90. package/templates/apps/h5/src/routes/+layout.svelte.hbs +16 -5
  91. package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
  92. package/templates/apps/mobile-app/src/App.svelte.hbs +15 -5
  93. package/templates/apps/mobile-app/src/lib/api.ts.hbs +173 -14
  94. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +2 -2
  95. package/templates/apps/website/messages/ja-JP.json +32 -0
  96. package/templates/apps/website/src/routes/+layout.svelte.hbs +13 -5
  97. package/templates/apps/website/src/routes/services/+page.svelte.hbs +1 -1
  98. package/templates/base/.dockerignore.hbs +14 -8
  99. package/templates/base/.gitignore.hbs +7 -0
  100. package/templates/base/e2e/app.spec.ts.hbs +23 -8
  101. package/templates/base/hai.build.json.hbs +1 -1
  102. package/templates/base/{Dockerfile.hbs → images/app.Dockerfile.hbs} +19 -17
  103. package/templates/base/package.json.hbs +11 -3
  104. package/templates/base/playwright.config.ts +15 -4
  105. package/templates/base/src/hooks.server.ts.hbs +15 -6
  106. package/templates/base/src/lib/server/init.ts.hbs +139 -30
  107. package/templates/base/vite.config.ts.hbs +5 -3
  108. package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +11 -6
  109. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +18 -25
  110. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +4 -0
  111. package/templates/i18n/project.inlang/settings.json +1 -1
  112. package/templates/shared/.gitattributes +6 -0
  113. package/templates/shared/e2e-env.ts +98 -0
  114. package/templates/shared/run-e2e.mjs +51 -12
  115. package/templates/skills/AGENTS.md +7 -3
  116. package/templates/skills/bridges/admin/AGENTS.md +6 -2
  117. package/templates/skills/bridges/api/AGENTS.md +3 -1
  118. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +5 -1
  119. package/templates/skills/bridges/h5/AGENTS.md +6 -2
  120. package/templates/skills/bridges/mobile-app/AGENTS.md +6 -2
  121. package/templates/skills/bridges/website/AGENTS.md +6 -2
  122. package/templates/skills/hai-ai/SKILL.md +8 -2
  123. package/templates/skills/hai-ai/guide.md +134 -60
  124. package/templates/skills/hai-ai/reference.md +51 -11
  125. package/templates/skills/hai-api-client/SKILL.md +15 -160
  126. package/templates/skills/hai-api-client/reference.md +178 -0
  127. package/templates/skills/hai-api-contract/SKILL.md +16 -273
  128. package/templates/skills/hai-api-contract/reference.md +280 -0
  129. package/templates/skills/hai-app-create/SKILL.md +6 -2
  130. package/templates/skills/hai-app-create/development.md +24 -8
  131. package/templates/skills/hai-app-create/reference.md +7 -5
  132. package/templates/skills/hai-app-review/SKILL.md +7 -3
  133. package/templates/skills/hai-app-review/differential.md +34 -0
  134. package/templates/skills/hai-app-tests/SKILL.md +6 -3
  135. package/templates/skills/hai-app-tests/reference.md +5 -5
  136. package/templates/skills/hai-app-tests/validation.md +38 -0
  137. package/templates/skills/hai-audit/SKILL.md +24 -147
  138. package/templates/skills/hai-audit/reference.md +148 -0
  139. package/templates/skills/hai-build/SKILL.md +14 -8
  140. package/templates/skills/hai-build/reference.md +16 -13
  141. package/templates/skills/hai-cache/SKILL.md +20 -181
  142. package/templates/skills/hai-cache/reference.md +229 -0
  143. package/templates/skills/hai-capacitor/SKILL.md +7 -4
  144. package/templates/skills/hai-capacitor/reference.md +15 -9
  145. package/templates/skills/hai-ci/SKILL.md +2 -0
  146. package/templates/skills/hai-core/SKILL.md +7 -3
  147. package/templates/skills/hai-core/reference.md +25 -5
  148. package/templates/skills/hai-crypto/SKILL.md +22 -250
  149. package/templates/skills/hai-crypto/reference.md +310 -0
  150. package/templates/skills/hai-datapipe/SKILL.md +16 -195
  151. package/templates/skills/hai-datapipe/reference.md +204 -0
  152. package/templates/skills/hai-deploy/SKILL.md +24 -54
  153. package/templates/skills/hai-deploy/middleware.md +51 -43
  154. package/templates/skills/hai-framework-sync/SKILL.md +2 -2
  155. package/templates/skills/hai-framework-sync/sync.md +1 -1
  156. package/templates/skills/hai-iam/SKILL.md +25 -11
  157. package/templates/skills/hai-iam/reference.md +181 -154
  158. package/templates/skills/hai-kit/SKILL.md +35 -174
  159. package/templates/skills/hai-kit/reference.md +190 -0
  160. package/templates/skills/hai-payment/SKILL.md +33 -263
  161. package/templates/skills/hai-payment/reference.md +295 -0
  162. package/templates/skills/hai-pr-review/SKILL.md +21 -88
  163. package/templates/skills/hai-reach/SKILL.md +6 -3
  164. package/templates/skills/hai-reach/reference.md +83 -22
  165. package/templates/skills/hai-reldb/SKILL.md +6 -3
  166. package/templates/skills/hai-reldb/reference.md +68 -25
  167. package/templates/skills/hai-scheduler/SKILL.md +18 -195
  168. package/templates/skills/hai-scheduler/reference.md +216 -0
  169. package/templates/skills/hai-serv/SKILL.md +25 -10
  170. package/templates/skills/hai-serv/reference.md +123 -87
  171. package/templates/skills/hai-spec-implement/SKILL.md +5 -1
  172. package/templates/skills/hai-spec-implement/evaluation.md +18 -0
  173. package/templates/skills/hai-spec-implement/handoff.md +47 -0
  174. package/templates/skills/hai-spec-implement/templates.md +5 -0
  175. package/templates/skills/hai-spec-implement/workflow.md +5 -3
  176. package/templates/skills/hai-spec-review/SKILL.md +4 -0
  177. package/templates/skills/hai-storage/SKILL.md +23 -238
  178. package/templates/skills/hai-storage/reference.md +282 -0
  179. package/templates/skills/hai-ui/SKILL.md +17 -3
  180. package/templates/skills/hai-ui/guide.md +3 -3
  181. package/templates/skills/hai-ui/reference.md +26 -11
  182. package/templates/skills/hai-ui-design/SKILL.md +31 -0
  183. package/templates/skills/hai-ui-design/patterns.md +26 -0
  184. package/templates/skills/hai-ui-review/SKILL.md +30 -0
  185. package/templates/skills/hai-ui-review/checklist.md +22 -0
  186. package/templates/skills/hai-vecdb/SKILL.md +14 -10
  187. package/templates/skills/hai-vecdb/reference.md +33 -3
  188. package/dist/chunk-FWN5B54L.js +0 -468
  189. package/dist/chunk-FWN5B54L.js.map +0 -1
  190. package/dist/chunk-QYX6V7H2.js.map +0 -1
  191. package/dist/cli-config-templates-3XSFIXBP.js +0 -5
  192. package/dist/src-RDQ2EIBT.js.map +0 -1
  193. package/templates/apps/api/Dockerfile.hbs +0 -35
  194. package/templates/apps/fullstack/Dockerfile.hbs +0 -57
  195. /package/templates/apps/fullstack/{docker → images/web}/19-runtime-config.envsh.hbs +0 -0
  196. /package/templates/apps/fullstack/{docker → images/web}/nginx.conf.hbs +0 -0
  197. /package/templates/apps/fullstack/{docker → images/web}/runtime-config.js.template.hbs +0 -0
  198. /package/templates/base/{docker → images/web}/nginx.conf.hbs +0 -0
@@ -0,0 +1,38 @@
1
+ # 分轮验证与集中修复
2
+
3
+ 适用于开发、审查修复、升级后的质量门禁与整体验收。默认执行“收集一轮 → 归并问题 → 集中修复 → 定向回归通过 → 较完整验收”,不要遇到一个普通失败就修改代码并从头重跑。新增行为的目标用例仍可做小范围 TDD Red → Green;它不要求提前运行整套门禁。
4
+
5
+ ## 1. 确定本轮检查
6
+
7
+ - 先读当前 `package.json`、任务依赖与环境要求,按影响范围列出命令、工作目录、前置条件和预期证据。优先 workspace filter;用户要求全量验收时保留全量范围。纯文案/文档修改只做适用检查,不新增镜像测试。
8
+ - 一轮默认按 typecheck → lint → build(涉及构建/配置/模板/跨包契约)→ test → 相关 E2E 调度;顺序服从真实依赖。同轮收集不等于同时运行:只有输出目录、端口、数据库、容器与 fixture 均隔离的检查才可并行,共用 `dist`、`.svelte-kit` 或预览产物的构建与测试必须串行。
9
+ - 使用现有任务编排或一个临时调度脚本逐项执行、捕获真实退出码并保存日志。不要用跨检查的 `&&`、全局 fail-fast 或 `|| true` 代替结果收集;脚本内部有前置短路时,确认后续检查是否真正执行,必要时分别调度等价子任务,保留原门禁的最终验收。
10
+
11
+ ## 2. 收集全部可执行结果
12
+
13
+ - 本轮开始后保持被测源码、配置、依赖和运行环境稳定;协作 agent 也不得边测边改,不运行自动修复。普通类型错误、lint 错误、测试断言失败只记录,继续其余具备前置条件的检查。
14
+ - 只有真实前置失败才阻塞依赖它的检查,例如依赖无法安装、执行器无法启动、上游构建未产生必要产物、必需服务不可用。标明阻塞原因,继续独立检查;确实无法继续收集时才提前结束本轮、集中修复阻塞。不得使用旧构建、旧镜像或旧截图让下游假通过。
15
+ - 为每轮使用独立且被 Git 忽略的日志目录,例如 `tmp/validation/round-01/`。逐项记录命令/范围、源码版本及未提交改动、环境、状态(通过/失败/阻塞/未执行)、退出码、耗时和日志路径;未执行与不适用须说明原因,不能写成通过。超时、取消和环境失败单列,不能当作断言失败或忽略。
16
+ - 调度脚本等子进程退出后再记录结果;重定向或管道不能覆盖实际退出码。所有必需项均有有效通过结果,整轮才算通过;收集到任何失败或阻塞时,汇总必须保留非成功状态。
17
+ - 完整输出写日志,AI 先读汇总及每类失败的有限上下文,再按需定位原始日志;不反复载入整份成功日志、密集轮询或启动尚未结束的同一检查。长任务期间定期简述进度。
18
+
19
+ ## 3. 集中分析与修复
20
+
21
+ - 本轮可执行检查结束后,把问题按根因去重,记录位置、证据、影响、修复项及关联门禁。上游故障造成的连锁失败合并处理;区分本次引入、原有问题和环境问题。
22
+ - 在已有授权范围内集中修复本次范围的问题,保留仍有效的断言与回归。不能靠删断言、跳过用例、放宽超时或关闭规则换绿灯。环境故障先保存证据、确认恢复条件,再定向重试;不反复重跑到偶然通过。
23
+ - 下载超时先区分 registry、DNS、代理等网络前提与实际编译/业务错误。复用包管理器的有界重试、可信镜像和缓存,保留总时限与每次结果;只对可安全重复的瞬时网络操作重试,不重试断言或掩盖业务失败。超时/取消后确认本轮进程树及已登记资源回收,再重试或启动冲突任务。
24
+ - 新发现的独立问题加入同一清单;修复期间的小范围诊断不触发从头全量重跑,也不能替代下一轮必要验收。
25
+
26
+ ## 4. 先定向回归,再扩大验收
27
+
28
+ - 集中修复后,先用最小适用范围验证原失败、已解除的阻塞及直接受影响的消费者;保留必要构建/服务前置。定向回归仍失败时继续归并和修复,只重跑失败及受新改动影响的项,暂不启动较完整门禁。
29
+ - 相关问题均已验证解决后,再按影响扩大到工作区或完整用户流程验收;影响范围不明、共享配置/依赖改变或用户要求全量时,执行全量门禁。扩大验收发现新问题时,仍回到“收集 → 集中修复 → 定向回归通过 → 扩大验收”,不要每改一处就重复整套流程。
30
+ - 只有源码、依赖、配置、工具、环境及所用产物等输入均未改变的已通过项才可复用,并注明来源轮次或缓存;输入变化使相关结果失效。最终所有必需检查必须对最终代码仍有效,缺项不能称为完成。真实部署、Provider、浏览器或原生验收不能只引用静态检查/构建缓存。
31
+ - 保留原有 CI/发布门禁的失败阻断;问题收集时继续运行不代表允许失败提交发布或忽略 required checks。
32
+ - 每轮都在 finally/teardown 停止本轮进程、清理本轮临时工程/容器/镜像/数据;确认退出和资源释放后再运行冲突任务。日志、截图与报告保留到问题分析和交付结束,再按项目约定清理,不覆盖失败证据、不提交验收产物、不删除用户资源。
33
+ - 部署夹具先检查固定公开基础镜像,仅确认缺失才拉取;成功 create 先登记完整 ID,再在私有 PID namespace 内异步准备 APT/pip/sshd。所有准备 exec 转交同一取消信号,等待本地客户端 close 后按该 ID 停止全树并核验消失。总准备 deadline 早于 hook 并预留回收预算;公共缓存不删,私有 tag 回收前复核内容 ID/owner。未取得可信 create 回执或测试进程被强制终止时记录未知,不能按名称或 label 认领资源。
34
+ - 浏览器执行器默认将每轮、每组的证据分别放入忽略的 `test-results/run-*/group-*`;只清理本轮临时数据库/上传数据。显式 `HAI_AUTH_EVIDENCE_DIR`、`--output` 和 Playwright HTML 输出目录会保留,取消也不删除已有报告。不要复制私有环境、密钥或业务数据库到证据目录。
35
+ - 经托管 `test:e2e` 入口为服务子进程提供绝对 `HAI_E2E_DATA_ROOT` 和显式测试后端,隔离继承的 `HAI_*` / `PUBLIC_*` / `VITE_*` 与用户 `.env.local`。仅本轮测试启用 `HAI_E2E=1`;普通开发与生产的 dotenv 加载、共享后端守卫不放宽。启用 transport 的验收使用本轮可信 ring 和 registry,不能关闭加密掩盖客户端契约问题。
36
+ - 最终报告各项门禁状态、执行/复用范围、修复结果和未验证原因;mock、容器、真实服务及原生结果分别说明。只陈述实际证据,不以“脚本执行完了”代表验证通过。
37
+
38
+ 公开 API 变更需验证 package.exports 实际入口与配套声明,核对根/子路径真实导入和浏览器打包;不使用 src/dist 深层导入绕过缺失公开产物。Svelte 默认组件、明确 selective/type-only 导出与 client/server 分隔按实际契约验收,不把内部 Provider/Deps 扩成公共 API。
@@ -1,160 +1,37 @@
1
1
  ---
2
2
  name: hai-audit
3
- description: "使用 @h-ai/audit 记录、查询、统计和清理操作审计。"
3
+ description: "接入 @h-ai/audit 记录业务操作,查询分页日志与统计,并按保留期清理。"
4
4
  ---
5
5
 
6
- # @h-ai/audit — 审计日志模块
6
+ # hai-audit
7
7
 
8
8
  ## 能力契约
9
9
 
10
- | 项目 | 契约 |
11
- | --- | --- |
12
- | 能力 | 使用 @h-ai/audit 记录、查询、统计和清理操作审计 |
13
- | 适用场景 | 业务操作留痕与审计记录检索 |
14
- | 输入 | AuditConfigInput、已初始化 reldb、审计事件与查询条件 |
15
- | 输出 | 记录/查询/统计的 HaiResult |
16
- | 限制 | 仅服务端;审计内容需脱敏,保留期和清理范围由应用策略决定。 |
10
+ | 项目 | 契约 |
11
+ | -------- | ---------------------------------------------------------- |
12
+ | 能力 | 使用 @h-ai/audit 记录、查询、统计和清理操作审计 |
13
+ | 适用场景 | 业务操作留痕与审计记录检索 |
14
+ | 输入 | AuditInitConfigInput、已初始化 reldb、审计事件与查询条件 |
15
+ | 输出 | 记录/查询/统计的 HaiResult |
16
+ | 限制 | 仅服务端;审计内容需脱敏,保留期和清理范围由应用策略决定。 |
17
17
 
18
- 统一审计日志模块,基于 `@h-ai/reldb` 实现持久化,提供审计日志的记录、分页查询、清理与统计。
18
+ ## 使用路径
19
19
 
20
- ## 运行环境
20
+ 1. 确认已初始化 reldb,校验 `AuditInitConfigInput` 后初始化 audit;init 等待DDL就绪才成功,失败保持未初始化;每步失败停止后续操作。
21
+ 2. 在实际业务成功/失败边界记录事件,明确审计失败如何影响业务,不重复记录同一事件。
22
+ 3. 查询使用返回的分页元数据;清理前核对保留期及授权范围。凭证字段会被脱敏,个人信息仍需业务策略。
23
+ 4. 检查写入、查询和清理的 HaiResult,先关闭 audit 再关闭数据库。
21
24
 
22
- > ⚠️ **服务端模块(Node.js only)。** 审计日志由服务端自动记录,浏览器端通过 API 端点查询审计数据。
25
+ 常见事件使用 `audit.helper` 与公开 `AuditHelper` 类型;内部记录器装配工厂不从包入口导出。
23
26
 
24
- ## 依赖
27
+ ## 按需参考
25
28
 
26
- | 模块 | 用途 | 是否必需 | 初始化要求 |
27
- | --- | --- | --- | --- |
28
- | `@h-ai/reldb` | 数据库(审计日志持久化) | **必需** | 需在 `audit.init()` 前初始化 |
29
+ 按本次操作读取对应小节;以已安装版本的公开类型核验签名,示例中的业务变量由应用提供。
29
30
 
30
- ## 使用步骤
31
-
32
- ### 1. 配置
33
-
34
- 审计模块依赖已初始化的 `@h-ai/reldb` 单例,无需独立配置文件。审计日志固定存储在 `hai_audit_logs` 表中。
35
-
36
- ### 2. 初始化
37
-
38
- ```ts
39
- import { audit } from '@h-ai/audit'
40
- import { reldb } from '@h-ai/reldb'
41
-
42
- // 先初始化依赖
43
- await reldb.init({ type: 'sqlite', database: './data.db' })
44
-
45
- // 再初始化审计模块(自动使用已初始化的 reldb 单例)
46
- const result = await audit.init()
47
- if (!result.success) {
48
- // 处理错误
49
- }
50
- ```
51
-
52
- 自定义用户表映射:
53
-
54
- ```ts
55
- await audit.init({
56
- userTable: 'hai_iam_users',
57
- userIdColumn: 'id',
58
- userNameColumn: 'username',
59
- })
60
- ```
61
-
62
- ### 3. 关闭
63
-
64
- ```ts
65
- const closeResult = await audit.close()
66
- if (!closeResult.success) {
67
- throw new Error(closeResult.error.message)
68
- }
69
- ```
70
-
71
- ## 核心 API
72
-
73
- ### 生命周期
74
-
75
- | 方法 | 签名 | 说明 |
76
- | --------------------- | ---------------------------------------------------------------- | ---------- |
77
- | `audit.init` | `(config: AuditInitConfig) => Promise<HaiResult<void>>` | 初始化模块 |
78
- | `audit.close` | `() => Promise<HaiResult<void>>` | 关闭模块 |
79
- | `audit.isInitialized` | `boolean` | 初始化状态 |
80
-
81
- ### 日志操作
82
-
83
- | 方法 | 签名 | 说明 |
84
- | --------------------- | ----------------------------------------------------------------------------------- | -------------------- |
85
- | `audit.log` | `(input: CreateAuditLogInput) => Promise<HaiResult<AuditLog>>` | 记录审计日志 |
86
- | `audit.list` | `(options?: ListAuditLogsOptions) => Promise<HaiResult<PaginatedResult<AuditLogWithUser>>>` | 分页查询(items/total/page/pageSize,含用户名;使用返回的规范化元数据,默认 pageSize 20) |
87
- | `audit.getUserRecent` | `(userId: string, limit?: number) => Promise<HaiResult<AuditLog[]>>` | 用户最近活动 |
88
- | `audit.cleanup` | `(olderThanDays?: number) => Promise<HaiResult<number>>` | 清理旧日志 |
89
- | `audit.getStats` | `(days?: number) => Promise<HaiResult<AuditStatItem[]>>` | 操作统计 |
90
-
91
- ### 便捷记录器 (`audit.helper`)
92
-
93
- | 方法 | 说明 |
94
- | ------------------------------------------------------------------------------ | ------------ |
95
- | `audit.helper.login(userId, ip?, ua?)` | 登录 |
96
- | `audit.helper.logout(userId, ip?, ua?)` | 登出 |
97
- | `audit.helper.register(userId, ip?, ua?)` | 注册 |
98
- | `audit.helper.passwordResetRequest(email, ip?, ua?)` | 密码重置请求 |
99
- | `audit.helper.passwordResetComplete(userId, ip?, ua?)` | 密码重置完成 |
100
- | `audit.helper.crud(input)` | CRUD 操作 |
101
-
102
- > `audit.log()` / `audit.helper.*()` 中的 `details` 仅会自动脱敏凭证类字段(如 `password` / `token` / `secret`);邮箱、手机号默认保留原值。
103
-
104
- ## 错误码
105
-
106
- | 错误码 | code | 说明 |
107
- | --------------------------------- | ---------------- | ------------ |
108
- | `HaiAuditError.LOG_FAILED` | `hai:audit:001` | 记录失败 |
109
- | `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | 查询失败 |
110
- | `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | 清理失败 |
111
- | `HaiAuditError.STATS_FAILED` | `hai:audit:004` | 统计失败 |
112
- | `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | 初始化进行中 |
113
- | `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | 模块未初始化 |
114
- | `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | 配置错误 |
115
-
116
- ## 常见模式
117
-
118
- ### 用户认证审计
119
-
120
- ```ts
121
- // 登录
122
- await audit.helper.login(userId, request.ip, request.headers['user-agent'])
123
-
124
- // 登出
125
- await audit.helper.logout(userId, request.ip, request.headers['user-agent'])
126
- ```
127
-
128
- ### CRUD 操作审计
129
-
130
- ```ts
131
- await audit.helper.crud({ userId, action: 'create', resource: 'users', resourceId: newUser.id, details: { name: newUser.name } })
132
- await audit.helper.crud({ userId, action: 'update', resource: 'roles', resourceId: roleId, details: { changes } })
133
- await audit.helper.crud({ userId, action: 'delete', resource: 'permissions', resourceId: permId })
134
- ```
135
-
136
- ### 仪表盘数据
137
-
138
- ```ts
139
- // 最近日志
140
- const recentLogs = await audit.list({ pageSize: 10 })
141
-
142
- // 7 天统计
143
- const stats = await audit.getStats(7)
144
- ```
145
-
146
- ### 定期清理
147
-
148
- ```ts
149
- // 清理 90 天前的日志
150
- const result = await audit.cleanup(90)
151
- if (result.success) {
152
- logger.info(`Cleaned up ${result.data} old audit logs`)
153
- }
154
- ```
155
-
156
- ## 相关 Skills
157
-
158
- - `hai-reldb` — 数据库模块(审计模块依赖)
159
- - `hai-iam` — 身份认证与权限管理(审计的主要记录对象)
160
- - `hai-core` — 核心工具(日志、ID 生成、i18n)
31
+ - [运行环境](reference.md#运行环境)
32
+ - [依赖](reference.md#依赖)
33
+ - [使用步骤](reference.md#使用步骤)
34
+ - [核心 API](reference.md#核心-api)
35
+ - [错误码](reference.md#错误码)
36
+ - [常见模式](reference.md#常见模式)
37
+ - [相关 Skills](reference.md#相关-skills)
@@ -0,0 +1,148 @@
1
+ # hai-audit 参考
2
+
3
+ 统一审计日志模块,基于 `@h-ai/reldb` 实现持久化,提供审计日志的记录、分页查询、清理与统计。
4
+
5
+
6
+ `audit.init()` 会等待自动建表和仓库就绪才返回成功;DDL 失败保持 `isInitialized=false`,修正数据库后可重试。自定义 JOIN、统计和清理也使用同一就绪屏障;初始化期间关闭会使迟到结果失效。先检查 init 的 HaiResult,再立即记录或查询;audit 不拥有共享 RelDB 的连接,关闭 audit 后再关闭数据库。
7
+
8
+ ## 运行环境
9
+
10
+ > ⚠️ **服务端模块(Node.js only)。** 审计日志由服务端自动记录,浏览器端通过 API 端点查询审计数据。
11
+
12
+ ## 依赖
13
+
14
+ | 模块 | 用途 | 是否必需 | 初始化要求 |
15
+ | --- | --- | --- | --- |
16
+ | `@h-ai/reldb` | 数据库(审计日志持久化) | **必需** | 需在 `audit.init()` 前初始化 |
17
+
18
+ ## 使用步骤
19
+
20
+ ### 1. 配置
21
+
22
+ 审计模块依赖已初始化的 `@h-ai/reldb` 单例,无需独立配置文件。审计日志固定存储在 `hai_audit_logs` 表中。
23
+
24
+ ### 2. 初始化
25
+
26
+ ```ts
27
+ import { audit } from '@h-ai/audit'
28
+ import { reldb } from '@h-ai/reldb'
29
+
30
+ // 先初始化依赖
31
+ await reldb.init({ type: 'sqlite', database: './data.db' })
32
+
33
+ // 再初始化审计模块(自动使用已初始化的 reldb 单例)
34
+ const result = await audit.init()
35
+ if (!result.success) {
36
+ // 处理错误
37
+ }
38
+ ```
39
+
40
+ 自定义用户表映射:
41
+
42
+ ```ts
43
+ await audit.init({
44
+ userTable: 'hai_iam_users',
45
+ userIdColumn: 'id',
46
+ userNameColumn: 'username',
47
+ })
48
+ ```
49
+
50
+ ### 3. 关闭
51
+
52
+ ```ts
53
+ const closeResult = await audit.close()
54
+ if (!closeResult.success) {
55
+ throw new Error(closeResult.error.message)
56
+ }
57
+ ```
58
+
59
+ ## 核心 API
60
+
61
+ ### 生命周期
62
+
63
+ | 方法 | 签名 | 说明 |
64
+ | --------------------- | ---------------------------------------------------------------- | ---------- |
65
+ | `audit.init` | `(config?: AuditInitConfigInput) => Promise<HaiResult<void>>` | 初始化模块 |
66
+ | `audit.close` | `() => Promise<HaiResult<void>>` | 关闭模块 |
67
+ | `audit.isInitialized` | `boolean` | 初始化状态 |
68
+
69
+ ### 日志操作
70
+
71
+ | 方法 | 签名 | 说明 |
72
+ | --------------------- | ----------------------------------------------------------------------------------- | -------------------- |
73
+ | `audit.log` | `(input: CreateAuditLogInput) => Promise<HaiResult<AuditLog>>` | 记录审计日志 |
74
+ | `audit.list` | `(options?: ListAuditLogsOptions) => Promise<HaiResult<PaginatedResult<AuditLogWithUser>>>` | 分页查询(items/total/page/pageSize,含用户名;使用返回的规范化元数据,默认 pageSize 20) |
75
+ | `audit.getUserRecent` | `(userId: string, limit?: number) => Promise<HaiResult<AuditLog[]>>` | 用户最近活动 |
76
+ | `audit.cleanup` | `(olderThanDays?: number) => Promise<HaiResult<number>>` | 清理旧日志 |
77
+ | `audit.getStats` | `(days?: number) => Promise<HaiResult<AuditStatItem[]>>` | 操作统计 |
78
+
79
+ ### 便捷记录器 (`audit.helper`)
80
+
81
+ | 方法 | 说明 |
82
+ | ------------------------------------------------------------------------------ | ------------ |
83
+ | `audit.helper.login(userId, ip?, ua?)` | 登录 |
84
+ | `audit.helper.logout(userId, ip?, ua?)` | 登出 |
85
+ | `audit.helper.register(userId, ip?, ua?)` | 注册 |
86
+ | `audit.helper.passwordResetRequest(email, ip?, ua?)` | 密码重置请求 |
87
+ | `audit.helper.passwordResetComplete(userId, ip?, ua?)` | 密码重置完成 |
88
+ | `audit.helper.crud(input)` | CRUD 操作 |
89
+
90
+ > `audit.log()` / `audit.helper.*()` 中的 `details` 仅会自动脱敏凭证类字段(如 `password` / `token` / `secret`);邮箱、手机号默认保留原值。
91
+
92
+ ## 错误码
93
+
94
+ | 错误码 | code | 说明 |
95
+ | --------------------------------- | ---------------- | ------------ |
96
+ | `HaiAuditError.LOG_FAILED` | `hai:audit:001` | 记录失败 |
97
+ | `HaiAuditError.QUERY_FAILED` | `hai:audit:002` | 查询失败 |
98
+ | `HaiAuditError.CLEANUP_FAILED` | `hai:audit:003` | 清理失败 |
99
+ | `HaiAuditError.STATS_FAILED` | `hai:audit:004` | 统计失败 |
100
+ | `HaiAuditError.INIT_IN_PROGRESS` | `hai:audit:005` | 初始化进行中 |
101
+ | `HaiAuditError.NOT_INITIALIZED` | `hai:audit:010` | 模块未初始化 |
102
+ | `HaiAuditError.CONFIG_ERROR` | `hai:audit:012` | 配置错误 |
103
+
104
+ ## 常见模式
105
+
106
+ ### 用户认证审计
107
+
108
+ ```ts
109
+ // 登录
110
+ await audit.helper.login(userId, request.ip, request.headers['user-agent'])
111
+
112
+ // 登出
113
+ await audit.helper.logout(userId, request.ip, request.headers['user-agent'])
114
+ ```
115
+
116
+ ### CRUD 操作审计
117
+
118
+ ```ts
119
+ await audit.helper.crud({ userId, action: 'create', resource: 'users', resourceId: newUser.id, details: { name: newUser.name } })
120
+ await audit.helper.crud({ userId, action: 'update', resource: 'roles', resourceId: roleId, details: { changes } })
121
+ await audit.helper.crud({ userId, action: 'delete', resource: 'permissions', resourceId: permId })
122
+ ```
123
+
124
+ ### 仪表盘数据
125
+
126
+ ```ts
127
+ // 最近日志
128
+ const recentLogs = await audit.list({ pageSize: 10 })
129
+
130
+ // 7 天统计
131
+ const stats = await audit.getStats(7)
132
+ ```
133
+
134
+ ### 定期清理
135
+
136
+ ```ts
137
+ // 清理 90 天前的日志
138
+ const result = await audit.cleanup(90)
139
+ if (result.success) {
140
+ logger.info(`Cleaned up ${result.data} old audit logs`)
141
+ }
142
+ ```
143
+
144
+ ## 相关 Skills
145
+
146
+ - `hai-reldb` — 数据库模块(审计模块依赖)
147
+ - `hai-iam` — 身份认证与权限管理(审计的主要记录对象)
148
+ - `hai-core` — 核心工具(日志、ID 生成、i18n)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-build
3
- description: "定位 hai 应用架构、模块依赖、初始化顺序、构建模式和对应技能。"
3
+ description: "构建或排查 hai 应用的源码、容器镜像和桌面产物;识别工程架构、依赖与对应构建入口。"
4
4
  ---
5
5
 
6
6
  # hai-build
@@ -22,25 +22,31 @@ description: "定位 hai 应用架构、模块依赖、初始化顺序、构建
22
22
  - 功能开发先用 [development.md](../hai-app-create/development.md) 把需求匹配到当前版本的框架能力与配置;再读取所选模块 skill 和公开类型。
23
23
  - 有生命周期的模块按真实依赖初始化、检查结果并反序清理;core、纯函数和工厂不套用相同生命周期。
24
24
  - 构建任务检查当前 engines、适配器、缓存与目标产物,不能照搬框架仓库私有构建命令。
25
+ - 多项门禁按 [分轮验证与集中修复](../hai-app-tests/validation.md) 先收集结果再集中修复;遵守产物依赖与资源隔离,不并行清理/重建同一输出目录,不用旧产物补成通过。
25
26
 
26
27
  ## 构建与部署
27
28
 
28
- - `pnpm build` 默认仅编译源码(调用 compile);`pnpm build --target docker` 根据 hai.build.json 构建并导出 app/可选 web 镜像,auto 优先可达 Podman、其次 Docker,可用 --runtime 显式指定。
29
- - compile 交付源码编译结果,docker 交付镜像归档,desktop 交付 Tauri 系统安装包;每次只选一种。images[].target 是 Dockerfile 阶段名,fullstack 的 app 使用 runtime、web 使用 web,不能与 CLI target 混用;参数默认值和示例必须与真实入口同步。
29
+ - 创建默认包含开发期部署工具,可用 --no-deploy 关闭。每个镜像使用 images/ 中独立 Dockerfile,Web 配置位于 images/web/,不使用镜像阶段 target 配置。
30
+ - 构建器生成 images/dependencies/ 安装输入;fetch、安装和生产依赖整理共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,并复用依赖层。file: 归档、补丁、workspace 元数据必须进入下载上下文;原生依赖缓存按系统/架构/ABI 区分。基础镜像、中间件及工具指定版本,禁止 latest。
31
+ - 默认容器面向 CPU 运行或远程 AI 服务,Dockerfile 设置 `ONNXRUNTIME_NODE_INSTALL_CUDA=skip`,跳过额外 CUDA/TensorRT 下载;使用宿主机 GPU 时定制镜像和运行参数,不修改本机 npm 或全局 AI/GPU 配置。
32
+ - pnpm run deploy --build 显式串联构建、打包和发布;--bundle-only 只交付完整离线包与跨平台脚本;--services 以服务器成功状态为基线只更新选中服务。完整包自动包含自建中间件镜像,服务器禁止联网拉取。
33
+ - `pnpm build` 默认仅编译源码(调用 compile);`pnpm build --target docker` 根据 hai.build.json 的 dockerfile 构建并导出 app/可选 web 镜像,可用 --images web 只构建前端,auto 优先可达 Podman、其次 Docker,可用 --runtime 显式指定。
34
+ - compile 交付源码编译结果,docker 交付镜像归档,desktop 交付 Tauri 系统安装包;每次只选一种。images[].dockerfile 指向独立镜像文件,最终阶段作为交付镜像;参数默认值和示例必须与真实入口同步。
30
35
  - Podman 的客户端代理通过预定义构建参数传递,覆盖 Windows/macOS 远程引擎的服务端默认值;代理地址必须能从构建容器访问,--no-http-proxy 禁止此传递。不要把代理写成 Dockerfile ENV 或固化进交付镜像。
31
36
  - --network 默认沿用引擎网络;只有实际构建网络无法访问依赖/代理时才显式选择网络,pasta 仅适用于 rootless Podman。build 与 run 的主机名解析可能不同,须验证构建网络中的可达性,不默认改成 host 网络。
32
- - 从运行 build 的应用根 package.json.version 读取版本,不能使用 CLI/框架版本或服务子包版本代替。清单格式 version=2,appVersion 为应用版本;镜像 tar 名含版本、buildId 区分同版本构建,Tauri 也接收根版本。不要手改清单或保留无版本的交付归档。
33
- - 构建不区分 dev/test/prod,不加载部署环境覆盖,不注入运行期凭据;完整镜像清单含 SHA-256,全部成功才发布 latest。不要让 compile、Dockerfile 或 Tauri beforeBuildCommand 递归调用自身的原生/镜像构建。
37
+ - 从运行 build 的应用根 package.json.version 读取版本,不能使用 CLI/框架版本或服务子包版本代替。清单格式 version=3,appVersion 为应用版本;appContainerPort/webContainerPort 仅记录 images 配置显式填写的端口,部分构建也保留未选镜像端口,未填写时沿用部署默认值。镜像 tar 名含版本、buildId 区分同版本构建,Tauri 也接收根版本。不要手改清单或保留无版本的交付归档。
38
+ - 构建不区分 dev/test/prod,不加载部署环境覆盖,不注入运行期凭据;所选镜像清单含 SHA-256,全部成功才更新本机最近构建指针(不是镜像标签)。不要让 compile、Dockerfile 或 Tauri beforeBuildCommand 递归调用自身的原生/镜像构建。
34
39
  - Vite 的 envDir 与 SvelteKit 的 kit.env.dir 是独立加载入口,必须同时阻止构建阶段读取工程根的 .env 文件;开发/预览由 core loader 注入,运行期由 deploy 注入。用临时 .env.local 哨兵值检查输出,避免只过滤进程变量却仍把私有文件固化进产物。
35
40
  - 静态客户端通过 runtime-config.js 或原生宿主初始化脚本获取公开地址与元数据;仅投影公开白名单,禁止将完整 process.env、服务配置或密钥序列化到浏览器。预览与容器启动均须验证真实登录,不能依赖构建期 API 地址让 E2E 通过。
41
+ - Fullstack Capacitor App 在 `public/runtime-config.js` 提供公开 API 地址,再编译并同步原生资源;Tauri 从启动进程的 PUBLIC_API_BASE 注入。不能把开发代理的 .env 配置当作已安装原生包的运行配置。
36
42
  - `pnpm build --target desktop --platform windows|linux|macos --arch x64|arm64` 调用对应工程的 Tauri build。要求在目标系统准备 Rust target、SDK 和打包工具,不假定跨系统编译。原生安装包必须按目标系统实测。
37
- - deploy 只消费已有产物,详见 [hai-deploy](../hai-deploy/SKILL.md)。网络不通时 --bundle-only 生成 tar,按说明手工搬运;packaged 不代表部署已运行。
38
- - 测试临时工程、镜像、容器、辅助进程、日志、截图和报告必须在 finally/teardown 自动清理,失败/取消也清理;不得提交测试产物或删除用户既有资源。
43
+ - deploy 默认消费已有产物,--build 显式先构建,详见 [hai-deploy](../hai-deploy/SKILL.md)。网络不通时 --bundle-only 生成 tar,按说明手工搬运;packaged 不代表部署已运行。
44
+ - 测试临时工程、镜像、容器、辅助进程和数据必须在 finally/teardown 自动清理,失败/取消也清理;日志、截图和报告保留到分析和交付结束再清理,不得提交测试产物或删除用户既有资源。
39
45
  - 浏览器测试的数据放入本轮独立临时目录;Windows 等子进程与服务退出后再删除数据库和上传文件,不依赖下一轮测试补清理。
40
46
 
41
47
  ## 按需参考
42
48
 
43
- 详细配置、API 签名、错误码和范本在 [reference.md](reference.md)。按下列标题定位所需小节,不默认通读;用例中的业务变量需结合当前应用补齐。
49
+ 按任务读取 [reference.md](reference.md) 的对应小节;签名以当前源码或安装版本的公开类型为准,不默认加载全部资料。示例中的业务变量由应用提供。
44
50
 
45
51
  - 适用场景
46
52
  - 项目架构
@@ -42,7 +42,7 @@
42
42
  | 公共 API | oRPC contract + Hono + typed client |
43
43
  | 认证 | Bearer access token + httpOnly refresh cookie(浏览器推荐) |
44
44
 
45
- pnpm 专属配置放在 `pnpm-workspace.yaml`,`.npmrc` 仅用于注册表与认证。Docker 缓存层使用 `pnpm fetch` 读取锁文件;pnpm 12 的该命令不支持 `--frozen-lockfile`。后续仍通过 `pnpm install --offline --frozen-lockfile` 校验清单与锁文件一致。容器裁剪用 `pnpm pm deploy --filter <服务包> --prod <目标目录>`,确保执行内置命令,避免项目同名 `deploy` 脚本覆盖它。
45
+ pnpm 专属配置放在 `pnpm-workspace.yaml`,`.npmrc` 仅用于注册表与认证。Docker 缓存层使用 `pnpm fetch` 读取锁文件;pnpm 12 的该命令不支持 `--frozen-lockfile`。后续仍通过 `pnpm install --offline --frozen-lockfile` 校验清单与锁文件一致。容器裁剪用 `pnpm pm deploy --filter <服务包> --prod <目标目录>`,确保执行内置命令,避免项目同名 `deploy` 脚本覆盖它。保留 `.gitattributes`,让 `.dockerignore`、Dockerfile 和 POSIX 脚本统一使用 LF,保持跨平台输入一致并确保 Linux 脚本可运行。
46
46
 
47
47
  ### SvelteKit Adapter 模式
48
48
 
@@ -150,13 +150,15 @@ const db = await reldb.init(dbConfig.data)
150
150
  if (!db.success) return db
151
151
  const cached = await cache.init(cacheConfig.data)
152
152
  if (!cached.success) {
153
- await reldb.close()
154
- return cached
153
+ const cleanup = await reldb.close()
154
+ return cleanup.success ? cached : cleanup
155
155
  }
156
156
  const identity = await iam.init(iamConfig.data)
157
157
  if (!identity.success) {
158
- await cache.close()
159
- await reldb.close()
158
+ const cacheCleanup = await cache.close()
159
+ const dbCleanup = await reldb.close()
160
+ if (!cacheCleanup.success) return cacheCleanup
161
+ if (!dbCleanup.success) return dbCleanup
160
162
  return identity
161
163
  }
162
164
  // 应用结束时 await iam.close()、cache.close()、reldb.close();
@@ -277,12 +279,15 @@ pnpm --filter <app-name> test:e2e
277
279
  pnpm --filter <app-name> test
278
280
  pnpm --filter <app-name> test:e2e
279
281
 
280
- # Refactor:质量门禁
282
+ # Refactor:按下方分轮验证流程收集适用门禁
281
283
  pnpm typecheck
282
284
  pnpm lint
285
+ pnpm build # 构建/配置/模板/跨包契约变更
283
286
  pnpm test
284
287
  ```
285
288
 
289
+ 以上命令按 [分轮验证与集中修复](../hai-app-tests/validation.md) 调度,不在普通失败时立即修改并从头重跑。
290
+
286
291
  ## 统一编码规范
287
292
 
288
293
  ### 强制规则
@@ -311,7 +316,7 @@ return kit.response.ok(result.data)
311
316
 
312
317
  ### 质量门禁
313
318
 
314
- 按当前项目已定义的 scripts 和变更影响执行;PowerShell 使用 `pnpm.cmd`:
319
+ 按当前项目已定义的 scripts 和变更影响选择检查,执行 [分轮验证与集中修复](../hai-app-tests/validation.md):普通失败先记录,独立检查继续,汇总后集中修复。PowerShell 使用 `pnpm.cmd`:
315
320
 
316
321
  ```bash
317
322
  pnpm typecheck # TypeScript 类型检查
@@ -338,11 +343,9 @@ pnpm test # Vitest 单元测试
338
343
 
339
344
  ### 变更后:验证
340
345
 
341
- 1. `pnpm typecheck` 通过
342
- 2. `pnpm lint` 通过
343
- 3. 构建/配置/跨包变更 `pnpm build` 通过
344
- 4. `pnpm test` 通过(单元测试)
345
- 5. UI/路由/端到端改动执行相应 `test:e2e`;从 package.json 确认入口
346
- 6. 搜索确认所有引用点已更新,报告未验证边界
346
+ 1. 按影响范围调度一轮 typecheck/lint/build/test;UI/路由/端到端改动加相应 E2E,从 package.json 确认入口
347
+ 2. 记录全部可执行结果与日志;真实前置失败只阻塞依赖项,普通失败不边测边改
348
+ 3. 归并问题并集中修复,再验证失败、阻塞及受影响项;最终必需门禁对最终代码有效通过
349
+ 4. 搜索确认所有引用点已更新,报告未验证边界与结果来源
347
350
 
348
351
  涉及原生交付时按当前项目 Tauri/Gradle/Xcode 等实际入口打包,在目标 OS/设备验证安装启动、会话、安全 TokenStorage、API 域名及覆盖升级。Web 构建/E2E 不代替原生验收;记录平台/工具链与结果,缺平台写未验证。