@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.
- package/README.en.md +74 -154
- package/README.ja.md +74 -154
- package/README.md +74 -154
- package/dist/{chunk-AKV2CQZV.js → chunk-2ZL5ORQ2.js} +316 -97
- package/dist/chunk-2ZL5ORQ2.js.map +1 -0
- package/dist/{chunk-EF7WOFWZ.js → chunk-L53P43B2.js} +1312 -163
- package/dist/chunk-L53P43B2.js.map +1 -0
- package/dist/cli-config-templates-LWMD2I6V.js +5 -0
- package/dist/{cli-config-templates-HHFHNXBN.js.map → cli-config-templates-LWMD2I6V.js.map} +1 -1
- package/dist/{cli-skill-templates-PN4FLGBC.js → cli-skill-templates-D6S2OQ6X.js} +3 -3
- package/dist/{cli-skill-templates-PN4FLGBC.js.map → cli-skill-templates-D6S2OQ6X.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30118 -3253
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +22 -18
- package/templates/README.md +45 -30
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -10
- package/templates/apps/admin/src/routes/+page.svelte.hbs +4 -4
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +17 -7
- package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +26 -6
- package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +2 -2
- package/templates/apps/api/.dockerignore.hbs +10 -0
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +8 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +6 -1
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +13 -5
- package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +13 -5
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
- package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +6 -2
- package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +24 -2
- package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +4 -4
- package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +74 -24
- package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
- package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +153 -37
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +39 -13
- package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +106 -33
- package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +3 -1
- package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
- package/templates/apps/api/e2e/api-serv.spec.ts.hbs +20 -3
- package/templates/apps/api/e2e/capture-evidence.ts.hbs +4 -1
- package/templates/apps/api/eslint.config.js.hbs +3 -1
- package/templates/apps/api/images/serv.Dockerfile.hbs +15 -10
- package/templates/apps/api/playwright.config.ts.hbs +23 -19
- package/templates/apps/api/pnpm-workspace.yaml.hbs +27 -16
- package/templates/apps/fullstack/.dockerignore.hbs +10 -0
- package/templates/apps/fullstack/.gitignore.hbs +7 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +14 -12
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +5 -3
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +10 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +10 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +4 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +16 -4
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +10 -8
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +3 -3
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +8 -2
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +0 -2
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +4 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +16 -4
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +2 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +9 -9
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +10 -2
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +0 -2
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +4 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +19 -5
- package/templates/apps/fullstack/docs/security-configuration.md.hbs +4 -1
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +140 -28
- package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +19 -5
- package/templates/apps/fullstack/eslint.config.js.hbs +3 -1
- package/templates/apps/fullstack/images/serv.Dockerfile.hbs +19 -11
- package/templates/apps/fullstack/images/web.Dockerfile.hbs +17 -8
- package/templates/apps/fullstack/package.json.hbs +2 -1
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +7 -5
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +114 -23
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +57 -11
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +17 -7
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +13 -7
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +17 -7
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +10 -4
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +65 -30
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +69 -21
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +21 -5
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +63 -11
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +147 -33
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +43 -12
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +146 -30
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +33 -10
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +142 -26
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +6 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +48 -66
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +9 -2
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +0 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +15 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +33 -7
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +16 -2
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +104 -13
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +37 -7
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +9 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +25 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +133 -19
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +14 -2
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +66 -34
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +132 -30
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +8 -2
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +23 -5
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +143 -21
- package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -2
- package/templates/apps/fullstack/playwright.config.ts.hbs +25 -3
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +30 -14
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +74 -30
- package/templates/apps/h5/src/routes/+page.svelte.hbs +2 -2
- package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +2 -2
- package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +2 -2
- package/templates/apps/mobile-app/capacitor.config.ts.hbs +5 -2
- package/templates/apps/mobile-app/messages/en-US.json +2 -2
- package/templates/apps/mobile-app/messages/ja-JP.json +2 -2
- package/templates/apps/mobile-app/messages/zh-CN.json +2 -2
- package/templates/apps/mobile-app/src/App.svelte.hbs +17 -5
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +20 -6
- package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +8 -1
- package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +6 -2
- package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -1
- package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +5 -1
- package/templates/apps/website/scripts/static-website.mjs.hbs +19 -6
- package/templates/apps/website/src/routes/+layout.svelte.hbs +56 -29
- package/templates/apps/website/src/routes/+page.svelte.hbs +4 -4
- package/templates/apps/website/src/routes/about/+page.svelte.hbs +2 -2
- package/templates/apps/website/src/routes/contact/+page.svelte.hbs +2 -2
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +20 -5
- package/templates/base/.dockerignore.hbs +10 -0
- package/templates/base/.gitignore.hbs +7 -2
- package/templates/base/e2e/app.spec.ts.hbs +130 -36
- package/templates/base/eslint-rules.js +44 -25
- package/templates/base/eslint.config.js.hbs +3 -1
- package/templates/base/images/web.Dockerfile.hbs +25 -14
- package/templates/base/package.json.hbs +13 -7
- package/templates/base/patches/daisyui-5.7.50.patch +8 -0
- package/templates/base/patches/deepmerge-4.3.1.patch +51 -0
- package/templates/base/playwright.config.ts +3 -1
- package/templates/base/pnpm-workspace.yaml.hbs +33 -16
- package/templates/base/src/app.d.ts.hbs +1 -1
- package/templates/base/src/app.html.hbs +1 -0
- package/templates/base/src/hooks.server.ts.hbs +44 -33
- package/templates/base/src/lib/build-metadata.ts.hbs +0 -1
- package/templates/base/src/lib/server/init.ts.hbs +146 -35
- package/templates/base/src/lib/server/kit-config.ts.hbs +7 -4
- package/templates/base/src/routes/+layout.server.ts.hbs +2 -2
- package/templates/base/svelte.config.js.hbs +10 -100
- package/templates/base/tests/scaffold.test.ts.hbs +12 -3
- package/templates/base/tsconfig.json.hbs +7 -4
- package/templates/base/vite.config.ts.hbs +108 -14
- package/templates/base/vitest.config.ts.hbs +6 -2
- package/templates/features/ai/routes/api/chat/+server.ts +3 -1
- package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +3 -3
- package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +3 -3
- package/templates/features/payment/routes/api/v1/payment/create/+server.ts +14 -3
- package/templates/shared/browser-check/startup.js +115 -0
- package/templates/shared/browser-check/update.css +37 -0
- package/templates/shared/browser-check/update.html +19 -0
- package/templates/shared/browser-startup.spec.ts +23 -0
- package/templates/shared/build-metadata.ts +18 -4
- package/templates/shared/e2e-env.ts +22 -6
- package/templates/shared/native-name.d.mts +5 -0
- package/templates/shared/native-name.mjs +94 -0
- package/templates/shared/public-base-path.mjs +17 -4
- package/templates/shared/run-e2e.mjs +46 -12
- package/templates/shared/run-node.mjs +56 -0
- package/templates/shared/run-tauri.mjs +74 -0
- package/templates/shared/vite-runtime-config.ts +9 -3
- package/templates/skills/AGENTS.md +10 -73
- package/templates/skills/bridges/admin/AGENTS.md +9 -65
- package/templates/skills/bridges/api/AGENTS.md +8 -59
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +9 -54
- package/templates/skills/bridges/h5/AGENTS.md +8 -63
- package/templates/skills/bridges/mobile-app/AGENTS.md +8 -62
- package/templates/skills/bridges/website/AGENTS.md +8 -63
- package/templates/skills/hai-ai/SKILL.md +6 -2
- package/templates/skills/hai-ai/acp.md +153 -0
- package/templates/skills/hai-ai/guide.md +27 -12
- package/templates/skills/hai-ai/reference.md +24 -15
- package/templates/skills/hai-ai/resources.md +69 -0
- package/templates/skills/hai-api-client/SKILL.md +1 -1
- package/templates/skills/hai-api-client/reference.md +3 -1
- package/templates/skills/hai-app-create/collaboration.md +7 -0
- package/templates/skills/hai-app-create/development.md +19 -10
- package/templates/skills/hai-app-create/project.md +33 -0
- package/templates/skills/hai-app-create/reference.md +10 -10
- package/templates/skills/hai-app-tests/reference.md +1 -1
- package/templates/skills/hai-app-tests/validation.md +1 -0
- package/templates/skills/hai-build/SKILL.md +19 -9
- package/templates/skills/hai-build/paths.md +4 -2
- package/templates/skills/hai-build/reference.md +26 -8
- package/templates/skills/hai-cache/reference.md +6 -2
- package/templates/skills/hai-capacitor/SKILL.md +1 -0
- package/templates/skills/hai-capacitor/reference.md +24 -0
- package/templates/skills/hai-ci/SKILL.md +3 -0
- package/templates/skills/hai-core/SKILL.md +9 -4
- package/templates/skills/hai-core/reference.md +40 -10
- package/templates/skills/hai-core/request-access.md +2 -2
- package/templates/skills/hai-crypto/SKILL.md +2 -2
- package/templates/skills/hai-crypto/reference.md +7 -3
- package/templates/skills/hai-deploy/SKILL.md +41 -5
- package/templates/skills/hai-deploy/middleware.md +26 -14
- package/templates/skills/hai-framework-sync/SKILL.md +13 -9
- package/templates/skills/hai-framework-sync/sync.md +2 -0
- package/templates/skills/hai-iam/reference.md +2 -2
- package/templates/skills/hai-kit/SKILL.md +1 -1
- package/templates/skills/hai-kit/reference.md +19 -5
- package/templates/skills/hai-payment/reference.md +41 -17
- package/templates/skills/hai-reach/SKILL.md +3 -1
- package/templates/skills/hai-reach/reference.md +29 -9
- package/templates/skills/hai-reldb/SKILL.md +1 -1
- package/templates/skills/hai-reldb/reference.md +9 -2
- package/templates/skills/hai-scheduler/reference.md +1 -1
- package/templates/skills/hai-serv/SKILL.md +2 -1
- package/templates/skills/hai-serv/reference.md +26 -15
- package/templates/skills/hai-storage/reference.md +23 -6
- package/templates/skills/hai-ui/SKILL.md +11 -6
- package/templates/skills/hai-ui/charts.md +51 -0
- package/templates/skills/hai-ui/guide.md +1 -1
- package/templates/skills/hai-ui/reference.md +58 -38
- package/templates/skills/hai-vecdb/reference.md +8 -3
- package/dist/chunk-AKV2CQZV.js.map +0 -1
- package/dist/chunk-EF7WOFWZ.js.map +0 -1
- package/dist/chunk-MUHRBJSW.js +0 -29272
- package/dist/chunk-MUHRBJSW.js.map +0 -1
- package/dist/cli-config-templates-HHFHNXBN.js +0 -5
- package/dist/src-TEBHR5I5.js +0 -5
- package/dist/src-TEBHR5I5.js.map +0 -1
- package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +0 -18
|
@@ -18,6 +18,8 @@ description: "构建并发布或交付已有镜像:完整离线包、按服务
|
|
|
18
18
|
| 输出 | 含 tar、清单、配置和跨平台入口的单一交付目录与分步结果,或经过 HTTP 检查的部署结果 |
|
|
19
19
|
| 限制 | SDK 只消费产物;CLI --build 显式先构建。首次安装必须完整交付,packaged 不代表服务器 ready。云资源需要外网。 |
|
|
20
20
|
|
|
21
|
+
Vercel API/文件上传只请求官方入口,拒绝重定向,每次请求和完整 JSON 读取共用 30 秒期限;超时先查询平台实际状态,不无条件重复发布。此期限没有配置开关。
|
|
22
|
+
|
|
21
23
|
--plan 和 --inspect-remote 从 CLI 完整透传,只读失败不得退回部署。target.runtime 只表示远端配置。旧凭据用服务器本机 `hai deploy-secrets <directory> --import <private.json>` 预检,--apply 才导入;SDK importDeploymentSecrets 默认 dryRun:true,验证项目/卷/实际凭据、共享 flock、v2 状态特殊字符与原子 0600 写入,缺状态的普通部署仍拒绝。完整格式和恢复步骤见 [凭据导入](credentials.md)。
|
|
22
24
|
|
|
23
25
|
## 操作流程
|
|
@@ -31,24 +33,56 @@ description: "构建并发布或交付已有镜像:完整离线包、按服务
|
|
|
31
33
|
排错与交付按[沟通与同步维护](../hai-app-create/collaboration.md)先说明实际影响、恢复步骤和验证边界,再附脱敏错误码/traceId/日志;配置、使用文档和截图随实际部署流程同步。
|
|
32
34
|
|
|
33
35
|
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
|
|
36
|
+
2. 选择环境,验证 .env.<mode> 存在,再处理部署目标与必要中间件。SSH 支持 key/agent 或 password,缺项按说明补齐,有效完整配置直接复用;--bundle-only 在构建和中间件配置后、打包前最后询问是否添加或修改 SSH 信息,保存并用于本次和后续 target;--yes 或跳过时复用已有配置。新私有参数写 .env.<mode>.local,共享 .env.local 保留本机私有值;私钥仅引用路径,密码隐藏输入并保留原值。Core、Node/Vite 和部署统一加载模式私有层,按来源先父后细项。优先级与认证边界见 [middleware.md](middleware.md)。
|
|
35
37
|
3. 先校验所选制品、版本、服务和SHA-256。--build只构建所选应用镜像;不带它时缺产物明确失败,不隐式补构建。根目录使用格式4,非根目录使用格式5及webBasePath;两者都记录appVersion、buildId、partial、hasWeb、镜像归档及显式配置的servContainerPort/webContainerPort,部分构建也保留未选镜像端口,缺省使用部署默认值。网站目录由构建进程PUBLIC_BASE_PATH确定,所有部分构建须保持一致;目录变化必须全量,健康与恢复按制品记录处理。具体步骤见[网站挂载目录](../hai-build/paths.md)。同一应用版本可重建,镜像引用区分实际内容;禁止latest与无版本镜像。
|
|
36
38
|
4. 完整包自动导出实际自建中间件镜像并去重;只更新 Web 不重新打包 API/中间件。打包机需容器引擎导出中间件,服务器仅 load,禁止 pull/build。外部连接及云开通不能伪称为离线自包含服务。
|
|
37
39
|
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
|
|
40
|
+
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。只复制归档时,解压后阅读同目录的 `APPLY.txt`,在该目录执行 `sh ./apply.sh`。脚本不依赖源码、Node 或 pnpm;本机运行 deploy.sh 需 sh、awk、ssh、scp。manifest.partial/selectedServices 固化模式:完整构建且无 --services 为全量;部分构建或显式 --services 为增量,必须匹配服务器成功基线。
|
|
39
41
|
7. 工具预检、基线、上传、校验、镜像导入、服务更新和 HTTP 检查分别报告。失败返回非零退出码,结果文件保留失败阶段;只有检查成功才更新服务器 current。已有部署失败尝试恢复所选服务的旧容器和配置,并按旧发布端口/路径验证容器和 HTTP;result 的 recoveryStatus 为 not-needed/passed/failed/stopped。数据卷保留,已写业务数据和不兼容 Schema 迁移不回退。恢复验证失败不能表述为已回滚成功。禁止把本地打包记录当服务器成功状态。
|
|
40
42
|
8. 部署及恢复全程用 Linux flock 持有固定 `.deploy.lock`;不得删除/替换文件或按时间抢锁。父进程强杀后,继承 FD 的活跃子命令仍持锁;所有持有进程退出或重启后自动释放。旧 `.deploy-lock` 目录保持原样,升级前结束旧版部署进程。强杀/断电不执行恢复 trap,缺结果文件须人工核对容器、镜像和 current 后用新包恢复,锁释放不代表副作用已回退。
|
|
41
43
|
|
|
42
44
|
成功后手工回退使用**当前 CLI**、旧应用 build 制品和匹配配置,省略 `--build`、`--services` 生成新全量 ID;离线也须重新打包,不能运行旧 bundle 或旧工具绕过账本。旧制品通常只保留 serv/web 镜像,中间件仍按当前 CLI 固定版本规划,不承诺精确回退全部中间件版本、DDL 或业务数据。确认主版本、Schema、拓扑和数据兼容并准备备份,再发布和验证。
|
|
43
45
|
|
|
46
|
+
`hai.json` 的 `deploy.container.compose.services` 支持给 `serv`、`web` 分别配置 `extra_hosts`,写主机名到 IPv4/IPv6 的映射。沿用环境插值、`--plan` 和离线归档校验,已有成功基线时可复用镜像制品只更新对应角色。恢复读取上次成功的 Compose 快照。
|
|
47
|
+
|
|
48
|
+
## 可选 HTTPS
|
|
49
|
+
|
|
50
|
+
所有容器模板共用deploy.provider.expose.https,省略时HTTP。files指定domain、certificateFile、privateKeyFile(相对工程根),校验域名/期限/密钥并复制到私有包。letsencrypt指定domain、email、acceptTerms:true,HTTP hostPort必须80,公网DNS、80入站及CA出站须可达。固定版本官方Certbot申请并每12小时检查续期,Nginx自动重载。仅单域名HTTP-01,无DNS/通配符。HTTPS默认443、redirectHttp默认true;--yes复用配置。启停或改模式/域名/端口/本地证书需全量。状态在服务器https/acme及按域名隔离的https/certificates目录,需备份;续期失败保留旧证书并须及时处理,隔离目标用已有证书。打包/plan不申请证书。
|
|
51
|
+
|
|
52
|
+
files 只接收末级无软链接或硬链接的普通 PEM 文件,每份最多 1 MiB,父目录仍须可信。Certbot `live/` 软链需安全复制为受控目录中的普通文件,或使用框架 `letsencrypt` 模式。
|
|
53
|
+
|
|
54
|
+
默认.tar.gz,显式--output release.tar为未压缩,README仅外层。镜像从解包目录导入,release只留配置/恢复状态;成功后清理本次incoming,失败保留诊断。中间件归档按镜像内容ID缓存且复用前验摘要。
|
|
55
|
+
|
|
56
|
+
Serv 生产登录的刷新 Cookie 默认带 `Secure`。受控内网或 VPN 的 HTTP 部署可在所选 `.env.prod.local` 配置 `HAI_SERV_REFRESH_COOKIE_SECURE=false` 和实际 `HAI_SERV_CORS_ORIGIN`,再重新部署后端。仅在工程使用 Serv 且已交付 `hai-serv` 时读取该技能 `reference.md` 的“Cookie 规格”;Kit 应用按自己的 `hai-kit` 认证契约处理,不加载未交付的 Serv 技能。
|
|
57
|
+
|
|
58
|
+
## 后端运行配置重载
|
|
59
|
+
|
|
60
|
+
SvelteKit SSR 的 HTTP/HTTPS 部署均通过独立 `gateway`,SSR 容器不映射公开端口。网关覆盖 Host 与标准转发头;Compose 固定 adapter-node 的协议/主机/客户端地址信任,业务 `.env.runtime` 不能覆盖。adapter-node 6 不再读取运行期 `ORIGIN`,旧直接公开 SSR 的部署必须重新生成全量交付包;源应用默认不固定 `paths.origin`,保持镜像跨环境复用。
|
|
61
|
+
|
|
62
|
+
外层 TLS 终止时,独立 gateway 只接受 `trustedEdgeProxies` 白名单真实对端的单值 `http` / `https` 协议;外层必须覆盖 Host/XFF/协议头。未授权来源或组合值使用 gateway 自身协议,不直接透传外部 Forwarded、主机/端口转发值。
|
|
63
|
+
|
|
64
|
+
交付 README 仅列初始账号变量名及所选环境文件或 `process.env` 来源,不打印密码。Fullstack 初始密码在创建工程时生成,部署带入已有值;已有账号不因环境变量变更重置密码或恢复旧职责,自定义应用以实际引导逻辑为准。
|
|
65
|
+
|
|
66
|
+
独立读取的核心环境、职责账号初始密码和传输密钥环保留进程语义,不能仅按前缀判定已失效;Node 启动参数及私有代理标记由部署装配提供,不在运行文件重复保留无效项。
|
|
67
|
+
|
|
68
|
+
生成端优先写细项,数组保留 JSON;手写 JSON 允许兜底,放在对应模块细项之前。同源细项覆盖 JSON,动态字典、JSON 文本和显式空对象保留原义;整体替换展开时以最上层 `{}` 标记阻止旧 YAML 字段恢复。容器路径只写交付配置,不反写工程源环境。
|
|
69
|
+
|
|
70
|
+
Node 后端(Serv / SvelteKit SSR)每次启动读取服务器 `<部署目录>/config/.env.runtime`。应用配置与托管连接在此合并,修改 `HAI_STORAGE_PUBLICENDPOINT` 等细项后重启对应后端即可;同一来源的细项覆盖父 JSON。配置目录只读挂载到 `/run/hai/config`,编辑器原子替换文件也会被下一次启动读取。私有代理标记和 Node 启动参数由部署装配管理;静态 Web、中间件原生环境、端口/挂载、Nginx 路由与限额变更仍需部署。仅更新 Web/中间件保留当前应用配置;后端局部更新保留服务器托管连接,其余值来自新包,全量更新采用新包并按已有凭据状态定稿。手工修改先备份,长期配置同步回源环境。
|
|
71
|
+
|
|
72
|
+
运行文件固定为 `<部署目录>/config/.env.runtime`,只读挂载目录到 `/run/hai/config`;各 release 保留配置快照。单文件不超过 1 MiB,缺失、不可读、重复变量或超限阻止启动;dotenv 字面解析不执行 shell。同源细项覆盖 JSON,显式进程 HAI 配置优先。修改后重启、验健康和受影响业务,失败恢复备份再重启。
|
|
73
|
+
|
|
74
|
+
每个部署包的外层 `README.txt` 和归档内 `APPLY.txt` 都包含文件索引、环境优先级、当前包的变量名和排障步骤。解包目录的 `config/.env.runtime` 是发布输入,部署根下的是当前运行配置,`releases/<ID>/` 下的是历史记录。外部 PostgreSQL 改密后更新项目源环境并发布后端。部署校验拒绝 URL 与分字段密码冲突,增量切换外部与随包中间件需要改用全量发布。 `HAI_SERV_REFRESH_COOKIE_SECURE` 独立于 `HAI_SERV` 父配置,容器部署接受 `true`、`false` 或空值。
|
|
75
|
+
|
|
76
|
+
部署归档顶层包含 `apply.sh`、`APPLY.txt`、`manifest.json`、`config/`、`images/` 和 `.hai/`。`config/.env.runtime` 是唯一应用环境文件;`manifest.json.metadata` 集中保存依赖、布局、健康路径、镜像列表、受管绑定等非敏感元数据。`.hai/compose.json` 是完整服务快照;局部更新在服务边界替换并保留未选服务,不串联历史 Compose 文件。`.hai/` 还存原生环境、加载器、Nginx/TLS、策略和校验和,秘密不写入 manifest。辅助脚本合入 `apply.sh`。失败时先恢复原应用配置再恢复服务,凭据、后端账本和数据卷继续保护。新包格式为 2,不实现旧目录兼容或迁移。
|
|
77
|
+
|
|
44
78
|
## CLI
|
|
45
79
|
|
|
46
80
|
```sh
|
|
47
81
|
pnpm run deploy --env prod --build
|
|
48
|
-
pnpm build --target
|
|
82
|
+
pnpm build --target image
|
|
49
83
|
pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId>
|
|
50
84
|
pnpm run deploy --env prod --bundle-only
|
|
51
|
-
pnpm build --target
|
|
85
|
+
pnpm build --target image --images web
|
|
52
86
|
pnpm run deploy --env prod --services web
|
|
53
87
|
```
|
|
54
88
|
|
|
@@ -72,6 +106,8 @@ S3 的内部 endpoint 与预签名 publicEndpoint 分开;后者无默认,填
|
|
|
72
106
|
|
|
73
107
|
deploy.init 后检查 HaiResult.success,deploy.deployApp 接收 artifactDir、bundleOnly、selectedServices、runtime 与 onProgress;finally 中 deploy.close。deploy.scan 和 deploy.credentials.* 不依赖 init。Vercel 只消费已有 .vercel/output,不执行源码构建,也不支持 Compose 离线/部分更新。
|
|
74
108
|
|
|
109
|
+
下载源由 `--image-source official|cn|custom` 控制构建和打包中间件,`--npm-source` 只随 `--build` 作用于 Corepack/pnpm。SDK 的 DeployAppOptions.imageSource 接收 `{ type, registries? }`,proxy 接收 `{ mode, url?, bypass? }`;resolveImageReference / resolveDownloadProxy 是无 init 的解析工具。配置、优先级与代理边界见 [hai-build 下载源与代理](../hai-build/reference.md#下载源与代理)。SDK 拉取子进程会覆盖代理变量,远程引擎仍需自身设置;镜像归档保持原始标签。
|
|
110
|
+
|
|
75
111
|
内部命令工具须显式枚举 `secrets`(包括转换后的敏感字面量),成功/失败/回调均跨块脱敏;不得向日志附加原始异常 cause。捕获默认每流末尾 1 Mi 字符,结构化消费先检查截断标志;异步输出回调按序等待并保持 pipe 背压。进度每行最多解析 512 字符,超时后确认远程执行状态。详细边界见 [middleware.md](middleware.md#命令输出)。
|
|
76
112
|
|
|
77
113
|
超时或输入/输出失败会终止本地受管理 Job/进程组并等待核验;Windows 用系统 PowerShell/.NET 内嵌 Job,先挂起创建、分配成功才恢复,失败不降级裸进程;POSIX 后代须保留继承的进程组。`terminationTimeoutMs` 默认 10000、最大 60000 毫秒,核验失败返回 unknown。失败分支用 `getDeployCommandState(error)` 读取 localTermination 和 remoteExecution;CLI 分别显示。本地已退出不能证明 SSH 远端停止;仅新连接读到完整、ID 匹配的原子结果才确认 finished,给出结果路径/退出码。未知状态不自动重跑发布或回滚,先核对 current、步骤和实际服务。
|
|
@@ -84,7 +120,7 @@ Linux 预备 Docker/Podman、支持 --pull never 的 Compose(Docker Compose v2
|
|
|
84
120
|
|
|
85
121
|
按 [分轮验证与集中修复](../hai-app-tests/validation.md) 收集适用的 typecheck、lint、build、test、scaffold gates 和 test:deploy-gates,汇总后集中修复、再验证。实际验证无 registry 网络的首次部署、登录刷新、同版本重发、只更新 Web/API、停止/down 后增量恢复、缺密码隐藏输入、上传进度、损坏归档、缺基线、健康失败与恢复。Windows/Linux/macOS 上传入口分别执行验收;原生安装包在对应 OS 验证。测试临时工程、容器、镜像、数据和进程在 finally/teardown 清理,只清理测试拥有的资源;日志、截图和报告保留到分析和交付结束再清理。
|
|
86
122
|
|
|
87
|
-
部署前可 hai deploy --env prod --plan
|
|
123
|
+
部署前可 hai deploy --env prod --plan,只读校验真实制品和执行范围,显示工程根root、服务源码/配置目录serviceDir、项目/环境、版本/构建、配置文件及键名、保留范围、基线要求和恢复目录;不构建、不创建凭据、不连接或改变目标。远端 current 未读取标 not-inspected;不得把计划或本地打包当真实基线成功。数据库与业务数据不随 Compose 恢复回退。
|
|
88
124
|
|
|
89
125
|
需要核对目标真实基线时加 --inspect-remote(必须配合 --plan),仅 SSH 读取 current/成功发布目录,按 verified/missing/unavailable 与真实发布 ID 报告,不写目标;不能把未检查当作成功。
|
|
90
126
|
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## 环境先行
|
|
6
6
|
|
|
7
|
-
自建 S3 还要区分内部 endpoint 和浏览器 publicEndpoint;后者是 HTTP(S) origin
|
|
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
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`。
|
|
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.gz`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
|
|
10
10
|
|
|
11
11
|
资源身份和制品格式沿用[构建技能](../hai-build/SKILL.md)及[网站挂载目录](../hai-build/paths.md):根目录格式4,非根目录格式5,两者都有primaryService/hasWeb;webBasePath仅格式5。旧工程同步镜像角色、Dockerfile、-serv包名与引用后重建,不手改清单。旧部署先核对项目名、卷和受管凭据,再建立完整基线;工具不跨项目迁移数据,改target目录不能完成迁移。
|
|
12
12
|
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
|
|
15
15
|
构建与部署配置统一在项目根 `hai.json`:`build` 保存 images/desktop,`deploy` 保存 provider/container/services 等项目级配置。服务目录只扫描运行依赖与模块 YAML。`deploy` 支持 `${变量:回退值}` 和 `HAI_DEPLOY_*` 分层覆盖;父对象可用 JSON 整体覆盖,缺省 SSH 节点可由 Schema 已知字段补齐,不接受未知字段。高层来源父对象覆盖低层叶字段,同一来源叶字段优先。凭据不要直接写入 hai.json。构建不读取部署环境或密钥。
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
公共配置保存在 `.env` 和 `.env.<mode>`,连接凭据与 SSH 配置保存在忽略 Git 的 `.env.<mode>.local`,`.env.local` 用于本机共享私有值。构建不读取部署秘密。
|
|
18
18
|
|
|
19
19
|
部署 SDK 的来源优先级从高到低为:
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
- 普通模块:进程 > `.env.<mode>.local` > 旧 `.env.local` > `.env.<mode>` > `.env`,保留旧私有凭据优先级。
|
|
21
|
+
所有 `HAI_*` 统一使用:进程 > `.env.<mode>.local` > `.env.local` > `.env.<mode>` > `.env` > YAML。同来源 JSON 为基础,细项继续覆盖;高来源整段替换先清掉低来源细项。Node/Vite 与部署共用 Core 合并,不维护模块专用顺序。
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
`.env.<mode>.local` 同时用于普通开发、Node 启动和部署;通过公共 Core 工具合并,不实现模块专用来源顺序。
|
|
25
25
|
|
|
26
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
27
|
|
|
@@ -31,11 +31,15 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
|
|
|
31
31
|
|
|
32
32
|
分批启动仅在首批清理孤立容器,后续 serv/Web 启动必须保留已经就绪的中间件。
|
|
33
33
|
|
|
34
|
-
生成时为 `.env.dev/.env.test/.env.prod`
|
|
34
|
+
生成时为 `.env.dev.local/.env.test.local/.env.prod.local` 分别生成独立的初始管理员密码和传输密钥环;文件不提交 Git,克隆后通过受保护配置分发对应环境秘密,并可通过本机私有文件或进程环境覆盖。启用 transport 的应用缺少/错误配置 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING` 时,部署在上传前指出配置来源;同一环境的所有节点可直接加载环境文件中的同一有效密钥环,也可由 Secret Manager 覆盖;不为每个节点临时生成。CLI 完成部署后提示 `HAI_ADMIN_DEFAULT_PASSWORD` 的实际来源,不打印密码,不依赖日志级别;该密码仅在首次创建管理员时生效。 离线入口也会提示服务器私有 `.env.runtime` 中的密码变量位置。
|
|
35
35
|
|
|
36
36
|
## 识别与逐项选择
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
默认和自定义模式均从同后端的有效配置继续,不能按表单重建对象而丢掉未展示项。自建/云开通保留连接池、操作日志、公开端点/前缀、Redis 重试、向量检索、SMTP 发件人及 LDAP 属性映射,仅由实际服务定稿地址与认证;旧 URL、TLS/集群选择器不能覆盖新服务。切换后端清除不兼容字段。生成端优先写细项,数组保留 JSON;手写 JSON 允许兜底,放在对应模块细项之前。同源细项覆盖 JSON,动态字典、JSON 文本和显式空对象保留原义;整体替换展开时以最上层 `{}` 标记阻止旧 YAML 字段恢复。容器路径只写交付配置,不反写工程源环境。
|
|
39
|
+
|
|
40
|
+
中间件原生变量(`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*`)按镜像契约保留原名,只写私有 `.hai/middleware-runtime.env`,仅由中间件读取。应用连接全部合并到 `config/.env.runtime`。
|
|
41
|
+
|
|
42
|
+
外部 PostgreSQL 改密后,更新项目私有环境中实际生效的 URL 或分字段密码,再发布后端。打包校验会报告冲突字段名。`managed-secrets.env` 只由受管中间件使用,随包 PostgreSQL 已有数据卷时须通过数据库维护协调真实账号和受管状态。增量发布拦截外部与随包中间件的归属切换。
|
|
39
43
|
|
|
40
44
|
数据库连接保存前复用所选后端的公开配置 Schema;MySQL `ssl` 仅 `false` 或严格对象,`{}` 默认验证证书链和 DNS 身份,`ca/cert/key` 为 PEM 内容且 `cert/key` 必须成对;私钥仅进入私有环境。PostgreSQL 保留其布尔值/字符串模式/对象契约。CLI 内联 `@h-ai/reldb/schemas` 与 Zod,无需为配置校验给目标应用额外安装数据库包或驱动;部署本身仍需已安装的 `@h-ai/deploy`,实际运行应用仍需其数据库依赖。
|
|
41
45
|
|
|
@@ -58,7 +62,7 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
|
|
|
58
62
|
|
|
59
63
|
1. **使用默认配置**:选择后端;Compose 生成匹配容器/卷,云平台调用已支持的 Provisioner,并保存实际连接配置。MySQL、LDAP、向量库等没有云自动开通器时,明确提示改用自定义连接;不能声称已经创建云资源。Resend 需要已验证的发件域名,R2 需要已有 S3 访问密钥,阿里云短信需要签名/模板与额度。
|
|
60
64
|
2. **使用自定义配置**:逐项输入所选后端的连接字段,展示字段用途与约束,校验必填项、端口、布尔和 URL;凭据用密码输入。保存配置后跳过该服务的开通与 sidecar。
|
|
61
|
-
3.
|
|
65
|
+
3. **保持不变**:仅在目标环境的 `.env.<mode>` 和 `.env.<mode>.local` 显式声明当前后端及完整连接配置时出现;私有凭据也可来自共享 `.env.local` 或进程。选择后不修改该项、不认证其 Provisioner、不创建或移除已有中间件容器,继续下一项。只有共享或其他环境有配置不满足此条件。
|
|
62
66
|
|
|
63
67
|
逐项配置前提供“环境配置已完备,直接部署”。选择后跳过全部中间件提示、变量改写、云资源与 sidecar 创建,保留已有服务;仍校验已有构建产物并执行部署及健康检查。命令行使用唯一的 `--skip-middleware`,SDK 使用 `skipMiddleware`。不要因为缺少某项中间件的目标文件声明而阻止用户主动跳过。
|
|
64
68
|
|
|
@@ -90,25 +94,33 @@ AI 使用 MySQL 的首次建表需 CREATE 与 INDEX 权限,节点可并发初
|
|
|
90
94
|
|
|
91
95
|
以下是自定义向导的连接字段;完整可用项、枚举与范围仍以项目 `.env.example` 和公开 Schema 为准。变量前缀为 `HAI_DB`、`HAI_CACHE`、`HAI_STORAGE`、`HAI_VECDB`、`HAI_IAM_LDAP`;Reach 使用实际索引 `HAI_REACH_PROVIDERS_<index>`。camelCase 不拆词,例如 `bindPassword` → `BINDPASSWORD`。
|
|
92
96
|
|
|
97
|
+
HTTP API 的全部自定义请求头整体写入私有环境文件,不能按头名猜测秘密。迁移已有 dotenv 项会处理行首空格/Tab、export 与多行引号,并移除同模式公共文件中的旧值;操作后仍核对私有文件与忽略规则,不在日志中输出值。
|
|
98
|
+
|
|
93
99
|
| 后端 | 连接字段 |
|
|
94
100
|
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
95
101
|
| SQLite | database(文件路径或 `:memory:`) |
|
|
96
|
-
| MySQL / PostgreSQL | url
|
|
97
|
-
| Redis | url
|
|
102
|
+
| MySQL / PostgreSQL | url 或 host、port(1–65535)、database、user、password;ssl 可单独配置 |
|
|
103
|
+
| Redis | url 或 host、port、password、db;tls、keyPrefix、connectTimeout、commandTimeout 可单独配置 |
|
|
98
104
|
| local / LanceDB | root / path |
|
|
99
105
|
| S3 | endpoint、bucket、region、accessKeyId、secretAccessKey、forcePathStyle |
|
|
100
106
|
| Qdrant / Chroma | url;Qdrant 可选 apiKey;Chroma apiKey 用于 Bearer 自托管网关,URL 仅支持 HTTP(S) 根端点,不提供 Cloud 契约 |
|
|
101
|
-
| pgvector | url
|
|
107
|
+
| pgvector | url 或 host、port、database、user、password |
|
|
102
108
|
| LDAP | url、bindDn、bindPassword、searchBase、searchFilter、usernameAttribute、emailAttribute、displayNameAttribute、useTls、connectTimeout |
|
|
103
109
|
| SMTP | host、port、secure、user、pass、from |
|
|
104
110
|
| HTTP API | url、method(POST / PUT)、headers(JSON)、timeout |
|
|
105
111
|
| 阿里云 SMS | accessKeyId、accessKeySecret、signName、endpoint |
|
|
106
112
|
|
|
113
|
+
对 PostgreSQL、MySQL、Redis 和 pgvector,先选 URL 或分字段。URL 以隐藏方式输入,保存后只显示协议、主机和端口。PostgreSQL 和 pgvector 从 URL 路径提取数据库名以满足模块 Schema。Redis URL 可带逻辑库编号,例如 `rediss://redis.example.com:6379/4`。重新配置时只保存所选方式涉及的连接字段。同一后端的连接池等其他设置会保留;如果共享 `.env.local` 中还有同组配置,整组生成值写入目标环境的私有文件以覆盖旧值。
|
|
114
|
+
|
|
115
|
+
自定义 S3 的 `endpoint` 填后端可访问的 HTTP(S) API 地址,例如 `http://storage.example.com:9000`。桶名只填 `bucket`。AWS S3 可留空,由 SDK 按 `region` 选择地址。`forcePathStyle=true` 使用 `endpoint/bucket`,`false` 使用 `bucket.endpoint`,以存储服务要求为准。浏览器签名入口使用 `publicEndpoint`,凭据使用独立的 `accessKeyId` 与 `secretAccessKey`。
|
|
116
|
+
|
|
117
|
+
生产模板的 `HAI_REACH_PROVIDERS='[]'` 要求显式配置通知服务。空列表时,交互式部署提示所选环境的私有文件路径。部署前在 `.env.prod.local` 或部署进程中用 `HAI_REACH_PROVIDERS` 设置完整的非空 JSON 数组,再运行 `deploy` 逐项配置。列表位于环境私有文件时,向导将逐项修改保存在同一文件。HTTP API 请求头以隐藏方式输入。若扫描报告空列表与 `HAI_REACH_PROVIDERS_<index>` 冲突,移除旧向导留下的索引变量,再设置完整列表并重新扫描。
|
|
118
|
+
|
|
107
119
|
## 离线准备与验收
|
|
108
120
|
|
|
109
121
|
构建与部署可分开,也可通过 pnpm run deploy --build 明确串联。构建保持环境无关;部署选择环境并只消费所选镜像。完整包自动包含 Compose 自建中间件镜像,因此导出阶段需要本地 Podman/Docker,缺镜像在打包阶段准备,不能留给隔离服务器下载。
|
|
110
122
|
|
|
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
|
|
123
|
+
每次离线交付都放在单一 .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,由脚本自动解包并执行部署。仅复制归档时,解压后阅读同目录的 `APPLY.txt`,使用 `sh ./apply.sh` 或传入部署根目录。每步失败返回非零,结果写 result-<部署ID>.json;只有 HTTP 检查通过才更新服务器 current。
|
|
112
124
|
|
|
113
125
|
离线 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
126
|
|
|
@@ -118,7 +130,7 @@ manifest.json 的 partial 与 selectedServices、apply 脚本共同记录部署
|
|
|
118
130
|
|
|
119
131
|
生成 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
132
|
|
|
121
|
-
完全离线构建另需基础镜像、Linux 依赖缓存、pnpm 和匹配驱动/Node ABI/架构/libc
|
|
133
|
+
完全离线构建另需基础镜像、Linux 依赖缓存、pnpm 和匹配驱动/Node ABI/架构/libc 的原生预编译包。联网准备可选 --image-source / --npm-source 的 official、cn、custom;npm 参数随 --build 使用。代理通过 --proxy-mode 及 --proxy-url / --proxy-bypass 配置,--no-http-proxy 等价 none;镜像拉取端还需配置引擎代理。具体契约见 [下载源与代理](../hai-build/reference.md#下载源与代理)。SQLite 13 的原生二进制随 npm 包交付,不再需要独立镜像参数;deploy 不下载编译环境。生产 HTTPS、CORS、证书、DNS 另行准备。实际断网验收登录、刷新、重启和数据持久化。
|
|
122
134
|
|
|
123
135
|
## 命令输出
|
|
124
136
|
|
|
@@ -12,7 +12,7 @@ description: "升级应用的 hai-framework 到最新或指定发布版本:分
|
|
|
12
12
|
| 能力 | 发现最新发布版本,比较当前到目标的累计差异,处理选择与阻塞,完成应用升级及 skills/AI 入口同步 |
|
|
13
13
|
| 适用场景 | “升级 Hai-framework 到最新版本”、指定版本升级、版本差异审查、模板同步或 npm/本地联调漂移排查 |
|
|
14
14
|
| 输入 | 当前应用、升级目标及已有约束;当前版本、registry、架构与本地覆盖从项目读取,不要求用户预先提供框架源目录 |
|
|
15
|
-
| 输出 |
|
|
15
|
+
| 输出 | 当前/目标版本及来源、框架能力复用与冗余清理、差异与处理清单、迁移后的依赖/代码/配置/skills、验证结果。未完成时给出选择或阻塞及恢复步骤 |
|
|
16
16
|
| 限制 | 仅操作授权项目,保留已有改动、架构和私有规则;以实际发布产物为准,未确认选择或未解除阻塞不得越过 |
|
|
17
17
|
|
|
18
18
|
## 任务入口
|
|
@@ -61,7 +61,9 @@ npm view @h-ai/cli dist-tags --json
|
|
|
61
61
|
- 公开入口、API/类型/错误码、HaiResult 与流/抛错语义、初始化依赖和关闭行为。
|
|
62
62
|
- 配置 schema、默认行为、环境覆盖、认证/安全策略、DB schema/迁移、外部服务与引擎要求。
|
|
63
63
|
- 构建/运行/发布脚本、第三方 peer 依赖、原生/容器集成,以及版本绑定的补丁是否仍必要。
|
|
64
|
-
- skills 及相邻资源、AGENTS/Claude/Copilot/OpenCode
|
|
64
|
+
- skills 及相邻资源、AGENTS/Claude/Copilot/OpenCode 路由。
|
|
65
|
+
|
|
66
|
+
按应用实际需求逐项对照本次升级范围内的自定义实现与目标发布版的公开 API、配置和扩展点。优先采用能满足业务规则、权限边界、数据兼容和失败处理要求的框架能力。列明替换依据、需迁移的调用方、可清理的重复实现和仍需保留的业务逻辑。框架只覆盖部分需求时,记录具体缺口及验证证据。按 [能力选择规则](../hai-app-create/development.md) 核对模块与应用架构的适配性。
|
|
65
67
|
|
|
66
68
|
先给出可追踪的差异清单,再执行迁移:
|
|
67
69
|
|
|
@@ -73,11 +75,13 @@ npm view @h-ai/cli dist-tags --json
|
|
|
73
75
|
|
|
74
76
|
| 类别 | 处理方式 |
|
|
75
77
|
| --- | --- |
|
|
76
|
-
| 自动处理 |
|
|
77
|
-
| 用户选择 |
|
|
78
|
+
| 自动处理 | 目标明确且保持现有行为的依赖更新、兼容性修正、等效框架能力替换与冗余清理、无冲突的 skills 合并和验证,直接执行 |
|
|
79
|
+
| 用户选择 | 目标版本需依赖补丁、改变配置契约或关键流程行为,或有影响产品行为、架构、成本、Provider 或运维方式的取舍时,说明方案并等待用户明确决定 |
|
|
78
80
|
| 阻塞 | 无法取得必要产物、依赖不兼容、无法无损合并、必要工具/服务/授权缺失等导致后续无法执行,先处理可自行解决的原因;仍无法推进时说明具体步骤。普通门禁失败先记录,继续独立检查,本轮汇总后集中修复;必要门禁未通过仍不能交付完成 |
|
|
79
81
|
| 不适用 | 当前应用未使用且不影响其依赖/运行的变化,记录依据;不要求用户逐项确认 |
|
|
80
82
|
|
|
83
|
+
- 框架能力不足且考虑使用补丁时,说明目标版本的缺口、拟改范围、兼容风险、后续维护成本和移除条件。给出经核实可行的选项,例如保留兼容的应用实现、采用目标版本的最小补丁或暂缓升级。用户明确选择补丁方案后再为目标版本新增、沿用或重建补丁。
|
|
84
|
+
- 配置或关键流程有变动时,实施前提示用户,说明变更前后、受影响的环境与调用方、需配合的操作及验证和回退方式。覆盖配置项、环境变量、默认值、覆盖顺序,以及初始化、认证授权、数据读写和部署等关键流程。仅由版本升级触发的默认值变化也须列出。保持配置契约和关键流程行为的等效迁移在提示后实施。改变其中任一项时,即使只有一条可行路径也要等用户明确确认。
|
|
81
85
|
- 尽量合并相互独立的选择,明确每个回答控制哪项改动;已给出的目标、授权和选择持续有效,不重复询问。
|
|
82
86
|
- 提问时给出问题位置、事实、影响、可选路径及推荐。用户未回答时保持选择待定,可继续独立分析/验证;不能以等待超时替用户选择,也不能先安装一部分框架包造成混版本。
|
|
83
87
|
- 阻塞报告包含失败命令、退出码、脱敏关键错误、受影响步骤、已尝试处理、用户最小操作和解除后的验证方式。不要求在聊天中粘贴密钥,不通过关闭检查、忽略 engines 或无依据覆盖依赖掩盖失败。
|
|
@@ -87,19 +91,19 @@ npm view @h-ai/cli dist-tags --json
|
|
|
87
91
|
|
|
88
92
|
必要选择和安装阻塞解除后,按既有包管理方式更新所有已用框架包的精确版本,统一修改相关 package.json/catalogs/overrides。保留应用 workspace 协议及无关依赖;必要 peer 更新须来自目标契约,禁止无差别升级全部依赖。
|
|
89
93
|
|
|
90
|
-
1.
|
|
91
|
-
2.
|
|
94
|
+
1. 按差异清单和用户决定迁移调用方、类型、配置、环境变量说明、初始化和构建入口。等效替换时先迁移全部相关调用,确认旧实现已被完全替代且无剩余引用后,删除重复代码、纯转发适配层及仅供旧实现使用的依赖和配置,保留项目特有的业务逻辑。生命周期模块遵循 init → use → close,core/serv/纯函数按各自契约使用。
|
|
95
|
+
2. 用目标版本回归核验已有补丁与本地覆盖。按用户选择和项目包管理器的补丁机制为精确目标版本维护补丁,记录适用范围、验证与移除条件。上游已覆盖且回归通过后,按清单移除冗余补丁。npm 升级遇到本地联调映射时,明确恢复 npm 或继续本地验证的选择,不能只改版本号却继续运行旧源码。
|
|
92
96
|
3. 使用当前包管理器安装并更新 lockfile,保留失败诊断;不手改 lockfile 的解析字段。安装后从**各消费 workspace**核对真实版本、公开 exports/类型及框架传递依赖,检查残留旧版/重复解析和本地路径。
|
|
93
97
|
4. 按 [同步规则](sync.md) 合并目标 CLI 中适配本架构的完整 skill 目录及 AI 入口。对“旧发布模板、应用现有文件、新发布模板”比较,保留仍适用的私有规则/自定义技能;已明确的业务需求优先于模板默认值,仅未决冲突转为选择。没有旧模板时先辨识私有内容,不直接覆盖。同步版本必须与目标运行时一致。
|
|
94
|
-
5. 同步受影响的 README、配置样例、skill
|
|
98
|
+
5. 同步受影响的 README、配置样例、skill 与测试,逐项更新差异清单状态。即使已处于目标版本,也核验能力替换项及解析、配置和 skills 漂移。版本一致且清单无待处理项时,报告无需升级。
|
|
95
99
|
|
|
96
100
|
### 6. 验证与交付
|
|
97
101
|
|
|
98
102
|
按应用实际 scripts 和 [分轮验证与集中修复](../hai-app-tests/validation.md) 先收集一轮适用门禁,汇总根因后集中修复、再验证;优先受影响 workspace,跨包契约验证所有消费者。按 [hai-app-tests](../hai-app-tests/SKILL.md) 选择集成/E2E,覆盖启动/关闭、变更 API、认证、持久化等实际路径;CI/发布按 [hai-ci](../hai-ci/SKILL.md) 保留失败阻断。
|
|
99
103
|
|
|
100
|
-
-
|
|
104
|
+
- 依赖升级后核对 lockfile 与安装版本、公开入口、各受影响环境的配置生效值和关键流程。对框架能力替换回归原业务规则、权限与失败路径;有补丁时核验按 lockfile 重装可复现。build 通过不能替代 typecheck 或运行验收。
|
|
101
105
|
- 检查同步后的全部相邻资源、相对引用和各工具入口;目标存在 `check:skills` 时运行,不假定应用具有框架仓库私有脚本。
|
|
102
106
|
- 修复本次引入的失败,区分升级前已有失败。必要验收缺服务/凭证/平台时提示阻塞;额外平台或未涉及的真实 Provider 验证明确标为未执行及原因,不能用 mock/Web 结果冒充真实/原生验证。
|
|
103
|
-
- 最终报告当前 →
|
|
107
|
+
- 最终报告当前 → 目标及来源、复用的框架能力与清理项、补丁等用户决定、配置与关键流程的变动、变更文件与同步入口、实际门禁和未验证边界、恢复方法。依赖与必要迁移完成、选择/阻塞已解除且必要验证通过才称“升级完成”;否则报告当前进度与下一步,用户处理后继续完成。
|
|
104
108
|
|
|
105
109
|
指定精确版本后先 hai upgrade <version>,一次核对实际消费包及 CLI/deploy 发布完整性、制品/skills、catalog/lock/安装漂移和业务定制。此命令只读,缺包不得先改工程;报告完整后再按本 skill 执行获授权的升级,合并定制不覆盖。数据库迁移单独停旧写入、备份、migrateIam/migrateReach/migrateScheduler 预检;无凭据代次的旧会话重新登录。
|
|
@@ -18,6 +18,8 @@ hai-framework 是通用能力和 skill 模板的源头;应用仓库消费这
|
|
|
18
18
|
|
|
19
19
|
## 同步完整技能与入口
|
|
20
20
|
|
|
21
|
+
依赖补丁必须与引用它的 pnpm 配置一起复制并验证安装。当前 DaisyUI 5.7.50 的 join 补丁是 CSS 构建兼容修复,**不是安全漏洞补丁**:它以零特异性的 `:where(:scope)` 避免优化器丢弃聚焦/悬停层级,依据 [官方问题](https://github.com/tailwindlabs/tailwindcss/issues/20668) 与[上游修复 PR](https://github.com/tailwindlabs/tailwindcss/pull/20671)。升级后验证实际 compile/optimize 与界面再决定移除;不要靠关闭优化或隐藏警告处理。纯 API 没有 UI/Svelte 构建依赖,不注册未使用的 DaisyUI/deepmerge 补丁;不能用安装豁免掩盖模板依赖差异。
|
|
22
|
+
|
|
21
23
|
通过 CLI 补齐缺失文件时,先按 [CLI 安装与命令](../hai-app-create/development.md#cli-安装与命令) 安装所需精确版本的 `@h-ai/cli` 并检查 `hai --version` / `hai --help`,再从应用根运行 `hai init`。临时使用 CLI 可隔离安装到临时目录;不为读取模板要求全局安装或改变系统级工具。
|
|
22
24
|
|
|
23
25
|
`hai init` 只补缺失内容,即使 `--force` 也不覆盖已有 AI 规则和 skills,不能用它代替旧版本规则合并。未发布模板修正从明确本地来源同步,不能假定已发布 CLI 已包含。
|
|
@@ -73,11 +73,11 @@ rbac:
|
|
|
73
73
|
import type { IamConfigSettingsInput } from '@h-ai/iam'
|
|
74
74
|
import { cache } from '@h-ai/cache'
|
|
75
75
|
import { core } from '@h-ai/core'
|
|
76
|
-
import { iam } from '@h-ai/iam'
|
|
76
|
+
import { iam, IamConfigSchema } from '@h-ai/iam'
|
|
77
77
|
import { reldb } from '@h-ai/reldb'
|
|
78
78
|
|
|
79
79
|
// 位于应用启动函数内;依赖初始化失败时立即返回,不能继续启动 IAM。
|
|
80
|
-
core.init({ configDir: './config' })
|
|
80
|
+
core.init({ configDir: './config', configSchemas: { iam: IamConfigSchema } })
|
|
81
81
|
const db = await reldb.init({ type: 'sqlite', database: './data.db' })
|
|
82
82
|
if (!db.success)
|
|
83
83
|
return db
|
|
@@ -7,7 +7,7 @@ description: "在 SvelteKit 中接入 hooks、认证守卫、输入校验、响
|
|
|
7
7
|
|
|
8
8
|
限流采用首次成功提交为起点的固定窗口,后续请求不延长 TTL。必须显式传 store;应用先检查共享 Redis 初始化结果,所有节点使用相同 namespace/windowMs/maxRequests。缓存读取/条件提交失败或冲突耗尽返回503,超限429;不会回退 get+set 或本地计数。createMemoryRateLimitStore 仅开发或显式 HAI_E2E/HAI_E2E_MOCK 测试使用,无常驻定时器,丢弃引用即可回收;每次请求最多惰性扫描 64 项,最多保存 10000 个窗口,容量满时对新 key 返回503且不驱逐有效计数,外部 store 生命周期由创建者管理;生产不得设置测试开关。响应重置时间为节点时钟估算,实际窗口由 Redis TTL 决定,须同步时钟。默认键只读取可信 adapter 的 getClientAddress、规范化等价IPv6和IPv4映射地址,不采信原始转发头;代理信任通过部署adapter配置。
|
|
9
9
|
|
|
10
|
-
transport 仅支持 v2:SM2 发送方签名、独立密钥的 Encrypt-then-HMAC、HTTP 上下文/响应状态绑定及共享原子防重放。GET/HEAD、空 POST 与空响应也认证;无降级开关。TLS
|
|
10
|
+
transport 仅支持 v2:SM2 发送方签名、独立密钥的 Encrypt-then-HMAC、HTTP 上下文/响应状态绑定及共享原子防重放。GET/HEAD、空 POST 与空响应也认证;无降级开关。TLS 信任边界、可配时间窗口、nonce 持久化与实现示例见 [参考](reference.md)。
|
|
11
11
|
|
|
12
12
|
## 能力契约
|
|
13
13
|
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
# hai-kit 参考
|
|
2
2
|
|
|
3
|
+
HTTP/UI 边界只对明确的有效 4xx 状态公开业务提示;错误缺少 `httpStatus` 或状态非法时按 500 返回安全提示。手写业务错误须提供完整错误定义或显式状态,不能依赖缺省状态展示原文。
|
|
4
|
+
|
|
3
5
|
> `@h-ai/kit` 只负责 SvelteKit 集成:`handle` hook、guard、response、validate、client、auth、crud、A2A。公共跨端 HTTP API 契约统一使用 `@h-ai/api-contract` + `@h-ai/serv`,不要在 kit 中定义业务 API contract。
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
命名空间公开类型为 `KitFunctions`(服务端)与 `BrowserKitFunctions`(浏览器)。浏览器条件入口仅暴露 client、crud、页面 Token 与默认语言操作,不含服务端认证、Hook 或限流。服务端认证 Cookie 的最小写入依赖为根入口的 `AuthCookieWriter`。运行时仍使用 `kit.xx`,导出方法或命名空间的声明不需要内部 helper 或私有构建路径。
|
|
8
|
+
|
|
9
|
+
认证协议仅支持 v2:独立随机 SM4-CBC 密钥和 HMAC-SM3 密钥由 SM2 封装,先验签、再验证 MAC,最后解密 CBC。请求由客户端私钥签名,响应由所选服务端版本签名。认证字段包括 version、direction、serverKeyId、clientId、128 位随机 requestId(兼 nonce)、issuedAt、HTTP method、pathname + 原始 search 的 SM3 pathHash,以及响应 status。请求默认有效期为 5 分钟,客户端时间最多可领先服务器 30 秒。服务端可用 `maxRequestAgeSeconds`(1~600)和 `maxFutureSkewSeconds`(0~300)调整,单位为整数秒。共享 registry 原子消费 (clientId, requestId),nonce 保留到 issuedAt + 11 分钟,覆盖最长可配窗口及节点时钟差,存储故障拒绝请求。Redis 必须保留有效 nonce,使用 noeviction/可靠持久化策略;各节点时钟须同步。此能力防止同一传输消息重放,业务重试仍需自己的幂等键。
|
|
10
|
+
|
|
11
|
+
在 `_kit.yml` 的 `transport` 块配置时间窗口,将字段传给服务端 transport 装配。完成旧节点升级后等待 12 分钟,再把有效期调到 300 秒以上。校时提示与 `TransportTimeError.serverTime` 见 [Crypto 参考](../hai-crypto/reference.md)。`kit.client.createAuthActions()` 将已认证校时错误转为 `HaiResult`,供 AuthPanel 展示。
|
|
6
12
|
|
|
7
13
|
空 POST 也发送空明文的认证封装;GET/HEAD 将封装放在 X-Hai-Transport 头,204/304/HEAD 等无正文响应也使用同名头承载认证封装。其它请求/响应在 JSON 正文承载封装并带 X-Encrypted: true。客户端必须关联原请求上下文和 HTTP status,缺标记、旧格式或认证失败一律 reject;明文接口由 Serv/Kit 路径规则 `encryption: disabled` 或宿主 `excludePaths` 显式允许;调用方同步选择普通请求,API Client/Kit 包装器使用自己的 `excludePaths`。CORS 须允许并暴露 X-Hai-Transport。握手公钥的真实性依赖 TLS,不替代 IAM 业务授权。
|
|
8
14
|
|
|
9
15
|
## 使用步骤
|
|
10
16
|
|
|
17
|
+
错误响应与 Serv 共用 `HaiCommonError`:未认证用 `UNAUTHORIZED.code`、无权限用 `FORBIDDEN.code`、限流用 `RATE_LIMIT_EXCEEDED.code`(429);不要匹配旧的无命名空间字符串。`fromError/fromResult` 保留安全字段校验、`httpStatus` 和追踪编号,内部异常只记录日志。前端使用已本地化的安全消息,排查按 `traceId` 关联服务端原因。
|
|
18
|
+
|
|
19
|
+
`kit.response.validationError(errors)` 同样经 `fromError` 过滤,响应 `error.cause` 只含本地化 `field/message`;不回显 rejectedValue、SQL 或其他字段,不再读取 `details.errors`。
|
|
20
|
+
|
|
11
21
|
### 1. 请求管道
|
|
12
22
|
|
|
13
23
|
```ts
|
|
14
|
-
import type { Handle } from '@sveltejs/kit'
|
|
24
|
+
import type { Handle } from '@sveltejs/kit/hooks'
|
|
15
25
|
import { cache } from '@h-ai/cache'
|
|
16
26
|
import { kit } from '@h-ai/kit'
|
|
17
27
|
|
|
@@ -32,6 +42,8 @@ export const handle: Handle = haiHandle
|
|
|
32
42
|
|
|
33
43
|
### 2. SvelteKit API endpoint
|
|
34
44
|
|
|
45
|
+
业务失败用 `kit.response.fromResult/fromError`,保留安全字段错误、显式 `publicExt` 和 HTTP 状态,内部异常仅进入关联日志;不要在业务 endpoint 手工拼接原始异常。
|
|
46
|
+
|
|
35
47
|
```ts
|
|
36
48
|
import { kit } from '@h-ai/kit'
|
|
37
49
|
import { z } from 'zod'
|
|
@@ -89,12 +101,14 @@ export const handle = kit.createHandle({
|
|
|
89
101
|
})
|
|
90
102
|
```
|
|
91
103
|
|
|
92
|
-
需要保护会话 Cookie 时配置 `crypto.encryptedCookies`,并通过 `crypto.cookieEncryptionKey` 或 `HAI_KIT_COOKIE_KEY`
|
|
104
|
+
需要保护会话 Cookie 时配置 `crypto.encryptedCookies`,并通过 `crypto.cookieEncryptionKey` 或 `HAI_KIT_COOKIE_KEY` 提供密钥。密钥必须为 32 位十六进制。Cookie 采用分离子密钥的 SM4-CBC/HMAC-SHA256,先验证版本、名称、IV 与密文,再解密;旧版无认证 Cookie 升级后失效,需重新登录。缺少或非法密钥会在 `createHandle()` 时失败;加解密错误不会回退到明文 Cookie。
|
|
105
|
+
|
|
106
|
+
不再使用无运行入口的旧 Crypto Helpers 或其 `CryptoServiceLike`、`EncryptedCookieConfig`、`CryptoCsrfConfig`、`WebhookVerifyConfig` 类型;这些已删除。Cookie 通过上述 `kit.createHandle` 配置保护,其他加密能力使用 `@h-ai/crypto` 真实公开 API。
|
|
93
107
|
|
|
94
108
|
```svelte
|
|
95
109
|
<!-- src/routes/+layout.svelte -->
|
|
96
110
|
<script lang='ts'>
|
|
97
|
-
import { browser } from '$app/
|
|
111
|
+
import { browser } from '$app/env'
|
|
98
112
|
import type { LayoutData } from './$types'
|
|
99
113
|
import { crypto } from '@h-ai/crypto'
|
|
100
114
|
import { kit } from '@h-ai/kit'
|
|
@@ -162,7 +176,7 @@ export function load() {
|
|
|
162
176
|
`resolveKitConfig()` 同时解析 `server`(host/port)与 `transport`;host/port 优先级为 `HOST` / `PORT` 环境变量 > `_kit.yml` 的 `server` > 默认 `127.0.0.1:3000`(与 `@h-ai/serv` 同构)。
|
|
163
177
|
`_kit.yml` 在服务端读取,可包含 access 和 trustedProxies;layout data 只投影公开 transport,不通过 ?raw 导入完整文件到浏览器,也不放密钥。如自定义 `keyExchangePath`,浏览器端必须同步映射为 `keyExchangeUrl`。请求策略按[共享约定](../hai-core/request-access.md)装配与验证。
|
|
164
178
|
|
|
165
|
-
|
|
179
|
+
子目录部署在 Vite 的 sveltekit 配置设置 `paths.relative: false`,从 `$app/paths` 用 `resolve('/').replace(/\/$/, '')` 取构建挂载目录 `base`,服务端 `crypto.transport.basePath` 与客户端 `installBrowserTransport(config, { crypto, basePath: base })` 同步;独立 client 的 `transport.basePath` 也用该值。默认空字符串为根目录,不能仅调整资源地址后把登录成功当作加密验证。交换/排除/容量路径保持完整请求路径,验证原始请求带加密标记、缺协议被拒绝、排除接口正常且不影响相邻目录。
|
|
166
180
|
|
|
167
181
|
## 核心 API
|
|
168
182
|
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
## 使用步骤
|
|
28
28
|
|
|
29
|
+
并发调用 `close()` 会使尚未完成的 `init()` 失效,迟到初始化不会重新打开模块;等待该次初始化返回后可再次初始化。
|
|
30
|
+
|
|
29
31
|
### 1. 配置
|
|
30
32
|
|
|
31
33
|
```yaml
|
|
@@ -244,30 +246,52 @@ import { apiContract } from '@h-ai/api-contract'
|
|
|
244
246
|
|
|
245
247
|
### 服务端路由(SvelteKit)
|
|
246
248
|
|
|
249
|
+
应用实现 `readOrder`:从共享数据库读取订单,返回持久化的金额、币种、所有者与支付状态。通知地址取服务端配置;在宿主权限配置中登记并授予 `payment:create`。以下工厂在路由模块中注入这两个可信依赖,`kit.handler` 仅提供错误边界,认证和资源授权仍在示例中显式执行。
|
|
250
|
+
|
|
247
251
|
```typescript
|
|
252
|
+
import type { HaiResult } from '@h-ai/core'
|
|
248
253
|
import { kit } from '@h-ai/kit'
|
|
249
|
-
// src/routes/api/v1/payment/create/+server.ts
|
|
250
254
|
import { payment } from '@h-ai/payment'
|
|
255
|
+
import { z } from 'zod'
|
|
256
|
+
|
|
257
|
+
interface PayableOrder {
|
|
258
|
+
orderNo: string
|
|
259
|
+
ownerId: string
|
|
260
|
+
amount: number
|
|
261
|
+
currency: string
|
|
262
|
+
description: string
|
|
263
|
+
status: 'pending' | 'paid' | 'closed'
|
|
264
|
+
}
|
|
251
265
|
|
|
252
|
-
export
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
266
|
+
export function createPaymentHandler(
|
|
267
|
+
readOrder: (id: string) => Promise<HaiResult<PayableOrder | null>>,
|
|
268
|
+
notifyUrl: string,
|
|
269
|
+
) {
|
|
270
|
+
return kit.handler(async ({ request, locals }) => {
|
|
271
|
+
const session = locals.session
|
|
272
|
+
if (!session) return kit.response.unauthorized()
|
|
273
|
+
kit.guard.require(session, 'payment:create')
|
|
274
|
+
const input = await kit.validate.body(request, z.object({ orderId: z.string().min(1) }).strict())
|
|
275
|
+
const order = await readOrder(input.orderId)
|
|
276
|
+
if (!order.success) return kit.response.fromError(order.error)
|
|
277
|
+
if (!order.data || order.data.ownerId !== session.userId || order.data.status !== 'pending')
|
|
278
|
+
return kit.response.forbidden()
|
|
279
|
+
const result = await payment.createOrder('stripe', {
|
|
280
|
+
orderNo: order.data.orderNo,
|
|
281
|
+
amount: order.data.amount,
|
|
282
|
+
currency: order.data.currency,
|
|
283
|
+
description: order.data.description,
|
|
284
|
+
tradeType: 'h5',
|
|
285
|
+
notifyUrl,
|
|
286
|
+
})
|
|
287
|
+
if (!result.success) return kit.response.fromError(result.error, locals.requestId)
|
|
288
|
+
return kit.response.ok(result.data, locals.requestId)
|
|
261
289
|
})
|
|
262
|
-
|
|
263
|
-
if (!result.success) {
|
|
264
|
-
return kit.response.internalError(result.error.message)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return kit.response.ok(result.data, locals.requestId)
|
|
268
|
-
})
|
|
290
|
+
}
|
|
269
291
|
```
|
|
270
292
|
|
|
293
|
+
在 `+server.ts` 中将可信业务读取函数和通知地址传给工厂,再导出返回值为 `POST`。
|
|
294
|
+
|
|
271
295
|
### 完整支付流程
|
|
272
296
|
|
|
273
297
|
```
|
|
@@ -19,8 +19,10 @@ API 空 2xx 表示受理成功;非空 JSON 回执上限 64 KiB。redirect 默
|
|
|
19
19
|
|
|
20
20
|
## 使用路径
|
|
21
21
|
|
|
22
|
-
-
|
|
22
|
+
- 使用模板先初始化 reldb,再初始化 Reach;非空配置模板的仓库/保存失败会使 init 返回 CONFIG_ERROR 并关闭候选 Provider。单次发送从同一模板快照渲染内容和选择默认 Provider,显式 provider 仍可覆盖;直接发送须提供 provider。启用 DND delay 也必须先初始化 reldb 并确保队列表可用;成功时 `deferred: true` 与 `queueId` 表示可靠入队,尚未投递;缺库、断连或插入失败须按 HaiResult 失败处理。即时投递与排队状态须区分。
|
|
23
|
+
- API 自定义请求头整体视为私密数据,部署时写私有环境文件;`reach.config` 隐藏全部头值,不能只依靠 Authorization/token 等名称识别秘密。
|
|
23
24
|
- 验证模板替换和错误分支时使用隔离测试收件人;真实通知须在用户授权范围内。
|
|
25
|
+
- 阿里云短信的 `gateway` 通过 POST 转发已签名查询,可配置请求头和正文;服务端 `reach.init` 可按 Provider 名注入 `gatewayHooks`。受信内网 HTTP 须显式启用,转发日志应脱敏查询串。
|
|
24
26
|
- 缓存锁只减少扫描,按实际执行逐条领取并在途续租。API 只有接收端真正具备原子持久去重时才能声明 idempotent=true,全部请求固定用 queueId 作为 Idempotency-Key;旧节点迟到请求也必须去重。SMTP/短信/默认 API 的在途失败或过期转 unknown,禁止自动重发;可信服务端用 queue.get/resolveUnknown 在人工隔离旧 worker、核对外部记录后裁定 sent/discarded。
|
|
25
27
|
- queue 重试策略随消息持久保存,默认最多领取 5 次,指数退避 60 秒至 1 小时;永久失败/超限进 dead,满批失败不会原地自旋。可信服务端用 queue.list 查询 dead/unknown;修复根因后以最新 updatedAt 调用 requeueDead,只能恢复 dead,保留同一 queueId 和接收端幂等要求。unknown 不能重排。
|
|
26
28
|
|