@h-ai/deploy 1.0.0-beta.18 → 1.0.0-beta.19

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 CHANGED
@@ -31,10 +31,12 @@ Automation can select the exact build using `artifactDir` from `hai build --targ
31
31
 
32
32
  #### Build options
33
33
 
34
- `--target` selects compile (default), image, app or desktop. `--images serv|web|serv,web` selects images. `--runtime auto|podman|docker` selects the local engine; auto prefers reachable Podman. `--network` overrides build networking, `--no-http-proxy` disables this build proxy (same as --proxy-mode none), and `--sqlite-prebuild-mirror` selects a trusted HTTP(S) binary mirror. Native `--platform` and `--arch` require the matching host SDK and Rust toolchain. Builds do not load deployment environments or runtime secrets.
34
+ `--target` selects compile (default), image, app or desktop. `--images serv|web|serv,web` selects images. `--runtime auto|podman|docker` selects the local engine; auto prefers reachable Podman. `--network` overrides build networking, `--no-http-proxy` disables this build proxy (same as --proxy-mode none). SQLite 13 includes native binaries in its npm package and uses the configured npm registry. Native `--platform` and `--arch` require the matching host SDK and Rust toolchain. Builds do not load deployment environments or runtime secrets.
35
35
 
36
36
  #### Download sources and proxies
37
37
 
38
+ Existing projects should remove the old SQLite mirror option and update their Dockerfiles. Image builds open an in-memory database to verify that the bundled native binary loads on the target platform.
39
+
38
40
  `--image-source official|cn|custom` covers application base images and missing middleware images during packaging. `--npm-source` requires `--build` and controls Corepack/pnpm. The China preset uses 1ms for Docker Hub/GHCR and npmmirror for npm. First interactive choices are saved in `hai.json.build.sources`; flags override one invocation. Set `--proxy-mode inherit|system|custom|none`, `--proxy-url`, and `--proxy-bypass`; `--no-http-proxy` means none. Docker/remote Podman image pulls require engine-side proxy settings; build containers check connectivity separately. See [sources and proxies](../../docs/usage/configuration/delivery.md#下载源和代理) for custom sources, supported platforms and old-template updates.
39
41
 
40
42
  SDK `DeployAppOptions.imageSource` accepts `{ type: 'cn' }` or `{ type: 'custom', registries: { 'docker.io': 'mirror.example.com/docker.io', 'ghcr.io': 'mirror.example.com/ghcr.io' } }`; `proxy` accepts `{ mode: 'inherit' }` or `{ mode: 'custom', url: 'http://127.0.0.1:10808', bypass: 'localhost' }`. Defaults use official sources and inherited process proxies. `resolveImageReference()` / `resolveDownloadProxy()` need no init and do not change engine settings. Middleware archives preserve canonical references for offline server imports.
@@ -117,6 +119,8 @@ All `HAI_*` settings use process > `.env.<mode>.local` > `.env.local` > `.env.<m
117
119
 
118
120
  Public settings live in `.env` and `.env.<mode>`; SSH settings and credentials go to Git-ignored `.env.<mode>.local`. `.env.local` contains shared machine-private settings. Builds do not read deployment secrets.
119
121
 
122
+ All custom HTTP API headers are treated as private values regardless of header names. Saving an existing environment also moves indented, `export` and multiline quoted entries out of the same-mode public file, so their previous values are not left behind.
123
+
120
124
  For existing projects, move the previous build object into `hai.json.build`, convert deployment YAML into `hai.json.deploy`, remove the old files and retain `HAI_DEPLOY_*` variables. Existing self-hosted S3 installations must use a full deployment for this upgrade: their old baseline contains an exited initialization service, which fails the dependency checks of new incremental packages. The full deployment also refreshes the `createBucket` middleware setting; subsequent incremental updates work normally.
121
125
 
122
126
  The CLI --project-name option and SDK DeployAppOptions.projectName override have been removed. Obsolete overrides fail explicitly; maintain resource identity in the root package.json.name.
@@ -215,6 +219,8 @@ Image builds run at most two images concurrently by default; use `--concurrency
215
219
 
216
220
  `pnpm run deploy` offers no HTTPS, existing PEM certificate/key paths, or Let’s Encrypt for every container template. Relative paths resolve from the project root. Certificates are checked for domain, validity and key matching, then copied into private releases. A pinned official Certbot image handles issuance and renewal checks every 12 hours, with automatic Nginx reload. It requires terms acceptance, a real email, public DNS, port 80 and CA connectivity. Isolated servers use existing certificates. Certificate state stays on the server; keys stay out of application images. `--yes` reuses saved settings.
217
221
 
222
+ Supply regular PEM files of at most 1 MiB each; final-component symbolic links and hard links are rejected, and parent directories must remain trusted. Securely copy Certbot `live/` symlink targets to regular files in a controlled directory, or use the framework `letsencrypt` mode.
223
+
218
224
  Configure `hai.json.deploy.provider.expose.https` or private environment overrides. Defaults are HTTPS 443 and HTTP redirection; omission retains HTTP. Enabling/disabling HTTPS or changing mode, domain, ports or supplied certificates requires a full deployment. See the [HTTPS guide](../../docs/usage/configuration/delivery.md#可选https证书). Plans use `root` for the project and `serviceDir` for the service source/configuration directory, exposing only public certificate metadata.
219
225
 
220
226
  ### SDK
@@ -222,7 +228,12 @@ Configure `hai.json.deploy.provider.expose.https` or private environment overrid
222
228
  ```ts
223
229
  import { deploy } from '@h-ai/deploy'
224
230
 
225
- const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 18080 } } })
231
+ const initialized = await deploy.init({
232
+ provider: {
233
+ type: 'docker-ssh',
234
+ expose: { hostPort: 18080 }
235
+ }
236
+ })
226
237
  if (!initialized.success)
227
238
  throw new Error(initialized.error.message)
228
239
  try {
@@ -254,6 +265,10 @@ SSH interruptions initially report `remoteExecution: 'unknown'`. The docker-ssh
254
265
 
255
266
  ### Runtime environment files and repeated deployments
256
267
 
268
+ SvelteKit SSR uses a separate `gateway` for HTTP and HTTPS, without publishing the backend port. The gateway overwrites standard forwarding headers, and Compose fixes the adapter's protocol, Host and client address trust settings; the application runtime file cannot override them. adapter-node 6 no longer reads runtime `ORIGIN`, and applications leave build-time `paths.origin` unset by default. Replace an older directly exposed SSR deployment with a new full bundle generated by the current tools.
269
+
270
+ For upstream TLS termination, list the load balancer's actual IPs/CIDRs in `trustedEdgeProxies`. The separate gateway accepts a single `http` or `https` protocol only from those actual peers; other sources and combined values use its own connection scheme. External `Forwarded` and forwarded host/port values are overwritten.
271
+
257
272
  Environment flags, initial account passwords and the transport key ring are also read directly by startup code. They remain available even when a similarly named configuration parent exists.
258
273
 
259
274
  Generators prefer field variables and retain JSON arrays. Handwritten JSON remains a base and appears before its module fields; fields in the same source win. Dynamic maps, JSON text and explicit empty objects preserve their meaning. Expanding a whole-object replacement retains its highest `{}` reset marker so old YAML fields cannot reappear. Container paths stay in delivery output without changing source settings.
package/README.ja.md CHANGED
@@ -31,10 +31,12 @@ pnpm build --target desktop --platform windows --arch x64
31
31
 
32
32
  #### build のオプション
33
33
 
34
- `--target` は compile(既定)、image、app、desktop を選択します。`--images serv|web|serv,web` は対象イメージを、`--runtime auto|podman|docker` はローカルエンジンを選択します。auto は接続可能な Podman を優先します。`--network` は構築ネットワーク、`--no-http-proxy` は 今回のビルドのプロキシ無効(none と同じ)、`--sqlite-prebuild-mirror` は信頼できる HTTP(S) バイナリ配布元です。ネイティブ配布物には対象 OS の SDK と Rust ツールチェーンが必要です。構築時にデプロイ環境や秘密情報を読み込みません。
34
+ `--target` は compile(既定)、image、app、desktop を選択します。`--images serv|web|serv,web` は対象イメージを、`--runtime auto|podman|docker` はローカルエンジンを選択します。auto は接続可能な Podman を優先します。`--network` は構築ネットワーク、`--no-http-proxy` は 今回のビルドのプロキシ無効(none と同じ)です。SQLite 13 のネイティブバイナリーは npm パッケージに同梱され、設定済みの npm レジストリーを使用します。ネイティブ配布物には対象 OS の SDK と Rust ツールチェーンが必要です。構築時にデプロイ環境や秘密情報を読み込みません。
35
35
 
36
36
  #### 取得元とプロキシ
37
37
 
38
+ 既存プロジェクトでは旧 SQLite ミラー引数を削除し、Dockerfile を更新してください。イメージ構築時にインメモリデータベースを開き、同梱されたネイティブバイナリーが対象環境で読み込めることを検証します。
39
+
38
40
  `--image-source official|cn|custom` はアプリのベースと梱包時に不足したミドルウェアイメージに適用します。`--npm-source` は `--build` と併用し Corepack/pnpm を制御します。中国本土は毫秒镜像の Docker Hub/GHCR 通道と npmmirror を使用します。初回対話で `hai.json.build.sources` に保存し、引数は今回のみ上書きします。プロキシは `--proxy-mode inherit|system|custom|none`、`--proxy-url`、`--proxy-bypass` で指定し、`--no-http-proxy` は none と同じです。Docker/リモート Podman の取得はエンジン側の設定が必要で、ビルドコンテナの接続は別途確認します。カスタム設定、対応 OS、旧テンプレートの更新は[取得元とプロキシ](../../docs/usage/configuration/delivery.md#下载源和代理)を参照してください。
39
41
 
40
42
  SDK の `DeployAppOptions.imageSource` は `{ type: 'cn' }` または `{ type: 'custom', registries: { 'docker.io': 'mirror.example.com/docker.io', 'ghcr.io': 'mirror.example.com/ghcr.io' } }`、`proxy` は `{ mode: 'inherit' }` または `{ mode: 'custom', url: 'http://127.0.0.1:10808', bypass: 'localhost' }` です。既定は公式とプロセスの継承です。`resolveImageReference()`/`resolveDownloadProxy()` は init 不要でエンジン設定を変更しません。ミドルウェアの元参照をアーカイブに保ち、サーバーではオフラインで読み込みます。
@@ -117,6 +119,8 @@ CLI の --project-name と SDK の DeployAppOptions.projectName 上書きは廃
117
119
 
118
120
  公開設定は `.env` と `.env.<mode>`、SSH と資格情報は Git 対象外の `.env.<mode>.local`、マシン共通の秘密値は `.env.local` に保存します。構築時には配備の秘密値を読みません。
119
121
 
122
+ HTTP API のカスタムヘッダーは名前にかかわらず全体を秘密値として扱います。既存環境の保存時は、インデント、`export`、複数行の引用値も同じモードの公開ファイルから非公開ファイルへ移し、以前の値を残しません。
123
+
120
124
  既存プロジェクトは旧構築オブジェクトを `hai.json.build`、旧配置 YAML を JSON に変換して `hai.json.deploy` に移し、元のファイルを削除します。`HAI_DEPLOY_*` は継続利用できます。既存の自前 S3 は今回の初回更新で全量配置が必要です。旧基準には終了済みの初期化サービスが残っており、新しい増分パッケージの依存稼働チェックで拒否されます。全量配置で `createBucket` 設定も更新した後は増分更新を継続できます。
121
125
 
122
126
  直接デプロイでは、サーバー、SSH ユーザー、認証方式、ポートなどの不足項目を説明付きで質問します。有効で完全な設定は `--yes` でも再利用し、再入力を求めません。SSH は `auth: key`(秘密鍵/agent)と `auth: password` に対応します。`auth` を省略した場合、空でない `password` があるときだけパスワード認証を使い、それ以外は key/agent を維持します。明示した `key` は残存パスワードを無視します。パスワード入力は非表示で、前後の空白と先頭のゼロを保持します。有効なパスワードは CR/LF/NUL を含まず、UTF-8 で 1023 バイト以内である必要があります。秘密鍵はパスのみ参照し、内容を読み取り・コピーしません。
@@ -139,7 +143,7 @@ SSH 設定は選択環境の `.env.<環境>.local` に保存します。`--bundl
139
143
 
140
144
  #### deploy のオプション
141
145
 
142
- --env/--env-dir は環境、--build は先行する選択イメージ構築、--services は更新対象、--artifact-dir は既存成果物を指定します。--bundle-only は SSH 接続なしで tar と OS 別スクリプトを生成します。--runtime はローカル構築・イメージ出力エンジンです。--output はコマンドの作業ディレクトリを基準とする出力先を指定し、アプリ版を末尾に付けます。--yes は有効な設定を非対話で使い、不足値はエラーで示します。一体化構築でも --network、--no-http-proxy、--sqlite-prebuild-mirror を指定できます。
146
+ --env/--env-dir は環境、--build は先行する選択イメージ構築、--services は更新対象、--artifact-dir は既存成果物を指定します。--bundle-only は SSH 接続なしで tar と OS 別スクリプトを生成します。--runtime はローカル構築・イメージ出力エンジンです。--output はコマンドの作業ディレクトリを基準とする出力先を指定し、アプリ版を末尾に付けます。--yes は有効な設定を非対話で使い、不足値はエラーで示します。一体化構築でも --network、--no-http-proxy を指定できます。
143
147
 
144
148
  #### マシン同士が接続できる場合:自動デプロイ
145
149
 
@@ -213,6 +217,8 @@ SDK はサーバー内の正常性確認と `current` 更新後、操作端末
213
217
 
214
218
  `pnpm run deploy` は全コンテナーテンプレートで HTTPS なし、既存 PEM 証明書・秘密鍵、Let’s Encrypt を選択できます。相対パスは工程ルート基準です。ドメイン・期限・鍵一致を検証して配布物にコピーします。版を固定した公式 Certbot イメージで申請し、12 時間ごとに更新を確認して Nginx を再読み込みします。利用規約の承認、実際のメール、公的 DNS、80 番ポート、CA 接続が必要です。隔離環境では既存証明書を使います。状態はサーバーに保持し、秘密鍵をアプリイメージに含めません。`--yes` は保存設定を使います。
215
219
 
220
+ PEM は各 1 MiB 以下の通常ファイルを指定してください。末尾要素のシンボリックリンクとハードリンクは拒否し、親ディレクトリーも信頼できる必要があります。Certbot `live/` のリンク先を管理下のディレクトリーへ通常ファイルとして安全にコピーするか、フレームワークの `letsencrypt` モードを使ってください。
221
+
216
222
  `hai.json.deploy.provider.expose.https` または環境別秘密設定で指定します。既定は HTTPS 443 と HTTP リダイレクト、省略時は HTTP です。有効/無効・モード・ドメイン・ポート・持込証明書の変更は完全デプロイが必要です。[HTTPS 設定](../../docs/usage/configuration/delivery.md#可选https证书)を参照してください。計画では `root` が工程ルート、`serviceDir` がサービスのソース・設定ディレクトリです。
217
223
 
218
224
  ### SDK
@@ -220,7 +226,12 @@ SDK はサーバー内の正常性確認と `current` 更新後、操作端末
220
226
  ```ts
221
227
  import { deploy } from '@h-ai/deploy'
222
228
 
223
- const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 18080 } } })
229
+ const initialized = await deploy.init({
230
+ provider: {
231
+ type: 'docker-ssh',
232
+ expose: { hostPort: 18080 }
233
+ }
234
+ })
224
235
  if (!initialized.success)
225
236
  throw new Error(initialized.error.message)
226
237
  try {
@@ -252,6 +263,10 @@ SSH 中断は最初に `remoteExecution: 'unknown'` とし、docker-ssh SDK は
252
263
 
253
264
  ### 実行環境ファイルと設定の再利用
254
265
 
266
+ SvelteKit SSR は HTTP/HTTPS ともに独立した `gateway` を使用し、バックエンドのポートを公開しません。ゲートウェイが標準の転送ヘッダーを上書きし、Compose が adapter のプロトコル、Host、クライアントアドレスの信頼設定を固定します。業務の実行環境ファイルでは変更できません。adapter-node 6 は実行時の `ORIGIN` を読み取らず、アプリは既定で構築時の `paths.origin` を固定しません。直接公開していた古い SSR 配置は、現在のツールで新しい完全配布物を作成して更新してください。
267
+
268
+ 上位で TLS を終端する場合は、ロードバランサーの実際の IP/CIDR を `trustedEdgeProxies` に指定します。独立 gateway は許可した実際の接続元の単一 `http` / `https` だけを採用し、その他の接続元や複合値では自身の接続プロトコルを使います。外部の `Forwarded`、ホスト/ポート転送値は上書きします。
269
+
255
270
  環境フラグ・初期アカウントパスワード・転送キーリングは起動コードも直接読み取るため、同じ接頭辞の親設定があっても保持します。
256
271
 
257
272
  生成処理は個別変数を優先し、配列は JSON を維持します。手書き JSON はモジュール細項の前に置く基礎値で、同一ソースの細項が優先されます。動的辞書、JSON テキスト、明示的な空オブジェクトの意味を維持します。全体置換を展開する際は最上位の `{}` リセットを残し、古い YAML フィールドの復活を防ぎます。コンテナー内パスは配布物のみ変更します。
package/README.md CHANGED
@@ -33,18 +33,19 @@ pnpm build --target desktop --platform windows --arch x64
33
33
 
34
34
  #### build 的可选参数
35
35
 
36
- | 参数 | 用途 |
37
- | -------------------------- | ----------------------------------------- |
38
- | `--target` | compile(默认)、image、app、desktop |
39
- | `--images` | serv、web 或 serv,web;只构建导出所选镜像 |
40
- | `--runtime` | auto(优先 Podman)、podman、docker |
41
- | `--network` | 容器构建网络,默认引擎设置 |
42
- | `--no-http-proxy` | 禁用本次构建代理(等价 none) |
43
- | `--sqlite-prebuild-mirror` | SQLite 预编译包的可信 HTTP(S) 根地址 |
44
- | `--platform` / `--arch` | 原生安装包的系统与架构 |
36
+ | 参数 | 用途 |
37
+ | ----------------------- | ----------------------------------------- |
38
+ | `--target` | compile(默认)、image、app、desktop |
39
+ | `--images` | serv、web 或 serv,web;只构建导出所选镜像 |
40
+ | `--runtime` | auto(优先 Podman)、podman、docker |
41
+ | `--network` | 容器构建网络,默认引擎设置 |
42
+ | `--no-http-proxy` | 禁用本次构建代理(等价 none) |
43
+ | `--platform` / `--arch` | 原生安装包的系统与架构 |
45
44
 
46
45
  #### 下载源和代理
47
46
 
47
+ SQLite 13 的原生二进制随 npm 包交付,使用同一 npm 源,无须额外下载器。已有工程升级时删除旧 SQLite 镜像参数并同步 Dockerfile;构建会实际打开内存数据库,确认目标平台的二进制可加载。
48
+
48
49
  `--image-source official|cn|custom` 同时作用于应用基础镜像和打包时缺少的中间件镜像。`--npm-source` 随 `--build` 控制 Corepack/pnpm;cn 使用毫秒镜像的 Docker Hub/GHCR 通道和 npmmirror。首次交互保存 `hai.json.build.sources`,命令覆盖只作用本次。代理使用 `--proxy-mode inherit|system|custom|none`、`--proxy-url` 与 `--proxy-bypass`;`--no-http-proxy` 等价 none。Docker/远程 Podman 的镜像拉取代理须在引擎侧设置,构建容器另做可达性检查。自定义源、平台范围及旧模板迁移见[下载源和代理](../../docs/usage/configuration/delivery.md#下载源和代理)。
49
50
 
50
51
  SDK 的 `DeployAppOptions.imageSource` 为 `{ type: 'cn' }` 或 `{ type: 'custom', registries: { 'docker.io': 'mirror.example.com/docker.io', 'ghcr.io': 'mirror.example.com/ghcr.io' } }`,`proxy` 为 `{ mode: 'inherit' }` 或 `{ mode: 'custom', url: 'http://127.0.0.1:10808', bypass: 'localhost' }`。缺省为官方源、继承进程代理。`resolveImageReference()` / `resolveDownloadProxy()` 是无需 init 的解析工具,不修改引擎设置。中间件归档保留原始引用,服务器继续离线导入。
@@ -130,6 +131,8 @@ CLI 的 --project-name 与 SDK 的 DeployAppOptions.projectName 覆盖入口已
130
131
 
131
132
  公共配置保存在 `.env` 和 `.env.<mode>`,连接凭据与 SSH 配置保存在忽略 Git 的 `.env.<mode>.local`,`.env.local` 用于本机共享私有值。构建不读取部署秘密。
132
133
 
134
+ HTTP API 的自定义请求头整体视为秘密,不按头名猜测是否包含凭据。保存已有环境时,缩进、`export` 与多行引号的旧项也会从同模式公共文件移入私有文件,避免原值残留。
135
+
133
136
  已有项目需把原构建对象移入 `hai.json.build`,把原部署 YAML 转成 JSON 放入 `hai.json.deploy`,删除原文件并保留现有 `HAI_DEPLOY_*` 变量。已有自建 S3 的项目首次升级必须全量部署:旧成功基线仍含已退出的一次性初始化服务,直接使用新增量包会被依赖存活检查拒绝;全量部署同时刷新中间件环境中的 `createBucket`,之后即可继续增量更新。
134
137
 
135
138
  直接部署时,向导按说明补齐服务器、SSH 用户、认证方式和端口等缺失配置,完整有效配置直接复用;`--yes` 不重复询问。SSH 支持 `auth: key`(私钥/agent)或 `auth: password`。省略 `auth` 时,仅非空 `password` 启用密码方式,否则保留 key/agent;显式 `key` 忽略残留密码。密码输入不回显并保留前后空格、前导零;有效密码不得包含 CR/LF/NUL,UTF-8 最多 1023 字节。私钥只保存路径,不读取或复制私钥内容。
@@ -239,6 +242,8 @@ SDK 在服务器本地健康通过并提交 `current` 后,还从操作机检
239
242
 
240
243
  `pnpm run deploy` 为所有容器模板统一提供“不启用 / 已有 PEM 证书和私钥路径 / Let’s Encrypt”。相对路径以工程根为基准,已有证书校验域名、有效期和密钥匹配后复制到私有发布包。Let’s Encrypt 使用固定版本官方 Certbot 镜像申请,每 12 小时检查续期,Nginx 自动重载。需要确认服务条款、真实邮箱、公网 DNS、80 端口和 CA 网络;隔离环境使用已有证书。证书状态保留在服务器,私钥不进入应用镜像。`--yes` 复用保存配置。
241
244
 
245
+ 只接受末级无软链接或硬链接的普通 PEM 文件,每份不超过 1 MiB;父目录仍须可信。Certbot `live/` 的软链接需安全复制为受控目录中的普通文件,或使用框架 `letsencrypt` 模式。
246
+
242
247
  配置为 `hai.json.deploy.provider.expose.https`,也可用环境私有文件覆盖。默认 HTTPS 443、HTTP 跳转开启,未配置保持 HTTP;启停或更改模式、域名、端口、本地证书需全量部署。配置和续期边界见[HTTPS 手册](../../docs/usage/configuration/delivery.md#可选https证书)。`--plan` 的 `root` 表示工程根,`serviceDir` 表示部署服务源码与配置目录,仅显示公开证书元数据。
243
248
 
244
249
  ### SDK
@@ -246,7 +251,12 @@ SDK 在服务器本地健康通过并提交 `current` 后,还从操作机检
246
251
  ```ts
247
252
  import { deploy } from '@h-ai/deploy'
248
253
 
249
- const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 18080 } } })
254
+ const initialized = await deploy.init({
255
+ provider: {
256
+ type: 'docker-ssh',
257
+ expose: { hostPort: 18080 }
258
+ }
259
+ })
250
260
  if (!initialized.success)
251
261
  throw new Error(initialized.error.message)
252
262
  try {
@@ -278,6 +288,10 @@ SSH 中断始终先记 `remoteExecution: 'unknown'`。docker-ssh SDK 用新连
278
288
 
279
289
  ### 运行环境文件与重复部署
280
290
 
291
+ SvelteKit SSR 的 HTTP/HTTPS 均使用独立 `gateway`,后端不公开端口。网关覆盖标准转发头,Compose 固定 adapter 的协议/Host/客户端地址信任;这些值不接受业务运行文件覆盖。adapter-node 6 不再读取运行期 `ORIGIN`,应用默认不固定构建期 `paths.origin`;旧直接公开 SSR 的部署须用当前工具重新生成全量交付包。
292
+
293
+ 外层 TLS 终止须将负载均衡真实 IP/CIDR 加入 `trustedEdgeProxies`;独立 gateway 仅对白名单真实对端接受单值 `http` / `https`,其他来源和组合值使用本连接协议,外部 `Forwarded` 与主机/端口转发头不直接透传。
294
+
281
295
  Node 后端(Serv / SvelteKit SSR)每次启动读取服务器 `<部署目录>/config/.env.runtime`。应用配置与托管连接在此合并,修改 `HAI_STORAGE_PUBLICENDPOINT` 等细项后重启对应后端即可;同一来源的细项覆盖父 JSON。配置目录只读挂载到 `/run/hai/config`,编辑器原子替换文件也会被下一次启动读取。私有代理标记和 Node 启动参数由部署装配管理;静态 Web、中间件原生环境、端口/挂载、Nginx 路由与限额变更仍需部署。仅更新 Web/中间件保留当前应用配置;后端局部更新保留服务器托管连接,其余值来自新包,全量更新采用新包并按已有凭据状态定稿。手工修改先备份,长期配置同步回源环境。
282
296
 
283
297
  每个部署包的外层 `README.txt` 和归档内 `APPLY.txt` 都包含文件索引、环境优先级、当前包的变量名和排障步骤。解包目录的 `config/.env.runtime` 是发布输入,部署根下的是当前运行配置,`releases/<ID>/` 下的是历史记录。外部 PostgreSQL 改密后更新项目源环境并发布后端。部署校验拒绝 URL 与分字段密码冲突,增量切换外部与随包中间件需要改用全量发布。
@@ -8,6 +8,16 @@ import { parseEnv } from 'node:util'
8
8
 
9
9
  const maximumBytes = 1024 * 1024
10
10
  const refreshCookieSecure = 'HAI_SERV_REFRESH_COOKIE_SECURE'
11
+ // 启动参数、代理身份和 adapter 转发信任均由 Compose 固定,不属于业务可重载配置。
12
+ const startupEnvironment = new Set([
13
+ 'NODE_OPTIONS',
14
+ 'HAI_DEPLOY_PRIVATE_PROXY',
15
+ 'PROTOCOL_HEADER',
16
+ 'HOST_HEADER',
17
+ 'PORT_HEADER',
18
+ 'ADDRESS_HEADER',
19
+ 'XFF_DEPTH',
20
+ ])
11
21
 
12
22
  /** 拒绝特殊文件、链接、超限与不可读文件,不输出秘密。 */
13
23
  function readText(name) {
@@ -109,9 +119,19 @@ function applyManagedPasswords(values, bindings, state) {
109
119
  }
110
120
  catch { throw new Error(`Invalid managed application configuration: ${prefix}`) }
111
121
  }
112
- const passwordField = prefix === 'HAI_STORAGE' ? 'secretAccessKey' : prefix === 'HAI_IAM_LDAP' ? 'bindPassword' : 'password'
113
- if (!['HAI_STORAGE', 'HAI_IAM_LDAP', 'HAI_DB', 'HAI_VECDB'].includes(prefix))
122
+ const passwordField = prefix === 'HAI_STORAGE'
123
+ ? 'secretAccessKey'
124
+ : prefix === 'HAI_IAM_LDAP'
125
+ ? 'bindPassword'
126
+ : 'password'
127
+ if (![
128
+ 'HAI_STORAGE',
129
+ 'HAI_IAM_LDAP',
130
+ 'HAI_DB',
131
+ 'HAI_VECDB',
132
+ ].includes(prefix)) {
114
133
  throw new Error('Unsupported managed middleware binding')
134
+ }
115
135
  const url = values[`${prefix}_URL`] ?? configuration.url
116
136
  if (['HAI_DB', 'HAI_VECDB'].includes(prefix) && url) {
117
137
  try {
@@ -129,8 +149,10 @@ function applyManagedPasswords(values, bindings, state) {
129
149
 
130
150
  /** 保留父 JSON 与显式细项;粗细覆盖由应用通用配置解析器完成。 */
131
151
  function serialize(values) {
132
- return `${Object.entries(values).sort(([left], [right]) => left.localeCompare(right)).filter(([name]) => name !== 'NODE_OPTIONS' && name !== 'HAI_DEPLOY_PRIVATE_PROXY').map(([name, value]) => {
133
- const literal = !value.includes('\'') ? `'${value}'` : JSON.stringify(value).replaceAll('\'', '\\u0027')
152
+ return `${Object.entries(values).sort(([left], [right]) => left.localeCompare(right)).filter(([name]) => !startupEnvironment.has(name)).map(([name, value]) => {
153
+ const literal = !value.includes('\'')
154
+ ? `'${value}'`
155
+ : JSON.stringify(value).replaceAll('\'', '\\u0027')
134
156
  return `${name}=${literal}`
135
157
  }).join('\n')}\n`
136
158
  }
@@ -141,10 +163,16 @@ function prepare(directory, previousManifest, previousEnvironment, credentialSta
141
163
  throw new Error('Invalid runtime configuration preparation mode')
142
164
  const base = new URL(directory, import.meta.url)
143
165
  const incoming = readManifest(new URL('manifest.json', base))
144
- const previous = mode === 'full' ? { metadata: {} } : readManifest(previousManifest)
145
- const before = mode === 'full' ? {} : readEnvironment(previousEnvironment)
166
+ const previous = mode === 'full'
167
+ ? { metadata: {} }
168
+ : readManifest(previousManifest)
169
+ const before = mode === 'full'
170
+ ? {}
171
+ : readEnvironment(previousEnvironment)
146
172
  const next = readEnvironment(new URL('config/.env.runtime', base))
147
- const entries = key => [...new Set(`${previous.metadata[key] ?? ''}\n${incoming.metadata[key] ?? ''}`.split('\n').filter(Boolean))]
173
+ const entries = key => [
174
+ ...new Set(`${previous.metadata[key] ?? ''}\n${incoming.metadata[key] ?? ''}`.split('\n').filter(Boolean)),
175
+ ]
148
176
  const keys = entries('managed-app-keys')
149
177
  if (keys.some(key => !/^HAI_[A-Z0-9_]+$/.test(key)))
150
178
  throw new Error('Invalid managed application environment key')
@@ -185,9 +213,8 @@ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.ur
185
213
  }
186
214
  else {
187
215
  const values = readEnvironment('./config/.env.runtime')
188
- // 启动参数与私有代理身份属于部署装配,不由业务运行文件覆盖。
189
- delete values.NODE_OPTIONS
190
- delete values.HAI_DEPLOY_PRIVATE_PROXY
216
+ for (const name of startupEnvironment)
217
+ delete values[name]
191
218
  // HAI 配置的显式进程来源最高;镜像内 NODE_ENV/HOST/PORT 默认值由运行文件定稿。
192
219
  const inherited = Object.fromEntries(Object.entries(process.env).filter(([name, value]) => name.startsWith('HAI_') && value !== undefined))
193
220
  for (const name of Object.keys(inherited).sort((left, right) => left.length - right.length)) {
package/dist/index.d.ts CHANGED
@@ -149,8 +149,8 @@ declare const DockerSshProviderConfigSchema: z.ZodObject<{
149
149
  baseDir: z.ZodDefault<z.ZodString>;
150
150
  runtime: z.ZodDefault<z.ZodEnum<{
151
151
  auto: "auto";
152
- podman: "podman";
153
152
  docker: "docker";
153
+ podman: "podman";
154
154
  }>>;
155
155
  }, z.core.$strip>>;
156
156
  expose: z.ZodObject<{
@@ -209,8 +209,8 @@ declare const ProviderConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
209
209
  baseDir: z.ZodDefault<z.ZodString>;
210
210
  runtime: z.ZodDefault<z.ZodEnum<{
211
211
  auto: "auto";
212
- podman: "podman";
213
212
  docker: "docker";
213
+ podman: "podman";
214
214
  }>>;
215
215
  }, z.core.$strip>>;
216
216
  expose: z.ZodObject<{
@@ -299,8 +299,8 @@ declare const DeployConfigSchema: z.ZodObject<{
299
299
  baseDir: z.ZodDefault<z.ZodString>;
300
300
  runtime: z.ZodDefault<z.ZodEnum<{
301
301
  auto: "auto";
302
- podman: "podman";
303
302
  docker: "docker";
303
+ podman: "podman";
304
304
  }>>;
305
305
  }, z.core.$strip>>;
306
306
  expose: z.ZodObject<{
@@ -1283,7 +1283,7 @@ declare function createDeploymentPlan(appDir: string, input: DeployConfigInput,
1283
1283
  host: string | undefined;
1284
1284
  port: number | undefined;
1285
1285
  directory: string | undefined;
1286
- runtime: "auto" | "podman" | "docker";
1286
+ runtime: "auto" | "docker" | "podman";
1287
1287
  hostPort: number;
1288
1288
  https: {
1289
1289
  type: "files" | "letsencrypt";
@@ -1400,4 +1400,5 @@ declare function importDeploymentSecrets(options: {
1400
1400
  changed: boolean;
1401
1401
  }>>;
1402
1402
 
1403
- export { DEPLOY_MIDDLEWARE, type DeployAppOptions, type DeployCommandState, type DeployConfig, type DeployConfigInput, DeployConfigSchema, type DeployCredentialOperations, type DeployError, type DeployFunctions, type DeployRecoveryInfo, type DeployResult, type DeployScanOptions, type DeploymentArtifact, DeploymentArtifactSchema, type DeploymentEnvironment, type DockerSshProviderConfig, type DownloadProxyConfig, HaiDeployError, type ImageSourceConfig, type MiddlewareBackend, type MiddlewareField, type MiddlewareMode, type MiddlewareRequirement, type PortExposeConfig, ProviderConfigSchema, type ProvisionResult, type ScanResult, type ServiceType, type SshConfig, artifactChecksum, canKeepMiddleware, createDeploymentPlan, deploy, describeMiddlewareBackend, getDeployCommandState, getDeployRecovery, importDeploymentSecrets, loadDeploymentConfig, loadDeploymentEnvironment, mergeEnvironmentLayers, normalizeProjectName, parseMiddlewareField, readDeploymentArtifact, resolveDownloadProxy, resolveImageReference, saveDeploymentEnvironment, saveMiddlewareEnvironment, validateMiddlewareField };
1403
+ export { DEPLOY_MIDDLEWARE, DeployConfigSchema, DeploymentArtifactSchema, HaiDeployError, ProviderConfigSchema, artifactChecksum, canKeepMiddleware, createDeploymentPlan, deploy, describeMiddlewareBackend, getDeployCommandState, getDeployRecovery, importDeploymentSecrets, loadDeploymentConfig, loadDeploymentEnvironment, mergeEnvironmentLayers, normalizeProjectName, parseMiddlewareField, readDeploymentArtifact, resolveDownloadProxy, resolveImageReference, saveDeploymentEnvironment, saveMiddlewareEnvironment, validateMiddlewareField };
1404
+ export type { DeployAppOptions, DeployCommandState, DeployConfig, DeployConfigInput, DeployCredentialOperations, DeployError, DeployFunctions, DeployRecoveryInfo, DeployResult, DeployScanOptions, DeploymentArtifact, DeploymentEnvironment, DockerSshProviderConfig, DownloadProxyConfig, ImageSourceConfig, MiddlewareBackend, MiddlewareField, MiddlewareMode, MiddlewareRequirement, PortExposeConfig, ProvisionResult, ScanResult, ServiceType, SshConfig };