@h-ai/deploy 1.0.0-beta.21 → 1.0.0-beta.23

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
@@ -119,7 +119,7 @@ Bodyless authenticated envelopes use X-Hai-Transport. Generated proxies set larg
119
119
 
120
120
  Dependency inputs are prepared under images/dependencies/ from package manifests, local archives and patches. Combine pnpm store caching with stable dependency layers. Source changes should reuse downloaded packages. Empty caches still permit online builds. Windows node_modules cannot supply Linux native dependencies. Offline builds additionally require base images, tools and matching ABI/architecture/libc binaries.
121
121
 
122
- The root package.json.version identifies the application. `.hai/build/docker/<buildId>/` contains the manifest, selected image archives and SHA-256. Root sites use format 4; non-root sites use format 5 with webBasePath. partial marks incremental builds and hasWeb records topology. servContainerPort and webContainerPort retain explicitly configured serv/web listening ports, including the image left out of a partial build. Omitted ports keep the deployment defaults. Rebuilding the same application version is allowed; unique build IDs/image references distinguish contents. Publish the local build pointer only after all exports succeed. Pin base images, middleware and tools; do not use latest.
122
+ The root package.json.version identifies the application. `.hai/build/docker/<buildId>/` contains the manifest, selected image archives and SHA-256. Image artifacts use format 5. `webBasePath` records the public mount path, with an empty string for the domain root. partial marks incremental builds and hasWeb records topology. servContainerPort and webContainerPort retain explicitly configured serv/web listening ports, including the image left out of a partial build. Omitted ports keep the deployment defaults. Rebuilding the same application version is allowed; unique build IDs/image references distinguish contents. Publish the local build pointer only after all exports succeed. Pin base images, middleware and tools; do not use latest.
123
123
 
124
124
  #### Website mount path
125
125
 
@@ -135,7 +135,7 @@ The default deployment name comes from `package.json.name` at the project root (
135
135
 
136
136
  For a gateway that only exposes `/somepath/`, build with `PUBLIC_BASE_PATH=/somepath` and explicitly place Serv `http.apiPrefix`, health/readiness, docs and storage `publicEndpoint` under that prefix. The SDK generates proxy paths and browser API configuration from those effective settings. Preserve the prefix at the edge; handle internal probes and root ACME challenges separately. [Complete configuration and checks](../../docs/usage/configuration/delivery.md#所有对外业务路径必须带同一目录).
137
137
 
138
- Artifact formats 4 and 5 record primaryService (serv/web); hasWeb describes the complete browser topology. Format 5 also records a non-root webBasePath. Only serv + web generates a same-origin API proxy. Rebuild artifacts using formats 1–3. Back up the existing deployment and verify project identity, volumes and managed credentials before establishing a new full deployment baseline. Tools do not migrate data across projects. Full deployments still remove obsolete service containers under the same Compose project; editing deploy-target.json.directory alone does not migrate resources.
138
+ `primaryService` records the primary service (`serv` or `web`), and `hasWeb` describes the complete browser topology. Projects with both services get a same-origin API proxy.
139
139
 
140
140
  Prepare `.env.<environment>` and the project root `hai.json`, with image/native configuration in `build` and application deployment in `deploy`. Fullstack scripts still point to packages/<project>-serv, and API workspaces to apps/<project>-serv, only to scan runtime dependencies and module YAML. Frontend and backend share the project configuration.
141
141
 
@@ -163,6 +163,8 @@ In `hai deploy`, choose a URL or individual fields for custom PostgreSQL, MySQL,
163
163
 
164
164
  #### Direct private object storage access
165
165
 
166
+ Nginx serves a standalone HTTP 404 page when a presigned download reaches the static site fallback or the SSR/API gateway receives an application 404. The page uses Chinese, English, or Japanese based on the browser language. Update the proxy rules with a full deployment bundle. Rebuild independently run static web images from the updated CLI templates. [Download troubleshooting](../../docs/usage/configuration/data.md#下载链接无法访问)
167
+
166
168
  Self-hosted S3 uses an internal endpoint. Set `_storage.yml` publicEndpoint to an external address such as `https://app.example.com/delivery/files`. Nginx exposes `/delivery/files/<bucket>/...`, removes the proxy directory and forwards the original bucket URI, signature query and Host directly to storage:9000. Files bypass Serv; omitting the directory retains root bucket routes. A route may sit under the website directory; API, asset and health conflicts fail packaging. Storage ports/consoles remain private, buffering/signature logs are disabled, and S3 handles authorization and cross-origin CORS. External ingress must retain the full entry path and Host so only the SDK gateway removes the prefix.
167
169
 
168
170
  Managed deployments retain bucket/region/prefix/publicEndpoint/publicUrl/operationLog while replacing internal connections and managed credentials. Adding the gateway or changing access settings requires a full baseline; partial preflight rejects mismatching configuration fingerprints. App/storage partial updates refresh retained proxy DNS, and recovery restores the previous topology. External/kept storage gets no local sidecar route; Local does not expose private directories. See the [storage handbook](../../docs/usage/configuration/data.md).
@@ -211,9 +213,7 @@ The server holds a nonblocking kernel lock with util-linux `flock` on `.deploy.l
211
213
 
212
214
  Preflight verifies the actual named volume and backend family for self-hosted `db`, `storage` and `vecdb`. The server's `<remoteDir>/persistent-backends` ledger records these bindings before any service starts and preserves them when a service is removed, a first installation fails, or recovery runs. Removing PostgreSQL while retaining its volume and later adding MySQL is therefore refused. Protect and back up the ledger together with `managed-secrets.env` and the data volumes. Never delete or edit it to force adoption of an old volume. These are private deployment metadata, with no new public configuration option.
213
215
 
214
- Legacy adoption requires a known family from the successful baseline, one actual service container, and matching named-volume mounts and image family. Unknown volumes left by removed services are not identified by their names or passwords; verify the data and plan an explicit migration. A missing volume owned by the active baseline stops deployment instead of silently creating an empty database. Each new release saves verified old bindings in `previous-state-backends`; recovery checks that snapshot, the permanent ledger and existing volumes without reverting the ledger.
215
-
216
- The separate [controlled credential import](docs/credential-import.md) path can supply evidence for an unclaimed volume: valid v2 state must bind the exact project, credential group and volume, and one running original container must confirm the same project/service through consistent Docker/Podman labels, actual mounts and image family. Missing evidence still fails closed. Import never overrides a known ledger claim or engine identity conflict and does not create a successful baseline. Without `current`, use the current CLI to create a **new full bundle with a new ID** for the first takeover; incremental updates require that full deployment to succeed first.
216
+ Each existing data volume must match the service, backend family and volume in the protected ledger. A missing active volume or ledger record stops deployment. Restore verified backups before retrying. Each new release saves `previous-state-backends` so recovery can revalidate its bindings against the ledger and existing volumes.
217
217
 
218
218
  These checks apply to `apply.sh` on the **target Linux server over SSH**: keep the SSH user and local daemon/store fixed. Docker must use its default context; Podman must actually run locally. Remote connections and explicit storage overrides are refused. In production, pin `remote.runtime` to the verified `docker` or `podman`. If installing Podman changes the engine selected by `auto`, first restore the original runtime, SSH user and store. Intentional server, daemon or storage changes need a separate migration; matching user IDs or directory names do not prove compatibility. Building and packaging on Windows/macOS with Docker Desktop or a Podman VM, then deploying over SSH, remains supported.
219
219
 
@@ -299,7 +299,7 @@ Environment flags, initial account passwords and the transport key ring are also
299
299
 
300
300
  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.
301
301
 
302
- The deployment archive contains `apply.sh`, `APPLY.txt`, `manifest.json`, `config/`, `images/`, and `.hai/` at the top level. `config/.env.runtime` is the single application environment file. `manifest.json.metadata` holds nonsecret layout, dependencies, health paths, image lists and managed bindings. `.hai/compose.json` is a complete snapshot; partial updates replace selected service definitions and retain other services without historical Compose chains. `.hai/` also contains native environment, the loader, Nginx/TLS, policy and checksums. Secrets stay out of the manifest; helper scripts are embedded in `apply.sh`. Failure recovery restores application configuration before services while protecting credentials, backend ledgers and volumes. Bundle format 2 has no old-layout compatibility or migration. Runtime preparation reuses the already imported Node application image in a temporary container with networking disabled. It downloads no extra image and requires no host Node or jq.
302
+ The deployment archive contains `apply.sh`, `APPLY.txt`, `manifest.json`, `config/`, `images/`, and `.hai/` at the top level. `config/.env.runtime` is the single application environment file. `manifest.json.metadata` holds nonsecret layout, dependencies, health paths, image lists and managed bindings. `.hai/compose.json` is a complete snapshot; partial updates replace selected service definitions and retain other services without historical Compose chains. `.hai/` also contains native environment, the loader, Nginx/TLS, policy and checksums. Secrets stay out of the manifest; helper scripts are embedded in `apply.sh`. Failure recovery restores application configuration before services while protecting credentials, backend ledgers and volumes. The deployment archive uses `bundleFormat: 2`. Runtime preparation reuses the already imported Node application image in a temporary container with networking disabled. It downloads no extra image and requires no host Node or jq.
303
303
 
304
304
  Node backends (Serv / SvelteKit SSR) read `<deployment-root>/config/.env.runtime` on every start. This single application file includes managed connections. Edit a field such as `HAI_STORAGE_PUBLICENDPOINT`, then restart the backend; fields override parent JSON within the same source. The configuration directory is mounted read-only at `/run/hai/config`, so atomic file replacement is visible on restart. Private proxy identity and Node startup options remain deployment settings. Static Web, native middleware environment, ports/mounts, and Nginx routes or limits require deployment. Web/middleware-only updates retain the file; partial backend updates preserve managed connections, while full updates use the new package with existing managed credentials. Back up edits and copy permanent settings into the source environment.
305
305
 
@@ -323,7 +323,7 @@ Each delivery still generates `config/.env.runtime` inside the archive for Compo
323
323
 
324
324
  Project-root `hai.json.deploy` stores deployment structure, `.env.<environment>` stores public settings, and `.env.<environment>.local` stores SSH settings and middleware secrets. Environment files default to the project/workspace root; override with `--env-dir`. After configuration, `pnpm run deploy --env test --build --bundle-only --yes` reuses complete settings without prompts; add `--skip-middleware` to retain middleware configuration. Interactive bundle-only mode offers to save or update SSH settings at the final configuration step; editing a delivery's `deploy-target.json` does not update the project.
325
325
 
326
- The server persists managed middleware passwords in `<remoteDir>/managed-secrets.env` (mode 0600); back it up with data volumes. Each package supplies random first-use candidates without a build-machine cache. The online SDK, deploy.sh, deploy.ps1 and deploy-local.sh resolve server values under the deployment lock and update both application connections and native middleware variables. The delivery tar stays immutable; only private server runtime files receive resolved values. Missing state with an existing corresponding volume stops deployment before services change: restore the server credential backup. Deployment never silently rotates passwords or deletes data. Legacy credentials can be explicitly verified and imported using the procedure below.
326
+ The server persists managed middleware passwords in `<remoteDir>/managed-secrets.env` (mode 0600); back it up with data volumes. Each package supplies random first-use candidates without a build-machine cache. The online SDK, deploy.sh, deploy.ps1 and deploy-local.sh resolve server values under the deployment lock and update both application connections and native middleware variables. The delivery tar stays immutable; only private server runtime files receive resolved values. Missing state with an existing corresponding volume stops deployment before services change: restore the server credential backup. Deployment never silently rotates passwords or deletes data.
327
327
 
328
328
  ### Read-only deployment plan
329
329
 
@@ -333,12 +333,10 @@ Use `--plan --inspect-remote` (SDK inspectRemote:true) to read current and the s
333
333
 
334
334
  Resources use the complete execution topology. `containers` lists selected explicit container names; Compose-named LDAP/SMTP services appear in `composeManagedServices`. The SSR/API storage gateway appears in the actual selected or retained scope. `logicalVolumes` declares the complete Compose topology, including retained services and data volumes still mounted by the app; it does not mean those volumes will be created or replaced. Engine names are scoped by the Compose project. Unselected middleware has action keep, and cloud provisioning follows the actual selection without exposing credentials.
335
335
 
336
- ### Capacity and credential import
336
+ ### Transport capacity
337
337
 
338
338
  Explicit plaintext limits are preserved. Packaging rejects feedback requirements above an explicit limit with a configuration conflict. Omitted/auto values derive capacity; the Web proxy and Kit BODY_SIZE_LIMIT use the same encrypted budget. Plan target.runtime reports remote provider.remote.runtime separately from local packaging options.runtime; auto is not a detected runtime.
339
339
 
340
- Use `importDeploymentSecrets({ directory, inputFile, runtime })` or run `hai deploy-secrets <directory> --import <private.json>` on the server for read-only verification. Only explicit `--apply` / dryRun:false imports state. The tool verifies projects, containers, volumes and live credentials; it never infers passwords from old bundles, rotates credentials or rebuilds services. V2 state supports special characters and is atomically written with mode 0600 under the deployment flock. Ordinary offline deployment still requires no server Node; this one-time import tool needs supported Node and installed CLI/deploy. See the [import and recovery procedure](docs/credential-import.en.md).
341
-
342
340
  ### Request policy files and trusted proxies
343
341
 
344
342
  Serv `http.access` and SvelteKit `access` can reference separate yml/yaml files. Deployment reads effective application configuration, including environment overrides such as `HAI_SERV`, `HAI_SERV_HTTP_ACCESS` and `HAI_KIT_ACCESS`, validates the file and includes a normalized snapshot in the bundle. Runtime configuration points to `/run/hai/request-access.yml` with a read-only Compose mount. The project retains its original file reference. The snapshot participates in SHA-256 verification; missing or invalid files fail before upload. The upload archive and its policy snapshot are integrity-checked inputs; replacing the SDK-managed snapshot requires a new bundle and deployment. The deployed Node backend reads its mounted `.env.runtime` on restart as described above. Inline rule changes do not rewrite the policy snapshot or Nginx configuration.
package/README.ja.md CHANGED
@@ -119,7 +119,7 @@ pnpm run deploy --env prod --build --bundle-only --image-source cn --npm-source
119
119
 
120
120
  構築器はパッケージ情報、ローカルアーカイブとパッチを images/dependencies/ に準備し、pnpm store と依存レイヤーをキャッシュします。通常のソース変更で全依存を再ダウンロードしない構成です。キャッシュが空でもオンライン構築できます。Windows の node_modules は Linux のネイティブ依存を代替できません。完全オフライン構築には基底イメージ、ツールと一致する ABI・アーキテクチャ・libc のバイナリも準備します。
121
121
 
122
- アプリの版はルートpackage.json.versionで管理します。`.hai/build/docker/<buildId>/`にmanifest、選択イメージのtarとSHA-256を出力します。ルートは形式4、非ルートはwebBasePathを含む形式5です。partialは部分構築、hasWebは構成を記録します。servContainerPortとwebContainerPortは明示したserv/webの待受ポートを保持し、部分構築で選ばなかったイメージのポートも失いません。未指定のポートにはデプロイ時の既定値を使います。同じアプリ版でも再構築可能で、構築IDとイメージ参照で内容を区別します。全出力に成功してからローカルの構築参照を更新します。基底・ミドルウェア・ツールは版を固定し、latestを使いません。
122
+ アプリの版はルートpackage.json.versionで管理します。`.hai/build/docker/<buildId>/`にmanifest、選択イメージのtarとSHA-256を出力します。イメージ成果物は形式 5 を使用します。`webBasePath` に公開マウントパスを記録し、ドメインのルートは空文字で表します。partialは部分構築、hasWebは構成を記録します。servContainerPortとwebContainerPortは明示したserv/webの待受ポートを保持し、部分構築で選ばなかったイメージのポートも失いません。未指定のポートにはデプロイ時の既定値を使います。同じアプリ版でも再構築可能で、構築IDとイメージ参照で内容を区別します。全出力に成功してからローカルの構築参照を更新します。基底・ミドルウェア・ツールは版を固定し、latestを使いません。
123
123
 
124
124
  #### サイトの公開ディレクトリー
125
125
 
@@ -135,7 +135,7 @@ SDKは対応するNginx、実行時設定URL、SSRヘルスチェック、公開
135
135
 
136
136
  既定の配置名はプロジェクトルート(最も近い `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` は削除しません。
137
137
 
138
- 成果物形式4・5はprimaryService(serv/web)と、工程全体のブラウザー構成を示すhasWebを記録します。形式5には非ルートのwebBasePathも含まれます。同一オリジンAPIプロキシはserv + webの場合だけ生成します。形式1~3は再構築が必要です。既存デプロイをバックアップし、プロジェクト名・ボリューム・管理対象の認証情報を確認してから、新しい完全デプロイの基準を作成してください。プロジェクト間のデータ移行は自動化しません。完全デプロイでは同じComposeプロジェクトの旧サービスコンテナーを削除するため、deploy-target.json.directoryの変更だけでは移行できません。
138
+ `primaryService` は主サービス(`serv` または `web`)を、`hasWeb` はブラウザー構成を記録します。同一オリジン API プロキシは両方のサービスがある場合に生成されます。
139
139
 
140
140
  `.env.<環境>` とプロジェクトルートの `hai.json` を用意します。`build` にイメージ・ネイティブ構築、`deploy` にアプリ全体の配置設定を保存します。fullstack は packages/<プロジェクト>-serv、API workspace は apps/<プロジェクト>-serv を実行依存とモジュール YAML の走査入口として使います。フロントとバックエンドは同じ設定を共有します。
141
141
 
@@ -163,6 +163,8 @@ SSH 設定は選択環境の `.env.<環境>.local` に保存します。`--bundl
163
163
 
164
164
  #### 非公開オブジェクトストレージへの直接アクセス
165
165
 
166
+ 署名付きダウンロードが静的サイトのフォールバックに到達した場合、または SSR/API ゲートウェイがアプリから 404 を受け取った場合、Nginx は専用ページを HTTP 404 で返します。ブラウザーの言語に応じて中国語、英語、日本語で表示します。プロキシのルールを更新するには完全デプロイバンドルを使用し、静的 Web イメージを単独で使う場合は更新後の CLI テンプレートから再構築してください。[ダウンロードのトラブルシューティング](../../docs/usage/configuration/data.md#下载链接无法访问)
167
+
166
168
  自前 S3 の endpoint は内部接続先です。publicEndpoint に `https://app.example.com/delivery/files` などの外部アドレスを設定できます。Nginx は `/delivery/files/<bucket>/...` を受け、入口パスだけを除去し、本来のバケット URI、署名クエリ、Host を保持して storage:9000 に転送します。Serv を経由せず、パス省略時は従来のルートバケット形式です。サイト配下に置けますが API、資源、ヘルスパスの競合は拒否します。ポートと管理コンソールは非公開、バッファリングと署名ログは無効です。認可と CORS は S3 に設定し、外部プロキシは入口パスと Host を保持してください。
167
169
 
168
170
  自前構成は bucket/region/prefix/publicEndpoint/publicUrl/operationLog を保持し、内部接続と受管認証情報だけを置き換えます。gateway 追加や公開設定変更には完全デプロイが必要で、部分更新の事前検証は設定摘要の不一致を拒否します。アプリ/ストレージ部分更新では保持プロキシの DNS を更新し、失敗時は以前の構成に復元します。外部/保持接続にローカルルートは生成せず、Local の非公開ディレクトリも公開しません。[ストレージ手引き](../../docs/usage/configuration/data.md)を参照してください。
@@ -211,9 +213,7 @@ pnpm run deploy --env prod --build --bundle-only
211
213
 
212
214
  事前検証で自前 `db`、`storage`、`vecdb` の実ボリューム名とバックエンド種類を確認します。サーバーの `<remoteDir>/persistent-backends` 台帳には起動前に対応関係を保存し、サービス削除、初回配置失敗、自動復元でも記録を残します。そのため、PostgreSQL を削除してボリュームを残した後に MySQL を追加する操作も拒否します。`managed-secrets.env`、データボリュームと一緒に保護・バックアップし、旧ボリュームを強制使用するために台帳を削除・編集しないでください。これらは配置内部のメタデータで、公開設定項目の追加はありません。
213
215
 
214
- 旧配置の情報を補うには、成功済み基準の既知の種類と、唯一の実サービスコンテナーの名前付きボリューム・イメージ種類が一致する必要があります。削除済みサービスの未知の旧ボリュームを、名前やパスワードから推測しません。データを確認して明示的に移行します。現行基準のボリュームがなければ配置を停止し、空のデータベースを自動生成しません。新配置の `previous-state-backends` は確認済みの旧対応関係を保存し、復元前に台帳と既存ボリュームを再確認するためだけに使います。永久台帳は巻き戻しません。
215
-
216
- 別途[管理された認証情報インポート](docs/credential-import.md)による補証も可能です。台帳に対象ボリュームの記録がない場合に限り、正しい v2 状態のプロジェクト・認証情報グループ・ボリュームが完全一致し、唯一の実行中旧コンテナーの Docker/Podman ラベル、実マウント、イメージ種類でも同じプロジェクトとサービスを確認します。一つでも不足すれば拒否し、既知の台帳やエンジン識別の競合を上書きしません。インポートは成功基準を作りません。`current` がなければ現在の CLI で**新 ID の全量パッケージ**を作り、最初の完全配置が成功してから増分を使います。
216
+ 既存のデータボリュームは、保護された台帳のサービス、バックエンド種類、ボリューム名と一致する必要があります。稼働中のボリュームまたは台帳の記録がなければ配置を停止します。確認済みのバックアップを復元してから再試行してください。新しいリリースの `previous-state-backends` は、復旧前に台帳と実ボリュームを再検証するために使います。
217
217
 
218
218
  この検査は **SSH 接続先の Linux サーバー**で `apply.sh` を実行するときに適用します。SSH ユーザーとローカル daemon/store を固定し、Docker は default context、Podman は実際のローカル実行が必要です。リモート接続や明示的な保存先上書きは拒否します。本番では `remote.runtime` を検証済みの `docker` または `podman` に固定してください。Podman の追加で `auto` が別エンジンを選んだ場合、まず元の runtime、SSH ユーザー、保存先に戻します。意図的なサーバー・daemon・保存先変更は個別に移行し、同じ uid やパスだけで互換性を判断しません。Windows/macOS の操作端末で Docker Desktop や Podman VM を使って構築・梱包し、SSH で配置する方法は引き続き利用できます。
219
219
 
@@ -323,7 +323,7 @@ Podman では設定済みの healthcheck を明示的に実行して状態を再
323
323
 
324
324
  プロジェクトルートの `hai.json.deploy` に配置構造、`.env.<環境>` に公開設定、`.env.<環境>.local` に SSH とミドルウェアの認証情報を保存します。環境ファイルは既定でプロジェクト/workspace ルート、変更時は `--env-dir` を指定します。設定後は `pnpm run deploy --env test --build --bundle-only --yes` で再入力を省略でき、ミドルウェア設定を保持する場合は `--skip-middleware` を追加します。対話式 bundle-only は最後に SSH 設定の保存・変更を確認します。配布物の `deploy-target.json` の編集はプロジェクトに反映されません。
325
325
 
326
- 自前ミドルウェアのパスワードはサーバーの `<remoteDir>/managed-secrets.env`(権限 0600)で永続管理し、データボリュームと一緒にバックアップします。各パッケージは初回用の候補のみ生成し、ビルド端末のキャッシュに依存しません。オンライン SDK、deploy.sh、deploy.ps1、deploy-local.sh は配置ロック内でサーバー値を再利用し、アプリ接続とミドルウェア固有変数の両方へ反映します。配布 tar は変更せず、サーバーの非公開実行ファイルだけに確定値を反映します。対応するボリュームが存在し状態がない場合、サービス変更前に停止してバックアップ復元を求めます。自動的なパスワード変更やデータ削除は行わず、旧認証情報は下記の明示的な検証・導入手順で移行できます。
326
+ 自前ミドルウェアのパスワードはサーバーの `<remoteDir>/managed-secrets.env`(権限 0600)で永続管理し、データボリュームと一緒にバックアップします。各パッケージは初回用の候補のみ生成し、ビルド端末のキャッシュに依存しません。オンライン SDK、deploy.sh、deploy.ps1、deploy-local.sh は配置ロック内でサーバー値を再利用し、アプリ接続とミドルウェア固有変数の両方へ反映します。配布 tar は変更せず、サーバーの非公開実行ファイルだけに確定値を反映します。対応するボリュームが存在し状態がない場合、サービス変更前に停止してバックアップ復元を求めます。パスワードとデータは保持されます。
327
327
 
328
328
  ### 読み取り専用デプロイ計画
329
329
 
@@ -333,12 +333,10 @@ Podman では設定済みの healthcheck を明示的に実行して状態を再
333
333
 
334
334
  リソースは実行側の完全な構成を共用します。`containers` は今回選択した明示名のみ、Compose が命名する LDAP/SMTP は `composeManagedServices` に表示します。SSR/API のストレージ gateway も更新・保持対象に表示します。`logicalVolumes` は保持サービスとアプリが継続使用するデータを含む構成全体の論理キーで、新規作成や再作成の指示ではありません。実際の名前は Compose プロジェクトのスコープで決まります。未選択ミドルウェアの action は keep で、クラウド開通は実際の選択範囲に従い、認証値を表示しません。
335
335
 
336
- ### 容量と認証情報のインポート
336
+ ### 暗号化通信の容量
337
337
 
338
338
  明示された平文上限を保持し、フィードバックの必要量が超える場合は競合を示して梱包を拒否します。省略/auto だけ自動計算し、Web プロキシと Kit BODY_SIZE_LIMIT は同じ暗号文予算を使います。計画の target.runtime はリモートの provider.remote.runtime を示し、ローカル梱包 options.runtime とは別です。auto を検出済みと表示しません。
339
339
 
340
- `importDeploymentSecrets({ directory, inputFile, runtime })` またはサーバー上の `hai deploy-secrets <directory> --import <private.json>` で読み取り専用検査を行います。明示 `--apply` / dryRun:false のみ保存します。プロジェクト・コンテナ・ボリューム・実際の認証情報を検証し、古いパッケージからの推測、パスワード変更、サービス再作成はしません。特殊文字対応 v2 状態をデプロイ共通 flock 内で原子的に0600で保存します。通常のオフライン配布にサーバー Node は不要で、一度限りの移行ツールには対応 Node と CLI/deploy が必要です。[導入・復旧手順](docs/credential-import.ja.md)を参照してください。
341
-
342
340
  ### リクエストポリシーファイルと信頼する代理
343
341
 
344
342
  Serv の `http.access` と SvelteKit の `access` は独立した yml/yaml を参照できます。配備は `HAI_SERV`、`HAI_SERV_HTTP_ACCESS`、`HAI_KIT_ACCESS` などの環境上書きを含む実効設定を読み、検証済みの正規化スナップショットを配布物へ含めます。実行時は `/run/hai/request-access.yml` を Compose の読み取り専用マウントで参照し、工程の元の参照先は変更しません。SHA-256 検証に含まれ、ファイル不足・不正はアップロード前に失敗します。アップロードするアーカイブとそのポリシースナップショットは整合性検証の対象です。SDK 管理のスナップショットを置き換える場合は新しい配布物を作成します。配置済み Node バックエンドのマウント済み `.env.runtime` は上記手順で編集・再起動できます。インライン規則の変更ではスナップショットや Nginx 設定は書き換わりません。
package/README.md CHANGED
@@ -131,7 +131,7 @@ pnpm run deploy --env prod --build --bundle-only --image-source cn --npm-source
131
131
 
132
132
  构建器将锁文件、包配置、本地归档和补丁准备为 `images/dependencies/` 输入,结合 pnpm store 缓存与 Docker 分层复用下载。源码修改不应重新下载全部依赖;缓存为空仍能联网构建。Windows node_modules 不用于 Linux 镜像。完全离线构建还需预先准备基础镜像、工具链和匹配 ABI/架构/libc 的原生预编译包。
133
133
 
134
- 版本来自应用根 package.json.version。制品位于 `.hai/build/docker/<buildId>/`,包括manifest.json、所选镜像tar和SHA-256;根目录使用格式4,非根目录使用格式5及webBasePath。partial 标识部分构建,hasWeb 保留工程拓扑。清单还会记住配置中填写的 serv/web 容器端口(servContainerPort、webContainerPort),只打包一个镜像也不会丢掉另一个的端口;没填写则沿用部署默认值。相同应用版本允许重建,构建编号和镜像引用区分实际内容;全部导出成功才更新本机构建入口。基础镜像、中间件及工具使用明确版本,不使用 latest。
134
+ 版本来自应用根 package.json.version。制品位于 `.hai/build/docker/<buildId>/`,包括manifest.json、所选镜像tar和SHA-256;镜像制品统一使用格式 5。`webBasePath` 记录公开挂载目录,空字符串表示域名根目录。partial 标识部分构建,hasWeb 保留工程拓扑。清单还会记住配置中填写的 serv/web 容器端口(servContainerPort、webContainerPort),只打包一个镜像也不会丢掉另一个的端口;没填写则沿用部署默认值。相同应用版本允许重建,构建编号和镜像引用区分实际内容;全部导出成功才更新本机构建入口。基础镜像、中间件及工具使用明确版本,不使用 latest。
135
135
 
136
136
  #### 网站挂载目录
137
137
 
@@ -147,7 +147,7 @@ SDK据制品生成Nginx目录、运行配置入口、SSR健康路径和返回URL
147
147
 
148
148
  全站仅开放 `/somepath/` 时,构建设置 `PUBLIC_BASE_PATH=/somepath`,并将 Serv 的 `http.apiPrefix`、健康/就绪和文档路径及存储 `publicEndpoint` 显式配置到同一目录。SDK 按这些有效配置生成代理和浏览器 API 地址;外层网关保留前缀,内部探活和 ACME 根路径单独处理。[完整配置与验收](../../docs/usage/configuration/delivery.md#所有对外业务路径必须带同一目录).
149
149
 
150
- 制品格式4和5都记录primaryService(serv/web),hasWeb表示完整工程是否包含浏览器端;格式5另记录非根目录webBasePath。只有serv + web才生成同源API代理。格式1至3制品须重新构建。旧部署先备份并核对项目名、数据卷和受管凭据,再切换到新的完整部署基线;工具不自动跨项目迁移数据。完整部署仍会按Compose规则清理同项目的旧服务容器,不能仅修改deploy-target.json.directory完成迁移。
150
+ `primaryService` 记录主服务(`serv` 或 `web`),`hasWeb` 记录工程是否包含浏览器端。只有 `serv` 与 `web` 同时存在时才生成同源 API 代理。
151
151
 
152
152
  准备 `.env.<环境>`(例如 `.env.prod`)和项目根 `hai.json`,其中 `build` 描述镜像与桌面构建,`deploy` 描述整个应用的部署。fullstack 的 deploy 参数仍指向 `packages/<项目>-serv`,API workspace 指向 `apps/<项目>-serv`,仅用于扫描运行依赖和模块 YAML;前后端构建与部署配置统一在项目根。
153
153
 
@@ -177,6 +177,8 @@ SSH 参数保存到选中环境的 `.env.<环境>.local`。`--bundle-only` 在
177
177
 
178
178
  #### 私有对象存储直连
179
179
 
180
+ 预签名下载请求落入静态网站回退,或 SSR/API 网关收到应用的 404 时,Nginx 返回 HTTP 404 和独立的下载提示页。提示按浏览器语言显示中文、英文或日文。现有容器部署使用完整交付包更新代理规则,独立静态 Web 镜像使用更新后的 CLI 模板重新构建。[下载排查](../../docs/usage/configuration/data.md#下载链接无法访问)
181
+
180
182
  自建 S3 的 `endpoint` 使用 Compose 内部地址,浏览器地址用 `_storage.yml` 的 `publicEndpoint` 配置,例如 `https://app.example.com/delivery/files`。Nginx 对外开放 `/delivery/files/<bucket>/...`,去掉 `/delivery/files` 后将原始桶 URI、签名查询与 Host 直接转发 storage:9000,文件不经过 Serv;省略目录时继续使用根桶路径。入口可位于网站目录内,API/资源/健康路径冲突会在打包前失败。存储端口与控制台不公开,对象缓冲和签名日志关闭;S3 负责私有桶授权和跨源 CORS。外层代理须保留完整入口路径与 Host,只由 SDK 网关去掉前缀。
181
183
 
182
184
  自建配置保留 bucket/region/prefix/publicEndpoint/publicUrl/operationLog,只替换内部连接与托管凭据。首次增加网关或改变这些访问设置须全量部署,增量预检按配置摘要拒绝不一致;普通应用/存储增量刷新保留代理的服务 DNS,失败恢复使用旧拓扑。外部/保持连接不生成本地存储路由,Local 不公开私有目录。详见[存储配置手册](../../docs/usage/configuration/data.md#配置人员区分三个访问地址).
@@ -235,9 +237,7 @@ pnpm run deploy --env prod --build --bundle-only
235
237
 
236
238
  部署前核对自建 `db`、`storage`、`vecdb` 的实际卷与后端家族;禁止把 PostgreSQL 数据卷交给 MySQL、RustFS 数据卷交给 MinIO,或在向量库引擎之间复用原卷。服务器 `<remoteDir>/persistent-backends` 长期记录这些绑定,在任何服务启动前保存;全量移除服务、首次安装失败和自动恢复都不会清掉记录。因此“移除 PostgreSQL → 保留卷 → 再加 MySQL”也会被拒绝。该文件与 `managed-secrets.env`、数据卷成套保护和备份,不得删除或编辑账本强行认领旧卷;这些是部署私有元数据,没有新增公开配置项。
237
239
 
238
- 旧部署缺少完整绑定时,只有成功基线中的已知家族、唯一真实服务容器的命名卷挂载和镜像家族一致,才能补证接管。已移除服务留下的未知旧卷不会按名称或密码猜测;需要核实数据并制定独立迁移方案。当前成功基线的卷缺失时停止发布,不自动创建空库。新发布的 `previous-state-backends` 保存已确认的旧绑定,只用于恢复前再次核验;恢复还要求旧卷存在且账本一致,不回退永久账本。
239
-
240
- 另有明确的[受控凭据导入路径](docs/credential-import.md):账本尚未认领该卷时,合法 v2 状态必须绑定准确项目、凭据组和卷,并由同项目/服务的唯一运行原容器,以一致的 Docker/Podman 标签、真实 Mounts 和 Config.Image 家族共同补证。缺任一证据仍拒绝,导入不能覆盖已知账本或引擎身份冲突。导入不建立成功基线;没有 `current` 时,首次接管必须用当前 CLI 生成**新 ID 的完整全量包**,成功后才可增量。
240
+ 已有数据卷必须与受保护账本中的服务、后端家族和卷名匹配。缺少活动卷或相应记录时停止部署,恢复已核验的备份后再试。每次发布保留 `previous-state-backends`,用于恢复前重新核验对应的账本记录与实际卷。
241
241
 
242
242
  这些身份检查在 **SSH 目标 Linux 服务器**执行 `apply.sh` 时生效:使用固定 SSH 用户、固定本地 daemon/store,Docker 要求默认 context,Podman 要求实际本地模式;远程连接与显式存储覆盖环境会被拒绝。生产建议显式设置 `remote.runtime` 为已验收的 `docker` 或 `podman`。若 `auto` 因新装 Podman 换了引擎,应先恢复原 runtime、SSH 用户和存储,再重试;有意更换服务器、daemon 或数据存储则单独迁移,不能用相同 uid 或目录名证明数据兼容。Windows/macOS 操作机通过 Docker Desktop 或 Podman VM 构建、打包再 SSH 发布不受这一服务器限制。
243
243
 
@@ -350,7 +350,7 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
350
350
 
351
351
  项目根 `hai.json.deploy` 保存部署结构,`.env.<环境>` 保存公共配置,`.env.<环境>.local` 保存 SSH 及中间件秘密值。环境文件默认来自项目/workspace 根,`--env-dir` 可指定目录。完整配置后可使用 `pnpm run deploy --env test --build --bundle-only --yes` 无交互复用;只想保留现有中间件配置时追加 `--skip-middleware`。交互式仅打包会在最后询问是否保存或修改 SSH 信息;修改交付目录的 `deploy-target.json` 不会回写工程。
352
352
 
353
- 自建中间件的密码由服务器 `<remoteDir>/managed-secrets.env` 持久保存(权限 0600),应与数据卷一起备份。每次打包只生成首次初始化的随机候选,不依赖打包机缓存;在线 SDK、deploy.sh、deploy.ps1 和 deploy-local.sh 都在部署锁内复用服务器值,同时更新应用连接配置及中间件原生变量。交付 tar 保持不可变,只有服务器私有运行文件使用定稿值。若状态缺失而对应数据卷已存在,部署在变更服务前明确停止,须恢复服务器凭据备份;不会自动换密或删除数据。状态缺失时可按显式预检和凭据导入流程补全,普通部署仍拒绝缺失状态。
353
+ 自建中间件的密码由服务器 `<remoteDir>/managed-secrets.env` 持久保存(权限 0600),应与数据卷一起备份。每次打包只生成首次初始化的随机候选,不依赖打包机缓存;在线 SDK、deploy.sh、deploy.ps1 和 deploy-local.sh 都在部署锁内复用服务器值,同时更新应用连接配置及中间件原生变量。交付 tar 保持不可变,只有服务器私有运行文件使用定稿值。若状态缺失而对应数据卷已存在,部署在变更服务前明确停止,须恢复服务器凭据备份;不会自动换密或删除数据。
354
354
 
355
355
  ### 请求策略文件与可信代理
356
356
 
@@ -370,12 +370,10 @@ Serv 的 `http.access`、SvelteKit 的 `access` 可引用独立 yml/yaml。部
370
370
 
371
371
  资源清单复用执行端的完整 sidecar 拓扑:`containers` 只列本次选中的显式容器名,LDAP/SMTP 等由 Compose 命名的服务列在 `composeManagedServices`;自建 S3 的 SSR/API gateway 也会列入实际更新或保留范围。`logicalVolumes` 是完整拓扑的 Compose 逻辑卷声明,包含保留服务和应用继续挂载的数据卷,不表示新建或重建这些卷;实际引擎卷名由 Compose 项目作用域决定。未选中间件的 action 为 keep,云开通仅按实际选择范围计算,不展示凭据值。
372
372
 
373
- ### 容量与凭据导入
373
+ ### 传输容量
374
374
 
375
375
  传输明文上限保留显式设置;反馈需求超过显式值时拒绝打包并说明冲突。缺省/auto 才按模块预算推导,Web 代理和 Kit BODY_SIZE_LIMIT 使用同一密文预算。计划的 target.runtime 表示远端 provider.remote.runtime,与本地镜像打包 options.runtime 分离;auto 不冒充已探测事实。
376
376
 
377
- 旧目标可用 `importDeploymentSecrets({ directory, inputFile, runtime })` 或在服务器执行 `hai deploy-secrets <directory> --import <private.json>` 只读核验;显式 `--apply` / dryRun:false 才导入。工具核验项目、容器、卷和实际服务凭据,不猜测旧包、不轮换密码、不重建服务。新 v2 状态支持特殊字符并与部署共用 flock,原子写入权限 0600。常规离线部署无需服务器 Node;一次性导入工具需要受支持的 Node 与已安装的 CLI/deploy。详见[导入与恢复流程](docs/credential-import.md).
378
-
379
377
  ## 配置
380
378
 
381
379
  生命周期:init 输入后端/业务配置,成功后才能使用;close 在释放借用依赖前等待完成。返回值以快速开始示例和公开签名为准。
@@ -103,12 +103,7 @@ function applyManagedPasswords(values, bindings, state) {
103
103
  continue
104
104
  if (!['DB_PASSWORD', 'STORAGE_PASSWORD', 'LDAP_PASSWORD'].includes(group) || !state[group])
105
105
  throw new Error('Managed middleware credential state is missing')
106
- let password = state[group]
107
- if (state.FORMAT_VERSION === '2') {
108
- if (!/^(?:[a-f0-9]{2})+$/.test(password))
109
- throw new Error('Managed middleware credential encoding is invalid')
110
- password = Buffer.from(password, 'hex').toString('utf8')
111
- }
106
+ const password = state[group]
112
107
  let configuration = {}
113
108
  const parent = Object.hasOwn(values, prefix)
114
109
  if (parent) {
@@ -191,15 +186,12 @@ function prepare(directory, previousManifest, previousEnvironment, credentialSta
191
186
  }
192
187
  const bindings = entries('managed-bindings').join('\n')
193
188
  const state = readEnvironment(credentialState)
194
- const project = incoming.metadata['managed-project'] ?? previous.metadata['managed-project']
195
- if (state.PROJECT && project && state.PROJECT !== project.trim())
196
- throw new Error('Managed middleware credential project mismatch')
189
+ if (Object.entries(state).some(([key, value]) => !['DB_PASSWORD', 'STORAGE_PASSWORD', 'LDAP_PASSWORD'].includes(key) || !/^[\w-]{32}$/.test(value)))
190
+ throw new Error('Managed middleware credential state is invalid')
197
191
  applyManagedPasswords(next, bindings, state)
198
192
  validateRefreshCookie(next)
199
193
  incoming.metadata['managed-app-keys'] = `${keys.join('\n')}${keys.length ? '\n' : ''}`
200
194
  incoming.metadata['managed-bindings'] = `${bindings}${bindings ? '\n' : ''}`
201
- if (project)
202
- incoming.metadata['managed-project'] = project
203
195
  const environment = serialize(next)
204
196
  if (Buffer.byteLength(environment) > maximumBytes)
205
197
  throw new Error('Prepared runtime environment exceeds 1 MiB')
package/dist/index.d.ts CHANGED
@@ -3,8 +3,8 @@ import * as _h_ai_core from '@h-ai/core';
3
3
  import { HaiResult, HaiError } from '@h-ai/core';
4
4
 
5
5
  /**
6
- * 镜像制品清单,例如 `{ version: 4, primaryService: 'serv', appVersion: '1.2.3', buildId: '1.2.3-build1', partial: false, hasWeb: false, images: [...] }`。
7
- * 根目录制品保留格式4;非根目录使用格式5,强制旧部署器拒绝而非静默忽略挂载路径。
6
+ * 镜像制品清单,例如 `{ version: 5, webBasePath: '', primaryService: 'serv', appVersion: '1.2.3', buildId: '1.2.3-build1', partial: false, hasWeb: false, images: [...] }`。
7
+ * webBasePath 记录完整工程的挂载目录,空字符串表示域名根目录。
8
8
  * 完整产物包含primaryService,hasWeb记录浏览器端拓扑;结构验证不能代替真实归档校验。
9
9
  * @example
10
10
  * ```ts
@@ -17,7 +17,7 @@ import { HaiResult, HaiError } from '@h-ai/core';
17
17
  * ```
18
18
  */
19
19
  declare const DeploymentArtifactSchema: z.ZodObject<{
20
- version: z.ZodUnion<readonly [z.ZodLiteral<4>, z.ZodLiteral<5>]>;
20
+ version: z.ZodLiteral<5>;
21
21
  primaryService: z.ZodEnum<{
22
22
  serv: "serv";
23
23
  web: "web";
@@ -30,7 +30,7 @@ declare const DeploymentArtifactSchema: z.ZodObject<{
30
30
  }, z.core.$strip>>;
31
31
  partial: z.ZodDefault<z.ZodBoolean>;
32
32
  hasWeb: z.ZodDefault<z.ZodBoolean>;
33
- webBasePath: z.ZodOptional<z.ZodString>;
33
+ webBasePath: z.ZodString;
34
34
  servContainerPort: z.ZodOptional<z.ZodNumber>;
35
35
  webContainerPort: z.ZodOptional<z.ZodNumber>;
36
36
  images: z.ZodArray<z.ZodObject<{
@@ -1077,7 +1077,7 @@ declare const deploy: DeployFunctions;
1077
1077
  * const message = deployM('deploy_sshRequired')
1078
1078
  * ```
1079
1079
  */
1080
- declare const deployM: (key: "deploy_composeHostAddressInvalid" | "deploy_composeHostnameInvalid" | "deploy_composeHostnameConflict" | "deploy_composeProviderRequired" | "deploy_composeServiceUnavailable" | "deploy_notInitialized" | "deploy_initFailed" | "deploy_unsupportedProviderType" | "deploy_unsupportedProvisionerType" | "deploy_configTokenRequired" | "deploy_authRequired" | "deploy_authFailed" | "deploy_projectCreateFailed" | "deploy_uploadFailed" | "deploy_deployFailed" | "deploy_provisionFailed" | "deploy_adapterMissing" | "deploy_scanFailed" | "deploy_envVarFailed" | "deploy_credentialError" | "deploy_credentialInvalidKey" | "deploy_credentialSaved" | "deploy_credentialLoaded" | "deploy_configError" | "deploy_credentialMissing" | "deploy_apiError" | "deploy_fileUploadFailed" | "deploy_provisionNoResult" | "deploy_recoveryFailure" | "deploy_recoverySuggestion" | "deploy_commandTimeout" | "deploy_commandFailed" | "deploy_remoteConnectFailed" | "deploy_remoteRuntimeMissing" | "deploy_imageTransferFailed" | "deploy_healthCheckFailed" | "deploy_invalidEnvironment" | "deploy_environmentMissing" | "deploy_environmentReadFailed" | "deploy_environmentWriteFailed" | "deploy_multipleApplications" | "deploy_purposeSqlite" | "deploy_purposeDatabase" | "deploy_purposeMemory" | "deploy_purposeLocal" | "deploy_purposeCache" | "deploy_purposeStorage" | "deploy_purposeVector" | "deploy_purposeDisabled" | "deploy_purposeLdap" | "deploy_purposeConsole" | "deploy_purposeEmail" | "deploy_purposeSms" | "deploy_webProxyInvalid" | "deploy_webBaseConflict" | "deploy_storageProxyInvalid" | "deploy_storagePublicEndpointInvalid" | "deploy_storageBackendRequired" | "deploy_artifactInvalid" | "deploy_sshRequired" | "deploy_sshPasswordInvalid" | "deploy_sshAskpassFailed" | "deploy_sshAskpassCleanupFailed" | "deploy_targetAuth" | "deploy_targetPasswordEnv" | "deploy_bundleInstructions" | "deploy_bundleApplyGuide" | "deploy_bundleMetadata" | "deploy_targetHost" | "deploy_targetPort" | "deploy_targetUsername" | "deploy_targetIdentityFile" | "deploy_targetKnownHostsFile" | "deploy_targetStrictHostKeyChecking" | "deploy_targetConnectTimeoutSeconds" | "deploy_targetDirectory" | "deploy_targetBundle" | "deploy_bundleOnlyContainer" | "deploy_selectedContainerOnly" | "deploy_selectionInvalid" | "deploy_imageVersionRequired" | "deploy_bundleRuntimeRequired" | "deploy_bundleFailed" | "deploy_configFileInvalid" | "deploy_configFileUnreadable" | "deploy_bundleNameInvalid" | "deploy_localStopped" | "deploy_localUnknown" | "deploy_localNotStarted" | "deploy_commandOutputFailed" | "deploy_commandInputFailed" | "deploy_commandTreeActive" | "deploy_commandExecutionFailed" | "deploy_remoteUnknown" | "deploy_remoteFinished" | "deploy_bundleDirectoryExists" | "deploy_bundleFull" | "deploy_bundlePartial" | "deploy_bundleSelection" | "deploy_transportBodyLimitInvalid" | "deploy_transportKeyRingInvalid" | "deploy_uploadPasswordPrompt" | "deploy_uploadPasswordUnavailable" | "deploy_uploadPasswordCancelled" | "deploy_uploadPasswordInvalid" | "deploy_managedSecretsInvalid" | "deploy_secretImportFailed" | "deploy_projectNameRequired" | "deploy_projectNameOverrideRemoved" | "deploy_requestAccessInvalid" | "deploy_httpsPortsInvalid" | "deploy_httpsCertificateInvalid" | "deploy_bundleRuntime" | "deploy_refreshCookieSecureInvalid" | "deploy_postgresPasswordConflict" | "deploy_bundleVariables" | "deploy_bundleHttpOnly" | "deploy_bundleHttps" | "deploy_bundleAcme" | "deploy_bundleAccounts" | "deploy_bundleDirectories" | "deploy_downloadInvalid" | "deploy_imageSourceMissing" | "deploy_proxySystemUnsupported" | "deploy_middlewareFieldInvalid" | "deploy_middlewareFieldError" | "deploy_middlewareRequired" | "deploy_middlewareInteger" | "deploy_middlewareBoolean" | "deploy_middlewareUrl" | "deploy_middlewareS3Endpoint" | "deploy_middlewareTlsSyntax" | "deploy_middlewareMysqlTls" | "deploy_middlewarePostgresTls" | "deploy_middlewareHeaders" | "deploy_middlewareMethod" | "deploy_configResolutionFailed" | "deploy_reachEmptyProviderOverride" | "deploy_s3Engine", options?: _h_ai_core.MessageOptions) => string;
1080
+ declare const deployM: (key: "deploy_composeHostAddressInvalid" | "deploy_composeHostnameInvalid" | "deploy_composeHostnameConflict" | "deploy_composeProviderRequired" | "deploy_composeServiceUnavailable" | "deploy_notInitialized" | "deploy_initFailed" | "deploy_unsupportedProviderType" | "deploy_unsupportedProvisionerType" | "deploy_configTokenRequired" | "deploy_authRequired" | "deploy_authFailed" | "deploy_projectCreateFailed" | "deploy_uploadFailed" | "deploy_deployFailed" | "deploy_provisionFailed" | "deploy_adapterMissing" | "deploy_scanFailed" | "deploy_envVarFailed" | "deploy_credentialError" | "deploy_credentialInvalidKey" | "deploy_credentialSaved" | "deploy_credentialLoaded" | "deploy_configError" | "deploy_credentialMissing" | "deploy_apiError" | "deploy_fileUploadFailed" | "deploy_provisionNoResult" | "deploy_recoveryFailure" | "deploy_recoverySuggestion" | "deploy_commandTimeout" | "deploy_commandFailed" | "deploy_remoteConnectFailed" | "deploy_remoteRuntimeMissing" | "deploy_imageTransferFailed" | "deploy_healthCheckFailed" | "deploy_invalidEnvironment" | "deploy_environmentMissing" | "deploy_environmentReadFailed" | "deploy_environmentWriteFailed" | "deploy_multipleApplications" | "deploy_purposeSqlite" | "deploy_purposeDatabase" | "deploy_purposeMemory" | "deploy_purposeLocal" | "deploy_purposeCache" | "deploy_purposeStorage" | "deploy_purposeVector" | "deploy_purposeDisabled" | "deploy_purposeLdap" | "deploy_purposeConsole" | "deploy_purposeEmail" | "deploy_purposeSms" | "deploy_webProxyInvalid" | "deploy_webBaseConflict" | "deploy_storageProxyInvalid" | "deploy_storagePublicEndpointInvalid" | "deploy_storageBackendRequired" | "deploy_artifactInvalid" | "deploy_sshRequired" | "deploy_sshPasswordInvalid" | "deploy_sshAskpassFailed" | "deploy_sshAskpassCleanupFailed" | "deploy_targetAuth" | "deploy_targetPasswordEnv" | "deploy_bundleInstructions" | "deploy_bundleApplyGuide" | "deploy_bundleMetadata" | "deploy_targetHost" | "deploy_targetPort" | "deploy_targetUsername" | "deploy_targetIdentityFile" | "deploy_targetKnownHostsFile" | "deploy_targetStrictHostKeyChecking" | "deploy_targetConnectTimeoutSeconds" | "deploy_targetDirectory" | "deploy_targetBundle" | "deploy_bundleOnlyContainer" | "deploy_selectedContainerOnly" | "deploy_selectionInvalid" | "deploy_imageVersionRequired" | "deploy_bundleRuntimeRequired" | "deploy_bundleFailed" | "deploy_configFileInvalid" | "deploy_configFileUnreadable" | "deploy_bundleNameInvalid" | "deploy_localStopped" | "deploy_localUnknown" | "deploy_localNotStarted" | "deploy_commandOutputFailed" | "deploy_commandInputFailed" | "deploy_commandTreeActive" | "deploy_commandExecutionFailed" | "deploy_remoteUnknown" | "deploy_remoteFinished" | "deploy_bundleDirectoryExists" | "deploy_bundleFull" | "deploy_bundlePartial" | "deploy_bundleSelection" | "deploy_transportBodyLimitInvalid" | "deploy_transportKeyRingInvalid" | "deploy_uploadPasswordPrompt" | "deploy_uploadPasswordUnavailable" | "deploy_uploadPasswordCancelled" | "deploy_uploadPasswordInvalid" | "deploy_managedSecretsInvalid" | "deploy_projectNameRequired" | "deploy_requestAccessInvalid" | "deploy_httpsPortsInvalid" | "deploy_httpsCertificateInvalid" | "deploy_bundleRuntime" | "deploy_refreshCookieSecureInvalid" | "deploy_postgresPasswordConflict" | "deploy_bundleVariables" | "deploy_bundleHttpOnly" | "deploy_bundleHttps" | "deploy_bundleAcme" | "deploy_bundleAccounts" | "deploy_bundleDirectories" | "deploy_downloadInvalid" | "deploy_imageSourceMissing" | "deploy_proxySystemUnsupported" | "deploy_middlewareFieldInvalid" | "deploy_middlewareFieldError" | "deploy_middlewareRequired" | "deploy_middlewareInteger" | "deploy_middlewareBoolean" | "deploy_middlewareUrl" | "deploy_middlewareS3Endpoint" | "deploy_middlewareTlsSyntax" | "deploy_middlewareMysqlTls" | "deploy_middlewarePostgresTls" | "deploy_middlewareHeaders" | "deploy_middlewareMethod" | "deploy_configResolutionFailed" | "deploy_reachEmptyProviderOverride" | "deploy_s3Engine" | "deploy_downloadUnavailableTitle" | "deploy_downloadUnavailableInstruction", options?: _h_ai_core.MessageOptions) => string;
1081
1081
 
1082
1082
  /**
1083
1083
  * 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。
@@ -1368,37 +1368,5 @@ declare function getDeployCommandState(error: HaiError): DeployCommandState | un
1368
1368
  */
1369
1369
  declare function getDeployRecovery(error: HaiError): DeployRecoveryInfo | undefined;
1370
1370
 
1371
- /** 旧部署凭据的显式、只读预检与原子导入;不轮换密码、不变更容器和数据卷。 */
1372
-
1373
- /**
1374
- * 在目标服务器导入前核验旧凭据;dryRun 默认 true,apply 需要 Linux flock 与运行中的原服务。
1375
- * 输入文件必须由操作者明确指定,权限 0600;API 不读取旧部署包猜测密码。
1376
- * @param options - 服务器项目目录、受保护的导入 JSON、容器引擎和只读开关。
1377
- * @param options.directory - 目标 Linux 服务器上已存在的项目部署目录。
1378
- * @param options.inputFile - 操作者提供的版本化私有 JSON 文件路径。
1379
- * @param options.runtime - 实际使用的 Docker 或 Podman 引擎。
1380
- * @param options.dryRun - 默认 true;只有显式 false 才在部署锁内保存状态。
1381
- * @returns 仅包含项目、凭据组和卷名的回执,不包含密码;失败不推进 current 或改变服务。
1382
- * @example
1383
- * ```ts
1384
- * import { importDeploymentSecrets } from '@h-ai/deploy'
1385
- * const plan = await importDeploymentSecrets({ directory: '/opt/hai/apps/shop-test', inputFile: '/private/shop-import.json', runtime: 'docker' })
1386
- * if (!plan.success) throw new Error(plan.error.message)
1387
- * // 停止业务写入、备份数据后,用相同输入显式传 dryRun: false 导入。
1388
- * ```
1389
- */
1390
- declare function importDeploymentSecrets(options: {
1391
- directory: string;
1392
- inputFile: string;
1393
- runtime: 'docker' | 'podman';
1394
- dryRun?: boolean;
1395
- }): Promise<HaiResult<{
1396
- projectName: string;
1397
- stateVersion: 2;
1398
- groups: string[];
1399
- volumes: string[];
1400
- changed: boolean;
1401
- }>>;
1402
-
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 };
1371
+ export { DEPLOY_MIDDLEWARE, DeployConfigSchema, DeploymentArtifactSchema, HaiDeployError, ProviderConfigSchema, artifactChecksum, canKeepMiddleware, createDeploymentPlan, deploy, describeMiddlewareBackend, getDeployCommandState, getDeployRecovery, loadDeploymentConfig, loadDeploymentEnvironment, mergeEnvironmentLayers, normalizeProjectName, parseMiddlewareField, readDeploymentArtifact, resolveDownloadProxy, resolveImageReference, saveDeploymentEnvironment, saveMiddlewareEnvironment, validateMiddlewareField };
1404
1372
  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 };