@h-ai/cli 1.0.0-beta.5 → 1.0.0-beta.6

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 (54) hide show
  1. package/README.en.md +21 -7
  2. package/README.ja.md +21 -7
  3. package/README.md +21 -7
  4. package/dist/{chunk-VUWM43KR.js → chunk-4XVCGFBA.js} +6123 -714
  5. package/dist/chunk-4XVCGFBA.js.map +1 -0
  6. package/dist/{chunk-YHSX7AQX.js → chunk-7DNIMG2H.js} +89 -14
  7. package/dist/chunk-7DNIMG2H.js.map +1 -0
  8. package/dist/{chunk-YVNNMC4H.js → chunk-STWZQ3IP.js} +59 -3
  9. package/dist/chunk-STWZQ3IP.js.map +1 -0
  10. package/dist/cli-config-templates-YGPVNRX5.js +5 -0
  11. package/dist/{cli-config-templates-LUJGDQNW.js.map → cli-config-templates-YGPVNRX5.js.map} +1 -1
  12. package/dist/{cli-skill-templates-COTP767H.js → cli-skill-templates-S2YH642Z.js} +3 -3
  13. package/dist/{cli-skill-templates-COTP767H.js.map → cli-skill-templates-S2YH642Z.js.map} +1 -1
  14. package/dist/index.js +362 -359
  15. package/dist/index.js.map +1 -1
  16. package/dist/metafile-esm.json +1 -1
  17. package/dist/src-NXCCU6GO.js +5 -0
  18. package/dist/src-NXCCU6GO.js.map +1 -0
  19. package/package.json +11 -11
  20. package/templates/README.md +4 -0
  21. package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +1 -1
  22. package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +4 -4
  23. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +41 -2
  24. package/templates/apps/api/images/serv.Dockerfile.hbs +11 -6
  25. package/templates/apps/fullstack/docs/security-configuration.md.hbs +1 -1
  26. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +11 -6
  27. package/templates/apps/fullstack/images/web.Dockerfile.hbs +11 -5
  28. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +4 -4
  29. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +4 -4
  30. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -2
  31. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +26 -2
  32. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +0 -1
  33. package/templates/base/images/web.Dockerfile.hbs +20 -10
  34. package/templates/base/package.json.hbs +3 -3
  35. package/templates/base/src/lib/server/init.ts.hbs +40 -2
  36. package/templates/shared/run-node.mjs +45 -0
  37. package/templates/skills/hai-ai/guide.md +1 -1
  38. package/templates/skills/hai-app-create/development.md +8 -7
  39. package/templates/skills/hai-build/SKILL.md +4 -1
  40. package/templates/skills/hai-build/reference.md +15 -1
  41. package/templates/skills/hai-core/SKILL.md +2 -2
  42. package/templates/skills/hai-core/reference.md +3 -3
  43. package/templates/skills/hai-core/request-access.md +1 -1
  44. package/templates/skills/hai-crypto/reference.md +1 -1
  45. package/templates/skills/hai-deploy/SKILL.md +8 -4
  46. package/templates/skills/hai-deploy/middleware.md +9 -9
  47. package/templates/skills/hai-iam/reference.md +2 -2
  48. package/templates/skills/hai-serv/reference.md +1 -1
  49. package/dist/chunk-VUWM43KR.js.map +0 -1
  50. package/dist/chunk-YHSX7AQX.js.map +0 -1
  51. package/dist/chunk-YVNNMC4H.js.map +0 -1
  52. package/dist/cli-config-templates-LUJGDQNW.js +0 -5
  53. package/dist/src-24PXSKE6.js +0 -5
  54. package/dist/src-24PXSKE6.js.map +0 -1
@@ -42,6 +42,7 @@ website默认SSR;静态发布须先移除服务端业务依赖、初始化及A
42
42
  | `.env.test` | 测试环境公共覆盖 | 提交 |
43
43
  | `.env.prod` | 生产环境公共覆盖 | 提交 |
44
44
  | `.env.local` | 当前机器的私有配置,覆盖公共配置 | 不提交 |
45
+ | `.env.<mode>.local` | 当前模式的私有覆盖、初始密码和传输密钥环 | 不提交 |
45
46
 
46
47
  YAML 使用 `${HAI_DB_TYPE:sqlite}` 等显式引用,冒号后是未配置时的本地默认值。应用仍通过 `core.config.validate(name, ModuleConfigSchema)` 和模块初始化校验类型、枚举、范围和必填项;插值本身不能代替校验。只开启实际使用的模块,未启用模块的整份 YAML 保留注释。
47
48
 
@@ -51,8 +52,8 @@ YAML 使用 `${HAI_DB_TYPE:sqlite}` 等显式引用,冒号后是未配置时
51
52
 
52
53
  - `HAI_<配置名>_<字段路径>`:`_db.yml` 的 `type` 对应 `HAI_DB_TYPE`;`_ai.yml` 的 `llm.apiKey` 对应 `HAI_AI_LLM_APIKEY`。camelCase 不拆词,数组使用从零开始的索引,如 `HAI_AI_AUDIO_MODELS_0_BASEURL`。
53
54
  - 框架配置统一采用路径命名,如 `HAI_REACH_PROVIDERS_0_PASS`。第三方 SDK 自身读取的 `OPENAI_API_KEY` 等外部变量保留厂商约定;应用 YAML 使用框架标准名。
54
- - 完整变量引用按 YAML 标量还原类型:布尔用 `true/false`,数字不带单位;要保留看似数字/布尔的字符串,在环境值中保留 YAML 引号,例如 dotenv 中 `HAI_AI_LLM_APIKEY='"123456"'`。空字符串保持为空字符串。
55
- - `HAI_DB` 等父级变量可用 JSON/YAML 整体替换对象,优先于子级变量;非必要不整体覆盖,避免遗漏字段。
55
+ - Schema 决定类型:布尔用 `true/false`,数字不带单位;字符串直接填写即可保留前导零,无须再嵌套 YAML 引号。没有 Schema 的自定义配置按已有 YAML/JSON 结构与 YAML 标量规则解析。空字符串保持为空字符串。
56
+ - JSON 对象可作为基础,后续按路径细化;同来源先父后子、与行序无关,高来源整段替换会清掉低来源细项。生成配置优先细项,数组保留 JSON;动态字典与空对象保留原意,JSON 放对应模块细项之前。
56
57
  - `PUBLIC_` / `VITE_` 只用于浏览器可见的 API 地址和非敏感参数。业务正文、模板 ID、表名/列名及数据结构留在代码/YAML;环境参数不能改变固定表结构契约。
57
58
 
58
59
  #### 加载与启动
@@ -62,13 +63,13 @@ YAML 使用 `${HAI_DB_TYPE:sqlite}` 等显式引用,冒号后是未配置时
62
63
  | Vite / SvelteKit | `pnpm dev` | `pnpm dev:test` | `pnpm dev:prod` 预览;build 不选择环境 |
63
64
  | Node service | `pnpm dev` | 构建后 `pnpm start:test` | 构建后 `pnpm start:prod` |
64
65
 
65
- `hai create` 为 fullstack 在 `.env.dev/.env.test/.env.prod` 各自生成不同的 `HAI_ADMIN_DEFAULT_PASSWORD` 和 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING`;API 启用 crypto 时也分别生成 ring。提交这些环境文件后,克隆用户共享对应环境的初始凭据;`.env.local` 默认只保留覆盖说明,进程环境仍最高。运行时不生成或轮换 ring,所有同环境节点使用同一 ring。模板默认 `pretty` 并声明运行依赖 `pino-pretty`,需要 JSON 时覆盖 `HAI_CORE_LOGGING_FORMAT`。启动失败检查模块、错误码和字段路径;监听冲突检查 `EADDRINUSE` 的地址与端口。
66
+ `hai create` 为 fullstack 在 `.env.dev.local/.env.test.local/.env.prod.local` 分别生成初始密码和传输密钥环,API 启用 crypto 时也生成 ring;这些私有文件不提交 Git。克隆后通过受保护配置或 Secret Manager 分发对应环境秘密。同环境节点共享 ring 和 registry,运行时不生成或轮换。模板默认 `pretty` 并声明运行依赖 `pino-pretty`,需要 JSON 时覆盖 `HAI_CORE_LOGGING_FORMAT`。启动失败检查模块、错误码和字段路径;监听冲突检查 `EADDRINUSE` 的地址与端口。
66
67
 
67
- 所有入口优先级一致:**进程环境 > `.env.local` > `.env.<dev|test|prod>` > `.env`**。Vite 配置在 Node 阶段通过 `core.config.loadEnvFiles({ mode, envDir })` 读取,检查 `success` 后注入进程;`development`/`production` 分别映射到 `dev`/`prod`。Node 服务按 `.env`、环境文件、`.env.local` 的顺序传入 `--env-file`,后者覆盖前者,已有进程环境最高。`core.init` 只读取已注入的变量,不自行读取 dotenv。
68
+ 所有入口优先级一致:**进程环境 > `.env.<mode>.local` > `.env.local` > `.env.<mode>` > `.env` > YAML**。Vite 在 Node 阶段通过 `core.config.loadEnvFiles` 读取并检查结果;Node 服务复用 `scripts/run-node.mjs <mode> <环境目录> <入口>`,让来源与对象覆盖规则一致,`NODE_OPTIONS` 在子进程启动前生效。`development`/`production` 映射为 `dev`/`prod`,`core.init` 不自行读取 dotenv。
68
69
 
69
70
  托管 `test:e2e` 是明确的隔离测试入口:服务子进程使用本轮绝对数据目录和完整模块配置,不继承 ambient 模块变量,也不读取用户 `.env.local`。Svelte 仅在 `HAI_E2E=1` 的测试分支跳过 dotenv;API 测试直接执行已构建产物。普通开发与生产的上述优先级和共享后端守卫保持不变,transport 使用测试独立可信 ring 与实际 registry。
70
71
 
71
- `prod` 是文件模式名,对应 `HAI_CORE_ENV=production`;环境枚举为 `development | test | production | staging`。SvelteKit adapter-node 产物使用 `node --env-file=.env --env-file=.env.prod --env-file-if-exists=.env.local build/index.js`。文件路径相对进程工作目录,公共文件随项目提交;容器通过部署平台或 `--env-file` 注入目标环境值。浏览器只接收公开白名单,构建产物和镜像不包含 `.env.local`。
72
+ `prod` 是文件模式名,对应 `HAI_CORE_ENV=production`;环境枚举为 `development | test | production | staging`。SvelteKit adapter-node 产物使用 `node scripts/run-node.mjs prod . build/index.js`。路径相对工作目录,公共文件提交 Git,私有文件不进入镜像或版本库。部署容器由 SDK 统一运行文件加载,浏览器只接收公开白名单。
72
73
 
73
74
  当前 SDK 的 Node 后端默认读取实际挂载的发布 `.env.runtime`,修改后重启容器生效;托管连接保持更高优先级,静态 Web、中间件、网关路径、端口/挂载和 Node 启动参数按部署流程更新。长期修改同步回源环境,下一次后端发布会重新生成;见[部署指引](../hai-deploy/SKILL.md#后端运行配置重载)。自行维护且只使用 Compose `env_file` 注入环境的容器,改文件后需要重新创建,通常无需重建镜像。请求策略可固定引用只读挂载 YAML,后续改文件并重启服务实例重新读取;运行中不监视文件、不逐请求读盘。完整 `HAI_SERV` / `HAI_KIT` 优先于叶子变量,不叠加覆盖。待上传归档与 SDK 策略快照不能手改;运维外部文件和 Compose override 另行备份,SDK 自动回滚不恢复外部文件。
74
75
 
@@ -96,7 +97,7 @@ Fullstack 的环境文件在工程根;service 脚本通过 `../../.env*` 加
96
97
  | `HAI_SERV_SERVER_HOST` / `HAI_SERV_SERVER_PORT` | HTTP 主机和整数端口 1–65535;部署平台 HOST/PORT 可覆盖 |
97
98
  | `HAI_AI_LLM_PROTOCOL` / `HAI_AI_LLM_TEMPERATURE` | `chat \| responses \| anthropic`;temperature 为数字 0–2 |
98
99
  | `HAI_AI_LLM_APIKEY` / `HAI_AI_LLM_BASEURL` / `HAI_AI_LLM_MODEL` | 厂商密钥、服务 URL、实际可用模型名;启用时满足厂商要求 |
99
- | `HAI_ADMIN_DEFAULT_PASSWORD` | 首次创建管理员的密码,满足 IAM 密码策略;CLI 为 fullstack 的 `.env.dev/.env.test/.env.prod` 分别生成独立随机值 |
100
+ | `HAI_ADMIN_DEFAULT_PASSWORD` | 首次创建管理员的密码,满足 IAM 密码策略;CLI 为 fullstack 的 `.env.dev.local/.env.test.local/.env.prod.local` 分别生成独立随机值 |
100
101
  | `PUBLIC_API_BASE` | 可公开的 API 地址,不得包含用户名、密码或 token |
101
102
 
102
103
  其余变量逐项见对应 `.env.example` 及模块公开 Schema;可选块启用后也应使用相同命名、显式引用与逐项说明。
@@ -179,7 +180,7 @@ CLI 用户消息通过现有中英字典输出。初始语言按非空的 `HAI_C
179
180
 
180
181
  独立 fullstack 默认后台的 Web/App/Desktop 共用管理组件、状态与 typed client。`@h-ai/serv/features/iam` 默认 procedures 可按需选用并与 contract 对齐;有业务缺口时覆写必要路由。主题的 DOM 更新和安全缓存使用 `@h-ai/ui/theme`(`applyTheme` / `getSavedTheme`),应用保留响应式状态与已编译主题白名单。初始 admin/user、管理员自我保护、头像限额、分页和审计策略都是应用示例,可按需求替换;实际权限、资源范围和写入一致性按目标业务落实。
181
182
 
182
- Fullstack 创建时在根 `.env.dev/.env.test/.env.prod` 分别写入独立随机 `HAI_ADMIN_DEFAULT_PASSWORD`,提交后克隆共享,`.env.example` 保留空占位。`dev` / `start` 自动读取;已有用户不重设密码。启动边界保留模块错误的具体说明与错误码,失败后反序清理。不能把环境凭据复制到前端配置、日志、源码或镜像。
183
+ Fullstack 创建时在根 `.env.dev.local/.env.test.local/.env.prod.local` 分别写入独立随机 `HAI_ADMIN_DEFAULT_PASSWORD`,文件不提交 Git,克隆后通过受保护配置共享,`.env.example` 保留空占位。`dev` / `start` 自动读取;已有用户不重设密码。启动边界保留模块错误的具体说明与错误码,失败后反序清理。不能把环境凭据复制到前端配置、日志、源码或镜像。
183
184
 
184
185
  ## 落实契约与安全边界
185
186
 
@@ -35,7 +35,8 @@ description: "构建或排查 hai 应用的源码、静态网站、容器镜像
35
35
  - pnpm run deploy --build 显式串联构建、打包和发布;--bundle-only 只交付完整离线包与跨平台脚本;--services 以服务器成功状态为基线只更新选中服务。完整包自动包含自建中间件镜像,服务器禁止联网拉取。
36
36
  - `pnpm build` 默认仅编译源码(调用 compile);`pnpm build --target image` 根据 hai.json.build.images 的 dockerfile 构建并导出 serv/web 镜像(可单独或组合),可用 --images web 只构建前端,默认最多两项并行,--concurrency 1可串行,auto 优先可达 Podman、其次 Docker,可用 --runtime 显式指定。
37
37
  - compile 交付源码编译结果,image 交付镜像归档,desktop 交付 Tauri 系统安装包,app 交付 Capacitor 原生制品;每次选择一个 target。hai.json 的 build.images[].dockerfile 指向独立镜像文件,build.desktop/build.app 声明原生工程目录,deploy 保存整个项目的部署配置;参数和平台前置以当前 CLI 类型与工程 scripts 为准。cap:sync 只同步工程,不能作为已打包或已安装的证据。
38
- - Podman 的客户端代理通过预定义构建参数传递,覆盖 Windows/macOS 远程引擎的服务端默认值;代理地址必须能从构建容器访问,--no-http-proxy 禁止此传递。不要把代理写成 Dockerfile ENV 或固化进交付镜像。
38
+ - `--image-source` / `--npm-source` 分别选 official/cn/custom;首次交互保存到 hai.json.build.sources,参数仅覆盖本次,--yes 复用且未配置时走官方。cn 镜像用毫秒镜像覆盖 Docker Hub/GHCR,npm 用 npmmirror;保留版本和 lockfile 校验。旧 Dockerfile 缺参数时明确提示同步模板。自定义映射见 [下载源与代理](reference.md#下载源与代理)。
39
+ - Docker/Podman 的构建代理用预定义参数传递;--proxy-mode 选 inherit/system/custom/none,--proxy-url 指定自定义地址,--proxy-bypass 覆盖绕过列表,--no-http-proxy 等价 none。Podman 默认网络保留原代理地址,显式 pasta 等隔离网络才改为宿主入口;Docker 非 host 网络使用宿主入口。首个下载步骤检查实际构建可达性,不能用 run 网络代替。镜像拉取端仍需 Docker daemon/Desktop 或 Podman Machine/API 自身代理,CLI 分别预检提示。不要把代理写成 Dockerfile ENV 或固化进运行镜像。
39
40
  - --network 默认沿用引擎网络;只有实际构建网络无法访问依赖/代理时才显式选择网络,pasta 仅适用于 rootless Podman。build 与 run 的主机名解析可能不同,须验证构建网络中的可达性,不默认改成 host 网络。
40
41
  - 从运行build的应用根package.json.version读取版本,不能使用CLI/框架版本或服务子包版本代替。根目录清单version=4,非根目录version=5并记录webBasePath;appVersion为应用版本。servContainerPort/webContainerPort仅记录images配置显式填写的端口,部分构建也保留未选镜像端口,未填写时沿用部署默认值。镜像tar名含版本、buildId区分同版本构建,Tauri也接收根版本。不要手改清单或保留无版本的交付归档。
41
42
  - 构建不区分 dev/test/prod,不加载部署环境覆盖,不注入运行期凭据;所选镜像清单含 SHA-256,全部成功才更新本机最近构建指针(不是镜像标签)。不要让 compile、Dockerfile 或 Tauri beforeBuildCommand 递归调用自身的原生/镜像构建。
@@ -54,6 +55,8 @@ description: "构建或排查 hai 应用的源码、静态网站、容器镜像
54
55
 
55
56
  ## 按需参考
56
57
 
58
+ Windows 构建子进程使用追加式 pnpm 日志并规范 CRLF,等待输出写完再完成;保留 stdout/stderr、UTF-8 和所有警告,不靠静默输出隐藏下载错误。Dockerfile 的 pnpm fetch/install 同步使用 --reporter=append-only。
59
+
57
60
  按任务读取 [reference.md](reference.md) 的对应小节;签名以当前源码或安装版本的公开类型为准,不默认加载全部资料。示例中的业务变量由应用提供。
58
61
 
59
62
  - 适用场景
@@ -44,6 +44,20 @@
44
44
 
45
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
+ ### 下载源与代理
48
+
49
+ ```sh
50
+ pnpm build --target image --image-source cn --npm-source cn
51
+ pnpm build --target image --proxy-mode custom --proxy-url http://127.0.0.1:10808
52
+ pnpm build --target image --image-source custom --image-mirrors "docker.io=mirror.example.com/docker.io,ghcr.io=mirror.example.com/ghcr.io" --npm-source custom --npm-registry https://npm.example.com/registry
53
+ ```
54
+
55
+ 首次交互保存尚未配置的 `hai.json.build.sources.image` / `.npm` 与 `build.proxy`。命令参数优先且不回写,已保存值其次;非交互未配置时官方源与 inherit 代理。image 形如 `{ "type": "custom", "registries": { "docker.io": "mirror.example.com/docker.io", "ghcr.io": "mirror.example.com/ghcr.io" } }`,npm 形如 `{ "type": "custom", "registry": "https://npm.example.com/registry" }`。official/cn 只需 type。cn 使用毫秒镜像的 docker.1ms.run / ghcr.1ms.run 及 registry.npmmirror.com;公共服务有同步延迟和限流,需验证实际版本。打包中间件会复用本地原始镜像,缺失时从所选源拉取并恢复原标签,离线包与部署身份保持一致。
56
+
57
+ 代理形如 `{ "mode": "custom", "url": "http://127.0.0.1:10808", "bypass": "localhost,127.0.0.1" }`。inherit 使用进程变量;system 读取 Windows/macOS 静态代理,PAC/自动发现或其他平台用继承/自定义;none 清空本次代理变量,--no-http-proxy 等价 none。自定义地址不含认证,认证代理仅从环境继承。Podman 默认构建网络保留原代理地址,显式 --network pasta 等隔离网络时回环地址替换为 host.containers.internal;Docker 非 host 网络使用 host.docker.internal。须验证真实构建网络,run 结果不能代替;默认不通时显式试 --network pasta 或改用可达代理地址。Docker/远程 Podman 拉取使用引擎侧代理,不能用构建参数代替配置引擎,修改与重启独立安排。
58
+
59
+ Dockerfile 在 FROM 前声明 HAI_NODE_IMAGE / 适用的 HAI_NGINX_IMAGE,构建阶段用 HAI_NPM_REGISTRY 设置 COREPACK_NPM_REGISTRY、npm_config_registry、pnpm_config_registry。首个下载步骤验证代理 TCP 可达性,代理不进入运行 ENV。旧工程同步模板后重新构建;显式 tarball/Git URL 和原生包不由 registry 覆盖,SQLite 继续用 --sqlite-prebuild-mirror。deploy 的 npm 参数须与 --build 一起使用。
60
+
47
61
  ### SvelteKit Adapter 模式
48
62
 
49
63
  CLI website模板默认Node SSR。新建工程包含完整模块和示例,静态发布须先移除服务端业务依赖、初始化和API/actions;在compile时使用`HAI_BUILD_STATIC=1`与可选`PUBLIC_BASE_PATH`切换完整静态预渲染,边界见本skill的静态网站说明;该模板没有使用下方VITE_ADAPTER工厂。静态产物用preview本机检查,上传build到Pages/CDN;生成的start/Docker配置属于普通SSR模式,不能用于运行静态HTML。切回SSR只需清除静态开关并重建,PUBLIC_BASE_PATH仍可按实际网站目录用于SSR或Docker;SvelteKit/Vite差异、制品格式和健康检查见[网站挂载目录](paths.md)。
@@ -141,7 +155,7 @@ import { reldb, ReldbConfigSchema } from '@h-ai/reldb'
141
155
  import { iam, IamConfigSchema } from '@h-ai/iam'
142
156
 
143
157
  // 放入应用已有的启动函数;并发防护和关闭钩子复用当前模板。
144
- core.init({ configDir: './config' })
158
+ core.init({ configDir: './config', configSchemas: { db: ReldbConfigSchema, cache: CacheConfigSchema, iam: IamConfigSchema } })
145
159
  const dbConfig = core.config.validate('db', ReldbConfigSchema)
146
160
  if (!dbConfig.success) return dbConfig
147
161
  const cacheConfig = core.config.validate('cache', CacheConfigSchema)
@@ -17,10 +17,10 @@ description: "配置 hai 应用启动、YAML/环境变量、日志、i18n 与 Ha
17
17
 
18
18
  ## 使用路径
19
19
 
20
- - Node 启动用 core.init({ configDir }) 加载配置;勿传 logging 覆盖 _core.yml 中的日志设置,除非任务明确要求。
20
+ - Node 启动用 core.init({ configDir, configSchemas }) 加载配置;configSchemas 登记所用模块的公开 Schema,使 YAML 未声明的合法可选字段也能接收细项环境变量。勿传 logging 覆盖 _core.yml 中的日志设置,除非任务明确要求。
21
21
  - 自动加载和监听配置目录内所有 YAML;项目根 `hai.json` 的 `build` / `deploy` 由 CLI 读取,不进入运行时配置。单项 load 返回失败时记日志并继续,必需配置须 validate 并检查 success;目录扫描、日志设置等异常仍可能传播。
22
22
  - 应用名称、版本、环境、默认语言和日志设置统一从 `_core.yml` 经 core.config 获取,日志使用 core.logger;UI 不另维护硬编码副本。SvelteKit layout / fullstack app.info 仅下发公开字段白名单;独立 Vite mobile-app 在 Node 构建时解析并注入公开默认值,修改这些编译默认值需要重新构建。静态 Web 的公开 API 地址等通过 `runtime-config.js` 覆盖时无需重建镜像,原生包在复制静态资源前准备配置入口。浏览器不加载 YAML,不接收完整模块配置、密钥或日志脱敏上下文。
23
- - `HAI_<配置名>_<路径>` 可整体覆盖根/对象/数组;父节点优先,未覆盖时才遍历已有叶子。camelCase 不拆词,约定变量优先于显式插值。
23
+ - `HAI_<配置名>_<路径>` 支持父 JSON 基础与细项覆盖,同源先父后子,高来源整段替换清除低来源细项。camelCase 不拆词,约定变量优先于显式插值;宿主显式提供 `configSchemas` 识别 YAML 缺少的可选路径,模块执行业务校验。
24
24
  - 环境文件采用六类:`.env.example` 完整列出字段用途、默认值、枚举和范围;`.env` 为公共基础;`.env.dev`、`.env.test`、`.env.prod` 为公共环境覆盖,这五类均提交 Git。`.env.local` 为本机私有配置,不提交 Git。优先级为进程环境 > `.env.local` > 环境文件 > `.env`;Vite 在 Node 配置阶段调用 `core.config.loadEnvFiles({ mode, envDir })` 并检查 success 后注入进程,Node 脚本按相同顺序传入 `--env-file`。`core.init` 不自行读取 dotenv。
25
25
  - 配置 getter 与 ID/logger 方法不是 HaiResult;validate/load 等须检查 success。
26
26
  - 日志可用 `{ error }` 记录原生 Error;两端先规范化诊断再字段/URL 脱敏,配置 redact 路径仍生效。默认包含 passwordHash、passwd、secretKey 等实际凭据字段;异常文本清理显式凭据标签和 URL,不保证识别无标签秘密。原异常不变,错误子图循环/深度用固定标记;业务隐私仍由调用方清理或遮蔽整条路径。
@@ -118,8 +118,8 @@ unwatch()
118
118
 
119
119
  - YAML 根、对象、数组和叶子节点均可映射为 `HAI_<配置名>_<YAML 路径>`;配置名和 key 转大写、层级以 `_` 分隔,camelCase 不拆词
120
120
  - 例如 `core.config.load('ai', ...)` 加载的 `llm.apiKey` 对应 `HAI_AI_LLM_APIKEY`,`llm.models[0].temperature` 对应 `HAI_AI_LLM_MODELS_0_TEMPERATURE`
121
- - 约定环境变量存在时整体替换对应节点并按 YAML 规则解析;例如 HAI_DB 可注入整段连接配置、HAI_REACH_PROVIDERS 可替换数组。父节点覆盖优先于子节点,覆盖后不再遍历其叶子变量;无父节点覆盖时,只遍历 YAML 已有路径
122
- - 优先级为父节点约定变量 > 当前节点约定变量 > 显式 `${VAR}` > YAML 默认值;显式语法只用于指定特殊变量名
121
+ - 父 JSON 提供节点基础,随后细项覆盖;例如 HAI_DB 提供连接基础,HAI_DB_HOST 细化主机。数组 JSON 替换完整列表,索引仅更新已有元素,缺少列表或越界报错。Schema 决定字段类型,字符串保留前导零,变量/JSON 中的内容不再次插值。
122
+ - 所有入口统一来源:进程 > `.env.<mode>.local` > `.env.local` > `.env.<mode>` > `.env` > YAML。同源先父后子,与行序无关;高来源整段替换清除低来源细项。约定变量优先于显式 `${VAR}`。`configSchemas` 由宿主显式传入,Core 不导入业务模块;扫描只使用结构,模块负责完整校验。
123
123
 
124
124
  - `${VAR}` — 读取 `process.env.VAR`;缺失则返回 `HaiConfigError.CONFIG_ENV_VAR_MISSING` 错误
125
125
  - `${VAR:default}` — 读取 `process.env.VAR`;缺失则使用默认值
@@ -474,7 +474,7 @@ if (!result.success) {
474
474
 
475
475
  ### 服务端初始化(SvelteKit hooks.server.ts)
476
476
 
477
- 在应用已有的 init.ts 中执行 core.init({ configDir: './config' }),然后初始化依赖模块;hooks.server.ts 等待该启动流程完成后接入 kit.createHandle。完整依赖顺序与失败清理见 [hai-build](../hai-build/SKILL.md)。不要在一个文件里同时 import 和声明同名 initModules。
477
+ 在应用已有的 init.ts 中执行 core.init({ configDir: './config', configSchemas }),configSchemas 登记所用模块的公开 Schema,再校验配置并初始化依赖模块;hooks.server.ts 等待该启动流程完成后接入 kit.createHandle。完整依赖顺序与失败清理见 [hai-build](../hai-build/SKILL.md)。不要在一个文件里同时 import 和声明同名 initModules。
478
478
 
479
479
  ### 配置校验最佳实践
480
480
 
@@ -48,7 +48,7 @@ Node listener 使用 socket 对端;Fetch 必须传可信平台 `remoteAddress`
48
48
 
49
49
  ## 部署与公共边界
50
50
 
51
- `.env.<环境>` 或私有覆盖可设置 `HAI_SERV_HTTP_ACCESS='{"file":"./config/security/request-access.yml"}'` / `HAI_KIT_ACCESS=...`。Core 父节点覆盖优先;已有 `HAI_SERV` / `HAI_KIT` 时应修改父对象,不能假定叶子变量会叠加。
51
+ `.env.<环境>` 或私有覆盖可设置 `HAI_SERV_HTTP_ACCESS='{"file":"./config/security/request-access.yml"}'` / `HAI_KIT_ACCESS=...`。同来源 `HAI_SERV` / `HAI_KIT` JSON 提供基础,`HAI_SERV_HTTP_ACCESS_FILE` / `HAI_KIT_ACCESS_FILE` 等细项继续覆盖;更高来源整段替换会清除低来源细项。
52
52
 
53
53
  部署校验当前选中后端的配置文件,规范化快照放入交付包并参加 SHA-256 校验,容器通过 `/run/hai/request-access.yml` 只读挂载。工程原始引用不回写成容器路径。仅更新前端时保留后端原文件;失败恢复使用旧发布的 Compose/文件。待上传归档和 SDK 策略快照不能手改;替换快照时重新打包。已部署 Node 后端挂载的 `.env.runtime` 可按[部署指引](../hai-deploy/SKILL.md#后端运行配置重载)修改后重启,注意上层 JSON 优先级;不会自动重写 Nginx 或策略文件。镜像/配置回退不能撤销数据库和业务效果。
54
54
 
@@ -214,7 +214,7 @@ const sharedServer = crypto.transport.createServer({
214
214
 
215
215
  `serverKeyRing` 为 `{ activeKeyId, keys: { [id]: { publicKey, privateKey } } }`,ID 为 1–64 个字母、数字、下划线或连字符。根入口 `parseTransportServerKeyRing(secret)` 接受服务端 Secret JSON 或配置对象,返回 HaiResult,错误不附带原始 Secret 或解析片段。工厂验证每对公私钥并捕获快照;没有隐式随机私钥或 memory registry 回退。`keyStore` 也必填,生产用共享 Redis/数据库;开发/测试可显式 `createInMemoryKeyStore(capacity)`。
216
216
 
217
- 示例服务端读取 `process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING`,检查解析结果后仅传给服务端工厂;禁止写入普通 YAML、PUBLIC_/VITE_、日志或响应。CLI 创建服务端项目时在 `.env.dev/.env.test/.env.prod` 分别生成独立 ring;环境文件随项目提交,克隆用户共享对应环境配置。可由进程环境、私有覆盖或 Secret Manager 替换,同一环境所有节点使用同一 ring。
217
+ 示例服务端读取 `process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING`,检查解析结果后仅传给服务端工厂;禁止写入普通 YAML、PUBLIC_/VITE_、日志或响应。CLI 创建服务端项目时在 `.env.dev.local/.env.test.local/.env.prod.local` 分别生成独立 ring;环境文件随项目提交,克隆用户共享对应环境配置。可由进程环境、私有覆盖或 Secret Manager 替换,同一环境所有节点使用同一 ring。
218
218
 
219
219
  请求密文 `EncryptedRequestPayload` 携带协商的 `serverKeyId`;服务端只按 ID 选择私钥,未知/撤销 ID 拒绝,不尝试其它 key。轮换先向所有节点分发包含新旧版本的 ring,再切 activeKeyId 并滚动重建 manager;过渡期后删除旧 ID 并更新所有节点。旧客户端 destroy 后重协商;禁止自动重放非幂等请求。共享 ring + registry 支持跨节点与重启,不依赖 sticky session。
220
220
 
@@ -31,7 +31,7 @@ description: "构建并发布或交付已有镜像:完整离线包、按服务
31
31
  排错与交付按[沟通与同步维护](../hai-app-create/collaboration.md)先说明实际影响、恢复步骤和验证边界,再附脱敏错误码/traceId/日志;配置、使用文档和截图随实际部署流程同步。
32
32
 
33
33
  1. 读取项目 scripts、images/ 中的 Dockerfile、项目根 hai.json 的 build/deploy 与服务目录运行配置。构建与部署属于整个项目;服务目录只用于扫描运行依赖。创建默认带开发期部署工具;用户明确 --no-deploy 时不生成部署入口。构建细节见 [hai-build](../hai-build/SKILL.md)。
34
- 2. 选择环境,验证 .env.<mode> 存在,再处理部署目标与必要中间件。SSH 支持 key/agent 或 password,缺项按说明补齐,有效完整配置直接复用;--bundle-only 在构建和中间件配置后、打包前最后询问是否添加或修改 SSH 信息,保存并用于本次和后续 target;--yes 或跳过时复用已有配置。新私有参数写 .env.<mode>.local,旧 .env.local 保留兼容回退;私钥仅引用路径,密码隐藏输入并保留原值。该按环境私有层仅由部署 SDK 加载,不改变 Core 运行规则。优先级与认证边界见 [middleware.md](middleware.md)。
34
+ 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
35
  3. 先校验所选制品、版本、服务和SHA-256。--build只构建所选应用镜像;不带它时缺产物明确失败,不隐式补构建。根目录使用格式4,非根目录使用格式5及webBasePath;两者都记录appVersion、buildId、partial、hasWeb、镜像归档及显式配置的servContainerPort/webContainerPort,部分构建也保留未选镜像端口,缺省使用部署默认值。网站目录由构建进程PUBLIC_BASE_PATH确定,所有部分构建须保持一致;目录变化必须全量,健康与恢复按制品记录处理。具体步骤见[网站挂载目录](../hai-build/paths.md)。同一应用版本可重建,镜像引用区分实际内容;禁止latest与无版本镜像。
36
36
  4. 完整包自动导出实际自建中间件镜像并去重;只更新 Web 不重新打包 API/中间件。打包机需容器引擎导出中间件,服务器仅 load,禁止 pull/build。外部连接及云开通不能伪称为离线自包含服务。
37
37
  5. --services 使用目标服务器最后成功状态为基线,检查端口/拓扑及未选依赖,保留未选配置、凭据、网络和卷。脚本先按项目/服务标签仅删除选中旧容器(保留卷),再 up -d --no-deps --no-build --pull never --no-recreate 创建新容器并保留其他容器;先等待选中中间件健康,再启动 serv/Web,失败恢复同序,避免 Compose Provider 连带重建反向依赖,禁止整个项目 down。S3 可选 createBucket 在 storage.init 中检查并创建缺失桶,自建 S3 注入 HAI_STORAGE_CREATEBUCKET=true;仅更新 storage 无须应用镜像,新桶在下次应用初始化时创建。Compose 网络统一 hai-app,序列化不使用 YAML 锚点。
@@ -53,11 +53,13 @@ description: "构建并发布或交付已有镜像:完整离线包、按服务
53
53
 
54
54
  独立读取的核心环境、职责账号初始密码和传输密钥环保留进程语义,不能仅按前缀判定已失效;Node 启动参数及私有代理标记由部署装配提供,不在运行文件重复保留无效项。
55
55
 
56
- 交付配置清理所有被 HAI 父级变量遮蔽的子项,并从 `.env.runtime` 移除由 `middleware.env` 提供的重复项;不据清理后的交付变量反向覆盖工程源环境。
56
+ 生成端优先写细项,数组保留 JSON;手写 JSON 允许兜底,放在对应模块细项之前。同源细项覆盖 JSON,动态字典、JSON 文本和显式空对象保留原义;整体替换展开时以最上层 `{}` 标记阻止旧 YAML 字段恢复。容器路径只写交付配置,不反写工程源环境。
57
57
 
58
- Node 后端(Serv / SvelteKit SSR)默认在每次启动时重读发布目录的 `.env.runtime`,修改后 `docker restart <容器名>` 或 `podman restart <容器名>` 即可,无需重建镜像或额外 override。旧部署先用新版 CLI 发布一次。删除的字段不会从旧 Compose 注入中复活;服务器托管连接的 `middleware.env` 保持原有更高优先级,私有代理标记和 Node 启动参数仍由部署装配管理。静态 Web、中间件、端口/挂载、Nginx 路由与限额不在该重载范围;改变网关路径、端口或挂载时使用全量部署。手工修改需备份;下一次后端发布会从工程环境重新生成,需要长期保留的配置同步回源环境。
58
+ Node 后端(Serv / SvelteKit SSR)每次启动读取服务器 `<部署目录>/config/.env.runtime`。应用配置与托管连接在此合并,修改 `HAI_STORAGE_PUBLICENDPOINT` 等细项后重启对应后端即可;同一来源的细项覆盖父 JSON。配置目录只读挂载到 `/run/hai/config`,编辑器原子替换文件也会被下一次启动读取。私有代理标记和 Node 启动参数由部署装配管理;静态 Web、中间件原生环境、端口/挂载、Nginx 路由与限额变更仍需部署。仅更新 Web/中间件保留当前应用配置;后端局部更新保留服务器托管连接,其余值来自新包,全量更新采用新包并按已有凭据状态定稿。手工修改先备份,长期配置同步回源环境。
59
59
 
60
- 运行文件在后端实际挂载的releases/<后端发布ID>/.env.runtime;仅更新Web/中间件后current可能指向新记录,不能据此猜测后端文件,按容器Mounts中/run/hai/.env.runtime的Source确认。只读文件挂载,上级目录0700,容器非root可读,宿主所有者可修改。dotenv字面解析不执行shell;双引号支持JSON转义。单文件≤1MiB,缺失/不可读/超限在应用导入前失败。父HAI_SERV/HAI_KIT仍优先于叶字段。重启后验健康与配置影响的业务,失败恢复文件再重启。
60
+ 运行文件固定为 `<部署目录>/config/.env.runtime`,只读挂载目录到 `/run/hai/config`;各 release 保留配置快照。单文件不超过 1 MiB,缺失、不可读、重复变量或超限阻止启动;dotenv 字面解析不执行 shell。同源细项覆盖 JSON,显式进程 HAI 配置优先。修改后重启、验健康和受影响业务,失败恢复备份再重启。
61
+
62
+ 部署归档只保留五个顶层入口:`apply.sh`、`manifest.json`、`config/`、`images/`、`.hai/`。`config/.env.runtime` 是唯一应用环境文件;`manifest.json.metadata` 集中保存依赖、布局、健康路径、镜像列表、受管绑定等非敏感元数据。`.hai/compose.json` 是完整服务快照;局部更新在服务边界替换并保留未选服务,不串联历史 Compose 文件。`.hai/` 还存原生环境、加载器、Nginx/TLS、策略和校验和,秘密不写入 manifest。辅助脚本合入 `apply.sh`。失败时先恢复原应用配置再恢复服务,凭据、后端账本和数据卷继续保护。新包格式为 2,不实现旧目录兼容或迁移。
61
63
 
62
64
  ## CLI
63
65
 
@@ -90,6 +92,8 @@ S3 的内部 endpoint 与预签名 publicEndpoint 分开;后者无默认,填
90
92
 
91
93
  deploy.init 后检查 HaiResult.success,deploy.deployApp 接收 artifactDir、bundleOnly、selectedServices、runtime 与 onProgress;finally 中 deploy.close。deploy.scan 和 deploy.credentials.* 不依赖 init。Vercel 只消费已有 .vercel/output,不执行源码构建,也不支持 Compose 离线/部分更新。
92
94
 
95
+ 下载源由 `--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 拉取子进程会覆盖代理变量,远程引擎仍需自身设置;镜像归档保持原始标签。
96
+
93
97
  内部命令工具须显式枚举 `secrets`(包括转换后的敏感字面量),成功/失败/回调均跨块脱敏;不得向日志附加原始异常 cause。捕获默认每流末尾 1 Mi 字符,结构化消费先检查截断标志;异步输出回调按序等待并保持 pipe 背压。进度每行最多解析 512 字符,超时后确认远程执行状态。详细边界见 [middleware.md](middleware.md#命令输出)。
94
98
 
95
99
  超时或输入/输出失败会终止本地受管理 Job/进程组并等待核验;Windows 用系统 PowerShell/.NET 内嵌 Job,先挂起创建、分配成功才恢复,失败不降级裸进程;POSIX 后代须保留继承的进程组。`terminationTimeoutMs` 默认 10000、最大 60000 毫秒,核验失败返回 unknown。失败分支用 `getDeployCommandState(error)` 读取 localTermination 和 remoteExecution;CLI 分别显示。本地已退出不能证明 SSH 远端停止;仅新连接读到完整、ID 匹配的原子结果才确认 finished,给出结果路径/退出码。未知状态不自动重跑发布或回滚,先核对 current、步骤和实际服务。
@@ -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
- 公共文件沿用 `.env.example` 清单、`.env` 基础和 `.env.dev/test/prod` 环境覆盖。部署 SDK 新保存的 SSH 连接、密码、API Key 和含认证 URL 写忽略 Git 的 `.env.<mode>.local`;公共后端和地址写目标环境文件。旧 `.env.local` 保留为共享兼容回退,不猜测其环境归属、不强制迁移、不删除旧值。CLI 不打印秘密值。调用 deploy API 时显式传 `{ environment: 'test', envDir: '/workspace/app' }`,不要用调用者的 `NODE_ENV` 猜测部署目标。
17
+ 公共配置保存在 `.env` 和 `.env.<mode>`,连接凭据与 SSH 配置保存在忽略 Git 的 `.env.<mode>.local`,`.env.local` 用于本机共享私有值。构建不读取部署秘密。
18
18
 
19
19
  部署 SDK 的来源优先级从高到低为:
20
20
 
21
- - `HAI_DEPLOY_*`:进程 > `.env.<mode>.local` > `.env.<mode>` > 旧 `.env.local` > `.env`,所选环境明确目标胜过旧全局目标。
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
- `.env.<mode>.local` 仅属于部署 SDK 的配置读取和记忆;Core 的普通应用加载规则不变,不能据此宣称 dev/start 会读取这个文件。
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,13 +31,13 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
31
31
 
32
32
  分批启动仅在首批清理孤立容器,后续 serv/Web 启动必须保留已经就绪的中间件。
33
33
 
34
- 生成时为 `.env.dev/.env.test/.env.prod` 分别生成独立的初始管理员密码和传输密钥环;环境文件随项目提交,克隆后可共享,并可通过本机私有文件或进程环境覆盖。启用 transport 的应用缺少/错误配置 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING` 时,部署在上传前指出配置来源;同一环境的所有节点可直接加载环境文件中的同一有效密钥环,也可由 Secret Manager 覆盖;不为每个节点临时生成。CLI 完成部署后提示 `HAI_ADMIN_DEFAULT_PASSWORD` 的实际来源,不打印密码,不依赖日志级别;该密码仅在首次创建管理员时生效。 离线入口也会提示服务器私有 `.env.runtime` 中的密码变量位置。
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
- 默认和自定义模式均从同后端的有效配置继续,不能按表单重建对象而丢掉未展示项。自建/云开通保留连接池、操作日志、公开端点/前缀、Redis 重试、向量检索、SMTP 发件人及 LDAP 属性映射,仅由实际服务定稿地址与认证;旧 URL、TLS/集群选择器不能覆盖新服务。切换后端清除不兼容字段。若旧向导已写出缺字段父 JSON,先从原配置/备份恢复最高优先级 `HAI_STORAGE` 的 `publicEndpoint` 等字段,再用修复版重建部署包;父 JSON 仍优先于 YAML 和叶变量,不自动猜测丢失值。
38
+ 默认和自定义模式均从同后端的有效配置继续,不能按表单重建对象而丢掉未展示项。自建/云开通保留连接池、操作日志、公开端点/前缀、Redis 重试、向量检索、SMTP 发件人及 LDAP 属性映射,仅由实际服务定稿地址与认证;旧 URL、TLS/集群选择器不能覆盖新服务。切换后端清除不兼容字段。生成端优先写细项,数组保留 JSON;手写 JSON 允许兜底,放在对应模块细项之前。同源细项覆盖 JSON,动态字典、JSON 文本和显式空对象保留原义;整体替换展开时以最上层 `{}` 标记阻止旧 YAML 字段恢复。容器路径只写交付配置,不反写工程源环境。
39
39
 
40
- 框架 `HAI_*` 连接配置与镜像原生变量分开:PostgreSQL/MySQL/RustFS/MinIO/LDAP 的原生键必须按镜像契约命名,只写私有 `middleware-runtime.env`、只让中间件加载。不得改成镜像不识别的 HAI 前缀,也不得写回工程 `.env.<mode>` / 私有覆盖或注入应用 `.env.runtime`。应用的增量覆盖文件 `middleware.env` 只含 `HAI_*`。旧工程原生字段不自动删除,新应用环境忽略框架曾生成的已知原生键;不要批量过滤其他业务变量。
40
+ 中间件原生变量(`POSTGRES_*`、`MYSQL_*`、`RUSTFS_*`、`MINIO_*`、`LDAP_*`)按镜像契约保留原名,只写私有 `.hai/middleware-runtime.env`,仅由中间件读取。应用连接全部合并到 `config/.env.runtime`。
41
41
 
42
42
  数据库连接保存前复用所选后端的公开配置 Schema;MySQL `ssl` 仅 `false` 或严格对象,`{}` 默认验证证书链和 DNS 身份,`ca/cert/key` 为 PEM 内容且 `cert/key` 必须成对;私钥仅进入私有环境。PostgreSQL 保留其布尔值/字符串模式/对象契约。CLI 内联 `@h-ai/reldb/schemas` 与 Zod,无需为配置校验给目标应用额外安装数据库包或驱动;部署本身仍需已安装的 `@h-ai/deploy`,实际运行应用仍需其数据库依赖。
43
43
 
@@ -60,7 +60,7 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
60
60
 
61
61
  1. **使用默认配置**:选择后端;Compose 生成匹配容器/卷,云平台调用已支持的 Provisioner,并保存实际连接配置。MySQL、LDAP、向量库等没有云自动开通器时,明确提示改用自定义连接;不能声称已经创建云资源。Resend 需要已验证的发件域名,R2 需要已有 S3 访问密钥,阿里云短信需要签名/模板与额度。
62
62
  2. **使用自定义配置**:逐项输入所选后端的连接字段,展示字段用途与约束,校验必填项、端口、布尔和 URL;凭据用密码输入。保存配置后跳过该服务的开通与 sidecar。
63
- 3. **保持不变**:仅在目标 `.env.<mode>` 显式声明当前后端及完整连接配置时出现;私有凭据可来自 `.env.<mode>.local`、兼容 `.env.local` 或进程。选择后不修改该项、不认证其 Provisioner、不创建或移除已有中间件容器,继续下一项。只有 `.env` 或其他环境有配置不满足此条件。
63
+ 3. **保持不变**:仅在目标 `.env.<mode>` 显式声明当前后端及完整连接配置时出现;私有凭据可来自 `.env.<mode>.local`、共享 `.env.local` 或进程。选择后不修改该项、不认证其 Provisioner、不创建或移除已有中间件容器,继续下一项。只有 `.env` 或其他环境有配置不满足此条件。
64
64
 
65
65
  逐项配置前提供“环境配置已完备,直接部署”。选择后跳过全部中间件提示、变量改写、云资源与 sidecar 创建,保留已有服务;仍校验已有构建产物并执行部署及健康检查。命令行使用唯一的 `--skip-middleware`,SDK 使用 `skipMiddleware`。不要因为缺少某项中间件的目标文件声明而阻止用户主动跳过。
66
66
 
@@ -120,7 +120,7 @@ manifest.json 的 partial 与 selectedServices、apply 脚本共同记录部署
120
120
 
121
121
  生成 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 获取同一预算。
122
122
 
123
- 完全离线构建另需基础镜像、Linux 依赖缓存、pnpm 和匹配驱动/Node ABI/架构/libc 的原生预编译包。构建可用 --sqlite-prebuild-mirror,Podman 代理不可达可用 --no-http-proxy;不要改系统代理或让 deploy 下载编译环境。生产 HTTPS、CORS、证书、DNS 另行准备。实际断网验收登录、刷新、重启和数据持久化。
123
+ 完全离线构建另需基础镜像、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-prebuild-mirror,不让 deploy 下载编译环境。生产 HTTPS、CORS、证书、DNS 另行准备。实际断网验收登录、刷新、重启和数据持久化。
124
124
 
125
125
  ## 命令输出
126
126
 
@@ -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
@@ -235,7 +235,7 @@ export default { fetch: handler }
235
235
  import { core } from '@h-ai/core'
236
236
  import { serv, ServConfigSchema } from '@h-ai/serv'
237
237
 
238
- core.init({ configDir: './config' })
238
+ core.init({ configDir: './config', configSchemas: { serv: ServConfigSchema } })
239
239
 
240
240
  const validation = core.config.validate('serv', ServConfigSchema)
241
241
  if (!validation.success)